From c4b90cf92e60140239b243b7022de08488fcd191 Mon Sep 17 00:00:00 2001 From: mason Date: Thu, 29 Oct 2020 08:43:30 -0400 Subject: [PATCH] updating to the cloud --- Lv0_dirs.py | 4 +- Lv0_get_swift_data.py | 35 + Lv0_psrpipe.py | 11 +- Lv0_scp.py | 2 +- Lv1_data_bin.py | 8 +- Lv1_data_gtis.py | 65 + Lv1_ngc300_binning.py | 161 +- Lv1_ngc300_binning_DEPRECATED.py | 143 ++ Lv1_ngc300_binning_DEPRECATED2.py | 120 + Lv1_ngc300_mathgrp_pha.py | 278 ++- Lv1_spectra_txt.py | 1180 ++++++++-- Lv1_swift_filter.py | 538 +++++ Lv2_TBOs_method.py | 15 +- Lv2_average_ps_methods.py | 189 +- Lv2_bestprof2par.py | 54 + Lv2_create_time_res_spec.py | 158 ++ Lv2_dj_lsp.py | 340 +++ Lv2_efsearch.py | 16 + Lv2_lc.py | 13 +- Lv2_merged_pulse_methods.py | 2 +- Lv2_merging_events.py | 69 +- Lv2_ngc300_color.py | 11 +- Lv2_phase.py | 175 +- Lv2_preprocess.py | 6 +- Lv2_presto_subroutines.py | 326 ++- Lv2_ps.py | 2 +- Lv2_ps_method.py | 28 +- Lv2_swift_lc.py | 289 +++ Lv3_B1957+20_merged.py | 48 +- Lv3_TBOs.py | 14 +- Lv3_analyze_time_res_spec.py | 74 + Lv3_average_ps_main.py | 3 +- Lv3_avg_ps_assess_cands.py | 125 ++ Lv3_det_Eres.py | 71 + Lv3_detection_level.py | 3 +- Lv3_diagnostics.py | 7 +- Lv3_incoming.py | 516 +++++ Lv3_main.py | 17 +- Lv3_ngc300_plots.py | 119 +- Lv3_ngc300x1_prof_xmm.py | 305 +++ Lv3_nicer_archival.py | 134 +- Lv3_orbitephem_visual.py | 107 + Lv3_quicklook.py | 155 +- Lv3_swift_ngc300.py | 917 ++++++++ Lv3_visualize_presto.py | 59 + __pycache__/Lv0_dirs.cpython-37.pyc | Bin 676 -> 786 bytes __pycache__/Lv0_fits2dict.cpython-37.pyc | Bin 1949 -> 1949 bytes .../Lv0_nicer_housekeeping.cpython-37.pyc | Bin 8946 -> 8946 bytes __pycache__/Lv0_psrpipe.cpython-37.pyc | Bin 2041 -> 2260 bytes __pycache__/Lv0_scp.cpython-37.pyc | Bin 1290 -> 1297 bytes __pycache__/Lv1_barycorr.cpython-37.pyc | Bin 5069 -> 5069 bytes __pycache__/Lv1_data_bin.cpython-37.pyc | Bin 5980 -> 5996 bytes __pycache__/Lv1_data_gtis.cpython-37.pyc | Bin 3542 -> 2159 bytes __pycache__/Lv2_TBOs_method.cpython-37.pyc | Bin 7034 -> 7311 bytes .../Lv2_average_ps_methods.cpython-37.pyc | Bin 17348 -> 22541 bytes __pycache__/Lv2_dj_lsp.cpython-37.pyc | Bin 0 -> 6155 bytes __pycache__/Lv2_efsearch.cpython-37.pyc | Bin 3778 -> 4207 bytes __pycache__/Lv2_lc.cpython-37.pyc | Bin 8043 -> 8365 bytes __pycache__/Lv2_merging_events.cpython-37.pyc | Bin 3092 -> 3062 bytes __pycache__/Lv2_ngc300_color.cpython-37.pyc | Bin 0 -> 2629 bytes __pycache__/Lv2_phase.cpython-37.pyc | Bin 16820 -> 19691 bytes __pycache__/Lv2_preprocess.cpython-37.pyc | Bin 4012 -> 4187 bytes .../Lv2_presto_subroutines.cpython-37.pyc | Bin 15466 -> 22130 bytes __pycache__/Lv2_ps.cpython-37.pyc | Bin 17056 -> 17065 bytes __pycache__/Lv2_ps_method.cpython-37.pyc | Bin 6061 -> 6406 bytes __pycache__/Lv2_swift_lc.cpython-37.pyc | Bin 0 -> 9476 bytes .../Lv3_detection_level.cpython-37.pyc | Bin 3289 -> 3297 bytes __pycache__/Lv3_diagnostics.cpython-37.pyc | Bin 9080 -> 9080 bytes gapsim.py | 347 +++ grb200205a_bary.dat | Bin 0 -> 806400 bytes grb200205a_bary.events | Bin 0 -> 120008 bytes grb200205a_bary.inf | 19 + test.py | 1944 +++++++++++++++++ test_timing.py | 80 + xte1739_1segs_128_5.701 | 7 + 75 files changed, 8671 insertions(+), 638 deletions(-) create mode 100644 Lv0_get_swift_data.py create mode 100644 Lv1_data_gtis.py create mode 100644 Lv1_ngc300_binning_DEPRECATED.py create mode 100644 Lv1_ngc300_binning_DEPRECATED2.py create mode 100644 Lv1_swift_filter.py create mode 100644 Lv2_bestprof2par.py create mode 100644 Lv2_create_time_res_spec.py create mode 100644 Lv2_dj_lsp.py create mode 100644 Lv2_swift_lc.py create mode 100644 Lv3_analyze_time_res_spec.py create mode 100644 Lv3_avg_ps_assess_cands.py create mode 100644 Lv3_det_Eres.py create mode 100644 Lv3_incoming.py create mode 100644 Lv3_ngc300x1_prof_xmm.py mode change 100644 => 100755 Lv3_nicer_archival.py create mode 100644 Lv3_orbitephem_visual.py create mode 100644 Lv3_swift_ngc300.py create mode 100755 Lv3_visualize_presto.py create mode 100644 __pycache__/Lv2_dj_lsp.cpython-37.pyc create mode 100644 __pycache__/Lv2_ngc300_color.cpython-37.pyc create mode 100644 __pycache__/Lv2_swift_lc.cpython-37.pyc create mode 100644 gapsim.py create mode 100644 grb200205a_bary.dat create mode 100644 grb200205a_bary.events create mode 100644 grb200205a_bary.inf create mode 100644 test_timing.py create mode 100644 xte1739_1segs_128_5.701 diff --git a/Lv0_dirs.py b/Lv0_dirs.py index 71cff89..676bb4b 100644 --- a/Lv0_dirs.py +++ b/Lv0_dirs.py @@ -12,8 +12,10 @@ def global_par(): """ Defining global variables for the directories """ - global BASE_DIR, NICER_DATADIR, NICERSOFT_DATADIR, NGC300 + global BASE_DIR, NICER_DATADIR, NICERSOFT_DATADIR, NGC300, NGC300_2020, NGC300_XMM BASE_DIR = '/Users/masonng/Documents/MIT/Research/' NICER_DATADIR = '/Volumes/Samsung_T5/NICER-data/' NICERSOFT_DATADIR = '/Volumes/Samsung_T5/NICERsoft_outputs/' NGC300 = '/Volumes/Samsung_T5/NGC300_ULX/' + NGC300_2020 = '/Volumes/Samsung_T5/n300_ulx_2020/' + NGC300_XMM = '/Volumes/Samsung_T5/NGC300_XMMdata/' diff --git a/Lv0_get_swift_data.py b/Lv0_get_swift_data.py new file mode 100644 index 0000000..daa3684 --- /dev/null +++ b/Lv0_get_swift_data.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +Created on Tues April 21 7:10pm 2020 + +Program that takes in a FITS table, from the HEASARC archive, of observation IDs +and pointing modes (for Swift), then uses the Perl script download_wget.pl to +obtain the data files! + +""" +from __future__ import division, print_function +import numpy as np +from astropy.io import fits +import Lv0_dirs,Lv1_data_gtis,Lv2_presto_subroutines,Lv2_mkdir +import os +from tqdm import tqdm +import subprocess +import pathlib + +Lv0_dirs.global_par() + +def download_txt(txtfile): + """ + Given the text file of download instructions, take the URLs of where the data + are stored within the HEASARC archive, and use download_wget.pl to retrieve them + """ + contents = open(txtfile,'r').read().split('\n') + urls = [contents[i].split(' ')[-1] for i in range(len(contents)-1)] + + for i in tqdm(range(len(urls))): + subprocess.run(['perl','/Volumes/Samsung_T5/download_wget.pl',urls[i]]) + +if __name__ == "__main__": + textfile = '/Volumes/Samsung_T5/NGC300_ULX_Swift/ngc300x1-ulx1_photon_pointing.txt' + download_txt(textfile) diff --git a/Lv0_psrpipe.py b/Lv0_psrpipe.py index 4561b9c..6a5f6e8 100644 --- a/Lv0_psrpipe.py +++ b/Lv0_psrpipe.py @@ -10,6 +10,7 @@ import numpy as np import Lv0_dirs from astropy.io import fits +from tqdm import tqdm import os import subprocess @@ -54,6 +55,10 @@ def psrpipe(eventfile,flags): return if __name__ == "__main__": - obsid = '1034070101' - eventfile = Lv0_dirs.NICER_DATADIR + obsid + '/xti/event_cl/ni' + obsid+'_0mpu7_cl.evt' - psrpipe(eventfile,['--emin','0.3','--emax','12.0']) + #obsid = '1034070101' + #eventfile = Lv0_dirs.NICER_DATADIR + obsid + '/xti/event_cl/ni' + obsid+'_0mpu7_cl.evt' + #psrpipe(eventfile,['--emin','0.3','--emax','12.0']) + + eventfiles = [Lv0_dirs.NICER_DATADIR + str(i) + '/xti/event_cl/ni' + str(i) + '_0mpu7_cl.evt' for i in range(1030180101,1030180188)] + for i in tqdm(range(len(eventfiles))): + psrpipe(eventfiles[i],['--emin','0.3','--emax','12.0','--nounderfilt']) diff --git a/Lv0_scp.py b/Lv0_scp.py index 4ff6037..535ca49 100644 --- a/Lv0_scp.py +++ b/Lv0_scp.py @@ -36,7 +36,7 @@ def scp(obsid): if __name__ == "__main__": #obsids = ['203420020' + str(i) for i in range(1,6)] + ['103419010' + str(i) for i in range(1,5)] + ['1034200' + str(i) for i in range(201,241)] - obsids = ['00' + str(i) for i in range(34070101,34070105)] + obsids = ['201001023' + str(i) for i in range(6,7)] for i in range(len(obsids)): scp(obsids[i]) diff --git a/Lv1_data_bin.py b/Lv1_data_bin.py index 2e5ea0a..c72aba9 100644 --- a/Lv1_data_bin.py +++ b/Lv1_data_bin.py @@ -41,7 +41,7 @@ def binning_t(eventfile,par_list,tbin_size,t1,t2): startt = int(t1) endt = int(t2) - t_bins = np.linspace(startt,endt,(endt-startt)*1/tbin_size+1) #getting an array of time values for the bins + t_bins = np.linspace(startt,endt,int((endt-startt)*1/tbin_size+1)) #getting an array of time values for the bins summed_data, bin_edges, binnumber = stats.binned_statistic(truncated_t,counts,statistic='sum',bins=t_bins) #binning the counts in the data print("The data is binned by " + str(tbin_size) + 's') @@ -81,13 +81,13 @@ def binning_E(eventfile,par_list,tbin_size,Ebin_size,E1,E2): startt = int(truncated_t[0]) endt = np.ceil(truncated_t[-1]) - t_bins = np.linspace(startt,endt,(endt-startt)*1/tbin_size+1) #getting an array of time values for the bins + t_bins = np.linspace(startt,endt,int((endt-startt)*1/tbin_size+1)) #getting an array of time values for the bins summed_data_t, bin_edges, binnumber = stats.binned_statistic(truncated_t,counts,statistic='sum',bins=t_bins) #binning the time values in the data if E1 < 1: #if less than 1keV, the binning for 0.3-1keV is slightly different. - E_bins = np.linspace(E1,E2,(E2-E1)*1/Ebin_size+2) #getting an array of energy values for the bins + E_bins = np.linspace(E1,E2,int((E2-E1)*1/Ebin_size+2)) #getting an array of energy values for the bins else: - E_bins = np.linspace(E1,E2,(E2-E1)*1/Ebin_size+1) #getting an array of energy values for the bins + E_bins = np.linspace(E1,E2,int((E2-E1)*1/Ebin_size+1)) #getting an array of energy values for the bins summed_data_E, bin_edges, binnumber = stats.binned_statistic(truncated_E,counts,statistic='sum',bins=E_bins) #binning the energy values in the data print("The data is binned by " + str(tbin_size) + 's, and ' + str(Ebin_size) + 'keV') diff --git a/Lv1_data_gtis.py b/Lv1_data_gtis.py new file mode 100644 index 0000000..b3d95f4 --- /dev/null +++ b/Lv1_data_gtis.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +Created on Sat Feb 22 4:55pm 2020 + +Script to manipulate GTIs where necessary. In the Feb 22 2020 edition, I will +be combining GTIs, such that consecutive GTIs that are a short time apart will be combined. +This is so that I can run acceleration searches on individual GTIs! + +https://stackoverflow.com/questions/3704918/python-way-to-restart-a-for-loop-similar-to-continue-for-while-loops +For GTI_bunching +""" +from __future__ import division, print_function +from astropy.io import fits +import numpy as np +import pathlib +import subprocess +import Lv0_dirs,Lv0_fits2dict + +Lv0_dirs.global_par() #obtaining the global parameters + +def GTI_bunching(eventfile,gap,gtifile): + """ + To bunch up GTIs which are separated by less than a few seconds apart. + + eventfile - path to the event file. Will extract ObsID from this for the NICER files. + gap - maximum separation between end time of 1st GTI and start time of 2nd GTI allowed + gtifile - name of GTI file + """ + parent_folder = str(pathlib.Path(eventfile).parent) + gtifile_path = parent_folder + '/' + gtifile + gtis = list(fits.open(eventfile)[2].data) + N = len(gtis) + + should_restart = True + while should_restart: #to restart the for loop if I reached a pair of GTIs that can be combined + should_restart = False + for i in range(N-1): #variable N is there as we need to UPDATE the length of the GTIs each time we delete one! + if (gtis[i+1][0]-gtis[i][1]) <= gap: #if (start time of next GTI - end time of previous GTI) is less than 5s, say + new_start = gtis[i][0] #defined here, because "i" will change after deleting the 2 previous GTIs! + new_end = gtis[i+1][1] + del gtis[i] + del gtis[i] #use the SAME index since the list after the first deletion will have N-1 items! + gtis.insert(i,(new_start,new_end)) + N = len(gtis) + should_restart = True + break + else: + N = len(gtis) + continue + + gtitxt = open(parent_folder + '/bunchedgtis.txt','w') + for i in range(len(gtis)): + gtitxt.write(str(gtis[i][0]) + ' ' + str(gtis[i][1]) + '\n') + gtitxt.close() + + gti_col_file = Lv0_dirs.NICER_DATADIR + 'gti_columns.txt' + gti_header_file = Lv0_dirs.NICER_DATADIR + 'gti_header.txt' + ftcreate_cmd = ['ftcreate',gti_col_file,parent_folder+'/bunchedgtis.txt',gtifile_path,'headfile='+gti_header_file,'extname="GTI"','clobber=yes'] + subprocess.run(ftcreate_cmd) + +if __name__ == "__main__": + eventfile = Lv0_dirs.NICER_DATADIR + 'xtej1739/2002131540_bary.evt' + gtifile = Lv0_dirs.NICER_DATADIR + 'xtej1739/bunched.gti' + GTI_bunching(eventfile,5,gtifile) diff --git a/Lv1_ngc300_binning.py b/Lv1_ngc300_binning.py index 207cb05..92a32d3 100644 --- a/Lv1_ngc300_binning.py +++ b/Lv1_ngc300_binning.py @@ -10,121 +10,88 @@ import numpy as np import matplotlib.pyplot as plt from tqdm import tqdm +from astropy.io import fits import subprocess +import pathlib import glob import Lv0_dirs Lv0_dirs.global_par() -binsize_s = 1 +binsize_s = 5 bin_size = str(binsize_s).zfill(2) + 'd' #bins of 1 day! +bgsub_type = 'xsbgsub' -RGcms = Lv0_dirs.NGC300 + 'n300_ulx.bgsub_cl50_RGcms.ffphot' -RGnorm = Lv0_dirs.NGC300 + 'n300_ulx.bgsub_cl50_RGnorm.ffphot' -RGerror = Lv0_dirs.NGC300 + 'n300_ulx.bgsub_cl50_RGerr_norm.ffphot' +#RGcms = Lv0_dirs.NGC300_2020 + 'n300_ulx.bgsub_cl50_g2020.fffphot' NOT USING for 2020. No fffphot file for this anyways +norm_fffphot = Lv0_dirs.NGC300_2020 + 'n300_ulx.' + bgsub_type + '_cl50_g2020norm.fffphot' -soft1,soft2,A_band,B_band,C_band,D_band,inband,time = np.genfromtxt(RGnorm,usecols=(3,4,5,6,7,8,9,11),unpack=True) -soft1_err,soft2_err,A_err,B_err,C_err,D_err,inband_err,time_error = np.genfromtxt(RGerror,usecols=(3,4,5,6,7,8,9,11),unpack=True) -# time_error does not mean error in the time value, I just mean the time value found in the error text file -filename = np.genfromtxt(RGnorm,dtype='str',usecols=(0),unpack=True) -filename_err = np.genfromtxt(RGerror,dtype='str',usecols=(0),unpack=True) +### extracting photometry/count rates for soft_1 (0.2-0.3 keV), soft_2 (0.3-0.4 keV), +### A (0.4-1 keV), B (1-2 keV), C (2-4 keV), D (4-12) keV, in-band (A+B+C+D = 0.4-12 keV) bands, plus MJD +time = np.genfromtxt(norm_fffphot,dtype='float64',usecols=(11),unpack=True) +filenames = np.genfromtxt(norm_fffphot,dtype='str',usecols=(0),unpack=True) time_bins = np.arange(58239,58606,binsize_s) -filename_dict,soft1_dict,soft2_dict,A_dict,B_dict,C_dict,D_dict,inband_dict = {},{},{},{},{},{},{},{} -filename_err_dict,soft1_err_dict,soft2_err_dict,A_err_dict,B_err_dict,C_err_dict,D_err_dict,inband_err_dict = {},{},{},{},{},{},{},{} time = np.floor(time) #can't use int ; basically round the time values down to the integer value -#### bin up the counts and associated errors into dictionaries! -for i in tqdm(range(len(time_bins))): -## so for each time bin, gather up the count rates (and errors) in a dictionary - filename_dict[time_bins[i]] = filename[(time>=time_bins[i])&(time=time_bins[i])&(time=time_bins[i])&(time=time_bins[i])&(time=time_bins[i])&(time=time_bins[i])&(time=time_bins[i])&(time=time_bins[i])&(time=time_bins[i])&(time=time_bins[i])&(time=time_bins[i])&(time=time_bins[i])&(time=time_bins[i])&(time=time_bins[i])&(time=time_bins[i])&(time=time_bins[i])&(time=float(mjd))&(time=time_bins[i])&(time=time_bins[i])&(time=time_bins[i])&(time=time_bins[i])&(time=time_bins[i])&(time=time_bins[i])&(time=time_bins[i])&(time=time_bins[i])&(time=time_bins[i])&(time=time_bins[i])&(time=time_bins[i])&(time=time_bins[i])&(time=time_bins[i])&(time=time_bins[i])&(time=time_bins[i])&(time=time_bins[i])&(time=time_bins[i])&(time=time_bins[i])&(time 0.25 and orb_phase <= 0.80): #off-eclipse + rate = top + + elif (orb_phase > 0.9 and orb_phase <= 1) or (orb_phase >= 0.0 and orb_phase <= 0.1): #on-eclipse + rate = bottom + + elif (orb_phase > 0.1 and orb_phase <= 0.15): + ##### the rate is 0.011361 + rate = 0.011361 + + elif (orb_phase > 0.15 and orb_phase <= 0.20): + ##### the rate is 0.014107 + rate = 0.014107 + + elif (orb_phase > 0.20 and orb_phase <= 0.25): + ##### the rate is 0.019135 + rate = 0.019135 + + elif (orb_phase > 0.80 and orb_phase <= 0.85): + ##### the rate is 0.015688 + rate = 0.015688 + + elif (orb_phase > 0.85 and orb_phase <= 0.90): + ##### the rate is 0.011368 + rate = 0.011368 + + return rate + +def combine_back_scal(init_back_array,fake_spec,T0,Porb): + """ + Given a timing model/ephemeris, figure out which orbital phase the events in a + background spectrum/event file are in (defined by some centroid time), then + write a mathpha command combining those files appropriately in rate space. + Unlike combine_back, this SCALES the spectra/GTIs in the ingress/egress sections + based on the folded PN light curve! + + Remember that: + 025-080 -> off + 080-090 -> ingress + 090-010 -> on + 010-025 -> egress + + init_back_array - array of input background file + fake_spec - array of files split by orbital phase + T0 - reference time ; deepest point of eclipse + Porb - orbital period in days + """ + command_file = open(Lv0_dirs.NGC300_2020 + '3C50_X1scale_mathpha.go','w') + on_e = fake_spec[0] + off_e = fake_spec[1] + + top = 0.022177 + bottom = 0.005351 + + counter = 0 + for i in tqdm(range(len(init_back_array))): + init_back = init_back_array[i] + gti_no = init_back[-8:-4] + init_cl = Lv0_dirs.NGC300_2020 + 'cl50/pha/cl50_' + gti_no + '.pha' + + backfile = str(pathlib.Path(init_back).name) + comb_spec_folder = Lv0_dirs.NGC300_2020 + 'bg_cl50/xspha/' #x for 'extra', s for 'scale' + + tstart = fits.open(init_cl)[1].header['TSTART'] + tstop = fits.open(init_cl)[1].header['TSTOP'] + centroid_t = fits.open(init_cl)[1].header['MJDREFI'] + fits.open(init_cl)[1].header['MJDREFF'] + ((tstart+tstop)/2)/86400 + + #first assuming the timing model, determine how much time (in d) has passed + orb_phase = (centroid_t-T0)%Porb/Porb + + calculation = '' + rate = orb_phase_rate(orb_phase) + + on_factor = round((top-rate)/(top-bottom),6) + off_factor = round((rate-bottom)/(top-bottom),6) + calculation += "('" + init_back + "'+" + str(off_factor) + "*'" + off_e + "'+" + str(on_factor) + "*'" + on_e + "')" + + bg_exp = fits.open(init_back)[1].header['EXPOSURE'] + eclipse_exp = 1e6 #1 Ms was used in the faked spectrum + #### now to build the mathpha command + mathpha = 'mathpha' + + unit = 'R' #for rate ; use 'C' for counts + outfile = "outfil='" + comb_spec_folder + "xs" + backfile + "'" + exposure = 'exposure=' + str(bg_exp + eclipse_exp) + errmeth = 'errmeth=gaussian' + properr = 'properr=yes' + ncomments = 'ncomments=0' + areascal = 'areascal=NULL' + clobber = 'clobber=YES' + + mathpha_line = mathpha+' "'+calculation+ '" '+unit+' '+outfile+' '+exposure+' '+errmeth+' '+properr+' '+ncomments+' '+areascal+' '+clobber + command_file.write(mathpha_line + '\n') + + command_file.close() + +def combine_back(init_back_array,fake_spec,T0,Porb): + """ + Given a timing model/ephemeris, figure out which orbital phase the events in a + background spectrum/event file are in (defined by some centroid time), then + write a mathpha command combining those files appropriately in rate space + + init_back_array - array of input background file + fake_spec - array of files split by orbital phase + T0 - reference time ; deepest point of eclipse + Porb - orbital period in days + """ + command_file = open(Lv0_dirs.NGC300_2020 + '3C50_X1_mathpha.go','w') + + for i in tqdm(range(len(init_back_array))): + init_back = init_back_array[i] + gti_no = init_back[-8:-4] + init_cl = Lv0_dirs.NGC300_2020 + 'cl50/pha/cl50_' + gti_no + '.pha' + + backfile = str(pathlib.Path(init_back).name) + comb_spec_folder = Lv0_dirs.NGC300_2020 + 'bg_cl50/xpha/' + + tstart = fits.open(init_cl)[1].header['TSTART'] + tstop = fits.open(init_cl)[1].header['TSTOP'] + centroid_t = fits.open(init_cl)[1].header['MJDREFI'] + fits.open(init_cl)[1].header['MJDREFF'] + ((tstart+tstop)/2)/86400 + + #first assuming the timing model, determine how much time (in d) has passed + orb_phase = (centroid_t-T0)%Porb/Porb + + if (orb_phase >= 0.0 and orb_phase <= 0.20) or (orb_phase >= 0.85 and orb_phase <= 1): + eclipse = fake_spec[0] + elif (orb_phase > 0.2 and orb_phase < 0.85): + eclipse = fake_spec[1] + + bg_exp = fits.open(init_back)[1].header['EXPOSURE'] + eclipse_exp = fits.open(eclipse)[1].header['EXPOSURE'] + #### now to build the mathpha command + mathpha = 'mathpha' + calculation = '' + calculation += "('" + init_back + "'+'" + eclipse + "')" + + unit = 'R' #for rate ; use 'C' for counts + outfile = "outfil='" + comb_spec_folder + "x" + backfile + "'" + exposure = 'exposure=' + str(bg_exp + eclipse_exp) + errmeth = 'errmeth=gaussian' + properr = 'properr=yes' + ncomments = 'ncomments=0' + areascal = 'areascal=NULL' + clobber = 'clobber=YES' + + mathpha_line = mathpha+' "'+calculation+ '" '+unit+' '+outfile+' '+exposure+' '+errmeth+' '+properr+' '+ncomments+' '+areascal+' '+clobber + command_file.write(mathpha_line + '\n') + + command_file.close() + + return def mathpha(bin_size,filetype): """ @@ -30,56 +191,82 @@ def mathpha(bin_size,filetype): will output pha files of the format 'MJD_binsize_' + filetype + '_cl50.pha'! bin_size - bin size in days - filetype - either 'bgsub' or 'bg' or 'cl'! + filetype - either 'bgsub' or 'bg' or 'cl' or 'x' or 'xbgsub' + x means "extra background" """ - normfile = Lv0_dirs.NGC300 + 'n300_ulx.bgsub_cl50_RGnorm_' + bin_size + '.ffphot' + normfile = Lv0_dirs.NGC300_2020 + 'n300_ulx.bgsub_cl50_g2020norm_' + bin_size + '.fffphot' mjds = np.genfromtxt(normfile,usecols=(0),unpack=True) - spectra_files = np.genfromtxt(normfile,dtype='str',usecols=(8),unpack=True) + spectra_files = np.genfromtxt(normfile,dtype='str',usecols=(9),unpack=True) for i in range(len(spectra_files)): #so for each BINNED MJD/counts exposures = [] + truncated_name = [] spectra_files_list = spectra_files[i].split(',') #get a list where each entry = one pha file + cl50_files = [spectra_files_list[j][:34] + spectra_files_list[j][40:49] + spectra_files_list[j][55:] for j in range(len(spectra_files_list))] #takes away the bgsub_ prefix if filetype == 'bg': - filetype_spectra_files_list = [spectra_files_list[j][0:2] + spectra_files_list[j][5:] for j in range(len(spectra_files_list))] #takes away the 'sub' part of the name + filetype_spectra_files_list = [spectra_files_list[j][:36] + spectra_files_list[j][39:51] + spectra_files_list[j][54:] for j in range(len(spectra_files_list))] #takes away the 'sub' part of the name elif filetype == 'cl': - filetype_spectra_files_list = [spectra_files_list[j][6:] for j in range(len(spectra_files_list))] #takes away the bgsub_ prefix + filetype_spectra_files_list = [spectra_files_list[j][:34] + spectra_files_list[j][40:49] + spectra_files_list[j][55:] for j in range(len(spectra_files_list))] #takes away the bgsub_ prefix elif filetype == 'bgsub': filetype_spectra_files_list = spectra_files_list + elif filetype == 'x': + filetype_spectra_files_list = [spectra_files_list[j][:36] + spectra_files_list[j][39:45] + 'xpha/xbg' + spectra_files_list[j][54:] for j in range(len(spectra_files_list))] + elif filetype == 'xbgsub': + filetype_spectra_files_list = [spectra_files_list[j][:45] + 'xpha/xbgsub_' + spectra_files_list[j][55:] for j in range(len(spectra_files_list))] + elif filetype == 'xsbg': + filetype_spectra_files_list = [spectra_files_list[j][:36] + spectra_files_list[j][39:45] + 'xspha/xsbg' + spectra_files_list[j][54:] for j in range(len(spectra_files_list))] + elif filetype == 'xsbgsub': + filetype_spectra_files_list = [spectra_files_list[j][:45] + 'xspha/xsbgsub_' + spectra_files_list[j][55:] for j in range(len(spectra_files_list))] + for j in range(len(filetype_spectra_files_list)): #for each individual pha file fits_file = fits.open(filetype_spectra_files_list[j]) exptime = fits_file[1].header['EXPOSURE'] #get exposure time + if filetype=='bg' or filetype=='x' or filetype=='xbgsub' or filetype=='xsbg' or filetype=='xsbgsub': + exptime = fits.open(cl50_files[j])[1].header['EXPOSURE'] exposures.append(exptime) #now we have a list of exposure times corresponding to each pha file for a given (binned) MJD/count rate total_exptime = sum(exposures) #get total exposure time for THAT MJD/count rate bin + for j in range(len(filetype_spectra_files_list)): + long_name = filetype_spectra_files_list[j] + short_name = str(pathlib.Path(long_name).name) + subprocess.run(['cp',long_name,short_name]) + truncated_name.append(short_name) + #### now to build the mathpha command + ################## NOTE, FOR BG/BGSUB FILES, MAKE SURE YOU USE EXPOSURE + ################## TIMES FROM THE CL50 FILES... SINCE THAT'S HOW MUCH THE + ################## OBSERVATION WAS EXPOSED FOR... mathpha = 'mathpha' calculation = '' for j in range(len(exposures)): - if filetype == 'bg' or filetype == 'bgsub': + if filetype == 'bg' or filetype == 'bgsub' or filetype == 'x' or filetype == 'xbgsub' or filetype == 'xsbg' or filetype == 'xsbgsub': if j == 0: calculation += '(' if j != len(exposures)-1: if int(exposures[j]) == exposures[j]: - calculation += str(int(exposures[j])) + '*' + filetype_spectra_files_list[j] + '+' + calculation += str(int(exposures[j])) + '*' + truncated_name[j] + '+' else: - calculation += str(exposures[j]) + '*' + filetype_spectra_files_list[j] + '+' + calculation += str(exposures[j]) + '*' + truncated_name[j] + '+' else: - calculation += str(exposures[j]) + '*' + filetype_spectra_files_list[j] + ') / ' + str(total_exptime) + calculation += str(exposures[j]) + '*' + truncated_name[j] + ') / ' + str(total_exptime) if filetype == 'cl': if j == 0: calculation += '(' if j != len(exposures)-1: - calculation += filetype_spectra_files_list[j] + '+' + calculation += truncated_name[j] + '+' else: - calculation += filetype_spectra_files_list[j] + ')' + calculation += truncated_name[j] + ')' + + if mjds[i] == 58449: + print(calculation) if filetype == 'cl': unit = 'C' - if filetype == 'bg' or filetype == 'bgsub': + if filetype == 'bg' or filetype == 'bgsub' or filetype == 'x' or filetype == 'xbgsub' or filetype == 'xsbg' or filetype == 'xsbgsub': unit = 'R' outfile = 'outfil=' + str(int(mjds[i])) + '_' + bin_size + '_' + filetype + '_cl50.pha' exposure = 'exposure=' + str(total_exptime) @@ -92,8 +279,15 @@ def mathpha(bin_size,filetype): logfile = str(int(mjds[i])) + '_' + bin_size + '_' + filetype + '_mathpha.log' #print(mathpha+' "'+calculation+ '" '+unit+' '+outfile+' '+exposure+' '+errmeth+' '+properr+' '+ncomments+' '+areascal+' '+clobber) with open(logfile,'w') as logtextfile: - logtextfile.write(subprocess.check_output([mathpha,calculation,unit,outfile,exposure,errmeth,properr,ncomments,areascal,clobber])) - logtextfile.close() + output = subprocess.run([mathpha,calculation,unit,outfile,exposure,errmeth,properr,ncomments,areascal,clobber],capture_output=True,text=True) + logtextfile.write(output.stdout) + logtextfile.write('*------------------------------* \n') + logtextfile.write(output.stderr) + logtextfile.close() + + ### removing the temporary spectra + for i in range(len(truncated_name)): + subprocess.run(['rm','-r',truncated_name[i]]) return @@ -104,31 +298,67 @@ def grppha(bin_size,filetype): will output pha files of the format 'grp_$MJD_$binsize_$filetype_cl50.pha'! bin_size - bin size in days - filetype - either 'bgsub' or 'bg' or 'cl'! + filetype - either 'bgsub' or 'bg' or 'cl' or 'x' or 'xbgsub' or 'xsbg' or 'xsbgsub'! """ binned_phas = sorted(glob.glob('*'+bin_size+'_'+filetype+'_*pha')) - command_file = Lv0_dirs.NGC300 + 'grppha_' + bin_size + '_' + filetype + '_commands.go' + command_file = Lv0_dirs.NGC300_2020 + 'grppha_' + bin_size + '_' + filetype + '_commands.go' writing = open(command_file,'w') #### now to build the grppha command grppha = 'grppha' chatter = 'chatter=0' for i in range(len(binned_phas)): backfile = binned_phas[i][:-11] + 'bg_cl50.pha' - #comm = 'comm="group nicer_channels_to_group.dat & systematics 30-1200 0.02 & chkey ANCRFILE /Volumes/Samsung_T5/nixtiaveonaxis20170601v002.arf & chkey RESPFILE /Volumes/Samsung_T5/nicer_upd_d52.rmf & chkey BACKFILE ' + backfile + ' & exit"' - comm = 'comm="group nicer_channels_to_group.dat & systematics 30-1200 0.02 & chkey ANCRFILE /Volumes/Samsung_T5/nixtiaveonaxis20170601v002.arf & chkey RESPFILE /Volumes/Samsung_T5/nicer_upd_d52.rmf & exit"' + #comm = 'comm="group nicer_channels_to_group.dat & systematics 30-1200 0.02 & chkey ANCRFILE /Volumes/Samsung_T5/nicer-consim135p-teamonly-array50.arf & chkey RESPFILE /Volumes/Samsung_T5/nicer-rmf6s-teamonly-array50.rmf & chkey BACKFILE ' + backfile + ' & exit"' + comm = 'comm="group nicer_channels_to_group.dat & systematics 30-1200 0.02 & chkey ANCRFILE /Volumes/Samsung_T5/nicer-consim135p-teamonly-array50.arf & chkey RESPFILE /Volumes/Samsung_T5/nicer-rmf6s-teamonly-array50.rmf & exit"' infile = 'infile="' + binned_phas[i] + '"' outfile = 'outfile="grp_' + binned_phas[i] + '"' writing.write(grppha+' '+infile+' '+outfile+' '+chatter+' '+comm+'\n') writing.close() - #subprocess.check_output(['source',command_file,'>','grppha_'+bin_size+'.log'],shell=True) + #subprocess.run(['source',command_file,'>','grppha_'+bin_size+'.log'],shell=True) if __name__ == "__main__": + + init_back_array = sorted(glob.glob(Lv0_dirs.NGC300_2020 + 'bg_cl50/pha/*.pha')) + on_eclipse = Lv0_dirs.NGC300_XMM + 'ngc300x1_oneclipse.fak' + off_eclipse = Lv0_dirs.NGC300_XMM + 'ngc300x1_offeclipse.fak' + fake_spec = np.array([on_eclipse,off_eclipse]) + T0 = 58239.3498 + Porb = (1/8.4712e-6)/86400 + + #combine_back(init_back_array,fake_spec,T0,Porb) + #combine_back_scal(init_back_array,fake_spec,T0,Porb) + + #mathpha(bin_size,'bg') + #mathpha(bin_size,'cl') #mathpha(bin_size,'bgsub') - grppha(bin_size,'bgsub') - #bg_mathpha(bin_size) - #bg_grppha(bin_size) + + #mathpha('03d','xbgsub') + #mathpha('05d','xbgsub') + #mathpha('10d','xbgsub') + + #mathpha('05d','xsbgsub') + + #mathpha('05d','xsbg') + + #grppha('03d','bg') + #grppha('05d','bg') + #grppha('10d','bg') + + #grppha('03d','cl') + #grppha('05d','cl') + #grppha('10d','cl') + + #grppha('03d','bgsub') + #grppha('05d','bgsub') + #grppha('10d','bgsub') + + #grppha('03d','x') + #grppha('05d','x') + #grppha('10d','x') + + #grppha('05d','xsbg') ################################## DEPRECATED ################################## @@ -195,7 +425,7 @@ def bg_mathpha(bin_size): logfile = str(int(mjds[i])) + '_' + bin_size + '_mathpha.log' print(mathpha+' "'+calculation+ '" '+unit+' '+outfile+' '+exposure+' '+errmeth+' '+properr+' '+ncomments+' '+areascal+' '+clobber) with open(logfile,'w') as logtextfile: - logtextfile.write(subprocess.check_output([mathpha,calculation,unit,outfile,exposure,errmeth,properr,ncomments,areascal,clobber])) + logtextfile.write(subprocess.run([mathpha,calculation,unit,outfile,exposure,errmeth,properr,ncomments,areascal,clobber])) logtextfile.close() return diff --git a/Lv1_spectra_txt.py b/Lv1_spectra_txt.py index c4baba7..7af48d7 100644 --- a/Lv1_spectra_txt.py +++ b/Lv1_spectra_txt.py @@ -18,6 +18,7 @@ import glob from mpldatacursor import datacursor import Lv0_dirs +import pathlib from matplotlib.backends.backend_pdf import PdfPages Lv0_dirs.global_par() @@ -84,11 +85,11 @@ """ ##### Do the same thing, but for the 5-day binned data -binspectra_bgsub = sorted(glob.glob('/Volumes/Samsung_T5/NGC300_ULX/jsgrp_*_cl_*.pha')) -spectra_all = '/Volumes/Samsung_T5/NGC300_ULX/jsgrp_cl_spectra.txt' +binspectra_bgsub = sorted(glob.glob('/Volumes/Samsung_T5/n300_ulx_2020/spectra_05d/jsgrp_*_3C50x_*.pha')) +spectra_all = '/Volumes/Samsung_T5/n300_ulx_2020/spectra_05d/jsgrp_3C50x_spectra.txt' spectra = np.array(open(spectra_all,'r').read().split('\n')) -separator = list(np.where(spectra=='NO NO NO NO')[0]) +separator = list(np.where(spectra=='NO NO NO NO NO NO')[0]) separator.insert(0,2) separator.insert(len(separator),len(spectra)-1) @@ -102,31 +103,34 @@ spectrum.close() """ +""" #not_to_use = ['58279','58334','58399','58464','58514','58599','58604'] not_to_use = [] #total_E = [] ##### time to plot all 41 spectra and save them onto PDFs...! -binspectra_cl = sorted(glob.glob('/Volumes/Samsung_T5/NGC300_ULX/jsgrp_58*_cl_*.txt')) -binspectra_bg = sorted(glob.glob('/Volumes/Samsung_T5/NGC300_ULX/grp_58*_bg_*.txt')) -binspectra_bgsub = sorted(glob.glob('/Volumes/Samsung_T5/NGC300_ULX/grp_58*_bgsub_*.txt')) +#binspectra_cl = sorted(glob.glob('/Volumes/Samsung_T5/n300_ulx_2020/spectra_05d/jsgrp_58*_cl_*.txt')) +#binspectra_cl = sorted(glob.glob('/Volumes/Samsung_T5/n300_ulx_2020/spectra_05d/grp_58*_bgsub_*.txt')) +binspectra_cl = sorted(glob.glob('/Volumes/Samsung_T5/n300_ulx_2020/spectra_05d/jsgrp_58*_3C50x_*.txt')) -""" -with PdfPages('jsgrp_binned_spectra.pdf') as pdf: + +with PdfPages('/Volumes/Samsung_T5/n300_ulx_2020/spectra_05d/jsgrp_3C50x_binned_spectra.pdf') as pdf: for i in tqdm(range(len(binspectra_cl))): - if binspectra_cl[i][-21:-16] not in not_to_use: - E_cl,E_cl_unc,flux_cl,flux_cl_unc = np.genfromtxt(binspectra_cl[i],usecols=(0,1,2,3),unpack=True,skip_footer=1) - E_bg,E_bg_unc,flux_bg,flux_bg_unc = np.genfromtxt(binspectra_bg[i],usecols=(0,1,2,3),unpack=True,skip_footer=1) - #total_E += list(E) - plt.errorbar(E_cl,flux_cl,xerr=E_cl_unc,yerr=flux_cl_unc,fmt='r+') - plt.errorbar(E_bg,flux_bg,xerr=E_bg_unc,yerr=flux_bg_unc,fmt='b+') - plt.title('File name: ' + binspectra_cl[i] + '\n' + 'Background: ' + binspectra_bg[i],fontsize=12) + if binspectra_cl[i][-24:-19] not in not_to_use: + E_cl,E_cl_unc,flux_cl,flux_cl_unc,bg,bg_unc = np.genfromtxt(binspectra_cl[i],usecols=(0,1,2,3,4,5),unpack=True,skip_footer=1) + plt.errorbar(E_cl,flux_cl,xerr=E_cl_unc,yerr=flux_cl_unc,color='r')#,drawstyle='steps-mid') + plt.errorbar(E_cl,bg,xerr=E_cl_unc,yerr=bg_unc,color='b')#,drawstyle='steps-mid' + plt.xscale('log') + plt.title('File name: ' + str(pathlib.Path(binspectra_cl[i]).name),fontsize=12) plt.xlabel('Energy (keV)',fontsize=10) + plt.xlim([0.3,12]) plt.ylabel('Normalized counts /s/keV',fontsize=10) - plt.legend(('cl','bg'),loc='best') + plt.axhline(y=0,lw=0.5,alpha=0.5) + #plt.legend(('cl','bg'),loc='best') pdf.savefig() plt.close() """ + #determined on 10/3 filtered_mjds = ['58239','58244','58249','58254','58259','58264','58269','58274', '58289','58309','58314','58324','58329','58334','58339','58389', @@ -155,161 +159,1025 @@ plt.show() """ +""" +##### 9/29/2020 - compare 3C50 and 3C50 plot_efsearch -################ 9/30 - to implement the 'area under the curve' idea... -#mjds = ['58239','58244','58249','58254','58259','58264','58269','58274','58279', -# '58284','58289','58294','58309','58314','58324','58329','58334','58339', -# '58344','58349','58384','58389','58394','58399','58409','58449','58454', -# '58459','58464','58469','58474','58479','58484','58489','58494','58499', -# '58504','58509','58514','58599','58604'] +binspectra_3C50 = sorted(glob.glob('/Volumes/Samsung_T5/n300_ulx_2020/spectra_05d/jsgrp_58*_3C50_*.txt')) +binspectra_3C50x = sorted(glob.glob('/Volumes/Samsung_T5/n300_ulx_2020/spectra_05d/jsgrp_58*_3C50x_*.txt')) -### 10/3 - spectra to actually use! -mjds = ['58239','58244','58249','58254','58259','58264','58269','58274', - '58289','58309','58314','58324','58329','58334','58339','58389', - '58399','58449','58454','58459','58464','58484','58489','58504', - '58509'] - -binspectra_cl = [binspectra_cl[i] for i in range(len(binspectra_cl)) if binspectra_cl[i][-21:-16] in mjds] - -index1 = 0 -index2 = -1 -all_energies_cl = [] -all_cl = [] - -all_energies_bgsub = [] -all_bgsub = [] -for i in tqdm(range(len(binspectra_cl))):#[index1:index2]): - area_cl = 0 - area_cl_percent = [] - - area_bgsub = 0 - area_bgsub_percent = [] - E_cl,E_cl_unc,flux_cl,flux_cl_unc = np.genfromtxt(binspectra_cl[i],usecols=(0,1,2,3),unpack=True,skip_footer=1) - #E_bg,E_bg_unc,flux_bg,flux_bg_unc = np.genfromtxt(binspectra_bg[i],usecols=(0,1,2,3),unpack=True,skip_footer=1) - E_bgsub,E_bgsub_unc,flux_bgsub,flux_bgsub_unc = np.genfromtxt(binspectra_bgsub[i],usecols=(0,1,2,3),unpack=True,skip_footer=1) - - for j in range(len(E_cl)-1): - if flux_cl[j] >= 0: - area_cl += (E_cl[j+1]-E_cl[j])*flux_cl[j] - - cumulative_cl = 0 - for j in range(len(E_cl)-1): - if flux_cl[j] >= 0: - area_current_cl = (E_cl[j+1]-E_cl[j])*flux_cl[j] - cumulative_cl += area_current_cl/area_cl*100 - area_cl_percent.append(cumulative_cl) - else: - if len(area_cl_percent) == 0: - area_cl_percent.append(0) - else: - area_cl_percent.append(area_cl_percent[-1]) - - for j in range(len(E_bgsub)-1): - if flux_bgsub[j] >= 0: - area_bgsub += (E_bgsub[j+1]-E_bgsub[j])*flux_bgsub[j] - - cumulative_bgsub = 0 - for j in range(len(E_bgsub)-1): - if flux_bgsub[j] >= 0: - area_current_bgsub = (E_bgsub[j+1]-E_bgsub[j])*flux_bgsub[j] - cumulative_bgsub += area_current_bgsub/area_bgsub*100 - area_bgsub_percent.append(cumulative_bgsub) - else: - if len(area_bgsub_percent) == 0: - area_bgsub_percent.append(0) - else: - area_bgsub_percent.append(area_bgsub_percent[-1]) +with PdfPages('/Volumes/Samsung_T5/n300_ulx_2020/spectra_05d/jsgrp_3C50_3C50x_altplot.pdf') as pdf: + for i in tqdm(range(len(binspectra_3C50))): + E1,E1_unc,flux1,flux1_unc,bg1,bg1_unc = np.genfromtxt(binspectra_3C50[i],usecols=(0,1,2,3,4,5),unpack=True,skip_footer=1) + E2,E2_unc,flux2,flux2_unc,bg2,bg2_unc = np.genfromtxt(binspectra_3C50x[i],usecols=(0,1,2,3,4,5),unpack=True,skip_footer=1) + plt.errorbar(E1,flux1,xerr=E1_unc,yerr=flux1_unc,color='r',drawstyle='steps-mid') + plt.errorbar(E2,flux2,xerr=E2_unc,yerr=flux2_unc,color='b',drawstyle='steps-mid') + plt.xscale('log') + plt.title('File name: ' + str(pathlib.Path(binspectra_3C50[i]).name),fontsize=12) + plt.xlabel('Energy (keV)',fontsize=10) + plt.xlim([0.3,12]) + plt.ylabel('Normalized counts /s/keV',fontsize=10) + plt.legend(('3C50','3C50 + X-1'),loc='best') + plt.axhline(y=0,lw=0.5,alpha=0.5) + pdf.savefig() + plt.close() +""" - all_energies_cl.append(E_cl[:-1]) - all_cl.append(area_cl_percent) +""" +##### 9/29/2020 - generate photometry files like Ron's! +xbgsub_fffphot = open(Lv0_dirs.NGC300_2020 + 'n300_ulx.xsbgsub_cl50_g2020norm.fffphot','w') +bgsub_file = np.genfromtxt(Lv0_dirs.NGC300_2020 + 'n300_ulx.bgsub_cl50_g2020norm.fffphot',dtype='str',usecols=(0),unpack=True) +exp,telapse,mjd,norm = np.genfromtxt(Lv0_dirs.NGC300_2020 + 'n300_ulx.bgsub_cl50_g2020norm.fffphot',dtype='float64',usecols=(1,2,11,12),unpack=True) +for i in tqdm(range(len(bgsub_file))): + xbgsub = Lv0_dirs.NGC300_2020 + 'bgsub_cl50/xspha/xs' + bgsub_file[i] + rates = fits.open(xbgsub)[1].data['RATE'] + chans = fits.open(xbgsub)[1].data['CHANNEL'] + s1 = str(round(sum(rates[20-1:30-1])*norm[i],4)) + s2 = str(round(sum(rates[30-1:40-1])*norm[i],4)) + a = str(round(sum(rates[40-1:100-1])*norm[i],4)) + b = str(round(sum(rates[100-1:200-1])*norm[i],4)) + c = str(round(sum(rates[200-1:400-1])*norm[i],4)) + d = str(round(sum(rates[400-1:1200-1])*norm[i],4)) + inband = str(round(sum(rates[40-1:1200-1])*norm[i],4)) + hbg = str(round(sum(rates[1300-1:1501-1])*norm[i],4)) + xbgsub_fffphot.write(str(pathlib.Path(xbgsub).name) + ' ' + str(exp[i]) + ' ' + str(telapse[i]) + ' ' + str(s1) + ' ' + str(s2) + ' ' + str(a) + ' ' + str(b) + ' ' + str(c) + ' ' + str(d) + ' ' + str(inband) + ' ' + str(hbg) + ' ' + str(mjd[i]) + ' ' + str(norm[i]) + '\n') +xbgsub_fffphot.close() +""" - all_energies_bgsub.append(E_bgsub[:-1]) - all_bgsub.append(area_bgsub_percent) +""" +a,b,c,d,inband,mjd = np.genfromtxt(Lv0_dirs.NGC300_2020 + 'n300_ulx.bgsub_cl50_g2020norm.fffphot',dtype='float64',usecols=(5,6,7,8,9,11),unpack=True) +a_x,b_x,c_x,d_x,inband_x,mjd_x = np.genfromtxt(Lv0_dirs.NGC300_2020 + 'n300_ulx.xbgsub_cl50_g2020norm.fffphot',dtype='float64',usecols=(5,6,7,8,9,11),unpack=True) plt.figure(1) -for i in range(len(all_energies_cl)): - #plt.figure(i+100) - plt.plot(all_energies_cl[i],all_cl[i],label=mjds[i+index1]) -#plt.plot(all_energies_cl[-3],all_cl[-3]) -plt.xlabel('Energy, E (keV)',fontsize=12) -plt.ylabel('Percentage of total area under curve, %',fontsize=12) -datacursor(formatter='{label}'.format,bbox=None) - -plt.axhline(y=80,alpha=0.5,lw=0.5) -plt.axhline(y=90,alpha=0.5,lw=0.5) -plt.axvline(x=4,alpha=0.5,lw=0.5) -plt.axvline(x=5,alpha=0.5,lw=0.5) -plt.axvline(x=6,alpha=0.5,lw=0.5) +plt.plot(mjd,a,'rx-') +plt.plot(mjd_x,a_x,'bx-') +plt.legend(('3C50 sub','3C50 + X-1 sub'),loc='best') +plt.title('A band (0.4-1 keV)',fontsize=12) +plt.figure(2) +plt.plot(mjd,b,'rx-') +plt.plot(mjd,b_x,'bx-') +plt.legend(('3C50 sub','3C50 + X-1 sub'),loc='best') +plt.title('B band (1-2 keV)',fontsize=12) +plt.figure(3) +plt.plot(mjd,c,'rx-') +plt.plot(mjd,c_x,'bx-') +plt.legend(('3C50 sub','3C50 + X-1 sub'),loc='best') +plt.title('C band (2-4 keV)',fontsize=12) +plt.figure(4) +plt.plot(mjd,inband,'rx-') +plt.plot(mjd,inband_x,'bx-') +plt.legend(('3C50 sub','3C50 + X-1 sub'),loc='best') +plt.title('In-band (0.4-12 keV)',fontsize=12) plt.show() +""" +""" +bgsub = sorted(glob.glob(Lv0_dirs.NGC300_2020 + 'bgsub_cl50/pha/bgsub_cl50*pha')) +comparison = open('/Volumes/Samsung_T5/n300_ulx_2020/n300_ulx.bgsub_cl50_g2020norm.phot','r').read().split('\n')[:-1] +s1_normphot = np.array([np.float(comparison[i].split()[3]) for i in range(len(comparison))]) +s2_normphot = np.array([np.float(comparison[i].split()[4]) for i in range(len(comparison))]) +a_normphot = np.array([np.float(comparison[i].split()[5]) for i in range(len(comparison))]) +b_normphot = np.array([np.float(comparison[i].split()[6]) for i in range(len(comparison))]) +c_normphot = np.array([np.float(comparison[i].split()[7]) for i in range(len(comparison))]) +d_normphot = np.array([np.float(comparison[i].split()[8]) for i in range(len(comparison))]) +inband_normphot = np.array([np.float(comparison[i].split()[9]) for i in range(len(comparison))]) +hbg_normphot = np.array([np.float(comparison[i].split()[10]) for i in range(len(comparison))]) +norm = np.array([np.float(comparison[i].split()[12]) for i in range(len(comparison))]) +""" """ -plt.figure(1) -for i in range(len(all_energies_bgsub)): - plt.plot(all_energies_bgsub[i],all_bgsub[i],label=mjds[i]) -plt.xlabel('Energy, E (keV)',fontsize=12) -plt.ylabel('Percentage of total area under curve, %',fontsize=12) -datacursor(formatter='{label}'.format) -plt.show() +##### To print the values from the data set +for i in range(len(bgsub)): + bgsub_file = str(pathlib.Path(bgsub[i]).name) + rates = fits.open(bgsub[i])[1].data['RATE'] + chans = fits.open(bgsub[i])[1].data['CHANNEL'] + s1 = str(round(sum(rates[20-1:30-1])*norm[i],4)) + s2 = str(round(sum(rates[30-1:40-1])*norm[i],4)) + a = str(round(sum(rates[40-1:100-1])*norm[i],4)) + b = str(round(sum(rates[100-1:200-1])*norm[i],4)) + c = str(round(sum(rates[200-1:400-1])*norm[i],4)) + d = str(round(sum(rates[400-1:1200-1])*norm[i],4)) + inband = str(round(sum(rates[40-1:1200-1])*norm[i],4)) + hbg = str(round(sum(rates[1300-1:1501-1])*norm[i],4)) + print(bgsub_file,s1,s2,a,b,c,d,inband,hbg) +##### """ """ -#bound1 = [0,0.5,1,2,3,4,5,6,7,8,9,10,11,12,13,14] -#bound2 = [0.5,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] -bound1 = [0.0,0.5,0.6,0.7,1.0,2.0,3.0,4.0,4.3,4.6,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0] -bound2 = [0.5,0.6,0.7,1.0,2.0,3.0,4.0,4.3,4.6,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0] -mjds = [] -for i in range(len(binspectra_bgsub)): - if binspectra_bgsub[i][-24:-19] not in not_to_use: - mjd = binspectra_bgsub[i][-24:-19] - E,E_unc,flux,flux_unc = np.genfromtxt(binspectra_bgsub[i],usecols=(0,1,2,3),unpack=True,skip_footer=1) - total_E += list(E) - - trunc1 = E[(E>=bound1[0])&(E=bound1[1])&(E=bound1[2])&(E=bound1[3])&(E=bound1[4])&(E=bound1[5])&(E=bound1[6])&(E=bound1[7])&(E=bound1[8])&(E=bound1[9])&(E=bound1[10])&(E=bound1[11])&(E=bound1[12])&(E=bound1[13])&(E=bound1[14])&(E=bound1[15])&(E=bound1[16])&(E=bound1[17])&(E=bound1[18])&(E=bound1[19])&(E=bound1[i])&(total_E<=bound2[i])] - percentage = round(len(truncated)/len(total_E)*100,2) - cumulative_percent += percentage - print('The percentage of ' + str(bound1[i]) + '-' + str(bound2[i]) + ' keV out of all data is: ' + str(percentage) + '% ; cumulative: ' + str(cumulative_percent) + '%') - - -plt.hist(total_E,bins=200,log=True) -plt.xlabel('Energy, E (keV)',fontsize=12) -plt.ylabel('Number',fontsize=12) -plt.show() +##### For the errors: +for i in range(len(bgsub)): + bgsub_file = str(pathlib.Path(bgsub[i]).name) + errs = fits.open(bgsub[i])[1].data['STAT_ERR'] + chans = fits.open(bgsub[i])[1].data['CHANNEL'] + s1 = str(round( np.sqrt(np.mean(errs[20-1:30-1]**2) * len(errs[20-1:30-1]))*norm[i],4)) + s2 = str(round( np.sqrt(np.mean(errs[30-1:40-1]**2) * len(errs[30-1:40-1]))*norm[i],4)) + a = str(round( np.sqrt(np.mean(errs[40-1:100-1]**2) * len(errs[40-1:100-1]))*norm[i],4)) + b = str(round( np.sqrt(np.mean(errs[100-1:200-1]**2) * len(errs[100-1:200-1]))*norm[i],4)) + c = str(round( np.sqrt(np.mean(errs[200-1:400-1]**2) * len(errs[200-1:400-1]))*norm[i],4)) + d = str(round( np.sqrt(np.mean(errs[400-1:1200-1]**2) * len(errs[400-1:1200-1]))*norm[i],4)) + inband = str(round( np.sqrt(np.mean(errs[40-1:1200-1]**2) * len(errs[40-1:1200-1]))*norm[i],4)) + hbg = str(round( np.sqrt(np.mean(errs[1300-1:1501-1]**2) * len(errs[1300-1:1501-1]))*norm[i],4)) + #print(bgsub_file,s1,s2,a,b,c,d,inband,hbg) +""" + +""" +comparison_err = open('/Volumes/Samsung_T5/n300_ulx_2020/n300_ulx.bgsub_cl50_g2020err_norm.phot','r').read().split('\n')[:-1] +s1_err = np.array([np.float(comparison_err[i].split()[3]) for i in range(len(comparison_err))]) +s2_err = np.array([np.float(comparison_err[i].split()[4]) for i in range(len(comparison_err))]) +a_err = np.array([np.float(comparison_err[i].split()[5]) for i in range(len(comparison_err))]) +b_err = np.array([np.float(comparison_err[i].split()[6]) for i in range(len(comparison_err))]) +c_err = np.array([np.float(comparison_err[i].split()[7]) for i in range(len(comparison_err))]) +d_err = np.array([np.float(comparison_err[i].split()[8]) for i in range(len(comparison_err))]) +inband_err = np.array([np.float(comparison_err[i].split()[9]) for i in range(len(comparison_err))]) +hbg_err = np.array([np.float(comparison_err[i].split()[10]) for i in range(len(comparison_err))]) +norm = np.array([np.float(comparison_err[i].split()[12]) for i in range(len(comparison_err))]) + +##### To compare between what I see in the bgsub spectra and the *err*.phot files generated by Ron +err_file = open(Lv0_dirs.NGC300_2020 + 'compare_photerr_bgsub.txt','w') +for i in tqdm(range(len(bgsub))): + bgsub_file = str(pathlib.Path(bgsub[i]).name) + errs = fits.open(bgsub[i])[1].data['STAT_ERR'] + chans = fits.open(bgsub[i])[1].data['CHANNEL'] + s1 = str(round( (round( np.sqrt(np.mean(errs[20-1:30-1]**2) * len(errs[20-1:30-1]))*norm[i],4) - s1_err[i])/s1_err[i]*100,4 )) + s2 = str(round( (round( np.sqrt(np.mean(errs[30-1:40-1]**2) * len(errs[30-1:40-1]))*norm[i],4) - s2_err[i])/s2_err[i]*100,4 )) + a = str(round( (round( np.sqrt(np.mean(errs[40-1:100-1]**2) * len(errs[40-1:100-1]))*norm[i],4) - a_err[i])/a_err[i]*100,4 )) + b = str(round( (round( np.sqrt(np.mean(errs[100-1:200-1]**2) * len(errs[100-1:200-1]))*norm[i],4) - b_err[i])/b_err[i]*100, 4)) + c = str(round( (round( np.sqrt(np.mean(errs[200-1:400-1]**2) * len(errs[200-1:400-1]))*norm[i],4) - c_err[i])/c_err[i]*100, 4)) + d = str(round( (round( np.sqrt(np.mean(errs[400-1:1200-1]**2) * len(errs[400-1:1200-1]))*norm[i],4) - d_err[i])/d_err[i]*100, 4)) + inband = str(round( (round( np.sqrt(np.mean(errs[40-1:1200-1]**2) * len(errs[40-1:1200-1]))*norm[i],4) - inband_err[i])/inband_err[i]*100, 4)) + hbg = str(round( (round( np.sqrt(np.mean(errs[1300-1:1501-1]**2) * len(errs[1300-1:1501-1]))*norm[i],4) - hbg_err[i])/hbg_err[i]*100, 4)) + err_file.write(bgsub_file + ' ' + s1 + ' ' + s2 + ' ' + a + ' ' + b + ' ' + c + ' ' + d + ' ' + inband + ' ' + hbg + '\n') +err_file.close() +""" + """ +##### To compare between what I see in the bgsub spectra and the .phot files generated by Ron +for i in range(len(bgsub)): + bgsub_file = str(pathlib.Path(bgsub[i]).name) + rates = fits.open(bgsub[i])[1].data['RATE'] + chans = fits.open(bgsub[i])[1].data['CHANNEL'] + s1 = str(round((round(sum(rates[20-1:30-1])*norm[i],4)-s1_normphot[i])/s1_normphot[i]*100,4)) + s2 = str(round((round(sum(rates[30-1:40-1])*norm[i],4)-s2_normphot[i])/s2_normphot[i]*100,4)) + a = str(round((round(sum(rates[40-1:100-1])*norm[i],4)-a_normphot[i])/a_normphot[i]*100,4)) + b = str(round((round(sum(rates[100-1:200-1])*norm[i],4)-b_normphot[i])/b_normphot[i]*100,4)) + c = str(round((round(sum(rates[200-1:400-1])*norm[i],4)-c_normphot[i])/c_normphot[i]*100,4)) + d = str(round((round(sum(rates[400-1:1200-1])*norm[i],4)-d_normphot[i])/d_normphot[i]*100,4)) + inband = str(round((round(sum(rates[40-1:1200-1])*norm[i],4)-inband_normphot[i])/inband_normphot[i]*100,4)) + hbg = str(round((round(sum(rates[1300-1:1501-1])*norm[i],4)-hbg_normphot[i])/hbg_normphot[i]*100,4)) + #print(bgsub_file,s1,s2,a,b,c,d,inband,hbg) +""" + +""" +##### To insert the error calculations into xbgsub: +bgsub_fffphot = open('/Volumes/Samsung_T5/n300_ulx_2020/n300_ulx.bgsub_cl50_g2020err_norm.fffphot','r').read().split('\n')[:-1] +exp,telapse,mjd,norm = np.genfromtxt(Lv0_dirs.NGC300_2020 + 'n300_ulx.bgsub_cl50_g2020err_norm.fffphot',dtype='float64',usecols=(1,2,11,12),unpack=True) +xbgsub_fffphot = np.array([Lv0_dirs.NGC300_2020 + 'bgsub_cl50/xspha/xs' + str(bgsub_fffphot[i].split()[0]) for i in range(len(bgsub_fffphot))]) + +##### To compare between what I see in the bgsub spectra and the *err*.phot files generated by Ron +xbgsub_err = open(Lv0_dirs.NGC300_2020 + 'n300_ulx.xsbgsub_cl50_g2020err_norm.fffphot','w') +for i in tqdm(range(len(xbgsub_fffphot))): + xbgsub_file = str(pathlib.Path(xbgsub_fffphot[i]).name) + errs = fits.open(xbgsub_fffphot[i])[1].data['STAT_ERR'] + chans = fits.open(xbgsub_fffphot[i])[1].data['CHANNEL'] + s1 = str(round( np.sqrt(np.mean(errs[20-1:30-1]**2) * len(errs[20-1:30-1]))*norm[i],4)) + s2 = str(round( np.sqrt(np.mean(errs[30-1:40-1]**2) * len(errs[30-1:40-1]))*norm[i],4)) + a = str(round( np.sqrt(np.mean(errs[40-1:100-1]**2) * len(errs[40-1:100-1]))*norm[i],4)) + b = str(round( np.sqrt(np.mean(errs[100-1:200-1]**2) * len(errs[100-1:200-1]))*norm[i],4)) + c = str(round( np.sqrt(np.mean(errs[200-1:400-1]**2) * len(errs[200-1:400-1]))*norm[i],4)) + d = str(round( np.sqrt(np.mean(errs[400-1:1200-1]**2) * len(errs[400-1:1200-1]))*norm[i],4)) + inband = str(round( np.sqrt(np.mean(errs[40-1:1200-1]**2) * len(errs[40-1:1200-1]))*norm[i],4)) + hbg = str(round( np.sqrt(np.mean(errs[1300-1:1501-1]**2) * len(errs[1300-1:1501-1]))*norm[i],4)) + xbgsub_err.write(xbgsub_file + ' ' + str(exp[i]) + ' ' + str(telapse[i]) + ' ' + str(s1) + ' ' + str(s2) + ' ' + str(a) + ' ' + str(b) + ' ' + str(c) + ' ' + str(d) + ' ' + str(inband) + ' ' + str(hbg) + ' ' + str(mjd[i]) + ' ' + str(norm[i]) + '\n') +xbgsub_err.close() +""" + +##### 10/8 + +def get_par(par_txt,pars): + """ + Extract values from the parameter text file + + par_txt - path to the text file + pars - list of parameters + """ + par_dict = {} + for i in range(len(pars)): + par_dict[pars[i]] = [] + + partext = open(par_txt,'r').read().split('\n') + for i in range(len(pars)): + for j in range(len(partext)): + if pars[i] in partext[j]: + parline = partext[j].split() + par_dict[pars[i]].append((float(parline[-3]),float(parline[-1]))) + + return par_dict + +def get_Cstat(cstat_txt): + """ + Extract values from the C-stat text file + + cstat_txt - path to the text file + """ + cstattxt = open(cstat_txt,'r').read().split('\n') + cstat = [] + for i in range(len(cstattxt)): + if "C-Statistic" in cstattxt[i]: + cstatline = cstattxt[i].split() + cstat.append((float(cstatline[1]),float(cstatline[3]))) + elif "Total" in cstattxt[i]: + total = (float(cstattxt[i].split()[-4]),float(cstattxt[i].split()[-2])) + + return cstat,total + +def get_lumin(lumin_txt): + """ + Extract values from the lumin text file + + lumin_txt - path to the text file + """ + lumintxt = open(lumin_txt,'r').read().split('\n') + lumin = [] + for i in range(len(lumintxt)): + if "Luminosity" in lumintxt[i]: + luminline = lumintxt[i].split() + lumin.append(float(luminline[2])) + + return np.array(lumin) + +def get_flux(flux_txt): + """ + Extract values from the flux text file + + flux_txt - path to the text file + """ + fluxtxt = open(flux_txt,'r').read().split('\n') + flux = [] + for i in range(len(fluxtxt)): + if "Model" in fluxtxt[i]: + fluxline = fluxtxt[i].split() + flux.append(float(fluxline[4][1:])) + + return np.array(flux) + +def area_under_curve(): + ################ 9/30/2019 - to implement the 'area under the curve' idea... + #mjds = ['58239','58244','58249','58254','58259','58264','58269','58274','58279', + # '58284','58289','58294','58309','58314','58324','58329','58334','58339', + # '58344','58349','58384','58389','58394','58399','58409','58449','58454', + # '58459','58464','58469','58474','58479','58484','58489','58494','58499', + # '58504','58509','58514','58599','58604'] + + """ + ### 10/3 - spectra to actually use! + mjds = ['58239','58244','58249','58254','58259','58264','58269','58274', + '58289','58309','58314','58324','58329','58334','58339','58389', + '58399','58449','58454','58459','58464','58484','58489','58504', + '58509'] + + binspectra_cl = [binspectra_cl[i] for i in range(len(binspectra_cl)) if binspectra_cl[i][-21:-16] in mjds] + + index1 = 0 + index2 = -1 + all_energies_cl = [] + all_cl = [] + + all_energies_bgsub = [] + all_bgsub = [] + for i in tqdm(range(len(binspectra_cl))):#[index1:index2]): + area_cl = 0 + area_cl_percent = [] + + area_bgsub = 0 + area_bgsub_percent = [] + E_cl,E_cl_unc,flux_cl,flux_cl_unc = np.genfromtxt(binspectra_cl[i],usecols=(0,1,2,3),unpack=True,skip_footer=1) + #E_bg,E_bg_unc,flux_bg,flux_bg_unc = np.genfromtxt(binspectra_bg[i],usecols=(0,1,2,3),unpack=True,skip_footer=1) + E_bgsub,E_bgsub_unc,flux_bgsub,flux_bgsub_unc = np.genfromtxt(binspectra_bgsub[i],usecols=(0,1,2,3),unpack=True,skip_footer=1) + + for j in range(len(E_cl)-1): + if flux_cl[j] >= 0: + area_cl += (E_cl[j+1]-E_cl[j])*flux_cl[j] + + cumulative_cl = 0 + for j in range(len(E_cl)-1): + if flux_cl[j] >= 0: + area_current_cl = (E_cl[j+1]-E_cl[j])*flux_cl[j] + cumulative_cl += area_current_cl/area_cl*100 + area_cl_percent.append(cumulative_cl) + else: + if len(area_cl_percent) == 0: + area_cl_percent.append(0) + else: + area_cl_percent.append(area_cl_percent[-1]) + + for j in range(len(E_bgsub)-1): + if flux_bgsub[j] >= 0: + area_bgsub += (E_bgsub[j+1]-E_bgsub[j])*flux_bgsub[j] + + cumulative_bgsub = 0 + for j in range(len(E_bgsub)-1): + if flux_bgsub[j] >= 0: + area_current_bgsub = (E_bgsub[j+1]-E_bgsub[j])*flux_bgsub[j] + cumulative_bgsub += area_current_bgsub/area_bgsub*100 + area_bgsub_percent.append(cumulative_bgsub) + else: + if len(area_bgsub_percent) == 0: + area_bgsub_percent.append(0) + else: + area_bgsub_percent.append(area_bgsub_percent[-1]) + + all_energies_cl.append(E_cl[:-1]) + all_cl.append(area_cl_percent) + + all_energies_bgsub.append(E_bgsub[:-1]) + all_bgsub.append(area_bgsub_percent) + + + plt.figure(1) + for i in range(len(all_energies_cl)): + #plt.figure(i+100) + plt.plot(all_energies_cl[i],all_cl[i],label=mjds[i+index1]) + #plt.plot(all_energies_cl[-3],all_cl[-3]) + plt.xlabel('Energy, E (keV)',fontsize=12) + plt.ylabel('Percentage of total area under curve, %',fontsize=12) + datacursor(formatter='{label}'.format,bbox=None) + + plt.axhline(y=80,alpha=0.5,lw=0.5) + plt.axhline(y=90,alpha=0.5,lw=0.5) + plt.axvline(x=4,alpha=0.5,lw=0.5) + plt.axvline(x=5,alpha=0.5,lw=0.5) + plt.axvline(x=6,alpha=0.5,lw=0.5) + + plt.show() + """ + + """ + plt.figure(1) + for i in range(len(all_energies_bgsub)): + plt.plot(all_energies_bgsub[i],all_bgsub[i],label=mjds[i]) + plt.xlabel('Energy, E (keV)',fontsize=12) + plt.ylabel('Percentage of total area under curve, %',fontsize=12) + datacursor(formatter='{label}'.format) + plt.show() + """ + + """ + #bound1 = [0,0.5,1,2,3,4,5,6,7,8,9,10,11,12,13,14] + #bound2 = [0.5,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] + bound1 = [0.0,0.5,0.6,0.7,1.0,2.0,3.0,4.0,4.3,4.6,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0] + bound2 = [0.5,0.6,0.7,1.0,2.0,3.0,4.0,4.3,4.6,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0] + mjds = [] + for i in range(len(binspectra_bgsub)): + if binspectra_bgsub[i][-24:-19] not in not_to_use: + mjd = binspectra_bgsub[i][-24:-19] + E,E_unc,flux,flux_unc = np.genfromtxt(binspectra_bgsub[i],usecols=(0,1,2,3),unpack=True,skip_footer=1) + total_E += list(E) + + trunc1 = E[(E>=bound1[0])&(E=bound1[1])&(E=bound1[2])&(E=bound1[3])&(E=bound1[4])&(E=bound1[5])&(E=bound1[6])&(E=bound1[7])&(E=bound1[8])&(E=bound1[9])&(E=bound1[10])&(E=bound1[11])&(E=bound1[12])&(E=bound1[13])&(E=bound1[14])&(E=bound1[15])&(E=bound1[16])&(E=bound1[17])&(E=bound1[18])&(E=bound1[19])&(E=bound1[i])&(total_E<=bound2[i])] + percentage = round(len(truncated)/len(total_E)*100,2) + cumulative_percent += percentage + print('The percentage of ' + str(bound1[i]) + '-' + str(bound2[i]) + ' keV out of all data is: ' + str(percentage) + '% ; cumulative: ' + str(cumulative_percent) + '%') + + + plt.hist(total_E,bins=200,log=True) + plt.xlabel('Energy, E (keV)',fontsize=12) + plt.ylabel('Number',fontsize=12) + plt.show() + """ + +##### 10/26; data obtained from doing a more systematic set of fits using tcl scripts + +def plot_fit_table(tablefile,pars): + """ + Plot the results from the fit_$MODEL.table tables + + table - the path to the table, which includes the model name + pars - model parameters, in the form of a list + """ + par_dict = {} + error_dict = {} + sigma_dict = {} + + filenames = np.genfromtxt(tablefile,dtype='str',usecols=(0),unpack=True) + mjds = np.array([float(filenames[i][-25:-20]) for i in range(len(filenames))]) + no_cols = 1 + 4*len(pars) + 8 + + counter = 0 #to keep track of the variable index; of the same order as in "pars"! + for i in range(1,no_cols-8,4): #for the parameter value + data_array = np.genfromtxt(tablefile,dtype='float',usecols=(i),unpack=True) + par_dict[pars[counter]] = data_array + counter += 1 + counter = 0 #to keep track of the variable index + for i in range(2,no_cols-8,4): #for the sigma value + data_array = np.genfromtxt(tablefile,dtype='float',usecols=(i),unpack=True) + sigma_dict[pars[counter]] = data_array + counter += 1 + counter = 0 #to keep track of the variable index + for i in range(3,no_cols-8,4): #for the error value + error_low, error_high = np.genfromtxt(tablefile,dtype='float',usecols=(i,i+1),unpack=True) #two arrays for lower and upper bound! + error_dict[pars[counter]] = np.array([(error_low[j],error_high[j]) for j in range(len(error_low)) ]) + counter += 1 + + cstat = np.genfromtxt(tablefile,dtype='float',usecols=(no_cols-8),unpack=True) + dof = np.genfromtxt(tablefile,dtype='float',usecols=(no_cols-7),unpack=True) + flux,flux_low,flux_high = np.genfromtxt(tablefile,dtype='float',usecols=(no_cols-6,no_cols-5,no_cols-4),unpack=True) + lumin,lumin_low,lumin_high = np.genfromtxt(tablefile,dtype='float',usecols=(no_cols-3,no_cols-2,no_cols-1),unpack=True)*1e44 + + ##### Plotting + fig,axs = plt.subplots(len(pars)+3,sharex=True,gridspec_kw={'hspace':0}) + fig.suptitle('Total C-stat: ' + str(round(sum(cstat),4)) + '/' + str(sum(dof))) + + for i in range(len(pars)): + axs[i].errorbar(x=mjds,y=par_dict[pars[i]],yerr=sigma_dict[pars[i]],color='r',fmt='x') + axs[i].set_ylabel(pars[i]) + axs[2].set_yscale('log') + axs[len(pars)].plot(mjds,lumin/1e39,'rx') + axs[len(pars)].set_yscale('log') + axs[len(pars)+1].plot(mjds,flux/1e-12,'rx') + axs[len(pars)+1].set_yscale('log') + axs[len(pars)+2].plot(mjds,cstat/dof,'rx') + axs[len(pars)+2].axhline(y=1.0,lw=0.5,alpha=0.5) + + axs[len(pars)].set_ylabel('Luminosity \n 1e39 \n ergs/s)') + axs[len(pars)+1].set_ylabel('Flux \n 1e-12 \n ergs/cm^2/s') + axs[len(pars)+2].set_ylabel('Reduced \n C-stat') + + axs[len(pars)+2].set_xlabel('Time (MJD)',fontsize=12) + + plt.show() + + +if __name__ == "__main__": + + tablefile = Lv0_dirs.NGC300_2020 + 'spectra_05d/fit_tbnew-diskbb.table' + pars = ['nH','Tin','norm'] + plot_fit_table(tablefile,pars) + + ##### For POWERLAW + + def powerlaw(): + cstat_varyPL,total_cstat_varyPL = get_Cstat(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-powerlaw_varyPL_cstat.txt') + lumin_varyPL = get_lumin(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-powerlaw_varyPL_lumin.txt') + flux_varyPL = get_flux(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-powerlaw_varyPL_flux.txt') + + par_dict_varynH = get_par(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-powerlaw_varynH_par.txt',['nH','PhoIndex','norm']) + cstat_varynH,total_cstat_varynH = get_Cstat(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-powerlaw_varynH_cstat.txt') + lumin_varynH = get_lumin(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-powerlaw_varynH_lumin.txt') + flux_varynH = get_flux(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-powerlaw_varynH_flux.txt') + + par_dict_varyall = get_par(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-powerlaw_varyall_par.txt',['nH','PhoIndex','norm']) + cstat_varyall,total_cstat_varyall = get_Cstat(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-powerlaw_varyall_cstat.txt') + lumin_varyall = get_lumin(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-powerlaw_varyall_lumin.txt') + flux_varyall = get_flux(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-powerlaw_varyall_flux.txt') + + mjds = np.genfromtxt(Lv0_dirs.NGC300_2020 + 'n300_ulx.xbgsub_cl50_g2020norm_05d.fffphot',usecols=(0),unpack=True) + + ##### for varyPL + def varyPL(): + fig,axs = plt.subplots(5,sharex=True,gridspec_kw={'hspace':0}) + fig.suptitle('Keep nH (TBNEW) fixed at (' + str(par_dict_varyPL['nH'][0][0]) + ' +- ' + str(par_dict_varyPL['nH'][0][1]) + ') E22 atoms cm^-2' + '\n' + 'Total C-stat: ' + str(total_cstat_varyPL[0]) + '/' + str(total_cstat_varyPL[1])) + phoindex_varyPL = np.array([par_dict_varyPL['PhoIndex'][i][0] for i in range(len(par_dict_varyPL['PhoIndex']))]) + phoindex_err_varyPL = np.array([par_dict_varyPL['PhoIndex'][i][1] for i in range(len(par_dict_varyPL['PhoIndex']))]) + norm_varyPL = np.array([par_dict_varyPL['norm'][i][0] for i in range(len(par_dict_varyPL['norm']))]) + norm_err_varyPL = np.array([par_dict_varyPL['norm'][i][1] for i in range(len(par_dict_varyPL['norm']))]) + + cstatarr_varyPL = np.array([cstat_varyPL[i][0]/cstat_varyPL[i][1] for i in range(len(cstat_varyPL)) ]) + + axs[0].errorbar(x=mjds,y=phoindex_varyPL,yerr=phoindex_err_varyPL,color='r',fmt='x') + axs[1].errorbar(x=mjds,y=norm_varyPL/1e-4,yerr=norm_err_varyPL/1e-4,color='r',fmt='x') + axs[2].plot(mjds,lumin_varyPL/1e38,'rx') + axs[3].plot(mjds,flux_varyPL/1e-12,'rx') + axs[4].plot(mjds,cstatarr_varyPL,'rx') + axs[4].axhline(y=1.0,lw=0.5,alpha=0.5) + + axs[0].set_ylabel('PhoIndex') + axs[1].set_ylabel('Norm (1e-4)') + axs[2].set_ylabel('Luminosity \n 1e38 \n ergs/s)') + axs[3].set_ylabel('Flux \n 1e-12 \n ergs/cm^2/s') + axs[4].set_ylabel('Reduced \n C-stat') + + axs[4].set_xlabel('Time (MJD)',fontsize=12) + + plt.show() + + ##### for varynH + def varynH(): + fig,axs = plt.subplots(4,sharex=True,gridspec_kw={'hspace':0}) + fig.suptitle('Keep PhoIndex fixed at (' + str(par_dict_varynH['PhoIndex'][0][0]) + ' +- ' + str(par_dict_varynH['PhoIndex'][0][1]) + ')' + '\n' + 'Keep norm fixed at (' + str(par_dict_varynH['norm'][0][0]) + ' +- ' + str(par_dict_varynH['norm'][0][1]) + '\n' + 'Total C-stat: ' + str(total_cstat_varynH[0]) + '/' + str(total_cstat_varynH[1])) + nH_varynH = np.array([par_dict_varynH['nH'][i][0] for i in range(len(par_dict_varynH['nH']))]) + nH_err_varynH = np.array([par_dict_varynH['nH'][i][1] for i in range(len(par_dict_varynH['nH']))]) + + cstatarr_varynH = np.array([cstat_varynH[i][0]/cstat_varynH[i][1] for i in range(len(cstat_varynH)) ]) + + axs[0].errorbar(x=mjds[nH_varynH<100],y=nH_varynH[nH_varynH<100],yerr=nH_err_varynH[nH_varynH<100],color='r',fmt='x') + axs[0].set_yscale('log') + axs[1].plot(mjds,lumin_varynH/1e38,'rx') + axs[2].plot(mjds,flux_varynH/1e-12,'rx') + axs[3].plot(mjds,cstatarr_varynH,'rx') + axs[3].axhline(y=1.0,lw=0.5,alpha=0.5) + + axs[0].set_ylabel('nH (E22 atoms/cm^2)') + axs[1].set_ylabel('Luminosity \n 1e38 \n ergs/s)') + axs[2].set_ylabel('Flux \n 1e-12 \n ergs/cm^2/s') + axs[3].set_ylabel('Reduced \n C-stat') + + axs[3].set_xlabel('Time (MJD)',fontsize=12) + + plt.show() + + ##### for varyall + def varyall(): + fig,axs = plt.subplots(6,sharex=True,gridspec_kw={'hspace':0}) + fig.suptitle('All of nH, PhoIndex, and norm are untied' + '\n' + 'Total C-stat: ' + str(total_cstat_varyall[0]) + '/' + str(total_cstat_varyall[1])) + phoindex_varyall = np.array([par_dict_varyall['PhoIndex'][i][0] for i in range(len(par_dict_varyall['PhoIndex']))]) + phoindex_err_varyall = np.array([par_dict_varyall['PhoIndex'][i][1] for i in range(len(par_dict_varyall['PhoIndex']))]) + norm_varyall = np.array([par_dict_varyall['norm'][i][0] for i in range(len(par_dict_varyall['norm']))]) + norm_err_varyall = np.array([par_dict_varyall['norm'][i][1] for i in range(len(par_dict_varyall['norm']))]) + nH_varyall = np.array([par_dict_varyall['nH'][i][0] for i in range(len(par_dict_varyall['nH']))]) + nH_err_varyall = np.array([par_dict_varyall['nH'][i][1] for i in range(len(par_dict_varyall['nH']))]) + + cstatarr_varyall = np.array([cstat_varyall[i][0]/cstat_varyall[i][1] for i in range(len(cstat_varyall)) ]) + + axs[0].errorbar(x=mjds,y=phoindex_varyall,yerr=phoindex_err_varyall,color='r',fmt='x') + axs[1].errorbar(x=mjds,y=norm_varyall/1e-4,yerr=norm_err_varyall/1e-4,color='r',fmt='x') + axs[2].errorbar(x=mjds,y=nH_varyall,yerr=nH_err_varyall,color='r',fmt='x') + axs[3].plot(mjds,lumin_varyall/1e38,'rx') + axs[4].plot(mjds,flux_varyall/1e-12,'rx') + axs[5].plot(mjds,cstatarr_varyall,'rx') + axs[5].axhline(y=1.0,lw=0.5,alpha=0.5) + + axs[0].set_ylabel('PhoIndex') + axs[1].set_ylabel('Norm \n (1e-4)') + axs[2].set_ylabel('nH \n 1E22 \n atoms/cm^2') + axs[3].set_ylabel('Luminosity \n 1e38 \n ergs/s)') + axs[4].set_ylabel('Flux \n 1e-12 \n ergs/cm^2/s') + axs[5].set_ylabel('Reduced \n C-stat') + + axs[5].set_xlabel('Time (MJD)',fontsize=12) + + plt.show() + + def bbodyrad(): + ##### vary kT, norm: + par_dict_varyBB = get_par(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-bbodyrad_varyBB_par.txt',['nH','kT','norm']) + cstat_varyBB,total_cstat_varyBB = get_Cstat(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-bbodyrad_varyBB_cstat.txt') + lumin_varyBB = get_lumin(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-bbodyrad_varyBB_lumin.txt') + flux_varyBB = get_flux(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-bbodyrad_varyBB_flux.txt') + + par_dict_varynH = get_par(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-bbodyrad_varynH_par.txt',['nH','kT','norm']) + cstat_varynH,total_cstat_varynH = get_Cstat(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-bbodyrad_varynH_cstat.txt') + lumin_varynH = get_lumin(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-bbodyrad_varynH_lumin.txt') + flux_varynH = get_flux(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-bbodyrad_varynH_flux.txt') + + par_dict_varyall = get_par(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-bbodyrad_varyall_par.txt',['nH','kT','norm']) + cstat_varyall,total_cstat_varyall = get_Cstat(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-bbodyrad_varyall_cstat.txt') + lumin_varyall = get_lumin(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-bbodyrad_varyall_lumin.txt') + flux_varyall = get_flux(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-bbodyrad_varyall_flux.txt') + + mjds = np.genfromtxt(Lv0_dirs.NGC300_2020 + 'n300_ulx.xbgsub_cl50_g2020norm_05d.fffphot',usecols=(0),unpack=True) + + ##### for varyBB + def varyBB(): + fig,axs = plt.subplots(5,sharex=True,gridspec_kw={'hspace':0}) + fig.suptitle('Keep nH (TBNEW) fixed at (' + str(par_dict_varyBB['nH'][0][0]) + ' +- ' + str(par_dict_varyBB['nH'][0][1]) + ') E22 atoms cm^-2' + '\n' + 'Total C-stat: ' + str(total_cstat_varyBB[0]) + '/' + str(total_cstat_varyBB[1])) + kT_varyBB = np.array([par_dict_varyBB['kT'][i][0] for i in range(len(par_dict_varyBB['kT']))]) + kT_err_varyBB = np.array([par_dict_varyBB['kT'][i][1] for i in range(len(par_dict_varyBB['kT']))]) + norm_varyBB = np.array([par_dict_varyBB['norm'][i][0] for i in range(len(par_dict_varyBB['norm']))]) + norm_err_varyBB = np.array([par_dict_varyBB['norm'][i][1] for i in range(len(par_dict_varyBB['norm']))]) + + cstatarr_varyBB = np.array([cstat_varyBB[i][0]/cstat_varyBB[i][1] for i in range(len(cstat_varyBB)) ]) + + axs[0].errorbar(x=mjds,y=kT_varyBB,yerr=kT_err_varyBB,color='r',fmt='x') + axs[1].errorbar(x=mjds,y=norm_varyBB,yerr=norm_err_varyBB,color='r',fmt='x') + axs[2].plot(mjds,lumin_varyBB/1e38,'rx') + axs[3].plot(mjds,flux_varyBB/1e-12,'rx') + axs[4].plot(mjds,cstatarr_varyBB,'rx') + axs[4].axhline(y=1.0,lw=0.5,alpha=0.5) + + axs[0].set_ylabel('kT (keV)') + axs[1].set_ylabel('Norm') + axs[2].set_ylabel('Luminosity \n 1e38 \n ergs/s)') + axs[3].set_ylabel('Flux \n 1e-12 \n ergs/cm^2/s') + axs[4].set_ylabel('Reduced \n C-stat') + + axs[4].set_xlabel('Time (MJD)',fontsize=12) + + plt.show() + + ##### for varynH + def varynH(): + fig,axs = plt.subplots(4,sharex=True,gridspec_kw={'hspace':0}) + fig.suptitle('Keep kT fixed at (' + str(par_dict_varynH['kT'][0][0]) + ' +- ' + str(par_dict_varynH['kT'][0][1]) + ') keV' + '\n' + 'Keep norm fixed at (' + str(par_dict_varynH['norm'][0][0]) + ' +- ' + str(par_dict_varynH['norm'][0][1]) + '\n' + 'Total C-stat: ' + str(total_cstat_varynH[0]) + '/' + str(total_cstat_varynH[1])) + nH_varynH = np.array([par_dict_varynH['nH'][i][0] for i in range(len(par_dict_varynH['nH']))]) + nH_err_varynH = np.array([par_dict_varynH['nH'][i][1] for i in range(len(par_dict_varynH['nH']))]) + + cstatarr_varynH = np.array([cstat_varynH[i][0]/cstat_varynH[i][1] for i in range(len(cstat_varynH)) ]) + + axs[0].errorbar(x=mjds,y=nH_varynH,yerr=nH_err_varynH,color='r',fmt='x') + axs[0].set_yscale('log') + axs[1].plot(mjds,lumin_varynH/1e38,'rx') + axs[2].plot(mjds,flux_varynH/1e-12,'rx') + axs[3].plot(mjds,cstatarr_varynH,'rx') + axs[3].axhline(y=1.0,lw=0.5,alpha=0.5) + + axs[0].set_ylabel('nH (E22 atoms/cm^2)') + axs[1].set_ylabel('Luminosity \n 1e38 \n ergs/s)') + axs[2].set_ylabel('Flux \n 1e-12 \n ergs/cm^2/s') + axs[3].set_ylabel('Reduced \n C-stat') + + axs[3].set_xlabel('Time (MJD)',fontsize=12) + + plt.show() + + ##### for varyall + def varyall(): + fig,axs = plt.subplots(6,sharex=True,gridspec_kw={'hspace':0}) + fig.suptitle('All of nH, kT, and norm are untied' + '\n' + 'Total C-stat: ' + str(total_cstat_varyall[0]) + '/' + str(total_cstat_varyall[1])) + kT_varyall = np.array([par_dict_varyall['kT'][i][0] for i in range(len(par_dict_varyall['kT']))]) + kT_err_varyall = np.array([par_dict_varyall['kT'][i][1] for i in range(len(par_dict_varyall['kT']))]) + norm_varyall = np.array([par_dict_varyall['norm'][i][0] for i in range(len(par_dict_varyall['norm']))]) + norm_err_varyall = np.array([par_dict_varyall['norm'][i][1] for i in range(len(par_dict_varyall['norm']))]) + nH_varyall = np.array([par_dict_varyall['nH'][i][0] for i in range(len(par_dict_varyall['nH']))]) + nH_err_varyall = np.array([par_dict_varyall['nH'][i][1] for i in range(len(par_dict_varyall['nH']))]) + + cstatarr_varyall = np.array([cstat_varyall[i][0]/cstat_varyall[i][1] for i in range(len(cstat_varyall)) ]) + + axs[0].errorbar(x=mjds,y=kT_varyall,yerr=kT_err_varyall,color='r',fmt='x') + axs[1].errorbar(x=mjds,y=norm_varyall,yerr=norm_err_varyall,color='r',fmt='x') + axs[2].errorbar(x=mjds,y=nH_varyall,yerr=nH_err_varyall,color='r',fmt='x') + axs[3].plot(mjds,lumin_varyall/1e38,'rx') + axs[4].plot(mjds,flux_varyall/1e-12,'rx') + axs[5].plot(mjds,cstatarr_varyall,'rx') + axs[5].axhline(y=1.0,lw=0.5,alpha=0.5) + + axs[0].set_ylabel('kT') + axs[1].set_ylabel('Norm') + axs[2].set_ylabel('nH \n 1E22 \n atoms/cm^2') + axs[3].set_ylabel('Luminosity \n 1e38 \n ergs/s)') + axs[4].set_ylabel('Flux \n 1e-12 \n ergs/cm^2/s') + axs[5].set_ylabel('Reduced \n C-stat') + + axs[5].set_xlabel('Time (MJD)',fontsize=12) + + plt.show() + + def diskbb(): + ##### vary kT, norm: + par_dict_varyBB = get_par(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-diskbb_varyBB_par.txt',['nH','Tin','norm']) + cstat_varyBB,total_cstat_varyBB = get_Cstat(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-diskbb_varyBB_cstat.txt') + lumin_varyBB = get_lumin(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-diskbb_varyBB_lumin.txt') + flux_varyBB = get_flux(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-diskbb_varyBB_flux.txt') + + par_dict_varynH = get_par(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-diskbb_varynH_par.txt',['nH','Tin','norm']) + cstat_varynH,total_cstat_varynH = get_Cstat(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-diskbb_varynH_cstat.txt') + lumin_varynH = get_lumin(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-diskbb_varynH_lumin.txt') + flux_varynH = get_flux(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-diskbb_varynH_flux.txt') + + par_dict_varyall = get_par(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-diskbb_varyall_par.txt',['nH','Tin','norm']) + cstat_varyall,total_cstat_varyall = get_Cstat(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-diskbb_varyall_cstat.txt') + lumin_varyall = get_lumin(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-diskbb_varyall_lumin.txt') + flux_varyall = get_flux(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-diskbb_varyall_flux.txt') + + mjds = np.genfromtxt(Lv0_dirs.NGC300_2020 + 'n300_ulx.xbgsub_cl50_g2020norm_05d.fffphot',usecols=(0),unpack=True) + + ##### for varyBB + def varyBB(): + fig,axs = plt.subplots(5,sharex=True,gridspec_kw={'hspace':0}) + fig.suptitle('Keep nH (TBNEW) fixed at (' + str(par_dict_varyBB['nH'][0][0]) + ' +- ' + str(par_dict_varyBB['nH'][0][1]) + ') E22 atoms cm^-2' + '\n' + 'Total C-stat: ' + str(total_cstat_varyBB[0]) + '/' + str(total_cstat_varyBB[1])) + Tin_varyBB = np.array([par_dict_varyBB['Tin'][i][0] for i in range(len(par_dict_varyBB['Tin']))]) + Tin_err_varyBB = np.array([par_dict_varyBB['Tin'][i][1] for i in range(len(par_dict_varyBB['Tin']))]) + norm_varyBB = np.array([par_dict_varyBB['norm'][i][0] for i in range(len(par_dict_varyBB['norm']))]) + norm_err_varyBB = np.array([par_dict_varyBB['norm'][i][1] for i in range(len(par_dict_varyBB['norm']))]) + + cstatarr_varyBB = np.array([cstat_varyBB[i][0]/cstat_varyBB[i][1] for i in range(len(cstat_varyBB)) ]) + + axs[0].errorbar(x=mjds,y=Tin_varyBB,yerr=Tin_err_varyBB,color='r',fmt='x') + axs[1].errorbar(x=mjds,y=norm_varyBB,yerr=norm_err_varyBB,color='r',fmt='x') + axs[2].plot(mjds,lumin_varyBB/1e38,'rx') + axs[3].plot(mjds,flux_varyBB/1e-12,'rx') + axs[4].plot(mjds,cstatarr_varyBB,'rx') + axs[4].axhline(y=1.0,lw=0.5,alpha=0.5) + + axs[0].set_ylabel('Tin (keV)') + axs[1].set_ylabel('Norm') + axs[2].set_ylabel('Luminosity \n 1e38 \n ergs/s)') + axs[3].set_ylabel('Flux \n 1e-12 \n ergs/cm^2/s') + axs[4].set_ylabel('Reduced \n C-stat') + + axs[4].set_xlabel('Time (MJD)',fontsize=12) + + plt.show() + + ##### for varynH + def varynH(): + fig,axs = plt.subplots(4,sharex=True,gridspec_kw={'hspace':0}) + fig.suptitle('Keep Tin fixed at (' + str(par_dict_varynH['Tin'][0][0]) + ' +- ' + str(par_dict_varynH['Tin'][0][1]) + ') keV' + '\n' + 'Keep norm fixed at (' + str(par_dict_varynH['norm'][0][0]) + ' +- ' + str(par_dict_varynH['norm'][0][1]) + '\n' + 'Total C-stat: ' + str(total_cstat_varynH[0]) + '/' + str(total_cstat_varynH[1])) + nH_varynH = np.array([par_dict_varynH['nH'][i][0] for i in range(len(par_dict_varynH['nH']))]) + nH_err_varynH = np.array([par_dict_varynH['nH'][i][1] for i in range(len(par_dict_varynH['nH']))]) + + cstatarr_varynH = np.array([cstat_varynH[i][0]/cstat_varynH[i][1] for i in range(len(cstat_varynH)) ]) + + axs[0].errorbar(x=mjds,y=nH_varynH,yerr=nH_err_varynH,color='r',fmt='x') + axs[0].set_yscale('log') + axs[1].plot(mjds,lumin_varynH/1e38,'rx') + axs[2].plot(mjds,flux_varynH/1e-12,'rx') + axs[3].plot(mjds,cstatarr_varynH,'rx') + axs[3].axhline(y=1.0,lw=0.5,alpha=0.5) + + axs[0].set_ylabel('nH (E22 atoms/cm^2)') + axs[1].set_ylabel('Luminosity \n 1e38 \n ergs/s)') + axs[2].set_ylabel('Flux \n 1e-12 \n ergs/cm^2/s') + axs[3].set_ylabel('Reduced \n C-stat') + + axs[3].set_xlabel('Time (MJD)',fontsize=12) + + plt.show() + + ##### for varyall + def varyall(): + fig,axs = plt.subplots(6,sharex=True,gridspec_kw={'hspace':0}) + fig.suptitle('All of nH, Tin, and norm are untied' + '\n' + 'Total C-stat: ' + str(total_cstat_varyall[0]) + '/' + str(total_cstat_varyall[1])) + Tin_varyall = np.array([par_dict_varyall['Tin'][i][0] for i in range(len(par_dict_varyall['Tin']))]) + Tin_err_varyall = np.array([par_dict_varyall['Tin'][i][1] for i in range(len(par_dict_varyall['Tin']))]) + norm_varyall = np.array([par_dict_varyall['norm'][i][0] for i in range(len(par_dict_varyall['norm']))]) + norm_err_varyall = np.array([par_dict_varyall['norm'][i][1] for i in range(len(par_dict_varyall['norm']))]) + nH_varyall = np.array([par_dict_varyall['nH'][i][0] for i in range(len(par_dict_varyall['nH']))]) + nH_err_varyall = np.array([par_dict_varyall['nH'][i][1] for i in range(len(par_dict_varyall['nH']))]) + + cstatarr_varyall = np.array([cstat_varyall[i][0]/cstat_varyall[i][1] for i in range(len(cstat_varyall)) ]) + + axs[0].errorbar(x=mjds,y=Tin_varyall,yerr=Tin_err_varyall,color='r',fmt='x') + axs[1].errorbar(x=mjds,y=norm_varyall,yerr=norm_err_varyall,color='r',fmt='x') + axs[2].errorbar(x=mjds,y=nH_varyall,yerr=nH_err_varyall,color='r',fmt='x') + axs[3].plot(mjds,lumin_varyall/1e38,'rx') + axs[4].plot(mjds,flux_varyall/1e-12,'rx') + axs[5].plot(mjds,cstatarr_varyall,'rx') + axs[5].axhline(y=1.0,lw=0.5,alpha=0.5) + + axs[0].set_ylabel('Tin') + axs[1].set_ylabel('Norm') + axs[2].set_ylabel('nH \n 1E22 \n atoms/cm^2') + axs[3].set_ylabel('Luminosity \n 1e38 \n ergs/s)') + axs[4].set_ylabel('Flux \n 1e-12 \n ergs/cm^2/s') + axs[5].set_ylabel('Reduced \n C-stat') + + axs[5].set_xlabel('Time (MJD)',fontsize=12) + + plt.show() + + #varyall() + + def simpl_diskbb(): + par_dict_varyGamma = get_par(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-simpl-diskbb-varyGamma_par.txt',['nH','Gamma','FracSctr','Tin','norm']) + cstat_varyGamma,total_cstat_varyGamma = get_Cstat(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-simpl-diskbb-varyGamma_cstat.txt') + lumin_varyGamma = get_lumin(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-simpl-diskbb-varyGamma_lumin.txt') + flux_varyGamma = get_flux(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-simpl-diskbb-varyGamma_flux.txt') + + par_dict_varyBB = get_par(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-simpl-diskbb-varyBB_par.txt',['nH','Gamma','FracSctr','Tin','norm']) + cstat_varyBB,total_cstat_varyBB = get_Cstat(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-simpl-diskbb-varyBB_cstat.txt') + lumin_varyBB = get_lumin(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-simpl-diskbb-varyBB_lumin.txt') + flux_varyBB = get_flux(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-simpl-diskbb-varyBB_flux.txt') + + par_dict_varyBB_Gamma = get_par(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-simpl-diskbb-varyBB-Gamma_par.txt',['nH','Gamma','FracSctr','Tin','norm']) + cstat_varyBB_Gamma,total_cstat_varyBB_Gamma = get_Cstat(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-simpl-diskbb-varyBB-Gamma_cstat.txt') + lumin_varyBB_Gamma = get_lumin(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-simpl-diskbb-varyBB-Gamma_lumin.txt') + flux_varyBB_Gamma = get_flux(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-simpl-diskbb-varyBB-Gamma_flux.txt') + + par_dict_varyBB_PL = get_par(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-simpl-diskbb-varyBB-PL_par.txt',['nH','Gamma','FracSctr','Tin','norm']) + cstat_varyBB_PL,total_cstat_varyBB_PL = get_Cstat(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-simpl-diskbb-varyBB-PL_cstat.txt') + lumin_varyBB_PL = get_lumin(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-simpl-diskbb-varyBB-PL_lumin.txt') + flux_varyBB_PL = get_flux(Lv0_dirs.NGC300_2020 + 'spectra_05d/tbnew-simpl-diskbb-varyBB-PL_flux.txt') + + mjds = np.genfromtxt(Lv0_dirs.NGC300_2020 + 'n300_ulx.xbgsub_cl50_g2020norm_05d.fffphot',usecols=(0),unpack=True) + + def varyGamma(): + fig,axs = plt.subplots(4,sharex=True,gridspec_kw={'hspace':0}) + fig.suptitle('Keep nH (TBNEW) fixed at (' + str(par_dict_varyGamma['nH'][0][0]) + ' +- ' + str(par_dict_varyGamma['nH'][0][1]) + ') E22 atoms cm^-2' + '\n' + 'FracSctr fixed at ' + str(par_dict_varyGamma['FracSctr'][0][0]) + ' +- ' + str(par_dict_varyGamma['FracSctr'][0][1]) + '\n' + 'Tin fixed at ' + str(par_dict_varyGamma['Tin'][0][0]) + ' +- ' + str(par_dict_varyGamma['Tin'][0][1]) + '\n' + 'diskbb norm fixed at ' + str(par_dict_varyGamma['norm'][0][0]) + ' +- ' + str(par_dict_varyGamma['norm'][0][1]) + '\n' + 'Total C-stat: ' + str(total_cstat_varyGamma[0]) + '/' + str(total_cstat_varyGamma[1])) + Gamma_varyGamma = np.array([par_dict_varyGamma['Gamma'][i][0] for i in range(len(par_dict_varyGamma['Gamma']))]) + Gamma_err_varyGamma = np.array([par_dict_varyGamma['Gamma'][i][1] for i in range(len(par_dict_varyGamma['Gamma']))]) + + cstatarr_varyGamma = np.array([cstat_varyGamma[i][0]/cstat_varyGamma[i][1] for i in range(len(cstat_varyGamma)) ]) + + axs[0].errorbar(x=mjds,y=Gamma_varyGamma,yerr=Gamma_err_varyGamma,color='r',fmt='x') + axs[0].set_yscale('log') + axs[1].plot(mjds,lumin_varyGamma,'rx') + axs[1].set_yscale('log') + axs[2].plot(mjds,flux_varyGamma,'rx') + axs[2].set_yscale('log') + axs[3].plot(mjds,cstatarr_varyGamma,'rx') + axs[3].set_yscale('log') + axs[3].axhline(y=1.0,lw=0.5,alpha=0.5) + + axs[0].set_ylabel('Gamma') + axs[1].set_ylabel('Luminosity \n (ergs/s)') + axs[2].set_ylabel('Flux \n (ergs/cm^2/s)') + axs[3].set_ylabel('Reduced \n C-stat') + + axs[3].set_xlabel('Time (MJD)',fontsize=12) + + plt.show() + + def varyBB(): + fig,axs = plt.subplots(5,sharex=True,gridspec_kw={'hspace':0}) + fig.suptitle('Keep nH (TBNEW) fixed at (' + str(par_dict_varyBB['nH'][0][0]) + ' +- ' + str(par_dict_varyBB['nH'][0][1]) + ') E22 atoms cm^-2' + '\n' + 'FracSctr fixed at ' + str(par_dict_varyBB['FracSctr'][0][0]) + ' +- ' + str(par_dict_varyBB['FracSctr'][0][1]) + '\n' + 'Gamma fixed at ' + str(par_dict_varyBB['Gamma'][0][0]) + ' +- ' + str(par_dict_varyBB['Gamma'][0][1]) + '\n' + 'Total C-stat: ' + str(total_cstat_varyBB[0]) + '/' + str(total_cstat_varyBB[1])) + Tin_varyBB = np.array([par_dict_varyBB['Tin'][i][0] for i in range(len(par_dict_varyBB['Tin']))]) + Tin_err_varyBB = np.array([par_dict_varyBB['Tin'][i][1] for i in range(len(par_dict_varyBB['Tin']))]) + norm_varyBB = np.array([par_dict_varyBB['norm'][i][0] for i in range(len(par_dict_varyBB['norm']))]) + norm_err_varyBB = np.array([par_dict_varyBB['norm'][i][1] for i in range(len(par_dict_varyBB['norm']))]) + + cstatarr_varyBB = np.array([cstat_varyBB[i][0]/cstat_varyBB[i][1] for i in range(len(cstat_varyBB)) ]) + + axs[0].errorbar(x=mjds,y=Tin_varyBB,yerr=Tin_err_varyBB,color='r',fmt='x') + axs[0].set_yscale('log') + axs[1].errorbar(x=mjds,y=norm_varyBB,yerr=norm_err_varyBB,color='r',fmt='x') + axs[1].set_yscale('log') + axs[2].plot(mjds,lumin_varyBB,'rx') + axs[2].set_yscale('log') + axs[3].plot(mjds,flux_varyBB,'rx') + axs[3].set_yscale('log') + axs[4].plot(mjds,cstatarr_varyBB,'rx') + axs[4].set_yscale('log') + axs[4].axhline(y=1.0,lw=0.5,alpha=0.5) + + axs[0].set_ylabel('Tin (keV)') + axs[1].set_ylabel('norm') + axs[2].set_ylabel('Luminosity \n (ergs/s)') + axs[3].set_ylabel('Flux \n (ergs/cm^2/s)') + axs[4].set_ylabel('Reduced \n C-stat') + + axs[4].set_xlabel('Time (MJD)',fontsize=12) + + plt.show() + + def varyBB_Gamma(): + fig,axs = plt.subplots(6,sharex=True,gridspec_kw={'hspace':0}) + fig.suptitle('Keep nH (TBNEW) fixed at (' + str(par_dict_varyBB_Gamma['nH'][0][0]) + ' +- ' + str(par_dict_varyBB_Gamma['nH'][0][1]) + ') E22 atoms cm^-2' + '\n' + 'FracSctr fixed at ' + str(par_dict_varyBB_Gamma['FracSctr'][0][0]) + ' +- ' + str(par_dict_varyBB_Gamma['FracSctr'][0][1]) + '\n' + 'Total C-stat: ' + str(total_cstat_varyBB_Gamma[0]) + '/' + str(total_cstat_varyBB_Gamma[1])) + Gamma_varyBB_Gamma = np.array([par_dict_varyBB_Gamma['Gamma'][i][0] for i in range(len(par_dict_varyBB_Gamma['Gamma']))]) + Gamma_err_varyBB_Gamma = np.array([par_dict_varyBB_Gamma['Gamma'][i][1] for i in range(len(par_dict_varyBB_Gamma['Gamma']))]) + Tin_varyBB_Gamma = np.array([par_dict_varyBB_Gamma['Tin'][i][0] for i in range(len(par_dict_varyBB_Gamma['Tin']))]) + Tin_err_varyBB_Gamma = np.array([par_dict_varyBB_Gamma['Tin'][i][1] for i in range(len(par_dict_varyBB_Gamma['Tin']))]) + norm_varyBB_Gamma = np.array([par_dict_varyBB_Gamma['norm'][i][0] for i in range(len(par_dict_varyBB_Gamma['norm']))]) + norm_err_varyBB_Gamma = np.array([par_dict_varyBB_Gamma['norm'][i][1] for i in range(len(par_dict_varyBB_Gamma['norm']))]) + + cstatarr_varyBB_Gamma = np.array([cstat_varyBB_Gamma[i][0]/cstat_varyBB_Gamma[i][1] for i in range(len(cstat_varyBB_Gamma)) ]) + + axs[0].errorbar(x=mjds,y=Gamma_varyBB_Gamma,yerr=Gamma_err_varyBB_Gamma,color='r',fmt='x') + axs[0].axhline(y=4.5,lw=0.5,alpha=0.5) + axs[0].axhline(y=1,lw=0.5,alpha=0.5) + axs[1].errorbar(x=mjds,y=Tin_varyBB_Gamma,yerr=Tin_err_varyBB_Gamma,color='r',fmt='x') + axs[2].errorbar(x=mjds,y=norm_varyBB_Gamma,yerr=norm_err_varyBB_Gamma,color='r',fmt='x') + axs[2].set_yscale('log') + axs[3].plot(mjds,lumin_varyBB_Gamma,'rx') + axs[3].set_yscale('log') + axs[4].plot(mjds,flux_varyBB_Gamma,'rx') + axs[4].set_yscale('log') + axs[5].plot(mjds,cstatarr_varyBB_Gamma,'rx') + axs[5].axhline(y=1.0,lw=0.5,alpha=0.5) + + axs[0].set_ylabel('Gamma') + axs[1].set_ylabel('Tin (keV)') + axs[2].set_ylabel('norm') + axs[3].set_ylabel('Luminosity \n (ergs/s)') + axs[4].set_ylabel('Flux \n (ergs/cm^2/s)') + axs[5].set_ylabel('Reduced \n C-stat') + + axs[5].set_xlabel('Time (MJD)',fontsize=12) + + plt.show() + + def varyBB_PL(): + fig,axs = plt.subplots(7,sharex=True,gridspec_kw={'hspace':0}) + fig.suptitle('Keep nH (TBNEW) fixed at (' + str(par_dict_varyBB_PL['nH'][0][0]) + ' +- ' + str(par_dict_varyBB_PL['nH'][0][1]) + ') E22 atoms cm^-2' + '\n' + 'Total C-stat: ' + str(total_cstat_varyBB_PL[0]) + '/' + str(total_cstat_varyBB_PL[1])) + Gamma_varyBB_PL = np.array([par_dict_varyBB_PL['Gamma'][i][0] for i in range(len(par_dict_varyBB_PL['Gamma']))]) + Gamma_err_varyBB_PL = np.array([par_dict_varyBB_PL['Gamma'][i][1] for i in range(len(par_dict_varyBB_PL['Gamma']))]) + FracSctr_varyBB_PL = np.array([par_dict_varyBB_PL['FracSctr'][i][0] for i in range(len(par_dict_varyBB_PL['FracSctr']))]) + FracSctr_err_varyBB_PL = np.array([par_dict_varyBB_PL['FracSctr'][i][1] for i in range(len(par_dict_varyBB_PL['FracSctr']))]) + Tin_varyBB_PL = np.array([par_dict_varyBB_PL['Tin'][i][0] for i in range(len(par_dict_varyBB_PL['Tin']))]) + Tin_err_varyBB_PL = np.array([par_dict_varyBB_PL['Tin'][i][1] for i in range(len(par_dict_varyBB_PL['Tin']))]) + norm_varyBB_PL = np.array([par_dict_varyBB_PL['norm'][i][0] for i in range(len(par_dict_varyBB_PL['norm']))]) + norm_err_varyBB_PL = np.array([par_dict_varyBB_PL['norm'][i][1] for i in range(len(par_dict_varyBB_PL['norm']))]) + + cstatarr_varyBB_PL = np.array([cstat_varyBB_PL[i][0]/cstat_varyBB_PL[i][1] for i in range(len(cstat_varyBB_PL)) ]) + + axs[0].errorbar(x=mjds,y=Gamma_varyBB_PL,yerr=Gamma_err_varyBB_PL,color='r',fmt='x') + axs[0].axhline(y=4.5,lw=0.5,alpha=0.5) + axs[0].set_yscale('log') + axs[0].set_ylim([0.1,5]) + axs[1].errorbar(x=mjds,y=FracSctr_varyBB_PL,yerr=FracSctr_err_varyBB_PL,color='r',fmt='x') + axs[1].set_yscale('log') + axs[1].set_ylim([0.1,1]) + axs[2].errorbar(x=mjds,y=Tin_varyBB_PL,yerr=Tin_err_varyBB_PL,color='r',fmt='x') + axs[2].set_yscale('log') + axs[3].errorbar(x=mjds,y=norm_varyBB_PL,yerr=norm_err_varyBB_PL,color='r',fmt='x') + axs[3].set_yscale('log') + axs[4].plot(mjds,lumin_varyBB_PL,'rx') + axs[4].set_yscale('log') + axs[5].plot(mjds,flux_varyBB_PL,'rx') + axs[5].set_yscale('log') + axs[6].plot(mjds,cstatarr_varyBB_PL,'rx') + axs[6].set_yscale('log') + axs[6].axhline(y=1.0,lw=0.5,alpha=0.5) + + axs[0].set_ylabel('Gamma') + axs[1].set_ylabel('FracSctr') + axs[2].set_ylabel('Tin (keV)') + axs[3].set_ylabel('norm') + axs[4].set_ylabel('Luminosity \n (ergs/s)') + axs[5].set_ylabel('Flux \n (ergs/cm^2/s)') + axs[6].set_ylabel('Reduced \n C-stat') + + axs[6].set_xlabel('Time (MJD)',fontsize=12) + + plt.show() + + #varyGamma() + varyBB_Gamma() + #varyBB_PL() + + def xs_simpl_diskbb(): + par_dict_varyBB_Gamma = get_par(Lv0_dirs.NGC300_2020 + 'spectra_05d/xs_E_tbnew-simpl-diskbb-varyBB-Gamma_par.txt',['nH','Gamma','FracSctr','Tin','norm']) + cstat_varyBB_Gamma,total_cstat_varyBB_Gamma = get_Cstat(Lv0_dirs.NGC300_2020 + 'spectra_05d/xs_E_tbnew-simpl-diskbb-varyBB-Gamma_cstat.txt') + lumin_varyBB_Gamma = get_lumin(Lv0_dirs.NGC300_2020 + 'spectra_05d/xs_E_tbnew-simpl-diskbb-varyBB-Gamma_lumin.txt') + flux_varyBB_Gamma = get_flux(Lv0_dirs.NGC300_2020 + 'spectra_05d/xs_E_tbnew-simpl-diskbb-varyBB-Gamma_flux.txt') + + mjds = np.genfromtxt(Lv0_dirs.NGC300_2020 + 'n300_ulx.xbgsub_cl50_g2020norm_05d.fffphot',usecols=(0),unpack=True) + + def varyBB_Gamma(): + fig,axs = plt.subplots(6,sharex=True,gridspec_kw={'hspace':0}) + fig.suptitle('Keep nH (TBNEW) fixed at (' + str(par_dict_varyBB_Gamma['nH'][0][0]) + ' +- ' + str(par_dict_varyBB_Gamma['nH'][0][1]) + ') E22 atoms cm^-2' + '\n' + 'FracSctr fixed at ' + str(par_dict_varyBB_Gamma['FracSctr'][0][0]) + ' +- ' + str(par_dict_varyBB_Gamma['FracSctr'][0][1]) + '\n' + 'Total C-stat: ' + str(total_cstat_varyBB_Gamma[0]) + '/' + str(total_cstat_varyBB_Gamma[1])) + Gamma_varyBB_Gamma = np.array([par_dict_varyBB_Gamma['Gamma'][i][0] for i in range(len(par_dict_varyBB_Gamma['Gamma']))]) + Gamma_err_varyBB_Gamma = np.array([par_dict_varyBB_Gamma['Gamma'][i][1] for i in range(len(par_dict_varyBB_Gamma['Gamma']))]) + Tin_varyBB_Gamma = np.array([par_dict_varyBB_Gamma['Tin'][i][0] for i in range(len(par_dict_varyBB_Gamma['Tin']))]) + Tin_err_varyBB_Gamma = np.array([par_dict_varyBB_Gamma['Tin'][i][1] for i in range(len(par_dict_varyBB_Gamma['Tin']))]) + norm_varyBB_Gamma = np.array([par_dict_varyBB_Gamma['norm'][i][0] for i in range(len(par_dict_varyBB_Gamma['norm']))]) + norm_err_varyBB_Gamma = np.array([par_dict_varyBB_Gamma['norm'][i][1] for i in range(len(par_dict_varyBB_Gamma['norm']))]) + + cstatarr_varyBB_Gamma = np.array([cstat_varyBB_Gamma[i][0]/cstat_varyBB_Gamma[i][1] for i in range(len(cstat_varyBB_Gamma)) ]) + + axs[0].errorbar(x=mjds,y=Gamma_varyBB_Gamma,yerr=Gamma_err_varyBB_Gamma,color='r',fmt='x') + axs[0].axhline(y=4.5,lw=0.5,alpha=0.5) + axs[0].axhline(y=1.0,lw=0.5,alpha=0.5) + axs[1].errorbar(x=mjds,y=Tin_varyBB_Gamma,yerr=Tin_err_varyBB_Gamma,color='r',fmt='x') + axs[2].errorbar(x=mjds,y=norm_varyBB_Gamma,yerr=norm_err_varyBB_Gamma,color='r',fmt='x') + axs[2].set_yscale('log') + axs[3].plot(mjds,lumin_varyBB_Gamma,'rx') + axs[3].set_yscale('log') + axs[4].plot(mjds,flux_varyBB_Gamma,'rx') + axs[4].set_yscale('log') + axs[5].plot(mjds,cstatarr_varyBB_Gamma,'rx') + axs[5].axhline(y=1.0,lw=0.5,alpha=0.5) + + axs[0].set_ylabel('Gamma') + axs[1].set_ylabel('Tin (keV)') + axs[2].set_ylabel('norm') + axs[3].set_ylabel('Luminosity \n (ergs/s)') + axs[4].set_ylabel('Flux \n (ergs/cm^2/s)') + axs[5].set_ylabel('Reduced \n C-stat') + + axs[5].set_xlabel('Time (MJD)',fontsize=12) + + plt.show() + + varyBB_Gamma() + + #powerlaw() + #bbodyrad() + #diskbb() + #simpl_diskbb() + #xs_simpl_diskbb() #data 1:1 bgsub_cl50_100.pha 2:2 bgsub_cl50_101.pha 3:3 bgsub_cl50_102.pha #response 1 /Users/masonng/Documents/MIT/Research/nicer-data/nicer.rmf 2 /Users/masonng/Documents/MIT/Research/nicer-data/nicer.rmf 3 /Users/masonng/Documents/MIT/Research/nicer-data/nicer.rmf diff --git a/Lv1_swift_filter.py b/Lv1_swift_filter.py new file mode 100644 index 0000000..0da9203 --- /dev/null +++ b/Lv1_swift_filter.py @@ -0,0 +1,538 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +Created on Tues May 5 2:43pm 2020 + +Filtering out Swift data. +5/5: Just doing filters based on region files + +""" +from __future__ import division, print_function +import numpy as np +import numpy.ma as ma +from astropy.io import fits +from astropy.wcs import WCS,utils +from reproject import reproject_interp +from astropy.coordinates import SkyCoord +from reproject.mosaicking import find_optimal_celestial_wcs +import matplotlib.pyplot as plt +import Lv0_dirs,Lv1_data_gtis,Lv2_presto_subroutines,Lv2_mkdir +from matplotlib.backends.backend_pdf import PdfPages +from scipy.ndimage import gaussian_filter +import os +from tqdm import tqdm +import subprocess +import pathlib +import glob + +Lv0_dirs.global_par() #obtaining the global parameters + +def get_ra_dec(eventfile): + """ + Obtain the RA_OBJ and DEC_OBJ corresponding to the observation! + + eventfile - path to the event file. Will extract ObsID from this for the NICER files. + """ + event = fits.open(eventfile) + event_header = event[1].header + + return event_header['RA_OBJ'], event_header['DEC_OBJ'] + +def barycorr(eventfile,outfile,refframe,orbit_file,output_folder): + """ + General function to perform the barycenter corrections for a Swift event file + + eventfile - path to the event file. Will extract ObsID from this for the NICER files. + outfile - path to the output event file with barycenter corrections applied + refframe - reference frame for barycenter corrections (usually ICRS) + orbit_file - path to the orbit file of the observation + output_folder - path to the folder where the outfile will be + """ + obsid = eventfile[2:13] + + logfile = output_folder + 'barycorr_notes.txt' + ra,dec = get_ra_dec(eventfile) + + with open(logfile,'w') as logtextfile: + output = subprocess.run(['barycorr',eventfile,'outfile='+outfile,'orbitfiles='+orbit_file,'ra='+str(ra),'dec='+str(dec),'refframe='+str(refframe),'clobber=YES'],capture_output=True,text=True) + logtextfile.write(output.stdout) + logtextfile.write('*------------------------------* \n') + logtextfile.write(output.stderr) + logtextfile.close() + +def filtering(eventlist,regtype,instructfile): + """ + Filtering the original event file based on the defined region files from DS9 + + eventlist - list of event files + regtype - type of region (e.g., for NGC 300, there's ngc300ulx1, ngc300x1, ngc300bg) + instructfile - where to save the instructions file + """ + if type(eventlist) != np.array and type(eventlist) != list: + raise TypeError('eventlist should either be an array or a list!') + + instruct = open(instructfile,'w') + + instruct.write('set mission swift' + '\n') + instruct.write('set inst xrt' + '\n') + + for i in range(len(eventlist)): + parent_folder = str(pathlib.Path(eventlist[i]).parent) + filename = str(pathlib.Path(eventlist[i]).name) + + instruct.write('set datadir ' + parent_folder + '/' + '\n') + + for j in range(len(regtype)): + instruct.write('read event ' + filename + '\n') + instruct.write('filter region ' + parent_folder + '/' + regtype[j] + '.reg' + '\n') #generalize this later!!! Maybe use a list + instruct.write('extract spectrum' + '\n') + instruct.write('save spectrum ' + parent_folder + '/' + regtype[j] + '/' + filename[:-4] + '_' + regtype[j] + '.pha' + '\n') + instruct.write('extract event' + '\n') + instruct.write('save event ' + parent_folder + '/' + regtype[j] + '/' + filename[:-4] + '_' + regtype[j] + '.evt' + '\n') + instruct.write('no' + '\n') + instruct.write('clear region' + '\n') + instruct.write('clear data' + '\n') + + instruct.write('\n') + + instruct.close() + +def time_order(eventlist,ordered_text): + """ + Return a list of event files in time order. The order of ObsIDs in the database + aren't necessarily organized in order of date. + + eventlist - list of event files + ordered_text - path to the text file that will list the time-ordered event files + """ + if type(eventlist) != np.array and type(eventlist) != list: + raise TypeError('eventlist should either be an array or a list!') + + start_times = [fits.open(eventlist[i])[1].header['TSTART'] for i in range(len(eventlist))] + + time_ordered = np.argsort(start_times) + ordered_eventlist = np.array(eventlist)[time_ordered] + + ordered_file = open(ordered_text,'w') + for i in range(len(ordered_eventlist)): + ordered_file.write(ordered_eventlist[i] + '\n') + ordered_file.close() + + return + +def interm_time_order(eventlist,initialfile,ordered_text): + """ + Return a list of event files in time order. The order of ObsIDs in the database + aren't necessarily organized in order of date. + + This is for the intermediate event files. + + eventlist - list of event files + initialfile - initialfile used for the merging; especially if it was generated from merging just the events + ordered_text - text file listing the paths and extension for the merging + """ + if type(eventlist) != np.array and type(eventlist) != list: + raise TypeError('eventlist should either be an array or a list!') + + start_times = [fits.open(eventlist[i])[1].header['TSTART'] for i in range(len(eventlist))] + + time_ordered = np.argsort(start_times) + ordered_eventlist = np.array(eventlist)[time_ordered] + + ordered_file = open(ordered_text,'w') + for i in range(len(ordered_eventlist)): + if i == 0: + ordered_file.write(initialfile + '[GTI]' + '\n') + else: + ordered_file.write(ordered_eventlist[i] + '[GTI]' + '\n') + ordered_file.close() + + return + +def merging(event_filelist,interm_file,interm_filelist,merged_file): + """ + Facilitating the merging of the total event file, with individual barycenter-corrected + event files! + + event_filelist - input text file containing paths to the barycenter-corrected event files + interm_file - intermediate event file + interm_filelist - input text file containing paths to the INTERMEDIATE event files. + Intermediate means events have been merged, but not the GTI rows + merged_file - path to the merged file! + """ + subprocess.run(['ftmerge','@'+event_filelist,interm_file]) + subprocess.run(['ftmerge','@'+interm_filelist,merged_file]) + + return + +def fparkey(fitsfile,keyword,value): + """ + Running FTOOLS' fparkey on some FITS file + + fitsfile - some FITS file + keyword - the key, e.g., ANCRFILE + value - what the input value is for the keyword + """ + subprocess.run(['fparkey',value,fitsfile,keyword]) + + return + +def images(imagelist,product,mode,output_folder): + """ + Combining images from a list of observations to produce either a) integrated image; + b) do a time-lapse of the observations of a field (controlled by mode) + + imagelist - list of image files (should be FITS files) + product - whether to create an "integrated" image or time-lapse "movie" + mode - whether to "show" or "save" the product + output_folder - output folder for products + """ + if type(imagelist) != np.array and type(imagelist) != list: + raise TypeError('imagelist should either be an array or a list!') + if product != 'integrated' and product != 'movie': + raise TypeError('product should either be "integrated" or "movie"! If there are new products, it should be updated.') + if mode != 'save' and mode != 'show': + raise TypeError('mode should either be "save" or "show"!') + + #ref_coord = SkyCoord('00h55m09.990s','-37d42m12.16s',frame='icrs') + ref_coord1 = SkyCoord('00h55m30.0s','-37d47m0.0s',frame='icrs') + ref_coord2 = SkyCoord('00h54m45.0s','-37d37m0.0s',frame='icrs') + + ngc300x1_coord = SkyCoord('00h55m9.6875s','-37d42m17.859s',frame='icrs') + ngc300ulx1_coord = SkyCoord('00h55m04.8989s','-37d41m45.579',frame='icrs') + ngc300bg_coord = SkyCoord('00h55m14.6298s','-37d39m57.287s',frame='icrs') + nicer_fov_coord = SkyCoord('00h55m04.8989s','-37d41m45.579',frame='icrs') #same as ULX-1, because NICER observations were on the ULX + + #ref_coord1 = SkyCoord('00h55m15.0s','-37d43m0.0s',frame='icrs') + #ref_coord2 = SkyCoord('00h55m00.0s','-37d41m0.0s',frame='icrs') + obj_name = fits.open(imagelist[0])[0].header['OBJECT'] + + if mode == 'save': + parent_folder = str(pathlib.Path(imagelist[0]).parent) + if product == 'integrated': + ref_image = fits.open(imagelist[0])[0] + base_image = np.zeros(np.shape(ref_image.data)) + base_exp = np.zeros(np.shape(ref_image.data)) + wcs = WCS(ref_image.header) + + ref_pixel1 = utils.skycoord_to_pixel(ref_coord1,wcs) + ref_pixel2 = utils.skycoord_to_pixel(ref_coord2,wcs) + + ngc300x1_pixel = utils.skycoord_to_pixel(ngc300x1_coord,wcs) + ngc300ulx1_pixel = utils.skycoord_to_pixel(ngc300ulx1_coord,wcs) + ngc300bg_pixel = utils.skycoord_to_pixel(ngc300bg_coord,wcs) + nicer_fov_pixel = utils.skycoord_to_pixel(nicer_fov_coord,wcs) + + for i in tqdm(range(len(imagelist))): + imagefile = fits.open(imagelist[i])[0] + expfile = fits.open(imagelist[i][:-6] + 'ex.img')[0] + array_im,footprint = reproject_interp(imagefile,ref_image.header) + array_ex,footprint = reproject_interp(expfile,ref_image.header) + + base_image += array_im + base_exp += array_ex + + plt.figure() + plt.subplot(projection=wcs) + ngc300x1_circle = plt.Circle((ngc300x1_pixel[0],ngc300x1_pixel[1]),radius=30/2.36,color='y',lw=0.5,fill=False,label='NGC300 X-1') + ngc300ulx1_circle = plt.Circle((ngc300ulx1_pixel[0],ngc300ulx1_pixel[1]),radius=35/2.36,color='b',lw=0.5,fill=False,label='NGC300 ULX-1') + ngc300bg_circle = plt.Circle((ngc300bg_pixel[0],ngc300bg_pixel[1]),radius=120/2.36,color='m',lw=0.5,fill=False,label='NGC300 bg') + nicer_fov_circle = plt.Circle((nicer_fov_pixel[0],nicer_fov_pixel[1]),radius=186/2.36,color='w',lw=0.5,fill=False,label='NICER FOV') + + plt.gcf().gca().add_artist(ngc300x1_circle) + plt.gcf().gca().add_artist(ngc300ulx1_circle) + plt.gcf().gca().add_artist(ngc300bg_circle) + plt.gcf().gca().add_artist(nicer_fov_circle) + + #log_image = ma.log10(base_image) + #plt.imshow(log_image.filled(0),vmin=0,vmax=np.log10(np.nanmax(base_image)),cmap='gist_heat') + #plt.imshow((base_image/base_exp)/np.nanmax(base_image/base_exp),vmin=0,vmax=1,cmap='gist_heat') + plt.imshow(gaussian_filter(base_image,1),vmin=0,vmax=10,cmap='gist_heat') + plt.xlabel('Right Ascension (hh:mm:ss)',fontsize=12) + plt.ylabel('Declination (deg)',fontsize=12) + plt.xlim([ref_pixel1[0],ref_pixel2[0]]) + plt.ylim([ref_pixel1[1],ref_pixel2[1]]) + plt.legend([ngc300x1_circle,ngc300ulx1_circle,ngc300bg_circle,nicer_fov_circle],["NGC300 X-1 (30 arcsec)",'NGC300 ULX-1 (35 arcsec)','NGC300 bg (120 arcsec)','nicer_fov_pixel (3.1 arcmin)']) + plt.colorbar().set_label('Counts') + + plt.show() + + if product == 'movie': + #### saving all the images into one PDF file + pdf_filename = output_folder + obj_name + '_field_movie.pdf' + with PdfPages(pdf_filename) as pdf: + for i in tqdm(range(len(imagelist))): + obsid = str(pathlib.Path(imagelist[i]).name)[:13] + + fitsfile = fits.open(imagelist[i])[0] + expfile = fits.open(imagelist[i][:-6] + 'ex.img')[0] + date_obs = fitsfile.header['DATE-OBS'] + + wcs = WCS(fitsfile.header) + ref_pixel1 = utils.skycoord_to_pixel(ref_coord1,wcs) + ref_pixel2 = utils.skycoord_to_pixel(ref_coord2,wcs) + + ngc300x1_pixel = utils.skycoord_to_pixel(ngc300x1_coord,wcs) + ngc300ulx1_pixel = utils.skycoord_to_pixel(ngc300ulx1_coord,wcs) + ngc300bg_pixel = utils.skycoord_to_pixel(ngc300bg_coord,wcs) + nicer_fov_pixel = utils.skycoord_to_pixel(nicer_fov_coord,wcs) + + plt.figure(figsize=(16,9)) + plt.subplot(projection=wcs) + norm = fitsfile.data/expfile.data + where_are_nans = np.isnan(norm) + norm[where_are_nans] = 0 + plt.imshow(gaussian_filter(norm/np.nanmax(norm),sigma=0.5),vmin=0,vmax=1,cmap='gist_heat') + ngc300x1_circle = plt.Circle((ngc300x1_pixel[0],ngc300x1_pixel[1]),radius=30/2.36,color='y',lw=0.5,fill=False,label='NGC300 X-1') + ngc300ulx1_circle = plt.Circle((ngc300ulx1_pixel[0],ngc300ulx1_pixel[1]),radius=35/2.36,color='b',lw=0.5,fill=False,label='NGC300 ULX-1') + ngc300bg_circle = plt.Circle((ngc300bg_pixel[0],ngc300bg_pixel[1]),radius=120/2.36,color='m',lw=0.5,fill=False,label='NGC300 bg') + nicer_fov_circle = plt.Circle((nicer_fov_pixel[0],nicer_fov_pixel[1]),radius=186/2.36,color='w',lw=0.5,fill=False,label='NICER FOV') + + plt.gcf().gca().add_artist(ngc300x1_circle) + plt.gcf().gca().add_artist(ngc300ulx1_circle) + plt.gcf().gca().add_artist(ngc300bg_circle) + plt.gcf().gca().add_artist(nicer_fov_circle) + + plt.title('Observation Date: ' + str(date_obs) + ', ObsID: ' + obsid) + plt.xlabel('Right Ascension (hh:mm:ss)',fontsize=12) + plt.ylabel('Declination (deg)',fontsize=12) + plt.xlim([ref_pixel1[0],ref_pixel2[0]]) + plt.ylim([ref_pixel1[1],ref_pixel2[1]]) + plt.legend([ngc300x1_circle,ngc300ulx1_circle,ngc300bg_circle,nicer_fov_circle],["NGC300 X-1 (30 arcsec)",'NGC300 ULX-1 (35 arcsec)','NGC300 bg (120 arcsec)','nicer_fov_pixel (3.1 arcmin)']) + plt.colorbar().set_label('Counts/s (relative to maximum)') + pdf.savefig() + plt.close() + + #### saving each image into an individual file + + for i in tqdm(range(len(imagelist))): + obsid = str(pathlib.Path(imagelist[i]).name)[:13] + + fitsfile = fits.open(imagelist[i])[0] + expfile = fits.open(imagelist[i][:-6] + 'ex.img')[0] + date_obs = fitsfile.header['DATE-OBS'] + + wcs = WCS(fitsfile.header) + ref_pixel1 = utils.skycoord_to_pixel(ref_coord1,wcs) + ref_pixel2 = utils.skycoord_to_pixel(ref_coord2,wcs) + + ngc300x1_pixel = utils.skycoord_to_pixel(ngc300x1_coord,wcs) + ngc300ulx1_pixel = utils.skycoord_to_pixel(ngc300ulx1_coord,wcs) + ngc300bg_pixel = utils.skycoord_to_pixel(ngc300bg_coord,wcs) + nicer_fov_pixel = utils.skycoord_to_pixel(nicer_fov_coord,wcs) + + plt.figure(figsize=(16,9)) + plt.subplot(projection=wcs) + #plt.imshow(fitsfile.data,vmin=0,vmax=np.max(fitsfile.data),cmap='gist_heat') + norm = fitsfile.data/expfile.data + where_are_nans = np.isnan(norm) + norm[where_are_nans] = 0 + plt.imshow(gaussian_filter(norm/np.nanmax(norm),sigma=0.5),vmin=0,vmax=1,cmap='gist_heat') + ngc300x1_circle = plt.Circle((ngc300x1_pixel[0],ngc300x1_pixel[1]),radius=30/2.36,color='y',lw=0.5,fill=False,label='NGC300 X-1') + ngc300ulx1_circle = plt.Circle((ngc300ulx1_pixel[0],ngc300ulx1_pixel[1]),radius=35/2.36,color='b',lw=0.5,fill=False,label='NGC300 ULX-1') + ngc300bg_circle = plt.Circle((ngc300bg_pixel[0],ngc300bg_pixel[1]),radius=120/2.36,color='m',lw=0.5,fill=False,label='NGC300 bg') + nicer_fov_circle = plt.Circle((nicer_fov_pixel[0],nicer_fov_pixel[1]),radius=186/2.36,color='w',lw=0.5,fill=False,label='NICER FOV') + + plt.gcf().gca().add_artist(ngc300x1_circle) + plt.gcf().gca().add_artist(ngc300ulx1_circle) + plt.gcf().gca().add_artist(ngc300bg_circle) + plt.gcf().gca().add_artist(nicer_fov_circle) + + plt.title('Observation Date: ' + str(date_obs) + ', ObsID: ' + obsid) + plt.xlabel('Right Ascension (hh:mm:ss)',fontsize=12) + plt.ylabel('Declination (deg)',fontsize=12) + plt.xlim([ref_pixel1[0],ref_pixel2[0]]) + plt.ylim([ref_pixel1[1],ref_pixel2[1]]) + plt.legend([ngc300x1_circle,ngc300ulx1_circle,ngc300bg_circle,nicer_fov_circle],["NGC300 X-1 (30 arcsec)",'NGC300 ULX-1 (35 arcsec)','NGC300 bg (120 arcsec)','nicer_fov_pixel (3.1 arcmin)']) + plt.colorbar().set_label('Counts') + plt.savefig(output_folder + obj_name + '_meanimage' + str(i).zfill(4) + '.png',format='png') + plt.close() + + + if mode == 'show': + for i in range(len(imagelist)): + fitsfile = fits.open(imagelist[i])[0] + wcs = WCS(fitsfile.header) + ref_pixel1 = utils.skycoord_to_pixel(ref_coord1,wcs) + ref_pixel2 = utils.skycoord_to_pixel(ref_coord2,wcs) + + plt.subplot(projection=wcs) + plt.imshow(fitsfile.data,vmin=0,vmax=np.max(fitsfile.data),cmap='gist_heat') + plt.xlabel('Right Ascension (hh:mm:ss)',fontsize=12) + plt.ylabel('Declination (deg)',fontsize=12) + plt.xlim([ref_pixel1[0],ref_pixel2[0]]) + plt.ylim([ref_pixel1[1],ref_pixel2[1]]) + plt.colorbar() + plt.show() + + +if __name__ == "__main__": + swift_xrt_event = '/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/' + filetype = 'ngc300_nicerfov' + + ancrfile = '/Volumes/Samsung_T5/swxpc0to12s6_20010101v013.arf' + respfile = '/Volumes/Samsung_T5/swxpc0to12s6_20130101v014.rmf' + + nicer_ancrfile = '/Volumes/Samsung_T5/nicer-consim135p-teamonly-array50.arf' + nicer_respfile = '/Volumes/Samsung_T5/nicer-rmf6s-teamonly-array50.rmf' + + ngc300_events = sorted(glob.glob(swift_xrt_event + '/sw*pc*po*cl*evt')) + instructfile = swift_xrt_event + 'instructions.txt' + + #for i in tqdm(range(len(ngc300_events))): + # inputfile = ngc300_events[i] + # outputfile = str(pathlib.Path(ngc300_events[i]).parent) + '/' + str(pathlib.Path(ngc300_events[i]).name)[:20] + '_bary_cl.evt' + # orbitfile = '/Volumes/Samsung_T5/NGC300_ULX_Swift/auxil/sw' + str(pathlib.Path(inputfile).name)[2:13] + 'sao.fits' + + # barycorr(inputfile,outputfile,'ICRS',orbitfile,swift_xrt_event) + + ngc300_events_bary = sorted(glob.glob(swift_xrt_event + 'sw*pc*po*bary*cl*evt')) + #filtering(ngc300_events_bary,['ngc300ulx1','ngc300x1','ngc300bg'],instructfile) + #filtering(ngc300_events_bary,['ngc300_nicerfov'],swift_xrt_event + 'nicerfov_instructions.txt') + + ngc300_type_events = sorted(glob.glob(swift_xrt_event + filetype + '/sw*pc*po*bary*cl*evt')) + #time_order(ngc300_type_events,swift_xrt_event + filetype + '/eventfiles.list') + #interm_time_order(ngc300_type_events,swift_xrt_event + filetype + '/' + filetype + '_intermediate.evt',swift_xrt_event + filetype + '/eventfiles_intermediate.list') + + #merging(swift_xrt_event + filetype + '/eventfiles.list',swift_xrt_event + filetype + '/' + filetype + '_intermediate.evt',swift_xrt_event + filetype + '/eventfiles_intermediate.list',swift_xrt_event + filetype + '/' + filetype + '_merge.evt') + + #merging('/Volumes/Samsung_T5/n300_ulx_2020/nicerdata_spectra/eventfiles.list','/Volumes/Samsung_T5/n300_ulx_2020/nicerdata_spectra/nicerdata_spectra_intermediate.evt','/Volumes/Samsung_T5/n300_ulx_2020/nicerdata_spectra/eventfiles_intermediate.list','/Volumes/Samsung_T5/n300_ulx_2020/nicerdata_spectra/nicerdata_spectra_merge.evt') + + #fparkey(swift_xrt_event + 'ngc300x1/ngc300x1_merge.pha','ANCRFILE',ancrfile) + #fparkey(swift_xrt_event + 'ngc300x1/ngc300x1_merge.pha','RESPFILE',respfile) + #fparkey(swift_xrt_event + 'ngc300bg/ngc300bg_merge.pha','ANCRFILE',ancrfile) + #fparkey(swift_xrt_event + 'ngc300bg/ngc300bg_merge.pha','RESPFILE',respfile) + #fparkey(swift_xrt_event + 'ngc300ulx1/ngc300ulx1_merge.pha','ANCRFILE',ancrfile) + #fparkey(swift_xrt_event + 'ngc300ulx1/ngc300ulx1_merge.pha','RESPFILE',respfile) + #fparkey(swift_xrt_event + 'ngc300x1/ngc300x1_merge.pha','BACKFILE','ngc300bg_merge.pha') + #fparkey(swift_xrt_event + 'ngc300ulx1/ngc300ulx1_merge.pha','BACKFILE','ngc300bg_merge.pha') + #fparkey(swift_xrt_event + 'ngc300_nicerfov/ngc300_nicerfov_merge.pha','ANCRFILE',ancrfile) + #fparkey(swift_xrt_event + 'ngc300_nicerfov/ngc300_nicerfov_merge.pha','RESPFILE',respfile) + + #fparkey('/Volumes/Samsung_T5/n300_ulx_2020/nicerdata_spectra/nicerdata_spectra_merge.pha','ANCRFILE','/Volumes/Samsung_T5/nicer-consim135p-teamonly-array50.arf') + #fparkey('/Volumes/Samsung_T5/n300_ulx_2020/nicerdata_spectra/nicerdata_spectra_merge.pha','RESPFILE','/Volumes/Samsung_T5//Volumes/Samsung_T5/nicer-rmf6s-teamonly-array50.rmf') + + #### First overlap + + ###merging(swift_xrt_event + 'ngc300x1/' + 'niceroverlap_all.list', swift_xrt_event + 'ngc300x1/ngc300x1_merge_niceroverlap_all_int.evt', swift_xrt_event + 'ngc300x1/' + 'niceroverlap_all_int.list', swift_xrt_event + 'ngc300x1/ngc300x1_merge_niceroverlap_all.evt') + ###merging(swift_xrt_event + 'ngc300x1/' + 'niceroverlap_spec1.list', swift_xrt_event + 'ngc300x1/ngc300x1_merge_niceroverlap_spec1_int.evt', swift_xrt_event + 'ngc300x1/' + 'niceroverlap_spec1_int.list', swift_xrt_event + 'ngc300x1/ngc300x1_merge_niceroverlap_spec1.evt' ) + ###merging(swift_xrt_event + 'ngc300x1/' + 'niceroverlap_spec2.list', swift_xrt_event + 'ngc300x1/ngc300x1_merge_niceroverlap_spec2_int.evt', swift_xrt_event + 'ngc300x1/' + 'niceroverlap_spec2_int.list', swift_xrt_event + 'ngc300x1/ngc300x1_merge_niceroverlap_spec2.evt' ) + + #merging(swift_xrt_event + 'ngc300bg/' + 'niceroverlap_all.list', swift_xrt_event + 'ngc300bg/ngc300bg_merge_niceroverlap_all_int.evt', swift_xrt_event + 'ngc300bg/' + 'niceroverlap_all_int.list', swift_xrt_event + 'ngc300bg/ngc300bg_merge_niceroverlap_all.evt') + #merging(swift_xrt_event + 'ngc300bg/' + 'niceroverlap_spec1.list', swift_xrt_event + 'ngc300bg/ngc300bg_merge_niceroverlap_spec1_int.evt', swift_xrt_event + 'ngc300bg/' + 'niceroverlap_spec1_int.list', swift_xrt_event + 'ngc300bg/ngc300bg_merge_niceroverlap_spec1.evt' ) + #merging(swift_xrt_event + 'ngc300bg/' + 'niceroverlap_spec2.list', swift_xrt_event + 'ngc300bg/ngc300bg_merge_niceroverlap_spec2_int.evt', swift_xrt_event + 'ngc300bg/' + 'niceroverlap_spec2_int.list', swift_xrt_event + 'ngc300bg/ngc300bg_merge_niceroverlap_spec2.evt' ) + + #merging(swift_xrt_event + 'ngc300ulx1/' + 'niceroverlap_all.list', swift_xrt_event + 'ngc300ulx1/ngc300ulx1_merge_niceroverlap_all_int.evt', swift_xrt_event + 'ngc300ulx1/' + 'niceroverlap_all_int.list', swift_xrt_event + 'ngc300ulx1/ngc300ulx1_merge_niceroverlap_all.evt') + #merging(swift_xrt_event + 'ngc300ulx1/' + 'niceroverlap_spec1.list', swift_xrt_event + 'ngc300ulx1/ngc300ulx1_merge_niceroverlap_spec1_int.evt', swift_xrt_event + 'ngc300ulx1/' + 'niceroverlap_spec1_int.list', swift_xrt_event + 'ngc300ulx1/ngc300ulx1_merge_niceroverlap_spec1.evt' ) + #merging(swift_xrt_event + 'ngc300ulx1/' + 'niceroverlap_spec2.list', swift_xrt_event + 'ngc300ulx1/ngc300ulx1_merge_niceroverlap_spec2_int.evt', swift_xrt_event + 'ngc300ulx1/' + 'niceroverlap_spec2_int.list', swift_xrt_event + 'ngc300ulx1/ngc300ulx1_merge_niceroverlap_spec2.evt' ) + + #merging(swift_xrt_event + 'ngc300_nicerfov/' + 'niceroverlap_all.list', swift_xrt_event + 'ngc300_nicerfov/ngc300_nicerfov_merge_niceroverlap_all_int.evt', swift_xrt_event + 'ngc300_nicerfov/' + 'niceroverlap_all_int.list', swift_xrt_event + 'ngc300_nicerfov/ngc300_nicerfov_merge_niceroverlap_all.evt') + #merging(swift_xrt_event + 'ngc300_nicerfov/' + 'niceroverlap_spec1.list', swift_xrt_event + 'ngc300_nicerfov/ngc300_nicerfov_merge_niceroverlap_spec1_int.evt', swift_xrt_event + 'ngc300_nicerfov/' + 'niceroverlap_spec1_int.list', swift_xrt_event + 'ngc300_nicerfov/ngc300_nicerfov_merge_niceroverlap_spec1.evt' ) + #merging(swift_xrt_event + 'ngc300_nicerfov/' + 'niceroverlap_spec2.list', swift_xrt_event + 'ngc300_nicerfov/ngc300_nicerfov_merge_niceroverlap_spec2_int.evt', swift_xrt_event + 'ngc300_nicerfov/' + 'niceroverlap_spec2_int.list', swift_xrt_event + 'ngc300_nicerfov/ngc300_nicerfov_merge_niceroverlap_spec2.evt' ) + + #merging(Lv0_dirs.NGC300_2020 + 'nicerdata_spectra/niceroverlap_all.list',Lv0_dirs.NGC300_2020 + 'nicerdata_spectra/nicerdata_spectra_overlap_all_intermediate.evt',Lv0_dirs.NGC300_2020 + 'nicerdata_spectra/niceroverlap_all_int.list',Lv0_dirs.NGC300_2020 + 'nicerdata_spectra/nicerdata_spectra_overlap_all.evt') + #merging(Lv0_dirs.NGC300_2020 + 'nicerdata_spectra/niceroverlap_spec1.list',Lv0_dirs.NGC300_2020 + 'nicerdata_spectra/nicerdata_spectra_overlap_spec1_intermediate.evt',Lv0_dirs.NGC300_2020 + 'nicerdata_spectra/niceroverlap_spec1_int.list',Lv0_dirs.NGC300_2020 + 'nicerdata_spectra/nicerdata_spectra_overlap_spec1.evt') + #merging(Lv0_dirs.NGC300_2020 + 'nicerdata_spectra/niceroverlap_spec2.list',Lv0_dirs.NGC300_2020 + 'nicerdata_spectra/nicerdata_spectra_overlap_spec2_intermediate.evt',Lv0_dirs.NGC300_2020 + 'nicerdata_spectra/niceroverlap_spec2_int.list',Lv0_dirs.NGC300_2020 + 'nicerdata_spectra/nicerdata_spectra_overlap_spec2.evt') + + #fparkey(swift_xrt_event + 'ngc300bg/ngc300bg_merge_niceroverlap_all.pha','ANCRFILE',ancrfile) + #fparkey(swift_xrt_event + 'ngc300bg/ngc300bg_merge_niceroverlap_spec1.pha','ANCRFILE',ancrfile) + #fparkey(swift_xrt_event + 'ngc300bg/ngc300bg_merge_niceroverlap_spec2.pha','ANCRFILE',ancrfile) + + #fparkey(swift_xrt_event + 'ngc300bg/ngc300bg_merge_niceroverlap_all.pha','RESPFILE',respfile) + #fparkey(swift_xrt_event + 'ngc300bg/ngc300bg_merge_niceroverlap_spec1.pha','RESPFILE',respfile) + #fparkey(swift_xrt_event + 'ngc300bg/ngc300bg_merge_niceroverlap_spec2.pha','RESPFILE',respfile) + + #fparkey(swift_xrt_event + 'ngc300ulx1/ngc300ulx1_merge_niceroverlap_all.pha','ANCRFILE',ancrfile) + #fparkey(swift_xrt_event + 'ngc300ulx1/ngc300ulx1_merge_niceroverlap_spec1.pha','ANCRFILE',ancrfile) + #fparkey(swift_xrt_event + 'ngc300ulx1/ngc300ulx1_merge_niceroverlap_spec2.pha','ANCRFILE',ancrfile) + + #fparkey(swift_xrt_event + 'ngc300ulx1/ngc300ulx1_merge_niceroverlap_all.pha','RESPFILE',respfile) + #fparkey(swift_xrt_event + 'ngc300ulx1/ngc300ulx1_merge_niceroverlap_spec1.pha','RESPFILE',respfile) + #fparkey(swift_xrt_event + 'ngc300ulx1/ngc300ulx1_merge_niceroverlap_spec2.pha','RESPFILE',respfile) + + #fparkey(swift_xrt_event + 'ngc300_nicerfov/ngc300_nicerfov_merge_niceroverlap_all.pha','RESPFILE',respfile) + #fparkey(swift_xrt_event + 'ngc300_nicerfov/ngc300_nicerfov_merge_niceroverlap_spec1.pha','RESPFILE',respfile) + #fparkey(swift_xrt_event + 'ngc300_nicerfov/ngc300_nicerfov_merge_niceroverlap_spec2.pha','RESPFILE',respfile) + + #fparkey(swift_xrt_event + 'ngc300_nicerfov/ngc300_nicerfov_merge_niceroverlap_all.pha','ANCRFILE',ancrfile) + #fparkey(swift_xrt_event + 'ngc300_nicerfov/ngc300_nicerfov_merge_niceroverlap_spec1.pha','ANCRFILE',ancrfile) + #fparkey(swift_xrt_event + 'ngc300_nicerfov/ngc300_nicerfov_merge_niceroverlap_spec2.pha','ANCRFILE',ancrfile) + + #fparkey(Lv0_dirs.NGC300_2020 + 'nicerdata_spectra/nicerdata_spectra_overlap_all.pha','ANCRFILE',nicer_ancrfile) + #fparkey(Lv0_dirs.NGC300_2020 + 'nicerdata_spectra/nicerdata_spectra_overlap_all.pha','RESPFILE',nicer_respfile) + #fparkey(Lv0_dirs.NGC300_2020 + 'nicerdata_spectra/nicerdata_spectra_overlap_spec1.pha','ANCRFILE',nicer_ancrfile) + #fparkey(Lv0_dirs.NGC300_2020 + 'nicerdata_spectra/nicerdata_spectra_overlap_spec1.pha','RESPFILE',nicer_respfile) + #fparkey(Lv0_dirs.NGC300_2020 + 'nicerdata_spectra/nicerdata_spectra_overlap_spec2.pha','ANCRFILE',nicer_ancrfile) + #fparkey(Lv0_dirs.NGC300_2020 + 'nicerdata_spectra/nicerdata_spectra_overlap_spec2.pha','RESPFILE',nicer_respfile) + + #fparkey(swift_xrt_event + 'ngc300x1/ngc300x1_merge_niceroverlap_all.pha','BACKFILE','ngc300bg_merge_niceroverlap_all.pha') + #fparkey(swift_xrt_event + 'ngc300x1/ngc300x1_merge_niceroverlap_spec1.pha','BACKFILE','ngc300bg_merge_niceroverlap_spec1.pha') + #fparkey(swift_xrt_event + 'ngc300x1/ngc300x1_merge_niceroverlap_spec2.pha','BACKFILE','ngc300bg_merge_niceroverlap_spec2.pha') + + #fparkey(swift_xrt_event + 'ngc300ulx1/ngc300ulx1_merge_niceroverlap_all.pha','BACKFILE','ngc300bg_merge_niceroverlap_all.pha') + #fparkey(swift_xrt_event + 'ngc300ulx1/ngc300ulx1_merge_niceroverlap_spec1.pha','BACKFILE','ngc300bg_merge_niceroverlap_spec1.pha') + #fparkey(swift_xrt_event + 'ngc300ulx1/ngc300ulx1_merge_niceroverlap_spec2.pha','BACKFILE','ngc300bg_merge_niceroverlap_spec2.pha') + + #### Second overlap + #merging(swift_xrt_event + 'ngc300x1/' + 'niceroverlap2_spec1.list', swift_xrt_event + 'ngc300x1/ngc300x1_merge_niceroverlap2_spec1_int.evt', swift_xrt_event + 'ngc300x1/' + 'niceroverlap2_spec1_int.list', swift_xrt_event + 'ngc300x1/ngc300x1_merge_niceroverlap2_spec1.evt' ) + #merging(swift_xrt_event + 'ngc300x1/' + 'niceroverlap2_spec2.list', swift_xrt_event + 'ngc300x1/ngc300x1_merge_niceroverlap2_spec2_int.evt', swift_xrt_event + 'ngc300x1/' + 'niceroverlap2_spec2_int.list', swift_xrt_event + 'ngc300x1/ngc300x1_merge_niceroverlap2_spec2.evt' ) + + #merging(swift_xrt_event + 'ngc300bg/' + 'niceroverlap2_spec1.list', swift_xrt_event + 'ngc300bg/ngc300bg_merge_niceroverlap2_spec1_int.evt', swift_xrt_event + 'ngc300bg/' + 'niceroverlap2_spec1_int.list', swift_xrt_event + 'ngc300bg/ngc300bg_merge_niceroverlap2_spec1.evt' ) + #merging(swift_xrt_event + 'ngc300bg/' + 'niceroverlap2_spec2.list', swift_xrt_event + 'ngc300bg/ngc300bg_merge_niceroverlap2_spec2_int.evt', swift_xrt_event + 'ngc300bg/' + 'niceroverlap2_spec2_int.list', swift_xrt_event + 'ngc300bg/ngc300bg_merge_niceroverlap2_spec2.evt' ) + + #merging(swift_xrt_event + 'ngc300ulx1/' + 'niceroverlap2_spec1.list', swift_xrt_event + 'ngc300ulx1/ngc300ulx1_merge_niceroverlap2_spec1_int.evt', swift_xrt_event + 'ngc300ulx1/' + 'niceroverlap2_spec1_int.list', swift_xrt_event + 'ngc300ulx1/ngc300ulx1_merge_niceroverlap2_spec1.evt' ) + #merging(swift_xrt_event + 'ngc300ulx1/' + 'niceroverlap2_spec2.list', swift_xrt_event + 'ngc300ulx1/ngc300ulx1_merge_niceroverlap2_spec2_int.evt', swift_xrt_event + 'ngc300ulx1/' + 'niceroverlap2_spec2_int.list', swift_xrt_event + 'ngc300ulx1/ngc300ulx1_merge_niceroverlap2_spec2.evt' ) + + #merging(swift_xrt_event + 'ngc300_nicerfov/' + 'niceroverlap2_spec1.list', swift_xrt_event + 'ngc300_nicerfov/ngc300_nicerfov_merge_niceroverlap2_spec1_int.evt', swift_xrt_event + 'ngc300_nicerfov/' + 'niceroverlap2_spec1_int.list', swift_xrt_event + 'ngc300_nicerfov/ngc300_nicerfov_merge_niceroverlap2_spec1.evt' ) + #merging(swift_xrt_event + 'ngc300_nicerfov/' + 'niceroverlap2_spec2.list', swift_xrt_event + 'ngc300_nicerfov/ngc300_nicerfov_merge_niceroverlap2_spec2_int.evt', swift_xrt_event + 'ngc300_nicerfov/' + 'niceroverlap2_spec2_int.list', swift_xrt_event + 'ngc300_nicerfov/ngc300_nicerfov_merge_niceroverlap2_spec2.evt' ) + + #merging(Lv0_dirs.NGC300_2020 + 'nicerdata_spectra/niceroverlap2_spec1.list',Lv0_dirs.NGC300_2020 + 'nicerdata_spectra/nicerdata_spectra_overlap2_spec1_intermediate.evt',Lv0_dirs.NGC300_2020 + 'nicerdata_spectra/niceroverlap2_spec1_int.list',Lv0_dirs.NGC300_2020 + 'nicerdata_spectra/nicerdata_spectra_overlap2_spec1.evt') + #merging(Lv0_dirs.NGC300_2020 + 'nicerdata_spectra/niceroverlap2_spec2.list',Lv0_dirs.NGC300_2020 + 'nicerdata_spectra/nicerdata_spectra_overlap2_spec2_intermediate.evt',Lv0_dirs.NGC300_2020 + 'nicerdata_spectra/niceroverlap2_spec2_int.list',Lv0_dirs.NGC300_2020 + 'nicerdata_spectra/nicerdata_spectra_overlap2_spec2.evt') + + """ + fparkey(swift_xrt_event + 'ngc300x1/ngc300x1_merge_niceroverlap2_spec1.pha','ANCRFILE',ancrfile) + fparkey(swift_xrt_event + 'ngc300x1/ngc300x1_merge_niceroverlap2_spec2.pha','ANCRFILE',ancrfile) + + fparkey(swift_xrt_event + 'ngc300x1/ngc300x1_merge_niceroverlap2_spec1.pha','RESPFILE',respfile) + fparkey(swift_xrt_event + 'ngc300x1/ngc300x1_merge_niceroverlap2_spec2.pha','RESPFILE',respfile) + + fparkey(swift_xrt_event + 'ngc300bg/ngc300bg_merge_niceroverlap2_spec1.pha','ANCRFILE',ancrfile) + fparkey(swift_xrt_event + 'ngc300bg/ngc300bg_merge_niceroverlap2_spec2.pha','ANCRFILE',ancrfile) + + fparkey(swift_xrt_event + 'ngc300bg/ngc300bg_merge_niceroverlap2_spec1.pha','RESPFILE',respfile) + fparkey(swift_xrt_event + 'ngc300bg/ngc300bg_merge_niceroverlap2_spec2.pha','RESPFILE',respfile) + + fparkey(swift_xrt_event + 'ngc300ulx1/ngc300ulx1_merge_niceroverlap2_spec1.pha','ANCRFILE',ancrfile) + fparkey(swift_xrt_event + 'ngc300ulx1/ngc300ulx1_merge_niceroverlap2_spec2.pha','ANCRFILE',ancrfile) + + fparkey(swift_xrt_event + 'ngc300ulx1/ngc300ulx1_merge_niceroverlap2_spec1.pha','RESPFILE',respfile) + fparkey(swift_xrt_event + 'ngc300ulx1/ngc300ulx1_merge_niceroverlap2_spec2.pha','RESPFILE',respfile) + + fparkey(swift_xrt_event + 'ngc300_nicerfov/ngc300_nicerfov_merge_niceroverlap2_spec1.pha','RESPFILE',respfile) + fparkey(swift_xrt_event + 'ngc300_nicerfov/ngc300_nicerfov_merge_niceroverlap2_spec2.pha','RESPFILE',respfile) + + fparkey(swift_xrt_event + 'ngc300_nicerfov/ngc300_nicerfov_merge_niceroverlap2_spec1.pha','ANCRFILE',ancrfile) + fparkey(swift_xrt_event + 'ngc300_nicerfov/ngc300_nicerfov_merge_niceroverlap2_spec2.pha','ANCRFILE',ancrfile) + """ + + #fparkey(Lv0_dirs.NGC300_2020 + 'nicerdata_spectra/nicerdata_spectra_overlap2_spec1.pha','ANCRFILE',nicer_ancrfile) + #fparkey(Lv0_dirs.NGC300_2020 + 'nicerdata_spectra/nicerdata_spectra_overlap2_spec1.pha','RESPFILE',nicer_respfile) + #fparkey(Lv0_dirs.NGC300_2020 + 'nicerdata_spectra/nicerdata_spectra_overlap2_spec2.pha','ANCRFILE',nicer_ancrfile) + #fparkey(Lv0_dirs.NGC300_2020 + 'nicerdata_spectra/nicerdata_spectra_overlap2_spec2.pha','RESPFILE',nicer_respfile) + + """ + fparkey(swift_xrt_event + 'ngc300x1/ngc300x1_merge_niceroverlap2_spec1.pha','BACKFILE','ngc300bg_merge_niceroverlap2_spec1.pha') + fparkey(swift_xrt_event + 'ngc300x1/ngc300x1_merge_niceroverlap2_spec2.pha','BACKFILE','ngc300bg_merge_niceroverlap2_spec2.pha') + + fparkey(swift_xrt_event + 'ngc300ulx1/ngc300ulx1_merge_niceroverlap2_spec1.pha','BACKFILE','ngc300bg_merge_niceroverlap2_spec1.pha') + fparkey(swift_xrt_event + 'ngc300ulx1/ngc300ulx1_merge_niceroverlap2_spec2.pha','BACKFILE','ngc300bg_merge_niceroverlap2_spec2.pha') + """ + + """ + image_files = glob.glob('/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/products/sw*xpc*_sk.img') + image_ordered_text = '/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/products/image_ordered.list' + #time_order(image_files,image_ordered_text) + + time_ordered_images = open(image_ordered_text).read().split('\n')[:-1] + images(time_ordered_images,'integrated','save','/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/images/') + """ diff --git a/Lv2_TBOs_method.py b/Lv2_TBOs_method.py index 9863a66..05985a5 100644 --- a/Lv2_TBOs_method.py +++ b/Lv2_TBOs_method.py @@ -108,10 +108,13 @@ def dynamic_ps(eventfile,search_window,T,dt,tbin_size,df,f_central,mode): times = fits.open(eventfile)[1].data['TIME'] T_zeroized = times-times[0] counts = np.ones(len(T_zeroized)) - - T_bins = np.linspace(0,np.ceil(T_zeroized[-1]),np.ceil(T_zeroized[-1])*1/tbin_size+1) - binned_counts, bin_edges, binnumber = stats.binned_statistic(T_zeroized,counts,statistic='sum',bins=T_bins) #binning the photons - + T_zeroized_trunc = T_zeroized[(T_zeroized>=search_window[0])&(T_zeroized<=search_window[1])] + counts_trunc = np.ones(len(T_zeroized_trunc)) + #print(len(T_zeroized),len(T_zeroized_trunc),len(counts_trunc)) + T_bins = np.linspace(T_zeroized_trunc[0],np.ceil(T_zeroized_trunc[-1]),np.ceil((T_zeroized_trunc[-1]-T_zeroized_trunc[0])*1/tbin_size+1)) + #print(len(T_bins),T_bins[:20],T_bins[-20:]) + binned_counts, bin_edges, binnumber = stats.binned_statistic(T_zeroized_trunc,counts_trunc,statistic='sum',bins=T_bins) #binning the photons + #print(len(binned_counts)) for i in tqdm(range(len(T))): #for every window size: output_file = open(parent_folder + '/' + obsid + '_TBO_search_' + str(T[i]) + 's.txt','w') output_file.write('Source name: ' + source_name + ' ; ObsID: ' + obsid + '\n') @@ -150,7 +153,9 @@ def dynamic_ps(eventfile,search_window,T,dt,tbin_size,df,f_central,mode): output_file.write(str(f_window[k]) + ' ' + str(ps_window[k]) + ' ' + str(Lv3_detection_level.signal_significance(N,1,1,ps_window[k])) + '\n') output_file.close() - + ps_max = np.array(ps_max) + f_max = np.array(f_max) + print('The maximum power in the whole plot is ' + str(round(np.max(ps_max),2)) + ' with corresponding frequency ' + str(f_max[ps_max==np.max(ps_max)][0]) + ' Hz') if mode == "show": mplcursors.cursor(hover=True) ax1.set_title('Window size: ' + str(T[i]) + 's, dt='+str(dt[i])+'s \n' + 'Central freq. = '+str(f_central) + 'Hz, df = ' + str(df) + 'Hz \n Power required for 3 sigma: ' + str(sig3),fontsize=12) diff --git a/Lv2_average_ps_methods.py b/Lv2_average_ps_methods.py index ba97812..c05df14 100644 --- a/Lv2_average_ps_methods.py +++ b/Lv2_average_ps_methods.py @@ -13,8 +13,8 @@ from tqdm import tqdm import matplotlib.pyplot as plt from astropy.io import fits -from presto import binary_psr -import Lv3_detection_level +#from presto import binary_psr +import Lv2_presto_subroutines,Lv3_detection_level import pathlib import subprocess import os @@ -89,6 +89,8 @@ def do_nicerfits2presto(eventfile,tbin,segment_length): eventfiles = sorted(glob.glob(parent_folder + '/accelsearch_' + str(segment_length) + 's/*.evt')) #get absolute paths of all demodulated event FITS files print('Now converting NICER event FITS files into the PRESTO-readable binary format!') for i in tqdm(range(len(eventfiles))): + if os.path.exists(eventfiles[i][:-3] + 'dat'): + continue try: subprocess.run(['nicerfits2presto.py','--dt='+str(tbin),eventfiles[i]]) except (ValueError,subprocess.CalledProcessError): @@ -189,15 +191,16 @@ def realfft(eventfile,segment_length): print('Doing realfft now!') with open(logfile,'w') as logtextfile: for i in tqdm(range(len(dat_files))): - output = subprocess.run(['realfft',dat_files[i]],capture_output=True,text=True) - logtextfile.write(output.stdout) - logtextfile.write('*------------------------------* \n') - logtextfile.write(output.stderr) + if os.path.exists(dat_files[i][:-3] + 'fft')==False: + output = subprocess.run(['realfft',dat_files[i]],capture_output=True,text=True) + logtextfile.write(output.stdout) + logtextfile.write('*------------------------------* \n') + logtextfile.write(output.stderr) logtextfile.close() return -def presto_dat(eventfile,segment_length,demod,PI1,PI2): +def presto_dat(eventfile,segment_length,demod,PI1,PI2,t1,t2): """ Obtain the dat files that were generated from PRESTO @@ -206,6 +209,9 @@ def presto_dat(eventfile,segment_length,demod,PI1,PI2): demod - whether we're dealing with demodulated data or not! PI1 - lower bound of PI (not energy in keV!) desired for the energy range PI2 - upper bound of PI (not energy in keV!) desired for the energy range + t1 - starting time for calculation of averaged power spectra + t2 - ending time for calculation of averaged power spectra + (note that t=0 corresponds to the MET of the FIRST event in the eventfile, so will need to inspect light curve with Lv2_lc.py to get times) """ if demod != True and demod != False: raise ValueError("demod should either be True or False!") @@ -213,8 +219,8 @@ def presto_dat(eventfile,segment_length,demod,PI1,PI2): parent_folder = str(pathlib.Path(eventfile).parent) if PI1 != '': #if we're doing energy cuts instead - dat_files = sorted(glob.glob(parent_folder + '/accelsearch_' + str(segment_length) + 's/*E' + str(PI1) + '-' + str(PI2) + '*.dat')) - demod_files = sorted(glob.glob(parent_folder + '/accelsearch_' + str(segment_length) + 's/*E' + str(PI1) + '-' + str(PI2) + '*demod.dat')) + dat_files = sorted(glob.glob(parent_folder + '/accelsearch_' + str(segment_length) + 's/*E' + str(PI1).zfill(4) + '-' + str(PI2).zfill(4) + '*.dat')) + demod_files = sorted(glob.glob(parent_folder + '/accelsearch_' + str(segment_length) + 's/*E' + str(PI1).zfill(4) + '-' + str(PI2).zfill(4) + '*demod.dat')) else: dat_files = [] demod_files = [] @@ -227,12 +233,24 @@ def presto_dat(eventfile,segment_length,demod,PI1,PI2): if 'E' not in str(pathlib.Path(all_demod_files[i]).name): demod_files.append(all_demod_files[i]) - if demod == True: - return np.array(demod_files) + if t1 != 0 or t2 != 0: #if both starting and ending times are not zero; otherwise default is to use ALL the data in the eventfile + gti_start = int(t1/segment_length) + gti_end = np.ceil(t2/segment_length) + filt_dat_files = np.array([dat_files[i] for i in range(len(dat_files)) if (int(dat_files[i][dat_files[i].index('GTI')+3:dat_files[i].index('GTI')+9]) >= gti_start) and (int(dat_files[i][dat_files[i].index('GTI')+3:dat_files[i].index('GTI')+9]) <= gti_end)]) + filt_demod_files = np.array([demod_files[i] for i in range(len(demod_files)) if (int(demod_files[i][demod_files[i].index('GTI')+3:demod_files[i].index('GTI')+9]) >= gti_start) and (int(demod_files[i][demod_files[i].index('GTI')+3:demod_files[i].index('GTI')+9]) <= gti_end)]) + + if demod == True: + return np.array(filt_demod_files) + else: + return np.array([datfile for datfile in filt_dat_files if datfile not in set(filt_demod_files)]) + else: - return np.array([datfile for datfile in dat_files if datfile not in set(demod_files)]) + if demod == True: + return np.array(demod_files) + else: + return np.array([datfile for datfile in dat_files if datfile not in set(demod_files)]) -def presto_fft(eventfile,segment_length,demod,PI1,PI2): +def presto_fft(eventfile,segment_length,demod,PI1,PI2,t1,t2): """ Obtain the FFT files that were generated from PRESTO @@ -241,6 +259,9 @@ def presto_fft(eventfile,segment_length,demod,PI1,PI2): demod - whether we're dealing with demodulated data or not! PI1 - lower bound of PI (not energy in keV!) desired for the energy range PI2 - upper bound of PI (not energy in keV!) desired for the energy range + t1 - starting time for calculation of averaged power spectra + t2 - ending time for calculation of averaged power spectra + (note that t=0 corresponds to the MET of the FIRST event in the eventfile, so will need to inspect light curve with Lv2_lc.py to get times) """ if demod != True and demod != False: raise ValueError("demod should either be True or False!") @@ -248,8 +269,9 @@ def presto_fft(eventfile,segment_length,demod,PI1,PI2): parent_folder = str(pathlib.Path(eventfile).parent) if PI1 != '': #if we're doing energy cuts instead - fft_files = sorted(glob.glob(parent_folder + '/accelsearch_' + str(segment_length) + 's/*E' + str(PI1) + '-' + str(PI2) + '*.fft')) - demod_files = sorted(glob.glob(parent_folder + '/accelsearch_' + str(segment_length) + 's/*E' + str(PI1) + '-' + str(PI2) + '*demod.fft')) + fft_files = sorted(glob.glob(parent_folder + '/accelsearch_' + str(segment_length) + 's/*E' + str(PI1).zfill(4) + '-' + str(PI2).zfill(4) + '*.fft')) + demod_files = sorted(glob.glob(parent_folder + '/accelsearch_' + str(segment_length) + 's/*E' + str(PI1).zfill(4) + '-' + str(PI2).zfill(4) + '*demod.fft')) + else: fft_files = [] demod_files = [] @@ -262,12 +284,24 @@ def presto_fft(eventfile,segment_length,demod,PI1,PI2): if 'E' not in str(pathlib.Path(all_demod_files[i]).name): demod_files.append(all_demod_files[i]) - if demod == True: - return np.array(demod_files) + if t1 != 0 or t2 != 0: #if both starting and ending times are not zero; otherwise default is to use ALL the data in the eventfile + gti_start = int(t1/segment_length) + gti_end = np.ceil(t2/segment_length) + filt_fft_files = np.array([fft_files[i] for i in range(len(fft_files)) if (int(fft_files[i][fft_files[i].index('GTI')+3:fft_files[i].index('GTI')+9]) >= gti_start) and (int(fft_files[i][fft_files[i].index('GTI')+3:fft_files[i].index('GTI')+9]) <= gti_end)]) + filt_demod_files = np.array([demod_files[i] for i in range(len(demod_files)) if (int(demod_files[i][demod_files[i].index('GTI')+3:demod_files[i].index('GTI')+9]) >= gti_start) and (int(demod_files[i][demod_files[i].index('GTI')+3:demod_files[i].index('GTI')+9]) <= gti_end)]) + + if demod == True: + return np.array(filt_demod_files) + else: + return np.array([fftfile for fftfile in filt_fft_files if fftfile not in set(filt_demod_files)]) + else: - return np.array([fftfile for fftfile in fft_files if fftfile not in set(demod_files)]) + if demod == True: + return np.array(demod_files) + else: + return np.array([fftfile for fftfile in fft_files if fftfile not in set(demod_files)]) -def segment_threshold(eventfile,segment_length,demod,tbin_size,threshold,PI1,PI2): +def segment_threshold(eventfile,segment_length,demod,tbin_size,threshold,PI1,PI2,t1,t2): """ Using the .dat files, rebin them into 1s bins, to weed out the segments below some desired threshold. Will return a *list* of *indices*! This is so that I @@ -280,13 +314,15 @@ def segment_threshold(eventfile,segment_length,demod,tbin_size,threshold,PI1,PI2 threshold - if data is under threshold (in percentage), then don't use the segment! PI1 - lower bound of PI (not energy in keV!) desired for the energy range PI2 - upper bound of PI (not energy in keV!) desired for the energy range + t1 - starting time for calculation of averaged power spectra + t2 - ending time for calculation of averaged power spectra + (note that t=0 corresponds to the MET of the FIRST event in the eventfile, so will need to inspect light curve with Lv2_lc.py to get times) """ if demod != True and demod != False: raise ValueError("demod should either be True or False!") - dat_files = presto_dat(eventfile,segment_length,demod,PI1,PI2) + dat_files = presto_dat(eventfile,segment_length,demod,PI1,PI2,t1,t2) rebin_t = np.arange(segment_length+1)*1 #1-second bins - passed_threshold = [] print('Now finding the number of segments that can be used...') for i in tqdm(range(len(dat_files))): @@ -300,9 +336,9 @@ def segment_threshold(eventfile,segment_length,demod,tbin_size,threshold,PI1,PI2 print('Will use ' + str(len(passed_threshold)) + ' out of ' + str(len(dat_files)) + ' segments.') - return passed_threshold, len(passed_threshold) + return np.array(passed_threshold), len(passed_threshold) -def average_ps(eventfile,segment_length,demod,tbin_size,threshold,PI1,PI2,starting_freq,W): +def average_ps(eventfile,segment_length,demod,tbin_size,threshold,PI1,PI2,t1,t2,starting_freq,W): """ Given the full list of .dat and .fft files, and the indices where the PRESTO-binned data is beyond some threshold, return the averaged power spectrum! @@ -314,17 +350,38 @@ def average_ps(eventfile,segment_length,demod,tbin_size,threshold,PI1,PI2,starti threshold - if data is under threshold (in percentage), then don't use the segment! PI1 - lower bound of PI (not energy in keV!) desired for the energy range PI2 - upper bound of PI (not energy in keV!) desired for the energy range + t1 - starting time for calculation of averaged power spectra + t2 - ending time for calculation of averaged power spectra + (note that t=0 corresponds to the MET of the FIRST event in the eventfile, so will need to inspect light curve with Lv2_lc.py to get times) starting_freq - frequency to start constructing the histogram of powers from W - number of consecutive frequency bins to AVERAGE over """ if demod != True and demod != False: raise ValueError("demod should either be True or False!") - dat_files = presto_dat(eventfile,segment_length,demod,PI1,PI2) #sorted array of .dat files - fft_files = presto_fft(eventfile,segment_length,demod,PI1,PI2) #sorted array of .fft files - passed_threshold,M = segment_threshold(eventfile,segment_length,demod,tbin_size,threshold,PI1,PI2) + dat_files = presto_dat(eventfile,segment_length,demod,PI1,PI2,t1,t2) #sorted array of .dat files + fft_files = presto_fft(eventfile,segment_length,demod,PI1,PI2,t1,t2) #sorted array of .fft files + passed_threshold,M = segment_threshold(eventfile,segment_length,demod,tbin_size,threshold,PI1,PI2,t1,t2) #list of indices where the rebinned .dat files are beyond the threshold + if len(passed_threshold) == 0: + freqs = np.fft.fftfreq(int(segment_length/tbin_size),tbin_size) + N = len(freqs) + + f = freqs[1:int(N/2)] + average_ps = np.ones(int(segment_length/(2*tbin_size)))*2 + ps = average_ps[1:] + + ps_to_use = ps[f>starting_freq] + ps_bins = np.linspace(min(ps_to_use),max(ps_to_use),1000) + N_greaterthanP = [] + print('Creating the noise histogram [N(>P)]...') + for i in tqdm(range(len(ps_bins))): + array_greaterthan = ps_to_use[ps_to_use>ps_bins[i]] + N_greaterthanP.append(len(array_greaterthan)) + + return f,ps,ps_bins,N_greaterthanP,M + dat_threshold = dat_files[passed_threshold] #.dat files that passed the threshold fft_threshold = fft_files[passed_threshold] #corresponding .fft files that passed the threshold @@ -377,7 +434,7 @@ def average_ps(eventfile,segment_length,demod,tbin_size,threshold,PI1,PI2,starti return f,ps,ps_bins,N_greaterthanP,M -def noise_hist(eventfile,segment_length,demod,tbin_size,threshold,PI1,PI2,starting_freq,W): +def noise_hist(eventfile,segment_length,demod,tbin_size,threshold,PI1,PI2,t1,t2,starting_freq,W): """ Given the average spectrum for an ObsID, return the histogram of powers, such that you have N(>P). This is for powers corresponding to frequencies larger @@ -390,13 +447,16 @@ def noise_hist(eventfile,segment_length,demod,tbin_size,threshold,PI1,PI2,starti threshold - if data is under threshold (in percentage), then don't use the segment! PI1 - lower bound of PI (not energy in keV!) desired for the energy range PI2 - upper bound of PI (not energy in keV!) desired for the energy range + t1 - starting time for calculation of averaged power spectra + t2 - ending time for calculation of averaged power spectra + (note that t=0 corresponds to the MET of the FIRST event in the eventfile, so will need to inspect light curve with Lv2_lc.py to get times) starting_freq - frequency to start constructing the histogram of powers from W - number of consecutive frequency bins to AVERAGE over """ if demod != True and demod != False: raise ValueError("demod should either be True or False!") - f,ps = average_ps(eventfile,segment_length,demod,tbin_size,threshold,PI1,PI2,starting_freq,W) + f,ps = average_ps(eventfile,segment_length,demod,tbin_size,threshold,PI1,PI2,t1,t2,starting_freq,W) ps_to_use = ps[f>starting_freq] ps_bins = np.linspace(min(ps_to_use),max(ps_to_use),1000) @@ -408,7 +468,7 @@ def noise_hist(eventfile,segment_length,demod,tbin_size,threshold,PI1,PI2,starti return ps_bins, N_greaterthanP -def plotting(eventfile,segment_length,demod,tbin,threshold,PI1,PI2,starting_freq,W,N,xlims,plot_mode): +def plotting(eventfile,segment_length,demod,tbin,threshold,PI1,PI2,t1,t2,starting_freq,W,hist_min_sig,N,xlims,plot_mode): """ Plotting the averaged power spectrum and the noise histogram @@ -419,8 +479,12 @@ def plotting(eventfile,segment_length,demod,tbin,threshold,PI1,PI2,starting_freq threshold - if data is under threshold (in percentage), then don't use the segment! PI1 - lower bound of PI (not energy in keV!) desired for the energy range PI2 - upper bound of PI (not energy in keV!) desired for the energy range + t1 - starting time for calculation of averaged power spectra + t2 - ending time for calculation of averaged power spectra + (note that t=0 corresponds to the MET of the FIRST event in the eventfile, so will need to inspect light curve with Lv2_lc.py to get times) starting_freq - frequency to start constructing the histogram of powers from W - number of consecutive frequency bins to AVERAGE over + hist_min_sig - minimum significance for a candidate frequency to be added to a text file; will be used to calculate histograms of candidates N - number of trials xlims - limits to apply on the x axis if desired plot_mode - whether to "show" the plots or to "save" them @@ -432,32 +496,50 @@ def plotting(eventfile,segment_length,demod,tbin,threshold,PI1,PI2,starting_freq parent_folder = str(pathlib.Path(eventfile).parent) - f,ps,ps_bins,N_greaterthanP,M = average_ps(eventfile,segment_length,demod,tbin,threshold,PI1,PI2,starting_freq,W) + f,ps,ps_bins,N_greaterthanP,M = average_ps(eventfile,segment_length,demod,tbin,threshold,PI1,PI2,t1,t2,starting_freq,W) power_required_3 = Lv3_detection_level.power_for_sigma(3,N,M,W) #power required for significance power_required_4 = Lv3_detection_level.power_for_sigma(4,N,M,W) #power required for significance - plt.figure(1) - plt.plot(f,ps,'rx-') + ### to create the histogram of pulsation candidates + ps_sig = Lv3_detection_level.signal_significance(N,M,W,ps) + + if PI1 == '': + output_file = open(parent_folder + '/S' + str(segment_length) + '_W' + str(W) + '_T' + str(threshold) + '_t1t2_' + str(t1) + '-' + str(t2) + '.txt','w') + else: + output_file = open(parent_folder + '/S' + str(segment_length) + '_W' + str(W) + '_T' + str(threshold) + '_E' + str(PI1) + '-' + str(PI2) + '_t1t2_' + str(t1) + '-' + str(t2) + '.txt','w') + cand_f = f[ps_sig>=hist_min_sig] #decided not to use hist_min_f ; otherwise I get empty files... + cand_ps = ps_sig[ps_sig>=hist_min_sig] + for i in range(len(cand_f)): + output_file.write(str(cand_f[i]) + ' ' + str(cand_ps[i]) + '\n') + output_file.close() + + plt.figure(num=1,figsize=(10,5.63)) + plt.errorbar(x=f,y=ps,color='r',drawstyle='steps-mid') plt.axhline(y=power_required_3,lw=0.8,alpha=0.5,color='b') plt.axhline(y=power_required_4,lw=0.8,alpha=0.5,color='k') + plt.axhline(y=2,lw=0.8,alpha=0.5,color='k',linestyle='--') plt.xlabel('Frequency (Hz)',fontsize=12) plt.ylabel('Leahy-normalized power',fontsize=12) + plt.xscale('log') + plt.yscale('log') + plt.ylim([1,min(20.0,3*power_required_4)]) + plt.xlim([0.001,1/(2*tbin)]) if len(xlims) != 0: plt.xlim([xlims[0],xlims[1]]) #plt.axvline(x=271.453,lw=0.5,alpha=0.5) - plt.title('W = ' + str(W) + ', Threshold = ' + str(threshold) + '%' + '\n' + 'Segment Length: ' + str(segment_length) + 's, No. Segments = ' + str(M) + '\n' + 'Demodulated: ' + str(demod) + ' ; St.D = ' + str(np.std(ps)), fontsize=12) - plt.legend(('Power Spectrum','3 sigma','4 sigma'),loc='best') + plt.title('PI: ' + str(PI1)+'-'+str(PI2) + '; W = ' + str(W) + ', Threshold = ' + str(threshold) + '%' + '\n' + 't1 = ' + str(t1) + ', t2 = ' + str(t2) + ' ; Segment Length: ' + str(segment_length) + 's, No. Segments = ' + str(M) + '\n' + 'Demodulated: ' + str(demod) + ' ; St.D = ' + str(np.std(ps)), fontsize=12) + plt.legend(('Power Spectrum','3 sigma','4 sigma','Poisson noise'),loc='best') if plot_mode == "save": if PI1 != '': - energy_suffix = '_E' + str(PI1) + '-' + str(PI2) + energy_suffix = '_E' + str(PI1).zfill(4) + '-' + str(PI2).zfill(4) else: energy_suffix = '' if demod == True: demod_suffix = '_demod' else: demod_suffix = '' - plt.savefig(parent_folder + '/' + str(segment_length) + 's_average_ps_W' + str(W) + demod_suffix + energy_suffix + '.pdf',dpi=900) + plt.savefig(parent_folder + '/' + str(segment_length) + 's_average_ps_W' + str(W) + '_T' + str(threshold) + demod_suffix + energy_suffix + '_t1t2_' + str(t1) + '-' + str(t2) + '.pdf',dpi=900) plt.close() plt.figure(2) @@ -467,23 +549,44 @@ def plotting(eventfile,segment_length,demod,tbin,threshold,PI1,PI2,starting_freq plt.title('Energy range: ' + str(PI1) + ' - ' + str(PI2) + ', W = ' + str(W),fontsize=12) if plot_mode == "save": if PI1 != '': - energy_suffix = '_E' + str(PI1) + '-' + str(PI2) + energy_suffix = '_E' + str(PI1).zfill(4) + '-' + str(PI2).zfill(4) else: energy_suffix = '' if demod == True: demod_suffix = '_demod' else: demod_suffix = '' - plt.savefig(parent_folder + '/' + str(segment_length) + 's_noise_hist_W' + str(W) + demod_suffix + energy_suffix + '.pdf',dpi=900) + plt.savefig(parent_folder + '/' + str(segment_length) + 's_noise_hist_W' + str(W) + '_T' + str(threshold) + demod_suffix + energy_suffix + '_t1t2_' + str(t1) + '-' + str(t2) + '.pdf',dpi=900) plt.close() if plot_mode == "show": plt.show() - if __name__ == "__main__": - eventfile = Lv0_dirs.NICERSOFT_DATADIR + '1034070101_pipe/ni1034070101_nicersoft_bary.evt' - mode = 't' + eventfile = Lv0_dirs.NICERSOFT_DATADIR + '0034070101_pipe/ni0034070101_nicersoft_bary.evt' + #mode = 't' segment_length = 100 - par_file = Lv0_dirs.NICERSOFT_DATADIR + 'J1231-1411.par' - do_demodulate(eventfile,segment_length,mode,par_file) + #par_file = Lv0_dirs.NICERSOFT_DATADIR + 'J1231-1411.par' + #do_demodulate(eventfile,segment_length,mode,par_file) + demod = False + tbin = 0.05 + threshold = 50 + PI1 = 30 + PI2 = 1200 + t1 = 200 + t2 = 2000 + starting_freq = 0.1 + W = 1 + hist_min_sig = 2.5 + N = Lv3_detection_level.N_trials(tbin,segment_length) + xlims = np.array([]) + plot_mode = "show" + + Lv2_presto_subroutines.get_gti_file(eventfile,segment_length) + Lv2_presto_subroutines.niextract_gti_time_energy(eventfile,segment_length,PI1,PI2) + do_nicerfits2presto(eventfile,tbin,segment_length) + edit_inf(eventfile,tbin,segment_length) + edit_binary(eventfile,tbin,segment_length) + realfft(eventfile,segment_length) + + plotting(eventfile,segment_length,demod,tbin,threshold,PI1,PI2,t1,t2,starting_freq,W,hist_min_sig,N,xlims,plot_mode) diff --git a/Lv2_bestprof2par.py b/Lv2_bestprof2par.py new file mode 100644 index 0000000..3c55f5b --- /dev/null +++ b/Lv2_bestprof2par.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" + +Created on Tuesday Oct 27 11:29am 2020 + +Converts the .bestprof file into a par file + +""" +from __future__ import division, print_function +import numpy as np +import pathlib +import Lv0_dirs + +Lv0_dirs.global_par() #obtaining the global parameters + +def bestprof2par(bestprof,parfile): + """ + Converts the .bestprof text file into a .par file + + bestprof - path to the bestprof file + parfile - path to the parfile + """ + contents = open(bestprof,'r').read().split('\n') + + for line in contents: + if line.startswith('# Epoch_bary'): + pepoch = float(line.split()[4]) + if line.startswith('# P_bary'): + p0 = float(line.split()[4])/1000.0 + if line.startswith("# P'_bary"): + p1 = float(line.split()[4]) + if line.startswith("# P''_bary"): + p2 = float(line.split()[4]) + + f0 = 1/p0 + f1 = -p1/p0**2 + f2 = (2*p1**2-p0*p2)/p0**3 + + par_write = open(parfile,'w') + par_write.write("PEPOCH " + str(pepoch) + '\n') + par_write.write("F0 " + repr(f0) + " 1" + '\n') + par_write.write("F1 " + repr(f1) + " 1" + '\n') + par_write.write("F2 " + repr(f2)) + + par_write.close() + + return + +if __name__ == "__main__": + + bestprof = Lv0_dirs.NICER_DATADIR + 'igrj17494-3030/accelsearch_GTIs/2010270036_bary_GTI000002_E0200-1200_ACCEL_Cand_1.pfd.bestprof' + parfile = Lv0_dirs.NICER_DATADIR + 'igrj17494-3030/igrj17494.par' + bestprof2par(bestprof,parfile) diff --git a/Lv2_create_time_res_spec.py b/Lv2_create_time_res_spec.py new file mode 100644 index 0000000..6ab9d2b --- /dev/null +++ b/Lv2_create_time_res_spec.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +Created on Sun April 5 5:32pm 2020 + +Program that splits up an event file to do time-resolved spectroscopy + +""" +from __future__ import division, print_function +import numpy as np +from astropy.io import fits +import Lv0_dirs,Lv1_data_gtis,Lv2_presto_subroutines,Lv2_mkdir +import os +from tqdm import tqdm +import subprocess +import pathlib +import glob + +Lv0_dirs.global_par() + +def niextract_gti(eventfile,gap,gtifile,min_exp): + """ + Using niextract-events to get segmented data based on the individual GTIs created with + GTI_bunching in Lv1_data_gtis. (Very similar to that in Lv2_presto_subroutines, + except I create a list of paths to the event files.) + + eventfile - path to the event file. Will extract ObsID from this for the NICER files. + gap - maximum separation between end time of 1st GTI and start time of 2nd GTI allowed + gtifile - name of GTI file + min_exp - minimum exposure to be used for the spectra + """ + parent_folder = str(pathlib.Path(eventfile).parent) + Lv1_data_gtis.GTI_bunching(eventfile,gap,gtifile) + + gtis = list(fits.open(parent_folder+'/'+gtifile)[1].data) + niextract_folder = parent_folder + '/accelsearch_GTIs/' + Lv2_mkdir.makedir(niextract_folder) + for i in tqdm(range(len(gtis))): + gti_start = gtis[i][0] + gti_end = gtis[i][1] + if gti_end - gti_start >= min_exp: + subprocess.run(['mkgti.py','--gtiname',niextract_folder+'GTI'+str(i+1)+'.gti',str(gti_start),str(gti_end)]) + subprocess.run(['niextract-events',eventfile,niextract_folder+str(pathlib.Path(eventfile).name)[:-4]+'_GTI'+str(i+1).zfill(4)+'.evt','timefile='+niextract_folder+'GTI'+str(i+1)+'.gti']) + + return + +def instructions(eventfile): + """ + Writing a set of instructions to use in XSELECT, in order to extract the spectra and all! + + eventfile - path to the event file. Will extract ObsID from this for the NICER files. + """ + parent_folder = str(pathlib.Path(eventfile).parent) + niextract_folder = parent_folder + '/accelsearch_GTIs/spectra/' + + instruct_file = niextract_folder + '/instructions.txt' + + eventfiles = sorted(glob.glob(niextract_folder+'/*E0050-1200.evt')) + instruct = open(instruct_file,'w') + for i in range(len(eventfiles)): + eventfile = str(pathlib.Path(eventfiles[i]).name) + + instruct.write('set mission nicer' + '\n') + instruct.write('set inst xti' + '\n') + instruct.write('set datadir ' + niextract_folder + '\n') + instruct.write('read event ' + eventfile + '\n') + instruct.write('extract spectrum' + '\n') + instruct.write('save spectrum ' + eventfile[:-3] + 'pha' + '\n') + instruct.write('clear data' + '\n') + instruct.write(' ' + '\n') + + instruct.close() + + return + +def set_rmf_arf(eventfile): + """ + Setting paths to response and arf files in the individual spectra files. + To check, can do "fkeyprint FILENAME ANCRFILE/RESPFILE" + + eventfile - path to the event file. Will extract ObsID from this for the NICER files. + """ + parent_folder = str(pathlib.Path(eventfile).parent) + niextract_folder = parent_folder + '/accelsearch_GTIs/spectra' + + spectrafiles = sorted(glob.glob(niextract_folder+'/*.pha')) + + resp = '/Volumes/Samsung_T5/nicer-rmf6s-teamonly-array52.rmf' + arf = '/Volumes/Samsung_T5/nicer-consim135p-teamonly-array52.arf' + + for i in range(len(spectrafiles)): + subprocess.run(['fparkey',resp,spectrafiles[i],'RESPFILE']) + subprocess.run(['fparkey',arf,spectrafiles[i],'ANCRFILE']) + + return + +def grppha(eventfile): + """ + Function that does GRPPHA on a set of pha files. + The function will output pha files of the format 'grp_$file'! + + eventfile - path to the event file. Will extract ObsID from this for the NICER files. + """ + parent_folder = str(pathlib.Path(eventfile).parent) + niextract_folder = parent_folder + '/accelsearch_GTIs/spectra/' + binned_phas = sorted(glob.glob(niextract_folder+'*pha')) + + command_file = niextract_folder + 'grppha_commands.go' + writing = open(command_file,'w') + #### now to build the grppha command + grppha = 'grppha' + chatter = 'chatter=0' + for i in range(len(binned_phas)): + #comm = 'comm="group nicer_channels_to_group.dat & systematics 30-1200 0.02 & chkey ANCRFILE /Volumes/Samsung_T5/nicer-consim135p-teamonly-array50.arf & chkey RESPFILE /Volumes/Samsung_T5/nicer-rmf6s-teamonly-array50.rmf & chkey BACKFILE ' + backfile + ' & exit"' + comm = 'comm="group nicer_channels_to_group.dat & systematics 30-1200 0.02 & exit"' + infile = 'infile="' + str(pathlib.Path(binned_phas[i]).name) + '"' + outfile = 'outfile="grp_' + str(pathlib.Path(binned_phas[i]).name) + '"' + writing.write(grppha+' '+infile+' '+outfile+' '+chatter+' '+comm+'\n') + writing.close() + +def xspec_read_all(eventfile): + """ + To read all the spectral files (with rmf,arf already set!) and ignore 0.0-0.3, 12-higher keV + + eventfile - path to the event file. Will extract ObsID from this for the NICER files. + """ + parent_folder = str(pathlib.Path(eventfile).parent) + niextract_folder = parent_folder + '/accelsearch_GTIs/spectra/' + + spectrafiles = sorted(glob.glob(niextract_folder+'/*.pha')) + + readspectra = open(niextract_folder + 'readspectra.xcm','w') + data_string = 'data ' + ' '.join([str(i+1)+':'+str(i+1) + ' ' + spectrafiles[i] for i in range(len(spectrafiles))]) + readspectra.write(data_string + '\n') + readspectra.write('ignore **:0.0-0.485,12.01-**' + '\n') + readspectra.write('abund wilm' + '\n') + readspectra.close() + + return + +if __name__ == "__main__": + eventfile = Lv0_dirs.NICER_DATADIR + 'at2019wey/2008041401_filt_bary.evt' + + gap = 5 + gtifile = 'bunched.gti' + min_exp = 50 + + #niextract_gti(eventfile,gap,gtifile,min_exp) + #instructions(eventfile) + + #set_rmf_arf(eventfile) + + #import pathlib + #specs = sorted(glob.glob('/Volumes/Samsung_T5/NICER-data/at2019wey/accelsearch_GTIs/spectra/*evt')) + #for i in range(len(specs)): + # print(str(pathlib.Path(specs[i]).name) + ' ' + str(fits.open(specs[i])[1].header['NAXIS2'])) + #grppha(eventfile) + xspec_read_all(eventfile) diff --git a/Lv2_dj_lsp.py b/Lv2_dj_lsp.py new file mode 100644 index 0000000..32524d8 --- /dev/null +++ b/Lv2_dj_lsp.py @@ -0,0 +1,340 @@ +import pandas as pd +import numpy as np +from tqdm import tqdm +import matplotlib.pyplot as plt +from astropy.io import fits +import Lv2_swift_lc +from scipy import stats +from scipy.optimize import curve_fit +import glob + +def rebin_lc(corr_lc_files,corr_bg_files,bg_scale,tbin,cmpltness): + """ + Rebinning the original light curve that was corrected through xrtlccorr + + lc_files - list of corrected light curve files + tbin - size of new time bins + cmpltness - level of completeness for the bins + """ + + """ + #### time order the lc files!!! + start_times = [fits.open(lc_files[i])[1].header['TIMEZERO'] for i in range(len(lc_files))] + time_ordered = np.argsort(start_times) + ordered_eventlist = np.array(lc_files)[time_ordered] + + times = [] + rates = [] + errors = [] + for i in tqdm(range(len(ordered_eventlist))): #getting every corrected light curve FITS file + data_arrays = fits.open(ordered_eventlist[i])[1].data + tstart = fits.open(ordered_eventlist[i])[1].header['TIMEZERO'] #get TIMEZERO + times += list(tstart+data_arrays['TIME']) #add to an overall list, the 'TIME' array from the corrected light curve FITS file, plus timezero + rates += list(data_arrays['RATE']) #get the corresponding column for the rates + errors += list(data_arrays['ERROR']) #get the corresponding column for the errors + + times = np.array(times) + trunc_times = times-times[0] + rates = np.array(rates) + errors = np.array(errors) + """ + times,rates,errors,fracexp = Lv2_swift_lc.get_bgsub(corr_lc_files,corr_bg_files,bg_scale) + trunc_times = times-times[0] + + rebinned_time = [] + rebinned_rate = [] + rebinned_errs = [] + rebinned_fracexp = [] + completeness = [] + + time_bins = np.arange(0,trunc_times[-1]+tbin,tbin) + print('Rebinning...') + for i in tqdm(range(len(time_bins)-1)): + time_interval = trunc_times[(trunc_times>=time_bins[i])&(trunc_times=time_bins[i])&(trunc_times=time_bins[i])&(trunc_times=time_bins[i])&(trunc_times= cmpltness: + mean_time = np.mean(time_interval) + mean_rate = np.mean(rate_interval) + mean_error = np.sqrt(np.sum(error_interval**2))/np.size(error_interval) + sum_fracexp = sum(fracexp_interval) + + rebinned_time.append(mean_time) + rebinned_rate.append(mean_rate) + rebinned_errs.append(mean_error) + rebinned_fracexp.append(sum_fracexp) + completeness.append(len(time_interval)/(tbin/10)) + + #plt.hist(completeness,bins=10) + #plt.xlabel('Completeness (fraction)',fontsize=12) + #plt.ylabel('Number',fontsize=12) + #plt.show() + + #print(len(rebinned_time)) + + return np.array(rebinned_time),np.array(rebinned_rate),np.array(rebinned_errs),np.array(rebinned_fracexp) + +def psd_error(times,rates,errors): + """ + obtain errors for the best frequency estimate of the signal + """ + + """ + print(len(times),len(rates),len(errors)) + newdatachoice = np.random.choice(len(times),size=int(0.1*len(times))) + + newtimes = list(np.array([times[0]])) + list(np.array([times[-1]])) + list(times[np.array(list(set(newdatachoice)))]) + newrates = list(np.array([rates[0]])) + list(np.array([rates[-1]])) + list(rates[np.array(list(set(newdatachoice)))]) + newerrs = list(np.array([errors[0]])) + list(np.array([errors[-1]])) + list(errors[np.array(list(set(newdatachoice)))]) + + times = newtimes + rates = newrates + errors = newerrs + print(len(times),len(rates),len(errors)) + """ + freqs_list = [] + psds_list = [] + for j in tqdm(range(1000)): + new_rates = np.zeros(len(rates)) + for i in range(len(rates)): + if rates[i] != 0: + new_rates[i] = np.random.normal(loc=rates[i],scale=errors[i]) + + trunc_times = times-times[0] + + newchoice = np.random.choice(len(trunc_times),size=len(trunc_times)) + rand_times = trunc_times[np.array(list(set(newchoice)))] + rand_rates = new_rates[np.array(list(set(newchoice)))] + omega,psd,prob3,prob4,prob5 = lsp(rand_times,rand_rates) + + nu_reg = omega/(2.0*np.pi) + freq = omega/(2*np.pi) + psds_list.append( np.max(psd[(freq>=8.2e-6)&(freq<=8.4e-6)]) ) + freqs_list.append( freq[psd==psds_list[-1]][0]) + + #plt.figure() + #plt.plot(freq,psd,'rx-') + #plt.show() + + return freqs_list,psds_list + +def lsp(times, rates): + """ + cast times and rates as numpy arrays + """ + times = np.array(times) + rates = np.array(rates) + """ + Set the initial time to 0 + """ + tmin = min(times) + times = times - tmin + """ + calculate the number of independent frequencies + """ + n0 = len(times) + Ni = int(-6.362 + 1.193*n0 + 0.00098*n0**2) + + """ + estimate the minimum and maximum frequencies to be sampled + """ + fmin = 1/np.max(times) + fmax = n0/(2.0*np.max(times)) + #print('Minimum frequency: ' + str(fmin)) + #print('Maximum frequency: ' + str(fmax)) + #print(fmax) + fmax = 1e-5 + + """ + The frequencies that will be sampled + """ + omega = 2*np.pi *(fmin+(fmax-fmin)*np.arange(Ni)/(Ni-1.)) + + """ + subtract the mean from data + """ + cn = rates - np.mean(rates) + """ + compute the lsp + """ + psd = np.zeros(Ni) + + print('Calculating the PSD...') + for i in tqdm(range(Ni)): + tau = np.arctan(np.sum(np.sin(2.*omega[i]*times))/np.sum(np.cos(2.*omega[i]*times))) + tau = tau/(2*omega[i]) + + co = np.cos(omega[i]*(times-tau)) + si = np.sin(omega[i]*(times-tau)) + psd[i] = 0.5*(np.sum(cn*co)**2/np.sum(co**2)+np.sum(cn*si)**2/np.sum(si**2)) + """ + correct normalization + """ + var = np.std(cn) + psd = psd/var**2 + + """ + calculate the false alarm probabilities + """ + + sigmathree=2.7e-03 + sigmafour=6.33e-05 + sigmafive=5.73e-7 + + probthree = -np.log(1.0 - ((1.0-sigmathree)**(1./Ni)) ) + probfour = -np.log(1.0 - ((1.0-sigmafour)**(1./Ni)) ) + probfive = -np.log(1.0 - ((1.0-sigmafive)**(1./Ni)) ) + + return omega, psd, probthree, probfour, probfive + +def rebin(array, rebinfac): + if len(array) % rebinfac == 0: + Nrebin = int(len(array) / rebinfac) + newarray = [None]*Nrebin + for i in range(Nrebin): + startinx = i*rebinfac + stopinx = startinx + rebinfac + newarray[i] = np.mean(array[startinx:stopinx]) + return newarray + else: + raise TypeError("rebinfac MUST be an integer factor of array size") + +def powlaw(x,a,b,c): + return a + b*x**(-c) + +if __name__ == '__main__': + #eventfile = '/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/ngc300x1/lightcurve/ngc300x1_100s.lc' + #lc_files = glob.glob('/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/lightcurve/sw*bgsub*corr.lc') + + bary_outputfolder = '/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/lightcurve/' + obsids = [str(i) for i in range(49834027,49834042)] + [str(i) for i in range(49834043,49834062)] + [str(i) for i in range(49834063,49834066)] + ['88810002'] + [str(i) for i in range(49834066,49834069)] + [str(i) for i in range(49834070,49834079)] + [str(i) for i in range(49834080,49834088)] + corr_lc_files = [bary_outputfolder + 'sw000' + obsids[i] + '_corr.lc' for i in range(len(obsids))] + corr_ulx1_files = [bary_outputfolder + 'sw000' + obsids[i] + '_ulx1_corr.lc' for i in range(len(obsids))] + corr_bg_files = [bary_outputfolder + 'sw000' + obsids[i] + '_bg_corr.lc' for i in range(len(obsids))] + bg_scale_x1 = (30/120)**2 + #bg_scale_ulx1 = (35/120)**2 + rebinned_t, rebinned_rate, rebinned_err, rebinned_fracexp = rebin_lc(corr_lc_files,corr_bg_files,bg_scale_x1,100,0) + #print(rebinned_fracexp[:50]) + #rebinned_t_ulx1, rebinned_rate_ulx1, rebinned_err_ulx1 = rebin_lc(corr_ulx1_files,corr_bg_files,bg_scale_ulx1,3600) + + #x1_text = open(bary_outputfolder + 'ngc300x1_bg_exp_corr_lc_3600s.txt','w') + #ulx1_text = open(bary_outputfolder + 'ngc300ulx1_bg_exp_corr_lc_3600s.txt','w') + + tstart_49834027 = 546830295.758713 + + #for i in range(len(rebinned_t)): + # x1_text.write(str(51910 + 7.428703700000000E-04+(rebinned_t[i]+tstart_49834027)/86400) + ' ' + str(rebinned_rate[i]) + ' ' + str(rebinned_err[i]) + '\n') + #x1_text.close() + + #for i in range(len(rebinned_t_ulx1)): + # ulx1_text.write(str(51910 + 7.428703700000000E-04 + (rebinned_t_ulx1[i]+tstart_49834027)/86400) + ' ' + str(rebinned_rate_ulx1[i]) + ' ' + str(rebinned_err_ulx1[i]) + '\n') + #ulx1_text.close() + + #print(51910 + 7.428703700000000E-04+(tstart_49834027+rebinned_t[rebinned_err>=0.06])/86400,rebinned_rate[rebinned_err>=0.06],rebinned_err[rebinned_err>=0.06]) + #print(51910 + 7.428703700000000E-04+(tstart_49834027+rebinned_t_ulx1[rebinned_err_ulx1>=0.06])/86400,rebinned_rate_ulx1[rebinned_err_ulx1>=0.06],rebinned_err_ulx1[rebinned_err_ulx1>=0.06]) + + #mjd = 51910 + 7.428703700000000E-04 + (tstart_49834027+rebinned_t)/86400 + #mjd_ulx1 = 51910 + 7.428703700000000E-04 + (tstart_49834027+rebinned_t_ulx1)/86400 + #plt.errorbar(x=mjd[rebinned_err<=0.06],y=rebinned_rate[rebinned_err<=0.06],yerr=rebinned_err[rebinned_err<=0.06],fmt='rx') + #plt.errorbar(x=mjd_ulx1[rebinned_err_ulx1<=0.06],y=rebinned_rate_ulx1[rebinned_err_ulx1<=0.06],yerr=rebinned_err_ulx1[rebinned_err_ulx1<=0.06],fmt='bx') + #plt.legend(('X-1','ULX-1'),fontsize=12) + #plt.xlabel('Time (MJD)',fontsize=12) + #plt.ylabel('[Exposure-corrected] Count rate (c/s)',fontsize=12) + #plt.axhline(y=0,color='k',lw=0.5,alpha=0.5) + #plt.show() + + #psd_error(times,rates,errors) + #freqs_list, psd_list = psd_error(rebinned_t,rebinned_rate,rebinned_err) + + #print('Median frequency: ' + str(np.median(freqs_list))) + #print('Error in frequency: ' + str(np.std(freqs_list))) + #print('Powers: ' + str(psd_list)) + + mjd_x1 = 51910 + 7.428703700000000E-04 + (tstart_49834027+rebinned_t)/86400 + + xmm_lc1 = '/Volumes/Samsung_T5/NGC300_XMMdata/0791010101/PROC/xmm_0791010101_lccorr.lc' + rebinned_t_xmm1 = fits.open(xmm_lc1)[1].data['TIME'] + rebinned_rate_xmm1 = fits.open(xmm_lc1)[1].data['RATE'] + xmm_lc2 = '/Volumes/Samsung_T5/NGC300_XMMdata/0791010301/PROC/xmm_0791010301_lccorr.lc' + rebinned_t_xmm2 = fits.open(xmm_lc2)[1].data['TIME'] + rebinned_rate_xmm2 = fits.open(xmm_lc2)[1].data['RATE'] + + mjd_x1_xmm = fits.open(xmm_lc1)[1].header['MJDREF'] + np.array(list(rebinned_t_xmm1) + list(rebinned_t_xmm2))/86400 + rebinned_rate_xmm = np.array(list(rebinned_rate_xmm1) + list(rebinned_rate_xmm2)) + + total_t = np.array(list(mjd_x1_xmm) + list(mjd_x1)) + total_t_s = (total_t - total_t[0])*86400 + total_rate = np.array(list(rebinned_rate_xmm) + list(rebinned_rate)) + + ### For the light curve + plt.figure() + plt.plot(total_t_s,total_rate,'r-') + plt.plot(total_t_s,0.2*np.sin(2*np.pi*8.4712e-6 * total_t_s + 0.2)+0.2,'b-') + + ### For the PSD + omega,psd,prob3,prob4,prob5 = lsp(total_t_s,total_rate) + #omega,psd,prob3,prob4,prob5 = lsp(times,rates) + freq = omega/(2*np.pi) + + plt.figure() + plt.plot(freq,psd,'rx-') + #plt.yscale('log') + #plt.xscale('log') + plt.xlabel('Frequency (Hz)',fontsize=12) + plt.ylabel('Normalized Power',fontsize=12) + plt.axhline(y=prob3,lw=0.5,alpha=0.5) + plt.axhline(y=prob4,lw=0.5,alpha=0.5) + plt.axhline(y=prob5,lw=0.5,alpha=0.5) + print(prob3,prob4,prob5) + + plt.show() + + + + + + + + + + + + + + + + + """ + df = pd.read_csv("lc0853980201.dat",delim_whitespace=True, header=None) + times = df.iloc[:,0] + rates = df.iloc[:,1] + + np.random.shuffle(rates) + + omega, psd,_,_,_ = lsp(times, rates) + nu_reg = omega/(2.0*np.pi) + + refac = 2 + if refac > 1: + hot = rebin(nu_reg,refac) + pot = rebin(psd, refac) + zot = pot/np.sqrt(refac) + else: + hot = nu_reg + pot = psd + zot = pot + print(len(psd)) + print(np.mean(psd)) + plt.step(hot, pot,where='mid',color='orange') + plt.errorbar(hot,pot,yerr=zot, ls='none', color='orange') + plt.xscale('log') + plt.yscale('log') + popt, pcov = curve_fit(powlaw, hot, pot) + plt.plot(nu_reg, powlaw(nu_reg, *popt), 'g--', label='fit: a=%5.3f, b=%5.3f, c=%5.3f' % tuple(popt)) + plt.legend(loc='best') + #plt.show() + """ diff --git a/Lv2_efsearch.py b/Lv2_efsearch.py index d11f573..8910e85 100644 --- a/Lv2_efsearch.py +++ b/Lv2_efsearch.py @@ -85,3 +85,19 @@ def efsearch(eventfile,n_segments,dper,nphase,nbint,nper,dres,outfile_root,plot_ plt.ylabel('chi-squared',fontsize=12) pdf.savefig() plt.close() + +if __name__ == "__main__": + eventfile = '/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/ngc300x1/ngc300x1_merge_niceroverlap_all.evt' + n_segments = 1 + dper = 1/8.461949e-6 + nphase = 20 + nper = 128 + dres = 1 + plot_efsearch = "yes" + + T = fits.open(eventfile)[2].data['STOP'][-1] - fits.open(eventfile)[2].data['START'][0] + + outfile_root = 'ngc300x1' + '_' + str(n_segments) + 'segs_' + str(nper) + nbint = int((T/(dper/nphase))/n_segments) + + efsearch(eventfile,n_segments,dper,nphase,nbint,nper,dres,outfile_root,plot_efsearch) diff --git a/Lv2_lc.py b/Lv2_lc.py index 3d0235c..adc31a9 100644 --- a/Lv2_lc.py +++ b/Lv2_lc.py @@ -42,19 +42,28 @@ def whole(eventfile,par_list,tbin_size,mode): parent_folder = str(pathlib.Path(eventfile).parent) + start_stop = Lv0_fits2dict.fits2dict(eventfile,2,['START','STOP']) + exptime = sum([ (start_stop['STOP'][i]-start_stop['START'][i]) for i in range(len(start_stop['START'])) ]) + data_dict = Lv0_fits2dict.fits2dict(eventfile,1,par_list) times = data_dict['TIME'] counts = np.ones(len(times)) shifted_t = times-times[0] - t_bins = np.linspace(0,np.ceil(shifted_t[-1]),np.ceil(shifted_t[-1])*1/tbin_size+1) + t_bins = np.linspace(0,np.ceil(shifted_t[-1]),int(np.ceil(shifted_t[-1])*1/tbin_size+1)) summed_data, bin_edges, binnumber = stats.binned_statistic(shifted_t,counts,statistic='sum',bins=t_bins) #binning the time values in the data event_header = fits.open(eventfile)[1].header obj_name = event_header['OBJECT'] obsid = event_header['OBS_ID'] - plt.plot(t_bins[:-1],summed_data) + #for i in range(len(t_bins)-1): + # print(t_bins[i],summed_data[i]) + #print('----') + print('Creating light curve from ' + eventfile) + #for i in range(len(plot_time)): + # print(plot_time[i],plot_data[i]) + plt.plot(t_bins[:-1],summed_data,'x') plt.title('Light curve for ' + obj_name + ', ObsID ' + str(obsid),fontsize=12) plt.xlabel('Time (s)', fontsize=12) plt.ylabel('Count/' + str(tbin_size) + 's',fontsize=12) diff --git a/Lv2_merged_pulse_methods.py b/Lv2_merged_pulse_methods.py index e4ef186..f202869 100644 --- a/Lv2_merged_pulse_methods.py +++ b/Lv2_merged_pulse_methods.py @@ -12,7 +12,7 @@ import subprocess from astropy.io import fits -from presto import binary_psr +#from presto import binary_psr import Lv0_dirs,Lv2_phase import matplotlib.pyplot as plt diff --git a/Lv2_merging_events.py b/Lv2_merging_events.py index bc62152..f2232a9 100644 --- a/Lv2_merging_events.py +++ b/Lv2_merging_events.py @@ -16,7 +16,7 @@ from tqdm import tqdm import matplotlib.pyplot as plt from astropy.io import fits -from presto import binary_psr +#from presto import binary_psr import subprocess import glob import os @@ -24,13 +24,59 @@ Lv0_dirs.global_par() -def merging(obsids): +def merging(obsids,merged_id): """ Given a list of ObsIDs, create a file which merges all the rows in the EVENTS extension of the FITS files! + Updated 8/14/2020: Use a list of event files given in a text file! obsids - list (or array) of ObsIDs + merged_id - 6-digit ID for the merged event file """ + if type(obsids) != list and type(obsids) != np.ndarray: + raise TypeError("obsids should either be a list or an array!") + if type(merged_id) != str or len(merged_id) != 6: + raise TypeError("merged_id should be a string and have 6 digits in the string!") + + all_merged_dir = Lv0_dirs.NICERSOFT_DATADIR + 'merged_events/' + merged_dir = all_merged_dir + 'merged' + merged_id + '/' + Lv2_mkdir.makedir(merged_dir) + + filelist = np.array([Lv0_dirs.NICERSOFT_DATADIR + str(obsids[i]) + '_pipe/ni' + str(obsids[i]) + '_nicersoft_bary.evt' for i in range(len(obsids))]) + int_text = open(merged_dir+'filelist.txt','w') + for i in range(len(filelist)): #writing the paths to each file in filelist + int_text.write(filelist[i] + '\n') + int_text.close() + + subprocess.run(['ftmerge','@'+merged_dir+'filelist.txt',merged_dir+'intermediate.evt']) + + gti_filelist = np.array([Lv0_dirs.NICERSOFT_DATADIR + str(obsids[i]) + '_pipe/ni' + str(obsids[i]) + '_nicersoft_bary.evt[GTI]' for i in range(1,len(obsids))]) + final_text = open(merged_dir+'filelist_gti.txt','w') #list of files with the GTI extension referenced + final_text.write(merged_dir+'intermediate.evt[GTI]'+'\n') + for i in range(len(gti_filelist)): + final_text.write(gti_filelist[i] + '\n') + final_text.close() + + merged_file = merged_dir+'merged'+merged_id+'_nicersoft_bary.evt' + subprocess.run(['ftmerge','@'+merged_dir+'filelist_gti.txt',merged_file,'clobber=YES']) + subprocess.run(['rm','-r',merged_dir+'intermediate.evt']) + + merged_gtis = fits.open(merged_file)[2].data + gti_sum = sum(np.array([merged_gtis[i][1]-merged_gtis[i][0] for i in range(len(merged_gtis))])) + subprocess.run(['fparkey',str(gti_sum),merged_file,'EXPOSURE']) + + return + +################################## DEPRECATED ################################## + +""" +def merging(obsids): + + Given a list of ObsIDs, create a file which merges all the rows in the EVENTS + extension of the FITS files! + + obsids - list (or array) of ObsIDs + if type(obsids) != list and type(obsids) != np.ndarray: raise TypeError("obsids should either be a list or an array!") @@ -54,19 +100,20 @@ def merging(obsids): merged_text.write('merged'+merged_id+': '+ ' '.join(obsids)) merged_text.close() - subprocess.check_call(['ftmerge',inputfile_string,merged_dir+'merged'+merged_id + '_nicersoft_bary.evt','clobber=YES']) + subprocess.run(['ftmerge',inputfile_string,merged_dir+'merged'+merged_id + '_nicersoft_bary.evt','clobber=YES']) + #print(inputfile_string) return def merging_GTIs(obsids,merged_id): - """ + Given a list of ObsIDs and the merged_id, create the final event file, which already has all the rows in the EVENTS extension of the FITS files, BUT also including the GTI extension of the FITS files! obsids - list (or array) of ObsIDs merged_id - 6-digit ID for the merged event file - """ + if type(obsids) != list and type(obsids) != np.ndarray: raise TypeError("obsids should either be a list or an array!") if type(merged_id) != str: @@ -85,12 +132,18 @@ def merging_GTIs(obsids,merged_id): else: inputfile_string += abs_filename - subprocess.check_call(['ftmerge',inputfile_string,merged_dir+'merged'+merged_id + '_nicersoft_bary.evt','clobber=YES']) + subprocess.run(['ftmerge',inputfile_string,merged_dir+'merged'+merged_id + '_nicersoft_bary.evt','clobber=YES']) + #print(inputfile_string) return +""" if __name__ == "__main__": - obsids = ['2060060363','2060060364','2060060365'] - merged_id = '000013' + #obsids = ['2060060363','2060060364','2060060365'] + #merged_id = '000013' + + obsids = ['2050280' +str(i) for i in range(119,125)] + merged_id = '000020' + merging(obsids) merging_GTIs(obsids,merged_id) diff --git a/Lv2_ngc300_color.py b/Lv2_ngc300_color.py index 14bcb39..ac962e2 100644 --- a/Lv2_ngc300_color.py +++ b/Lv2_ngc300_color.py @@ -14,15 +14,14 @@ Lv0_dirs.global_par() -bin_size = '03d' #bins of 1 day! - -def get_color(bin_size,band1,band2): +def get_color(bin_size,bgsub_type,band1,band2): """ Obtain colors and the corresponding uncertainties. Will NOT use values where either the counts/rate from band1 OR band2 are negative! Allowed band values are "soft1, soft2, A, B, C, D, and inband." bin_size - binning size desired (1 day or 10 days, for example) + bgsub_type - either 'bgsub' or 'xbgsub' band1 - energy band 1 band2 - energy band 2 """ @@ -31,8 +30,8 @@ def get_color(bin_size,band1,band2): if band2 != 'soft1' and band2 != 'soft2' and band2 != 'A' and band2 != 'B' and band2 != 'C' and band2 != 'D' and band2 != 'inband': raise ValueError("Make sure band2 is either of soft1, soft2, A, B, C, D, or inband!") - binned_counts_file = Lv0_dirs.NGC300 + 'n300_ulx.bgsub_cl50_RGnorm_' + bin_size + '.ffphot' - binned_unc_file = Lv0_dirs.NGC300 + 'n300_ulx.bgsub_cl50_RGerr_' + bin_size + '.ffphot' + binned_counts_file = Lv0_dirs.NGC300_2020 + 'n300_ulx.' + bgsub_type + '_cl50_g2020norm_' + bin_size + '.fffphot' + binned_unc_file = Lv0_dirs.NGC300_2020 + 'n300_ulx.' + bgsub_type + '_cl50_g2020err_norm_' + bin_size + '.fffphot' mjds = np.genfromtxt(binned_counts_file,usecols=(0),unpack=True) if band1 == 'soft1': @@ -91,4 +90,4 @@ def get_color(bin_size,band1,band2): return mjds_pos, color, color_unc if __name__ == "__main__": - binned_text() + bin_size = '01d' #bins of x day(s)! diff --git a/Lv2_phase.py b/Lv2_phase.py index 9f3febe..934a184 100644 --- a/Lv2_phase.py +++ b/Lv2_phase.py @@ -13,6 +13,7 @@ import numpy as np import Lv0_dirs,Lv0_fits2dict,Lv1_data_bin,Lv2_mkdir from scipy import stats +from pint.eventstats import sf_z2m,z2m,sig2sigma from PyAstronomy.pyasl import foldAt import pathlib import matplotlib.gridspec as gridspec @@ -42,11 +43,99 @@ def pulse_profile(f_pulse,times,counts,shift,no_phase_bins): counts = list(counts[index_sort])*2 phase_bins = np.linspace(0,2,no_phase_bins*2+1) - summed_profile, bin_edges, binnumber = stats.binned_statistic(phases,counts,statistic='sum',bins=phase_bins) + summed_profile, bin_edges, binnumber = stats.binned_statistic(phases,counts,statistic='mean',bins=phase_bins) return phases, phase_bins, summed_profile -def pulse_folding(t,T,T0,f,fdot,fdotdot,no_phase_bins): + +def phase_exposure(start_time, stop_time, period, nbin=16, gtis=None): + """Calculate the exposure on each phase of a pulse profile. + + THIS FUNCTION IS FROM STINGRAY. + https://stingray.readthedocs.io/en/latest/_modules/stingray/pulse/pulsar.html + (as of 6/29/2020) + + Parameters + ---------- + start_time, stop_time : float + Starting and stopping time (or phase if ``period==1``) + period : float + The pulse period (if 1, equivalent to phases) + + Other parameters + ---------------- + nbin : int, optional, default 16 + The number of bins in the profile + gtis : [[gti00, gti01], [gti10, gti11], ...], optional, default None + Good Time Intervals + + Returns + ------- + expo : array of floats + The normalized exposure of each bin in the pulse profile (1 is the + highest exposure, 0 the lowest) + """ + if gtis is None: + gtis = np.array([[start_time, stop_time]]) + + # Use precise floating points ------------- + start_time = np.longdouble(start_time) + stop_time = np.longdouble(stop_time) + period = np.longdouble(period) + gtis = np.array(gtis, dtype=np.longdouble) + # ----------------------------------------- + + expo = np.zeros(nbin) + phs = np.linspace(0, 1, nbin + 1) + phs = np.array(list(zip(phs[0:-1], phs[1:]))) + + # Discard gtis outside [start, stop] + good = np.logical_and(gtis[:, 0] < stop_time, gtis[:, 1] > start_time) + gtis = gtis[good] + + for g in gtis: + g0 = g[0] + g1 = g[1] + if g0 < start_time: + # If the start of the fold is inside a gti, start from there + g0 = start_time + if g1 > stop_time: + # If the end of the fold is inside a gti, end there + g1 = stop_time + length = g1 - g0 + # How many periods inside this length? + nraw = length / period + # How many integer periods? + nper = nraw.astype(int) + + # First raw exposure: the number of periods + expo += nper / nbin + + # FRACTIONAL PART ================= + # What remains is additional exposure for part of the profile. + start_phase = np.fmod(g0 / period, 1) + end_phase = nraw - nper + start_phase + + limits = [[start_phase, end_phase]] + # start_phase is always < 1. end_phase not always. In this case... + if end_phase > 1: + limits = [[0, end_phase - 1], [start_phase, 1]] + + for l in limits: + l0 = l[0] + l1 = l[1] + # Discards bins untouched by these limits + goodbins = np.logical_and(phs[:, 0] <= l1, phs[:, 1] >= l0) + idxs = np.arange(len(phs), dtype=int)[goodbins] + for i in idxs: + start = np.max([phs[i, 0], l0]) + stop = np.min([phs[i, 1], l1]) + w = stop - start + expo[i] += w + + return expo / np.max(expo) + +def pulse_folding(t,T,T0,f,fdot,fdotdot,no_phase_bins,mission): """ Calculating the pulse profile by also incorporating \dot{f} corrections! Goes from 0 to 2. @@ -58,32 +147,74 @@ def pulse_folding(t,T,T0,f,fdot,fdotdot,no_phase_bins): fdot - frequency derivative fdotdot - second derivative of frequency no_phase_bins - number of phase bins desired (recommended 20!) + mission - "NICER", "XMM", or "SWIFT" for now Returns the pulse profile in counts/s/phase bin vs phase. The number of counts is divided by the exposure time (calculated through total sum of the GTIs) Also added a "TIMEZERO" manually in the script since it'd be inconvenient to call the eventfile here. """ - MJDREFI = 56658 - MJDREFF = 0.000777592592592593 - TIMEZERO = -1 - t_MJDs = MJDREFI + MJDREFF + (TIMEZERO+t)/86400 - - tau = (t_MJDs-T0)*86400 + if mission == "NICER": + ##### NICER + MJDREFI = 56658.0 + MJDREFF = 0.000777592592592593 + TIMEZERO = -1 + t_MJDs = MJDREFI + MJDREFF + (TIMEZERO+t)/86400 #Swift or NICER + + if mission == "SWIFT": + ##### SWIFT + MJDREFI = 51910.0 + MJDREFF = 7.428703700000000E-04 + TIMEZERO = 0 + t_MJDs = MJDREFI + MJDREFF + (TIMEZERO+t)/86400 #Swift or NICER + + if mission == "XMM": + ##### XMM-NEWTON + MJDREF = 50814.0 + t_MJDs = MJDREF + t/86400.0 + + tau = (t_MJDs-T0)*86400.0 + #print(tau[:10]) + #print(f*tau[:10]) phase = (f*tau + fdot/2 *tau**2 + fdotdot/6*tau**3)%1 + #print(phase[:10]) counts = np.ones(len(phase)) phase_bins = np.linspace(0,1,no_phase_bins+1) summed_profile,bin_edges,binnumber = stats.binned_statistic(phase,counts,statistic='sum',bins=phase_bins) - phase_bins_pad = np.linspace(1,2,no_phase_bins+1) - summed_profile_pad = summed_profile + phase_bins_total = np.array(list(phase_bins[:-1]) + list(phase_bins+1)) + summed_profile_total = np.array(list(summed_profile)*2) + error = np.sqrt(summed_profile_total) + + return phase_bins_total, summed_profile_total/T, error/T #/T + #return phase_bins_total, summed_profile_total, error + +def get_Z2(phases,m): + """ + Calculate the Z^2 significances given the event file and harmonic number m + + eventfile - name of event file + m - number of harmonics + """ + z_vals = z2m(phases,m=m) + probs = sf_z2m(z_vals) + significances = sig2sigma(probs) + + return significances - phase_bins_total = np.array(list(phase_bins[:-1]) + list(phase_bins_pad)) - summed_profile_total = np.array(list(summed_profile) + list(summed_profile_pad)) +def get_chi2(profile,error): + """ + Calculating the chi^2 value from the folded profile + + phase - array of phase values + profile - flux/counts per sec per phase bin + error - corresponding errors + """ + mean_prof = np.mean(profile) - return phase_bins_total, summed_profile_total/T + return sum( (profile-mean_prof)**2/error**2 ) def whole(eventfile,par_list,tbin_size,pulse_pars,shift,no_phase_bins,mode): """ @@ -125,7 +256,7 @@ def whole(eventfile,par_list,tbin_size,pulse_pars,shift,no_phase_bins,mode): if pulse_pars[1] == 0 and pulse_pars[2] == 0: #i.e., if both \dot{f} and \ddot{f} are zero; that is, if we have no frequency derivatives counts = np.ones(len(times)) shifted_t = times-times[0] - t_bins = np.linspace(0,np.ceil(shifted_t[-1]),np.ceil(shifted_t[-1])*1/tbin_size+1) + t_bins = np.linspace(0,np.ceil(shifted_t[-1]),int(np.ceil(shifted_t[-1])*1/tbin_size+1)) summed_data, bin_edges, binnumber = stats.binned_statistic(shifted_t,counts,statistic='sum',bins=t_bins) #binning the time values in the data phases, phase_bins, summed_profile = pulse_profile(pulse_pars[0],t_bins[:-1],summed_data,shift,no_phase_bins) else: @@ -138,8 +269,8 @@ def whole(eventfile,par_list,tbin_size,pulse_pars,shift,no_phase_bins,mode): if mode != 'overlap': plt.figure() plt.title('Pulse profile for ' + obj_name + ', ObsID ' + str(obsid),fontsize=12) -# plt.plot(phase_bins[:-1],summed_profile) - plt.step(phase_bins[:-1],summed_profile) +# plt.plot(phase_bins[:-1],summed_profile*(times[-1]-times[0])/T) + plt.step(phase_bins[:-1],summed_profile*(times[-1]-times[0])/T) plt.xlabel('Phase', fontsize=12) plt.ylabel('Count/' + str(tbin_size) + 's',fontsize=12) @@ -205,8 +336,8 @@ def partial_t(eventfile,par_list,tbin_size,pulse_pars,shift,no_phase_bins,t1,t2, if mode != 'overlap': plt.figure() plt.title('Pulse profile for ' + obj_name + ', ObsID ' + str(obsid) + '\n Time interval: ' + str(t1) + 's - ' + str(t2) + 's',fontsize=12) -# plt.plot(phase_bins[:-1], summed_profile) - plt.step(phase_bins[:-1],summed_profile) +# plt.plot(phase_bins[:-1], summed_profile*(times[-1]-times[0])/T) + plt.step(phase_bins[:-1],summed_profile*(times[-1]-times[0])/T) plt.xlabel('Phase', fontsize=12) plt.ylabel('Count/' + str(tbin_size) + 's',fontsize=12) @@ -276,9 +407,9 @@ def partial_E(eventfile,par_list,tbin_size,Ebin_size,pulse_pars,shift,no_phase_b if mode != 'overlap': plt.figure() -# plt.plot(phase_bins[:-1], summed_profile,'-') +# plt.plot(phase_bins[:-1], summed_profile*(times[-1]-times[0])/T,'-') # print(sum(summed_profile)/truncated_t[-1]) - plt.step(phase_bins[:-1],summed_profile) + plt.step(phase_bins[:-1],summed_profile*(times[-1]-times[0])/T) plt.xlabel('Phase', fontsize=12) plt.ylabel('Count/' + str(tbin_size) + 's',fontsize=12) @@ -353,8 +484,8 @@ def partial_tE(eventfile,par_list,tbin_size,Ebin_size,pulse_pars,shift,no_phase_ if mode != 'overlap': plt.figure() plt.title('Pulse profile for ' + obj_name + ', ObsID ' + str(obsid)+ '\n Time interval: ' + str(t1) + 's - ' + str(t2) + 's'+ '\n Energy range: ' + str(E1) + 'keV - ' + str(E2) + 'keV',fontsize=12) -# plt.plot(phase_bins[:-1], summed_profile) - plt.step(phase_bins[:-1],summed_profile) +# plt.plot(phase_bins[:-1], summed_profile*(times[-1]-times[0])/T) + plt.step(phase_bins[:-1],summed_profile*(times[-1]-times[0])/T) plt.xlabel('Phase', fontsize=12) plt.ylabel('Count/' + str(tbin_size) + 's',fontsize=12) diff --git a/Lv2_preprocess.py b/Lv2_preprocess.py index 6209d8a..00704bf 100644 --- a/Lv2_preprocess.py +++ b/Lv2_preprocess.py @@ -45,10 +45,14 @@ def preprocess(obsdir,nicerl2_flags,psrpipe_flags,refframe,orbitfile,parfile,nic if refframe != 'ICRS' and refframe != 'FK5': raise ValueError("refframe should either be ICRS or FK5! Otherwise, update Lv1_barycorr.py if there are options I was unaware of.") + print('Now unzipping all the files!') Lv0_gunzip.unzip_all(obsdir) #unzipping the contents within the observation + print('Now running nicerl2!') Lv0_nicerl2.nicerl2(obsdir,nicerl2_flags) + print('Now running psrpipe.py from NICERsoft!') Lv0_psrpipe.psrpipe(nicer_datafile,psrpipe_flags) #applying custom cuts (though no need --shrinkelv after HEASOFT 6.26) + print('Now running barycorr from HEASOFT!') ##### For the NICER data Lv1_barycorr.barycorr(nicer_datafile,nicer_output,refframe,orbitfile,parfile,obsdir,custom_coords) ##### For the NICERsoft file (cleanfilt.evt, usually) @@ -58,7 +62,7 @@ def preprocess(obsdir,nicerl2_flags,psrpipe_flags,refframe,orbitfile,parfile,nic if __name__ == "__main__": #obsdirs = [Lv0_dirs.NICER_DATADIR + str(i) + '/' for i in range(1034200124,1034200200)] + [Lv0_dirs.NICER_DATADIR + str(i) + '/' for i in range(1034200201,1034200241)] + [Lv0_dirs.NICER_DATADIR + str(i) + '/' for i in range(2034200201,2034200206)] - obsdirs = [Lv0_dirs.NICER_DATADIR + '/1050070103/'] + obsdirs = [Lv0_dirs.NICER_DATADIR + '/2584010501/'] nicerl2_flags = ['clobber=YES'] psrpipe_flags = ['--emin','0.3','--emax','12.0'] #for psrpipe in Lv0_psrpipe refframe = 'ICRS' #for barycorr in Lv1_barycorr diff --git a/Lv2_presto_subroutines.py b/Lv2_presto_subroutines.py index 592e137..ffc5db7 100644 --- a/Lv2_presto_subroutines.py +++ b/Lv2_presto_subroutines.py @@ -2,17 +2,16 @@ # -*- coding: utf-8 -*- """ Created on Mon May 27 6:22pm 2019 - Program for doing mkgti, niextract-events, nicerfits2presto, padding, calculate duty cycle, realfft, accelsearch, prepfold, and ps2pdf! This is for when we want to split the original time series up into segments (whether by energy or time) Use Lv2_presto_all.py instead if you want to do the analysis for the whole time series. - """ from __future__ import division, print_function import numpy as np from astropy.io import fits -import Lv0_dirs,Lv2_mkdir +import Lv0_dirs,Lv1_data_gtis,Lv2_mkdir +from scipy import stats from tqdm import tqdm import os from os.path import relpath @@ -28,12 +27,12 @@ def get_gti_file(eventfile,segment_length): """ Creating the individual .gti files for my data segments! - eventfile - path to the event file. Will extract ObsID from this for the NICER files. segment_length - length of the individual segments for combining power spectra """ parent_folder = str(pathlib.Path(eventfile).parent) gtis = fits.open(eventfile)[2].data + times = fits.open(eventfile)[1].data['TIME'] Tobs_start = gtis[0][0] #MJD for the observation start time Tobs_end = gtis[-1][1] #MJD for the observation end time @@ -41,13 +40,78 @@ def get_gti_file(eventfile,segment_length): segment_times = np.arange(Tobs_start,Tobs_end+segment_length,segment_length) #array of time values, starting #Jul 10 2019: also added Tobs_end+segment_length instead of Tobs_end, to get that final piece of data + binned_counts, bin_edges, binnumber = stats.binned_statistic(times,np.ones(len(times)),statistic='sum',bins=segment_times) + #bin edges defined by left boundary + + gtilist = open(parent_folder + '/segment_GTI.list','w') + gti_folder = parent_folder + '/gtis/' Lv2_mkdir.makedir(gti_folder) - for i in tqdm(range(len(segment_times)-1)): - gti_file = gti_folder + str(segment_length) + 's_GTI' + str(i) + '.gti' - #print(str(segment_times[i]),str(segment_times[i+1])) - subprocess.run(['mkgti.py','--gtiname',gti_file,str(segment_times[i]),str(segment_times[i+1])] ) - #no need to do 'startmet=', 'stopmet=', but make sure I do it in the right order! + for i in tqdm(range(len(bin_edges)-1)): + gtilist.write('GTI'+str(i).zfill(6)+ ' ' + str(bin_edges[i]) + '\n') + gti_file = gti_folder + str(segment_length).zfill(5) + 's_GTI' + str(i).zfill(6) + '.gti' + if binned_counts[i] != 0 and os.path.exists(gti_file)==False: #prevents from processing GTIs with no counts + #print(str(segment_times[i]),str(segment_times[i+1])) + subprocess.run(['mkgti.py','--gtiname',gti_file,str(segment_times[i]),str(segment_times[i+1])] ) + #no need to do 'startmet=', 'stopmet=', but make sure I do it in the right order! + + gtilist.close() + + return + +def niextract_gti(eventfile,gap,gtifile): + """ + Using niextract-events to get segmented data based on the individual GTIs created with + GTI_bunching in Lv1_data_gtis. + + eventfile - path to the event file. Will extract ObsID from this for the NICER files. + gap - maximum separation between end time of 1st GTI and start time of 2nd GTI allowed + gtifile - name of GTI file + """ + parent_folder = str(pathlib.Path(eventfile).parent) + Lv1_data_gtis.GTI_bunching(eventfile,gap,gtifile) + + gtis = list(fits.open(parent_folder+'/'+gtifile)[1].data) + niextract_folder = parent_folder + '/accelsearch_GTIs/' + Lv2_mkdir.makedir(niextract_folder) + for i in tqdm(range(len(gtis))): + gti_start = gtis[i][0] + gti_end = gtis[i][1] + if os.path.exists(niextract_folder+'GTI'+str(i+1).zfill(6)+'.gti') == False: + subprocess.run(['mkgti.py','--gtiname',niextract_folder+'GTI'+str(i+1).zfill(6)+'.gti',str(gti_start),str(gti_end)]) + + niextract_output = niextract_folder+str(pathlib.Path(eventfile).name)[:-4]+'_GTI'+str(i+1).zfill(6)+'.evt' + if os.path.exists(niextract_output)==False: + subprocess.run(['niextract-events',eventfile,niextract_output,'timefile='+niextract_folder+'GTI'+str(i+1).zfill(6)+'.gti']) + + return + +def niextract_gti_E(eventfile,gap,gtifile,PI1,PI2): + """ + Using niextract-events to get segmented data based on the individual GTIs created with + GTI_bunching in Lv1_data_gtis, AND with energy cuts + + eventfile - path to the event file. Will extract ObsID from this for the NICER files. + gap - maximum separation between end time of 1st GTI and start time of 2nd GTI allowed + gtifile - name of GTI file + PI1 - lower bound of PI (not energy in keV!) desired for the energy range + PI2 - upper bound of PI (not energy in keV!) desired for the energy range + """ + parent_folder = str(pathlib.Path(eventfile).parent) + Lv1_data_gtis.GTI_bunching(eventfile,gap,gtifile) + + gtis = list(fits.open(parent_folder+'/'+gtifile)[1].data) + niextract_folder = parent_folder + '/accelsearch_GTIs/' + Lv2_mkdir.makedir(niextract_folder) + for i in tqdm(range(len(gtis))): + gti_start = gtis[i][0] + gti_end = gtis[i][1] + if os.path.exists(niextract_folder+'GTI'+str(i+1).zfill(6)+'.gti') == False: + subprocess.run(['mkgti.py','--gtiname',niextract_folder+'GTI'+str(i+1).zfill(6)+'.gti',str(gti_start),str(gti_end)]) + + niextract_output = niextract_folder+str(pathlib.Path(eventfile).name)[:-4]+'_GTI'+str(i+1).zfill(6)+'_E' + str(PI1).zfill(4) + '-' + str(PI2).zfill(4) + '.evt' + if os.path.exists(niextract_output)==False: + subprocess.run(['niextract-events',eventfile+'[PI='+str(PI1)+':'+str(PI2)+']',niextract_output,'timefile='+niextract_folder+'GTI'+str(i+1).zfill(6)+'.gti']) return @@ -55,12 +119,12 @@ def niextract_gti_time(eventfile,segment_length): """ Using niextract-events to get segmented data based on the [segment_length]-length GTIs that were created above! - eventfile - path to the event file. Will extract ObsID from this for the NICER files. segment_length - length of the individual segments for combining power spectra """ parent_folder = str(pathlib.Path(eventfile).parent) gtis = fits.open(eventfile)[2].data + times = fits.open(eventfile)[1].data['TIME'] event_header = fits.open(eventfile)[1].header obj_name = event_header['OBJECT'] @@ -76,21 +140,26 @@ def niextract_gti_time(eventfile,segment_length): #Also had Tobs_end+segment_length to get the last section of data. It's ok if it's short, will zero-pad in #edit_binary! Done Jul 10. + binned_counts, bin_edges, binnumber = stats.binned_statistic(times,np.ones(len(times)),statistic='sum',bins=segment_times) + #bin edges defined by left boundary + niextract_folder = parent_folder + '/accelsearch_' + str(segment_length) + 's/' Lv2_mkdir.makedir(niextract_folder) for i in tqdm(range(len(segment_times)-1)): - outputfile = niextract_folder + 'ni' + obsid + '_nicersoft_bary_GTI'+str(i)+'_'+str(segment_length)+'s.evt' - if 'merged' in parent_folder: - merged_id = str(pathlib.Path(eventfile).name)[:12] - outputfile = niextract_folder + merged_id + '_nicersoft_bary_GTI' + str(i) + '_' + str(segment_length) + 's.evt' - subprocess.run(['niextract-events',eventfile,outputfile,'timefile='+parent_folder+'/gtis/'+str(segment_length)+'s_GTI'+str(i)+'.gti']) + if binned_counts[i] != 0: #prevents from processing GTIs with no counts + outputfile = niextract_folder + 'ni' + obsid + '_nicersoft_bary_GTI'+str(i).zfill(6)+'_'+str(segment_length).zfill(5)+'s.evt' + if 'merged' in parent_folder: + merged_id = str(pathlib.Path(eventfile).name)[:12] + outputfile = niextract_folder + merged_id + '_nicersoft_bary_GTI' + str(i).zfill(6) + '_' + str(segment_length).zfill(5) + 's.evt' + + if os.path.exists(outputfile)==False: + subprocess.run(['niextract-events',eventfile,outputfile,'timefile='+parent_folder+'/gtis/'+str(segment_length).zfill(5)+'s_GTI'+str(i).zfill(6)+'.gti']) return def niextract_gti_energy(eventfile,PI1,PI2): """ Using niextract-events to get segmented data based on the energy range - eventfile - path to the event file. Will extract ObsID from this for the NICER files. PI1 - lower bound of PI (not energy in keV!) desired for the energy range PI2 - upper bound of PI (not energy in keV!) desired for the energy range @@ -104,9 +173,10 @@ def niextract_gti_energy(eventfile,PI1,PI2): niextract_folder = parent_folder + '/accelsearch_E/' Lv2_mkdir.makedir(niextract_folder) - output_file = niextract_folder + eventfile.split('/')[-1][:-4] + '_E'+str(PI1)+'-'+str(PI2)+'.evt' + output_file = niextract_folder + eventfile.split('/')[-1][:-4] + '_E'+str(PI1).zfill(4)+'-'+str(PI2).zfill(4)+'.evt' - subprocess.run(['niextract-events',eventfile+'[PI='+str(PI1)+':'+str(PI2)+']',output_file]) + if os.path.exists(output_file)==False: + subprocess.run(['niextract-events',eventfile+'[PI='+str(PI1)+':'+str(PI2)+']',output_file]) return @@ -114,7 +184,6 @@ def niextract_gti_time_energy(eventfile,segment_length,PI1,PI2): """ Using niextract-events to get segmented data based on [segment_length]-length GTIs that were created above, AND energy range! - eventfile - path to the event file. Will extract ObsID from this for the NICER files. segment_length - length of the individual segments for combining power spectra PI1 - lower bound of PI (not energy in keV!) desired for the energy range @@ -122,6 +191,7 @@ def niextract_gti_time_energy(eventfile,segment_length,PI1,PI2): """ parent_folder = str(pathlib.Path(eventfile).parent) gtis = fits.open(eventfile)[2].data + times = fits.open(eventfile)[1].data['TIME'] event_header = fits.open(eventfile)[1].header obj_name = event_header['OBJECT'] @@ -136,52 +206,73 @@ def niextract_gti_time_energy(eventfile,segment_length,PI1,PI2): segment_times = np.arange(Tobs_start,Tobs_end+segment_length,segment_length) #array of time values, starting #Jul 10: added Tobs_end + segment_length to get that final piece of data + binned_counts, bin_edges, binnumber = stats.binned_statistic(times,np.ones(len(times)),statistic='sum',bins=segment_times) + #bin edges defined by left boundary + niextract_folder = parent_folder + '/accelsearch_' + str(segment_length) + 's/' Lv2_mkdir.makedir(niextract_folder) for i in tqdm(range(len(segment_times)-1)): - outputfile = niextract_folder + 'ni' + obsid + '_nicersoft_bary_GTI'+str(i)+'_'+str(segment_length)+'s_' + 'E'+str(PI1)+'-'+str(PI2)+'.evt' - if 'merged' in parent_folder: - merged_id = str(pathlib.Path(eventfile).name)[:12] - outputfile = niextract_folder + merged_id + '_nicersoft_bary_GTI' + str(i) + '_' + str(segment_length) + 's_E' + str(PI1) + '-' + str(PI2) + '.evt' - subprocess.run(['niextract-events',eventfile+'[PI='+str(PI1)+':'+str(PI2)+']',outputfile,'timefile='+parent_folder+'/gtis/'+str(segment_length)+'s_GTI'+str(i)+'.gti']) + if binned_counts[i] != 0: #prevents from processing GTIs with no counts + outputfile = niextract_folder + 'ni' + obsid + '_nicersoft_bary_GTI'+str(i).zfill(6)+'_'+str(segment_length).zfill(5)+'s_' + 'E'+str(PI1).zfill(4)+'-'+str(PI2).zfill(4)+'.evt' + if 'merged' in parent_folder: + merged_id = str(pathlib.Path(eventfile).name)[:12] + outputfile = niextract_folder + merged_id + '_nicersoft_bary_GTI' + str(i).zfill(6) + '_' + str(segment_length).zfill(5) + 's_E' + str(PI1).zfill(4) + '-' + str(PI2).zfill(4) + '.evt' + if os.path.exists(outputfile)==False: + subprocess.run(['niextract-events',eventfile+'[PI='+str(PI1)+':'+str(PI2)+']',outputfile,'timefile='+parent_folder+'/gtis/'+str(segment_length).zfill(5)+'s_GTI'+str(i).zfill(6)+'.gti']) return -def do_nicerfits2presto(eventfile,tbin,segment_length): +def do_nicerfits2presto(eventfile,tbin,segment_length,mode): """ Using nicerfits2presto.py to bin the data, and to convert into PRESTO-readable format. I can always move files to different folders to prevent repeats (especially for large files) - eventfile - path to the event file. Will extract ObsID from this for the NICER files. tbin - size of the bins in time segment_length - length of the individual segments for combining power spectra + mode - "all", "t", "gtis" or "E" ; basically to tell the function where to access files to run realfft for """ parent_folder = str(pathlib.Path(eventfile).parent) event_header = fits.open(eventfile)[1].header obj_name = event_header['OBJECT'] obsid = event_header['OBS_ID'] - if segment_length == 0: #for non-segmented event file + if mode == "all": #for non-segmented event file subprocess.run(['nicerfits2presto.py','--dt='+str(tbin),eventfile]) - else: + if mode == "E": E_files = glob.glob(parent_folder+'/accelsearch_E/*.evt') - time_files = glob.glob(parent_folder+'/accelsearch_' + str(segment_length) + 's/*.evt') - if len(E_files) != 0: #if E_files is not empty for i in tqdm(range(len(E_files))): + if os.path.exists(E_files[i][:-3] + 'dat'): + continue try: subprocess.run(['nicerfits2presto.py','--dt='+str(tbin),E_files[i]]) except (ValueError,subprocess.CalledProcessError): pass + + if mode == 't': + time_files = glob.glob(parent_folder+'/accelsearch_' + str(segment_length) + 's/*.evt') if len(time_files) != 0: for i in tqdm(range(len(time_files))): + if os.path.exists(time_files[i][:-3] + 'dat'): + continue try: subprocess.run(['nicerfits2presto.py','--dt='+str(tbin),time_files[i]]) except (ValueError,subprocess.CalledProcessError): pass + if mode == "gtis": + gti_files = glob.glob(parent_folder+'/accelsearch_GTIs/*.evt') + if len(gti_files) != 0: + for i in tqdm(range(len(gti_files))): + if os.path.exists(gti_files[i][:-3] + 'dat'): + continue + try: + subprocess.run(['nicerfits2presto.py','--dt='+str(tbin),gti_files[i]]) + except (ValueError,subprocess.CalledProcessError): + pass + ##### will probably remove once I know to either NOT work in nicerpy_xrayanalysis, ##### and/or install my packages such that I can run the scripts from anywhere ##### in the terminal! @@ -190,12 +281,14 @@ def do_nicerfits2presto(eventfile,tbin,segment_length): if 'merged' in eventfile: presto_files = glob.glob('merged*') for i in range(len(presto_files)): - if segment_length == 0: + if mode == "all": subprocess.run(['mv',presto_files[i],parent_folder+'/']) - elif 'GTI' in presto_files[i]: + if mode == "t": subprocess.run(['mv',presto_files[i],parent_folder+'/accelsearch_' + str(segment_length) + 's/']) - else: + if mode == "E": subprocess.run(['mv',presto_files[i],parent_folder+'/accelsearch_E/']) + if mode == "gtis": + subprocess.run(['mv',presto_files[i],parent_folder+'/accelsearch_GTIs/']) return @@ -204,17 +297,17 @@ def edit_inf(eventfile,tbin,segment_length): Editing the .inf file, as it seems like accelsearch uses some information from the .inf file! Mainly need to edit the "Number of bins in the time series". This is only for when we make segments by time though! - eventfile - path to the event file. Will extract ObsID from this for the NICER files. tbin - size of the bins in time segment_length - length of the individual segments """ parent_folder = str(pathlib.Path(eventfile).parent) event_header = fits.open(eventfile)[1].header - obj_name = event_header['OBJECT'] - obsid = event_header['OBS_ID'] + #obj_name = event_header['OBJECT'] + #obsid = event_header['OBS_ID'] - inf_files = sorted(glob.glob(parent_folder + '/accelsearch_' + str(segment_length) + 's/*GTI*' + str(segment_length)+'s*.inf')) #not the .evt file; some .evt files will be empty + inf_files = sorted(glob.glob(parent_folder + '/accelsearch_' + str(segment_length) + 's/*GTI*' + str(segment_length).zfill(5)+'s*.inf')) #not the .evt file; some .evt files will be empty + #inf_files = sorted(glob.glob(parent_folder + '/accelsearch_GTIs/*GTI*.inf')) #not the .evt file; some .evt files will be empty no_desired_bins = float(segment_length)/float(tbin) @@ -243,17 +336,18 @@ def edit_binary(eventfile,tbin,segment_length): The value to pad with for each time bin, is the average count rate in THAT segment! Jul 10: Do zero-padding instead... so that number of counts is consistent! Again, this is only for when we make segments by time! - eventfile - path to the event file. Will extract ObsID from this for the NICER files. tbin - size of the bins in time segment_length - length of the individual segments """ parent_folder = str(pathlib.Path(eventfile).parent) event_header = fits.open(eventfile)[1].header - obj_name = event_header['OBJECT'] - obsid = event_header['OBS_ID'] + #obj_name = event_header['OBJECT'] + #obsid = event_header['OBS_ID'] + + dat_files = sorted(glob.glob(parent_folder + '/accelsearch_' + str(segment_length) + 's/*GTI*' + str(segment_length).zfill(5) + 's*.dat')) #not that order matters here I think, but just in case + #dat_files = sorted(glob.glob(parent_folder + '/accelsearch_GTIs/*GTI*.dat')) #not that order matters here I think, but just in case - dat_files = sorted(glob.glob(parent_folder + '/accelsearch_' + str(segment_length) + 's/*GTI*' + str(segment_length) + 's*.dat')) #not that order matters here I think, but just in case for i in tqdm(range(len(dat_files))): bins = np.fromfile(dat_files[i],dtype='0]) #number of bins with data (NOT the ones with averaged count rate!) @@ -276,10 +370,9 @@ def edit_binary(eventfile,tbin,segment_length): def realfft(eventfile,segment_length,mode): """ Performing PRESTO's realfft on the binned data (.dat) - eventfile - path to the event file. Will extract ObsID from this for the NICER files. segment_length - length of the individual segments - mode - "all", "t" or "E" ; basically to tell the function where to access files to run realfft for + mode - "all", "t", "gtis", or "E" ; basically to tell the function where to access files to run realfft for """ parent_folder = str(pathlib.Path(eventfile).parent) @@ -292,16 +385,20 @@ def realfft(eventfile,segment_length,mode): elif mode == "E": dat_files = sorted(glob.glob(parent_folder+'/accelsearch_E/*.dat')) logfile = parent_folder + '/accelsearch_E/realfft_E.log' + elif mode == "gtis": + dat_files = sorted(glob.glob(parent_folder+'/accelsearch_GTIs/*.dat')) + logfile = parent_folder + '/accelsearch_GTIs/realfft_gtis.log' else: - raise ValueError("mode should either of 'all', 't', or 'E'!") + raise ValueError("mode should either of 'all', 't', 'gtis', or 'E'!") print("Running realfft now:") with open(logfile,'w') as logtextfile: for i in tqdm(range(len(dat_files))): - output = subprocess.run(['realfft',dat_files[i]],capture_output=True,text=True) - logtextfile.write(output.stdout) - logtextfile.write('*------------------------------* \n') - logtextfile.write(output.stderr) + if os.path.exists(dat_files[i][:-3] + 'fft')==False: + output = subprocess.run(['realfft',dat_files[i]],capture_output=True,text=True) + logtextfile.write(output.stdout) + logtextfile.write('*------------------------------* \n') + logtextfile.write(output.stderr) logtextfile.close() return @@ -309,10 +406,9 @@ def realfft(eventfile,segment_length,mode): def accelsearch(eventfile,segment_length,mode,flags): """ Performing PRESTO's accelsearch on the FFT data (.fft) - eventfile - path to the event file. Will extract ObsID from this for the NICER files. segment_length - length of the individual segments - mode - "all", "t" or "E" ; basically to tell the function where to access files to run accelsearch for + mode - "all", "t", "gtis" or "E" ; basically to tell the function where to access files to run accelsearch for flags - a LIST of input flags for accelsearch """ if type(flags) != list: @@ -329,12 +425,18 @@ def accelsearch(eventfile,segment_length,mode,flags): elif mode == "E": fft_files = sorted(glob.glob(parent_folder+'/accelsearch_E/*.fft')) logfile = parent_folder + '/accelsearch_E/accelsearch_E.log' + elif mode == "gtis": + fft_files = sorted(glob.glob(parent_folder+'/accelsearch_GTIs/*.fft')) + logfile = parent_folder + '/accelsearch_GTIs/accelsearch_gtis.log' else: - raise ValueError("mode should either of 'all', 't', or 'E'!") + raise ValueError("mode should either of 'all', 't', 'gtis', or 'E'!") + zmax_index = flags.index('-zmax') + zmax_num = str(flags[zmax_index+1]) print("Running accelsearch now:") with open(logfile,'w') as logtextfile: for i in tqdm(range(len(fft_files))): + #if os.path.exists(fft_files[i][:-4] + '_ACCEL_' + zmax_num + '.txtcand') == False: command = ['accelsearch'] + flags + [fft_files[i]] output = subprocess.run(command,capture_output=True,text=True) logtextfile.write(output.stdout) @@ -347,10 +449,9 @@ def accelsearch(eventfile,segment_length,mode,flags): def prepfold(eventfile,segment_length,mode,zmax): """ Performing PRESTO's prepfold on the pulsation candidates. - eventfile - path to the event file. Will extract ObsID from this for the NICER files. segment_length - length of the individual segments - mode - "all", "t" or "E" ; basically to tell the function where to access files to run prepfold for + mode - "all", "t", "gtis", or "E" ; basically to tell the function where to access files to run prepfold for zmax - maximum acceleration """ parent_folder = str(pathlib.Path(eventfile).parent) @@ -364,18 +465,21 @@ def prepfold(eventfile,segment_length,mode,zmax): elif mode == "E": ACCEL_files = sorted(glob.glob(parent_folder+'/accelsearch_E/*ACCEL_'+str(zmax))) logfile = parent_folder + '/accelsearch_E/prepfold.log' + elif mode == "gtis": + ACCEL_files = sorted(glob.glob(parent_folder+'/accelsearch_GTIs/*ACCEL_'+str(zmax))) + logfile = parent_folder + '/accelsearch_GTIs/prepfold.log' else: - raise ValueError("mode should either of 'all', 't', or 'E'!") + raise ValueError("mode should either of 'all', 't', 'gtis', or 'E'!") cand_files = [ACCEL_files[i] + '.cand' for i in range(len(ACCEL_files))] if zmax < 10: - events_files = [cand_files[i][:-11]+'.events' for i in range(len(cand_files))] + events_files = [cand_files[i][:-13]+'.events' for i in range(len(cand_files))] if (zmax >= 10) & (zmax < 100): - events_files = [cand_files[i][:-12]+'.events' for i in range(len(cand_files))] + events_files = [cand_files[i][:-14]+'.events' for i in range(len(cand_files))] if (zmax >= 100) & (zmax < 999): - events_files = [cand_files[i][:-13]+'.events' for i in range(len(cand_files))] + events_files = [cand_files[i][:-15]+'.events' for i in range(len(cand_files))] else: - events_files = [cand_files[i][:-14]+'.events' for i in range(len(cand_files))] + events_files = [cand_files[i][:-16]+'.events' for i in range(len(cand_files))] header1 = " Summed Coherent Num Period Frequency FFT 'r' Freq Deriv FFT 'z' Accel " header2 = " Power / Raw FFT 'r' Pred 'r' FFT 'z' Pred 'z' Phase Centroid Purity " @@ -389,8 +493,8 @@ def prepfold(eventfile,segment_length,mode,zmax): cand_relpath = relpath(cand_files[i],parent_folder) #relative path of .cand file ; PRESTO doesn't like using absolute paths events_relpath = relpath(events_files[i],parent_folder) #relative path of .events file ; PRESTO doesn't like using absolute paths - for j in range(min(100,no_cands)): #to control the number of outputs! Sometimes there can be thousands of candidates - insane! - command = 'cd ' + parent_folder + ' ; prepfold -double -events -noxwin -n 50 -accelcand ' + str(j+1) + ' -accelfile ' + cand_relpath + ' ' + events_relpath + for j in range(min(50,no_cands)): #to control the number of outputs! Sometimes there can be thousands of candidates - insane! + command = 'cd ' + parent_folder + ' ; prepfold -double -events -noxwin -n 20 -accelcand ' + str(j+1) + ' -accelfile ' + cand_relpath + ' ' + events_relpath output = subprocess.run(command,shell=True,capture_output=True,text=True) logtextfile.write(output.stdout) logtextfile.write('*------------------------------* \n') @@ -399,12 +503,63 @@ def prepfold(eventfile,segment_length,mode,zmax): return +def filter_accelsearch(eventfile,mode,min_freq,zmax): + """ + Added on 8/31/2020. To filter out the ACCEL files by displaying a list of candidates + that have met a frequency threshold (to avoid very low frequency candidates, really) + + The files will have been generated via prepfold already - perhaps in the future, I may + only run prepfold on candidates I want! Maybe do this to avoid having too many candidates... + + eventfile - path to the event file. Will extract ObsID from this for the NICER files. + mode - "all", "t", "gtis", or "E" ; basically to tell the function where to access files to run prepfold for + min_freq - minimum frequency to include in the list + zmax - maximum acceleration + """ + parent_folder = str(pathlib.Path(eventfile).parent) + + if mode == "all": + ACCEL_files = sorted(glob.glob(parent_folder+'/*ACCEL_'+str(zmax))) + elif mode == "t": + ACCEL_files = sorted(glob.glob(parent_folder+'/accelsearch_'+str(segment_length)+'s/*ACCEL_'+str(zmax))) + elif mode == "E": + ACCEL_files = sorted(glob.glob(parent_folder+'/accelsearch_E/*ACCEL_'+str(zmax))) + elif mode == "gtis": + ACCEL_files = sorted(glob.glob(parent_folder+'/accelsearch_GTIs/*ACCEL_'+str(zmax))) + else: + raise ValueError("mode should either of 'all', 't', 'gtis', or 'E'!") + + ### below are just the headers in the *ACCEL_100 files ; the intention is just to get the indices for these lines later on + header1 = " Summed Coherent Num Period Frequency FFT 'r' Freq Deriv FFT 'z' Accel " + header2 = " Power / Raw FFT 'r' Pred 'r' FFT 'z' Pred 'z' Phase Centroid Purity " + + output_file = open(str(pathlib.Path(ACCEL_files[0]).parent) + '/ACCEL_' + str(zmax) + '_cands_minfreq_' + str(min_freq) + '.txt','w') + output_file.write(header1 + '\n') + + for i in range(len(ACCEL_files)): + freqs = [] + accel_textfile = np.array(open(ACCEL_files[i],'r').read().split('\n')) #read the data from the ACCEL_$zmax files + index_header1 = np.where(accel_textfile==header1)[0][0] #index for "Summed, Coherent, Num, Period etc + index_header2 = np.where(accel_textfile==header2)[0][0] #index for "Power / Raw FFT 'r' etc + no_cands = index_header2 - index_header1 - 5 #to obtain number of candidates + for j in range(no_cands): + freq = float(accel_textfile[j+3].split()[6][:-3]) + freqs.append(freq) + if not any(np.array(freqs)>min_freq): #if none are above the minimum frequency + continue + else: + output_file.write(str(pathlib.Path(ACCEL_files[i]).name) + '\n') + for j in range(no_cands): + freq = float(accel_textfile[j+3].split()[6][:-3]) + if freq >= min_freq: + output_file.write(accel_textfile[j+3] + '\n') + output_file.close() + def ps2pdf(eventfile,segment_length,mode): """ Converting from .ps to .pdf - eventfile - path to the event file. Will extract ObsID from this for the NICER files. - mode - "all", "t" or "E" ; basically to tell the function where to access files to run ps2pdf for + mode - "all", "t", "gtis", or "E" ; basically to tell the function where to access files to run ps2pdf for """ parent_folder = str(pathlib.Path(eventfile).parent) @@ -414,8 +569,10 @@ def ps2pdf(eventfile,segment_length,mode): ps_files = sorted(glob.glob(parent_folder+'/accelsearch_'+str(segment_length)+'s/*ps')) elif mode == "E": ps_files = sorted(glob.glob(parent_folder+'/accelsearch_E/*ps')) + elif mode == "gtis": + ps_files = sorted(glob.glob(parent_folder+'/accelsearch_GTIs/*ps')) else: - raise ValueError("mode should either of 'all', 't', or 'E'!") + raise ValueError("mode should either of 'all', 't', 'gtis', or 'E'!") print('Running ps2pdf now!') for i in tqdm(range(len(ps_files))): @@ -426,7 +583,11 @@ def ps2pdf(eventfile,segment_length,mode): return if __name__ == "__main__": - eventfile = Lv0_dirs.NICERSOFT_DATADIR + '1034070101_pipe/ni1034070101_nicersoft_bary.evt' + #eventfile = Lv0_dirs.NICERSOFT_DATADIR + '1034070101_pipe/ni1034070101_nicersoft_bary.evt' + #eventfile = Lv0_dirs.NICER_DATADIR + 'xtej1739/2002131540_bary.evt' + + gap = 5 + gtifile = Lv0_dirs.NICER_DATADIR + 'xtej1739/bunched.gti' mode = 't' segment_length = 100 PI1 = 100 @@ -437,17 +598,32 @@ def ps2pdf(eventfile,segment_length,mode): accelsearch_flags = ['-numharm','4','-zmax','100','-photon','-flo','1','-fhi','1000'] - get_gti_file(eventfile,segment_length) - niextract_gti_time(eventfile,segment_length) - niextract_gti_energy(eventfile,PI1,PI2) - niextract_gti_time_energy(eventfile,segment_length,PI1,PI2) - do_nicerfits2presto(eventfile,tbin,segment_length) - edit_inf(eventfile,tbin,segment_length) - edit_binary(eventfile,tbin,segment_length) - realfft(eventfile,segment_length,mode) - accelsearch(eventfile,segment_length,mode,accelsearch_flags) - prepfold(eventfile,mode,zmax) - ps2pdf(eventfile,mode) + #get_gti_file(eventfile,segment_length) + #niextract_gti(eventfile,gap,gtifile) + #niextract_gti_time(eventfile,segment_length) + #niextract_gti_energy(eventfile,PI1,PI2) + #niextract_gti_time_energy(eventfile,segment_length,PI1,PI2) + #do_nicerfits2presto(eventfile,tbin,segment_length) + #edit_inf(eventfile,tbin,segment_length) + #edit_binary(eventfile,tbin,segment_length) + #realfft(eventfile,segment_length,mode) + #accelsearch(eventfile,segment_length,mode,accelsearch_flags) + #prepfold(eventfile,mode,zmax) + #ps2pdf(eventfile,mode) #testfile = '/Volumes/Samsung_T5/NICERsoft_outputs/1034070101_pipe/niextract/ni1034070101_nicersoft_bary_GTI0_100s.dat' #bins = np.fromfile(testfile,dtype='= mjd1 and obs_time <= mjd2: + truncated_eventlist.append(ordered_eventlist[i]) + + return truncated_eventlist + + else: + return ordered_eventlist + +def att_file_use(eventfile): + """ + For a given event file, determines what attitude file to use + + eventfile - path to the event file + """ + obsid = str(pathlib.Path(eventfile).name)[:13] + + attflag = fits.open(eventfile)[1].header['ATTFLAG'] + if attflag == '110': + return '/Volumes/Samsung_T5/NGC300_ULX_Swift/auxil/' + obsid + 'pat.fits.gz' + elif attflag == '100': + return '/Volumes/Samsung_T5/NGC300_ULX_Swift/auxil/' + obsid + 'sat.fits.gz' + elif attflag == '111': + return '/Volumes/Samsung_T5/NGC300_ULX_Swift/auxil/' + obsid + 'uat.fits.gz' + +def barycorr(eventfile,outfile,refframe,orbit_file,output_folder): + """ + General function to perform the barycenter corrections for a Swift event file + + eventfile - path to the event file. Will extract ObsID from this for the NICER files. + outfile - path to the output event file with barycenter corrections applied + refframe - reference frame for barycenter corrections (usually ICRS) + orbit_file - path to the orbit file of the observation + output_folder - path to the folder where the outfile will be + """ + obsid = eventfile[2:13] + + logfile = output_folder + 'barycorr_notes.txt' + ra,dec = get_ra_dec(eventfile) + + with open(logfile,'w') as logtextfile: + output = subprocess.run(['barycorr',eventfile,'outfile='+outfile,'orbitfiles='+orbit_file,'ra='+str(ra),'dec='+str(dec),'refframe='+str(refframe),'clobber=YES'],capture_output=True,text=True) + logtextfile.write(output.stdout) + logtextfile.write('*------------------------------* \n') + logtextfile.write(output.stderr) + logtextfile.close() + + return + +def xselect_script(eventlist,regfile,binsize,mjd1,mjd2): + """ + Writes a script so that XSELECT can take in the events, bins them, and + outputs them into a light curve (.lc) form + + eventlist - a list of event files + binsize - desired bin size for the light curve + """ + parent_folder = str(pathlib.Path(eventlist[0]).parent) + script_name = parent_folder + '/xselect_earlier_ulx1_instructions.txt' + + writing = open(script_name,'w') + writing.write('set mission swift' + '\n') + writing.write('set inst xrt' + '\n') + for i in range(len(eventlist)): + if (fits.open(eventlist[i])[1].header['MJD-OBS'] >= mjd1) and (fits.open(eventlist[i])[1].header['MJD-OBS'] <= mjd2): + eventfile = str(pathlib.Path(eventlist[i]).name) + obsid = eventfile[:13] + writing.write('set datadir ' + parent_folder + '\n') + writing.write('read events ' + eventfile + '\n') + writing.write('filter region ' + regfile + '\n') + writing.write('extract curve binsize=' + str(binsize) + '\n') + writing.write('save curve ' + obsid + '_ulx1.lc' + '\n') + writing.write('clear data' + '\n') + writing.write('clear region' + '\n') + writing.write(' ' + '\n') + writing.close() + +def xrtlccorr(event_files,lc_files,att_files,hk_files,mjd1,mjd2): + """ + Runs xrtlccorr to produce the corrected light curves + + event_files - list of the barycenter-corrected event files + lc_files - list of the un-corrected .lc files + att_files - list of barycenter-corrected att_files + hk_files - list of barycenter-corrected hk_files + """ + parent_folder = str(pathlib.Path(lc_files[0]).parent) + instruct_file = parent_folder + '/xrtlccorr_earlier_ulx1_instruc.txt' + + ordered_events = time_order(event_files,0,0) + ordered_lc = time_order(lc_files,0,0) + ordered_att = time_order(att_files,0,0) + ordered_hk = time_order(hk_files,0,0) + + writing = open(instruct_file,'w') + for i in range(len(ordered_lc)): + if (fits.open(ordered_lc[i])[1].header['MJD-OBS']>=mjd1) and (fits.open(ordered_lc[i])[1].header['MJD-OBS']<=mjd2): + outfile = ordered_lc[i][:-3] + '_corr.lc' + output = 'xrtlccorr'+ ' lcfile='+ordered_lc[i] + ' regionfile=NONE' + ' outfile='+outfile + ' corrfile=DEFAULT' + ' attfile='+ordered_att[i] + ' hdfile='+ordered_hk[i] + ' outinstrfile=DEFAULT' + ' pcnframe=0' + ' psfflag=yes' + ' energy=1.0' + ' createinstrmap=yes' + ' infile='+ordered_events[i] + ' clobber=yes' + writing.write(output + '\n') + writing.close() + +def lcmath(corr_lc_files,corr_bg_files,bg_scale): + """ + Running lcmath to do background subtraction on the xrtlccorr-corrected light curves + + corr_lc_files - list of corrected sw*_corr.lc files + corr_bg_files - list of corrected sw*_bg_corr.lc files + bg_scale - scaling factor for background + """ + parent_folder = str(pathlib.Path(corr_lc_files[0]).parent) + lcmath = open(parent_folder + '/lcmath_instruct.txt','w') + + for i in range(len(corr_lc_files)): + inputfile = corr_lc_files[i] + bgfile = corr_bg_files[i] + outputfile = corr_lc_files[i][:-7] + 'bgsub_corr.lc' + lcmath.write('lcmath ' + 'infile='+str(inputfile) + ' bgfile=' + bgfile + ' outfile=' + outputfile + ' multi=1' + ' multb=' + str(bg_scale) + ' addsubr=no' + ' err_mode=2' + '\n') + + lcmath.close() + +def get_bgsub(corr_lc_files,corr_bg_files,bg_scale): + """ + Getting background-subtracted light curves in the case of low counts (i.e., + cannot use lcmath!) + + corr_lc_files - list of corrected sw*_corr.lc files + corr_bg_files - list of corrected sw*_bg_corr.lc files + bg_scale - scaling factor for background + """ + lc_start_times = [fits.open(corr_lc_files[i])[1].header['TIMEZERO'] for i in range(len(corr_lc_files))] + lc_time_ordered = np.argsort(lc_start_times) + lc_ordered_eventlist = np.array(corr_lc_files)[lc_time_ordered] + + lc_times = [] + lc_rates = [] + lc_errors = [] + lc_fracexp = [] + for i in tqdm(range(len(lc_ordered_eventlist))): #getting every corrected light curve FITS file + data_arrays = fits.open(lc_ordered_eventlist[i])[1].data + tstart = fits.open(lc_ordered_eventlist[i])[1].header['TIMEZERO'] #get TIMEZERO + lc_times += list(tstart+data_arrays['TIME']) #add to an overall list, the 'TIME' array from the corrected light curve FITS file, plus timezero + lc_rates += list(data_arrays['RATE']) #get the corresponding column for the rates + lc_errors += list(data_arrays['ERROR']) #get the corresponding column for the errors + lc_fracexp += list(data_arrays['FRACEXP']) #get the corresponding column for the fractional exposure + + lc_times = np.array(lc_times) + lc_trunc_times = lc_times-lc_times[0] + lc_rates = np.array(lc_rates) + lc_errors = np.array(lc_errors) + lc_fracexp = np.array(lc_fracexp) + + ########## + + bg_start_times = [fits.open(corr_bg_files[i])[1].header['TIMEZERO'] for i in range(len(corr_bg_files))] + bg_time_ordered = np.argsort(bg_start_times) + bg_ordered_eventlist = np.array(corr_bg_files)[bg_time_ordered] + + bg_times = [] + bg_rates = [] + bg_errors = [] + bg_fracexp = [] + for i in tqdm(range(len(bg_ordered_eventlist))): #getting every corrected light curve FITS file + data_arrays = fits.open(bg_ordered_eventlist[i])[1].data + tstart = fits.open(bg_ordered_eventlist[i])[1].header['TIMEZERO'] #get TIMEZERO + bg_times += list(tstart+data_arrays['TIME']) #add to an overall list, the 'TIME' array from the corrected light curve FITS file, plus timezero + bg_rates += list(data_arrays['RATE']) #get the corresponding column for the rates + bg_errors += list(data_arrays['ERROR']) #get the corresponding column for the errors + bg_fracexp += list(data_arrays['FRACEXP']) #get the corresponding column for the fractional exposure + + bg_times = np.array(bg_times) + bg_trunc_times = bg_times-bg_times[0] + bg_rates = np.array(bg_rates) + bg_errors = np.array(bg_errors) + bg_fracexp = np.array(bg_fracexp) + + ########## + if False in lc_times==bg_times: + return 'lc_times is not equal to bg_times!' + + if False in lc_fracexp==bg_fracexp: + return 'lc_fracexp is not aequal to bg_fracexp!' + + new_rates = lc_rates - bg_rates*bg_scale + new_errors = np.sqrt(lc_errors**2 + (bg_scale*bg_errors)**2) + + #for i in range(100): + # print(i,lc_rates[i],bg_rates[i],new_rates[i],lc_errors[i],bg_errors[i],new_errors[i]) + + return lc_times,new_rates,new_errors,lc_fracexp + + +if __name__ == "__main__": + eventlist = glob.glob('/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/sw*pc*po_cl.evt') + #eventlist = ['/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/sw00049834027xpcw3po_cl.evt','/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/sw00049834087xpcw3po_cl.evt'] + bary_outputfolder = '/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/lightcurve/' + trunc_eventlist = time_order(eventlist,57739.00,58238.99) #originally was 58239 to 58605 + + do_barycorr = False + + if do_barycorr == True: + print('Doing barycenter corrections...') + for i in tqdm(range(len(trunc_eventlist))): + inputfile = trunc_eventlist[i] + obsid = str(pathlib.Path(inputfile).name)[:13] + + outputfile = bary_outputfolder + str(pathlib.Path(inputfile).name)[:20] + '_bary_cl.evt' + orbitfile = '/Volumes/Samsung_T5/NGC300_ULX_Swift/auxil/' + obsid + 'sao.fits' + + attfile = att_file_use(trunc_eventlist[i]) + output_attfile = bary_outputfolder + str(pathlib.Path(attfile).name)[:16] + '_bary.fits' + + hkfile = '/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/hk/' + obsid + 'xhd.hk.gz' + output_hkfile = bary_outputfolder + obsid + '_bary_xhd.hk.gz' + + ### applying barycenter corrections to the hd hk file + barycorr(hkfile,output_hkfile,'ICRS',orbitfile,bary_outputfolder) + + ### applying barycenter corrections to the attitude file + barycorr(attfile,output_attfile,'ICRS',orbitfile,bary_outputfolder) + + ### applying barycenter corrections to the event file + barycorr(inputfile,outputfile,'ICRS',orbitfile,bary_outputfolder) + + bary_eventlist = glob.glob(bary_outputfolder + 'sw*bary_cl.evt') + #xselect_script(bary_eventlist,'/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/ngc300ulx1.reg',10,57739.00,58238.99) + + #xrtlccorr(glob.glob(bary_outputfolder+'sw*bary_cl.evt'),glob.glob(bary_outputfolder+'sw*_ulx1.lc'),glob.glob(bary_outputfolder+'sw*at_bary.fits'),glob.glob(bary_outputfolder+'sw*_bary_*hd*hk*'),57739.00,58238.99) + + #obsids = [str(i) for i in range(49834027,49834042)] + [str(i) for i in range(49834043,49834062)] + [str(i) for i in range(49834063,49834066)] + ['88810002'] + [str(i) for i in range(49834066,49834069)] + [str(i) for i in range(49834070,49834079)] + [str(i) for i in range(49834080,49834088)] + #corr_lc_files = [bary_outputfolder + 'sw000' + obsids[i] + '_corr.lc' for i in range(len(obsids))] + #corr_bg_files = [bary_outputfolder + 'sw000' + obsids[i] + '_bg_corr.lc' for i in range(len(obsids))] + #bg_scale = (30/120)**2 + + #lcmath(corr_lc_files,corr_bg_files,bg_scale) + #new_times,new_rates,new_errs = get_bgsub(corr_lc_files,corr_bg_files,bg_scale) diff --git a/Lv3_B1957+20_merged.py b/Lv3_B1957+20_merged.py index f2f42c7..bdd9f90 100644 --- a/Lv3_B1957+20_merged.py +++ b/Lv3_B1957+20_merged.py @@ -11,14 +11,52 @@ import numpy as np import time from tqdm import tqdm +from astropy.io import fits import glob +import pathlib import subprocess -import Lv0_dirs -import Lv2_average_ps_methods,Lv2_average_merge_ps_methods -import Lv3_detection_level - import matplotlib.pyplot as plt +from stingray.pulse.pulsar import pulse_phase,phase_exposure,fold_events + +eventfile = '/Volumes/Samsung_T5/NICERsoft_outputs/merged_events/merged000021/merged000021_nicersoft_bary_phase.evt' +times = fits.open(eventfile)[1].data['TIME'] +pulse_phase = fits.open(eventfile)[1].data['PULSE_PHASE'] +gtis = fits.open(eventfile)[2].data +T = sum([ gtis[i]['STOP']-gtis[i]['START'] for i in range(len(gtis)) ]) #exposure time + +gtis_conform = [] +for i in range(len(gtis)): + gtis_conform.append([gtis[i][0],gtis[i][1]]) #conform to the input that Stingray uses + +freq = 622.12202499673376738 +freqdot = -6.5114520166830696246e-15 +freqdotdot = 0 +nbins = 20 + +phase_sr,prof_sr,err_sr = fold_events(times,freq,freqdot,freqdotdot,gtis=np.array(gtis_conform),ref_time=times[0],nbin=nbins) +phase_sr_expo,prof_sr_expo,err_sr_expo = fold_events(times,freq,freqdot,freqdotdot,gtis=np.array(gtis_conform),ref_time=times[0],expocorr=True,nbin=nbins) + +total_phase_sr = list(phase_sr) + list(phase_sr+1) +total_prof_sr = list(prof_sr)*2 +total_err_sr = list(err_sr)*2 + +total_phase_sr_expo = list(phase_sr_expo) + list(phase_sr_expo+1) +total_prof_sr_expo = list(prof_sr_expo)*2 +total_err_sr_expo = list(err_sr_expo)*2 + +plt.figure() +plt.errorbar(x=total_phase_sr,y=total_prof_sr/T,yerr=total_err_sr/T,color='r',drawstyle='steps-mid') +plt.errorbar(x=total_phase_sr_expo,y=total_prof_sr_expo/T,yerr=total_err_sr_expo/T,color='b',drawstyle='steps-mid') +plt.legend(('Folded profile','Exposure-corrected'),loc='best',fontsize=12) +plt.title(str(pathlib.Path(eventfile).name) +', exposure-corrected (using Stingray fold_events)',fontsize=12) +plt.xlabel('Phase',fontsize=12) +plt.ylabel('Counts/s',fontsize=12) +plt.show() + + +""" +DEPRECATED FOR NOW - 8/17 par_file = Lv0_dirs.NICERSOFT_DATADIR + 'B1957+20.par' #parameter file for demodulation T_asc_paper = 51260.200512649951936 @@ -61,7 +99,7 @@ pyfile_contents.close() execfile("Lv3_average_ps_main.py") - +""" """ obsids = ['10301801'+str(i) for i in range(49,58)] diff --git a/Lv3_TBOs.py b/Lv3_TBOs.py index a42eeb8..6c2a475 100644 --- a/Lv3_TBOs.py +++ b/Lv3_TBOs.py @@ -26,17 +26,19 @@ Lv0_dirs.global_par() -eventfiles = ['/Volumes/Samsung_T5/NICERsoft_outputs/1050070103_pipe/ni1050070103_nicersoft_bary.evt'] +#eventfiles = ['/Volumes/Samsung_T5/NICERsoft_outputs/1050070103_pipe/ni1050070103_nicersoft_bary.evt'] +#eventfiles = ['/Volumes/Samsung_T5/NICER-data/xtej1739/2002131540_bary_E200-1200.evt'] +eventfiles = ['/Users/masonng/Documents/MIT/Research/xtej1739_burst8/2002251704_bary.evt'] do_search = False # Searching for burst candidates! do_plots = True # Creating dynamic power spectra and contours -search_window = [16360,16508] #start/end times of burst oscillation search -T = np.array([4]) #window sizes +search_window = [0,350] #start/end times of burst oscillation search +T = np.array([10]) #window sizes dt = T/10 #i.e., do overlapping windows of T seconds in steps of dt seconds -tbin_size = 0.0005 #size of time bins in seconds -df = 5 #tolerance of 10 Hz, say -f_central = 619 #central frequency +tbin_size = 0.00025 #size of time bins in seconds +df = 10 #tolerance of 10 Hz, say +f_central = 561 #central frequency mode = "show" for i in range(len(eventfiles)): diff --git a/Lv3_analyze_time_res_spec.py b/Lv3_analyze_time_res_spec.py new file mode 100644 index 0000000..9af5331 --- /dev/null +++ b/Lv3_analyze_time_res_spec.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +Created on Tues April 14 10:57am 2020 + +Very quick analysis of time-resolved spectroscopy results. I need to generalize this +and the previous scripts (used for NGC300 ULX-1) during the summer...! + +""" +from __future__ import division, print_function +import numpy as np +from astropy.io import fits +import Lv0_dirs,Lv1_data_gtis,Lv2_presto_subroutines,Lv2_mkdir +import os +from scipy import stats +import matplotlib.pyplot as plt +from tqdm import tqdm +import subprocess +import pathlib +import glob + +Lv0_dirs.global_par() + +tbin_size = 16 +eventfile = Lv0_dirs.NICER_DATADIR + 'xtej1812/2003250926_bary.evt' +times = fits.open(eventfile)[1].data['TIME'] +trunc = times - times[0] +t_bins = np.linspace(0,np.ceil(trunc[-1]),np.ceil(trunc[-1])*1/tbin_size+1) +summed_data, bin_edges, binnumber = stats.binned_statistic(trunc,np.ones(len(times)),statistic='sum',bins=t_bins) + +spectra_GTIs = np.array([1,2,3,4,7,8,9,11,12,13]) +gti_start,gti_stop = np.loadtxt('/Volumes/Samsung_T5/NICER-data/xtej1812/bunchedgtis.txt',usecols=(0,1),unpack=True) + +gti_used_start = np.array([gti_start[i-1] for i in spectra_GTIs]) - times[0] +gti_used_stop = np.array([gti_stop[i-1] for i in spectra_GTIs]) - times[0] +#for i in range(len(gti_used_start)): +# print(gti_used_stop[i]-gti_used_start[i]) +gti_used_centroid = gti_used_start + (gti_used_stop-gti_used_start)/2 + +contents = open('/Volumes/Samsung_T5/NICER-data/xtej1812/accelsearch_GTIs/tbabs-bbodyrad.txt','r').read().split('\n') +phoindex = [] +phoindex_err = [] +norm = [] +norm_err = [] + +for i in range(len(contents)): #for each line + if "kT" in contents[i]: + line = [x for x in contents[i].split(' ') if x] + phoindex.append(float(line[5])) + phoindex_err.append(float(line[7])) + elif "norm" in contents[i]: + line = [x for x in contents[i].split(' ') if x] + norm.append(float(line[4])) + norm_err.append(float(line[6])) + +fig,(ax1,ax2,ax3) = plt.subplots(3,1,sharex=True) + +time_bins = t_bins[:-1] +count_bins = summed_data/tbin_size +ax1.plot(time_bins[count_bins>0],count_bins[count_bins>0],'rx') #plot the light curve +for i in range(len(gti_used_start)): + ax1.axvline(x=gti_used_start[i],alpha=0.5,lw=0.5) + ax1.axvline(x=gti_used_stop[i],alpha=0.5,lw=0.5) + +ax1.set_ylabel('Counts/s',fontsize=12) + +ax2.errorbar(x=gti_used_centroid,y=phoindex,yerr=phoindex_err,fmt='x-') +ax2.set_ylabel('kT (keV)',fontsize=12) + +ax3.errorbar(x=gti_used_centroid,y=norm,yerr=norm_err,fmt='x-') +ax3.set_ylabel('norm',fontsize=12) +ax3.set_xlabel('Time from first event (s)',fontsize=12) + +plt.show() diff --git a/Lv3_average_ps_main.py b/Lv3_average_ps_main.py index 7cca07b..04f2ae5 100644 --- a/Lv3_average_ps_main.py +++ b/Lv3_average_ps_main.py @@ -91,8 +91,7 @@ if merged == True: if preprocessing == True: - Lv2_merging_events.merging(obsids) - Lv2_merging_events.merging_GTIs(obsids,merged_id) + Lv2_merging_events.merging(obsids,merged_id) if time_segments == True or time_energy_segments == True: Lv2_presto_subroutines.get_gti_file(eventfile,segment_length) if time_segments == True: diff --git a/Lv3_avg_ps_assess_cands.py b/Lv3_avg_ps_assess_cands.py new file mode 100644 index 0000000..e24686e --- /dev/null +++ b/Lv3_avg_ps_assess_cands.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +Created on Sat Mar 21 4:08pm 2020 + +Script that creates a heat map (histogram with 3rd dimension) showing on the y axis, +log10(f), and has either W (fixed threshold) or threshold (fixed W) on the x axis. +The color bar will correspond to significances. + +""" +from __future__ import division, print_function +import numpy as np +import subprocess +import pathlib +from tqdm import tqdm + +import Lv0_dirs,Lv2_TBOs_method +import matplotlib.pyplot as plt +from matplotlib.backends.backend_pdf import PdfPages +from matplotlib import cm +import mplcursors + +Lv0_dirs.global_par() + +def assess_cands(eventfile,segment_length,PI1,PI2,hist_min_f,W,threshold): + """ + Creating the heat map + + eventfile - path to the event file. Will extract ObsID from this for the NICER files. + segment_length - desired length of segments in seconds + PI1 - lower bound of PI (not energy in keV!) desired for the energy range + PI2 - upper bound of PI (not energy in keV!) desired for the energy range + hist_min_f - minimum frequency to calculate the histogram from + W - list of W values (number of consecutive Fourier bins to average over) + threshold - list of thresholds for counts in each segment (in 1s bins; in terms of a percentage) + """ + parent_folder = str(pathlib.Path(eventfile).parent) + + powers = [] + for k in range(len(W)): + for l in range(len(threshold)): + if PI1 != '': + f,ps = np.genfromtxt(parent_folder+'/S'+str(segment_length)+'_W'+str(W[k])+'_T'+str(threshold[l])+'_E'+str(PI1)+'-'+str(PI2)+'.txt',usecols=(0,1),unpack=True) + else: + f,ps = np.genfromtxt(parent_folder+'/S'+str(segment_length)+'_W'+str(W[k])+'_T'+str(threshold[l]) + '.txt',usecols=(0,1),unpack=True) + cand_f = f[f>hist_min_f] + cand_ps = ps[f>hist_min_f] + powers += list(cand_ps) + powers = np.array(powers) + powers_min = np.min(powers[powers!=np.inf]) + powers_max = np.max(powers[powers!=np.inf]) + + ### keeping W constant + for k in range(len(W)): + if PI1 != '': + filename = parent_folder + '/S'+str(segment_length)+'_W'+str(W[k])+'_E'+str(PI1)+'-'+str(PI2)+'.pdf' + else: + filename = parent_folder + '/S'+str(segment_length)+'_W'+str(W[k])+'.pdf' + with PdfPages(filename) as pdf: + for l in range(len(threshold)): + if PI1 != '': + f,ps = np.genfromtxt(parent_folder+'/S'+str(segment_length)+'_W'+str(W[k])+'_T'+str(threshold[l])+'_E'+str(PI1)+'-'+str(PI2)+'.txt',usecols=(0,1),unpack=True) + else: + f,ps = np.genfromtxt(parent_folder+'/S'+str(segment_length)+'_W'+str(W[k])+'_T'+str(threshold[l]) + '.txt',usecols=(0,1),unpack=True) + cand_f = f[f>hist_min_f] + cand_ps = ps[f>hist_min_f] + + plt.scatter(x=np.ones(len(cand_f))*threshold[l],y=cand_f,c=cand_ps,marker='o',cmap=cm.gist_heat,vmin=powers_min,vmax=powers_max,edgecolor='k') + if PI1 != '': + title = 'Segment Length: ' + str(segment_length) + 's; E = ' + str(PI1) + '-' + str(PI2) + '; W = '+str(W[k]) + else: + title = 'Segment Length: ' + str(segment_length) + 's; W = '+str(W[k]) + plt.title(title,fontsize=12) + plt.xlabel('Threshold (percentage)',fontsize=12) + plt.ylabel('log10(f)',fontsize=12) + plt.yscale('log') + plt.colorbar() + pdf.savefig() + plt.close() + + ### keeping threshold constant + for l in range(len(threshold)): + if PI1 != '': + filename = parent_folder + '/S'+str(segment_length)+'_T'+str(threshold[l])+'_E'+str(PI1)+'-'+str(PI2)+'.pdf' + else: + filename = parent_folder + '/S'+str(segment_length)+'_T'+str(threshold[l])+'.pdf' + with PdfPages(filename) as pdf: + for k in range(len(W)): + if PI1 != '': + f,ps = np.genfromtxt(parent_folder+'/S'+str(segment_length)+'_W'+str(W[k])+'_T'+str(threshold[l])+'_E'+str(PI1)+'-'+str(PI2)+'.txt',usecols=(0,1),unpack=True) + else: + f,ps = np.genfromtxt(parent_folder+'/S'+str(segment_length)+'_W'+str(W[k])+'_T'+str(threshold[l]) + '.txt',usecols=(0,1),unpack=True) + cand_f = f[f>hist_min_f] + cand_ps = ps[f>hist_min_f] + + plt.scatter(x=np.ones(len(cand_f))*W[k],y=cand_f,c=cand_ps,marker='o',cmap=cm.gist_heat,vmin=powers_min,vmax=powers_max,edgecolor='k') + if PI1 != '': + title = 'Segment Length: ' + str(segment_length) + 's; E = ' + str(PI1) + '-' + str(PI2) + '; Threshold = '+str(threshold[l]) + else: + title = 'Segment Length: ' + str(segment_length) + 's; Threshold = '+str(threshold[l]) + plt.title(title,fontsize=12) + plt.xlabel('W',fontsize=12) + plt.ylabel('log10(f)',fontsize=12) + plt.yscale('log') + plt.colorbar() + pdf.savefig() + plt.close() + + ### keeping the threshold constant + +if __name__ == "__main__": + merged_id = '000019' + eventfile = Lv0_dirs.NICERSOFT_DATADIR + 'merged_events/merged' + merged_id + '/merged' + merged_id + '_nicersoft_bary.evt' + #eventfile = '/Volumes/Samsung_T5/NICER-data/xtej1739_mostrec/2002131540_filt_bary.evt' + + segment_lengths = [500] #desired length of segments in seconds + PI1 = [30,200] + PI2 = [200,1200] + threshold = [5,10,20,30,40,50] #threshold for counts in each segment (in 1s bins; in terms of a percentage) + W = [1,5,10] #number of consecutive Fourier bins to average over + hist_min_f = 1 + + for i in tqdm(range(len(segment_lengths))): + for j in tqdm(range(len(PI1))): + assess_cands(eventfile,segment_lengths[i],PI1[j],PI2[j],hist_min_f,W,threshold) diff --git a/Lv3_det_Eres.py b/Lv3_det_Eres.py new file mode 100644 index 0000000..4f54a6c --- /dev/null +++ b/Lv3_det_Eres.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +Created on Sun Aug 2 7:01pm 2020 + +Determining the energy resolution of detectors by fitting model Gaussians with the +instrument response folded in. + +""" +from __future__ import division, print_function +import numpy as np +from astropy.io import fits +import matplotlib.pyplot as plt +import Lv0_dirs,Lv2_dj_lsp,Lv2_swift_lc,Lv2_phase +import os +from scipy import stats +from scipy.optimize import curve_fit +from tqdm import tqdm +import subprocess +import time + +input_E = np.array([0.5,0.6,0.7,0.8,0.9] + list(np.arange(1.0,12.5,0.5))) +pi_ev = input_E * 100 +fwhm = [] +fwhm_err = [] + +for i in range(len(pi_ev)): + + def gauss(x,a,sig,constant): + return a*np.exp( -(x-input_E[i])**2/(2*sig**2) ) + constant + + #testspec = '/Volumes/Samsung_T5/NICERsoft_outputs/0034070101_pipe/gauss_' + str(int(pi_ev[i])).zfill(5) + '.txt' + testspec = '/Volumes/Samsung_T5/NGC300_XMMdata/0791010101/PROC/getEres/gauss_mos1_' + str(int(pi_ev[i])).zfill(4) + '.txt' + print(testspec) + E,E_err,flux,flux_err,model = np.genfromtxt(testspec,usecols=(0,1,2,3,4),skip_header=3,skip_footer=1,unpack=True) + + pguess = np.array([100,0.05,0.01]) + popt,pcov = curve_fit(gauss,E,model,p0=pguess) + + print('Gaussian width is ' + str(round(popt[1]*1000,2)) + ' eV; FWHM is ' + str(round(popt[1]*1000*2.355,2)) + ' +- ' + str(round(np.sqrt(np.diag(pcov)[1])*1000*2.355,2)) + ' eV, and divided by 3, this is ' + str(round(popt[1]*1000*2.355/3,2)) + 'eV') + fwhm.append(popt[1]*1000*2.355) + fwhm_err.append(np.sqrt(np.diag(pcov)[1])*1000*2.355) + #plt.plot(E,model,'b-') + #plt.plot(E,gauss(E,popt[0],popt[1],popt[2]),'r-') + #plt.show() + +timeend = time.time() + + +def sqrtfunc(x,a,b,c): + return a*(x+b)**c + +popt,pcov = curve_fit(sqrtfunc,input_E,fwhm,sigma=fwhm_err,p0=[10,3.3,0.5]) +print(popt) +print(np.sqrt(np.diag(pcov))) +#for i in range(len(input_E)): +# print(input_E[i],sqrtfunc(input_E,popt[0],popt[1],popt[2],popt[3])[i]/3) + +N = 8.7 +fano = 0.114 +w = 3.71 + +nicer_spie = 2.35*w*(N**2 + input_E*1000*fano/w)**(1/2) #for NICER + +plt.plot(input_E,fwhm,'rx-') +plt.plot(input_E,sqrtfunc(input_E,*popt),'b-') +plt.annotate(str(round(popt[0],2))+'(E+'+str(round(popt[1],2))+')^'+str(round(popt[2],2)),(2,160)) +plt.xlabel('Energy, E (keV)',fontsize=12) +plt.ylabel('FWHM (eV)',fontsize=12) +plt.legend(('Measured','curve_fit'),fontsize=12) +plt.show() diff --git a/Lv3_detection_level.py b/Lv3_detection_level.py index 492b50b..d005943 100644 --- a/Lv3_detection_level.py +++ b/Lv3_detection_level.py @@ -101,6 +101,7 @@ def power_for_sigma(significance,N,M,W): #print(max_acc(200,200,230)) #sig_sig = signal_significance(43,5000,2.02697) #sig_sig = signal_significance(43,5000,2.01199) - print(power_for_sigma(5,4000,1,1)) + #print(power_for_sigma(5,4000,1,1)) + print(power_for_sigma(2.9,10/0.00025,1,1)) #single_trial_prob(2,4e6) #single_trial_prob(1,4e6) diff --git a/Lv3_diagnostics.py b/Lv3_diagnostics.py index e761650..cf6de15 100644 --- a/Lv3_diagnostics.py +++ b/Lv3_diagnostics.py @@ -56,7 +56,8 @@ def diag_all(eventfile,par_list,tbin_size,mode,diag_vars): counts = np.ones(len(times)) shifted_t = times-times[0] - t_bins = np.linspace(0,int(shifted_t[-1]),int(shifted_t[-1])*1/tbin_size+1) + + t_bins = np.linspace(0,int(shifted_t[-1]),int(shifted_t[-1]*1/tbin_size)+1) summed_data, bin_edges, binnumber = stats.binned_statistic(shifted_t,counts,statistic='sum',bins=t_bins) #binning the time values in the data binned_t = t_bins @@ -299,4 +300,6 @@ def diag_t(eventfile,par_list,tbin_size,t1,t2,mode,diag_vars): plt.close() if __name__ == "__main__": - print('hi') #placeholder, but this is more of a methods script + #eventfile = '/Volumes/Samsung_T5/NICER-data/1030180113/' + #diag_all(eventfile,['TIME','ANG_DIST'],1,'save',{}) + print('hi') diff --git a/Lv3_incoming.py b/Lv3_incoming.py new file mode 100644 index 0000000..79bc4f7 --- /dev/null +++ b/Lv3_incoming.py @@ -0,0 +1,516 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +Created on Sunday Feb 16 4:25pm 2020 + +Performing pulsation search techniques on incoming data beyond quicklook but before archival. + +Don't need to search for burst candidates here - already have it in Lv3_TBOs.py! + +Pretty similar to Lv3_quicklook.py, but takes as input a list of NICER observation directories. +- semi-coherent searches + +""" +from __future__ import division, print_function +from astropy.io import fits +import numpy as np +import pathlib +import Lv0_dirs,Lv0_fits2dict,Lv0_scp +import Lv1_barycorr +import Lv2_preprocess,Lv2_lc,Lv2_ps,Lv2_color,Lv2_phase,Lv2_efsearch,Lv2_TBOs_method,Lv2_merging_events,Lv2_average_ps_methods,Lv2_presto_subroutines +import Lv3_E_boundary,Lv3_detection_level +from matplotlib.backends.backend_pdf import PdfPages +import time +import matplotlib.pyplot as plt +import os +from tqdm import tqdm +import subprocess +import glob +import time + +Lv0_dirs.global_par() #obtaining the global parameters + +start_time = time.time() + +def nicerql(eventfile,extra_nicerql_args): + """ + Probably the second step in the process, but this is to generate the psrpipe + diagnostic plots, to see if there are any obvious red flags in the data. + + Will just really need eventfile ; orb file and mkf file is assumed to be in the SAME folder + + eventfile - path to the event file. Will extract ObsID from this for the NICER files. + extra_nicerql_args - extra arguments to the nicerql script + """ + parent_folder = str(pathlib.Path(eventfile).parent) + orbfiles = glob.glob(parent_folder+'/*.orb') + mkffiles = glob.glob(parent_folder+'/*.mkf*') + if len(orbfiles) != 1 and len(mkffiles) != 1: + raise ValueError("Either there's no orb/mkf file (in which case, make sure they're in the same folder as the event file!) or there are multiple files - do check!") + + logfile = parent_folder + '/nicerql.log' + print('Running nicerql now for ' + eventfile + ':') + with open(logfile,'w') as logtextfile: + output = subprocess.run(['nicerql.py',eventfile,'--orb',orbfiles[0],'--mkf',mkffiles[0]] + extra_nicerql_args,capture_output=True,text=True) + logtextfile.write(output.stdout) + logtextfile.write('*------------------------------* \n') + logtextfile.write(output.stderr) + logtextfile.close() + + png_files = glob.glob('*evt*png') + for i in range(len(png_files)): + subprocess.run(['mv',png_files[i],parent_folder+'/']) + + return + +def filtering(eventfile,outfile,maskdet,eventflags,rm_artifacts): + """ + Function that will filter out bad detectors and impose eventflag restrictions. + Will expect to add to this function over time... + + eventfile - path to the event file. Will extract ObsID from this for the NICER files. + outfile - output file from the filtering + maskdet - list of DET_IDs to mask + eventflags - NICER event flags to filter out (e.g., in the format '(EVENT_FLAGS==bx1x000)') + rm_artifacts - a list of [start,end,start,end] times (specified in intervals) to REMOVE! + Artifacts are defined as whatever you want to remove. Bursts are considered artifacts in the sense + that they are not part of the persistent emission. + """ + outfile_parent_folder = str(pathlib.Path(outfile).parent) + + evfilt_expr = eventflags + for i in range(len(maskdet)): + evfilt_expr += '.and.(DET_ID!='+str(maskdet[i]) + ')' + + if len(rm_artifacts) != 0: + intfile = outfile_parent_folder + '/intermediate_filt.evt' + subprocess.run(['ftcopy',eventfile+'['+evfilt_expr+']',intfile,'clobber=yes','history=yes']) + + gtis = list(fits.open(intfile)[2].data) + rm_artifacts = fits.open(intfile)[2].data['START'][0]+np.array(open( str(pathlib.Path(eventfile).parent)+'/rm_artifacts.txt','r').read().split('\n')[:-1],dtype=np.float64) + + ### To identify GTIs that are not part of the artifacts (or bursts) + gtis_remove = [] + print('Removing GTIs...') + for i in tqdm(range(len(gtis))): + for j in range(0,len(rm_artifacts)-1,2): + if (gtis[i][0] >= rm_artifacts[j]) and (gtis[i][1] <= rm_artifacts[j+1]): + gtis_remove.append(gtis[i]) + + new_gtis = [] + print('Getting new GTIs...') + for i in tqdm(range(len(gtis))): + if gtis[i] not in np.array(gtis_remove): + new_gtis.append(gtis[i]) + ### + + gtitxt = open(outfile_parent_folder + '/filtered_gtis.txt','w') + for i in range(len(new_gtis)): + gtitxt.write(str(new_gtis[i][0]) + ' ' + str(new_gtis[i][1]) + '\n') + gtitxt.close() + + gti_col_file = Lv0_dirs.NICER_DATADIR + 'gti_columns.txt' + gti_header_file = Lv0_dirs.NICER_DATADIR + 'gti_header.txt' + ftcreate_cmd = ['ftcreate',gti_col_file,outfile_parent_folder+'/filtered_gtis.txt',outfile_parent_folder+'/final_filtered.gti','headfile='+gti_header_file,'extname="GTI"','clobber=yes'] + subprocess.run(ftcreate_cmd) + + subprocess.run(['niextract-events',intfile,outfile,'timefile='+outfile_parent_folder+'/final_filtered.gti']) + + else: + subprocess.run(['ftcopy',eventfile+'['+evfilt_expr+']',outfile,'clobber=yes','history=yes']) + +if __name__ == "__main__": + #eventfile = '/Volumes/Samsung_T5/NICER-data/maxij0556/2004131927.evt' + #eventfile = Lv0_dirs.NICER_DATADIR + 'at2019wey/2008041401.evt' + eventfile = Lv0_dirs.NICER_DATADIR + 'igrj17494-3030/2010270036.evt' + #eventfile = Lv0_dirs.NICER_DATADIR + 'xtej1739_mostrec/2002131540.evt' + +############################# DIAGNOSTIC PARAMETERS ############################ + do_diagnostic = False + extra_nicerql_args = ['--save','--emin','1.0','--emax','10'] +################################################################################ + +############################# BARYCORR PARAMETERS ############################## + do_bary = True + #out_baryfile = Lv0_dirs.NICER_DATADIR + 'xtej1739_mostrec/2002131540_filt_bary.evt' + out_baryfile = Lv0_dirs.NICER_DATADIR + 'igrj17494-3030/2010270036_bary.evt' + #out_baryfile = Lv0_dirs.NICER_DATADIR + 'at2019wey/2008041401_filt_bary.evt' + refframe = 'ICRS' + #orbitfile = Lv0_dirs.NICER_DATADIR + 'maxij0556/2004131927.orb' + orbitfile = Lv0_dirs.NICER_DATADIR + 'igrj17494-3030/2010270036.orb' + #orbitfile = Lv0_dirs.NICER_DATADIR + 'at2019wey/2008041401.orb' + parfile = '' + output_folder = Lv0_dirs.NICER_DATADIR + 'igrj17494-3030/' + #output_folder = Lv0_dirs.NICER_DATADIR + 'maxij0556/' + #output_folder = Lv0_dirs.NICER_DATADIR + 'at2019wey/' + custom_coords = np.array([]) +################################################################################ + +############################# FILTERING PARAMETERS ############################# + do_filter = False + if do_filter == True: + filtfile = '/Volumes/Samsung_T5/NICER-data/at2019wey/2008041401_bary.evt' + maskdets = [34,43] + eventflags = '(EVENT_FLAGS==bx1x000)' + + timezero = fits.open(eventfile)[2].data['START'][0] + rm_artifacts = timezero + np.array(open(str(pathlib.Path(eventfile).parent)+'/rm_artifacts.txt','r').read().split('\n')[:-1],dtype=np.float64) +################################################################################ + +######################### LC_PS_PHASE_COLOR PARAMETERS ######################### + do_lc_ps_phase_color = False +##### fill out the parameters below ; there are quite a number +################################################################################ + +############################### PRESTO PARAMETERS ############################## + do_presto = True + if do_presto == True: + conv_fits2presto = False #only for process_all + process_all = False #whether to process the ENTIRE observation or not + + preprocess_segments = True #whether to get GTI files, run niextract, edit_inf, edit_binary, nicerfits2presto + process_segments = True #whether to make truncations to the data + + time_segments = False #truncate by time segments + gti_segments = False #truncate by GTI segments + gti_energy_segments = False #truncate by GTI AND energy range + energy_segments = True #truncate by energy range + time_energy_segments = False #truncate both by time segments and energy range + + accelsearch = True + prepfold = True + + ### for gti_segments + gap = 11 #seconds + gtifile = 'bunched.gti' + + tbin = '0.0002' #time bin for PRESTO in seconds + + ##### For when we analyze the entire data set (no truncations in energy or time) + accelsearch_flags = ['-numharm','4','-zmax','100','-photon','-flo','1','-fhi','1000'] + + ##### Parameters for prepfold + zmax = 100 + + ##### From Lv2_presto_subroutines + segment_lengths = ['GTI'] #desired length of segments in seconds + PI1 = [100] + PI2 = [1000] +################################################################################ + +############################ AVERAGE_PS PARAMETERS ############################# + do_average_ps = False + if do_average_ps == True: + demod = False + preprocessing = True #getting GTIs, running niextract, nicerfits2presto, edit_inf, edit_bin, and realfft! + time_segments = False + time_energy_segments = True + mode = 't' + segment_lengths = [64] #desired length of segments in seconds + PI1 = [100] + PI2 = [1000] + #t1 = [0,3315000,3500000,3615000,3860000,4045000,4295000,4430000] + #t2 = [0,3490000,3605000,3850000,4040000,4290000,4420000,4695000] + t1 = [0] + t2 = [0] + par_file = '' + tbin = 0.0002 #bin size in s + threshold = [100] #threshold for counts in each segment (in 1s bins; in terms of a percentage) + W = [1] #number of consecutive Fourier bins to average over + hist_min_sig = 2.5 + starting_freq = 10 #for the noise histogram + xlims = np.array([0.01,1000]) + plot_mode = "save" + +################################################################################ + +############################# SEARCH_BIN PARAMETERS ############################ +##### SIDEBAND SEARCHES + do_searchbin = False + fft_files = eventfile[:-3] + 'fft' + ncand = 1000 #no. of candidates to try to return ; default 100 (1 to 1000) + flo = 1 #the lowest frequency to check + fhi = 1000 #the highest frequency to check + overlap = 0.05 + extra_args = [] +################################################################################ + +############################# EF_SEARCH PARAMETERS ############################# +##### EPOCH FOLDING + do_efsearch = False + if do_efsearch == True: + n_segments = 100 #number of segments to break the epoch folding search into + dper = 4.80 #Value for the period used in the folding. In 'efsearch' the + #input period represents the centre of the range of the trial periods. + nphase = 32 #Number of phases in the folded light curve(s). Typing 'INDEF' + #forces the task to use the default value (see parameter "nbdf"). + nper = 64 #The number of periods over which the search is carried out + dres = 1E-4 # The period resolution is the spacing between two contiguous periods in the search. + #'INDEF' uses the default value of: half the Fourier resolution in the interval (e.g., P^2/T(i)/2 ; T(i) is interval duration) + plot_efsearch = 'no' #to plot the results from efsearch ; do "exit" to see the next plot! + +################################################################################ + + if do_diagnostic == True: + ##### Quick look at diagnostic plots + nicerql(eventfile,extra_nicerql_args) + + if do_bary == True: + if do_filter == True: + Lv1_barycorr.barycorr(eventfile,filtfile,refframe,orbitfile,parfile,output_folder,custom_coords) + print('Done filtering and barycentering') + else: + Lv1_barycorr.barycorr(eventfile,out_baryfile,refframe,orbitfile,parfile,output_folder,custom_coords) + + if do_filter == True: + ##### Filtering if needed + filtering(filtfile,out_baryfile,maskdets,eventflags,rm_artifacts) + + if do_lc_ps_phase_color == True: #would only be useful for looking at the whole time series? Might be of limited usage depending on what I want to use it for. + par_list = ['PI','PI_FAST','TIME'] #parameter list from event_cl + tbin_size = 1 #how you want to bin the light curve data + Ebin_size = 0.05 #in keV + mode = 'show' #probably best to 'save' if using a LARGE set of ObsIDs! + truncations = 'E' #'all', 't', 'E', or 'tE', depending on whether we want to look at entire time series (all), or truncation by time interval (t), or time truncation by energy range (E), or truncation by both (tE) + + lc = True + ps = False + phase = False + color = False + ############################################################################### + + #### DEFINE DESIRED TIME INTERVALS AND ENERGY RANGES HERE FOR: + # Lv2_ps - partial_t, partial_E, partial_tE + # Lv2_phase - partial_t, partial_E, partial_tE + # Lv2_color - plotting_t + + t1 = 2629580 + t2 = 2630180 + E1 = 1 + E2 = 10 + + #for Lv2_ps + ps_type = 'manual' # 'period' (for periodogram) or 'manual' (for FFT) or 'both' + oversampling = [False,5] # [False to NOT oversample, oversampling factor - 5 to oversample by factor of 5. (factor-1) sets of 0s are padded.] + xlims = [False,0,5] # [False to NOT impose xlimit on plots; 2nd/3rd entries are the desired x-limits if needed.] + vlines = [False,0.2081] # [False to NOT draw a vertical line on the plot; 2nd entry is the equation for the vertical line, e.g. x=2] + + #for Lv2_phase + ### For an unknown observation, one should run JUST Lv2_lc and Lv2_ps first to get + ### the pulsation frequencies. Pulse profiles come LATER. + ### If I have pulse_pars[1] and pulse_pars[2] != 0, then time binning DOES NOT MATTER, i.e., it'll be counts/s! + pulse_pars = [275.518,0,0] + shift = 0.4 # how much to shift the pulse by in the phase axis. It only affects how the pulse profile is 'displaced'. + no_phase_bins = 20 # number of phase bins desired + + #for Lv2_color + E1_data = 0.3 #data is reliable between 0.3 and 12 keV + E2_data = 12 # in keV + cut_type = 'manual' # 'manual' cut for boundary energy, or 'median' - for half number of counts + bound = 2.7 # boundary energy for when cut_type = 'manual'! + + E_bound = Lv3_E_boundary.E_bound(out_baryfile,par_list,E1_data,E2_data,cut_type,bound) #use Lv3_E_boundary to get boundary energy + ############################ FOR WHOLE OBSERVATION ############################ + if truncations == 'all': + if lc == True: + Lv2_lc.whole(out_baryfile,par_list,tbin_size,mode) #light curve + time.sleep(1) + if ps == True: + Lv2_ps.whole(out_baryfile,par_list,tbin_size,mode,ps_type,oversampling,xlims,vlines) #power spectra + time.sleep(1) + if phase == True: + Lv2_phase.whole(out_baryfile,par_list,tbin_size,pulse_pars,shift,no_phase_bins,mode) + time.sleep(1) + if color == True: + Lv2_color.plotting(out_baryfile,par_list,E_bound,tbin_size,mode) + + ########################## FOR DESIRED TIME INTERVAL ########################## + if truncations == 't': + if lc == True: + Lv2_lc.partial_t(out_baryfile,par_list,tbin_size,t1,t2,mode) #light curve + time.sleep(1) + if ps == True: + Lv2_ps.partial_t(out_baryfile,par_list,tbin_size,t1,t2,mode,ps_type,oversampling,xlims,vlines) #power spectra + time.sleep(1) + if phase == True: + Lv2_phase.partial_t(out_baryfile,par_list,tbin_size,pulse_pars,shift,no_phase_bins,t1,t2,mode) + time.sleep(1) + if color == True: + Lv2_color.plotting_t(out_baryfile,par_list,E_bound,tbin_size,t1,t2,mode) + + ########################### FOR DESIRED ENERGY RANGE ########################## + # anticipate that this will be used much? + if truncations == 'E': + if lc == True: + Lv2_lc.partial_E(out_baryfile,par_list,tbin_size,E1,E2,mode) + time.sleep(1) + if ps == True: + Lv2_ps.partial_E(out_baryfile,par_list,tbin_size,Ebin_size,E1,E2,mode,ps_type,oversampling,xlims,vlines) + time.sleep(1) + if phase == True: + Lv2_phase.partial_E(out_baryfile,par_list,tbin_size,Ebin_size,pulse_pars,shift,no_phase_bins,E1,E2,mode) + + ################# FOR DESIRED TIME INTERVAL AND ENERGY RANGE ################# + if truncations == 'tE': + if lc == True: + Lv2_lc.partial_tE(out_baryfile,par_list,tbin_size,Ebin_size,t1,t2,E1,E2,mode) + time.sleep(1) + if ps == True: + Lv2_ps.partial_tE(out_baryfile,par_list,tbin_size,Ebin_size,t1,t2,E1,E2,mode,ps_type,oversampling,xlims,vlines) + time.sleep(1) + if phase == True: + Lv2_phase.partial_tE(out_baryfile,par_list,tbin_size,Ebin_size,pulse_pars,shift,no_phase_bins,t1,t2,E1,E2,mode) + time.sleep(1) + if color == True: + Lv2_color.plotting_t(out_baryfile,par_list,E_bound,tbin_size,t1,t2,mode) + + if do_average_ps == True: + for k in range(0,len(PI1)): + for j in range(len(segment_lengths)): + N = Lv3_detection_level.N_trials(tbin,segment_lengths[j]) + + if preprocessing == True: + if time_segments == True or time_energy_segments == True: + Lv2_presto_subroutines.get_gti_file(out_baryfile,segment_lengths[j]) + if time_segments == True: + Lv2_presto_subroutines.niextract_gti_time(out_baryfile,segment_lengths[j]) + if time_energy_segments == True: + Lv2_presto_subroutines.niextract_gti_time_energy(out_baryfile,segment_lengths[j],PI1[k],PI2[k]) + + if demod == True: + Lv2_average_ps_methods.do_demodulate(out_baryfile,segment_lengths[j],mode,par_file) + + Lv2_average_ps_methods.do_nicerfits2presto(out_baryfile,tbin,segment_lengths[j]) + Lv2_average_ps_methods.edit_inf(out_baryfile,tbin,segment_lengths[j]) + Lv2_average_ps_methods.edit_binary(out_baryfile,tbin,segment_lengths[j]) + Lv2_average_ps_methods.realfft(out_baryfile,segment_lengths[j]) + + for z in range(len(t1)): + for x in range(len(W)): + for y in range(len(threshold)): + Lv2_average_ps_methods.plotting(out_baryfile,segment_lengths[j],demod,tbin,threshold[y],PI1[k],PI2[k],t1[z],t2[z],starting_freq,W[x],hist_min_sig,N,xlims,plot_mode) + + if do_presto == True: + if process_all == True: + if conv_fits2presto == True: + Lv2_presto_subroutines.do_nicerfits2presto(out_baryfile,tbin,0,'all') + + if accelsearch == True: + print('Doing realfft/accelsearch now!') + ### Running realfft and accelsearch from PRESTO + Lv2_presto_subroutines.realfft(out_baryfile,0,'all') + Lv2_presto_subroutines.accelsearch(out_baryfile,0,'all',accelsearch_flags) + + ## no_cand might be a list, if I'm processing multiple out_baryfiles at once... + if prepfold == True: + Lv2_presto_subroutines.prepfold(out_baryfile,0,'all',zmax) + Lv2_presto_subroutines.ps2pdf(out_baryfile,0,'all') + +################################################################################ +############################### PRESTO_SEGMENTS ################################ +################################################################################ + + if process_segments == True: + if time_segments == True and preprocess_segments == True: + for j in range(len(segment_lengths)): + Lv2_presto_subroutines.get_gti_file(out_baryfile,segment_lengths[j]) #make GTI files for each segment + Lv2_presto_subroutines.niextract_gti_time(out_baryfile,segment_lengths[j]) #performing niextract-events + + Lv2_presto_subroutines.do_nicerfits2presto(out_baryfile,tbin,segment_lengths[j],'t') + Lv2_presto_subroutines.edit_inf(out_baryfile,tbin,segment_lengths[j]) + Lv2_presto_subroutines.edit_binary(out_baryfile,tbin,segment_lengths[j]) + + # Lv3_duty_cycle.duty_cycle(out_baryfile,tbin,segment_lengths[j],duty_cycle_bin,threshold) + # Lv3_duty_cycle.duty_cycle_dist(out_baryfile,tbin,segment_lengths[j],duty_cycle_bin,threshold) + + if gti_segments == True and preprocess_segments == True: + Lv2_presto_subroutines.niextract_gti(out_baryfile,gap,gtifile) + Lv2_presto_subroutines.do_nicerfits2presto(out_baryfile,tbin,0,'gtis') + + if gti_energy_segments == True and preprocess_segments == True: + if len(PI1) != len(PI2): + raise ValueError("Make sure that the length of PI1 and PI2 are the same! Need pairs of PI values.") + for j in range(len(PI1)): + Lv2_presto_subroutines.niextract_gti_E(out_baryfile,gap,gtifile,PI1[j],PI2[j]) + Lv2_presto_subroutines.do_nicerfits2presto(out_baryfile,tbin,0,'gtis') #segment_length makes no sense, so 0 is a placeholder + + if energy_segments == True and preprocess_segments == True: + if len(PI1) != len(PI2): + raise ValueError("Make sure that the length of PI1 and PI2 are the same! Need pairs of PI values.") + for j in range(len(PI1)): + Lv2_presto_subroutines.niextract_gti_energy(out_baryfile,PI1[j],PI2[j]) + Lv2_presto_subroutines.do_nicerfits2presto(out_baryfile,tbin,0,'E') #segment_length makes no sense, so 0 is a placeholder + + if time_energy_segments == True and preprocess_segments == True: + for j in range(len(segment_lengths)): + Lv2_presto_subroutines.get_gti_file(out_baryfile,segment_lengths[j]) #make GTI files for each segment + for k in range(len(PI1)): + Lv2_presto_subroutines.niextract_gti_time_energy(out_baryfile,segment_lengths[j],PI1[k],PI2[k]) + + Lv2_presto_subroutines.do_nicerfits2presto(out_baryfile,tbin,segment_lengths[j],'t') + Lv2_presto_subroutines.edit_inf(out_baryfile,tbin,segment_lengths[j]) + Lv2_presto_subroutines.edit_binary(out_baryfile,tbin,segment_lengths[j]) + + #for k in range(len(PI1)): + # Lv3_duty_cycle.duty_cycle_tE(out_baryfile,tbin,segment_lengths[j],PI1[k],PI2[k],duty_cycle_bin,threshold) + # Lv3_duty_cycle.duty_cycle_tE_dist(out_baryfile,tbin,segment_lengths[j],PI1[k],PI2[k],duty_cycle_bin,threshold) + + ### Running realfft and accelsearch from PRESTO + if accelsearch == True: + if time_segments == True or time_energy_segments == True: + for j in range(len(segment_lengths)): + Lv2_presto_subroutines.realfft(out_baryfile,segment_lengths[j],'t') + Lv2_presto_subroutines.accelsearch(out_baryfile,segment_lengths[j],'t',accelsearch_flags) + if gti_segments == True or gti_energy_segments == True: + Lv2_presto_subroutines.realfft(out_baryfile,0,'gtis') + Lv2_presto_subroutines.accelsearch(out_baryfile,0,'gtis',accelsearch_flags) + if energy_segments == True: + Lv2_presto_subroutines.realfft(out_baryfile,0,'E') + Lv2_presto_subroutines.accelsearch(out_baryfile,0,'E',accelsearch_flags) + else: + "None of time_segments, gti_segments, gti_energy_segments, time_energy_segments, or energy_segments are True!" + + ## no_cand might be a list, if I'm processing multiple out_baryfiles at once... + if prepfold == True: + print("Running prepfold now!") + if time_segments == True or time_energy_segments == True: + for j in range(len(segment_lengths)): + Lv2_presto_subroutines.prepfold(out_baryfile,segment_lengths[j],'t',zmax) + if gti_segments == True or gti_energy_segments == True: + Lv2_presto_subroutines.prepfold(out_baryfile,0,'gtis',zmax) + if energy_segments == True: + Lv2_presto_subroutines.prepfold(out_baryfile,0,'E',zmax) + + ### doing ps2pdf + if time_segments == True or time_energy_segments == True: + for j in range(len(segment_lengths)): + Lv2_presto_subroutines.ps2pdf(out_baryfile,segment_lengths[j],'t') + if gti_segments == True or gti_energy_segments == True: + Lv2_presto_subroutines.ps2pdf(out_baryfile,0,'gtis') + if energy_segments == True: + Lv2_presto_subroutines.ps2pdf(out_baryfile,0,'E') + + else: + "None of time_segments, gti_segments, gti_energy_segments, time_energy_segments, or energy_segments are True!" + + if do_searchbin == True: + for i in range(len(fft_files)): + search_bin_cmd = ['search_bin','-ncand',str(ncand),'-flo',str(flo),'-fhi',str(fhi),'-overlap',str(overlap)] + extra_args + [fft_files[i]] + subprocess.run(search_bin_cmd) + + if do_efsearch == True: + print('Doing epoch-folding searches!') + eventfile_header = fits.open(out_baryfile)[1].header + T = eventfile_header['TSTOP'] - eventfile_header['TSTART'] + nbint = int((T/(dper/nphase))/n_segments) # The number of newbins per interval used in the analysis. The + #"nbint" together with the NEWBIN duration determines the length in time of an interval + #and therefore the total number of intervals within the start and stop time over which the + #analysis will be carried out. Typing 'INDEF' forces the task to use the default value + #(see parameter "nbdf"). NOTE: By pressing return "nbint" is set to the value found in the + #parameter file used in a previous run." + outfile_root = nicer_obsids[i] + '_' + str(n_segments) + 'segs_' + str(nper) + Lv2_efsearch.efsearch(out_baryfile,n_segments,dper,nphase,nbint,nper,dres,outfile_root,plot_efsearch) + +end_time = time.time() + +print('Time elapsed: ' + str(end_time-start_time) + ' seconds.') diff --git a/Lv3_main.py b/Lv3_main.py index 75b3460..c8b319a 100644 --- a/Lv3_main.py +++ b/Lv3_main.py @@ -21,18 +21,19 @@ ### parameters used EVERYWHERE basedir = Lv0_dirs.NICERSOFT_DATADIR -eventfiles = [basedir + str(i) + '_pipe/ni' + str(i) + '_nicersoft_bary.evt' for i in ['0050070102']] +#eventfiles = [basedir + str(i) + '_pipe/ni' + str(i) + '_nicersoft_bary.evt' for i in ['0034070101']] #eventfiles = [Lv0_dirs.NICER_DATADIR + 'rxj0209/rxj0209kgfilt_bary.evt'] +eventfiles = ['/Volumes/Samsung_T5/NICER-data/1030180113/xti/event_cl/ni1030180113_0mpu7_ufa.evt'] par_list = ['PI','PI_FAST','TIME'] #parameter list from event_cl -tbin_size = 0.0005 #how you want to bin the light curve data +tbin_size = 1 #how you want to bin the light curve data Ebin_size = 0.05 #in keV mode = 'show' -truncations = 'tE' #'all', 't', 'E', or 'tE', depending on whether we want to look at entire time series (all), or truncation by time interval (t), or time truncation by energy range (E), or truncation by both (tE) +truncations = 'all' #'all', 't', 'E', or 'tE', depending on whether we want to look at entire time series (all), or truncation by time interval (t), or time truncation by energy range (E), or truncation by both (tE) lc = False -ps = True -phase = True +ps = False +phase = False color = False ############################################################################### @@ -144,9 +145,9 @@ # [Best to do mode='save' with the many plots] # Getting diagnostic plots over the entire observation; looks at how variables # like TOT_OVER_COUNT changes over time! -#mode = 'show' -#for i in range(len(eventfiles)): -# Lv3_diagnostics.diag_all(eventfiles[i],par_list,tbin_size,mode,diag_vars) +mode = 'save' +for i in range(len(eventfiles)): + Lv3_diagnostics.diag_all(eventfiles[i],par_list,tbin_size,mode,diag_vars) # [Best to do mode='save' with the many plots] # Getting diagnostic plots over the desired time interval; looks at how variables diff --git a/Lv3_ngc300_plots.py b/Lv3_ngc300_plots.py index 4d2e3a1..e838af5 100644 --- a/Lv3_ngc300_plots.py +++ b/Lv3_ngc300_plots.py @@ -31,7 +31,8 @@ Lv0_dirs.global_par() ### this is for the individual GTIs though! Use later... -spectra = sorted(glob.glob(Lv0_dirs.NGC300 + 'bgsub_cl50*.txt')) +spectra = sorted(glob.glob(Lv0_dirs.NGC300_2020 + 'bgsub_cl50*.txt')) +bgsub_type = 'xbgsub' ################################## FOR COLORS ################################## bin_size = '05d' #for 1 day @@ -40,14 +41,14 @@ band3 = 'C' band4 = 'D' -mjds_soft_color,soft_color,soft_color_unc = Lv2_ngc300_color.get_color(bin_size,band1,band2) -mjds_hard_color,hard_color,hard_color_unc = Lv2_ngc300_color.get_color(bin_size,band3,band4) +mjds_soft_color,soft_color,soft_color_unc = Lv2_ngc300_color.get_color(bin_size,bgsub_type,band1,band2) +mjds_hard_color,hard_color,hard_color_unc = Lv2_ngc300_color.get_color(bin_size,bgsub_type,band3,band4) ################################################################################ ################################# FOR INTENSITY ################################ intensity_band = 'inband' -counts_file = Lv0_dirs.NGC300 + 'n300_ulx.bgsub_cl50_RGnorm_' + bin_size + '.ffphot' -unc_file = Lv0_dirs.NGC300 + 'n300_ulx.bgsub_cl50_RGerr_' + bin_size + '.ffphot' +counts_file = Lv0_dirs.NGC300_2020 + 'n300_ulx.' + bgsub_type + '_cl50_g2020norm_' + bin_size + '.fffphot' +unc_file = Lv0_dirs.NGC300_2020 + 'n300_ulx.' + bgsub_type + '_cl50_g2020err_norm_' + bin_size + '.fffphot' mjds_band = np.genfromtxt(counts_file,usecols=(0),unpack=True) if intensity_band == 'soft1': counts_band = np.genfromtxt(counts_file,usecols=(1),unpack=True) @@ -74,36 +75,48 @@ boundaries = np.array([58230,58280,58290,58300,58310,58335,58340,58355,58380,58420,58460,58520]) +### plots intensity (at least in 0.4-12 keV) vs time plt.figure(figsize=(16,9)) plt.errorbar(mjds_band,counts_band,yerr=unc_band,fmt='kx') -plt.errorbar(mjds_band[0],counts_band[0],yerr=unc_band[0],fmt='rx',markersize=10) -plt.errorbar(mjds_band[-5],counts_band[-5],yerr=unc_band[-5],fmt='bx',markersize=10) -plt.legend(('Data','Sample 1','Sample 2'),loc='best',fontsize=12) +#plt.errorbar(mjds_band[0],counts_band[0],yerr=unc_band[0],fmt='rx',markersize=10) +#plt.errorbar(mjds_band[-5],counts_band[-5],yerr=unc_band[-5],fmt='bx',markersize=10) +#plt.legend(('Data','Sample 1','Sample 2'),loc='best',fontsize=12) plt.axhline(y=0,ls='--',lw=0.5,alpha=0.5) plt.ylabel('Intensity in counts/s \n (0.4-12 keV)',fontsize=12) plt.xlabel('Time (MJD)',fontsize=12) -plt.title('5-day binned data',fontsize=12) +plt.title(bin_size[:2] + '-day binned data',fontsize=12) #plt.show() +### plots intensity vs time as well fig, (ax1,ax2,ax3) = plt.subplots(3,1,sharex=True) ax1.errorbar(mjds_band,counts_band,yerr=unc_band,fmt='^',mfc='none') ax1.axhline(y=0,ls='--',lw=0.5,alpha=0.5) ax1.set_ylabel('Counts/s for band: ' + intensity_band, fontsize=12) -for i in range(len(boundaries)): - ax1.axvline(x=boundaries[i],lw=0.5,alpha=0.5,color='r') +#for i in range(len(boundaries)): +# ax1.axvline(x=boundaries[i],lw=0.5,alpha=0.5,color='r') #ax1.set_ylim([-2,4]) + +texta = open(Lv0_dirs.NGC300_2020 + 'time_intens_' + bgsub_type + '.txt','w') +for i in range(len(mjds_band)): + texta.write(str(mjds_band[i]) + ' ' + str(counts_band[i]) + ' ' + str(unc_band[i]) + '\n') +texta.close() + + +### plots soft color vs time ax2.errorbar(mjds_soft_color,soft_color,yerr=soft_color_unc,fmt='^',mfc='none') ax2.set_xlabel('Time (MJD)',fontsize=12) ax2.set_ylabel('Soft Color: ' + band2+'/'+band1,fontsize=12) -for i in range(len(boundaries)): - ax2.axvline(x=boundaries[i],lw=0.5,alpha=0.5,color='r') +#for i in range(len(boundaries)): +# ax2.axvline(x=boundaries[i],lw=0.5,alpha=0.5,color='r') +### plots hard color vs time ax3.errorbar(mjds_hard_color,hard_color,yerr=hard_color_unc,fmt='^',mfc='none') +ax3.set_yscale('log') ax3.set_xlabel('Time (MJD)',fontsize=12) ax3.set_ylabel('Hard Color: ' + band4+'/'+band3,fontsize=12) -for i in range(len(boundaries)): - ax3.axvline(x=boundaries[i],lw=0.5,alpha=0.5,color='r') +#for i in range(len(boundaries)): +# ax3.axvline(x=boundaries[i],lw=0.5,alpha=0.5,color='r') plt.subplots_adjust(hspace=0) @@ -163,14 +176,15 @@ hard_counts6 = hard_color_common[(mjds_common>=58460)&(mjds_common<=58520)] hard_unc_counts6 = hard_color_unc_common[(mjds_common>=58460)&(mjds_common<=58520)] -#plt.errorbar(hard_color_common,soft_color_common,xerr=hard_color_unc_common,yerr=soft_color_unc_common,fmt='^',mfc='none') -plt.errorbar(hard_counts1,soft_counts1,xerr=hard_unc_counts1,yerr=soft_unc_counts1,fmt='^',mfc='none') -plt.errorbar(hard_counts2,soft_counts2,xerr=hard_unc_counts2,yerr=soft_unc_counts2,fmt='^',mfc='none') -plt.errorbar(hard_counts3,soft_counts3,xerr=hard_unc_counts3,yerr=soft_unc_counts3,fmt='^',mfc='none') -plt.errorbar(hard_counts4,soft_counts4,xerr=hard_unc_counts4,yerr=soft_unc_counts4,fmt='^',mfc='none') -plt.errorbar(hard_counts5,soft_counts5,xerr=hard_unc_counts5,yerr=soft_unc_counts5,fmt='^',mfc='none') -plt.errorbar(hard_counts6,soft_counts6,xerr=hard_unc_counts6,yerr=soft_unc_counts6,fmt='^',mfc='none') -plt.legend(('58230-58280','58290-58300','58310-58335','58340-58355','58380-58420','58460-58520'),loc='best') +plt.errorbar(hard_color_common,soft_color_common,xerr=hard_color_unc_common,yerr=soft_color_unc_common,fmt='^',mfc='none') +plt.xscale('log') +#plt.errorbar(hard_counts1,soft_counts1,xerr=hard_unc_counts1,yerr=soft_unc_counts1,fmt='^',mfc='none') +#plt.errorbar(hard_counts2,soft_counts2,xerr=hard_unc_counts2,yerr=soft_unc_counts2,fmt='^',mfc='none') +#plt.errorbar(hard_counts3,soft_counts3,xerr=hard_unc_counts3,yerr=soft_unc_counts3,fmt='^',mfc='none') +#plt.errorbar(hard_counts4,soft_counts4,xerr=hard_unc_counts4,yerr=soft_unc_counts4,fmt='^',mfc='none') +#plt.errorbar(hard_counts5,soft_counts5,xerr=hard_unc_counts5,yerr=soft_unc_counts5,fmt='^',mfc='none') +#plt.errorbar(hard_counts6,soft_counts6,xerr=hard_unc_counts6,yerr=soft_unc_counts6,fmt='^',mfc='none') +#plt.legend(('58230-58280','58290-58300','58310-58335','58340-58355','58380-58420','58460-58520'),loc='best') plt.xlabel('Hard Color: ' + band4+'/'+band3,fontsize=12) plt.ylabel('Soft Color: ' + band2+'/'+band1,fontsize=12) @@ -259,35 +273,39 @@ '58464','58469','58474','58479','58484','58489','58494','58499', '58504','58509','58599','58604'] -soft_counts_list = list(soft_counts1)+list(soft_counts2)+list(soft_counts3)+list(soft_counts4)+list(soft_counts5)+list(soft_counts6)+list(soft_counts7) -soft_counts_unc_list = list(soft_unc_counts1)+list(soft_unc_counts2)+list(soft_unc_counts3)+list(soft_unc_counts4)+list(soft_unc_counts5)+list(soft_unc_counts6)+list(soft_unc_counts7) -intensity_list = list(intensity1)+list(intensity2)+list(intensity3)+list(intensity4)+list(intensity5)+list(intensity6)+list(intensity7) -intensity_unc_list = list(intensity_unc1)+list(intensity_unc2)+list(intensity_unc3)+list(intensity_unc4)+list(intensity_unc5)+list(intensity_unc6)+list(intensity_unc7) +#soft_counts_list = list(soft_counts1)+list(soft_counts2)+list(soft_counts3)+list(soft_counts4)+list(soft_counts5)+list(soft_counts6)+list(soft_counts7) +#soft_counts_unc_list = list(soft_unc_counts1)+list(soft_unc_counts2)+list(soft_unc_counts3)+list(soft_unc_counts4)+list(soft_unc_counts5)+list(soft_unc_counts6)+list(soft_unc_counts7) +#intensity_list = list(intensity1)+list(intensity2)+list(intensity3)+list(intensity4)+list(intensity5)+list(intensity6)+list(intensity7) +#intensity_unc_list = list(intensity_unc1)+list(intensity_unc2)+list(intensity_unc3)+list(intensity_unc4)+list(intensity_unc5)+list(intensity_unc6)+list(intensity_unc7) -for i in range(len(mjds)): - if (float(mjds[i]) in mjds_soft_color): - print(mjds[i],soft_counts_list[i],soft_counts_unc_list[i],intensity_list[i],intensity_unc_list[i]) +#for i in range(len(mjds)): +# if (float(mjds[i]) in mjds_soft_color): +# print(mjds[i],soft_counts_list[i],soft_counts_unc_list[i],intensity_list[i],intensity_unc_list[i]) +#plt.errorbar(soft_counts1,intensity1,xerr=soft_unc_counts1,yerr=intensity_unc1,fmt='^',mfc='none',label=mjds[i]) +#plt.errorbar(soft_counts2,intensity2,xerr=soft_unc_counts2,yerr=intensity_unc2,fmt='^',mfc='none',label=mjds[i]) +#plt.errorbar(soft_counts3,intensity3,xerr=soft_unc_counts3,yerr=intensity_unc3,fmt='^',mfc='none',label=mjds[i]) +#plt.errorbar(soft_counts4,intensity4,xerr=soft_unc_counts4,yerr=intensity_unc4,fmt='^',mfc='none',label=mjds[i]) +#plt.errorbar(soft_counts5,intensity5,xerr=soft_unc_counts5,yerr=intensity_unc5,fmt='^',mfc='none',label=mjds[i]) +#plt.errorbar(soft_counts6,intensity6,xerr=soft_unc_counts6,yerr=intensity_unc6,fmt='^',mfc='none',label=mjds[i]) +#plt.errorbar(soft_counts7,intensity7,xerr=soft_unc_counts7,yerr=intensity_unc7,fmt='^',mfc='none',label=mjds[i]) +#plt.legend(('[58230,58280]','(58280,58310]','(58310,58340]','(58340,58355]','[58380,58420]','[58440-58520]','[58595,58605]'),loc='best') + +#print(len(soft_counts_list)) -#plt.errorbar(hard_color_common,soft_color_common,xerr=hard_color_unc_common,yerr=soft_color_unc_common,fmt='^',mfc='none') -""" -plt.errorbar(soft_counts1,intensity1,xerr=soft_unc_counts1,yerr=intensity_unc1,fmt='^',mfc='none',label=mjds[i]) -plt.errorbar(soft_counts2,intensity2,xerr=soft_unc_counts2,yerr=intensity_unc2,fmt='^',mfc='none',label=mjds[i]) -plt.errorbar(soft_counts3,intensity3,xerr=soft_unc_counts3,yerr=intensity_unc3,fmt='^',mfc='none',label=mjds[i]) -plt.errorbar(soft_counts4,intensity4,xerr=soft_unc_counts4,yerr=intensity_unc4,fmt='^',mfc='none',label=mjds[i]) -plt.errorbar(soft_counts5,intensity5,xerr=soft_unc_counts5,yerr=intensity_unc5,fmt='^',mfc='none',label=mjds[i]) -plt.errorbar(soft_counts6,intensity6,xerr=soft_unc_counts6,yerr=intensity_unc6,fmt='^',mfc='none',label=mjds[i]) -plt.errorbar(soft_counts7,intensity7,xerr=soft_unc_counts7,yerr=intensity_unc7,fmt='^',mfc='none',label=mjds[i]) -plt.legend(('[58230,58280]','(58280,58310]','(58310,58340]','(58340,58355]','[58380,58420]','[58440-58520]','[58595,58605]'),loc='best') -""" #datacursor(formatter='{label}'.format,bbox=None) -plt.errorbar(np.array(soft_counts_list),np.array(intensity_list),xerr=np.array(soft_counts_unc_list),yerr=np.array(intensity_unc_list),fmt='^',mfc='none') +plt.errorbar(x=soft_color_common,y=intensity_common,xerr=soft_color_unc_common,yerr=intensity_unc_common,fmt='^',mfc='none') #plt.xlabel('Soft Color: ' + band2+'/'+band1,fontsize=12) plt.xlabel('Soft Color: (1-2 keV)/(0.4-1 keV)',fontsize=12) plt.ylabel('Intensity in counts/s (0.4-12 keV)',fontsize=12) #plt.xlim([-0.1,2.9]) #plt.ylim([-0.9,1.6]) +textb = open(Lv0_dirs.NGC300_2020 + 'soft_intens_' + bgsub_type + '.txt','w') +for i in range(len(soft_color_common)): + textb.write(str(soft_color_common[i]) + ' ' + str(soft_color_unc_common[i]) + ' ' + str(intensity_common[i]) + ' ' + str(intensity_unc_common[i]) + '\n') +textb.close() + ################################################################################ #### now intensity vs hard color @@ -344,15 +362,16 @@ intensity6 = intensity_common[(mjds_common>=58460)&(mjds_common<=58520)] intensity_unc6 = intensity_unc_common[(mjds_common>=58460)&(mjds_common<=58520)] -#plt.errorbar(hard_color_common,hard_color_common,xerr=hard_color_unc_common,yerr=hard_color_unc_common,fmt='^',mfc='none') -plt.errorbar(hard_counts1,intensity1,xerr=hard_unc_counts1,yerr=intensity_unc1,fmt='^',mfc='none') -plt.errorbar(hard_counts2,intensity2,xerr=hard_unc_counts2,yerr=intensity_unc2,fmt='^',mfc='none') -plt.errorbar(hard_counts3,intensity3,xerr=hard_unc_counts3,yerr=intensity_unc3,fmt='^',mfc='none') -plt.errorbar(hard_counts4,intensity4,xerr=hard_unc_counts4,yerr=intensity_unc4,fmt='^',mfc='none') -plt.errorbar(hard_counts5,intensity5,xerr=hard_unc_counts5,yerr=intensity_unc5,fmt='^',mfc='none') -plt.errorbar(hard_counts6,intensity6,xerr=hard_unc_counts6,yerr=intensity_unc6,fmt='^',mfc='none') -plt.legend(('58230-58280','58290-58300','58310-58335','58340-58355','58380-58420','58460-58520'),loc='best') +plt.errorbar(hard_color_common,intensity_common,xerr=hard_color_unc_common,yerr=intensity_unc_common,fmt='^',mfc='none') +#plt.errorbar(hard_counts1,intensity1,xerr=hard_unc_counts1,yerr=intensity_unc1,fmt='^',mfc='none') +#plt.errorbar(hard_counts2,intensity2,xerr=hard_unc_counts2,yerr=intensity_unc2,fmt='^',mfc='none') +#plt.errorbar(hard_counts3,intensity3,xerr=hard_unc_counts3,yerr=intensity_unc3,fmt='^',mfc='none') +#plt.errorbar(hard_counts4,intensity4,xerr=hard_unc_counts4,yerr=intensity_unc4,fmt='^',mfc='none') +#plt.errorbar(hard_counts5,intensity5,xerr=hard_unc_counts5,yerr=intensity_unc5,fmt='^',mfc='none') +#plt.errorbar(hard_counts6,intensity6,xerr=hard_unc_counts6,yerr=intensity_unc6,fmt='^',mfc='none') +#plt.legend(('58230-58280','58290-58300','58310-58335','58340-58355','58380-58420','58460-58520'),loc='best') +plt.xscale('log') plt.xlabel('Hard Color: ' + band4+'/'+band3,fontsize=12) plt.ylabel('Intensity (ct/s)',fontsize=12) diff --git a/Lv3_ngc300x1_prof_xmm.py b/Lv3_ngc300x1_prof_xmm.py new file mode 100644 index 0000000..485f900 --- /dev/null +++ b/Lv3_ngc300x1_prof_xmm.py @@ -0,0 +1,305 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +Created on Fri Aug 7 11:14am 2020 + +Analyzing the folded orbital profiles of NGC 300 X-1 with XMM-Newton data + +""" +from __future__ import division, print_function +import numpy as np +from astropy.io import fits +import matplotlib.pyplot as plt +import glob +from scipy.interpolate import interp1d +from scipy.optimize import curve_fit +import subprocess +import pathlib +import math +#from stingray.pulse.pulsar import pulse_phase + +##### The data + +eventfile_pn = '/Volumes/Samsung_T5/NGC300_XMMdata/ngc300x1_pn.evt' +offset_pn = 0.09249852833769791 +times_pn = fits.open(eventfile_pn)[1].data['TIME'] +#phases_pn = pulse_phase(times_pn-times_pn[0],8.4712e-6,ph0=offset_pn) +gtis_pn = fits.open(eventfile_pn)[59].data #59 for pn, 15 for mos1, 19 for mos2 +T_pn = sum([ gtis_pn[i]['STOP']-gtis_pn[i]['START'] for i in range(len(gtis_pn)) ]) #exposure time + +eventfile_mos1 = '/Volumes/Samsung_T5/NGC300_XMMdata/ngc300x1_mos1.evt' +offset_mos1 = 0.08930142107215873 +times_mos1 = fits.open(eventfile_mos1)[1].data['TIME'] +#phases_mos1 = pulse_phase(times_mos1-times_mos1[0],8.4712e-6,ph0=offset_mos1) +gtis_mos1 = fits.open(eventfile_mos1)[15].data #59 for pn, 15 for mos1, 19 for mos2 +T_mos1 = sum([ gtis_mos1[i]['STOP']-gtis_mos1[i]['START'] for i in range(len(gtis_mos1)) ]) #exposure time + +eventfile_mos2 = '/Volumes/Samsung_T5/NGC300_XMMdata/ngc300x1_mos2.evt' +offset_mos2 = 0.06837599396512264 +times_mos2 = fits.open(eventfile_mos2)[1].data['TIME'] +#phases_mos2 = pulse_phase(times_mos2-times_mos2[0],8.4712e-6,ph0=offset_mos2) +gtis_mos2 = fits.open(eventfile_mos2)[19].data #59 for pn, 15 for mos1, 19 for mos2 +T_mos2 = sum([ gtis_mos2[i]['STOP']-gtis_mos2[i]['START'] for i in range(len(gtis_mos2)) ]) #exposure time + +MJDREF = fits.open(eventfile_pn)[1].header['MJDREF'] + +phases = np.arange(0.025,2,0.05) +##### FOR PN: +pn_prof = np.array([1604.0,2164.0,1937.4058099752326,2676.0,3300.0,3839.637730914639,4038.0,4056.0,3540.7859071725998,2140.5, 3804.0,3668.75965331829,3826.5,3006.0, +1034.213403644357,1404.0,483.0,703.8586733495172,474.2092322833178,487.5]*2)/T_pn +pn_inter = interp1d(phases,pn_prof,kind='cubic') +pn_prof_err = np.array([40.049968789001575,46.51881339845203,55.65052783180561,89.5991071384085,99.49874371066204,107.4471256562774,110.06361796706489,110.30865786510145,100.06852620303427, +56.66348030257233,75.53806987208498,74.28709253420669,75.76113779504647,67.14908785679812,39.400392759523484,45.89117562233503,26.916537667389523,32.50117373800949, +26.67635348746897,27.04163456597996]*2)/T_pn + +##### FOR MOS1: +mos1_prof = np.array([448.0,572.0,645.7875788096308,864.0,1152.0,1032.3053915630078,1167.0,1236.0,978.8970623790145,676.5,1014.0,1073.182141931018,1099.5,943.5, +444.50831287810894,507.0,318.0,210.0,208.69091755823553,178.58161485859577]*2)/T_mos1 +mos1_inter = interp1d(phases,mos1_prof,kind='cubic') +mos1_prof_err = np.array([21.166010488516726,23.916521486202797,29.055356803825024,50.911688245431435,58.78775382679629,55.73925190095661,59.169248769948084,60.89334939055334, +48.883786528584615,31.855140872392965,38.99999999999997,40.190987067477344,40.610959112042714,37.61980861195333,25.8365208870395,27.57716446627533,21.840329667841537, +17.748239349298878, 17.700932599765082, 16.37054979377456]*2)/T_mos1 + +##### FOR MOS2: +mos2_prof = np.array([336.0,651.0,588.6128641386009,855.3569611778419,1308.0,1011.0,1218.0,1116.0,1323.0,804.5623109294818,1038.0,1129.4531069776747,1100.2580003973176,1054.5, +759.8367288864442,486.4282601354391,439.5,171.0,304.56707598060035,150.0]*2)/T_mos2 +mos2_inter = interp1d(phases,mos2_prof,kind='cubic') +mos2_prof_err = np.array([18.33030277982336,25.514701644346147,24.9179694998494,44.77142958345511,62.64183905346333,55.07267925205741,60.44832503882968,57.86190456595775,63.0,36.57101413315826, +39.458839313897684,41.21432922222213,40.63895649552821,39.77122075068852,33.77886277372683,27.023792229746615,25.675864152935514,16.015617378046993,21.376418084077713,15.0]*2)/T_mos2 + +def step_n_ramp(phase,prof,prof_err,start_phase,end_phase,pguess): + """ + Fitting 6-model step-and-ramp parameters to the folded profile + """ + phase_model = np.linspace(start_phase,end_phase,101) + x = phase[(phase>=start_phase)&(phase<=end_phase)] + y = prof[(phase>=start_phase)&(phase<=end_phase)] + y_err = prof_err[(phase>=start_phase)&(phase<=end_phase)] + + def piecewise_linear(x,b1,b2,b3,b4,top,bottom): + return np.piecewise(x, [(x>=start_phase)&(x<=b1), (x>b1)&(x<=b2), (x>b2)&(x<=b3), (x>b3)&(x<=b4), (x>b4)&(x<=end_phase)], [lambda x:top, lambda x:((bottom-top)/(b2-b1)*x+bottom-(bottom-top)/(b2-b1)*b2), lambda x:bottom, lambda x:((top-bottom)/(b4-b3)*x+top-(top-bottom)/(b4-b3)*b4), lambda x:top]) + + plt.figure() + popt,pcov = curve_fit(piecewise_linear,x,y,p0=pguess,sigma=y_err,absolute_sigma=True) + pars = popt + pars_err = np.diag(np.sqrt(pcov)) + print('Top: ' + str(pars[4]) + ' +- ' + str(pars_err[4])) + print('Bottom: ' + str(pars[5]) + ' +- ' + str(pars_err[5])) + print('Vertex 1: ' + str(pars[0]) + ' +- ' + str(pars_err[0])) + print('Vertex 2: ' + str(pars[1]) + ' +- ' + str(pars_err[1])) + print('Vertex 3: ' + str(pars[2]) + ' +- ' + str(pars_err[2])) + print('Vertex 4: ' + str(pars[3]) + ' +- ' + str(pars_err[3])) + plt.plot(phase_model,piecewise_linear(phase_model,*popt),'k-') + + ##### Plotting the folded profiles themselves + plt.errorbar(x=phase,y=prof,yerr=prof_err,color='r',drawstyle='steps-mid') + plt.title('Exposure-corrected (profiles from Stingray)',fontsize=12) + plt.xlabel('Phase',fontsize=12) + plt.ylabel('Counts/s',fontsize=12) + plt.legend(('Piecewise fit','Exposure-corrected profile'),loc='best',fontsize=12) + +def plot_profs(interpolate): + spacing = 0.05/20 + phases_long = np.arange(0.025,1.975+spacing,spacing) + + plt.figure() + if interpolate == False: + plt.errorbar(x=phases,y=pn_prof,yerr=pn_prof_err,color='r',drawstyle='steps-mid') + plt.errorbar(x=phases,y=mos1_prof,yerr=mos1_prof_err,color='b',drawstyle='steps-mid') + plt.errorbar(x=phases,y=mos2_prof,yerr=mos2_prof_err,color='k',drawstyle='steps-mid') + plt.legend(('PN','MOS1','MOS2'),loc='best',fontsize=12) + if interpolate == True: + plt.plot(phases_long,pn_inter(phases_long),'r--') + plt.plot(phases_long,mos1_inter(phases_long),'b--') + plt.plot(phases_long,mos2_inter(phases_long),'k--') + plt.legend(('PN interp1d','MOS1 interp1d','MOS2 interp1d'),loc='best',fontsize=12) + elif interpolate == 'both': + plt.errorbar(x=phases,y=pn_prof,yerr=pn_prof_err,color='r',drawstyle='steps-mid') + plt.plot(phases_long,pn_inter(phases_long),'r--') + plt.errorbar(x=phases,y=mos1_prof,yerr=mos1_prof_err,color='b',drawstyle='steps-mid') + plt.plot(phases_long,mos1_inter(phases_long),'b--') + plt.errorbar(x=phases,y=mos2_prof,yerr=mos2_prof_err,color='k',drawstyle='steps-mid') + plt.plot(phases_long,mos2_inter(phases_long),'k--') + plt.legend(('PN','PN interp1d','MOS1','MOS1 interp1d','MOS2','MOS2 interp1d'),loc='best',fontsize=12) + + plt.title('Exposure-corrected (using Stingray fold_events)',fontsize=12) + plt.xlabel('Phase',fontsize=12) + plt.ylabel('Counts/s',fontsize=12) + plt.show() + +def shift_profs(nbins,prof,prof_err,offset): + """ + Shifting the profiles by a constant factor in Fourier space + """ + ##### Shifting pulse profiles through a shifted FT (see Deepto's 7/20/2020 email) + if nbins % 2 == 0: + fft_x = np.array(list(np.arange(int(nbins/2)+1)) + list(np.arange(int(nbins/2)-1) - (int(nbins/2)-1))) + else: + fft_x = np.array(list(np.arange(int(nbins/2)+1)) + list(np.arange(int(nbins/2)) - int(nbins/2))) + + shift = np.exp(-2j*np.pi*fft_x*offset/nbins) + shifted_prof = np.real(np.fft.ifft(np.fft.fft(prof)*shift)) #taking the real component of the inverse transform of the shifted Fourier transform of the original folded profile + shifted_err = np.real(np.fft.ifft(np.fft.fft(prof_err)*shift)) #taking the real component of the inverse transform of the shifted Fourier transform of the original folded profile + + return shift,shifted_prof,shifted_err + +def update_fits(eventfile,phases): + """ + Updating the event file with the orbital phases + """ + events = fits.open(eventfile,mode='update') + if 'ORBPHASE' in events[1].columns.names: + print("ORBPHASE exists already; so overwriting...") + events[1].data['ORBPHASE'] = phases + else: + print("ORBPHASE does not exist, so adding it into the event file") + datacol = [fits.ColDefs( [fits.Column(name='ORBPHASE',format="D",array=phases) ])] + cols = events[1].columns + cols = cols + datacol[0] #adding in the info for ORBPHASE + bt = fits.BinTableHDU.from_columns(cols,header=events[1].header,name=events[1].name) + events[1] = bt + + events.flush() + +def ftselect_phase(instrument): + #phase_range = np.arange(0,1.01,0.05) + phase_range = np.array([0.25,0.8,0.8,0.9,0.9,0.1,0.1,0.25]) + ftselect_txt = open('/Volumes/Samsung_T5/NGC300_XMMdata/ftselect_onoffiegress.txt','w') + for i in range(0,len(phase_range)-1,2): + input_events = '/Volumes/Samsung_T5/NGC300_XMMdata/ngc300x1_' + instrument + '.evt' + output_file = '/Volumes/Samsung_T5/NGC300_XMMdata/phase_res_spec/ngc300x1_' + instrument + '_' + str(int(phase_range[i]*100)).zfill(3) + '-' + str(int(phase_range[i+1]*100)).zfill(3) + '.evt' + #subprocess.run(['ftselect',input_events+'[events]',output_file,'ORBPHASE >= ' + str(phase_range[i]) + ' && ORBPHASE < ' + str(phase_range[i+1]),'clobber=yes']) + ftselect_txt.write('ftselect ' + input_events+'[events]' + ' ' + output_file + ' ' + 'ORBPHASE >= ' + str(phase_range[i]) + ' && ORBPHASE < ' + str(phase_range[i+1]) + ' ' + 'clobber=yes' + '\n') + ftselect_txt.close() + + return + +def evselect_instructions(instrument): + """ + Create a set of instructions to extract spectra from the phase-resolved event files + """ + if instrument != 'mos1' and instrument != 'mos2' and instrument != 'pn': + raise ValueError('Make sure that the instrument is either mos1, mos2, or pn!') + + instructions = open('/Volumes/Samsung_T5/NGC300_XMMdata/phase_res_spec/evselect_' + instrument + '_instructions.txt','w') + eventfiles = glob.glob('/Volumes/Samsung_T5/NGC300_XMMdata/phase_res_spec/*' + instrument+'*.evt') + + for i in range(len(eventfiles)): + if instrument == 'mos1' or instrument == 'mos2': + instructions.write('evselect table='+eventfiles[i]+' withspectrumset=yes spectrumset=' + eventfiles[i][:-3]+'pha energycolumn=PI spectralbinsize=5 withspecranges=yes specchannelmin=0 specchannelmax=11999') + elif instrument == 'pn': + instructions.write('evselect table='+eventfiles[i]+' withspectrumset=yes spectrumset=' + eventfiles[i][:-3]+'pha energycolumn=PI spectralbinsize=5 withspecranges=yes specchannelmin=0 specchannelmax=20479') + + instructions.write('\n') + +def grppha_instructions(instrument): + """ + Create a set of instructions to introduce a grouping column onto the phase-resolved spectral files + """ + if instrument != 'mos1' and instrument != 'mos2' and instrument != 'pn': + raise ValueError('Make sure that the instrument is either mos1, mos2, or pn!') + + instructions = open('/Volumes/Samsung_T5/NGC300_XMMdata/phase_res_spec/grppha_' + instrument + '_instructions.txt','w') + spectra = glob.glob('/Volumes/Samsung_T5/NGC300_XMMdata/phase_res_spec/ngc300x1*' + instrument+'*.pha') + + for i in range(len(spectra)): + spectrum_file = str(pathlib.Path(spectra[i]).name) + if instrument == 'pn': + instructions.write('grppha infile="' + spectrum_file + '" outfile="grp_' + spectrum_file + '" chatter=0 comm="group pn_channels_to_group.dat & systematics 60 2000 0.02 & exit"') + elif instrument == 'mos1' or instrument == 'mos2': + instructions.write('grppha infile="' + spectrum_file + '" outfile="grp_' + spectrum_file + '" chatter=0 comm="group mos_channels_to_group.dat & systematics 60 2000 0.02 & exit"') + + instructions.write('\n') + +if __name__ == "__main__": + #plot_profs('both') + + print('Step and Ramp model for PN:') + step_n_ramp(phases,pn_prof,pn_prof_err,0.225,1.675,np.array([0.65,0.75,1,1.25,0.016,0.0035])) + + #print('Step and Ramp model for MOS1:') + #step_n_ramp(phases,mos1_prof,mos1_prof_err,0.225,1.675,np.array([0.67,0.8,1,1.25,0.0045,0.001])) + + #print('Step and Ramp model for MOS2:') + #step_n_ramp(phases,mos2_prof,mos2_prof_err,0.225,1.675,np.array([0.625,0.75,1,1.25,0.0045,0.001])) + + plt.show() + + pn_v2 = 0.735155769390959 + pn_v2_err = 0.0013104756938545274 + pn_v3 = 0.9734922065666258 + pn_v3_err = 0.0025331177762865694 + + eclipse_ph = (pn_v2 + pn_v3)/2 + eclipse_ph_err = np.sqrt( (pn_v2_err/2)**2 + (pn_v3_err/2)**2 ) + #print(eclipse_ph,eclipse_ph_err) + + Porb_days = (1/8.4712e-6)/86400 + Porb_days_err = (0.00296e-6/(8.4712e-6)**2)/86400 #make sure to change!! Recall this is from FR/RSS simulations with 40% completeness + #print(Porb_days) + #print(Porb_days_err) + #print(Porb_days,Porb_days_err) + T0_xmm_MJD = fits.open(eventfile_pn)[1].header['MJDREF'] +(fits.open(eventfile_pn)[1].data['TIME'][0]+eclipse_ph*1/8.4712e-6)/86400 + T0_xmm_err = (eclipse_ph_err*1/8.4712e-6)/86400 + + T0_swift_MJD = 58239.3498 + T0_swift_err = 0.0208 + + no_cycles = (T0_swift_MJD - T0_xmm_MJD)/Porb_days + no_cycles_err = np.sqrt( (T0_swift_err/Porb_days)**2 + (T0_xmm_err/Porb_days)**2 + ((T0_swift_err-T0_xmm_err)/Porb_days**2)*Porb_days_err**2 ) + #print(no_cycles,no_cycles_err) + + shift,shift_pn_prof,shift_pn_err = shift_profs(20,pn_prof[:20],pn_prof_err[:20],eclipse_ph) + #shift,shift_mos1_prof,shift_mos1_err = shift_profs(20,mos1_prof[:20],mos1_prof_err[:20],eclipse_ph) + #shift,shift_mos2_prof,shift_mos2_err = shift_profs(20,mos2_prof[:20],mos2_prof_err[:20],eclipse_ph) + + """ + plt.errorbar(x=phases,y=np.array(list(shift_pn_prof)*2),yerr=np.array(list(shift_pn_err)*2),drawstyle='steps-mid') + #plt.errorbar(x=phases,y=np.array(list(shift_mos1_prof)*2),yerr=np.array(list(shift_mos1_err)*2),drawstyle='steps-mid') + #plt.errorbar(x=phases,y=np.array(list(shift_mos2_prof)*2),yerr=np.array(list(shift_mos2_err)*2),drawstyle='steps-mid') + plt.title('Exposure-corrected (using Stingray fold_events), shifted by factor of ' + str(eclipse_ph),fontsize=12) + plt.xlabel('Phase',fontsize=12) + plt.ylabel('Counts/s',fontsize=12) + #plt.legend(('PN','MOS1','MOS2'),loc='best',fontsize=12) + plt.show() + """ + + #### Updating the FITS files with the orbital phase! + #update_fits(eventfile_pn,phases_pn) + #update_fits(eventfile_mos1,phases_mos1) + #update_fits(eventfile_mos2,phases_mos2) + + #ftselect_phase('pn') + #ftselect_phase('mos1') + #ftselect_phase('mos2') + + #### CHECKING THE INCLUSION OF ORBPHASE INTO THE EVENT FILES + #newphases_pn = fits.open(eventfile_pn)[1].data['ORBPHASE'] + #newphases_mos1 = fits.open(eventfile_mos1)[1].data['ORBPHASE'] + #newphases_mos2 = fits.open(eventfile_mos2)[1].data['ORBPHASE'] + + #newprof_pn,bins = np.histogram(newphases_pn,bins=np.linspace(0,1,21)) + #newprof_mos1,bins = np.histogram(newphases_mos1,bins=np.linspace(0,1,21)) + #newprof_mos2,bins = np.histogram(newphases_mos2,bins=np.linspace(0,1,21)) + #plt.errorbar(bins[:-1],newprof_pn,drawstyle='steps-mid') + #plt.errorbar(bins[:-1],newprof_mos1,drawstyle='steps-mid') + #plt.errorbar(bins[:-1],newprof_mos2,drawstyle='steps-mid') + #plt.show() + + ##### Get the phase offset between Swift eclipse time and XMM's first event time: + xmm_first_pn = MJDREF + times_pn[0]/86400 + xmm_ecl = T0_swift_MJD - int(no_cycles)*Porb_days #time of the mid-eclipse BEFORE the first XMM event + if xmm_ecl > xmm_first_pn: + xmm_ecl -= Porb_days + phaseoff_pn = (xmm_first_pn-xmm_ecl)/Porb_days + #print(phaseoff_pn) + + ##### Appending background file, + #evselect_instructions('pn') + #evselect_instructions('mos1') + #evselect_instructions('mos2') + + ##### Adding the grouping column to the spectral files + #grppha_instructions('pn') + #grppha_instructions('mos1') + #grppha_instructions('mos2') diff --git a/Lv3_nicer_archival.py b/Lv3_nicer_archival.py old mode 100644 new mode 100755 index 872da91..9092673 --- a/Lv3_nicer_archival.py +++ b/Lv3_nicer_archival.py @@ -13,6 +13,12 @@ - Power spectral stacking - semi-coherent searches +NOTE on 4/23/2020: Perhaps create a "text" mode for averaged spectra, when I first run +with "save" where it saves both the plot AND a text file of Leahy-normalized power +vs frequency; then when I want to retrieve it again, just plot data from the text +file instead of going through the whole mess of re-calculating the averaged power spectrum... +I should save things like number of segments used, threshold etc. in the text file though! + """ from __future__ import division, print_function from astropy.io import fits @@ -36,19 +42,26 @@ start_time = time.time() if __name__ == "__main__": - obsdirs = [Lv0_dirs.NICER_DATADIR + '00' + str(i) +'/' for i in range(34070101,34070105)] +# obsdirs = [Lv0_dirs.NICER_DATADIR + '1034100' + str(i) +'/' for i in range(101,121)] + [Lv0_dirs.NICER_DATADIR + '1034100' + str(i) +'/' for i in range(122,128)] + #obsdirs = [Lv0_dirs.NICER_DATADIR + '1030180' + str(i) + '/' for i in range(101,131)] + [Lv0_dirs.NICER_DATADIR + '1030180' + str(i) + '/' for i in range(149,188)] + [Lv0_dirs.NICER_DATADIR + '3614020' + str(i) + '/' for i in range(101,121)] + #obsdirs = [Lv0_dirs.NICER_DATADIR + '1030180' + str(i) + '/' for i in range(101,188)] + #obsdirs = [Lv0_dirs.NICER_DATADIR + '3614020' + str(i) + '/' for i in range(101,121)] + obsdirs = [Lv0_dirs.NICER_DATADIR + '3201710' + str(i) + '/' for i in range(138,158)] nicer_obsids = [obsdirs[i][-11:-1] for i in range(len(obsdirs))] - eventfiles = [Lv0_dirs.NICERSOFT_DATADIR + nicer_obsids[i] + '_pipe/ni' + nicer_obsids[i] + '_nicersoft_bary.evt' for i in range(len(obsdirs))] +# eventfiles = [Lv0_dirs.NICERSOFT_DATADIR + nicer_obsids[i] + '_pipe/ni' + nicer_obsids[i] + '_nicersoft_bary.evt' for i in range(len(obsdirs))] + #eventfiles = ['/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/ngc300x1/lightcurve/ngc300x1_merge_niceroverlap_all.evt'] +# eventfiles = ['/Volumes/Samsung_T5/NICERsoft_outputs/0034070101_pipe/ni0034070101_nicersoft_bary.evt'] -############################# PREPROCESSING PARAMETERS ############################ + #eventfiles = ['/Volumes/Samsung_T5/NGC300_XMMdata/0791010101/PROC/xmm_0791010101_lccorr.evt'] +######################## PREPROCESSING PARAMETERS ############################ do_preprocess = False #scp, unzips, runs nicerl2, runs psrpipe, and then barycorr - if do_preprocess == True: - for i in range(len(nicer_obsids)): - Lv0_scp.scp(nicer_obsids[i]) + #if do_preprocess == True: + #for i in range(len(nicer_obsids)): + # Lv0_scp.scp(nicer_obsids[i]) - nicerl2_flags = ['clobber=YES','ang_dist=0.035'] - psrpipe_flags = ['--emin','0.3','--emax','12.0','--angdist','0.035'] #for psrpipe in Lv0_psrpipe + nicerl2_flags = ['clobber=YES','underonly_range=0-650'] + psrpipe_flags = ['--emin','0.3','--emax','12.0','--nounderfilt','--mask','34','43'] #for psrpipe in Lv0_psrpipe refframe = 'ICRS' parfile = '' @@ -57,15 +70,15 @@ ############################## MERGING PARAMETERS ############################## do_merge = True - merged_yet = True - merged_id = '000014' + merged_yet = False + merged_id = '000027' if do_merge == True: #Lv2_merging_events is put higher up because it's quite important! if merged_yet == False: #if the ObsIDs haven't been merged yet - Lv2_merging_events.merging(nicer_obsids) - Lv2_merging_events.merging_GTIs(nicer_obsids,merged_id) + Lv2_merging_events.merging(nicer_obsids,merged_id) #### will add in an interface with cr_cut.py at some point...! eventfiles = [Lv0_dirs.NICERSOFT_DATADIR + 'merged_events/merged' + merged_id + '/merged' + merged_id + '_nicersoft_bary.evt'] + #eventfiles = ['/Volumes/Samsung_T5/NGC300_ULX_Swift/ngc300x-1/xrt/event/merge_pocl_all.evt'] ################################################################################ ######################### LC_PS_PHASE_COLOR PARAMETERS ######################### @@ -83,42 +96,48 @@ process_segments = True #whether to make truncations to the data time_segments = True #truncate by time segments - energy_segments = True #truncate by energy range + gti_segments = True #truncate by GTI segments + energy_segments = False #truncate by energy range time_energy_segments = True #truncate both by time segments and energy range accelsearch = True prepfold = True - tbin = '1' #time bin for PRESTO in seconds + ### for gti_segments + gap = 5 #seconds + gtifile = 'bunched.gti' + + tbin = '0.00025' #time bin for PRESTO in seconds ##### From Lv2_presto_all ##### For when we analyze the entire data set (no truncations in energy or time) - accelsearch_flags = ['-numharm','4','-zmax','10','-photon','-flo','0.1','-fhi','1'] + accelsearch_flags = ['-numharm','4','-zmax','100','-photon','-flo','0.1','-fhi','2000'] ##### Parameters for prepfold - zmax = 10 + zmax = 100 ##### From Lv2_presto_subroutines - segment_lengths = [10000] #desired length of segments in seconds - PI1 = [30,300] - PI2 = [300,1200] + segment_lengths = [500] #desired length of segments in seconds + PI1 = [30,200] + PI2 = [200,1200] ################################################################################ ############################ AVERAGE_PS PARAMETERS ############################# do_average_ps = False if do_average_ps == True: demod = False - preprocessing = False #getting GTIs, running niextract, nicerfits2presto, edit_inf, edit_bin, and realfft! - time_segments = True + preprocessing = True #getting GTIs, running niextract, nicerfits2presto, edit_inf, edit_bin, and realfft! + time_segments = False time_energy_segments = True mode = 't' - segment_lengths = [500] #desired length of segments in seconds - PI1 = [''] - PI2 = [''] + segment_lengths = [500,1000] #desired length of segments in seconds + PI1 = [30,200] + PI2 = [200,1200] par_file = '' - tbin = 1 #bin size in s - threshold = 5 #threshold for counts in each segment (in 1s bins; in terms of a percentage) - W = 1 #number of consecutive Fourier bins to average over - starting_freq = 0.1 #for the noise histogram + tbin = 0.5 #bin size in s + threshold = [5,10,20,30,40,50] #threshold for counts in each segment (in 1s bins; in terms of a percentage) + W = [1] #number of consecutive Fourier bins to average over + hist_min_sig = 2.5 + starting_freq = 0.02 #for the noise histogram xlims = np.array([]) plot_mode = "save" @@ -127,7 +146,7 @@ ############################# SEARCH_BIN PARAMETERS ############################ ##### SIDEBAND SEARCHES do_searchbin = False - fft_files = [eventfiles[i][:-3] + 'fft' for i in range(len(eventfiles))] + #fft_files = [eventfiles[i][:-3] + 'fft' for i in range(len(eventfiles))] ncand = 1000 #no. of candidates to try to return ; default 100 (1 to 1000) flo = 1 #the lowest frequency to check fhi = 1000 #the highest frequency to check @@ -138,7 +157,7 @@ ############################# EF_SEARCH PARAMETERS ############################# ##### EPOCH FOLDING - do_efsearch = True + do_efsearch = False if do_efsearch == True: n_segments = 100 #number of segments to break the epoch folding search into dper = 4.80 #Value for the period used in the folding. In 'efsearch' the @@ -165,16 +184,16 @@ Lv2_preprocess.preprocess(obsdirs[i],nicerl2_flags,psrpipe_flags,refframe,orbitfiles[i],parfile,nicer_datafile[i],nicer_output[i],nicersoft_datafile[i],nicersoft_output[i],nicersoft_folder[i],custom_coords) if do_lc_ps_phase_color == True: #would only be useful for looking at the whole time series? Might be of limited usage depending on what I want to use it for. - par_list = ['PI','PI_FAST','TIME'] #parameter list from event_cl - tbin_size = 1 #how you want to bin the light curve data + par_list = ['PI','TIME'] #parameter list from event_cl + tbin_size = 100 #how you want to bin the light curve data Ebin_size = 0.05 #in keV mode = 'show' #probably best to 'save' if using a LARGE set of ObsIDs! truncations = 'all' #'all', 't', 'E', or 'tE', depending on whether we want to look at entire time series (all), or truncation by time interval (t), or time truncation by energy range (E), or truncation by both (tE) lc = True - ps = True - phase = True - color = True + ps = False + phase = False + color = False ############################################################################### #### DEFINE DESIRED TIME INTERVALS AND ENERGY RANGES HERE FOR: @@ -182,22 +201,22 @@ # Lv2_phase - partial_t, partial_E, partial_tE # Lv2_color - plotting_t - t1 = 2629580 - t2 = 2630180 - E1 = 0.3 - E2 = 2.5 + t1 = 1200 + t2 = 56420 + E1 = 3 + E2 = 12 #for Lv2_ps - ps_type = 'manual' # 'period' (for periodogram) or 'manual' (for FFT) or 'both' + ps_type = 'both' # 'period' (for periodogram) or 'manual' (for FFT) or 'both' oversampling = [False,5] # [False to NOT oversample, oversampling factor - 5 to oversample by factor of 5. (factor-1) sets of 0s are padded.] xlims = [False,0,5] # [False to NOT impose xlimit on plots; 2nd/3rd entries are the desired x-limits if needed.] - vlines = [True,0.2081] # [False to NOT draw a vertical line on the plot; 2nd entry is the equation for the vertical line, e.g. x=2] + vlines = [False,0.2081] # [False to NOT draw a vertical line on the plot; 2nd entry is the equation for the vertical line, e.g. x=2] #for Lv2_phase ### For an unknown observation, one should run JUST Lv2_lc and Lv2_ps first to get ### the pulsation frequencies. Pulse profiles come LATER. ### If I have pulse_pars[1] and pulse_pars[2] != 0, then time binning DOES NOT MATTER, i.e., it'll be counts/s! - pulse_pars = [0.2081,0,0] + pulse_pars = [8.461664906286253e-06,0,0] #[8.45162E-6,0,0] shift = 0.4 # how much to shift the pulse by in the phase axis. It only affects how the pulse profile is 'displaced'. no_phase_bins = 20 # number of phase bins desired @@ -205,7 +224,7 @@ E1_data = 0.3 #data is reliable between 0.3 and 12 keV E2_data = 12 # in keV cut_type = 'manual' # 'manual' cut for boundary energy, or 'median' - for half number of counts - bound = 2.7 # boundary energy for when cut_type = 'manual'! + bound = 1.0 # boundary energy for when cut_type = 'manual'! for i in range(len(eventfiles)): E_bound = Lv3_E_boundary.E_bound(eventfiles[i],par_list,E1_data,E2_data,cut_type,bound) #use Lv3_E_boundary to get boundary energy @@ -264,7 +283,7 @@ Lv2_color.plotting_t(eventfiles[i],par_list,E_bound,tbin_size,t1,t2,mode) if do_average_ps == True: - for k in range(0,len(PI1),2): + for k in range(0,len(PI1)): for j in range(len(segment_lengths)): for i in range(len(eventfiles)): N = Lv3_detection_level.N_trials(tbin,segment_lengths[j]) @@ -285,13 +304,15 @@ Lv2_average_ps_methods.edit_binary(eventfiles[i],tbin,segment_lengths[j]) Lv2_average_ps_methods.realfft(eventfiles[i],segment_lengths[j]) - Lv2_average_ps_methods.plotting(eventfiles[i],segment_lengths[j],demod,tbin,threshold,PI1[k],PI2[k],starting_freq,W,N,xlims,plot_mode) + for x in range(len(W)): + for y in range(len(threshold)): + Lv2_average_ps_methods.plotting(eventfiles[i],segment_lengths[j],demod,tbin,threshold[y],PI1[k],PI2[k],starting_freq,W[x],hist_min_sig,N,xlims,plot_mode) if do_presto == True: if process_all == True: if conv_fits2presto == True: for i in range(len(eventfiles)): - Lv2_presto_subroutines.do_nicerfits2presto(eventfiles[i],tbin,0) + Lv2_presto_subroutines.do_nicerfits2presto(eventfiles[i],tbin,0,'all') if accelsearch == True: print('Doing realfft/accelsearch now!') @@ -317,20 +338,25 @@ Lv2_presto_subroutines.get_gti_file(eventfiles[i],segment_lengths[j]) #make GTI files for each segment Lv2_presto_subroutines.niextract_gti_time(eventfiles[i],segment_lengths[j]) #performing niextract-events - Lv2_presto_subroutines.do_nicerfits2presto(eventfiles[i],tbin,segment_lengths[j]) + Lv2_presto_subroutines.do_nicerfits2presto(eventfiles[i],tbin,segment_lengths[j],'t') Lv2_presto_subroutines.edit_inf(eventfiles[i],tbin,segment_lengths[j]) Lv2_presto_subroutines.edit_binary(eventfiles[i],tbin,segment_lengths[j]) # Lv3_duty_cycle.duty_cycle(eventfiles[i],tbin,segment_lengths[j],duty_cycle_bin,threshold) # Lv3_duty_cycle.duty_cycle_dist(eventfiles[i],tbin,segment_lengths[j],duty_cycle_bin,threshold) + if gti_segments == True: + for i in range(len(eventfiles)): + Lv2_presto_subroutines.niextract_gti(eventfiles[i],gap,gtifile) + Lv2_presto_subroutines.do_nicerfits2presto(eventfiles[i],tbin,0,'gtis') + if energy_segments == True and preprocess_segments == True: if len(PI1) != len(PI2): raise ValueError("Make sure that the length of PI1 and PI2 are the same! Need pairs of PI values.") for j in range(len(PI1)): for i in range(len(eventfiles)): Lv2_presto_subroutines.niextract_gti_energy(eventfiles[i],PI1[j],PI2[j]) - Lv2_presto_subroutines.do_nicerfits2presto(eventfiles[i],tbin,0) #segment_length makes no sense, so 0 is a placeholder + Lv2_presto_subroutines.do_nicerfits2presto(eventfiles[i],tbin,0,'E') #segment_length makes no sense, so 0 is a placeholder if time_energy_segments == True and preprocess_segments == True: for j in range(len(segment_lengths)): @@ -339,7 +365,7 @@ for k in range(len(PI1)): Lv2_presto_subroutines.niextract_gti_time_energy(eventfiles[i],segment_lengths[j],PI1[k],PI2[k]) - Lv2_presto_subroutines.do_nicerfits2presto(eventfiles[i],tbin,segment_lengths[j]) + Lv2_presto_subroutines.do_nicerfits2presto(eventfiles[i],tbin,segment_lengths[j],'t') Lv2_presto_subroutines.edit_inf(eventfiles[i],tbin,segment_lengths[j]) Lv2_presto_subroutines.edit_binary(eventfiles[i],tbin,segment_lengths[j]) @@ -354,6 +380,10 @@ for i in range(len(eventfiles)): Lv2_presto_subroutines.realfft(eventfiles[i],segment_lengths[j],'t') Lv2_presto_subroutines.accelsearch(eventfiles[i],segment_lengths[j],'t',accelsearch_flags) + if gti_segments == True: + for i in range(len(eventfiles)): + Lv2_presto_subroutines.realfft(eventfiles[i],0,'gtis') + Lv2_presto_subroutines.accelsearch(eventfiles[i],0,'gtis',accelsearch_flags) if energy_segments == True: for i in range(len(eventfiles)): Lv2_presto_subroutines.realfft(eventfiles[i],0,'E') @@ -367,6 +397,9 @@ for j in range(len(segment_lengths)): for i in range(len(eventfiles)): Lv2_presto_subroutines.prepfold(eventfiles[i],segment_lengths[j],'t',zmax) + if gti_segments == True: + for i in range(len(eventfiles)): + Lv2_presto_subroutines.prepfold(eventfiles[i],0,'gtis',zmax) if energy_segments == True: for i in range(len(eventfiles)): Lv2_presto_subroutines.prepfold(eventfiles[i],0,'E',zmax) @@ -376,6 +409,9 @@ for j in range(len(segment_lengths)): for i in range(len(eventfiles)): Lv2_presto_subroutines.ps2pdf(eventfiles[i],segment_lengths[j],'t') + if gti_segments == True: + for i in range(len(eventfiles)): + Lv2_presto_subroutines.ps2pdf(eventfiles[i],0,'gtis') if energy_segments == True: for i in range(len(eventfiles)): Lv2_presto_subroutines.ps2pdf(eventfiles[i],0,'E') diff --git a/Lv3_orbitephem_visual.py b/Lv3_orbitephem_visual.py new file mode 100644 index 0000000..f5a6b97 --- /dev/null +++ b/Lv3_orbitephem_visual.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +Created on Wed Jul 15 11:14am 2020 + +Given an orbital ephemeris (really just T0 and orbital period), show visually/graphically +where in the orbit an observation is (e.g., for NICER's NGC 300 ULX-1, whether it's in +eclipse of X-1 or otherwise) + +""" +from __future__ import division, print_function +import numpy as np +from astropy.io import fits +import matplotlib.pyplot as plt +import Lv0_dirs,Lv2_dj_lsp,Lv2_swift_lc,Lv2_phase +import os +from scipy import stats +from scipy.optimize import curve_fit +from tqdm import tqdm +import subprocess +import mplcursors +import pathlib +from stingray.pulse.pulsar import pulse_phase,phase_exposure,fold_events + +def folding(eventfile,Porb,nbins): + """ + Folding the events by some orbital period + """ + times = fits.open(eventfile)[1].data['TIME'] #getting array of times + gtis_data = fits.open(eventfile)[2].data #getting GTIs + T = sum([ gtis_data[i]['STOP']-gtis_data[i]['START'] for i in range(len(gtis_data)) ]) #exposure time + + gtis_conform = [] + for i in range(len(gtis_data)): + gtis_conform.append([gtis_data[i][0],gtis_data[i][1]]) #conform to the input that Stingray uses + + phase_sr,prof_sr,err_sr = fold_events(times,1/Porb,gtis=np.array(gtis_conform),ref_time=times[0],nbin=nbins) + phase_sr_expo,prof_sr_expo,err_sr_expo = fold_events(times,1/Porb,gtis=np.array(gtis_conform),ref_time=times[0],expocorr=True,nbin=nbins) + + total_phase_sr = list(phase_sr) + list(phase_sr+1) + total_prof_sr = list(prof_sr)*2 + total_err_sr = list(err_sr)*2 + + total_phase_sr_expo = list(phase_sr_expo) + list(phase_sr_expo+1) + total_prof_sr_expo = list(prof_sr_expo)*2 + total_err_sr_expo = list(err_sr_expo)*2 + + plt.figure() + plt.errorbar(x=total_phase_sr,y=total_prof_sr/T,yerr=total_err_sr/T,color='r',drawstyle='steps-mid') + plt.errorbar(x=total_phase_sr_expo,y=total_prof_sr_expo/T,yerr=total_err_sr_expo/T,color='b',drawstyle='steps-mid') + plt.legend(('Folded profile','Exposure-corrected'),loc='best',fontsize=12) + plt.title(str(pathlib.Path(eventfile).name) +', exposure-corrected (using Stingray fold_events)',fontsize=12) + plt.xlabel('Phase',fontsize=12) + plt.ylabel('Counts/s',fontsize=12) + + return total_phase_sr_expo,total_prof_sr_expo/T,total_err_sr_expo/T + +def ephemeris(x,y,yerr,eventfile,T0,Porb,nbins): + """ + Plotting the light curve (usually), along with the ephemeris visually + """ + + ##### Figure 1 shows the folded profile ; using stingray.pulse.par's fold_events + phase,prof,prof_err = folding(eventfile,Porb,nbins) + + ##### Figure 2 will superpose the light curve and the ephemeris + plt.figure() + plt.errorbar(x,y,yerr=yerr,color='r',fmt='x') + plt.xlabel('Time (MJD)',fontsize=12) + plt.ylim([np.min(y),1.1*np.max(y)]) + plt.ylabel('Rate (counts/s)',fontsize=12) + + intervals = np.arange(T0,x[-1]+Porb/86400,Porb/86400) #defining EACH orbital cycle, starting with T0 + for i in range(0,len(intervals)-1): + subintervals = np.linspace(intervals[i],intervals[i+1],nbins+1) + plt.axvline(x=intervals[i],color='k') + plt.axvline(x=intervals[i+1],color='k') + plt.errorbar(subintervals,prof[:nbins+1]*(0.5*np.max(y)/np.mean(prof)),yerr=prof_err[:nbins+1]*(0.5*np.max(y)/np.mean(prof)),color='b',drawstyle='steps-mid',alpha=0.5) + + for j in range(len(subintervals)): + plt.axvline(x=subintervals[j],alpha=0.5,lw=0.5,color='k') + + plt.show() + +if __name__ == "__main__": + eventfile = '/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/ngc300x1/ngc300x1_merge_niceroverlap_all.evt' + ##### Running ephemeris + nbins = 20 + Porb = 1/8.4712e-6 + + ##### Calling X-1 light curve data from Swift + bary_outputfolder = '/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/lightcurve/' + obsids = [str(i) for i in range(49834027,49834042)] + [str(i) for i in range(49834043,49834062)] + [str(i) for i in range(49834063,49834066)] + ['88810002'] + [str(i) for i in range(49834066,49834069)] + [str(i) for i in range(49834070,49834079)] + [str(i) for i in range(49834080,49834088)] + corr_lc_files = [bary_outputfolder + 'sw000' + obsids[i] + '_corr.lc' for i in range(len(obsids))] + corr_bg_files = [bary_outputfolder + 'sw000' + obsids[i] + '_bg_corr.lc' for i in range(len(obsids))] + bg_scale_x1 = (30/120)**2 + rebinned_t, rebinned_rate, rebinned_err, rebinned_fracexp = Lv2_dj_lsp.rebin_lc(corr_lc_files,corr_bg_files,bg_scale_x1,100,0.0) + + tstart_49834027 = 546830295.758713 + mjd = fits.open(eventfile)[1].header['MJDREFI'] + fits.open(eventfile)[1].header['MJDREFF'] + (tstart_49834027+rebinned_t)/86400 + T0_MJD = fits.open(eventfile)[1].header['MJDREFI'] + fits.open(eventfile)[1].header['MJDREFF'] + (tstart_49834027)/86400 + + #ephemeris(mjd,rebinned_rate,rebinned_err,eventfile,T0_MJD,Porb,nbins) + + ##### Calling NICER's ULX-1 observations + s1,s2,a,b,c,d,inband,mjd = np.genfromtxt('/Volumes/Samsung_T5/n300_ulx_2020/n300_ulx.bgsub_cl50_g2020norm.fffphot',usecols=(3,4,5,6,7,8,9,11),unpack=True) + ephemeris(mjd,inband,np.zeros(len(inband)),eventfile,T0_MJD,Porb,nbins) diff --git a/Lv3_quicklook.py b/Lv3_quicklook.py index 10eb9ea..8c7bb43 100644 --- a/Lv3_quicklook.py +++ b/Lv3_quicklook.py @@ -74,7 +74,9 @@ def filtering(eventfile,outfile,maskdet,eventflags): subprocess.run(['ftcopy',eventfile+'['+evfilt_expr+']',outfile,'clobber=yes','history=yes']) if __name__ == "__main__": - eventfile = '/Volumes/Samsung_T5/NICER-data/rxj0209/rxj0209kgfilt.evt' + #eventfile = '/Volumes/Samsung_T5/NICER-data/swiftj0044/2004110232.evt' + eventfile = '/Volumes/Samsung_T5/NICER-data/at2020wey/2008041401.evt' + #eventfile = '/Users/masonng/Documents/MIT/Research/xtej1739_burst8/2002251704.evt' ############################# DIAGNOSTIC PARAMETERS ############################ do_diagnostic = False @@ -83,18 +85,21 @@ def filtering(eventfile,outfile,maskdet,eventflags): ############################# FILTERING PARAMETERS ############################# do_filter = False - filtfile = '/Volumes/Samsung_T5/NICER-data/rxj0209/rxj0209kgfilt_filt.evt' + filtfile = '/Volumes/Samsung_T5/NICER-data/xtej1739_burst19+/2002131540_filt.evt' maskdets = [34] eventflags = '(EVENT_FLAGS==bx1x000)' ################################################################################ ############################# BARYCORR PARAMETERS ############################## - do_bary = False - out_baryfile = Lv0_dirs.NICER_DATADIR + 'rxj0209/rxj0209kgfilt_filt_bary.evt' + do_bary = True + out_baryfile = Lv0_dirs.NICER_DATADIR + 'at2020wey/2008041401.evt' + #out_baryfile = '/Users/masonng/Documents/MIT/Research/xtej1739_burst8/2002251704_bary.evt' refframe = 'ICRS' - orbitfile = Lv0_dirs.NICER_DATADIR + 'rxj0209/rxj0209.orb' + orbitfile = Lv0_dirs.NICER_DATADIR + 'at2020wey/2008041401.orb' + #orbitfile = '/Users/masonng/Documents/MIT/Research/xtej1739_burst8/2002251704.orb' parfile = '' - output_folder = Lv0_dirs.NICER_DATADIR + 'rxj0209/' + output_folder = Lv0_dirs.NICER_DATADIR + 'at2020wey/' + #output_folder = '/Users/masonng/Documents/MIT/Research/xtej1739_burst8/' custom_coords = np.array([]) ################################################################################ @@ -109,20 +114,27 @@ def filtering(eventfile,outfile,maskdet,eventflags): ############################### PRESTO PARAMETERS ############################## do_presto = False - conv_fits2presto = False #only for process_all - process_all = False #whether to process the ENTIRE observation or not - process_segments = False #whether to make truncations to the data + conv_fits2presto = True #only for process_all + process_all = True #whether to process the ENTIRE observation or not + + process_segments = True #whether to make truncations to the data time_segments = False #truncate by time segments - energy_segments = False #truncate by energy range + gti_segments = False #truncate by GTI segments + energy_segments = True #truncate by energy range time_energy_segments = False #truncate both by time segments and energy range - accelsearch = False - prepfold = False - tbin = '0.5' #time bin for PRESTO in seconds + accelsearch = True + prepfold = True + + ### for gti_segments + gap = 5 #seconds + gtifile = 'bunched.gti' + + tbin = '0.01' #time bin for PRESTO in seconds ##### From Lv2_presto_all ##### For when we analyze the entire data set (no truncations in energy or time) - accelsearch_flags = ['-numharm','4','-zmax','100','-photon','-flo','0.05','-fhi','1'] + accelsearch_flags = ['-numharm','8','-zmax','100','-photon','-flo','1','-fhi','2000'] ##### Parameters for prepfold zmax = 100 @@ -134,8 +146,8 @@ def filtering(eventfile,outfile,maskdet,eventflags): ## but currently, the best thing is just to track the segment size on the terminal, then increase ## accordingly. For example, I tried 100s segments for 0034070101 (Cen X-3), but nicerfits2presto.py ## is binning at 100.8s, so I went up to the next nice number - 102.. - PI1 = [30] - PI2 = [200] + PI1 = [30,200] + PI2 = [200,1200] ################################################################################ ############################# SEARCH_BIN PARAMETERS ############################ @@ -152,14 +164,14 @@ def filtering(eventfile,outfile,maskdet,eventflags): ############################# EF_SEARCH PARAMETERS ############################# ##### EPOCH FOLDING - do_efsearch = True + do_efsearch = False if do_efsearch == True: eventfile_header = fits.open(out_baryfile)[1].header T = eventfile_header['TSTOP'] - eventfile_header['TSTART'] - n_segments = 100 #number of segments to break the epoch folding search into - dper = 9.25 #Value for the period used in the folding. In 'efsearch' the + n_segments = 1 #number of segments to break the epoch folding search into + dper = 1.36 #Value for the period used in the folding. In 'efsearch' the #input period represents the centre of the range of the trial periods. - nphase = 32 #Number of phases in the folded light curve(s). Typing 'INDEF' + nphase = 16 #Number of phases in the folded light curve(s). Typing 'INDEF' #forces the task to use the default value (see parameter "nbdf"). nbint = int((T/(dper/nphase))/n_segments) # The number of newbins per interval used in the analysis. The #"nbint" together with the NEWBIN duration determines the length in time of an interval @@ -167,10 +179,10 @@ def filtering(eventfile,outfile,maskdet,eventflags): #analysis will be carried out. Typing 'INDEF' forces the task to use the default value #(see parameter "nbdf"). NOTE: By pressing return "nbint" is set to the value found in the #parameter file used in a previous run." - nper = 512 #The number of periods over which the search is carried out + nper = 128 #The number of periods over which the search is carried out dres = 1E-4 # The period resolution is the spacing between two contiguous periods in the search. #'INDEF' uses the default value of: half the Fourier resolution in the interval (e.g., P^2/T(i)/2 ; T(i) is interval duration) - outfile_root = 'rxj0209_' + str(n_segments) + 'segs_' + str(nper) + outfile_root = 'swift1818_' + str(n_segments) + 'segs_' + str(nper) plot_efsearch = 'no' #to plot the results from efsearch ; do "exit" to see the next plot! ################################################################################ @@ -198,13 +210,13 @@ def filtering(eventfile,outfile,maskdet,eventflags): if do_lc_ps_phase_color == True: par_list = ['PI','PI_FAST','TIME'] #parameter list from event_cl - tbin_size = 1 #how you want to bin the light curve data + tbin_size = 0.001 #how you want to bin the light curve data Ebin_size = 0.05 #in keV mode = 'show' - truncations = 'all' #'all', 't', 'E', or 'tE', depending on whether we want to look at entire time series (all), or truncation by time interval (t), or time truncation by energy range (E), or truncation by both (tE) + truncations = 't' #'all', 't', 'E', or 'tE', depending on whether we want to look at entire time series (all), or truncation by time interval (t), or time truncation by energy range (E), or truncation by both (tE) - lc = False - ps = False + lc = True + ps = True phase = False color = False ############################################################################### @@ -214,22 +226,22 @@ def filtering(eventfile,outfile,maskdet,eventflags): # Lv2_phase - partial_t, partial_E, partial_tE # Lv2_color - plotting_t - t1 = 2629580 - t2 = 2630180 - E1 = 0.3 - E2 = 2.5 + t1 = 5450 + t2 = 6300 + E1 = 2 + E2 = 12 #for Lv2_ps ps_type = 'manual' # 'period' (for periodogram) or 'manual' (for FFT) or 'both' oversampling = [False,5] # [False to NOT oversample, oversampling factor - 5 to oversample by factor of 5. (factor-1) sets of 0s are padded.] - xlims = [False,0,5] # [False to NOT impose xlimit on plots; 2nd/3rd entries are the desired x-limits if needed.] - vlines = [False,271.453] # [False to NOT draw a vertical line on the plot; 2nd entry is the equation for the vertical line, e.g. x=2] + xlims = [False,0,1] # [False to NOT impose xlimit on plots; 2nd/3rd entries are the desired x-limits if needed.] + vlines = [False,1/1.3632] # [False to NOT draw a vertical line on the plot; 2nd entry is the equation for the vertical line, e.g. x=2] #for Lv2_phase ### For an unknown observation, one should run JUST Lv2_lc and Lv2_ps first to get ### the pulsation frequencies. Pulse profiles come LATER. ### If I have pulse_pars[1] and pulse_pars[2] != 0, then time binning DOES NOT MATTER, i.e., it'll be counts/s! - pulse_pars = [0.1075,0,0] #J0209.6-7427 + pulse_pars = [1/1.3632,0,0] #J0209.6-7427 shift = 0.4 # how much to shift the pulse by in the phase axis. It only affects how the pulse profile is 'displaced'. no_phase_bins = 20 # number of phase bins desired @@ -239,101 +251,110 @@ def filtering(eventfile,outfile,maskdet,eventflags): cut_type = 'manual' # 'manual' cut for boundary energy, or 'median' - for half number of counts bound = 2.7 # boundary energy for when cut_type = 'manual'! - E_bound = Lv3_E_boundary.E_bound(eventfile,par_list,E1_data,E2_data,cut_type,bound) #use Lv3_E_boundary to get boundary energy + E_bound = Lv3_E_boundary.E_bound(out_baryfile,par_list,E1_data,E2_data,cut_type,bound) #use Lv3_E_boundary to get boundary energy ############################ FOR WHOLE OBSERVATION ############################ if truncations == 'all': if lc == True: - Lv2_lc.whole(eventfile,par_list,tbin_size,mode) #light curve + Lv2_lc.whole(out_baryfile,par_list,tbin_size,mode) #light curve time.sleep(1) if ps == True: - Lv2_ps.whole(eventfile,par_list,tbin_size,mode,ps_type,oversampling,xlims,vlines) #power spectra + Lv2_ps.whole(out_baryfile,par_list,tbin_size,mode,ps_type,oversampling,xlims,vlines) #power spectra time.sleep(1) if phase == True: - Lv2_phase.whole(eventfile,par_list,tbin_size,pulse_pars,shift,no_phase_bins,mode) + Lv2_phase.whole(out_baryfile,par_list,tbin_size,pulse_pars,shift,no_phase_bins,mode) time.sleep(1) if color == True: - Lv2_color.plotting(eventfile,par_list,E_bound,tbin_size,mode) + Lv2_color.plotting(out_baryfile,par_list,E_bound,tbin_size,mode) ########################## FOR DESIRED TIME INTERVAL ########################## if truncations == 't': if lc == True: - Lv2_lc.partial_t(eventfile,par_list,tbin_size,t1,t2,mode) #light curve + Lv2_lc.partial_t(out_baryfile,par_list,tbin_size,t1,t2,mode) #light curve time.sleep(1) if ps == True: - Lv2_ps.partial_t(eventfile,par_list,tbin_size,t1,t2,mode,ps_type,oversampling,xlims,vlines) #power spectra + Lv2_ps.partial_t(out_baryfile,par_list,tbin_size,t1,t2,mode,ps_type,oversampling,xlims,vlines) #power spectra time.sleep(1) if phase == True: - Lv2_phase.partial_t(eventfile,par_list,tbin_size,pulse_pars,shift,no_phase_bins,t1,t2,mode) + Lv2_phase.partial_t(out_baryfile,par_list,tbin_size,pulse_pars,shift,no_phase_bins,t1,t2,mode) time.sleep(1) if color == True: - Lv2_color.plotting_t(eventfile,par_list,E_bound,tbin_size,t1,t2,mode) + Lv2_color.plotting_t(out_baryfile,par_list,E_bound,tbin_size,t1,t2,mode) ########################### FOR DESIRED ENERGY RANGE ########################## # anticipate that this will be used much? if truncations == 'E': if lc == True: - Lv2_lc.partial_E(eventfile,par_list,tbin_size,Ebin_size,E1,E2,mode) + Lv2_lc.partial_E(out_baryfile,par_list,tbin_size,Ebin_size,E1,E2,mode) time.sleep(1) if ps == True: - Lv2_ps.partial_E(eventfile,par_list,tbin_size,Ebin_size,E1,E2,mode,ps_type,oversampling,xlims,vlines) + Lv2_ps.partial_E(out_baryfile,par_list,tbin_size,Ebin_size,E1,E2,mode,ps_type,oversampling,xlims,vlines) time.sleep(1) if phase == True: - Lv2_phase.partial_E(eventfile,par_list,tbin_size,Ebin_size,pulse_pars,shift,no_phase_bins,E1,E2,mode) + Lv2_phase.partial_E(out_baryfile,par_list,tbin_size,Ebin_size,pulse_pars,shift,no_phase_bins,E1,E2,mode) ################# FOR DESIRED TIME INTERVAL AND ENERGY RANGE ################# if truncations == 'tE': if lc == True: - Lv2_lc.partial_tE(eventfile,par_list,tbin_size,Ebin_size,t1,t2,E1,E2,mode) + Lv2_lc.partial_tE(out_baryfile,par_list,tbin_size,Ebin_size,t1,t2,E1,E2,mode) time.sleep(1) if ps == True: - Lv2_ps.partial_tE(eventfile,par_list,tbin_size,Ebin_size,t1,t2,E1,E2,mode,ps_type,oversampling,xlims,vlines) + Lv2_ps.partial_tE(out_baryfile,par_list,tbin_size,Ebin_size,t1,t2,E1,E2,mode,ps_type,oversampling,xlims,vlines) time.sleep(1) if phase == True: - Lv2_phase.partial_tE(eventfile,par_list,tbin_size,Ebin_size,pulse_pars,shift,no_phase_bins,t1,t2,E1,E2,mode) + Lv2_phase.partial_tE(out_baryfile,par_list,tbin_size,Ebin_size,pulse_pars,shift,no_phase_bins,t1,t2,E1,E2,mode) time.sleep(1) if color == True: - Lv2_color.plotting_t(eventfile,par_list,E_bound,tbin_size,t1,t2,mode) + Lv2_color.plotting_t(out_baryfile,par_list,E_bound,tbin_size,t1,t2,mode) if do_presto == True: if process_all == True: if conv_fits2presto == True: - Lv2_presto_subroutines.do_nicerfits2presto(eventfile,tbin,0) + Lv2_presto_subroutines.do_nicerfits2presto(out_baryfile,tbin,0,'all') if accelsearch == True: print('Doing realfft/accelsearch now!') ### Running realfft and accelsearch from PRESTO - Lv2_presto_subroutines.realfft(eventfile,0,'all') - Lv2_presto_subroutines.accelsearch(eventfile,0,'all',accelsearch_flags) + Lv2_presto_subroutines.realfft(out_baryfile,0,'all') + Lv2_presto_subroutines.accelsearch(out_baryfile,0,'all',accelsearch_flags) - ## no_cand might be a list, if I'm processing multiple eventfiles at once... + ## no_cand might be a list, if I'm processing multiple out_baryfiles at once... if prepfold == True: - Lv2_presto_all.prepfold(eventfile,zmax) - Lv2_presto_all.ps2pdf(eventfile) + print("Running prepfold now!") + Lv2_presto_subroutines.prepfold(out_baryfile,0,'all',zmax) + Lv2_presto_subroutines.ps2pdf(out_baryfile,0,'all') ################################################################################ ############################### PRESTO_SEGMENTS ################################ ################################################################################ if process_segments == True: - """ if time_segments == True: for j in range(len(segment_lengths)): Lv2_presto_subroutines.get_gti_file(out_baryfile,segment_lengths[j]) #make GTI files for each segment Lv2_presto_subroutines.niextract_gti_time(out_baryfile,segment_lengths[j]) #performing niextract-events - Lv2_presto_subroutines.do_nicerfits2presto(out_baryfile,tbin,segment_lengths[j]) + Lv2_presto_subroutines.do_nicerfits2presto(out_baryfile,tbin,segment_lengths[j],'t') Lv2_presto_subroutines.edit_inf(out_baryfile,tbin,segment_lengths[j]) Lv2_presto_subroutines.edit_binary(out_baryfile,tbin,segment_lengths[j]) - # """ + # # Lv3_duty_cycle.duty_cycle(out_baryfile,tbin,segment_lengths[j],duty_cycle_bin,threshold) # Lv3_duty_cycle.duty_cycle_dist(out_baryfile,tbin,segment_lengths[j],duty_cycle_bin,threshold) + if gti_segments == True: + Lv2_presto_subroutines.niextract_gti(out_baryfile,gap,gtifile) + Lv2_presto_subroutines.do_nicerfits2presto(out_baryfile,tbin,0,'gtis') + if energy_segments == True: + print("Doing acceleration searches with energy cuts!") if len(PI1) != len(PI2): raise ValueError("Make sure that the length of PI1 and PI2 are the same! Need pairs of PI values.") + parent_folder = str(pathlib.Path(out_baryfile).parent) + accelE_folder = parent_folder + '/accelsearch_E/' + file_suffix = str(pathlib.Path(out_baryfile).name) + for j in range(len(PI1)): Lv2_presto_subroutines.niextract_gti_energy(out_baryfile,PI1[j],PI2[j]) - Lv2_presto_subroutines.do_nicerfits2presto(out_baryfile,tbin,0) #segment_length makes no sense, so 0 is a placeholder + Lv2_presto_subroutines.do_nicerfits2presto(accelE_folder+file_suffix[:-4]+'_E'+str(PI1[j])+'-'+str(PI2[j])+'.evt',tbin,0,'E') #segment_length makes no sense, so 0 is a placeholder if time_energy_segments == True: for j in range(len(segment_lengths)): @@ -341,7 +362,7 @@ def filtering(eventfile,outfile,maskdet,eventflags): for k in range(len(PI1)): Lv2_presto_subroutines.niextract_gti_time_energy(out_baryfile,segment_lengths[j],PI1[k],PI2[k]) - Lv2_presto_subroutines.do_nicerfits2presto(out_baryfile,tbin,segment_lengths[j]) + Lv2_presto_subroutines.do_nicerfits2presto(out_baryfile,tbin,segment_lengths[j],'t') Lv2_presto_subroutines.edit_inf(out_baryfile,tbin,segment_lengths[j]) Lv2_presto_subroutines.edit_binary(out_baryfile,tbin,segment_lengths[j]) @@ -351,29 +372,37 @@ def filtering(eventfile,outfile,maskdet,eventflags): ### Running realfft and accelsearch from PRESTO if accelsearch == True: + print("Running acceleration searches now!") if time_segments == True or time_energy_segments == True: for j in range(len(segment_lengths)): Lv2_presto_subroutines.realfft(out_baryfile,segment_lengths[j],'t') Lv2_presto_subroutines.accelsearch(out_baryfile,segment_lengths[j],'t',accelsearch_flags) + if gti_segments == True: + Lv2_presto_subroutines.realfft(out_baryfile,0,'gtis') + Lv2_presto_subroutines.accelsearch(out_baryfile,0,'gtis',accelsearch_flags) if energy_segments == True: Lv2_presto_subroutines.realfft(out_baryfile,0,'E') Lv2_presto_subroutines.accelsearch(out_baryfile,0,'E',accelsearch_flags) else: - "None of time_segments, time_energy_segments, or energy_segments are True!" + "None of time_segments, gti_segments, time_energy_segments, or energy_segments are True!" ## no_cand might be a list, if I'm processing multiple eventfiles at once... if prepfold == True: - """ + print("Running prepfold now!") if time_segments == True or time_energy_segments == True: for j in range(len(segment_lengths)): Lv2_presto_subroutines.prepfold(out_baryfile,segment_lengths[j],'t',zmax) + if gti_segments == True: + Lv2_presto_subroutines.prepfold(out_baryfile,0,'gtis',zmax) if energy_segments == True: Lv2_presto_subroutines.prepfold(out_baryfile,0,'E',zmax) - """ + ### doing ps2pdf if time_segments == True or time_energy_segments == True: for j in range(len(segment_lengths)): Lv2_presto_subroutines.ps2pdf(out_baryfile,segment_lengths[j],'t') + if gti_segments == True: + Lv2_presto_subroutines.ps2pdf(out_baryfile,0,'gtis') if energy_segments == True: Lv2_presto_subroutines.ps2pdf(out_baryfile,0,'E') diff --git a/Lv3_swift_ngc300.py b/Lv3_swift_ngc300.py new file mode 100644 index 0000000..c628dc0 --- /dev/null +++ b/Lv3_swift_ngc300.py @@ -0,0 +1,917 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +Created on Mon Jun 29 7:07pm 2020 + +Meant to interface with Lv2_dj_lsp and functions from stingray.pulse.pulsar to +analyze Swift data pertaining to NGC 300 X-1 in one place, instead of having +the analysis spread between Lv2_dj_lsp.py and test.py + +""" +from __future__ import division, print_function +import numpy as np +from astropy.io import fits +import matplotlib.pyplot as plt +import Lv0_dirs,Lv2_dj_lsp,Lv2_swift_lc,Lv2_phase +import os +from scipy import stats +from scipy.optimize import curve_fit +from tqdm import tqdm +import subprocess +from matplotlib import cm +from PyAstronomy.pyasl import foldAt +from mpl_toolkits.mplot3d import Axes3D +import mplcursors +import pathlib +from stingray.pulse.pulsar import pulse_phase,phase_exposure,fold_events + +##### +## Noting here first that all the barycentering, time-ordering, extracting events +## (with XSELECT), doing exposure corrections (xrtlccorr), and subsequently the +## background subtraction, are all done in Lv2_swift_lc. There's no need to do so here. +##### + +##### Parameters +eventfile = '/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/ngc300x1/ngc300x1_merge_niceroverlap_all.evt' #1 year of data; overlaps with NICER +#eventfile = '/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/ngc300x1/ngc300x1_swift_dec16_may19.evt' +#eventfile = '/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/ngc300x1/ngc300x1_merge.evt' #all 14 years +eventfile_xmm = '/Volumes/Samsung_T5/NGC300_XMMdata/ngc300x1_pn.evt' + +times = fits.open(eventfile)[1].data['TIME'] #getting array of times +times_xmm = fits.open(eventfile_xmm)[1].data['TIME'] + +gtis_data = fits.open(eventfile)[2].data #getting GTIs +gtis_data_xmm = fits.open(eventfile_xmm)[59].data #59 for pn, 15 for mos1, 19 for mos2 + +T = sum([ gtis_data[i]['STOP']-gtis_data[i]['START'] for i in range(len(gtis_data)) ]) #exposure time +T_xmm = sum([ gtis_data_xmm[i]['STOP']-gtis_data_xmm[i]['START'] for i in range(len(gtis_data_xmm)) ]) #exposure time +print(T_xmm) +T0_MJD = fits.open(eventfile)[1].header['MJDREFI'] + fits.open(eventfile)[1].header['MJDREFF'] + fits.open(eventfile)[1].header['TSTART']/86400 #SWIFT +T0_MJD_eclipse = 58239.3498 #mid-eclipse! +T0_MJD_xmm = fits.open(eventfile_xmm)[1].header['MJDREF'] + fits.open(eventfile_xmm)[1].header['TSTART']/86400 #XMM-NEWTON + +MJDREFI = fits.open(eventfile)[1].header['MJDREFI'] #Swift +MJDREFF = fits.open(eventfile)[1].header['MJDREFF'] #Swift +MJDREF = fits.open(eventfile_xmm)[1].header['MJDREF'] #XMM-Newton +diff_swiftxmm = (MJDREFI+MJDREFF-MJDREF)*86400 + +##### Get the phase offset between Swift eclipse time and XMM's first event time: +Porb_days = (1/8.4712e-6)/86400 +xmm_first = MJDREF + times_xmm[0]/86400 +no_cycles = (T0_MJD_eclipse - T0_MJD_xmm)/Porb_days +xmm_ecl = T0_MJD_eclipse - int(no_cycles)*Porb_days #time of the mid-eclipse BEFORE the first XMM event +if xmm_ecl > xmm_first: + xmm_ecl -= Porb_days +phaseoff = (xmm_first-xmm_ecl)/Porb_days +print('Phase offset is ' + str(phaseoff)) + +##### Be careful here, as Swift and XMM have different MJDREFs!!! +gtis_conform = [] +for i in range(len(gtis_data)): + gtis_conform.append([gtis_data[i][0],gtis_data[i][1]]) #conform to the input that Stingray uses + +gtis_conform_xmm = [] +for i in range(len(gtis_data_xmm)): + gtis_conform_xmm.append([gtis_data_xmm[i][0],gtis_data_xmm[i][1]]) #conform to the input that Stingray uses + +#bary_outputfolder = '/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/lightcurve/' +#obsids = [str(i) for i in range(49834027,49834042)] + [str(i) for i in range(49834043,49834062)] + [str(i) for i in range(49834063,49834066)] + ['88810002'] + [str(i) for i in range(49834066,49834069)] + [str(i) for i in range(49834070,49834079)] + [str(i) for i in range(49834080,49834088)] +#corr_lc_files = [bary_outputfolder + 'sw000' + obsids[i] + '_corr.lc' for i in range(len(obsids))] +#corr_ulx1_files = [bary_outputfolder + 'sw000' + obsids[i] + '_ulx1_corr.lc' for i in range(len(obsids))] +#corr_bg_files = [bary_outputfolder + 'sw000' + obsids[i] + '_bg_corr.lc' for i in range(len(obsids))] +#bg_scale_x1 = (30/120)**2 +#bg_scale_ulx1 = (35/120)**2 +#completeness = np.array([0,10,20,30,40,50,60,70,80,90,100])/100 +#rebinned_t, rebinned_rate, rebinned_err, rebinned_fracexp = Lv2_dj_lsp.rebin_lc(corr_lc_files,corr_bg_files,bg_scale_x1,100,0.5) +#rebinned_t_ulx1, rebinned_rate_ulx1, rebinned_err_ulx1, rebinned_fracexp_ulx1 = rebin_lc(corr_ulx1_files,corr_bg_files,bg_scale_ulx1,3600,0) + +#tstart_49834027 = 546830295.758713 + +""" +### Writing the data from the light curves of X-1 and ULX-1 into text files; also plotting the light curve, This is mainly for 3600s bins + +x1_text = open(bary_outputfolder + 'ngc300x1_bg_exp_corr_lc_3600s.txt','w') +ulx1_text = open(bary_outputfolder + 'ngc300ulx1_bg_exp_corr_lc_3600s.txt','w') + +for i in range(len(rebinned_t)): + x1_text.write(str(51910 + 7.428703700000000E-04+(rebinned_t[i]+tstart_49834027)/86400) + ' ' + str(rebinned_rate[i]) + ' ' + str(rebinned_err[i]) + '\n') +x1_text.close() + +for i in range(len(rebinned_t_ulx1)): + ulx1_text.write(str(51910 + 7.428703700000000E-04 + (rebinned_t_ulx1[i]+tstart_49834027)/86400) + ' ' + str(rebinned_rate_ulx1[i]) + ' ' + str(rebinned_err_ulx1[i]) + '\n') +ulx1_text.close() + +mjd = 51910 + 7.428703700000000E-04 + (tstart_49834027+rebinned_t)/86400 +mjd_ulx1 = 51910 + 7.428703700000000E-04 + (tstart_49834027+rebinned_t_ulx1)/86400 +plt.errorbar(x=mjd[rebinned_err<=0.06],y=rebinned_rate[rebinned_err<=0.06],yerr=rebinned_err[rebinned_err<=0.06],fmt='rx') +plt.errorbar(x=mjd_ulx1[rebinned_err_ulx1<=0.06],y=rebinned_rate_ulx1[rebinned_err_ulx1<=0.06],yerr=rebinned_err_ulx1[rebinned_err_ulx1<=0.06],fmt='bx') +plt.legend(('X-1','ULX-1'),fontsize=12) +plt.xlabel('Time (MJD)',fontsize=12) +plt.ylabel('[Exposure-corrected] Count rate (c/s)',fontsize=12) +plt.axhline(y=0,color='k',lw=0.5,alpha=0.5) +plt.show() +""" + +### Running Lv2_dj_lsp.lsp +""" +for i in range(len(completeness)): + rebinned_t, rebinned_rate, rebinned_err, rebinned_fracexp = Lv2_dj_lsp.rebin_lc(corr_lc_files,corr_bg_files,bg_scale_x1,100,completeness[i]) + + omega,psd,prob3,prob4,prob5 = Lv2_dj_lsp.lsp(rebinned_t,rebinned_rate) + nu_reg = omega/(2.0*np.pi) + freq = omega/(2*np.pi) + + plt.figure() + plt.plot(freq,psd,'rx-') + #plt.yscale('log') + #plt.xscale('log') + plt.xlabel('Frequency (Hz)',fontsize=12) + plt.ylabel('Normalized Power',fontsize=12) + plt.axhline(y=prob3,lw=0.5,alpha=0.5) + plt.axhline(y=prob4,lw=0.5,alpha=0.5) + plt.axhline(y=prob5,lw=0.5,alpha=0.5) + #print(prob3,prob4,prob5) + + print(np.max(psd),freq[psd==np.max(psd)][0]) + #plt.show() +""" + +### Doing FR/RSS + +#for i in range(len(completeness)): +# rebinned_t, rebinned_rate, rebinned_err, rebinned_fracexp = Lv2_dj_lsp.rebin_lc(corr_lc_files,corr_bg_files,bg_scale_x1,100,completeness[i]) +# freqs_list, psd_list = Lv2_dj_lsp.psd_error(rebinned_t,rebinned_rate,rebinned_err) +# print(str(completeness[i]) + '%') +# print('Median frequency: ' + str(np.median(freqs_list))) +# print('Error in frequency: ' + str(np.std(freqs_list))) +#print('Powers: ' + str(psd_list)) + +################################################################################ +################################### FOLDING #################################### +################################################################################ + +""" +##### Folding using my routine; confirmed that the folding of the raw data agrees with Stingray's and foldAt +nbins = 20 +freq = 8.4712e-6 +offset = -0.215*nbins +#freq = 8.6088e-6 +freqdot = 0 +freqdotdot = 0 +phase_frac = (T0_MJD_eclipse-T0_MJD)/((1/freq)/86400) + +#print('MID ECLIPSE TIME:') +#print( fits.open(eventfile)[1].header['MJDREFI'] + fits.open(eventfile)[1].header['MJDREFF'] + (times[0] + 0.21569724*1/freq)/86400) +#T0_MJD = fits.open(eventfile)[1].header['MJDREF'] + times[0]/86400 + +##### Using Lv2_phase +plt.figure() +phase,profile,profile_error = Lv2_phase.pulse_folding(times,T,T0_MJD,freq,freqdot,freqdotdot,nbins,"SWIFT") +plt.errorbar(x=phase[:-1],y=profile,yerr=profile_error,color='r',drawstyle='steps-mid') + +expos = Lv2_phase.phase_exposure(times[0]-times[0],times[-1]-times[0],1/freq,nbin=nbins,gtis=np.array(gtis_conform)-times[0]) +total_expos = np.array(list(expos) + list(expos)) +plt.errorbar(x=phase[:-1],y=profile/total_expos,yerr=profile_error/total_expos,color='b',drawstyle='steps-mid') +plt.title(str(pathlib.Path(eventfile).name) +', exposure-corrected (using Lv2_phase)',fontsize=12) +plt.xlabel('Phase',fontsize=12) +plt.ylabel('Counts/s',fontsize=12) +plt.legend(('Folded profile','Exposure-corrected profile'),loc='best',fontsize=12) +print('Original expos:') +print(expos) +##### Using stingray.pulse.pulsar's fold_events +phase_sr,prof_sr,err_sr = fold_events(times,freq,freqdot,freqdotdot,gtis=np.array(gtis_conform),ref_time=times[0],nbin=nbins) +phase_sr_expo,prof_sr_expo,err_sr_expo = fold_events(times,freq,freqdot,freqdotdot,gtis=np.array(gtis_conform),ref_time=times[0],expocorr=True,nbin=nbins) + +total_phase_sr = list(phase_sr) + list(phase_sr+1) +total_prof_sr = list(prof_sr)*2 +total_err_sr = list(err_sr)*2 + +total_phase_sr_expo = list(phase_sr_expo) + list(phase_sr_expo+1) +total_prof_sr_expo = list(prof_sr_expo)*2 +total_err_sr_expo = list(err_sr_expo)*2 + +if nbins % 2 == 0: + fft_x = np.array(list(np.arange(int(nbins/2)+1)) + list(np.arange(int(nbins/2)-1) - (int(nbins/2)-1))) +else: + fft_x = np.array(list(np.arange(int(nbins/2)+1)) + list(np.arange(int(nbins/2)) - int(nbins/2))) + +shift = np.exp(-2j*np.pi*fft_x*offset/nbins) +shifted_prof_sr = np.real(np.fft.ifft(np.fft.fft(prof_sr_expo)*shift)) #taking the real component of the inverse transform of the shifted Fourier transform of the original folded profile +shifted_err_sr = np.real(np.fft.ifft(np.fft.fft(err_sr_expo)*shift)) #taking the real component of the inverse transform of the shifted Fourier transform of the original folded profile +a = np.array(list(shifted_prof_sr)*2)/T +b = np.array(list(shifted_err_sr)*2)/T + +swift_lc = open(Lv0_dirs.NGC300_2020 + 'swift_shifted_folded_curve.txt','w') +for i in range(len(total_expos)): + swift_lc.write(str(total_phase_sr[i]) + ' ' + str(a[i]) + ' ' + str(b[i]) + '\n') +swift_lc.close() + +plt.figure() +plt.errorbar(x=total_phase_sr,y=total_prof_sr/T,yerr=total_err_sr/T,color='r',drawstyle='steps-mid') +plt.errorbar(x=total_phase_sr_expo,y=total_prof_sr_expo/T,yerr=total_err_sr_expo/T,color='b',drawstyle='steps-mid') +plt.legend(('Folded profile','Exposure-corrected'),loc='best',fontsize=12) +plt.title(str(pathlib.Path(eventfile).name) +', exposure-corrected (using Stingray fold_events)',fontsize=12) +plt.xlabel('Phase',fontsize=12) +plt.ylabel('Counts/s',fontsize=12) +plt.show() +""" + +""" +##### Using foldAt by PyAstronomy +plt.figure() +phase_bins = np.linspace(0,1,21) +phases = foldAt(times,1/freq,T0=times[0]-(1-phase_frac)*1/freq) + +expos = Lv2_phase.phase_exposure(times[0]-times[0],times[-1]-times[0],1/freq,nbin=nbins,gtis=np.array(gtis_conform)-times[0]) +total_expos = np.array(list(expos) + list(expos)) +expos_index = int(phase_frac/(phase_bins[1]-phase_bins[0])) #starting point for exposures +altered_expos = np.array(list(total_expos[expos_index:]) + list(total_expos[:expos_index])) + +#print('Altered expos:') +#print(altered_expos) + +profile,bin_edges,binnumber = stats.binned_statistic(phases,np.ones(len(phases)),statistic='sum',bins=phase_bins) +error = np.sqrt(profile) +phase_to_2 = np.array(list(phase_bins[:-1]) + list(phase_bins+1)) +profile_to_2 = np.array(list(profile)*2) +error_to_2 = np.array(list(error)*2) +plt.errorbar(phase_to_2[:-1],profile_to_2/(T*altered_expos),yerr=error_to_2/(T*altered_expos),color='b',drawstyle='steps-mid') +plt.legend(('Folded profile','Exposure-corrected'),loc='best',fontsize=12) +plt.title(str(pathlib.Path(eventfile).name) +', exposure-corrected (using PyAstronomy foldAt)',fontsize=12) +plt.xlabel('Phase',fontsize=12) +plt.ylabel('Counts/s',fontsize=12) + + +##### Shifting pulse profiles through a shifted FT (see Deepto's 7/20/2020 email) +if nbins % 2 == 0: + fft_x = np.array(list(np.arange(int(nbins/2)+1)) + list(np.arange(int(nbins/2)-1) - (int(nbins/2)-1))) +else: + fft_x = np.array(list(np.arange(int(nbins/2)+1)) + list(np.arange(int(nbins/2)) - int(nbins/2))) + +shift = np.exp(-2j*np.pi*fft_x*offset/nbins) +shifted_prof_sr = np.real(np.fft.ifft(np.fft.fft(prof_sr_expo)*shift)) #taking the real component of the inverse transform of the shifted Fourier transform of the original folded profile +shifted_err_sr = np.real(np.fft.ifft(np.fft.fft(err_sr_expo)*shift)) #taking the real component of the inverse transform of the shifted Fourier transform of the original folded profile + +plt.figure() +plt.errorbar(x=total_phase_sr_expo,y=total_prof_sr_expo/T,yerr=total_err_sr_expo/T,color='b',drawstyle='steps-mid') +plt.errorbar(total_phase_sr,np.array(list(shifted_prof_sr)*2)/T,yerr=np.array(list(shifted_err_sr)*2)/T,color='r',drawstyle='steps-mid') +plt.xlabel('Phase',fontsize=12) +plt.ylabel('Counts/s',fontsize=12) +plt.title('Exposure-corrected, folded profiles for NGC 300 X-1 from Swift over May 2018 to May 2019') +plt.legend(('Folded with T0 = time of first event','Folded with T0 = inferred eclipse time/phase'),fontsize=12) +""" + +""" +nbins_t = len(times) +offset = (1-0.215)*1/freq +##### Shifting pulse profiles through a shifted FT (see Deepto's 7/20/2020 email) +if nbins_t % 2 == 0: + fft_x = np.array(list(np.arange(int(nbins_t/2)+1)) + list(np.arange(int(nbins_t/2)-1) - (int(nbins_t/2)-1))) +else: + fft_x = np.array(list(np.arange(int(nbins_t/2)+1)) + list(np.arange(int(nbins_t/2)) - int(nbins_t/2))) + +shift = np.exp(-2j*np.pi*fft_x*offset/nbins_t) +shifted_t = np.real(np.fft.ifft(np.fft.fft(times)*shift)) #taking the real component of the inverse transform of the shifted Fourier transform of the original folded profile +for i in range(20): + print(times[i],shifted_t[i]) + +phase_sr,prof_sr,err_sr = fold_events(shifted_t,freq,freqdot,freqdotdot,gtis=np.array(gtis_conform),ref_time=times[0],nbin=nbins) +phase_sr_expo,prof_sr_expo,err_sr_expo = fold_events(shifted_t,freq,freqdot,freqdotdot,gtis=np.array(gtis_conform),ref_time=times[0],expocorr=True,nbin=nbins) + +plt.figure() +plt.errorbar(phase_sr,prof_sr/T,color='b',drawstyle='steps-mid') +plt.errorbar(phase_sr,prof_sr_expo/T,color='r',drawstyle='steps-mid') +plt.xlabel('Phase',fontsize=12) +plt.ylabel('Counts/s',fontsize=12) +""" + +#plt.show() + +""" +##### Fitting 6-model step-and-ramp parameters to the folded profile +plt.figure() +plt.errorbar(x=phase[:-1],y=profile,yerr=profile_error,color='r',drawstyle='steps-mid') +plt.errorbar(x=phase[:-1],y=profile/total_expos,yerr=profile_error/total_expos,color='b',drawstyle='steps-mid') +plt.title(str(pathlib.Path(eventfile).name) +', exposure-corrected (using Lv2_phase)',fontsize=12) +plt.xlabel('Phase',fontsize=12) +plt.ylabel('Counts/s',fontsize=12) +plt.legend(('Folded profile','Exposure-corrected profile'),loc='best',fontsize=12) + +start_phase = 0.45 +end_phase = 1.95 +phase_model = np.linspace(start_phase,end_phase,1001) +x = phase[:-1][(phase[:-1]>=start_phase)&(phase[:-1]<=end_phase)] +y = profile[(phase[:-1]>=start_phase)&(phase[:-1]<=end_phase)]/total_expos[(phase[:-1]>=start_phase)&(phase[:-1]<=end_phase)] +y_err = profile_error[(phase[:-1]>=start_phase)&(phase[:-1]<=end_phase)]/total_expos[(phase[:-1]>=start_phase)&(phase[:-1]<=end_phase)] + +def piecewise_linear(x,b1,b2,b3,b4,top,bottom): + return np.piecewise(x, [(x>=start_phase)&(x<=b1), (x>b1)&(x<=b2), (x>b2)&(x<=b3), (x>b3)&(x<=b4), (x>b4)&(x<=end_phase)], [lambda x:top, lambda x:((bottom-top)/(b2-b1)*x+bottom-(bottom-top)/(b2-b1)*b2), lambda x:bottom, lambda x:((top-bottom)/(b4-b3)*x+top-(top-bottom)/(b4-b3)*b4), lambda x:top]) + +pguess = np.array([1.05,1.15,1.30,1.45,0.0011,0.0003]) +popt,pcov = curve_fit(piecewise_linear,x,y,p0=pguess)#,sigma=y_err) +print(popt) +print(np.diag(np.sqrt(pcov))/popt*100) +plt.plot(phase_model,piecewise_linear(phase_model,*popt),'k-') +""" + +#plt.show() + +########################### DOING CHI^2 EXPLORATION ############################ + +def lorentzian(f, f0, a, gam,const): + x = (f-f0)/(gam/2) + return a * 1/(1+x**2) + const + +def gaussian(f,f0,a,sig,const): + return a * np.exp( -(f-f0)**2/(2*sig**2) ) + const + +def sum(f,f0,a,gam,b,sig,const): + x = (f-f0)/(gam/2) + return a * 1/(1+x**2) + b * np.exp( -(f-f0)**2/(2*sig**2)) + const + +""" +nbins=20 +chi2 = [] +freqs = np.arange(8.25e-6,8.7e-6,0.01e-6) +#freqs = np.arange(-9e-17,-1e-18,1e-20) +for i in tqdm(range(len(freqs))): + phase_sr_expo,prof_sr_expo,err_sr_expo = fold_events(times,freqs[i],gtis=np.array(gtis_conform),ref_time=times[0],expocorr=True,nbins=nbins) + chi2_freq = Lv2_phase.get_chi2(prof_sr_expo,err_sr_expo) + chi2.append( chi2_freq ) +""" + +""" +freqs_filter = freqs[(freqs>=8.4693e-6)&(freqs<=8.472e-6)] #8.47 to 8.47275 for 1-year data +chi2_filter = np.array(chi2)[(freqs>=8.4693e-6)&(freqs<=8.472e-6)] + +freq_model = np.linspace(8.4693e-6,8.472e-6,1001) + +pguess_l = np.array([8.4706e-6,650,0.002e-6]) +popt_l,pcov_l = curve_fit(lorentzian,freqs_filter,chi2_filter,p0=pguess_l) +print(popt_l) +print(np.sqrt(np.diag(pcov_l))) + +pguess_g = np.array([8.4706e-6,650,0.002e-6]) +popt_g,pcov_g = curve_fit(gaussian,freqs_filter,chi2_filter,p0=pguess_g) +print(popt_g) +print(np.sqrt(np.diag(pcov_g))) + +pguess_s = np.array([8.4706e-6,650,0.002e-6,600,0.002e-6]) +popt_s,pcov_s = curve_fit(sum,freqs_filter,chi2_filter,p0=pguess_s) +print(popt_s) +print(np.sqrt(np.diag(pcov_s))) +""" + +""" +fig,ax = plt.subplots() + +def pdot_to_fdot(pdot): + return -pdot/(1/8.4712e-6)**2 + +def fdot_to_pdot(fdot): + return (-fdot/(8.4712e-6)**2)/1e-7 +chi2 = np.array(chi2) +#secax = ax.secondary_xaxis('top',functions=(fdot_to_pdot,pdot_to_fdot)) +#secax.set_xlabel('Period Derivative (1E-7 s/s)',fontsize=12) +print(np.max(chi2),freqs[chi2==np.max(chi2)]) +ax.plot(freqs,chi2,'rx-') +#ax.axvline(x=-5.60e-17,lw=0.5,alpha=0.5,color='k') +#ax.axvline(x=-2.80e-17,lw=0.5,alpha=0.5,color='k') +ax.axhline(y=869.357,lw=0.5,alpha=0.5,color='b') +#plt.plot(freq_model,lorentzian(freq_model,popt_l[0],popt_l[1],popt_l[2]),'b-') +#plt.plot(freq_model,gaussian(freq_model,popt_g[0],popt_g[1],popt_g[2]),'k-') +#plt.plot(freq_model,sum(freq_model,popt_s[0],popt_s[1],popt_s[2],popt_s[3],popt_s[4]),'m-') +ax.set_xlabel('Frequency Derivative (Hz/s)',fontsize=12) +ax.set_ylabel('chi^2 [ sum( (profile-mean)^2/error^2) ]',fontsize=12) +#plt.legend(('manual chi^2','Lorentzian fit','Gaussian fit','L+G'),fontsize=12) +plt.show() +""" + +def sinecurve(x,a,T,phi,c): + return a*np.sin(2*np.pi/T*x+phi) + c + +##### Exploring reduced data from XMM-Newton +##### Doing sine curve fitting with the RATE data +""" +xmm_lc1 = '/Volumes/Samsung_T5/NGC300_XMMdata/0791010101/PROC/xmm_0791010101_lccorr.lc' +rebinned_t_xmm1 = fits.open(xmm_lc1)[1].data['TIME'] +rebinned_rate_xmm1 = fits.open(xmm_lc1)[1].data['RATE'] +rebinned_err_xmm1 = fits.open(xmm_lc1)[1].data['ERROR'] +xmm_lc2 = '/Volumes/Samsung_T5/NGC300_XMMdata/0791010301/PROC/xmm_0791010301_lccorr.lc' +rebinned_t_xmm2 = fits.open(xmm_lc2)[1].data['TIME'] +rebinned_rate_xmm2 = fits.open(xmm_lc2)[1].data['RATE'] +rebinned_err_xmm2 = fits.open(xmm_lc2)[1].data['ERROR'] + +mjd_x1_xmm = fits.open(xmm_lc1)[1].header['MJDREF'] + np.array(list(rebinned_t_xmm1) + list(rebinned_t_xmm2))/86400 +rebinned_t_xmm = np.array(list(rebinned_t_xmm1) + list(rebinned_t_xmm2)) +rebinned_rate_xmm = np.array(list(rebinned_rate_xmm1) + list(rebinned_rate_xmm2)) +rebinned_err_xmm = np.array(list(rebinned_err_xmm1) + list(rebinned_err_xmm2)) + +pguess = np.array([0.2,120e3,-0.5,0.2]) +popt,pcov = curve_fit(sinecurve,rebinned_t_xmm,rebinned_rate_xmm,sigma=rebinned_err_xmm,absolute_sigma=True,p0=pguess) +print('amplitude: ' + str(popt[0])) +print('period: ' + str(popt[1])) +print('freq: ' + str(1/popt[1])) +print('phase shift: ' + str(popt[2])) +print('offset: ' + str(popt[3])) +print(np.sqrt(np.diag(pcov))) + +plt.plot(rebinned_t_xmm,rebinned_rate_xmm,'r-') +plt.plot(rebinned_t_xmm,sinecurve(rebinned_t_xmm,*popt),'b-') +plt.xlabel('Time (s)',fontsize=12) +plt.ylabel('Rate (counts/s)',fontsize=12) + +print('subset1') +subset_t = rebinned_t_xmm[(rebinned_t_xmm>=5.9845e8)&(rebinned_t_xmm<=5.98475e8)] +subset_rate = sinecurve(rebinned_t_xmm,*popt)[(rebinned_t_xmm>=5.9845e8)&(rebinned_t_xmm<=5.98475e8)] +print(np.min(subset_rate)) +print(subset_t[subset_rate==np.min(subset_rate)][0]) +print(50814 + subset_t[subset_rate==np.min(subset_rate)][0]/86400) + +print('subset2') +subset_t = rebinned_t_xmm[rebinned_t_xmm>=5.9855e8] +subset_rate = sinecurve(rebinned_t_xmm,*popt)[rebinned_t_xmm>=5.9855e8] +print(np.min(subset_rate)) +print(subset_t[subset_rate==np.min(subset_rate)][0]) +print(50814 + subset_t[subset_rate==np.min(subset_rate)][0]/86400) + +plt.show() +""" + +""" +tbins = np.arange(times[0],times[-1]+100,100) +summed_data, bin_edges, binnumber = stats.binned_statistic(times,np.ones(len(times)),statistic='sum',bins=tbins) + +t_used = tbins[:-1][summed_data>0] +counts_used = summed_data[summed_data>0] + +pguess = np.array([10,120e3,5,15]) +#popt,pcov = curve_fit(sinecurve,tbins[:-1],summed_data,sigma=np.sqrt(summed_data),absolute_sigma=True,p0=pguess) +popt,pcov = curve_fit(sinecurve,t_used,counts_used,sigma=np.sqrt(counts_used),absolute_sigma=True,p0=pguess,maxfev=10000) +print('amplitude: ' + str(popt[0])) +print('period: ' + str(popt[1])) +print('freq: ' + str(1/popt[1])) +print('phase shift: ' + str(popt[2])) +print('offset: ' + str(popt[3])) +print(np.sqrt(np.diag(pcov))) + +plt.plot(t_used,counts_used,'r-') +plt.plot(t_used,sinecurve(t_used,*popt),'b-') +plt.xlabel('Time (s)',fontsize=12) +plt.ylabel('Counts',fontsize=12) + + +print('subset1') +subset_t = t_used[(t_used>=5.9845e8)&(t_used<=5.98475e8)] +subset_rate = sinecurve(t_used,*popt)[(t_used>=5.9845e8)&(t_used<=5.98475e8)] +print(np.min(subset_rate)) +print(subset_t[subset_rate==np.min(subset_rate)][0]) +print(50814 + subset_t[subset_rate==np.min(subset_rate)][0]/86400) + +print('subset2') +subset_t = tbins[:-1][tbins[:-1]>=5.9855e8] +subset_rate = sinecurve(tbins[:-1],*popt)[tbins[:-1]>=5.9855e8] +print(np.min(subset_rate)) +print(subset_t[subset_rate==np.min(subset_rate)][0]) +print(50814 + subset_t[subset_rate==np.min(subset_rate)][0]/86400) + +plt.show() +""" + +############################################################################### +######################### Folding the XMM-Newton data ######################### +############################################################################### + +pb = 1/8.4712e-6 +freqdot = 0 +freqdotdot = 0 +nbins = 20 + +gtis_conform = [] +for i in range(len(gtis_data_xmm)): + gtis_conform.append([gtis_data_xmm[i][0],gtis_data_xmm[i][1]]) + +""" +nbins=20 +chi2 = [] +freqs = np.arange(8e-6,9e-6,0.001e-6) +#freqs = np.arange(-9e-17,-1e-18,1e-20) +for i in tqdm(range(len(freqs))): + phase_sr_expo,prof_sr_expo,err_sr_expo = fold_events(times_xmm,freqs[i],gtis=np.array(gtis_conform),ref_time=times_xmm[0],expocorr=True,nbins=nbins) + chi2_freq = Lv2_phase.get_chi2(prof_sr_expo,err_sr_expo) + chi2.append( chi2_freq ) + +fig,ax = plt.subplots() + +chi2 = np.array(chi2) +#secax = ax.secondary_xaxis('top',functions=(fdot_to_pdot,pdot_to_fdot)) +#secax.set_xlabel('Period Derivative (1E-7 s/s)',fontsize=12) +#print(np.max(chi2),freqs[chi2==np.max(chi2)]) +ax.plot(freqs,chi2,'rx-') +ax.set_xlabel('Frequency (Hz)',fontsize=12) +ax.set_ylabel('chi^2 [ sum( (profile-mean)^2/error^2) ]',fontsize=12) + +plt.show() +""" + +##### Using Lv2_phase +plt.figure() +phase,profile,profile_error = Lv2_phase.pulse_folding(times_xmm,T_xmm,T0_MJD_xmm,1/pb,freqdot,freqdotdot,nbins,"XMM") +plt.errorbar(x=phase[:-1],y=profile,yerr=profile_error,color='r',drawstyle='steps-mid') + +expos = Lv2_phase.phase_exposure(times_xmm[0]-times_xmm[0],times_xmm[-1]-times_xmm[0],pb,nbin=nbins,gtis=np.array(gtis_conform)-times_xmm[0]) +total_expos = np.array(list(expos) + list(expos)) +plt.errorbar(x=phase[:-1],y=profile/total_expos,yerr=profile_error/total_expos,color='b',drawstyle='steps-mid') +plt.title(str(pathlib.Path(eventfile_xmm).name) +', exposure-corrected (using Lv2_phase)',fontsize=12) +plt.xlabel('Phase',fontsize=12) +plt.ylabel('Counts/s',fontsize=12) +plt.legend(('Folded profile','Exposure-corrected profile'),loc='best',fontsize=12) + +##### Using stingray.pulse.pulsar's fold_events +phase_sr,prof_sr,err_sr = fold_events(times_xmm,1/pb,freqdot,freqdotdot,gtis=np.array(gtis_conform),ref_time=times_xmm[0]-phaseoff*pb,nbin=nbins) +phase_sr_expo,prof_sr_expo,err_sr_expo = fold_events(times_xmm,1/pb,freqdot,freqdotdot,gtis=np.array(gtis_conform),ref_time=times_xmm[0]-phaseoff*pb,expocorr=True,nbin=nbins) + +total_phase_sr = np.array(list(phase_sr) + list(phase_sr+1)) +total_prof_sr = np.array(list(prof_sr)*2) +total_err_sr = np.array(list(err_sr)*2) + +total_phase_sr_expo = np.array(list(phase_sr_expo) + list(phase_sr_expo+1)) +total_prof_sr_expo = np.array(list(prof_sr_expo)*2) +total_err_sr_expo = np.array(list(err_sr_expo)*2) + +plt.figure() +plt.errorbar(x=total_phase_sr,y=total_prof_sr/T_xmm,yerr=total_err_sr/T_xmm,color='r',drawstyle='steps-mid') +plt.errorbar(x=total_phase_sr_expo,y=total_prof_sr_expo/T_xmm,yerr=total_err_sr_expo/T_xmm,color='b',drawstyle='steps-mid') +plt.legend(('Folded profile','Exposure-corrected'),loc='best',fontsize=12) +plt.title(str(pathlib.Path(eventfile_xmm).name) +', exposure-corrected (using Stingray fold_events)',fontsize=12) +plt.xlabel('Phase',fontsize=12) +plt.ylabel('Counts/s',fontsize=12) + +for i in range(len(total_phase_sr_expo)): + print(total_phase_sr_expo[i],total_prof_sr_expo[i]/T_xmm,total_err_sr_expo[i]/T_xmm) + +def step_n_ramp(phase,prof,prof_err,start_phase,end_phase,pguess): + """ + Fitting 6-model step-and-ramp parameters to the folded profile + """ + phase_model = np.linspace(start_phase,end_phase,101) + x = phase[(phase>=start_phase)&(phase<=end_phase)] + y = prof[(phase>=start_phase)&(phase<=end_phase)] + y_err = prof_err[(phase>=start_phase)&(phase<=end_phase)] + + def piecewise_linear(x,b1,b2,b3,b4,top,bottom): + return np.piecewise(x, [(x>=start_phase)&(x<=b1), (x>b1)&(x<=b2), (x>b2)&(x<=b3), (x>b3)&(x<=b4), (x>b4)&(x<=end_phase)], [lambda x:top, lambda x:((bottom-top)/(b2-b1)*x+bottom-(bottom-top)/(b2-b1)*b2), lambda x:bottom, lambda x:((top-bottom)/(b4-b3)*x+top-(top-bottom)/(b4-b3)*b4), lambda x:top]) + + plt.figure() + popt,pcov = curve_fit(piecewise_linear,x,y,p0=pguess,sigma=y_err,absolute_sigma=True) + pars = popt + pars_err = np.diag(np.sqrt(pcov)) + print('Top: ' + str(pars[4]) + ' +- ' + str(pars_err[4])) + print('Bottom: ' + str(pars[5]) + ' +- ' + str(pars_err[5])) + print('Vertex 1: ' + str(pars[0]) + ' +- ' + str(pars_err[0])) + print('Vertex 2: ' + str(pars[1]) + ' +- ' + str(pars_err[1])) + print('Vertex 3: ' + str(pars[2]) + ' +- ' + str(pars_err[2])) + print('Vertex 4: ' + str(pars[3]) + ' +- ' + str(pars_err[3])) + plt.plot(phase_model,piecewise_linear(phase_model,*popt),'k-') + + ##### Plotting the folded profiles themselves + plt.errorbar(x=phase,y=prof,yerr=prof_err,color='r',drawstyle='steps-mid') + plt.title('Exposure-corrected (profiles from Stingray)',fontsize=12) + plt.xlabel('Phase',fontsize=12) + plt.ylabel('Counts/s',fontsize=12) + plt.legend(('Piecewise fit','Exposure-corrected profile'),loc='best',fontsize=12) + +#step_n_ramp(total_phase_sr_expo,total_prof_sr_expo/T_xmm,total_err_sr_expo/T_xmm,0.225,1.775,np.array([0.65,0.75,1,1.25,0.016,0.0035])) + +plt.show() + + + +############################################################################### +######################## Combining Swift and XMM-Newton ####################### +############################################################################### +""" +#pb = 117403.24413 +#pb = 1/8.47145464e-6 +pb = 1/8.4712e-6 +freqdot = 0 +freqdotdot = 0 +nbins = 20 + +MJDREFI = fits.open(eventfile)[1].header['MJDREFI'] #Swift +MJDREFF = fits.open(eventfile)[1].header['MJDREFF'] #Swift +MJDREF = fits.open(eventfile_xmm)[1].header['MJDREF'] #XMM-Newton +diff_swiftxmm = (MJDREFI+MJDREFF-MJDREF)*86400 + +gtis_conform = [] +for i in range(len(gtis_data_xmm)): #for each GTI in the XMM data + gtis_conform.append([gtis_data_xmm[i][0],gtis_data_xmm[i][1]]) +for i in range(len(gtis_data)): #for each GTI in the Swift data + gtis_conform.append([gtis_data[i][0]+diff_swiftxmm,gtis_data[i][1]+diff_swiftxmm]) + +times_all = np.array(list(times_xmm) + list(diff_swiftxmm + times)) +T_all = T + T_xmm +T0_MJD_all = T0_MJD_xmm +""" + +""" +##### chi^2 exploration +chi2 = [] +freqs = np.arange(8.4e-6,8.500000e-6,0.01e-6) +for i in tqdm(range(len(freqs))): + phase_sr_expo,prof_sr_expo,err_sr_expo = fold_events(times_all,freqs[i],gtis=np.array(gtis_conform),ref_time=times_all[0],expocorr=True,nbins=nbins) + chi2_freq = Lv2_phase.get_chi2(prof_sr_expo,err_sr_expo) + chi2.append( chi2_freq ) + +plt.figure() +plt.plot(freqs/1e-6,chi2,'rx-') +plt.axvline(x=8.4712,lw=0.5,alpha=0.5) +plt.xlabel('Frequency (microHz)',fontsize=12) +plt.ylabel('chi^2 [ sum( (profile-mean)^2/error^2) ]',fontsize=12) +plt.legend(('chi^2 exploration','8.4712E-6 Hz, freq. from Swift'),loc='best') +plt.show() +""" + +""" +##### Using Lv2_phase +plt.figure() +phase,profile,profile_error = Lv2_phase.pulse_folding(times_all,T_all,T0_MJD_all,1/pb,freqdot,freqdotdot,nbins,"XMM") +plt.errorbar(x=phase[:-1],y=profile,yerr=profile_error,color='r',drawstyle='steps-mid') + +expos = Lv2_phase.phase_exposure(times_all[0]-times_all[0],times_all[-1]-times_all[0],pb,nbin=nbins,gtis=np.array(gtis_conform)-times_all[0]) +total_expos = np.array(list(expos) + list(expos)) +plt.errorbar(x=phase[:-1],y=profile/total_expos,yerr=profile_error/total_expos,color='b',drawstyle='steps-mid') +plt.title('XMM + Swift, exposure-corrected (using Lv2_phase)',fontsize=12) +plt.xlabel('Phase',fontsize=12) +plt.ylabel('Counts/s',fontsize=12) +plt.legend(('Folded profile','Exposure-corrected profile'),loc='best',fontsize=12) + +##### Using stingray.pulse.pulsar's fold_events +phase_sr,prof_sr,err_sr = fold_events(times_all,1/pb,freqdot,freqdotdot,gtis=np.array(gtis_conform),ref_time=times_all[0],nbin=nbins) +phase_sr_expo,prof_sr_expo,err_sr_expo = fold_events(times_all,1/pb,freqdot,freqdotdot,gtis=np.array(gtis_conform),ref_time=times_all[0],expocorr=True,nbin=nbins) + +total_phase_sr = list(phase_sr) + list(phase_sr+1) +total_prof_sr = list(prof_sr)*2 +total_err_sr = list(err_sr)*2 + +total_phase_sr_expo = list(phase_sr_expo) + list(phase_sr_expo+1) +total_prof_sr_expo = list(prof_sr_expo)*2 +total_err_sr_expo = list(err_sr_expo)*2 + +plt.figure() +plt.errorbar(x=total_phase_sr,y=total_prof_sr/T_all,yerr=total_err_sr/T_all,color='r',drawstyle='steps-mid') +plt.errorbar(x=total_phase_sr_expo,y=total_prof_sr_expo/T_all,yerr=total_err_sr_expo/T_all,color='b',drawstyle='steps-mid') +plt.legend(('Folded profile','Exposure-corrected'),loc='best',fontsize=12) +plt.title('XMM + Swift, exposure-corrected (using Stingray fold_events)',fontsize=12) +plt.xlabel('Phase',fontsize=12) +plt.ylabel('Counts/s',fontsize=12) + +plt.show() +""" + + +fig,ax = plt.subplots() + +def pdot_to_fdot(pdot): + return -pdot/(1/8.4712e-6)**2 + +def fdot_to_pdot(fdot): + return (-fdot/(8.4712e-6)**2)/1e-7 + +##### Independent sums of chi^2 (Deepto's suggestion) +nbins = 20 +""" +chi2 = [] +chi2_swift_all = [] +chi2_xmm_all = [] +#freqs = np.arange(1.0/(40.0*3600.0),1.0/(20.0*3600.0),1e-11) +freqs = np.arange(8.45e-6,8.50e-6,1e-10) +freqdots = np.arange(1e-18,9e-17,1e-20) +chi2_all_write = open('/Volumes/Samsung_T5/NGC300_XMMdata/placeholder.txt','w') +chi2_swift_write = open('/Volumes/Samsung_T5/NGC300_XMMdata/placeholder2','w') +chi2_xmm_write = open('/Volumes/Samsung_T5/NGC300_XMMdata/placeholder3','w') + +for i in tqdm(range(len(freqdots))): + for j in tqdm(range(len(freqdots))): + ## Swift + phase_sr_expo,prof_sr_expo,err_sr_expo = fold_events(times,freqs[i],freqdots[j],gtis=np.array(gtis_conform),ref_time=times[0],expocorr=True,nbins=nbins) + chi2_swift = Lv2_phase.get_chi2(prof_sr_expo,err_sr_expo) + chi2_swift_all.append(chi2_swift) + + chi2_swift_write.write(str(freqs[i]) + ' ' + str(freqdots[j]) + ' ' + str(chi2_swift) + '\n') + + ## XMM-Newton + phase_sr_expo_xmm,prof_sr_expo_xmm,err_sr_expo_xmm = fold_events(times_xmm,freqs[i],freqdots[j],gtis=np.array(gtis_conform_xmm),ref_time=times_xmm[0],expocorr=True,nbins=nbins) + chi2_xmm = Lv2_phase.get_chi2(prof_sr_expo_xmm,err_sr_expo_xmm) + chi2_xmm_all.append(chi2_xmm) + chi2_xmm_write.write(str(freqs[i]) + ' ' + str(freqdots[j]) + ' ' + str(chi2_xmm) + '\n') + + chi2.append( chi2_swift + chi2_xmm ) + chi2_all_write.write(str(freqs[i]) + ' ' + str(freqdots[j]) + ' ' + str(chi2_swift + chi2_xmm) + '\n') + +chi2_all_write.close() +chi2_swift_write.close() +chi2_xmm_write.close() + +secax = ax.secondary_xaxis('top',functions=(fdot_to_pdot,pdot_to_fdot)) +secax.set_xlabel('Period Derivative (1E-7 s/s)',fontsize=12) + +ax.plot(freqdots,chi2,'kx-') +ax.plot(freqdots,chi2_swift_all,'rx-',lw=0.5,alpha=0.5) +ax.plot(freqdots,chi2_xmm_all,'bx-',lw=0.5,alpha=0.5) +#plt.yscale('log') +ax.legend(('Swift+XMM','Swift','XMM'),fontsize=12) +ax.set_xlabel('Frequency Derivative (Hz/s)',fontsize=12) +ax.set_ylabel('chi^2 [ sum( (profile-mean)^2/error^2) ]',fontsize=12) +mplcursors.cursor(hover=True) + +ax.axvline(x=5.60e-17,lw=0.5,alpha=0.5,color='k') +ax.axvline(x=2.80e-17,lw=0.5,alpha=0.5,color='k') +#ax.axhline(y=869.357,lw=0.5,alpha=0.5,color='b') for 1e-11 Hz spacing +#ax.axhline(y=11830.79495183693,lw=0.5,alpha=0.5,color='b') for 1e-11 spacing +ax.axhline(y=734.51,lw=0.5,alpha=0.5,color='b') +ax.axhline(y=11689.2,lw=0.5,alpha=0.5,color='b') + +plt.show() +""" + +""" +##### Plotting results from the chi^2 exploration +## secondary axis reference: https://matplotlib.org/3.1.0/gallery/subplots_axes_and_figures/secondary_axis.html + +freqs,chi2_all = np.genfromtxt('/Volumes/Samsung_T5/NGC300_XMMdata/chi2_all_dec16-may19.txt',usecols=(0,1),unpack=True) +freqs,chi2_swift = np.genfromtxt('/Volumes/Samsung_T5/NGC300_XMMdata/chi2_swift_dec16-may19.txt',usecols=(0,1),unpack=True) +freqs,chi2_xmm = np.genfromtxt('/Volumes/Samsung_T5/NGC300_XMMdata/chi2_xmm_dec16-may19.txt',usecols=(0,1),unpack=True) + +fig,ax = plt.subplots() + +ax.plot(freqs/1e-6,chi2_all,'kx-') +ax.plot(freqs/1e-6,chi2_swift,'rx-',lw=0.5,alpha=0.5) +ax.plot(freqs/1e-6,chi2_xmm,'bx-',lw=0.5,alpha=0.5) + +def time_to_freq(x): + return (1/x) + +def freq_to_time(x): + return (1/x)/3600*1e6 + +secax = ax.secondary_xaxis('top',functions=(freq_to_time,time_to_freq)) +secax.set_xlabel('Time (h)',fontsize=12) + +freqs_fit = freqs[(freqs>=8.46e-6)&(freqs<=8.48e-6)] +chi_fit = np.array(chi2_all)[(freqs>=8.46e-6)&(freqs<=8.48e-6)] + +#pguess = np.array([8.4712,400,0.02,200]) #for Swift +pguess = np.array([8.4712,500,0.02,11100]) #for all + +#popt,pcov = curve_fit(lorentzian,freqs_fit/1e-6,chi_fit,p0=pguess) +#print('Lorentzian') +#print(popt) +#print(np.sqrt(np.diag(pcov))) +#plt.plot(freqs_fit/1e-6,lorentzian(freqs_fit/1e-6,*popt),'r-') + +#popt,pcov = curve_fit(gaussian,freqs_fit/1e-6,chi_fit,p0=pguess) +#print('Gaussian') +#print(popt) +#print(np.sqrt(np.diag(pcov))) +#plt.plot(freqs_fit/1e-6,gaussian(freqs_fit/1e-6,*popt),'b-') + +#plt.legend(('All data','Swift data','XMM data','Lorentzian fit','Gaussian fit'),loc='best') +ax.set_xlabel('Frequency (microHz)',fontsize=12) +ax.set_ylabel('chi^2 [ sum( (profile-mean)^2/error^2) ]',fontsize=12) + +plt.show() +""" + + +##### Doing contour plots for the 2D P-Pdot exploration +### do a PDOT version too?? + +def summarize_2d(space,chi2_type,posneg): + """ + Summarizing the information from the 2D chi^2 exploration involving frequency and + the frequency derivative + + space - whether in frequency space or period space + chi2_type - 'XMM', 'Swift', or 'all' + posneg - positive fdot or negative fdot + """ + plt.figure() + if chi2_type == 'XMM': + plt.title('XMM') + if posneg == 'pos': + freq,freqdot,chi2 = np.genfromtxt('/Volumes/Samsung_T5/NGC300_XMMdata/chi2_xmm_fine_ffdot.txt',usecols=(0,1,2),unpack=True) + if space == 'frequency': + plt.axhline(y=5.6e-17,color='w',lw=1,alpha=0.5) + plt.axhline(y=2.8e-17,color='w',lw=1,alpha=0.5) + elif space == 'period': + plt.axhline(y=-3.9,color='w',lw=1,alpha=0.5) + plt.axhline(y=-7.8,color='w',lw=1,alpha=0.5) + elif posneg == 'neg': + freq,freqdot,chi2 = np.genfromtxt('/Volumes/Samsung_T5/NGC300_XMMdata/chi2_xmm_fine_ffdotneg.txt',usecols=(0,1,2),unpack=True) + if space == 'frequency': + plt.axhline(y=-5.6e-17,color='w',lw=1,alpha=0.5) + plt.axhline(y=-2.8e-17,color='w',lw=1,alpha=0.5) + elif space == 'period': + plt.axhline(y=3.9,color='w',lw=1,alpha=0.5) + plt.axhline(y=7.8,color='w',lw=1,alpha=0.5) + elif chi2_type == 'Swift': + plt.title('Swift') + if posneg == 'pos': + freq,freqdot,chi2 = np.genfromtxt('/Volumes/Samsung_T5/NGC300_XMMdata/chi2_swift_fine_ffdot.txt',usecols=(0,1,2),unpack=True) + if space == 'frequency': + plt.axhline(y=5.6e-17,color='w',lw=1,alpha=0.5) + plt.axhline(y=2.8e-17,color='w',lw=1,alpha=0.5) + elif space == 'period': + plt.axhline(y=-3.9,color='w',lw=1,alpha=0.5) + plt.axhline(y=-7.8,color='w',lw=1,alpha=0.5) + elif posneg == 'neg': + freq,freqdot,chi2 = np.genfromtxt('/Volumes/Samsung_T5/NGC300_XMMdata/chi2_swift_fine_ffdotneg.txt',usecols=(0,1,2),unpack=True) + if space == 'frequency': + plt.axhline(y=-5.6e-17,color='w',lw=1,alpha=0.5) + plt.axhline(y=-2.8e-17,color='w',lw=1,alpha=0.5) + elif space == 'period': + plt.axhline(y=3.9,color='w',lw=1,alpha=0.5) + plt.axhline(y=7.8,color='w',lw=1,alpha=0.5) + elif chi2_type == 'all': + plt.title('all') + if posneg == 'pos': + freq,freqdot,chi2 = np.genfromtxt('/Volumes/Samsung_T5/NGC300_XMMdata/chi2_all_fine_ffdot.txt',usecols=(0,1,2),unpack=True) + if space == 'frequency': + plt.axhline(y=5.6e-17,color='w',lw=1,alpha=0.5) + plt.axhline(y=2.8e-17,color='w',lw=1,alpha=0.5) + elif space == 'period': + plt.axhline(y=-3.9,color='w',lw=1,alpha=0.5) + plt.axhline(y=-7.8,color='w',lw=1,alpha=0.5) + elif posneg == 'neg': + freq,freqdot,chi2 = np.genfromtxt('/Volumes/Samsung_T5/NGC300_XMMdata/chi2_all_fine_ffdotneg.txt',usecols=(0,1,2),unpack=True) + if space == 'frequency': + plt.axhline(y=-5.6e-17,color='w',lw=1,alpha=0.5) + plt.axhline(y=-2.8e-17,color='w',lw=1,alpha=0.5) + elif space == 'period': + plt.axhline(y=3.9,color='w',lw=1,alpha=0.5) + plt.axhline(y=7.8,color='w',lw=1,alpha=0.5) + else: + raise ValueError("Make sure that chi2_type is one of 'XMM', 'Swift', or 'all'! Also that posneg is either 'pos' or 'neg'.") + + freq_1d = np.arange(8.45e-6,8.5e-6,1e-10) + if posneg == 'pos': + freqdot_1d = np.arange(1e-18,9e-17,1e-20) + elif posneg == 'neg': + freqdot_1d = np.arange(-9e-17,-1e-18,1e-20) + + N_freq = len(freq_1d) + N_freqdot = len(freqdot_1d) + + freq_grid,freqdot_grid = np.meshgrid(freq_1d,freqdot_1d) + chi2_reshape = np.reshape(chi2,(N_freqdot,N_freq),order='F') + + if space == 'frequency': + print('Maximum chi^2 is ' + str(round(np.max(chi2),2)) + ', at freq ' + str(round(freq[chi2==np.max(chi2)][0]/1e-6,4)) + ' microHz, at freqdot ' + str(round(freqdot[chi2==np.max(chi2)][0]/1e-17,4)) + 'E-17 Hz/s') + + plt.pcolormesh(freq_grid/1e-6,freqdot_grid,chi2_reshape,cmap='gist_heat',vmin=np.min(chi2),vmax=np.max(chi2)) + cbar = plt.colorbar() + cbar.set_label('chi^2 [ sum( (profile-mean)^2/error^2) ]') + mplcursors.cursor(hover=True) + plt.xlabel('Frequency (microHz)',fontsize=12) + plt.ylabel('Frequency Derivative (Hz/s)',fontsize=12) + + plt.show() + + elif space == 'period': + period = 1/freq + pdot = -freqdot/freq**2 + + period_1d = np.linspace(np.min(period),np.max(period),len(freq_1d)+1) + pdot_1d = np.linspace(np.min(pdot),np.max(pdot),len(freqdot_1d)+1) + + p_grid,pdot_grid = np.meshgrid(period_1d,pdot_1d) + + print('Maximum chi^2 is ' + str(round(np.max(chi2),2)) + ', at period ' + str(round(period[chi2==np.max(chi2)][0],4)) + ' seconds, at pdot ' + str(round(pdot[chi2==np.max(chi2)][0]/1e-7,4)) + 'E-7 s/s') + + plt.pcolormesh(p_grid,pdot_grid/1e-7,chi2_reshape,cmap='gist_heat',vmin=np.min(chi2),vmax=np.max(chi2)) + cbar = plt.colorbar() + cbar.set_label('chi^2 [ sum( (profile-mean)^2/error^2) ]') + mplcursors.cursor(hover=True) + plt.xlabel('Period (ks)',fontsize=12) + plt.ylabel('Period Derivative (1E-7 s/s)',fontsize=12) + + plt.show() + + else: + raise ValueError("Make sure that the variable space is either 'frequency' or 'period'!") + +#summarize_2d('period','Swift','pos') +#summarize_2d('period','XMM','pos') +#summarize_2d('period','all','pos') +#summarize_2d('period','Swift','neg') +#summarize_2d('period','XMM','neg') +#summarize_2d('period','all','neg') + +def add_orbphase(eventfile,pb): + """ + Add the orbital phase column into the event file + + eventfile - path to the event file + pb - orbital period in seconds + """ diff --git a/Lv3_visualize_presto.py b/Lv3_visualize_presto.py new file mode 100755 index 0000000..d89eb9c --- /dev/null +++ b/Lv3_visualize_presto.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" + +Created on Wed Aug 5 5:54pm 2020 + +Script that visualizes the candidates from PRESTO's acceleration search algorithm. + +""" +from __future__ import division, print_function +import mplcursors +import matplotlib.pyplot as plt +from astropy.io import fits +import glob +import numpy as np + +def visual_accelsearch(timetype,min_freq,min_sigma): + + ACCEL_files = glob.glob('/Volumes/Samsung_T5/NICER-data/at2019wey/accelsearch_GTIs/*E0200-1200_ACCEL_100') #gets the path to all the *ACCEL_100 files + eventfiles_ACCEL = [str(ACCEL_files[i][:-10]) + '.evt' for i in range(len(ACCEL_files))] #gets the path to all the corresponding event files where there exists a *ACCEL_100 file + gti_no = [float(ACCEL_files[i][-25:-21]) for i in range(len(ACCEL_files))] #gets the GTI number where there exists a *ACCEL_100 file + + ### below are just the headers in the *ACCEL_100 files ; the intention is just to get the indices for these lines later on + header1 = " Summed Coherent Num Period Frequency FFT 'r' Freq Deriv FFT 'z' Accel " + header2 = " Power / Raw FFT 'r' Pred 'r' FFT 'z' Pred 'z' Phase Centroid Purity " + + for i in range(len(ACCEL_files)): #for each successful ACCEL_zmax file + freqs = [] + sigmas = [] + accel_textfile = np.array(open(ACCEL_files[i],'r').read().split('\n')) #read the data from the ACCEL_$zmax files + index_header1 = np.where(accel_textfile==header1)[0][0] #index for "Summed, Coherent, Num, Period etc + index_header2 = np.where(accel_textfile==header2)[0][0] #index for "Power / Raw FFT 'r' etc + no_cands = index_header2 - index_header1 - 5 #to obtain number of candidates + for j in range(no_cands): + freq = accel_textfile[j+3].split()[6][:-3] + sigma = float(accel_textfile[j+3].split()[1]) + if float(freq) > min_freq and float(sigma) > min_sigma: + freqs.append(float(freq)) + sigmas.append(float(sigma)) + if timetype == 'seconds': + times = np.ones(len(freqs))*(fits.open(eventfiles_ACCEL[i])[1].header['TSTART']+fits.open(eventfiles_ACCEL[i])[1].header['TSTOP'])/2 + plt.xlabel('Time (s)') + elif timetype == 'GTIs': + times = np.ones(len(freqs))*gti_no[i] + plt.xlabel('GTI number',fontsize=12) + #print(times,freqs,sigmas) + plt.scatter(x=times,y=freqs,c=sigmas,marker='o',cmap='gist_heat',vmin=3,vmax=4,edgecolors='k') + + #plt.yscale('log') + plt.colorbar().set_label('Significance (sigma)') + plt.title('Energy range: 2-12 keV',fontsize=12) + + mplcursors.cursor(hover=True) + plt.ylabel('Frequency',fontsize=12) + plt.show() + +if __name__ == "__main__": + #visual_accelsearch('seconds',10) + visual_accelsearch('GTIs',10,3) diff --git a/__pycache__/Lv0_dirs.cpython-37.pyc b/__pycache__/Lv0_dirs.cpython-37.pyc index faf40aac18be01ab1945783aabb30d80a51b7224..1497b58b09e02b42353b9feffb363aaf011b5afe 100644 GIT binary patch delta 222 zcmZ3&I*Ezk5TlBn;e$ri=o z delta 21 bcmez5`pK2YiI_wHn8HX+gY03{}jl9-c%#6>g+9>jw}U@#10svRbo$8OI=G(>XP zoV+db2lVQ}OTept!qZ&+177uH^+IA5_0^-P{=TOF^ndzmk6qURGSj#p{k8#qspi}) zDjrc(-==H#PV~&q?a*d`3_F<z!DT=f=dh0+`iVZ_491^!06Q-s7#uyAen%@{ ztyYgQKU-#8W9`{B{TX8`O=9e@`R0dl_th$?ZLKKEga) z<>g9p1-+>a}hK`T-(6i_Ce)b6Eb<;XWlp|o=?iR;{R8ZhchCR; delta 342 zcmca2_>*7ViI;IHNdI7*m*YxT3gH z*%ojwWME`SVNGFcVTj^MVQ39zvsRAk7 zDLg5>DSYWH%}hYO%)tzr{1b1bZT4VfVquKh?9J-Q$fz`VDqA?C(B!vl`cf)D%WrYS z$LA(y=EcWHaTyvIn;4iI7#bK(E?`%j{D57WNmFn#4~KTW5J)9gVsS}PenF*PW_}S1 zP@sq(M2LW;(sS~Y5_94U5{rsprsgH)rpCt?$$=D!fe2|3p@d2(1G%?2Y;yBcN^?@} hfFZ&|@^Z3paT*yI8UT@z@nlIBYp$1UK-rh%q$cNBqN2g81*L~5sGFso~$4&1r)Is)|9paD!j#+UzC(tl9rj1TBHQhXagdw JC)W%60RRwP9)th@ delta 114 zcmX@Bepa2wiIE0t>zXooBKt*<2Cf=Tpaw3e1}>0>$t4`B&Uz&* z3;1eSYFL44SZi3IYM6nB@`BVXWUl4UQ^KhRY|iE@90{zPN{kXrT#PDAN}Fx@C3df~xz%B`;UZMSRl^B1f(vQ{ zmpH@Z8V*%!wGx&Ed^IdJtU$;Dm1hQ8!7I+NkhzvWPY#DXQ2*v990{zPASZA!Dlo}y J_T`i31OO%aC>j6& diff --git a/__pycache__/Lv1_data_gtis.cpython-37.pyc b/__pycache__/Lv1_data_gtis.cpython-37.pyc index 1ec2debeccc62d9dea901f2c34c993a3dc0ef2ba..4fa6a1e5445ce0b5b01df295ad61c7a0e0bc01ad 100644 GIT binary patch literal 2159 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 pdC=))rl~T_yFvOXR)niMFHutn_#nn@S zxTxZQ3l~$I$U*)IR8CwuaNxv|GB>J#1OI^Hz26&bN}(m_;H2#{X9zi#DD0r1_U2H<_85oaLf;J^fw6p z21GPN!q=dnhXp+(=srwemLNvnrq_lcX~i0`VthCkCLS`n54ugsio-K{AXk5B)**6S z2YKxWYYYlDMgpHZBGM@;!pB6rPIUc3(rDW_@A>~;<&^03<_Q+5_w#W+Ve>$=HfbgJ zBrFeihjAVR6?!!fNsih#>r!0FMVs@I#Cd^YLy#~DNs{0xl4Jw9K`3yFOznHEDITv6 z@gz@y#V}7D%1QyHTQ8CHy*_CM4kO4I9P)~ zaH7_3ThrJxuuAf2oFOtRY*Gylrb+P7XQk0)@DBS9U8nna;M%(SKss=2{qz8OS|2%- zWPA}~d=y@eQ9;FlinBPGV-5zA8sr8_;@X4Z1}F2vX`JI`p=o5@9O{J-1O~~s5U9q1 zn>yH7Zk)u(85|U-?gV-3wGn??oCYJ_v_A_T&Iy@Ecsn1e;alSt%%V^<<~2bs>^sDf zljI^f=IV(?YY{`zrbBdMBzJnxNG=MsjYC668x4g-l9=MFgvcdwdB4?~X(aIwviR|} zEJohwB$i9zv2f@WvIIw5-S=3tJeHf{v*ev-u(A3yxh6u2)e~QLMA9C5<@C|4uRenv z0nZL7pG=cHK(33dPwtInc=P92Uv9Q}x6DDwZjhT;4X_s-J&?DO4-63Ts z%Q8y3M5$qxOGT0`ZYmqp*s2)C^fP7GsodVR|LS=@`4H}7`Z0ov@Cm{rgf)c62pWKD zf72U>D8BE#+^afCIh&X}@_nS|E5;2>?m+|dqFFkTESqM5>Y(`y;#xn zYKxiH88axwkB!>8nKhY~F?2@HqO(gV>;?x#J&%5h*^O*kFQ$78dLH$&07vdJ%@!G5 zvYnyJGpdi#Y`Rorr3zI&>Ab#f3y`rFIi%qF5AV>h1v~Z)K+5~{St`e zL)@`~Lca;8qz$d87Yup}#kW!HTh(?ATFUMkguaV{juU~#Xr-7|+tQ^TP(^rV4@B>D R7kskI>6P1Luk32Be*sBYB^Uqz delta 1985 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 YM#P&pP;MaAC>d0AP#i3yR=4N>3*mz!4*&oF literal 0 HcmV?d00001 diff --git a/__pycache__/Lv2_efsearch.cpython-37.pyc b/__pycache__/Lv2_efsearch.cpython-37.pyc index db93d24a2004b25a5659a937757255c43e559627..b171e7aa0b0b18a62aa4f20e4faa9860fa1e60b9 100644 GIT binary patch delta 612 zcmZ9IPj3=I7{+JlqJX;N0ag@f0X*O!kemwe`v4qC@z{QE6|I~>EQQMoYYOWM=M?G^0(bbVGFOzDl1t*N%C`T-H8oAO{g4ejxSo|Rx+>0 ziY28WwJ3@$uOK6_I5mnjFDWyxC%?2LEi)%Iz9>JxBx>?Po_Ml6qOz#sP>E$gL>$J1ImRz0f|#D99D<}S8kk8#DU*$Q%WgOC=$Dx&-`ZQx4+-) zcYm|LOn-e&IUfxA2wYDto+>;W{6_haDp44Ep*f)GznksQCG)&A(qdlbD@$$1BO(G1 z$r@#T7I+|wpin*~%$p=zbc@c~Y`TPR$8Qi8G-%t=bQ^9aB}vmGTstA57@jTKrcK%K z7#^l1NrE)Juo7kpFk*OFC`sB>L|-1UU}uXMQa6N*LkbA$6CLZFhS!i;*zmE)w(|o= z)87miMxjI`cT(_l7Yls?8#MeZ)^_0R zdN+$3p*UfQI1$tcZ_zkuu_Q}vOZIXP>wam}%X+{`LMPS>?YW=fV6HpT=ahd7Y0_;% zNp%M1-1gjWENz6rH)AK*e>NK@%?KpV7*5s~Cq@L;``N&L&K-XiL$Iy|k~^}y>-b7) zN$`Cv*TUktn~RonVe#7a5``JOaK#0!1DbvWP$mZXu%}7kOA&Zcnj~NW(MpiV(nn4R zD{()#ax90ZFtViKQHyFhYWZ|gpl{qEy?cPY=VA zj;Y4k=*4>er+aGkC3G|Xua-~__68L)G4o`sJ0A^H&m z2>iBu5OEZ73~?NhBgA~9WN(b&;4Q@4h|`F1#2Lf{!h?7RF$u^8`4rmkBBlYBB;JHJ z#?Ru+jJc-_49}vOM_fd_hrq(vhpno&4ke=%D+O`Yyd0XO^Scj2W!Hg9Wz9@irggYb zww5o{;_pMUhVzcPJk;<250)(UI+9(2NGsk|tyQf;H5T&RiSO}u*(~>(R^H_5zsNU( zPudzP|IjcG8s?vCcoqDtsNkE`Qc&T^-wEBIHzg~XK{4SlD!&7HTHQn-+E45WP4iJ~m;rcvc8F34JmT`Hi4tl;oU}nLkhE!<7@9V!gg_i3z&M^w*wnGp z@dl_h#)p;*QV`Po0XRZEaNq!u_#Y4_t_#QB_y^#|dux=G5``k+(R}vJn>TM}zkXwX zyZqZV>xO9>1U_HwPQ70_|DE+KwNfzDpszsh{2+g)_xpk#MtV^ZWlEm(Vt#ax@J$hW zKo4mzE@C3a^gPLto(3}((}78$F(Xe7>613oGDIjv!Ze3KKHax>QbH4Pc24LlaiG2% z=^4Fqy@a10j0jlEv^?3#^i0t=nF$+P!ekaalm6%+3rmvB_zVstj6;PIe{{!Twy+$+ zQV#K{NIsxor`gECa5l#>PmJQx(sWya*7RDPy?Vn9)Q0Odn`B48v{f6)bnU1gB3Zfr> z*lxO6{EA)ykVJxNVJiS_swuW&fn_NPTA?`wJmAaF32M;-HNuvoS<0^-y=Od9Q#z#J zCc*;T;f7q!mgIag-^Xg;NkEx$8y;QlZEx2tUFej%v6c3I%b(?G3>g6gN~hLUIy2p9 zr?SVkcm{ml!$`Px6zsCY@x!@w{Sv=~o_V=wKUcYeCW^;jMZAVsIL0DafxcJgzE^M7 z{8f2iFVK~vAMNevscJ3t&lV}v@mMK-4bpejyY4$P-8k@cxw6k9*Aisf&^Nt)tL3$} zYgMk|JN#X;AhzXg?{oKGq?^Z;p?=ms^s9n?)xY$+0dYav=liWj-FI2duQl5H@>A#e z|DqH8dji+%E=G1g+5=!^PMg8Qwn1-{$DEh$%e7%4OR9}m6=!Z zfM=KIiN^L*8uRP8dKvLL;tfPtuc$Y_c@?>axP^Fz@->djw>prICzj~CJU{7DU4A~f zF@+Z{(AGbit1*vvcnNc2Ed|j|!`r*hqv#lyMrraU-nu|(cLHO(+1`Zf0C{q qw-M_Yqt$Ay`mS564PWi#Hig!ryjPk|RkRsxR-4nP3cp7=Xnz8Fd`X`G diff --git a/__pycache__/Lv2_merging_events.cpython-37.pyc b/__pycache__/Lv2_merging_events.cpython-37.pyc index 1e86c587b549cba485ae3f45bc19ff86dd982040..841ae15ac4ae48a837b6f5c13f56ab0fce7df3f4 100644 GIT binary patch literal 3062 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 diff --git a/__pycache__/Lv2_ngc300_color.cpython-37.pyc b/__pycache__/Lv2_ngc300_color.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..65aa5869ed6cf64031d451e83d820b5343ec10c3 GIT binary patch literal 2629 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 AUjP6A delta 4158 zcmb`KU2NOd6~}og%A&q(S(d0zOLF4G(Na6Mo5XG6IL?Qg#Bs8wO|wkR$|}0FBU@j+ zq?1~psxE1UVOZA&7sI}=)_K@~y{+&b25i{&wzmKShG8JEVL-7BS%K|o>zbGD97>iQ z*F{pSl=#1w=kikIIX|9r^}+YZ&u)=D$Nhef09&=Z`=#a=1>t=>Sl>kGOvA4KQMj|` zVY;!z0?P7ocd`u zvS(x4mnlaC(`^b7fl3L`hR5`nVib--Lc?o1Om9dqCF)EFrk6VVgb?TBH#&gh6|_$2Rx1&0#ZShE0+X=0)(K zKmYog+WiVyBY_}k7N7f*AS~2JfB5nT^)pBBe+*mk^$SE`Zt%%{^w50=2t&Uyf`Xi6 zMdro659EASW`1Zbsanx=%TdxQ4E@iXD7`r1%rll>VLi~#Di$#;a*@e6K*IAmX`WV% zoC_7c3+W2&EkIMRSiY+PVS^nB`N!Qf*YKayr3u9o?@p?i~BKQf3KJtXv4g5sKAd$or zQA9QZ;~jnwGkgSej{bfAZo0((5dK=vP18ZWF@Xk_#J35%$(NMj1JY`*>7%_dh!FJv zHey1c9y|7aBe>WHvG>v-#J|sueK$tm2=U)3J4u-TTN&~zs}a+l8xt0zJR3>)9~iOK zIKEg$Y%#$vL=wAVt4T9RL$nu}F#GO`_EYr&gBhIl5LW#CJ~+F;Or``HNpZ~rke z$`7TEcZKm(h2KmKo*cq%9}0qIx%F$sc>^ditS-Z5%ks9lqIn~~fgeK(+FbH~q=uvR zqZ2lPW}7qTjce7CcA4)>j~pK%Q8Fm*5d%afG9)IMq{I+F7AGG26D11R*#b;1;M<2A z-ed=}ch=rbe?(^O;3|u8is4P#0Z|qcG}Q@R975F|G39oM4;sp9(hmD&u*r7Vzs3JE z@MNUlbkjiya0q7YqPttyTTQJ^@2ES-KK_ecU-gc{T`+t}*f{_7*r7lx?09Skd_TXl z`{ejm0N4RM;UGx1?UByw$DRV~Zv^fd+UL#SSx=)J;>U&#H>a?B7zAcbV*dz8z3W7E zxnk^NN6|73Vu`w17xm$~Qy;0(d3FqJ#W&z>glWg2pG~t9(6EyzGbosS>_o+$!QLs9 z(L-xLQ`OK*hR9~ITYl|^37czQ!)66gXIRPK;BS|Hdc6^gaV~gV9%mlKzR=3 zd6bJNFQ8mPu|4`F>|F-QhS`^~pR<4eMeJTdX(0+dOEkt{A7@`d^Ghfy3W95S4Yph< zQ8bi!lug(MTim*9d1e&zCDr(WzysN%BOwBy0<`!UZGl>a zsRi^CZV%vIjYx(mLgpPeyLf!ne@zHDso~{ij_7KO-e0I>B z0(^JykH*u@4y5cFoLrZdv`fQv7wG3o>b9V=A|kW_=*;5)x`j=f*DZiXJAeud`Lx_K z@D8YYv95gr)#MDYIIoLH1P=pE^@9W};3o*dpbEq-R`Uf}N?84G0K2{u7Dj;WDM@sX)ivxY;D zPLM73FhhR6{53nN@>2m6EKesvJ{EwFks;&j05;+2?F`A#4-cnFwuH74ijHESY?Crs z83&e8uA|&Qc}yr{>($Jz@19PcoXPUPA3YxGM4f|2vpYO20`wN|Pcy2_@(^ms{VU~9Rw>*JQ1xuslU ziL>PPuW|K^67LjD%tHcu1tpDgg}-$sihnFy)e&dajG|G}S|xI$Fm9K8GV8I2*&Cq` z;>9`@GUsXEhdQHg7ktYxU*x-I2T$RG_sEPg3K@>vO3Cb5KC6o zO1`YAYRiXM>03`=_iTpc$#Ru0m$WHNo%$XSi3Erb)~6XzY;6@~QI5$&@(K8ymCwn~ H$b|e4(g{}v diff --git a/__pycache__/Lv2_preprocess.cpython-37.pyc b/__pycache__/Lv2_preprocess.cpython-37.pyc index 579a552d61d7b8a1cdc7a3415e3880e055790422..4a8aab2c349fc75791f64745553750310341f882 100644 GIT binary patch delta 895 zcmb7?F>ljA6vusb;@FOzw9p19X=|5;5=Cm#LPe#bia>*!1_DYuA%Srdr&w|v>%}RG zWhn#fARQkd84wFg+kuhq5xxTp8xwbKkP1^c%m2Ikz5lyA-}9Hn?`qGa+R0flOE| z;DSgHB^mKyjAT$M1mc)V=d>a2Gg-;_$uW$ilJ*SDvmYFe^!;?T{YLFNzU8`>bEF!! zt$MFbwQ1RANAqWB6uOQ>V~$lf!Cu$=n-{6u0oQWPRkx=$q1{re<%gwOr`_~4f9ay{ z(12dO4RG$-Efx2lK01hK)vSWw3Cn!c1YxLeubXp7L`eMdQ5lP4!@AsY0dIk4*qY6 zC-`|{cQ(vX=(Y(eNh(wLYa-YGQx3;ynYunw!kiz7ZhH!(9W zKE8@a-_XF+z`)$V(7<@|FRrE9GC=tvFd++M{o=C8$t*5O&d)8da|H5>nScZvLy-!Q zx-~hEC&5|)$g1LvH^?n0HIGlu(Mv5W(PS)A1d3`h6)6F!B4rSPYAjg4>tsG&g~@i@ z#*=sOh%qWmKF=eiN{l`?puQlW`b1s}qSU)j-p88;RIkdXs;>rei#muP#wHJtO?C=E zkw2<*rrL6B-85FrdCZm||6=B20JV$Mm;D-r>Tih@NGi;5B}i=;sUVv`^8 WONgQcJ0wac3kzs7Do?f-kO2Uqdw_ZX diff --git a/__pycache__/Lv2_presto_subroutines.cpython-37.pyc b/__pycache__/Lv2_presto_subroutines.cpython-37.pyc index ed00825d82542c03bf19beb7bb73e2a5132c8981..b735ce0e18b4634765828494552a2f68c2ff7fb3 100644 GIT binary patch literal 22130 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 literal 15466 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 XsQ^&bKO<=zHK>F@6(1?^Kg#_tlL?AC diff --git a/__pycache__/Lv2_ps.cpython-37.pyc b/__pycache__/Lv2_ps.cpython-37.pyc index 907fe6ac1f9cbbc2496c00b30a225d02419a4811..d5047831fb72e0a3bfd34af6d8049a38bff1d184 100644 GIT binary patch delta 1297 zcma))&ubGw6vuaVH))f0o1{N>v)Oi&R@Eed4##pzU!3q!vQDP(%=D6o_aD5YU8q zRFoXW4&~}eEvbQeqCmr4qW7ZcG&)VTnv2ka)HU~=c^cf)8X^*S^Wt3*C!mEiXabm;U?U>VBesref}^si zW>O6?O&}_>wL;sX$nH?x7M_7LlBP-Vj6h`YmGgXFM`3QD(44TXiVUMe?wWhB3C71w zFxvkELnGl;3_rt=v0G7uj&(%{yQ^3otU7B4WiB@goe(IBtXevo5yv2UE=GUI?Q^aC zov@=Qu@^^jZO{bVxXg^XB4EVr>{H7m?jze8obn*p@bHy-sQdku?+IP7F&*P_hha~&MGX^hKpCd;C|i_HXmk&K|z z^sBjr)<^f%06#BFnx2X-p_$T;=n(~7rh`3wC`)I0UZWgM_U;emc@E!1*0QozCN+v> z+M8_qJ4M3^g|VK3{_NH0%cSl-%`cs%eewPc3{T@rs8Bk$b4W2W%&QRe$40F*&fJRO zaVwJ^h!x~~`g{+@rP3gv`ZAS&jmrKfR`&{4%X%yhV{@6}VsW|7WtP4(n^n95%MCZU z+~jhL)hiuKV4dFRc>VOFAU{E5dZ)H delta 1213 zcmah{OHUI~6rMXXl;_X_old9ILP1-?s|6GU!`q4s=rnJ(O^f54>+8)MWEm&BC|H+pY@$U|f%_sc!!esjL>oI5Ypk+qJbK1nLz z=!4_I(NC|W=cpi$MwjSHTIsjwBI?bt?6?R@R4#?U?&L79abQ=tlweARBUXZoa3Pdp z3CcFa5y31r?WV&hwaRdouW~Ub=@PU+t07yi6o)uNvD{d~#n^^(!G&{Dwh`WRnzA9s zRB~UalXoc7!q(YJ;csWXnr_2y)=t0R`VN z1;un{6>7!0l}GPNXCTb4A-WGJoav%pouJA*VgYW&MglTiv4s}Wzbh_F;xs$@+8O5c z8M55)9!1GOs13!)YRGw-bg)J{DxKdy9!*4&(dEeu-%nli@4E1z1nCI3AM^1#yoHw1 zqm4Zhnj+6Sz2a@==8M;r{?K_HQ5Tin@@X#WYkWss=t)mvb&!~io+UL=wji%&)(yH>N;@E3q2`&$11Nq;X1 diff --git a/__pycache__/Lv2_ps_method.cpython-37.pyc b/__pycache__/Lv2_ps_method.cpython-37.pyc index e3933011320f1a8bba7f29f35f6497813b511d7d..b4d878e4b0e1f0986c570a31158991d122c1f905 100644 GIT binary patch delta 1759 zcmb_cO>7%Q6y8~{y+8J@?ZkF|oF+~~mAa5PNoh$FlvFKhRYAic5LE`TS~6>EQ}5cH z9fu^^C`bWrfrhbpdsgeF^xtJc+6PPJ05R@Y)V(Mr3Sx(>2T zm5+qFK~<_jpQUMiNPx{>A{?S!(EkTCEjxwSY#uEM$K$Mk6BUF3gd)NqLJz_)Ks6bq8rCXrGgc1w4osxifF_!yxjm5xJiTVn{K+T~&#e3sR%F9{bp+S0<&GY!KP1RVxU0_t zLEq`)i+P4=A14-P+>67QfPR$X+$E6e>5k2uHf=YVoYf>wcc z+dg`n-%Y$ZhPQ|SZ1pZ}KIl3=uQZtbplf@pn{yR5f@T@brCTTJ3bXxotIM6XH&7OoEC02zoyM*u}!bJf#R1l^RrV(ZkE(1hT+q32X0O{GuX)W?Fl|hq3Z`qb zrfqu8s?D%~wXBY5wOW(*I^UZ8=jInrcfWV{F15H-+i+d;eT!|HCtKsvYBBt+G(LtU z28#8n)7fNLRU*v-_S>D!NvF+{pkS%+Qs2l<%r6#N7%Q6yBNL_0Il!As&_W<-sXzjX5Fo)RNJOj5+Og}k&FluL z(ON+&aDh}rBXPw(Lr*#OgoMNe?r1@xS1w4Lx$xeapO909QefQquJ+!K^&_uFdPj}ss}b8`MB#+1Ju|YlY~VUCe57nS+~5pmmz&&z+2b~M zU@nF}cW+a%8_sa=E&+S>ZKYW}`ud(vGd)g%B+d$Pr`->F$M2BmR8p7sv^7$Y-)Mpu z@~VC~@4z;iMA$G17a%i+0q325+mk=(=gGn`DG0LeqekuY6ETa120{&?j4+2VgRlV5 z)U!e>*hvOL%*(Hg$KR@>2IEX2k75lz2t^!3!(Mm=G%>0b!y$}R;9*oO!+NKHQW&U3 z{t~?L&vKFd;io#c=Ab^e>E}c|pP2HRxuJiXSYuoMZk8((N|eOvI^5$$?jKH9uKd!h z>SHkS?=80F47Ged zl<^r}f@k(n0}pw%xCLj03Jx`^{JV(>IlZnz{T^kbEegF>4)&>{Sm$8863VJ|;drz3 zu6q74JSPO84KI$H0?)5l1lXtIl2`#Ezjx~g4IqCRJ$#|5i3@1fM7W6X1VFR;C81E3|s_cJZ-?1y=0i6_zdB}I8%5lcufBVZ?rrw~>FGHuWg zgDpw zXw0^^qoC8@-p=T5r&*GVwMGg14sNiW&hU=VfD2vj)|Pm_ZOn9<#dTzV`{)Nz2tM?o pzj1!PwI&3o<@V#Dm18Wmw8*9XeF7$~**)l7#Rd$n+KLI=3Eyn-= diff --git a/__pycache__/Lv2_swift_lc.cpython-37.pyc b/__pycache__/Lv2_swift_lc.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..96c2540cca17d156c3a9868fab5a7edc570ba381 GIT binary patch literal 9476 zcmc&)TWs7`dL}uX8O~L=v1B{mgtl|B9D8(0ve^bv>YJRzaO_l8>Xhh~rRGqhk!FVD zLyj&4^-^uI#sWpR?|o2!MS;GwZ^b_D)AqHmB?=Tp(FX&0F3<(q^!tBuE|Qhq?4m$5 zKIGxK-~R9a{{Q$+rBYPz_w+x?_Aizd<=^RJ@RvvA7J_eRiXs$C5vtJIYDcrQPR7cp z^qpzzR+itnPTtCMn%*`#1*?$e7ds`ZoW?6wh09j0D!(VJ34TvnlXz#_Q=MsRIxRb6 z%^)q;u61fwEloRTo#XPe)-1p0tU0%GeEus1`FUadNU<)6f+*sBQItd(?^i@cRPnwf zCd4G(-xE_}8t+%djHu!Lnm8wB@iyJdVs1zKsU~%I?s!g||4Oy4hzr(L_o916TokVy zWvti5CF>3M4e>pcQ{{iUZ;DrsR8`rJ-J1KBd(D0QNTuIB<%hqt=H1ub`3s75-F@4g zJ-*>y|4QAyd4%;6ul>1(^tyZXr5uxT<`i*xPO%om6}OJ~Rm2zFSCZC_RBLHiZ)w=# z>uJ3=P3uw z%WrwzxZ0DgZeVZryNv+fkLJ}_-)sdw-p1!*^K+-^Qd|$7iB3bM>iEl~;V$0(>v#mp zu^M3>hiaq>^@6gk9cqy#u;zGXE-0HCW~YZgE1LLwyb(C9t{H5(=Gtxh@tp@e@O!Iw zIo|N3bp4*!6*RxV<8t1H@5)_=MtHf%jkvpRH`r{oUGt{dbAqiwNlrH@qi#NJwcDn< zA4sPWpjZFXd&!CfTP>`OC%NfIpWaav~tPNtb97I`Ha+&9_wDu?Z&w+ z*AcFq&%}k{K;kS%tunvtq{QDUvW#lKda&>XX5cS$9N+79n+x~6M!$m@_zRzXy1uaH z`mQ4zTMOM*!5-b9gAZ zqFU5s6|n~G4*eAnvIz9;{{oLdd9EC(fx4~jWaO3fE5mVJK)U`+{jstM91@uy89_G4 zQE8I7BlR#7sK@yzgB{ipGoE9wBmIJMn8kkUXyNDBXMQ)8!`%J@svTuhiT&U(9~6#@ zQ8vn7Ks}Mg`6!7TY8#OesXJM@i?_C;;+;D#56Y>^v)!jklzXB?*(bmtoFKz_1)IaW zwC?QCiTBM`x7QDDm<~k24@_^<9Gw6k$q)&zAD{>dn|>eX=%qs3-riQLv1K~aH9d)) zg#gkKZFStF4a#VET{^hP+H2tmbLoF--BeIS-cIn7!(fQ8XiZ}-}3rxVQ#n>A|{3t zg{h_Mba^PsP(KPCpcw=f<)#uTKfH9Pl1M*SA_z0KOd*jb!Tu}lnU0OnBq^{sxBg`P z_S$+X8`40Uq*Dik(dvt_+5&PU0zzxTk{~O{|5forN@#eU-bV}g_LEVBuhN3syaDwO z+g`(I`yU}PC@M)Zx#uvC^}6}^&XY&;6=2gr&yBTiFV1%bPc+u4PFz?=#;TN_jI+|| zHr+VWhVbSc+4Mab#91!Pay=S*oO7_$T`^yf)95bNX}|cnY?b`Lk%3L4^sVw}u&%JC z(qm)u22l6bOdx@(1m>eeIfXVY19--*@RH1{+!L=%TpYD}l~(2=9!lY&YG@bLqFU7^ zRb8D{&#RN_w5DgIiQM5{X7E8Ebr->J;}IwjR*ispI|Bs?(I$0H2&x4h}y}o|`;q8yD%+k_g z`1ZmddTrpVzwiWVu-|Rk>+dZ*`uOfUi;MOb55KfoB`!Gq{Z@M+EJ1zLN#)g>A*wGf zh9&<*%FW@<9^Kk};InI;XX}30F{c}WOz3X(`Q)dZ+K@>2~V!vC$%45o#ZKs(C z0_lZh&&x=+X}&g=;P;X2PvW8E&TBQ*P|InMZy~KgfKGpIcP zfH*+vk^0BlVgAqv)CfC$r2S>@un=h58G#cp*y{+Tg%Rjc{)qOzfSAFtB4QfHN=-wQ z@vHnr=CBwQaDIy0xvxOcC@!jl7*g|T+#u@sR1p(@psXoh;*B#h>HOmWz(01ou5{Yw zfO*gf0K`EpcUUiPIP#zY4GGj^O2G6aQQJ<+X+}u@UC+($$_b!C&Nz>WVi`N+tQgF1 z8987DurB!MN_TS;42{SOqEI*82IPQKh?jgz3)lL7-)XlG%unyGJxR2KCpTKj**V37 zI3p1)=tSaLV;qXdkc{5m^xDvOr)sB(ds`S<6*B7aN1*&`4KsB`opCXf^$nFe9CnPzRA&2@8WYL6Jt=+t_gB${(#hS%)sE zHk@A2m(UEX$pQEvb>WrkH-GKlb+h;gAWoEs(LF9g{r9BTaD6|{0Gj0$WX0J%*$Uh^ z=LZ7K^V^kB7#M@^&X*Da&Zon-jKL_a;%MouN;0r?E#;eN*UGoOCe6~)q!VW_MXQ7q z8abuLxunV|D3I4t^)Z59!$T>SHORkKR&N0XiU`vhmpFj}q`esh-i2rl5TA5)g8HCn zS)nl+=sfLp-0U{NEcQQ4EL^1w=WNx&&K1oT3x#E~`C8;P5Y$Jj?wAIXO^>$;PY>>_vbP;QS zAf8EOxmD_@6%uL)*KZL?MT*Hu1REsfW1Vmn=1k$63;Vv?b{m16kV|Rz+xts4ngd5k zkd z&GITHAju+)b3JhOZjcZ=BAN06J%~>wTAGNee1jfv&M1&{qI*^zjk4J0)5VsrQjyp2 zh$~5xshEQe@-eYV@yB_B5m>BD@E9~022RO$TpjE~Qn!g_nRP1$RJ{fp4!>#j2WpLk zoqx0HET>jg`2k8d*xEycC<2iI7X9lZ(P#TR75y9po8KHuBG0j6-R7&F$$RkmoLYPLFL8u|$Nb}F3-HE6S zdvij}CLr-lJXMgA2t4e``8ns(fQGE~A-g!!?FO+7CLz)jeW+uSrj&U=(8lD-9}`)o zZ9W8&WjEEdBlUfA)WC?W_$-+1#+h~d-LX12_=#tNYYbT8cz0)ZH7v;0wsv0X=*(J! za$~S@bz!(NX9C9%Gfn}*i~s)Sn{ObzGsbMo_yFt>m5>BQ-z+aCZKUxh7WT+>Z zQ@rpTzqfk-_7@M=kxS&6s~YB(NMh%x3WL~*vL&j6CVaX)g z**sWTsxO8!W`mt=+(O6caR~!3m$Y6s2RsBd<@X_LFQJTlAE|7FB{*{y#4z?S#7tTx zJ_X5sSjON8ScTz^S;k-+Mz|w?fKIH+0Ia#TRXt&E`b0`3^naqX(NIBU_{}+^QqwrsgMMQyGYaA22Gxr!VoAAEL|&f76hR{0(vjL|}}J zWEf?DNsKP~{w{lp2Bc#XWCh+Hn4>U4`3*usZ=s7Uqec$WZAAKUUgSXqa%`FaNg|l5 z0`wt5e1IfFs*s|I0E)2sUj!QH$84Sma%N0~|HEekM_R@ep zvMZ6)7yc1G3>RxmXkSJO5(DhZOJXJSKv>2Ep6hKie?vVKNabv-DiVFTPlzhe zo2Io1FDOVtVqXjhWH&}Cm%8w-3 zFgyKr&{|mv^BmiNf;Sx@(2!i|dL)lnn~o>kmE}al3a1o#B4X@X8cEkkrV4T8#PX(} zgH?kGlCA_xQJhN#%|Z|t*mp?6Zsn4($Hjz}Q`#xXkhgH6{~94N&Y`cX+B8ga1G@SS z{3gg5N&>lMNfI&$egHG+$141)aKFH>3YW}tQ0$>!RXfh4epT&Qf36Pvs^mvS$RijC zh5hG{6x2<;s!Y*?!(xzwR~Du?>tb@|7>A{o(hBV0DMz`W7?q{VNgYxOa%AA;RKatzw!j+e-d+^LYPLFL8$HjB%S{xtsT#QH=Y0F8S@`c z8_a*|rTI@q(L7TELtr^ zhN#ZK7>Z_U3dIQ94(G5Vv(a2s*koLDssonuu?uG#FkpmcHwS2TirYY(6XxUia2afp zn;OcvkDH3rJY46t^074Ly0-Rs&C1_jyM1@{%g@=s`#+f$clDcQ^bw8ea>k3Ld6(riv<%KQ!u@m9`z!RgL=VE)k;^sK$@=6A z2swwGSofdFVE%lv3p{Xgu3AuB_P8T|A{}ya@c>_b4G9AZ#e|LB`9#-v0!-W_-MUx> zq(Oms5(EscuR4u!>h!nmVE1RVR%6Q9-qF22VF+cMTCxv z2>Q)J|D8ve#IFW+NRBG}^lvXUJ1UjAr0N=lvU)KqA5fQuZFg|XX4~OM-^q&)3bw$T zv;bu3HLmwOyV0(@yFvKDZ&{y-8#^8r$Szm@bm{9`&3_APfA_E6*SGGkhp*l95)3`d zFOgJB04o_z<+a-*!JDZtbt(p+kh}zKMP&LUQ*6imTyQGA}XhCV$|b%&0uMg(rlO6#%xN6EXk* delta 65 zcmaDTc~g?tiIyft|$x3h!_Q0x{*e0*+VW?p>!OI9E^a{)gC S!{i^_lNnVe_wa-;vH$=<>k+^J diff --git a/__pycache__/Lv3_diagnostics.cpython-37.pyc b/__pycache__/Lv3_diagnostics.cpython-37.pyc index 726ab2d7f05253570f6501c70209b294332c9156..7652a6aab327dab22cbb1fe168133f521145bee6 100644 GIT binary patch delta 61 zcmez2_QQ?OiI=time_bins[i])&(trunc_times=time_bins[i])&(trunc_times=time_bins[i])&(trunc_times=time_bins[i])&(trunc_times= 0.99: + mean_time = np.mean(time_interval) + mean_rate = np.mean(rate_interval) + mean_error = np.sqrt(np.sum(error_interval**2))/np.size(error_interval) + sum_fracexp = sum(fracexp_interval) + + rebinned_time.append(mean_time) + rebinned_rate.append(mean_rate) + rebinned_errs.append(mean_error) + rebinned_fracexp.append(sum_fracexp) + completeness.append(len(time_interval)/(tbin/10)) + + return np.array(rebinned_time),np.array(rebinned_rate),np.array(rebinned_errs),np.array(rebinned_fracexp) + +def rebin_txt(times,rates,errors,fracexp,tbin,cmpltness): + """ + Very similar to rebin_lc, but takes in the 10s-binned light curve from running + rebin_lc with tbin=10s. This saves time! + """ + + rebinned_time = [] + rebinned_rate = [] + rebinned_errs = [] + rebinned_fracexp = [] + completeness = [] + + trunc_times = times-times[0] + + time_bins = np.arange(0,trunc_times[-1]+tbin,tbin) + print('Rebinning...') + for i in tqdm(range(len(time_bins)-1)): + time_interval = trunc_times[(trunc_times>=time_bins[i])&(trunc_times=time_bins[i])&(trunc_times=time_bins[i])&(trunc_times=time_bins[i])&(trunc_times= cmpltness: + mean_time = np.mean(time_interval) + mean_rate = np.mean(rate_interval) + mean_error = np.sqrt(np.sum(error_interval**2))/np.size(error_interval) + sum_fracexp = sum(fracexp_interval) + + rebinned_time.append(mean_time) + rebinned_rate.append(mean_rate) + rebinned_errs.append(mean_error) + rebinned_fracexp.append(sum_fracexp) + completeness.append(len(time_interval)/(tbin/10)) + + return np.array(rebinned_time),np.array(rebinned_rate),np.array(rebinned_errs),np.array(rebinned_fracexp) + +def phase_folding(t,y,T,T0,f,nbins): + """ + Calculating the folded profile + Goes from 0 to 2. + + x - array of time values + y - flux array + T - sum of all the GTIs + T0 - reference epoch in MJD + f - folding frequency + nbins - number of phase bins desired + """ + MJDREFI = 51910 + MJDREFF = 7.428703700000000E-04 + TIMEZERO = 0 + + t_MJDs = MJDREFI + MJDREFF + (TIMEZERO+t)/86400 + + tau = (t_MJDs-T0)*86400 + #phase = (f*tau + fdot/2 *tau**2 + fdotdot/6*tau**3)%1 + phase = (f*tau)%1 + + phase_bins = np.linspace(0,1,nbins+1) + summed_profile,bin_edges,binnumber = stats.binned_statistic(phase,y,statistic='mean',bins=phase_bins) + error = np.sqrt(summed_profile*100)/100 + + phase_bins_total = np.array(list(phase_bins[:-1]) + list(phase_bins+1)) + summed_profile_total = np.array(list(summed_profile)*2) + error_total = np.array(list(error)*2) #the 100 should change!!! + + return phase_bins_total, summed_profile_total, error_total + +##### Part 1 of the simulation + +eventfile = '/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/ngc300x1/ngc300x1_merge_niceroverlap_all.evt' +times = fits.open(eventfile)[1].data['TIME'] +gtis_data = fits.open(eventfile)[2].data + +gtis_conform = [] +for i in range(len(gtis_data)): + gtis_conform.append([gtis_data[i][0],gtis_data[i][1]]) #conform to the input that Stingray uses + +T = sum([ gtis_data[i]['STOP']-gtis_data[i]['START'] for i in range(len(gtis_data)) ]) #exposure time +x = times-times[0] +pb = 120e3 #120ks orbital period +longx = np.linspace(x[0],x[-1],10001) + +y = 5*np.sin(2*np.pi/pb * x) + 5 #+ np.random.normal(0,10,size=len(x)) +longy = 5*np.sin(2*np.pi/pb * longx) + 5# + np.random.normal(0,1,size=len(longx)) + +""" +omega,psd,prob3,prob4,prob5 = Lv2_dj_lsp.lsp(longx,longy) +freq = omega/(2*np.pi) + +print(psd[psd>=0.98*np.max(psd)],freq[psd>=0.98*np.max(psd)]) + +plt.figure() +plt.plot(freq,psd,'rx-') +plt.xlabel('Frequency (Hz)',fontsize=12) +plt.ylabel('Normalized Power',fontsize=12) +plt.axhline(y=prob3,lw=0.5,alpha=0.5) +plt.axhline(y=prob4,lw=0.5,alpha=0.5) +plt.axhline(y=prob5,lw=0.5,alpha=0.5) +plt.show() +""" + +nphase = 20 + +##### using foldAt +phases = foldAt(x,pb,T0=0) + +##### using phase mod 1 +phase_mod = (1/pb * x)%1 #or shift by -0.7*pb + +##### using stingray.pulse.pulsar +phase_stingray = pulse_phase(x,[1/pb])#,ph0=1-0.7) + +expocorr = Lv2_phase.phase_exposure(times[0]-times[0],times[-1]-times[0],period=pb,nbin=nphase,gtis=gtis_conform) + +################################################################################ + +##### Testing the 3 different routines for calculating phase + +phase_bins = np.linspace(0,1,nphase+1) +profile,bin_edges,binnumber = stats.binned_statistic(phases,y,statistic='mean',bins=nphase) +profile_mod,bin_edges,binnumber = stats.binned_statistic(phase_mod,y,statistic='mean',bins=nphase) +profile_sr,bin_edges,binnumber = stats.binned_statistic(phase_stingray,y,statistic='mean',bins=nphase) + +phase_to_2 = np.array(list(phase_bins[:-1]) + list(phase_bins+1)) +profile_to_2 = np.array(list(profile)*2) +profile_mod_to_2 = np.array(list(profile_mod)*2) +profile_sr_to_2 = np.array(list(profile_sr)*2) + +plt.step(phase_to_2[:-1],profile_to_2,'b-') +plt.step(phase_to_2[:-1],profile_mod_to_2,'r-') +plt.step(phase_to_2[:-1],profile_sr_to_2,'k-') +plt.xlabel('Phase',fontsize=12) +plt.ylabel('Flux',fontsize=12) +plt.legend(('foldAt','f*t mod 1','stingray'),fontsize=12,loc='best') +#plt.show() + +##### Doing phase shifts... + +offset = 0.7*nphase + +##### Shifting pulse profiles through a shifted FT (see Deepto's 7/20/2020 email) +if nphase % 2 == 0: + fft_x = np.array(list(np.arange(int(nphase/2)+1)) + list(np.arange(int(nphase/2)-1) - (int(nphase/2)-1))) +else: + fft_x = np.array(list(np.arange(int(nphase/2)+1)) + list(np.arange(int(nphase/2)) - int(nphase/2))) + +shift = np.exp(-2j*np.pi*fft_x*offset/nphase) +shifted_prof = np.real(np.fft.ifft(np.fft.fft(profile_mod)*shift)) #taking the real component of the inverse transform of the shifted Fourier transform of the original folded profile +#shifted_err_sr = np.real(np.fft.ifft(np.fft.fft(err_sr)*shift)) #taking the real component of the inverse transform of the shifted Fourier transform of the original folded profile + +shifted_prof_to_2 = np.array(list(shifted_prof)*2) + +plt.figure() +plt.step(phase_to_2[:-1],profile_mod_to_2,'r-') +plt.errorbar(phase_to_2[:-1],shifted_prof_to_2,color='c',drawstyle='steps-mid') +plt.xlabel('Phase',fontsize=12) +plt.ylabel('Counts/s',fontsize=12) + +plt.show() + +##### Part 2 of the simulation +bary_outputfolder = '/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/lightcurve/' +obsids = [str(i) for i in range(49834027,49834042)] + [str(i) for i in range(49834043,49834062)] + [str(i) for i in range(49834063,49834066)] + ['88810002'] + [str(i) for i in range(49834066,49834069)] + [str(i) for i in range(49834070,49834079)] + [str(i) for i in range(49834080,49834088)] +corr_lc_files = [bary_outputfolder + 'sw000' + obsids[i] + '_corr.lc' for i in range(len(obsids))] +corr_bg_files = [bary_outputfolder + 'sw000' + obsids[i] + '_bg_corr.lc' for i in range(len(obsids))] +bg_scale_x1 = (30/120)**2 + +""" +times,rates,errors,fracexp = Lv2_swift_lc.get_bgsub(corr_lc_files,corr_bg_files,bg_scale_x1) + +simfile = open(bary_outputfolder + 'simulate_10s.txt','w') +print('Writing into the text file...') +for i in tqdm(range(len(times))): + simfile.write(str(times[i]-times[0]) + ' ' + str(rates[i]) + ' ' + str(errors[i]) + ' ' + str(fracexp[i]) + '\n') +simfile.close() +""" + +""" +##### Calling the text file (faster than always running "rebin_lc") +txt_t,txt_rate,txt_err,txt_fracexp = np.genfromtxt(bary_outputfolder + 'simulate_10s.txt',usecols=(0,1,2,3),unpack=True) +rebinned_t,rebinned_rate,rebinned_err,rebinned_fracexp = rebin_txt(txt_t,txt_rate,txt_err,txt_fracexp,100,0) +#new_rebinned_rate = np.array([ 5*np.sin(2*np.pi/pb * rebinned_t[i]) + 5 + np.random.normal(0,5) if rebinned_rate[i] > 0 else 0 for i in range(len(rebinned_t)) ]) + +#for i in range(50): +# print(rebinned_t[i],rebinned_rate[i],new_rebinned_rate[i]) + +print(len(rebinned_t),len(rebinned_rate)) +##### CHECKING THE PERIODOGRAM - IT IS THE SAME! +omega,psd,prob3,prob4,prob5 = Lv2_dj_lsp.lsp(rebinned_t,rebinned_rate) +#omega_new,psd_new,prob3_new,prob4_new,prob5_new = Lv2_dj_lsp.lsp(rebinned_t,new_rebinned_rate) + +freq = omega/(2*np.pi) +#freq_new = omega_new/(2*np.pi) + +plt.figure() +plt.plot(freq,psd,'rx-') +#plt.yscale('log') +#plt.xscale('log') +plt.xlabel('Frequency (Hz)',fontsize=12) +plt.ylabel('Normalized Power',fontsize=12) +plt.axhline(y=prob3,lw=0.5,alpha=0.5) +plt.axhline(y=prob4,lw=0.5,alpha=0.5) +plt.axhline(y=prob5,lw=0.5,alpha=0.5) +#print(prob3,prob4,prob5) +print(freq[psd==np.max(psd)][0],psd[psd==np.max(psd)][0]) + +#plt.figure() +#plt.plot(freq_new,psd_new,'rx-') +#plt.yscale('log') +#plt.xscale('log') +#plt.xlabel('Frequency (Hz)',fontsize=12) +#plt.ylabel('Normalized Power',fontsize=12) +#plt.axhline(y=prob3_new,lw=0.5,alpha=0.5) +#plt.axhline(y=prob4_new,lw=0.5,alpha=0.5) +#plt.axhline(y=prob5_new,lw=0.5,alpha=0.5) +#print(prob3,prob4,prob5) +#print(freq_new[psd_new==np.max(psd_new)][0],psd_new[psd_new==np.max(psd_new)][0]) + +plt.show() +""" + + +##### Testing the folding... +tstart_49834027 = 546830295.758713 +tstart_49834027_MJD = fits.open(eventfile)[1].header['MJDREFI'] + fits.open(eventfile)[1].header['MJDREFF'] + tstart_49834027/86400 + +""" +phases,profile,error = phase_folding(rebinned_t+tstart_49834027,rebinned_rate,T,tstart_49834027_MJD,8.46465218853785e-06,nphase) +expocorr = Lv2_phase.phase_exposure(times[0]-times[0],times[-1]-times[0],period=1/8.46465218853785e-06,nbin=nphase,gtis=gtis_conform-times[0]) +plt.figure() +plt.errorbar(x=phases[:-1],y=profile,yerr=error,color='r',drawstyle='steps-mid') +plt.errorbar(x=phases[:-1],y=profile/np.array(list(expocorr)*2),yerr=error/np.array(list(expocorr)*2),color='b',drawstyle='steps-mid') +plt.legend(('Folded','Expo-corr'),fontsize=12) + +print(expocorr) + +phases_new,profile_new,error_new = phase_folding(rebinned_t+tstart_49834027,new_rebinned_rate,T,tstart_49834027_MJD,8.334549348081744e-06,nphase) +expocorr_new = Lv2_phase.phase_exposure(times[0]-times[0],times[-1]-times[0],period=1/8.334549348081744e-06,nbin=nphase,gtis=gtis_conform-times[0]) +plt.figure() +plt.errorbar(x=phases_new[:-1],y=profile_new,yerr=error_new,color='r',drawstyle='steps-mid') +plt.errorbar(x=phases_new[:-1],y=profile_new/np.array(list(expocorr_new)*2),yerr=error_new/np.array(list(expocorr_new)*2),color='b',drawstyle='steps-mid') +plt.legend(('Folded','Expo-corr'),fontsize=12) + +print(expocorr_new) + +plt.show() +""" + +""" +##### Doing the chi^2 exploration + +chi2 = [] +freqs = np.arange(8.3e-6,8.4e-6,0.0001e-6) +for i in tqdm(range(len(freqs))): + phases,profile,error = phase_folding(rebinned_t+tstart_49834027,new_rebinned_rate,T,tstart_49834027_MJD,freqs[i],nphase) + expocorr = Lv2_phase.phase_exposure(times[0]-times[0],times[-1]-times[0],period=1/freqs[i],nbin=nphase,gtis=gtis_conform-times[0]) + chi2.append( Lv2_phase.get_chi2(profile/np.array(list(expocorr)*2),error/np.array(list(expocorr)*2) ) ) + +plt.figure() +plt.plot(freqs,chi2,'rx-') +plt.yscale('log') +plt.xlabel('Frequency (Hz)',fontsize=12) +plt.ylabel('chi^2 [ sum( (profile-mean)^2/error^2) ]',fontsize=12) +plt.show() +""" + +""" +print('Looking at completeness...') +completeness = np.array([0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0]) +txt_t,txt_rate,txt_err,txt_fracexp = np.genfromtxt(bary_outputfolder + 'simulate_10s.txt',usecols=(0,1,2,3),unpack=True) +noise_rate = np.array([ 0.005*np.sin(2*np.pi/pb * txt_t[i]) + 0.005 + np.random.normal(0,0.005) if txt_rate[i] > 0 else 0 for i in range(len(txt_t)) ]) +noise_err = np.array([ 0 if noise_rate[i] == 0 else np.sqrt(np.abs(noise_rate[i])*10)/10 for i in range(len(noise_rate)) ]) + +for i in range(len(completeness)): + rebinned_t,rebinned_rate,rebinned_err,rebinned_fracexp = rebin_txt(txt_t,noise_rate,noise_err,txt_fracexp,100,completeness[i]) + omega_new,psd_new,prob3_new,prob4_new,prob5_new = Lv2_dj_lsp.lsp(rebinned_t,rebinned_rate) + freq_new = omega_new/(2*np.pi) + + freqs_list, psd_list = Lv2_dj_lsp.psd_error(rebinned_t,rebinned_rate,rebinned_err) + print(str(completeness[i]*100) + '%') + print(freq_new[psd_new==np.max(psd_new)][0],psd_new[psd_new==np.max(psd_new)][0]) + print(len(rebinned_t)) + print('Median frequency: ' + str(np.median(freqs_list))) + print('Error in frequency: ' + str(np.std(freqs_list))) +""" diff --git a/grb200205a_bary.dat b/grb200205a_bary.dat new file mode 100644 index 0000000000000000000000000000000000000000..f5166443ff844c1d71204fcca53ea2a7203d1452 GIT binary patch literal 806400 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 OSOf?VAn<=G@V@|3Uh0|v literal 0 HcmV?d00001 diff --git a/grb200205a_bary.events b/grb200205a_bary.events new file mode 100644 index 0000000000000000000000000000000000000000..ece8f526d01ba71e14be9d0e888e5a472c00aaaf GIT binary patch literal 120008 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 literal 0 HcmV?d00001 diff --git a/grb200205a_bary.inf b/grb200205a_bary.inf new file mode 100644 index 0000000..317a5ef --- /dev/null +++ b/grb200205a_bary.inf @@ -0,0 +1,19 @@ + Data file name without suffix = grb200205a_bary + Telescope used = NICER + Instrument used = XTI + Object being observed = GRB200205A + J2000 Right Ascension (hh:mm:ss.ssss) = 00:00:00 + J2000 Declination (dd:mm:ss.ssss) = 00:00:00 + Data observed by = NICER + Epoch of observation (MJD) = 58884.618761393 + Barycentered? (1=yes, 0=no) = 1 + Number of bins in the time series = 201600 + Width of each time series bin (sec) = 0.5 + Any breaks in the data? (1=yes, 0=no) = 0 + Type of observation (EM band) = X-ray + Field-of-view diameter (arcsec) = 180.00 + Central energy (kev) = 4.2 + Energy bandpass (kev) = 3.8 + Data analyzed by = masonng + Any additional notes: + None diff --git a/test.py b/test.py index fc65950..680601c 100644 --- a/test.py +++ b/test.py @@ -16,13 +16,23 @@ from presto import binary_psr import matplotlib.gridspec as gridspec import subprocess +from astropy.wcs import WCS,utils +#import pint.toa as toa +import Lv0_fits2dict,Lv2_dj_lsp import glob +from PyAstronomy.pyasl import foldAt import peakutils +import pathlib import Lv0_dirs,Lv1_data_bin,Lv2_phase,Lv3_detection_level from matplotlib.backends.backend_pdf import PdfPages from scipy import stats from scipy import signal from scipy.optimize import curve_fit +#from astropy.visualization import quantity_support +#from stingray.pulse.pulsar import pulse_phase,phase_exposure,fold_events +#from stingray.pulse.search import plot_profile + +#quantity_support() timestart = time.time() @@ -1591,10 +1601,1944 @@ def GaussSum(x,*p): print(Lv3_detection_level.power_for_sigma(3,10/0.0005,1,1)) """ +""" for i in range(1200250101,1200250127): #for all of the AT2018cow ObsIDs: gtis = fits.open(Lv0_dirs.NICERSOFT_DATADIR + str(i) + '_pipe/ni' + str(i) + '_nicersoft_bary.evt')[2].data print('ObsID: ' + str(i) + ' ; Start time in GTI: ' + str(gtis[0][0]) + ' ; End time in GTI: ' + str(gtis[-1][1])) +""" + +""" +r_sun = 6.96e8 #radius of sun in m +P = 88*86400 #orbital period of mercury +a = 0.387 * 1.5e11 #orbital radius in m +e = 0.206 #eccentricity of mercury orbit +M_sun = 1.989e30 #mass of sun +G = 6.674e-11 #grav. constant + +omega_sun = 2*np.pi/(25*86400) +omega_b = np.sqrt(G*M_sun/r_sun**3) + +omega_prec = 6*np.pi*r_sun**2/(P*(a*(1-e**2))**2) * (omega_sun/omega_b) +print(omega_prec) +print(omega_prec*180/np.pi*3600 * 86400 * 365 * 100) +""" + +""" +gtifolder = '/Volumes/Samsung_T5/NICER-data/xtej1739/accelsearch_GTIs/GTI' +for i in range(1,93): + gti = gtifolder+str(i)+'.gti' + gti_fits = fits.open(gti)[1].data + print(i,gti_fits[0][0]-193073992.57127872,gti_fits[0][1]-193073992.57127872) +""" + +""" +eventfile = '/Users/masonng/Documents/MIT/Research/xtej1739_burst8/2002251704_bary.evt' +gtifolder = '/Users/masonng/Documents/MIT/Research/xtej1739_burst8/accelsearch_GTIs/' +#gtistart = fits.open('/Users/masonng/Documents/MIT/Research/xtej1739_burst8/2002251704_bary.evt')[2].data[0][0] + +#for i,starttime in enumerate(np.arange(gtistart+100,gtistart+205,5)): + #subprocess.run(['mkgti.py','--gtiname',gtifolder+'GTI'+str(i+1)+'.gti',str(starttime),str(starttime+10)]) +# subprocess.run(['niextract-events',eventfile,gtifolder+'2002251704_bary_GTI'+str(i+1)+'.evt','timefile='+gtifolder+'GTI'+str(i+1)+'.gti']) + +def exp_func(x,a,b,c,d): + return a*np.exp(-b*x+c) + d #a for amplitude, b for decay constant, and c for a constant background + +times = fits.open(eventfile)[1].data['TIME'] +times_t = times-times[0] +counts = np.ones(len(times_t)) + +t_bins = np.linspace(0,np.ceil(times_t[-1]),np.ceil(times_t[-1])+1) +summed_data, bin_edges, binnumber = stats.binned_statistic(times_t,counts,statistic='sum',bins=t_bins) + +plt.plot(t_bins[:-1],summed_data,'r-') + +#popt,pcov = curve_fit(exp_func,t_bins[:-1],summed_data,p0=[350,10,50]) +#print(popt,pcov) + +plt.plot(t_bins[:-1],exp_func(t_bins[:-1],20,0.02,2,50),'b-') + +for i in range(1,22): + gtis = fits.open(gtifolder+'GTI'+str(i)+'.gti')[1].data + start = gtis[0][0]-times[0] + end = gtis[0][1]-times[0] + plt.axvline(x=start) + plt.axvline(x=end) + +plt.xlabel('Time (s)',fontsize=12) +plt.ylabel('Counts/s',fontsize=12) +plt.axvline(x=150,color='k') +plt.axvline(x=160,color='k') +""" + +""" +#plt.show() +timezero = 193073992.641447 +artifacts = [617550,618550,645580,646500,673350,674375,741020,741290,974690,975200,985830,986350,1013740,1014200,1041630,1041990, + 1489670,1490520,1529070,1529860,1589670,1590900,1595745,1596900,1612070,1612660,1617800,1619200,1656460,1658240, + 1718650,1719220,1774380,1775140,1841220,1842320,1880190,1881360,1919150,1920400,1969270,1970120,2047220,2048070, + 2052800,2053640,2080650,2081500,2152530,2153700,2181020,2181850,2253630,2255040] + +""" + +""" +eventfile = Lv0_dirs.NICER_DATADIR + 'xtej1739_burst27+/2002131540_bary.evt' +gtis = fits.open(eventfile)[2].data +times = fits.open(eventfile)[1].data['TIME'] +segment_length = 10000 + +Tobs_start = gtis[0][0] #MJD for the observation start time +Tobs_end = gtis[-1][1] #MJD for the observation end time + +segment_times = np.arange(Tobs_start,Tobs_end+segment_length,segment_length) #array of time values, starting +binned_counts, bin_edges, binnumber = stats.binned_statistic(times,np.ones(len(times)),statistic='sum',bins=segment_times) +""" + +#for i in range(len(binned_counts)): +# print(binned_counts[i],bin_edges[i]) + +""" +gtis = list(fits.open(eventfile)[2].data) +rm_artifacts = 193073992.641447008+np.array(open( str(pathlib.Path(eventfile).parent)+'/rm_artifacts.txt','r').read().split('\n')[:-1],dtype=np.float64) + +N = len(gtis) + +gtis_remove = [] +for i in range(len(gtis)): + for j in range(0,len(rm_artifacts)-1,2): + if (gtis[i][0] >= rm_artifacts[j]) and (gtis[i][1] <= rm_artifacts[j+1]): + gtis_remove.append(gtis[i]) + # break + +new_gtis = [] +for i in range(len(gtis)): + if gtis[i] not in np.array(gtis_remove): + new_gtis.append(gtis[i]) +print(len(new_gtis)) +""" + +#eventfile = Lv0_dirs.NICER_DATADIR + 'xtej1739_burst27+/2002131540.evt' +#t = toa.get_TOAs(eventfile, usepickle=True) + +""" +eventfile = '/Volumes/Samsung_T5/NICER-data/1034100102/xti/event_cl/ni1034100102_0mpu7_cl_bary.evt' +import pint.event_toas as event_toas +t = event_toas.load_event_TOAs(eventfile,'nicer') +print(t[0],t[1]) +tt = t.table +tt.show_in_browser() +""" + +""" +txtfile = '/Volumes/Samsung_T5/NICERsoft_outputs/merged_events/merged000017/S500_W5_T30_E30-200.txt' +f,ps = np.genfromtxt(txtfile,usecols=(0,1),unpack=True) +print(f) +""" + +""" +for i in range(101,128): + print('1034100'+str(i)) + +merged_files = [Lv0_dirs.NICERSOFT_DATADIR+'merged_events/merged0000'+str(i)+'/merged0000'+str(i)+'_nicersoft_bary.evt' for i in range(15,19)] +for i in range(len(merged_files)): + gtis = fits.open(merged_files[i])[2].data + print(len(gtis)) + differences = np.array( [ (gtis[j][1]-gtis[j][0]) for j in range(len(gtis)) ]) + print(sum(differences)) +""" + +""" +filenames = sorted(glob.glob('/Volumes/Samsung_T5/NICER-data/xtej1812/accelsearch_64s/*.evt')) +for i in range(len(filenames)): + print(filenames[i],len(fits.open(filenames[i])[1].data)) +""" + +""" +tbin_size = 16 + +eventfile = Lv0_dirs.NICER_DATADIR + 'xtej1701/2003261259_filt_bary.evt' +times = fits.open(eventfile)[1].data['TIME'] +trunc = times - times[0] +t_bins = np.linspace(0,np.ceil(trunc[-1]),np.ceil(trunc[-1])*1/tbin_size+1) +summed_data, bin_edges, binnumber = stats.binned_statistic(trunc,np.ones(len(times)),statistic='sum',bins=t_bins) + +spectra_GTIs = np.array([1,2,3,4,5,6,7,8,9,10,11,12,20]) #corresponding GTI no. that had spectra extracted +gti_start,gti_stop = np.loadtxt('/Volumes/Samsung_T5/NICER-data/xtej1701/bunchedgtis.txt',usecols=(0,1),unpack=True) + +gti_used_start = np.array([gti_start[i-1] for i in spectra_GTIs]) - times[0] +gti_used_stop = np.array([gti_stop[i-1] for i in spectra_GTIs]) - times[0] +for i in range(len(gti_used_start)): + print(gti_used_stop[i]-gti_used_start[i]) +gti_used_centroid = gti_used_start + (gti_used_stop-gti_used_start)/2 +""" + +""" +fig,(ax1,ax2,ax3) = plt.subplots(3,1,sharex=True) + +time_bins = t_bins[:-1] +count_bins = summed_data/tbin_size +ax1.plot(time_bins[count_bins>0],count_bins[count_bins>0],'rx') #plot the light curve +for i in range(len(gti_used_start)): + ax1.axvline(x=gti_used_start[i],alpha=0.5,lw=0.5) + ax1.axvline(x=gti_used_stop[i],alpha=0.5,lw=0.5) + +ax1.set_ylabel('Counts/s',fontsize=12) + +#nH fixed +gamma_fixed = np.array([1.6687,1.5988,1.5699,1.7324,1.7758,1.8787,1.8873,1.8097,1.8023,2.1124,2.0908,2.2772,2.1631]) +gamma_fixed_err = np.array([0.011,0.010,0.011,0.011,0.011,0.014,0.012,0.024,0.023,0.041,0.015,0.045,0.022]) +norm_fixed = np.array([0.168,0.168,0.152,0.164,0.161,0.159,0.148,0.153,0.143,0.091,0.102,0.092,0.083]) +norm_fixed_err = np.array([0.0025,0.0023,0.0021,0.0024,0.0024,0.0028,0.0023,0.0045,0.0040,0.0042,0.0019,0.0046,0.0021]) + +ax2.errorbar(x=gti_used_centroid,y=gamma_fixed,yerr=gamma_fixed_err) +ax2.set_ylabel('Gamma',fontsize=12) + +ax3.errorbar(x=gti_used_centroid,y=norm_fixed,yerr=norm_fixed_err) +ax3.set_ylabel('norm',fontsize=12) +ax3.set_xlabel('Time from first event (s)',fontsize=12) + +plt.show() +""" + +""" +fig,(ax1,ax2,ax3,ax4) = plt.subplots(4,1,sharex=True) + +time_bins = t_bins[:-1] +count_bins = summed_data/tbin_size +ax1.plot(time_bins[count_bins>0],count_bins[count_bins>0],'rx') #plot the light curve +for i in range(len(gti_used_start)): + ax1.axvline(x=gti_used_start[i],alpha=0.5,lw=0.5) + ax1.axvline(x=gti_used_stop[i],alpha=0.5,lw=0.5) + +ax1.set_ylabel('Counts/s',fontsize=12) + +#nH not fixed +nH_not_fixed = np.array([4.501,4.574,4.311,4.735,4.700,4.695,4.680,4.981,4.940,5.534,4.508,4.777,4.797]) +nH_not_fixed_err = np.array([0.048,0.044,0.044,0.048,0.048,0.062,0.051,0.122,0.111,0.215,0.063,0.199,0.098]) +gamma_not_fixed = np.array([1.633,1.586,1.478,1.769,1.803,1.904,1.908,1.933,1.912,2.481,2.053,2.343,2.230]) +gamma_not_fixed_err = np.array([0.018,0.016,0.016,0.018,0.019,0.025,0.021,0.048,0.044,0.094,0.027,0.094,0.043]) +norm_not_fixed = np.array([0.158,0.164,0.130,0.174,0.168,0.166,0.153,0.187,0.170,0.159,0.096,0.102,0.092]) +norm_not_fixed_err = np.array([0.004,0.004,0.003,0.005,0.005,0.006,0.005,0.013,0.011,0.021,0.004,0.013,0.006]) + +ax2.errorbar(x=gti_used_centroid,y=nH_not_fixed,yerr=nH_not_fixed_err) +ax2.set_ylabel('nH',fontsize=12) + +ax3.errorbar(x=gti_used_centroid,y=gamma_not_fixed,yerr=gamma_not_fixed_err) +ax3.set_ylabel('Gamma',fontsize=12) + +ax4.errorbar(x=gti_used_centroid,y=norm_not_fixed,yerr=norm_not_fixed_err) +ax4.set_ylabel('norm',fontsize=12) + +ax4.set_xlabel('Time from first event (s)',fontsize=12) + +plt.show() +""" + +""" +tbin_size = 16 +eventfile = Lv0_dirs.NICER_DATADIR + 'xtej1739_mostrec/2002131540_filt_bary.evt' +times = fits.open(eventfile)[1].data['TIME'] +trunc = times - times[0] +t_bins = np.linspace(0,np.ceil(trunc[-1]),np.ceil(trunc[-1])*1/tbin_size+1) +summed_data, bin_edges, binnumber = stats.binned_statistic(trunc,np.ones(len(times)),statistic='sum',bins=t_bins) + +spectra_GTIs = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,36,37,38,39, + 46,60,61,62,63,64,65,66,67,77,78,83,84,85,86,91,92,93,94,97,98, + 103,106,107,108,110,117,120,121,122,123,125,126,127,135,136, + 139,146,150,152,155,156,157,158,161,162,167,168,169,170,171, + 172,179,188,197,198,199,200,201,203,204,207,208,213,214,238, + 239,240,241,242,244]) #corresponding GTI no. that had spectra extracted +gti_start,gti_stop = np.loadtxt('/Volumes/Samsung_T5/NICER-data/xtej1739_mostrec/bunchedgtis.txt',usecols=(0,1),unpack=True) + +gti_used_start = np.array([gti_start[i-1] for i in spectra_GTIs]) - times[0] +gti_used_stop = np.array([gti_stop[i-1] for i in spectra_GTIs]) - times[0] +#for i in range(len(gti_used_start)): +# print(gti_used_stop[i]-gti_used_start[i]) +gti_used_centroid = gti_used_start + (gti_used_stop-gti_used_start)/2 + +contents = open('/Volumes/Samsung_T5/NICER-data/xtej1739_mostrec/accelsearch_GTIs/tbabs-powerlaw.txt','r').read().split('\n') +phoindex = [] +phoindex_err = [] +norm = [] +norm_err = [] + +for i in range(len(contents)): #for each line + if "PhoIndex" in contents[i]: + line = [x for x in contents[i].split(' ') if x] + phoindex.append(float(line[4])) + phoindex_err.append(float(line[6])) + elif "norm" in contents[i]: + line = [x for x in contents[i].split(' ') if x] + norm.append(float(line[4])) + norm_err.append(float(line[6])) + +fig,(ax1,ax2,ax3) = plt.subplots(3,1,sharex=True) + +time_bins = t_bins[:-1] +count_bins = summed_data/tbin_size +ax1.plot(time_bins[count_bins>0],count_bins[count_bins>0],'rx') #plot the light curve +for i in range(len(gti_used_start)): + ax1.axvline(x=gti_used_start[i],alpha=0.5,lw=0.5) + ax1.axvline(x=gti_used_stop[i],alpha=0.5,lw=0.5) + +ax1.set_ylabel('Counts/s',fontsize=12) + +ax2.errorbar(x=gti_used_centroid,y=phoindex,yerr=phoindex_err,fmt='x-') +ax2.set_ylabel('Gamma',fontsize=12) + +ax3.errorbar(x=gti_used_centroid,y=norm,yerr=norm_err,fmt='x-') +ax3.set_ylabel('norm',fontsize=12) +ax3.set_xlabel('Time from first event (s)',fontsize=12) + +plt.show() +""" + +""" +counts = 0 +gtis_no = 0 +for i in range(2050280101,2050280125): + fitsfile = Lv0_dirs.NICERSOFT_DATADIR + str(i)+'_pipe/ni'+str(i)+'_nicersoft_Bary.evt' + counts += len(fits.open(fitsfile)[1].data['TIME']) + gtis_no += len(fits.open(fitsfile)[2].data['START']) + +print(counts) +print(gtis_no) +""" + +""" +evtfiles = sorted(glob.glob(Lv0_dirs.NICERSOFT_DATADIR + 'merged_events/merged000019/accelsearch_500s/merged000019_nicersoft_bary_GTI8**_500s_E200-1200.evt')) +for i in range(len(evtfiles)): + times = fits.open(evtfiles[i])[1].data['TIME'] + trunc = times-times[0] + t_bins = np.linspace(0,np.ceil(trunc[-1]),np.ceil(trunc[-1])*1/1+1) + summed_data, bin_edges, binnumber = stats.binned_statistic(trunc,np.ones(len(times)),statistic='sum',bins=t_bins) + + plt.plot(t_bins[:-1],summed_data,'rx-') + plt.show() +""" + +""" +ngc300x1_files = sorted(glob.glob('/Volumes/Samsung_T5/NGC300_ULX_Swift/ngc300ulx-1/xrt/event/*pc*po*cl*evt')) +exp = 0 +for i in range(len(ngc300x1_files)): + exptime = fits.open(ngc300x1_files[i])[1].header['EXPOSURE'] + exp += exptime +print(exp) +""" + +""" +import Lv2_ps_method +eventfile = '/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/ngc300x1/ngc300x1_merge.evt' +times = fits.open(eventfile)[1].data['TIME'] +truncated_times = (times-times[0])/3600 +tbins = np.arange(0,np.ceil(truncated_times[-1])) + +counts,bin_edges,binnumber=stats.binned_statistic(truncated_times,np.ones(len(truncated_times)),statistic='sum',bins=tbins) + +nout = 1e4 +f = np.linspace(0.01,1,nout) +import scipy.signal as signal +pgram = signal.lombscargle(times,np.ones(len(times)),f,normalize=True) +plt.plot(f,pgram,'r-') + +#f,ps = Lv2_ps_method.manual(tbins[:-1],counts,[False],[False],True,[False,0,0]) +#plt.plot(f,ps,'r-') + +#plt.plot(tbins[:-1],counts,'rx') +#plt.xlabel('Time (h)',fontsize=12) +#plt.ylabel('Counts/hr', fontsize=12) +plt.show() +""" + +""" +t = np.linspace(0,100,10001) +y = 0.5*np.sin(3*t) + np.random.normal(0,0.01,10001) +f = np.linspace(0.01,5,10001) + +indices = np.random.randint(0,10001,100) +filt_t = t#[indices] +filt_y = y#[indices] + +#filt_t = t[::100] +#filt_y = y[::100] + +ffilt_t = [] +ffilt_y = [] + +bound1 = 10 +bound2 = 20 +bound3 = 40 +bound4 = 50 +bound5 = 70 +bound6 = 90 + +for i in range(len(filt_t)): + if (filt_t[i] >= bound1 and filt_t[i] <= bound2) or (filt_t[i] >= bound3 and filt_t[i] <= bound4) or (filt_t[i] >= bound5 and filt_t[i] <= bound6): + ffilt_t.append(filt_t[i]) + ffilt_y.append(filt_y[i]) + +#ffilt_t = filt_t +#ffilt_y = filt_y + +phase_bins = np.linspace(0,2,20*2+1) + +normal_pgram = signal.lombscargle(t,y,f,normalize=True) +pgram = signal.lombscargle(ffilt_t,ffilt_y,f,normalize=True) + +### +normal_phases = foldAt(t,2*np.pi/3,T0=0) +index_sort = np.argsort(normal_phases) +normal_phases = list(normal_phases[index_sort]) + list(normal_phases[index_sort]+1) +normal_fluxes = list(y[index_sort]) + list(y[index_sort]) + +normal_profile, bin_edges, binnumber = stats.binned_statistic(normal_phases,normal_fluxes,statistic='mean',bins=phase_bins) +### + +### +phases = foldAt(np.array(ffilt_t),2*np.pi/3,T0=0) +index_sort = np.argsort(phases) +phases = list(phases[index_sort]) + list(phases[index_sort]+1) +fluxes = list(np.array(ffilt_y)[index_sort]) + list(np.array(ffilt_y)[index_sort]) + +profile, bin_edges, binnumber = stats.binned_statistic(phases,fluxes,statistic='mean',bins=phase_bins) +### + +print(normal_profile) +print(profile) + +### +#sr_ph,sr_profile,sr_profile_err = fold_events(y,3/(2*np.pi),nbin=20) +### + +plt.figure() +plt.plot(t,y,'bx') +plt.plot(ffilt_t,ffilt_y,'rx') +plt.figure() +plt.plot(f,pgram,'r-') +plt.plot(f,normal_pgram,'b-') +plt.legend(('Altered','Original'),loc='best') +plt.figure() +plt.step(phase_bins[:-1],normal_profile,'b-') +plt.step(phase_bins[:-1],profile,'r-') +#plt.step(sr_ph,sr_profile/1000-0.5,'k-') +plt.legend(('No gaps','Gaps','Stingray (no gaps)'),loc='best') +plt.show() +""" +""" +eventfile = '/Volumes/Samsung_T5/NICERsoft_outputs/0034070102_pipe/ni0034070102_nicersoft_bary.evt' +times = fits.open(eventfile)[1].data['TIME'] +gtis = Lv0_fits2dict.fits2dict(eventfile,2,['START','STOP']) +T = sum([ (gtis['STOP'][i]-gtis['START'][i]) for i in range(len(gtis['START'])) ]) +trunc_t = times - times[0] + +sr_ph,sr_profile,sr_profile_err = fold_events(trunc_t,0.2081,nbin=20,expocorr=True) +plt.step(sr_ph,sr_profile,'k-') +_ = plot_profile(sr_ph,sr_profile*T/(trunc_t[-1])) +plt.show() +""" + +""" +nin = 1000 +nout = 100000 +x = np.linspace(0.01,10*np.pi,nin) +y = 2*np.sin(1*x) +f = np.linspace(0.01,10,nout) +pgram = signal.lombscargle(x,y,f,normalize=True) +plt.figure() +plt.plot(x,y,'bx-') +plt.figure() +plt.plot(f,pgram,'r-') +plt.show() +""" + +""" +basefolder = '/Volumes/Samsung_T5/n300_ulx_2020/' +obsids = ['1034200' + str(i) for i in range(101,200)] + ['1034200' + str(i) for i in range(201,241)] + ['2034200' + str(i) for i in range(201,206)] +print(len(obsids)) +""" + +""" +ngc300x1 = fits.open('/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/ngc300x1/ngc300x1_merge.evt')[1].data['PI'] +bins = np.array([20,100,200,300,400,500,600,700,800,900,1000]) +plt.hist(ngc300x1*10/1000,bins*10/1000,log=True) +plt.xlabel('Energy (keV)',fontsize=12) +plt.ylabel('Number of events',fontsize=12) +plt.show() +""" + +""" +eventlist = open('/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/ngc300x1/eventfiles.list','r').read().split('\n')[:-1] +E_boundary = 2.0 #energy boundary in keV + +mjds = [] +color = [] +color_err = [] + +for i in tqdm(range(len(eventlist))): + eventheader = fits.open(eventlist[i])[1].header + mjd = eventheader['MJDREFI'] + eventheader['MJDREFF'] + (eventheader['TSTART']+eventheader['TSTOP'])/(2*86400) + + pis = fits.open(eventlist[i])[1].data['PI'] + if len(pis) != 0: + soft = len(pis[pis*10/1000=E_boundary]) + soft_err = np.sqrt(soft) + hard_err = np.sqrt(hard) + if soft != 0: + color.append(hard/soft) + error = np.sqrt( (hard_err/soft)**2 + (hard*soft_err/soft**2)**2 ) + color_err.append(error) + mjds.append(mjd) + +mjds = np.array(mjds) +color = np.array(color) +color_err = np.array(color_err) +print(mjds[0],mjds[-1]) + +plt.figure() +plt.errorbar(x=mjds,y=color,yerr=color_err,fmt='rx-') +plt.xlabel('Time (MJD)',fontsize=12) +plt.ylabel('Color (H/S) - (2.0-10 keV)/(0.2-2.0 keV)',fontsize=12) +plt.show() +""" + +""" +plt.figure() +circle1 = plt.Circle((0.5,0.5),radius=0.2,color='r',lw=0.5,label='NICER FOV') +plt.gcf().gca().add_artist(circle1) +plt.show() +""" + +""" +energy = np.linspace(100,12000,100001) +N = 8.7 +fano = 0.114 +w = 3.71 +fwhm = 2.35*w*(N**2+fano*energy/w)**(1/2) +plt.plot(energy,fwhm,'r-') +plt.show() +""" + +""" +checkfile = '/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/ngc300x1/ngc300x1_merge_niceroverlap2_spec2.evt' +times = fits.open(checkfile)[1].data['TIME'] +gtis = fits.open(checkfile)[2].data +startt = gtis['START'] +stopt = gtis['STOP'] +checkdict = {} + +for i in range(len(times)): + if times[i] == times[i-1]: + print(times[i]) + checkdict[times[i]] = [] + for j in range(len(startt)): + if (times[i]>=startt[j]) and (times[i]<=stopt[j]): + checkdict[times[i]].append(startt[j]) + +dictkeys = list(checkdict.keys()) +print(len(dictkeys)) + +#for i in range(len(dictkeys)): +# if len(checkdict[dictkeys[i]]) == 0: +# print(dictkeys[i]) +""" + +""" +import numpy.ma as ma +from reproject import reproject_interp + +testimage = '/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/products/sw00049834027xpc_sk.img' +expimage = '/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/products/sw00049834027xpc_ex.img' +testimage2 = '/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/products/sw00049834028xpc_sk.img' + +obsid = str(pathlib.Path(testimage).name)[:13] +obsid2 = str(pathlib.Path(testimage2).name)[:13] + +fitsfile = fits.open(testimage)[0] +expfile = fits.open(expimage)[0] +fitsfile2 = fits.open(testimage2)[0] + +wcs = WCS(fitsfile.header) +wcs2 = WCS(fitsfile2.header) + +plt.figure() +plt.subplot(projection=wcs) +a = plt.imshow(fitsfile.data,vmin=0,vmax=np.nanmax(fitsfile.data),cmap='gist_heat') +plt.colorbar() + +plt.figure() +plt.subplot(projection=wcs) +b = plt.imshow(fitsfile.data/expfile.data,vmin=0,vmax=np.nanmax(fitsfile.data/expfile.data),cmap='gist_heat') +plt.colorbar() + +print(np.max(fitsfile.data/expfile.data)) +""" + +""" +plt.figure() +plt.subplot(projection=wcs) +b = plt.imshow(fitsfile2.data,vmin=0,vmax=np.max(fitsfile2.data),cmap='gist_heat') + + +getarray = np.array(a.get_array()) +getarray2 = np.array(b.get_array()) + +plt.figure() +plt.imshow(getarray+getarray2,vmin=0,vmax=np.max(getarray+getarray2),cmap='gist_heat') + +plt.figure() +plt.subplot(projection=wcs) +array,footprint = reproject_interp(fitsfile2,fitsfile.header) +print(np.nanmax(array)) +plt.imshow(fitsfile.data+array,vmin=0,cmap='gist_heat') +""" + +#plt.show() + + +""" +input_E = np.array([0.5,0.6,0.7,0.8,0.9] + list(np.arange(1.0,12.5,0.5))) +pi_ev = input_E * 100 +fwhm = [] +fwhm_err = [] + +for i in range(len(pi_ev)): + + def gauss(x,a,sig,constant): + return a*np.exp( -(x-input_E[i])**2/(2*sig**2) ) + constant + + #testspec = '/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/find_E_res/gauss_' + str(int(pi_ev[i])).zfill(4) + '.txt' + testspec = '/Volumes/Samsung_T5/NICERsoft_outputs/0034070101_pipe/gauss_' + str(int(pi_ev[i])).zfill(5) + '.txt' + print(testspec) + E,E_err,flux,flux_err,model = np.genfromtxt(testspec,usecols=(0,1,2,3,4),skip_header=3,skip_footer=1,unpack=True) + + pguess = np.array([100,0.05,0.01]) + popt,pcov = curve_fit(gauss,E,model,p0=pguess) + + print('Gaussian width is ' + str(round(popt[1]*1000,2)) + ' eV; FWHM is ' + str(round(popt[1]*1000*2.355,2)) + ' +- ' + str(round(np.sqrt(np.diag(pcov)[1])*1000*2.355,2)) + ' eV') + fwhm.append(popt[1]*1000*2.355) + fwhm_err.append(np.sqrt(np.diag(pcov)[1])*1000*2.355) + #plt.plot(E,model,'b-') + #plt.plot(E,gauss(E,popt[0],popt[1],popt[2]),'r-') + #plt.show() + +timeend = time.time() + + +def sqrtfunc(x,a,b,c): + return a*(x+b)**c + +#def parabola(x,a,b,c): +# return a*(x-) + +popt,pcov = curve_fit(sqrtfunc,input_E,fwhm,sigma=fwhm_err,p0=[10,3.3,0.5]) +print(popt) +print(np.sqrt(np.diag(pcov))) +#for i in range(len(input_E)): +# print(input_E[i],sqrtfunc(input_E,popt[0],popt[1],popt[2],popt[3])[i]/3) + +N = 8.7 +fano = 0.114 +w = 3.71 + +nicer_spie = 2.35*w*(N**2 + input_E*1000*fano/w)**(1/2) + +plt.plot(input_E,fwhm,'rx-') +plt.plot(input_E,sqrtfunc(input_E,popt[0],popt[1],popt[2]),'b-') +plt.plot(input_E,nicer_spie,'kx-') +plt.annotate(str(round(popt[0],2))+'(E+'+str(round(popt[1],2))+')^'+str(round(popt[2],2)),(2,160)) +plt.xlabel('Energy, E (keV)',fontsize=12) +plt.ylabel('FWHM (eV)',fontsize=12) +plt.legend(('Measured','curve_fit','NICER SPIE'),fontsize=12) +plt.show() +""" + +""" +MJDs_nicer = np.array([58239,58244,58249,58254,58259,58264,58269,58274,58309,58314,58324,58329,58334,58339,58389,58449,58454,58484,58489,58504,58509]) +flux_nicer = np.array([3.93e-12,4.79e-12,3.28e-12,3.01e-12,3.00e-12,3.05e-12,3.17e-12,2.80e-12,2.36e-12,2.70e-12,2.05e-12,1.73e-12,1.95e-12,2.48e-12,1.36e-12,1.17e-12,2.21e-12,2.85e-12,1.65e-12,1.57e-12,9.21e-13]) + +plt.semilogy(MJDs_nicer,flux_nicer,'rx-') +#plt.axhline(y=1.36e-13,color='k',xmax=0.18) +#plt.axhline(y=1.55e-13,color='k',xmin=0.2) + +#plt.axhline(y=1.83e-13,color='b',xmax=0.18) +#plt.axhline(y=1.35e-13,color='b',xmin=0.2) + +#plt.axhline(y=1.37e-12,color='m',xmax=0.18) +#plt.axhline(y=3.41e-13,color='m',xmin=0.2) + +#plt.legend(('NICER flux','NGC300 X-1','NGC300 X-1','NGC300 bg','NGC300 bg','NGC300 ULX-1','NGC300 ULX-1'),loc='best') + +plt.axhline(y=1.42e-13,color='k') +plt.axhline(y=1.59e-13,color='b') +plt.axhline(y=8.40e-13,color='m') +plt.legend(('NICER flux','NGC300 X-1','NGC300 bg','NGC300 ULX-1'),loc='best') + +plt.xlabel('Time (MJD)',fontsize=12) +plt.ylabel('Flux (ergs/s/cm^2)',fontsize=12) +plt.show() +""" + +""" +mjds = ['58239','58244','58249','58254','58259','58264','58269','58274','58279','58284','58289','58294','58309','58314','58324','58329','58334','58339','58344','58349','58384','58389','58394','58399','58409','58449','58454','58459','58464','58469','58474','58479','58484','58489','58494','58499','58504','58509','58604'] +textfile = '/Volumes/Samsung_T5/n300_ulx_2020/spectra_05d/fparkey_jsgrp_05d.go' +writing = open(textfile,'w') +for i in range(len(mjds)): + writing.write('fparkey' + ' grp_' + mjds[i] + '_05d_bg_cl50.pha ' + 'jsgrp_' + mjds[i] + '_05d_cl_cl50.pha ' + 'BACKFILE' + '\n') +writing.close() +""" + +""" +mjds = ['58239','58244','58249','58254','58259','58264','58269','58274','58279','58284','58289','58294','58309','58314','58324','58329','58334','58339','58344','58349','58384','58389','58394','58399','58409','58449','58454','58459','58464','58469','58474','58479','58484','58489','58494','58499','58504','58509','58604'] +cl_bg_file = '/Volumes/Samsung_T5/n300_ulx_2020/spectra_05d/getspec_cl_bg.xcm' +basefolder = '/Volumes/Samsung_T5/n300_ulx_2020/spectra_05d/' +writing = open(cl_bg_file,'w') +writing.write('data ') +base_string = '' +for i in range(len(mjds)): + base_string += str(i+1) + ':' + str(i+1) + ' ' + basefolder + 'jsgrp_' + mjds[i] + '_05d_cl_cl50.pha ' +writing.write(base_string + '\n') + +#for i in range(len(mjds)): +# writing.write('backgrnd ' + str(i+1) + ' grp_' + mjds[i] + '_05d_bg_cl50.pha' + '\n') + +writing.write('setplot energy' + '\n') +#writing.write('setplot background on' + '\n') +writing.write('ignore **:0.0-0.285,12.01-**') +writing.close() +""" + +""" +def sinfunc(t,a,b,c,d): + return a*np.sin(d*2*np.pi*t+b) + c + +eventfile = '/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/ngc300x1/lightcurve/ngc300x1_100s.lc' +fitsfile = fits.open(eventfile)[1].data + +times = fitsfile['TIME'][:1000] +rate = fitsfile['RATE'][:1000] + +popt,pcov = curve_fit(sinfunc,times,rate,p0=np.array([0.05,0.1,0.05,8.46e-6])) +print(popt) +print(np.sqrt(np.diag(pcov))) + +plt.plot(times,rate,'rx-') +plt.plot(times,sinfunc(times,popt[0],popt[1],popt[2],popt[3]),'b-') +plt.xlabel('Time (s)',fontsize=12) +plt.ylabel('Counts/s',fontsize=12) +plt.show() +""" + + +""" +import Lv2_ps_method + +cenx3 = fits.open('/Volumes/Samsung_T5/NICERsoft_outputs/0034070101_pipe/trylc/haha.lc')[1].data +times = cenx3['TIME'] +rates = cenx3['RATE'] +errors = cenx3['ERROR'] +fracexp = cenx3['FRACEXP'] + +plt.figure() +T = times[fracexp==1][-1] - times[fracexp==1][0] +dt = T/len(times[fracexp==1]) +freq = 1/dt + +dt = 0.5 +freq = 2 +f,pxx = signal.periodogram(rates[fracexp==1],fs=freq) +print(T,dt,freq) +#pdgm_f,pdgm_ps = Lv2_ps_method.pdgm(times,rates,[False,0,10],[False,2],True,[False,5]) + +#plt.plot(pdgm_f,pdgm_ps,'b-') +plt.plot(f,pxx,'b-') + +#plt.figure() +#plt.errorbar(x=times[fracexp==1],y=rates[fracexp==1],yerr=errors[fracexp==1],fmt='bx-') +plt.show() +""" + +""" +#eventfile = '/Volumes/Samsung_T5/NICERsoft_outputs/0034070101_pipe/ni0034070101_nicersoft_bary.evt' +eventfile = '/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/ngc300x1/ngc300x1_merge_niceroverlap_all.evt' +#eventfile = '/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/ngc300x1/ngc300x1_merge.evt' + +times = fits.open(eventfile)[1].data['TIME'] +gtis_data = fits.open(eventfile)[2].data +T = sum([ gtis_data[i]['STOP']-gtis_data[i]['START'] for i in range(len(gtis_data)) ]) +#T0 = 56658 + 0.000777592592592593 + (fits.open(eventfile)[1].header['TSTART'] + (-1))/86400 +T0 = 51910 + 7.428703700000000E-04 + fits.open(eventfile)[1].header['TSTART']/86400 +#T0 = 58244.6660 + +#plt.figure() +#plt.title('NGC300x1_merge_niceroverlap_all.evt') +#plt.xlabel('Phase',fontsize=12) +#plt.ylabel('Counts/s',fontsize=12) + +#phase,profile,profile_error = Lv2_phase.pulse_folding(times,T,T0,8.466777057846186e-06,0,0,20) +#phase,profile,profile_error = Lv2_phase.pulse_folding(times,T,T0,8.464749477590145e-06,0,0,20) +#phase,profile,profile_error = Lv2_phase.pulse_folding(times,T,T0,8.47122e-6,0,0,20) +### 8.461949E-6 is from chi^2 ; 8.46185E-6 is from Z^2, 8.465941706160968E-6 is from FR/RSS + +#plt.step(phase[:-1],profile,'r-') +#plt.errorbar(x=phase[:-1],y=profile,yerr=profile_error,color='r',drawstyle='steps-mid') +gtis_conform = [] +for i in range(len(gtis_data)): + gtis_conform.append([gtis_data[i][0],gtis_data[i][1]]) +""" + +""" +expos = phase_exposure(times[0]-times[0],times[-1]-times[0],1/8.47122e-6,nbin=20,gtis=gtis_conform-times[0]) +print(expos) +total_expos = np.array(list(expos) + list(expos)) +#plt.figure() +plt.errorbar(x=phase[:-1],y=profile/total_expos,yerr=profile_error/total_expos,color='b',drawstyle='steps-mid') +plt.title('NGC300x1_merge_niceroverlap_all.evt, exposure-corrected') +plt.xlabel('Phase',fontsize=12) +plt.ylabel('Counts/s',fontsize=12) +plt.legend(('Folded profile','Exposure-corrected profile'),loc='best',fontsize=12) + +#print(times[0],times[-1]) +#t0 = (times[0]+times[-1])/2+0.175*1/8.47122e-06 +#print(t0) +t0 = times[0] + +phase_sr,prof_sr,err_sr = fold_events(times,[8.47122e-06],gtis=np.array(gtis_conform),ref_time=t0,nbin=20) +phase_sr_expo,prof_sr_expo,err_sr_expo = fold_events(times,[8.47122e-6],gtis=np.array(gtis_conform),ref_time=t0,expocorr=True,nbin=20) + +print(prof_sr/prof_sr_expo) + +total_phase_sr = list(phase_sr) + list(phase_sr+1) +total_prof_sr = list(prof_sr)*2 +total_err_sr = list(err_sr)*2 + +total_phase_sr_expo = list(phase_sr_expo) + list(phase_sr_expo+1) +total_prof_sr_expo = list(prof_sr_expo)*2 +total_err_sr_expo = list(err_sr_expo)*2 + +plt.figure() +plt.errorbar(x=total_phase_sr,y=total_prof_sr/T,yerr=total_err_sr/T,color='r',drawstyle='steps-mid') +plt.errorbar(x=total_phase_sr_expo,y=total_prof_sr_expo/T,yerr=total_err_sr_expo/T,color='b',drawstyle='steps-mid') +plt.legend(('Folded profile','Exposure-corrected'),loc='best',fontsize=12) +plt.xlabel('Phase',fontsize=12) +plt.ylabel('Counts/s',fontsize=12) + +#print(prof_sr) +#print(sum(prof_sr)) +#print(prof_sr_expo) +#print(sum(prof_sr_expo)) + +#print(sum(profile*T)) +#print(sum(profile/total_expos*T)) + +plt.show() +""" + +""" +chi2 = [] +freqs = np.arange(8.0e-6,9.0e-6,0.0001e-6) +for i in tqdm(range(len(freqs))): + phase_sr_expo,prof_sr_expo,err_sr_expo = fold_events(times,[freqs[i]],gtis=np.array(gtis_conform),ref_time=times[0],expocorr=True) + chi2.append( Lv2_phase.get_chi2(prof_sr_expo,err_sr_expo) ) + +plt.figure() +plt.plot(freqs,chi2,'rx-') +plt.xlabel('Frequency (Hz)',fontsize=12) +plt.ylabel('chi^2 [ sum( (profile-mean)^2/error^2) ]',fontsize=12) +plt.show() +""" + +""" +medians = np.array([8.335751931919311,8.33584176174108,8.337165146653654,8.337165146653544, + 8.337652596774758,8.337623326928423,8.337600802469019,8.338121728007296, + 8.338676789004637,8.338070034352355,8.338064677098994]) + +median_err = np.array([0.015450388314367997,0.014905023834124513,0.016690004956593195,0.011717682240614905, + 0.01499435360625864,0.011451324497186582,0.014450108614211365,0.01536640919810147, + 0.01590570701944077,0.01510912946652743,0.017427593377916324]) + +pdgm = np.array([8.335234336108602,8.335234336108602,8.337495697570686,8.337230902833188, + 8.337931466792437,8.3384201347159,8.337091556933076,8.337865199746701, + 8.338395922865838,8.337507666407173,8.338676789004637]) + +expected = (1/120e3)/1e-6 + +stddev = np.abs(medians-pdgm)/median_err +stddev_exp = np.abs(medians-expected)/median_err + +print(stddev) +print(np.median(stddev),np.mean(stddev),np.std(stddev)) +print(stddev_exp) +print(np.median(stddev_exp),np.mean(stddev_exp),np.std(stddev_exp)) +""" + +""" +basefolder = '/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/ngc300x1/' +obsids = [str(i) for i in range(49834027,49834042)] + [str(i) for i in range(49834043,49834062)] + [str(i) for i in range(49834063,49834066)] + ['88810002'] + [str(i) for i in range(49834066,49834069)] + [str(i) for i in range(49834070,49834079)] + [str(i) for i in range(49834080,49834088)] +counter = 0 +for i in range(len(obsids)): + fitsfile = fits.open(basefolder + 'sw000' + obsids[i] + 'xpcw3po_bary_cl_ngc300x1_ngc300x1.evt') + print(len(fitsfile[2].data)) + counter += len(fitsfile[2].data) + +print(counter) +""" + +""" +##### eclipse timings - 6/24, see the spreadsheet + +#eclipse_times = np.array([547432660.5728,548500113.9923,548730242.8801,549555729.5291, +# 550037412.9875,552279376.5862,552747356.4104,553577945.8216,557242679.2037, +# 559373193.2472,569064024.9780]) #8.461949e-6 + +eclipse_times = np.array([547432660.5728,548500113.9923,548730242.8801, + 549555729.5291,550037412.9875,552279376.5862,552747356.4104,553577945.8216, + 554042992.9464,557235752.3213,567870701.9700]) #8.464749e-6 + +MJDREFI = 51910 +MJDREFF = 7.428703700000000E-04 +mjds = MJDREFI + MJDREFF + eclipse_times/86400 + +#no_cycles = np.array([1,10,12,19,23,42,46,53,84,102,184]) #8.461949e-6 +no_cycles = np.array([1,10,12,19,23,42,46,53,57,84,174]) #8.464749e-6 + +T0 = MJDREFI + MJDREFF + 547313659.6723/86400 + +def linear_mod(N,x0,a): + return x0 + a*N + +def quad_mod(N,x0,a,b): + return x0 + a*N + b*N**2 + +popt,pcov = curve_fit(linear_mod,no_cycles,mjds,p0=[T0,1.5]) +popt_q,pcov_q = curve_fit(quad_mod,no_cycles,mjds,p0=[T0,1.5,1e-5]) + +print('T0 from linear: ' + str(popt[0])) +print('T0 from quadratic: ' + str(popt_q[0])) + +print( (popt[0] - MJDREFI - MJDREFF) * 86400 ) +print( (popt[0] - MJDREFI - MJDREFF) * 86400 - 547313659.6723 ) +print( (popt_q[0] - MJDREFI - MJDREFF) * 86400 ) +print( (popt_q[0] - MJDREFI - MJDREFF) * 86400 - 547313659.6723 ) + +print('Linear:') +print(popt) +print(np.diag(np.sqrt(pcov))) +print('Quadratic:') +print(popt_q) +print(np.diag(np.sqrt(pcov_q))) + +plt.figure() +plt.plot(no_cycles,mjds,'rx-') +plt.plot(no_cycles,linear_mod(no_cycles,popt[0],popt[1]),'bx-') +plt.figure() +plt.plot(no_cycles,mjds-linear_mod(no_cycles,popt[0],popt[1])) +plt.figure() +plt.plot(no_cycles,quad_mod(no_cycles,popt_q[0],popt_q[1],popt_q[2])) +plt.figure() +plt.plot(no_cycles,mjds-quad_mod(no_cycles,popt_q[0],popt_q[1],popt_q[2])) +plt.show() +""" + +""" +nsample = 100 +T = 480 +x = np.arange(0,86400,nsample) +y = 0.05*np.sin(2*np.pi/T*x) + np.random.normal(loc=0,scale=0.05,size=len(x)) +#plt.plot(x,y,'r-') + +omega,psd,prob3,prob4,prob5 = Lv2_dj_lsp.lsp(x,y) +nu_reg = omega/(2.0*np.pi) +freq = omega/(2*np.pi) + +plt.axhline(y=prob3,lw=0.5,alpha=0.5) +plt.axhline(y=prob4,lw=0.5,alpha=0.5) +plt.axhline(y=prob5,lw=0.5,alpha=0.5) + +plt.plot(freq,psd,'rx-') + +plt.show() +""" + +""" +eventfiles = open('/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/ngc300x1/niceroverlap_all.list','r').read().split('\n')[:-1] +expos = [] +for i in range(len(eventfiles)): + gtis = fits.open(eventfiles[i])[2].data + total_gti = sum( [gtis[i][1] - gtis[i][0] for i in range(len(gtis)) ]) + expos.append(total_gti) + +expos = np.array(expos) +print(np.mean(expos)) +print(np.median(expos)) +print(np.std(expos)) +print(np.sum(expos)) +plt.hist(expos) +plt.xlabel('Exposure times (s)',fontsize=12) +plt.ylabel('Number',fontsize=12) +plt.show() +""" + +""" +popt,pcov = curve_fit(linear_mod,no_cycles,mjds,p0=[1.5]) +popt_q,pcov_q = curve_fit(quad_mod,no_cycles,mjds,p0=[1.5,1e-5]) +print('Linear:') +print(popt) +print(np.diag(np.sqrt(pcov))) +print('Quadratic:') +print(popt_q) +print(np.diag(np.sqrt(pcov_q))) + +plt.figure() +plt.plot(no_cycles,mjds,'rx-') +plt.plot(no_cycles,linear_mod(no_cycles,popt[0]),'bx-') +plt.figure() +plt.plot(no_cycles,mjds-linear_mod(no_cycles,popt[0])) +plt.figure() +plt.plot(no_cycles,quad_mod(no_cycles,popt_q[0],popt_q[1])) +plt.figure() +plt.plot(no_cycles,mjds-quad_mod(no_cycles,popt_q[0],popt_q[1])) +plt.show() +""" + +""" +def phase_exposure(start_time, stop_time, period, nbin=16, gtis=None): + + Calculate the exposure on each phase of a pulse profile. + + Parameters + ---------- + start_time, stop_time : float + Starting and stopping time (or phase if ``period==1``) + period : float + The pulse period (if 1, equivalent to phases) + + Other parameters + ---------------- + nbin : int, optional, default 16 + The number of bins in the profile + gtis : [[gti00, gti01], [gti10, gti11], ...], optional, default None + Good Time Intervals + + Returns + ------- + expo : array of floats + The normalized exposure of each bin in the pulse profile (1 is the + highest exposure, 0 the lowest) + + if gtis is None: + gtis = np.array([[start_time, stop_time]]) + + # Use precise floating points ------------- + + start_time = np.longdouble(start_time) + stop_time = np.longdouble(stop_time) + period = np.longdouble(period) + gtis = np.array(gtis, dtype=np.longdouble) + # ----------------------------------------- + #print('GTIs from longdouble: ' + str(sum([gtis[i][1]-gtis[i][0] for i in range(len(gtis))]))) + + expo = np.zeros(nbin) + phs = np.linspace(0, 1, nbin + 1) + phs = np.array(list(zip(phs[0:-1], phs[1:]))) + + # Discard gtis outside [start, stop] + good = np.logical_and(gtis[:, 0] < stop_time, gtis[:, 1] > start_time) + gtis = gtis[good] + + for g in gtis: + g0 = g[0] + g1 = g[1] + if g0 < start_time: + # If the start of the fold is inside a gti, start from there + g0 = start_time + if g1 > stop_time: + # If the end of the fold is inside a gti, end there + g1 = stop_time + length = g1 - g0 + # How many periods inside this length? + nraw = length / period + # How many integer periods? + nper = nraw.astype(int) + + # First raw exposure: the number of periods + expo += nper / nbin + + # FRACTIONAL PART ================= + # What remains is additional exposure for part of the profile. + start_phase = np.fmod(g0 / period, 1) + end_phase = nraw - nper + start_phase + limits = [[start_phase, end_phase]] + # start_phase is always < 1. end_phase not always. In this case... + if end_phase > 1: + limits = [[0, end_phase - 1], [start_phase, 1]] + + for l in limits: + l0 = l[0] + l1 = l[1] + # Discards bins untouched by these limits + goodbins = np.logical_and(phs[:, 0] <= l1, phs[:, 1] >= l0) + idxs = np.arange(len(phs), dtype=int)[goodbins] + for i in idxs: + start = np.max([phs[i, 0], l0]) + stop = np.min([phs[i, 1], l1]) + w = stop - start + expo[i] += w + + #print('Expo*period: ' + str(sum(expo)*period)) + return expo / np.max(expo) +""" + +""" +#eventfile = '/Volumes/Samsung_T5/NICERsoft_outputs/0034070101_pipe/ni0034070101_nicersoft_bary.evt' +eventfile = '/Volumes/Samsung_T5/NGC300_ULX_Swift/xrt/event/ngc300x1/ngc300x1_merge_niceroverlap_all.evt' + +times = fits.open(eventfile)[1].data['TIME'] +gtis_data = fits.open(eventfile)[2].data +T = sum([ gtis_data[i]['STOP']-gtis_data[i]['START'] for i in range(len(gtis_data)) ]) +#T0 = 56658 + 0.000777592592592593 + (fits.open(eventfile)[1].header['TSTART'] + (-1))/86400 +T0 = 51910 + 7.428703700000000E-04 + fits.open(eventfile)[1].header['TSTART']/86400 + +gtis_conform = [] +for i in range(len(gtis_data)): + gtis_conform.append([gtis_data[i][0],gtis_data[i][1]]) + +#print('T: ' + str(T)) + +expos = phase_exposure(times[0],times[-1],1/8.4666e-6,nbin=20,gtis=gtis_conform) +print(expos) +total_expos = np.array(list(expos) + list(expos)) +""" + +""" +t1 = 5 +t2 = 35 +GTIs1 = np.array([ [3,6], [10,19], [20,25], [26,32], [33,36] ]) +nbin = 20 +expos = phase_exposure(t1,t2,3,nbin=20,gtis=GTIs1) +print(expos) + +gti_phases = pulse_phase(GTIs1,[1/3],to_1=False) +start_phase,stop_phase = pulse_phase(np.array([t1,t2]),[1/3],to_1=False) +expo_norm = phase_exposure(start_phase,stop_phase,1,20,gtis=gti_phases) +print(expo_norm) +""" + + +""" +f1 = [8.465068630012935e-06, 8.46813510807163e-06, 8.464302689232871e-06, 8.466605940469421e-06, 8.467369167046e-06, 8.468898333913252e-06, 8.467369167046e-06, 8.464302689232871e-06, 8.467366452353124e-06, 8.465834570792998e-06, 8.465065916058498e-06, 8.466597797127494e-06, 8.46277894733641e-06, 8.467363737661991e-06, 8.470432931148515e-06, 8.467363737661991e-06, 8.464305402943485e-06, 8.465834570792998e-06, 8.466600511573061e-06, 8.465834570792998e-06, 8.467363737661991e-06, 8.465831856592996e-06, 8.47119615625344e-06, 8.470432931148515e-06, 8.471193440334479e-06, 8.467363737661991e-06, 8.46812967819649e-06, 8.468895618730987e-06, 8.465065916058498e-06, 8.467363737661991e-06, 8.468901049097257e-06, 8.46584271340345e-06, 8.466597797127494e-06, 8.466597797127494e-06, 8.465065916058498e-06, 8.472725321403475e-06, 8.467366452353124e-06, 8.463547602323434e-06, 8.465839999198226e-06, 8.468898333913252e-06, 8.469664274693314e-06, 8.467366452353124e-06, 8.470432931148515e-06, 8.465831856592996e-06, 8.468132393133189e-06, 8.464305402943485e-06, 8.465831856592996e-06, 8.464305402943485e-06, 8.466600511573061e-06, 8.467363737661991e-06] + +f2 = [8.468895618730987e-06, 8.468895618730987e-06, 8.46507677188669e-06, 8.46812967819649e-06, 8.466597797127494e-06, 8.465834570792998e-06, 8.468132393133189e-06, 8.464302689232871e-06, 8.4696697055542e-06, 8.465068630012935e-06, 8.466597797127494e-06, 8.464302689232871e-06, 8.462768094455006e-06, 8.466597797127494e-06, 8.463536748452808e-06, 8.465079485848087e-06, 8.468132393133189e-06, 8.469664274693314e-06, 8.469661559265485e-06, 8.466597797127494e-06, 8.465068630012935e-06, 8.46431083036993e-06, 8.47119615625344e-06, 8.466600511573061e-06, 8.464302689232871e-06, 8.465071343969115e-06, 8.47503129445256e-06, 8.463534034989504e-06, 8.46812967819649e-06, 8.469661559265485e-06, 8.46123892611262e-06, 8.465834570792998e-06, 8.46507677188669e-06, 8.466605940469421e-06, 8.468903764283003e-06] + +f3 = [8.46812967819649e-06, 8.468132393133189e-06, 8.465068630012935e-06, 8.466597797127494e-06, 8.465834570792998e-06, 8.465065916058498e-06, 8.468895618730987e-06, 8.462776234113448e-06, 8.468901049097257e-06, 8.464302689232871e-06, 8.46812967819649e-06, 8.462002153920508e-06, 8.468132393133189e-06, 8.46660322602037e-06, 8.463539461917857e-06] + +total_f = f1+f2+f3 +print(len(total_f)) +print(np.std(np.array(total_f))) +print(np.mean(np.array(total_f))) +""" + +""" +import numpy as np +import numpy.polynomial.polynomial as npoly +from scipy import optimize +import matplotlib.pyplot as plt +np.random.seed(2017) + +def f(breakpoints, x, y, fcache): + breakpoints = tuple(map(int, sorted(breakpoints))) + if breakpoints not in fcache: + total_error = 0 + for f, xi, yi in find_best_piecewise_polynomial(breakpoints, x, y): + total_error += ((f(xi) - yi)**2).sum() + fcache[breakpoints] = total_error + # print('{} --> {}'.format(breakpoints, fcache[breakpoints])) + return fcache[breakpoints] + +def find_best_piecewise_polynomial(breakpoints, x, y): + breakpoints = tuple(map(int, sorted(breakpoints))) + xs = np.split(x, breakpoints) + ys = np.split(y, breakpoints) + result = [] + for xi, yi in zip(xs, ys): + if len(xi) < 2: continue + coefs = npoly.polyfit(xi, yi, 1) + f = npoly.Polynomial(coefs) + result.append([f, xi, yi]) + return result + +x = np.arange(0.45,1.95,0.05) +y = np.array([0.00105478,0.00108443,0.00104594,0.00126743,0.00125505,0.00110672, + 0.00106399,0.00094255,0.00111247,0.00120255,0.00122203,0.00125356, + 0.0010629,0.00050578,0.00029983,0.00033695,0.00036172,0.00035548, + 0.00056006,0.00064167,0.00105478,0.00108443,0.00104594,0.00126743, + 0.00125505,0.00110672,0.00106399,0.00094255,0.00111247,0.00120255]) + +num_breakpoints = 4 +breakpoints = optimize.brute( + f, [slice(1, len(x), 1)]*num_breakpoints, args=(x, y, {}), finish=None) + +plt.scatter(x, y, c='blue', s=50) +for f, xi, yi in find_best_piecewise_polynomial(breakpoints, x, y): + x_interval = np.array([xi.min(), xi.max()]) + print('y = {:35s}, if x in [{}, {}]'.format(str(f), *x_interval)) + plt.plot(x_interval, f(x_interval), 'ro-') + +plt.show() +""" + +""" +xmm_lc1 = '/Volumes/Samsung_T5/NGC300_XMMdata/0791010101/PROC/xmm_0791010101_lccorr.lc' +xmm_lc2 = '/Volumes/Samsung_T5/NGC300_XMMdata/0791010301/PROC/xmm_0791010301_lccorr.lc' + +times1 = fits.open(xmm_lc1)[1].data['TIME'] +rates1 = fits.open(xmm_lc1)[1].data['RATE'] +times2 = fits.open(xmm_lc2)[1].data['TIME'] +rates2 = fits.open(xmm_lc2)[1].data['RATE'] + +total_time = np.array(list(fits.open(xmm_lc1)[1].header['MJDREF'] + times1) + list(fits.open(xmm_lc2)[1].header['MJDREF'] + times2) ) +total_rates = np.array(list(rates1) + list(rates2)) + +#print(sum(100*total_rates)) + + +trunc_times = total_time-total_time[0] +""" +#t_bins = np.arange(trunc_times[0],trunc_times[-1]+100,100) +#summed_data, bin_edges, binnumber = stats.binned_statistic(trunc_times,total_rates,statistic='mean',bins=t_bins) #binning the time values in the data + +#freqs = np.linspace(1e-7,1e-4,10001) +""" +plt.figure() +plt.plot(total_time,total_rates,'r-') +plt.xlabel('Time (s)',fontsize=12) +plt.ylabel('Rate (counts/s)',fontsize=12) +plt.title('XMM Newton light curve for NGC 300 X-1 (0791010101 and 0791010301)') +plt.show() + + +plt.figure() + +import scipy.signal as signal +pgram = signal.lombscargle(total_time, total_rates, freqs, normalize=True) +plt.plot(freqs,pgram,'rx-') + +plt.figure() +pgram2 = signal.lombscargle(t_bins[:-1],summed_data,freqs,normalize=True) +plt.plot(freqs,pgram2,'bx-') +print(freqs[:10],pgram2[:10]) +""" + +""" +plt.figure() +omega,psd,prob3,prob4,prob5 = Lv2_dj_lsp.lsp(trunc_times,total_rates) +freq = omega/(2*np.pi) + +plt.plot(freq,psd,'rx-') +plt.show() +""" + +""" +xmm_evt1 = '/Volumes/Samsung_T5/NGC300_XMMdata/0791010101/PROC/xmm_0791010101_bary_ngc300x1.evt' +xmm_evt1_bg = '/Volumes/Samsung_T5/NGC300_XMMdata/0791010101/PROC/xmm_0791010101_bary_ngc300bg.evt' +xmm_evt2 = '/Volumes/Samsung_T5/NGC300_XMMdata/0791010301/PROC/xmm_0791010301_bary_ngc300x1.evt' +xmm_evt2_bg = '/Volumes/Samsung_T5/NGC300_XMMdata/0791010301/PROC/xmm_0791010301_bary_ngc300bg.evt' + +times1 = fits.open(xmm_evt1)[1].data['TIME'] +counts1 = fits.open(xmm_evt1)[1].data['COUNTS'] +times2 = fits.open(xmm_evt2)[1].data['TIME'] +counts2 = fits.open(xmm_evt2)[1].data['COUNTS'] +exp1 = fits.open(xmm_evt1)[1].header['EXPOSURE'] +exp2 = fits.open(xmm_evt2)[1].header['EXPOSURE'] + +trunc_times1 = times1-times1[0] +trunc_times2 = times2-times1[0] + +counts_bg1 = fits.open(xmm_evt1_bg)[1].data['COUNTS'] +counts_bg2 = fits.open(xmm_evt2_bg)[1].data['COUNTS'] + +tbins = np.arange(trunc_times1[0],trunc_times2[-1]+100,100) + +summed_data1, bin_edges, binnumber = stats.binned_statistic(trunc_times1,counts1,statistic='sum',bins=tbins) +summed_data2, bin_edges, binnumber = stats.binned_statistic(trunc_times2,counts2,statistic='sum',bins=tbins) + +bg_summed_data1, bin_edges, binnumber = stats.binned_statistic(trunc_times1,counts_bg1,statistic='sum',bins=tbins) +bg_summed_data2, bin_edges, binnumber = stats.binned_statistic(trunc_times2,counts_bg2,statistic='sum',bins=tbins) + +total_sum = summed_data1 + summed_data2 +total_bg = bg_summed_data1 + bg_summed_data2 + + + +plt.figure() +plt.plot(tbins[:-1],total_sum,'k-') + +plt.figure() +omega,psd,prob3,prob4,prob5 = Lv2_dj_lsp.lsp(tbins[:-1],total_sum) +freq = omega/(2*np.pi) + +plt.plot(freq,psd,'rx-') +plt.show() +""" + +""" +print(sum(total_sum),sum(total_bg)) + +plt.plot(tbins[:-1],total_sum,'k-') +plt.plot(tbins[:-1],total_bg*1/9,'r-') +plt.xlabel('Time (s)',fontsize=12) +plt.ylabel('Counts/s',fontsize=12) +plt.title('Exposure time for 0791010101: ' + str(exp1) + ' ; exposure time for 0791010301: ' + str(exp2)) +plt.show() +""" + +""" +completeness = np.array([0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0]) +data = np.array([43.6,43.6,45.5,78.1,84.8,84.2,84.3,84.2,82.8,79.0,78.3]) +sim1 = np.array([213.51,213.51,228.35,228.86,230.04,228.82,225.64,223.16,221.71,216.18,210.67]) +sim2 = np.array([207.05,207.05,223.88,224.41,225.56,224.25,221.81,219.14,217.22,211.45,206.46]) +sim3 = np.array([141.57,141.57,145.70,145.72,143.23,142.83,141.18,143.39,144.69,141.67,135.36]) +sim4 = np.array([61.80,61.80,64.46,63.96,65.15,65.55,66.46,65.46,68.81,67.69,66.76]) +sim5 = np.array([28.03,28.03,29.29,27.29,26.17,25.40,22.50,24.02,23.08,22.09,23.01]) +sim6 = np.array([123.64,123.64,143.11,142.797,142.802,144.12,140.16,140.24,137.53,133.64,128.01]) + +plt.plot(completeness,data,'x-') +plt.plot(completeness,sim1,'x-') +plt.plot(completeness,sim2,'x-') +plt.plot(completeness,sim3,'x-') +plt.plot(completeness,sim4,'x-') +plt.plot(completeness,sim5,'x-') +plt.plot(completeness,sim6,'x-') + +plt.xlabel('Completeness (fraction)',fontsize=12) +plt.ylabel('Normalized Power from LS periodogram',fontsize=12) +plt.legend(('Data','Sim 1','Sim 2','Sim 3','Sim 4','Sim 5','Sim 6'),loc='best') + +plt.title('Sim. 1) No noise' + '\n' + 'Sim. 2) Noise level ~ 10% of amplitude of data' + '\n' + 'Sim. 3) Noise level ~ half of amplitude of data' + '\n' + 'Sim. 4) Noise level ~ same amplitude of data' + '\n' + 'Sim. 5) Noise level ~ 2x amplitude of data' + '\n' + 'Sim. 6) Low amplitude, and noise level ~ half amplitude of data') +plt.show() +""" + +""" +freq,freqdot = np.meshgrid(np.arange(8.25e-6,8.7e-6,1e-8),np.arange(1e-18,9e-17,1e-20)) +a = np.meshgrid(np.arange(8.25e-6,8.7e-6,1e-8),np.arange(1e-18,9e-17,1e-20)) +freq_swift,freqdot_swift,chi2_swift = np.genfromtxt('/Volumes/Samsung_T5/NGC300_XMMdata/chi2_swift_freq_freqdot.txt',usecols=(0,1,2),unpack=True) +N_freq = len(np.arange(8.25e-6,8.7e-6,1e-8)) +N_freqdot = len(np.arange(1e-18,9e-17,1e-20)) +chi2_reshape = np.reshape(chi2_swift,(N_freqdot,N_freq),order='F') +""" + +""" +print('0791010101 PN') +data1a = fits.open('/Volumes/Samsung_T5/NGC300_XMMdata/0791010101/PROC/xmm_0791010101_pn_clean.pha') +print(sum(data1a[1].data['COUNTS'][30:1000])) +bg1a = fits.open('/Volumes/Samsung_T5/NGC300_XMMdata/0791010101/PROC/xmm_0791010101_pn_bg.pha') +print(sum(bg1a[1].data['COUNTS'][30:1000])) + +print('0791010101 MOS1') +data1b = fits.open('/Volumes/Samsung_T5/NGC300_XMMdata/0791010101/PROC/xmm_0791010101_mos1_clean.pha') +print(sum(data1b[1].data['COUNTS'][30:1000])) +bg1b = fits.open('/Volumes/Samsung_T5/NGC300_XMMdata/0791010101/PROC/xmm_0791010101_mos1_bg.pha') +print(sum(bg1b[1].data['COUNTS'][30:1000])) + +print('0791010101 MOS2') +data1c = fits.open('/Volumes/Samsung_T5/NGC300_XMMdata/0791010101/PROC/xmm_0791010101_mos2_clean.pha') +print(sum(data1c[1].data['COUNTS'][30:1000])) +bg1c = fits.open('/Volumes/Samsung_T5/NGC300_XMMdata/0791010101/PROC/xmm_0791010101_mos2_bg.pha') +print(sum(bg1c[1].data['COUNTS'][30:1000])) + +print('0791010301 PN') +data2a = fits.open('/Volumes/Samsung_T5/NGC300_XMMdata/0791010301/PROC/xmm_0791010301_pn_clean.pha') +print(sum(data2a[1].data['COUNTS'][30:1000])) +bg2a = fits.open('/Volumes/Samsung_T5/NGC300_XMMdata/0791010301/PROC/xmm_0791010301_pn_bg.pha') +print(sum(bg2a[1].data['COUNTS'][30:1000])) + +print('0791010301 MOS1') +data2b = fits.open('/Volumes/Samsung_T5/NGC300_XMMdata/0791010301/PROC/xmm_0791010301_mos1_clean.pha') +print(sum(data2b[1].data['COUNTS'][30:1000])) +bg2b = fits.open('/Volumes/Samsung_T5/NGC300_XMMdata/0791010301/PROC/xmm_0791010301_mos1_bg.pha') +print(sum(bg2b[1].data['COUNTS'][30:1000])) + +print('0791010301 MOS2') +data2c = fits.open('/Volumes/Samsung_T5/NGC300_XMMdata/0791010301/PROC/xmm_0791010301_mos2_clean.pha') +print(sum(data2c[1].data['COUNTS'][30:1000])) +bg2c = fits.open('/Volumes/Samsung_T5/NGC300_XMMdata/0791010301/PROC/xmm_0791010301_mos2_bg.pha') +print(sum(bg2c[1].data['COUNTS'][30:1000])) +""" + +""" +eventfile = '/Volumes/Samsung_T5/NICERsoft_outputs/at2018cow_2020/at2018cow_filtered.evt' +eventfiles = glob.glob('/Volumes/Samsung_T5/NICERsoft_outputs/at2018cow_2020/accelsearch_GTIs/*.evt') +gtis_highsnr = fits.open(eventfile)[5].data +niextract_folder = '/Volumes/Samsung_T5/NICERsoft_outputs/at2018cow_2020/accelsearch_GTIs/' + +ACCEL_files = glob.glob('/Volumes/Samsung_T5/NICERsoft_outputs/at2018cow_2020/accelsearch_GTIs/*ACCEL_100') +eventfiles_ACCEL = [ACCEL_files[i][:-10] + '.evt' for i in range(len(ACCEL_files))] +gti_no = [float(ACCEL_files[i][-14:-10]) for i in range(len(ACCEL_files))] + +#with PdfPages('/Volumes/Samsung_T5/NICERsoft_outputs/at2018cow_2020/at2018cow_accelsearch.pdf') as pdf: + +#header1 = " Summed Coherent Num Period Frequency FFT 'r' Freq Deriv FFT 'z' Accel " +#header2 = " Power / Raw FFT 'r' Pred 'r' FFT 'z' Pred 'z' Phase Centroid Purity " + +for i in tqdm(range(len(ACCEL_files))): #for each successful ACCEL_zmax file: + freqs = [] + sigmas = [] + accel_textfile = np.array(open(ACCEL_files[i],'r').read().split('\n')) #read the data from the ACCEL_$zmax files + index_header1 = np.where(accel_textfile==header1)[0][0] #index for "Summed, Coherent, Num, Period etc + index_header2 = np.where(accel_textfile==header2)[0][0] #index for "Power / Raw FFT 'r' etc + no_cands = index_header2 - index_header1 - 5 #to obtain number of candidates + for j in range(no_cands): + freqs.append(float(accel_textfile[j+3].split()[6][:-3])) + sigmas.append(float(accel_textfile[j+3].split()[1])) + #times = np.ones(no_cands)*(fits.open(eventfiles_ACCEL[i])[1].header['TSTART']+fits.open(eventfiles_ACCEL[i])[1].header['TSTOP'])/2 + times = np.ones(no_cands)*gti_no[i] + plt.scatter(x=times,y=freqs,c=sigmas,marker='o',cmap='gist_heat',vmin=2,vmax=4,edgecolors='k') + +plt.colorbar().set_label('Significance (sigma)') + +import mplcursors +mplcursors.cursor(hover=True) +plt.xlabel('Time',fontsize=12) +plt.ylabel('Frequency',fontsize=12) +#pdf.savefig() +#plt.close() +plt.show() +""" + +""" +pn_file = fits.open('/Volumes/Samsung_T5/NGC300_XMMdata/0791010101/PROC/xmm_0791010101_mos1_grp.pha')[1].data +pn_chans = pn_file['CHANNEL'] +pn_group = pn_file['GROUPING'] + +pn_chans_1 = pn_chans[pn_group==1] +for i in range(len(pn_chans)-1): + if pn_chans_1[i] <= 2500: + if i == 0: + print(pn_chans_1[i],pn_chans_1[i]*5) + else: + print(pn_chans_1[i],pn_chans_1[i]*5,(pn_chans_1[i+1]-pn_chans_1[i])*5) +""" + +""" +energies = np.array(list(np.arange(0.5,1.05,0.1)) + list(np.arange(1.5,12.5,0.5))) +fwhm = np.array([126.06,109.68,107.23,107.73,109.08,110.81,121.43,138.13,147.88, + 158.82,168.35,178.80,189.79,199.75,209.74,220.28,229.68,239.02, + 248.66,257.29,265.68,274.18,281.65,288.76,295.80,301.66,307.05,312.19]) + +for i in range(len(energies)): + print(energies[i],fwhm[i]/3) + +def sqrtfunc(x,a,b,c): + return a*(x+b)**c + + +#popt,pcov = curve_fit(sqrtfunc,energies,fwhm,p0=[10,1.0,1.2],maxfev=50000) +#print(popt) +#print(np.sqrt(np.diag(pcov))) +#for i in range(len(energies)): +# print(input_E[1:][i],sqrtfunc(energies,popt[0],popt[1],popt[2],popt[3])[i]/3) + +plt.plot(energies,fwhm,'rx-') +#plt.plot(energies,sqrtfunc(energies,*popt),'bx-') +plt.annotate('48.2(E+2.5)^0.71',(4,300)) +plt.xlabel('Energy (keV)',fontsize=12) +plt.ylabel('FWHM (eV)',fontsize=12) +plt.legend(('Measured','curve_fit')) +plt.show() +""" + +""" +from scipy.interpolate import interp1d + +##### FOR PN: +phases = np.arange(0.025,2,0.05) +pn_prof = np.array([1604.0,2164.0,1937.4058099752326,2676.0,3300.0,3839.637730914639,4038.0,4056.0,3540.7859071725998,2140.5, 3804.0,3668.75965331829,3826.5,3006.0, +1034.213403644357,1404.0,483.0,703.8586733495172,474.2092322833178,487.5]*2) +pn_inter = interp1d(phases,pn_prof,kind='cubic') +pn_prof_err = np.array([40.049968789001575,46.51881339845203,55.65052783180561,89.5991071384085,99.49874371066204,107.4471256562774,110.06361796706489,110.30865786510145,100.06852620303427, +56.66348030257233,75.53806987208498,74.28709253420669,75.76113779504647,67.14908785679812,39.400392759523484,45.89117562233503,26.916537667389523,32.50117373800949, +26.67635348746897,27.04163456597996]*2) + +##### FOR MOS1: +mos1_prof = np.array([448.0,572.0,645.7875788096308,864.0,1152.0,1032.3053915630078,1167.0,1236.0,978.8970623790145,676.5,1014.0,1073.182141931018,1099.5,943.5, +444.50831287810894,507.0,318.0,210.0,208.69091755823553,178.58161485859577]*2) +mos1_inter = interp1d(phases,mos1_prof,kind='cubic') +mos1_prof_err = np.array([21.166010488516726,23.916521486202797,29.055356803825024,50.911688245431435,58.78775382679629,55.73925190095661,59.169248769948084,60.89334939055334, +48.883786528584615,31.855140872392965,38.99999999999997,40.190987067477344,40.610959112042714,37.61980861195333,25.8365208870395,27.57716446627533,21.840329667841537, +17.748239349298878, 17.700932599765082, 16.37054979377456]*2) + +##### FOR MOS2: +mos2_prof = np.array([336.0,651.0,588.6128641386009,855.3569611778419,1308.0,1011.0,1218.0,1116.0,1323.0,804.5623109294818,1038.0,1129.4531069776747,1100.2580003973176,1054.5, +759.8367288864442,486.4282601354391,439.5,171.0,304.56707598060035,150.0]*2) +mos2_inter = interp1d(phases,mos2_prof,kind='cubic') +mos2_prof_err = np.array([18.33030277982336,25.514701644346147,24.9179694998494,44.77142958345511,62.64183905346333,55.07267925205741,60.44832503882968,57.86190456595775,63.0,36.57101413315826, +39.458839313897684,41.21432922222213,40.63895649552821,39.77122075068852,33.77886277372683,27.023792229746615,25.675864152935514,16.015617378046993,21.376418084077713,15.0]*2) + +spacing = 0.05/20 +phases_long = np.arange(0.025,1.975+spacing,spacing) + +plt.figure() +#plt.errorbar(x=phases,y=pn_prof,yerr=pn_prof_err,color='r',drawstyle='steps-mid') +plt.plot(phases_long,pn_inter(phases_long),'r--') +#plt.errorbar(x=phases,y=mos1_prof,yerr=mos1_prof_err,color='b',drawstyle='steps-mid') +plt.plot(phases_long,mos1_inter(phases_long),'b--') +#plt.errorbar(x=phases,y=mos2_prof,yerr=mos2_prof_err,color='k',drawstyle='steps-mid') +plt.plot(phases_long,mos2_inter(phases_long),'k--') +plt.legend(('PN','MOS1','MOS2'),loc='best',fontsize=12) +plt.title('Exposure-corrected (using Stingray fold_events)',fontsize=12) +plt.xlabel('Phase',fontsize=12) +plt.ylabel('Counts',fontsize=12) +plt.show() +""" + +#from stingray.pulse.pulsar import pulse_phase +#a = np.array([2,8,9,11,12,14,16,17,18,19,20]) +#print(pulse_phase(a,1/3)) +#b = np.array([2,8,9,11,12,14,16,17,18,19,20])-9 +#print(pulse_phase(b,1/3)) + +#bgfile = fits.open('/Volumes/Samsung_T5/NGC300_XMMdata/phase_res_spec/combined_bg_pn.pha') +#ounts = bgfile[1].data['COUNTS'] +#print(sum(counts)) + +""" +T_orb = 1/8.4712e-6 + +pn_expos_frac = np.array([0.05251764,0.07677285,0.14237649,0.13152822,0.04864319, + 0.03305885,0.04322354,0.04902803,0.05,0.05,0.05,0.06141165, + 0.1,0.09972594,0.1,0.08189309,0.03509542,0.06472928, + 0.04661179,0.05677649]) +0.00-0.05, 0.05-0.10, 0.10-0.15, 0.15-0.20, 0.20-0.25, 0.25-0.30, 0.30-0.35 +0.35-0.40, 0.40-0.45, 0.45-0.50, 0.50-0.55, 0.55-0.60, 0.60-0.65, 0.65-0.70 +0.70-0.75, 0.75-0.80, 0.80-0.85, 0.85-0.90, 0.90-0.95, 0.95-1.00 +pn_expos = pn_expos_frac * T_orb +#pn_off_eclipse = pn_expos[4:-3] +#pn_on_eclipse = np.array(list(pn_expos[:4]) + list(pn_expos[-3:])) +#print(sum(pn_off_eclipse)) +#print(sum(pn_on_eclipse)) +pn_off = sum(pn_expos[5:-4]) +pn_ingress = sum(pn_expos[-4:-2]) +pn_on = sum(np.array(list(pn_expos[-2:]) + list(pn_expos[:2]))) +pn_egress = sum(pn_expos[2:5]) +print(pn_off,pn_ingress,pn_on,pn_egress) + +mos1_expos_frac = np.array([0.07237615,0.09413837,0.15,0.13729413,0.06624048,0.03560002, + 0.04915294,0.04981703,0.05,0.05,0.05169412,0.07558012, + 0.1,0.09883275,0.1,0.09143779,0.04672711,0.07289424, + 0.07510179,0.07400623]) + +mos1_expos = mos1_expos_frac * T_orb +#mos1_off_eclipse = mos1_expos[4:-3] +#mos1_on_eclipse = np.array(list(mos1_expos[:4]) + list(mos1_expos[-3:])) +#print(sum(mos1_off_eclipse)) +#print(sum(mos1_on_eclipse)) +mos1_off = sum(mos1_expos[5:-4]) +mos1_ingress = sum(mos1_expos[-4:-2]) +mos1_on = sum(np.array(list(mos1_expos[-2:]) + list(mos1_expos[:2]))) +mos1_egress = sum(mos1_expos[2:5]) +print(mos1_off,mos1_ingress,mos1_on,mos1_egress) + +mos2_expos_frac = np.array([0.08557638,0.10630647,0.15,0.14237648,0.08618251,0.04152942, + 0.05,0.04986786,0.05,0.05,0.05423529,0.08545808,0.1, + 0.09966964,0.1,0.09576473,0.0643135,0.07628246, + 0.09402377,0.07879993]) + +mos2_expos = mos2_expos_frac * T_orb +#mos2_off_eclipse = mos2_expos[4:-3] +#mos2_on_eclipse = np.array(list(mos2_expos[:4]) + list(mos2_expos[-3:])) +#print(sum(mos2_off_eclipse)) +#print(sum(mos2_on_eclipse)) +mos2_off = sum(mos2_expos[5:-4]) +mos2_ingress = sum(mos2_expos[-4:-2]) +mos2_on = sum(np.array(list(mos2_expos[-2:]) + list(mos2_expos[:2]))) +mos2_egress = sum(mos2_expos[2:5]) +print(mos2_off,mos2_ingress,mos2_on,mos2_egress) +""" + +""" +pn_spectra = sorted(glob.glob('/Volumes/Samsung_T5/NGC300_XMMdata/phase_res_spec/ngc300x1_pn_*pha')) +mos1_spectra = sorted(glob.glob('/Volumes/Samsung_T5/NGC300_XMMdata/phase_res_spec/ngc300x1_mos1_*pha')) +mos2_spectra = sorted(glob.glob('/Volumes/Samsung_T5/NGC300_XMMdata/phase_res_spec/ngc300x1_mos2_*pha')) + +change_expos = open('/Volumes/Samsung_T5/NGC300_XMMdata/phase_res_spec/change_expos.txt','w') +for i in range(len(pn_spectra)): + change_expos.write('fparkey ' + str(pn_expos[i]) + ' ' + str(pn_spectra[i]) + ' EXPOSURE' + '\n') +for i in range(len(mos1_spectra)): + change_expos.write('fparkey ' + str(mos1_expos[i]) + ' ' + str(mos1_spectra[i]) + ' EXPOSURE' + '\n') +for i in range(len(mos2_spectra)): + change_expos.write('fparkey ' + str(mos2_expos[i]) + ' ' + str(mos2_spectra[i]) + ' EXPOSURE' + '\n') +change_expos.close() +""" + +""" +cleaned_event = '/Volumes/Samsung_T5/NGC300_XMMdata/0791010101/PROC/xmm_0791010101_pn_clean.evt' +cleaned_spectra = '/Volumes/Samsung_T5/NGC300_XMMdata/0791010101/PROC/xmm_0791010101_pn_clean.pha' + +plt.figure() +print(cleaned_event) +stdgti_indices = range(52,64) +stdgti_names = np.array(['stdgti' + str(i) for i in range(1,13)]) +for i in range(len(stdgti_indices)): + eventgti = fits.open(cleaned_event)[stdgti_indices[i]].data + gti_sum = sum( [eventgti[j][1] - eventgti[j][0] for j in range(len(eventgti))] ) + for j in range(len(eventgti)): + plt.plot(eventgti[j][0]-eventgti[0][0],i,'rx') + plt.plot(eventgti[j][1]-eventgti[0][0],i,'rx') + print(stdgti_names[i] + ' has sum of ' + str(gti_sum)) + +#plt.xscale('log') + +plt.figure() +gti_indices = range(64,76) +gti_names = np.array(['gti0003','gti0103','gti0203','gti0303','gti0403','gti0503','gti0603','gti0703','gti0803','gti0903','gti1003','gti1103']) +for i in range(len(gti_indices)): + eventgti = fits.open(cleaned_event)[gti_indices[i]].data + gti_sum = sum( [eventgti[j][1] - eventgti[j][0] for j in range(len(eventgti))] ) + for j in range(len(eventgti)): + plt.plot(eventgti[j][0]-eventgti[0][0],i,'rx') + plt.plot(eventgti[j][1]-eventgti[0][0],i,'rx') + print(gti_names[i] + ' has sum of ' + str(gti_sum)) + +#plt.xscale('log') + + +plt.show() + +print(cleaned_spectra) +specgti_indices = [2] + list(range(4,15)) +gti_names = np.array(['gti0003','gti0103','gti0203','gti0303','gti0403','gti0503','gti0603','gti0703','gti0803','gti0903','gti1003','gti1103']) +for i in range(len(gti_indices)): + eventgti = fits.open(cleaned_spectra)[specgti_indices[i]].data + gti_sum = sum( [eventgti[j][1] - eventgti[j][0] for j in range(len(eventgti))] ) + print(gti_names[i] + ' has sum of ' + str(gti_sum)) +""" + +""" +eventfile = '/Volumes/Samsung_T5/NICERsoft_outputs/merged_events/merged000023/merged000023_nicersoft_bary_phase.evt' +gtis = fits.open(eventfile)[2].data +print( sum([gtis[i][1]-gtis[i][0] for i in range(len(gtis))]) ) +""" + +""" +results_file = '/Volumes/Samsung_T5/NICER-data/at2019wey/from_dragonfly/last_line.txt' +contents = open(results_file,'r').read().split('\n') +freq_sig = np.array([contents[i] for i in range(1,len(contents),3)]) +freqs = np.array([np.float(freq_sig[i].split()[0]) for i in range(len(freq_sig))]) +plt.hist(freqs,bins=700) +plt.xlabel('Frequency (Hz)',fontsize=12) +plt.plot() +plt.show() +""" + +""" +obs1_pn = fits.open('/Volumes/Samsung_T5/NGC300_XMMdata/0791010101/PROC/xmm_0791010101_pn_bg.pha')[9].data +print( sum([obs1_pn[i][1]-obs1_pn[i][0] for i in range(len(obs1_pn))]) ) + +obs2_pn = fits.open('/Volumes/Samsung_T5/NGC300_XMMdata/0791010301/PROC/xmm_0791010301_pn_bg.pha')[9].data +print( sum([obs2_pn[i][1]-obs2_pn[i][0] for i in range(len(obs2_pn))]) ) + +obs1_mos1 = fits.open('/Volumes/Samsung_T5/NGC300_XMMdata/0791010101/PROC/xmm_0791010101_mos1_bg.pha')[2].data +print( sum([obs1_mos1[i][1]-obs1_mos1[i][0] for i in range(len(obs1_mos1))]) ) + +obs2_mos1 = fits.open('/Volumes/Samsung_T5/NGC300_XMMdata/0791010301/PROC/xmm_0791010301_mos1_bg.pha')[2].data +print( sum([obs2_mos1[i][1]-obs2_mos1[i][0] for i in range(len(obs2_mos1))]) ) + +obs1_mos2 = fits.open('/Volumes/Samsung_T5/NGC300_XMMdata/0791010101/PROC/xmm_0791010101_mos2_bg.pha')[2].data +print( sum([obs1_mos2[i][1]-obs1_mos2[i][0] for i in range(len(obs1_mos2))]) ) + +obs2_mos2 = fits.open('/Volumes/Samsung_T5/NGC300_XMMdata/0791010301/PROC/xmm_0791010301_mos2_bg.pha')[2].data +print( sum([obs2_mos2[i][1]-obs2_mos2[i][0] for i in range(len(obs2_mos2))]) ) +""" + +""" +folder = '/Volumes/Samsung_T5/n300_ulx_2020/spectra_10d/' +fparkey = open(folder + 'fparkey_jsgrp_10d.txt','w') +jsgrp_files = sorted(glob.glob(folder+'jsgrp_*_cl_*pha')) +for i in range(len(jsgrp_files)): + bg_file = str(pathlib.Path(jsgrp_files[i]).name)[2:16] + 'bg_cl50.pha' + fparkey.write('fparkey ' + bg_file + ' ' + jsgrp_files[i] + ' BACKFILE' + '\n') +fparkey.close() +""" + +""" +folder = '/Volumes/Samsung_T5/n300_ulx_2020/spectra_05d/' +load_data = open(folder+'bgsub_load_all.xcm','w') +jsgrp_files = sorted(glob.glob(folder+'grp_*_bgsub_*pha')) +load_data.write('data ') +for i in range(len(jsgrp_files)): + load_data.write(str(i+1)+':'+str(i+1) + ' ' + str(pathlib.Path(jsgrp_files[i]).name) + ' ') +load_data.write('\n') +load_data.write('ignore **:0.0-0.295,12.01-**' + '\n') +load_data.write('setplot energy' + '\n') +load_data.write('setplot background' + '\n') +load_data.close() +""" + + +""" +spec = '/Volumes/Samsung_T5/NGC300_XMMdata/jsgrp_ngc300x1_mos2_020-085.pha' +counts = sum(fits.open(spec)[1].data['COUNTS']) +print(counts) +""" + +""" +eventfiles = sorted(glob.glob('/Volumes/Samsung_T5/NICER-data/at2019wey/accelsearch_GTIs/2008041401_filt_bary_*E0050-0200.evt')) +exps = [] +for i in range(len(eventfiles)): + exps.append(fits.open(eventfiles[i])[1].header['EXPOSURE']) +exps = np.array(exps) +print(min(exps),max(exps),np.median(exps),np.std(exps)) + +print(len(exps)) +print(len(exps[exps>64])) +print(min(exps[exps>64]),max(exps[exps>64]),np.median(exps[exps>64]),np.std(exps[exps>64])) + +plt.hist(exps,bins=100) +plt.show() +""" + +""" +eventfile = '/Volumes/Samsung_T5/NICERsoft_outputs/merged_events/merged000026/merged000026_nicersoft_bary_center_phase.evt' +times = fits.open(eventfile)[1].data['TIME'] #getting array of times +gtis_data = fits.open(eventfile)[2].data #getting GTIs +T = sum([ gtis_data[i]['STOP']-gtis_data[i]['START'] for i in range(len(gtis_data)) ]) #exposure time +T0_MJD = fits.open(eventfile)[1].header['MJDREFI'] + fits.open(eventfile)[1].header['MJDREFF'] + fits.open(eventfile)[1].header['TSTART']/86400 #SWIFT +gtis_conform = [] +for i in range(len(gtis_data)): + gtis_conform.append([gtis_data[i][0],gtis_data[i][1]]) #conform to the input that Stingray uses + +nbins = 20 +freq = 1/(0.38196674159633911059*86400) +freqdot = 0#-2.3091587842511194363e-11/(0.38196674159633911059*86400)**2 +freqdotdot = 0 + +expos = Lv2_phase.phase_exposure(times[0]-times[0],times[-1]-times[0],1/freq,nbin=nbins,gtis=np.array(gtis_conform)-times[0]) +total_expos = np.array(list(expos) + list(expos)) + +print('Original expos:') +print(expos) + +phase_sr,prof_sr,err_sr = fold_events(times,freq,freqdot,freqdotdot,gtis=np.array(gtis_conform),ref_time=times[0],nbin=nbins) +phase_sr_expo,prof_sr_expo,err_sr_expo = fold_events(times,freq,freqdot,freqdotdot,gtis=np.array(gtis_conform),ref_time=times[0],expocorr=True,nbin=nbins) + +total_phase_sr = list(phase_sr) + list(phase_sr+1) +total_prof_sr = list(prof_sr)*2 +total_err_sr = list(err_sr)*2 + +total_phase_sr_expo = list(phase_sr_expo) + list(phase_sr_expo+1) +total_prof_sr_expo = list(prof_sr_expo)*2 +total_err_sr_expo = list(err_sr_expo)*2 + +plt.figure() +plt.errorbar(x=total_phase_sr,y=total_prof_sr/T,yerr=total_err_sr/T,color='r',drawstyle='steps-mid') +plt.errorbar(x=total_phase_sr_expo,y=total_prof_sr_expo/T,yerr=total_err_sr_expo/T,color='b',drawstyle='steps-mid') +plt.legend(('Folded profile','Exposure-corrected'),loc='best',fontsize=12) +plt.title(str(pathlib.Path(eventfile).name) +', exposure-corrected (using Stingray fold_events)',fontsize=12) +plt.xlabel('Phase',fontsize=12) +plt.ylabel('Counts/s',fontsize=12) +plt.show() +""" + +""" +mergedfile = '/Volumes/Samsung_T5/NICERsoft_outputs/merged_events/merged000026/merged000026_nicersoft_bary_center_phase.evt' +orbphase = fits.open(mergedfile)[1].data['ORBIT_PHASE'] +exposure = fits.open(mergedfile)[1].header['EXPOSURE'] +plt.hist(orbphase,bins=20) +plt.xlabel('Phase',fontsize=12) +plt.ylabel('Counts',fontsize=12) +plt.show() +""" + +"""ad_all +binsize = '10d' +sourcefile = open('/Volumes/Samsung_T5/n300_ulx_2020/spectra_' + binsize + '/3C50x_BACKFILE.go','w') +jsgrp = sorted(glob.glob('/Volumes/Samsung_T5/n300_ulx_2020/spectra_' + binsize + '/jsgrp_58*3C50x*pha')) +for i in range(len(jsgrp)): + mjd = jsgrp[i][-24:-19] + backfile = 'grp_' + mjd + '_' + binsize + '_x_cl50.pha' + sourcefile.write('fparkey ' + backfile + ' ' + str(jsgrp[i]) + '[1] BACKFILE' + '\n') +sourcefile.close() +""" + +""" +cl_files = sorted(glob.glob(Lv0_dirs.NGC300_2020 + 'cl50/pha/cl50_*pha')) +xbg_files = sorted(glob.glob(Lv0_dirs.NGC300_2020 + 'bg_cl50/xpha/xbg_cl50_*pha')) +xbgsub_command = open(Lv0_dirs.NGC300_2020 + 'xbgsub_generate.go','w') +for i in range(len(xbg_files)): #because there are 387 xbg files and 396 cl files + gtino = xbg_files[i][-8:-4] + xbgfile = xbg_files[i] + clfile = Lv0_dirs.NGC300_2020 + 'cl50/pha/cl50_' + gtino + '.pha' + outfile = Lv0_dirs.NGC300_2020 + 'bgsub_cl50/xpha/xbgsub_cl50_' + gtino + '.pha' + + cl_exp = fits.open(clfile)[1].header['EXPOSURE'] + xbg_exp = fits.open(xbgfile)[1].header['EXPOSURE'] + + xbgsub_command.write('mathpha ' + '"(' + "'" + clfile + "'-'" + xbgfile + "')" + '"' + " R outfil='" + outfile + "' exposure=" + str(cl_exp+xbg_exp) + ' errmeth=gaussian properr=yes ncomments=0 areascal=NULL clobber=YES') + xbgsub_command.write('\n') +xbgsub_command.close() +""" + +""" +bgsub_soft, bgsub_soft_err, bgsub_softintens, bgsub_softintens_err = np.genfromtxt(Lv0_dirs.NGC300_2020 + 'soft_intens_bgsub.txt',dtype='float64',usecols=(0,1,2,3),unpack=True) +xbgsub_soft, xbgsub_soft_err, xbgsub_softintens, xbgsub_softintens_err = np.genfromtxt(Lv0_dirs.NGC300_2020 + 'soft_intens_xbgsub.txt',dtype='float64',usecols=(0,1,2,3),unpack=True) + +bgsub_mjd, bgsub_intens, bgsub_intens_err = np.genfromtxt(Lv0_dirs.NGC300_2020 + 'time_intens_bgsub.txt',dtype='float64',usecols=(0,1,2),unpack=True) +xbgsub_mjd, xbgsub_intens, xbgsub_intens_err = np.genfromtxt(Lv0_dirs.NGC300_2020 + 'time_intens_xbgsub.txt',dtype='float64',usecols=(0,1,2),unpack=True) + +plt.figure(1) +plt.errorbar(x=bgsub_soft,y=bgsub_softintens,xerr=bgsub_soft_err,yerr=bgsub_softintens_err,color='r',fmt='x',label='bgsub') +plt.errorbar(x=xbgsub_soft,y=xbgsub_softintens,xerr=xbgsub_soft_err,yerr=xbgsub_softintens_err,color='b',fmt='x',label='xbgsub') +plt.legend(('bgsub','xbgsub'),loc='best',fontsize=12) +plt.axhline(y=0,lw=0.5,alpha=0.5) +plt.xlabel('Soft Color: (1-2 keV)/(0.4-1 keV)',fontsize=12) +plt.ylabel('Intensity in counts/s (0.4-12 keV)',fontsize=12) + +plt.figure(2) +plt.errorbar(x=bgsub_mjd,y=bgsub_intens,yerr=bgsub_intens_err,color='r',fmt='x',label='bgsub') +plt.errorbar(x=xbgsub_mjd,y=xbgsub_intens,yerr=xbgsub_intens_err,color='b',fmt='x',label='xbgsub') +plt.legend(('bgsub','xbgsub'),loc='best',fontsize=12) +plt.axhline(y=0,lw=0.5,alpha=0.5) +plt.xlabel('Time (MJD)',fontsize=12) +plt.ylabel('Intensity in counts/s (0.4-12 keV)',fontsize=12) + +plt.show() +""" + +""" +plt.figure() + +init_back_array = sorted(glob.glob(Lv0_dirs.NGC300_2020 + 'bg_cl50/pha/*.pha')) +Porb = (1/8.4712e-6)/86400 +T0 = 58239.3498 +for i in range(len(init_back_array)): + init_back = init_back_array[i] + gti_no = init_back[-8:-4] + init_cl = Lv0_dirs.NGC300_2020 + 'cl50/pha/cl50_' + gti_no + '.pha' + + backfile = str(pathlib.Path(init_back).name) + comb_spec_folder = Lv0_dirs.NGC300_2020 + 'bg_cl50/xpha/' + + tstart = fits.open(init_cl)[1].header['TSTART'] + tstop = fits.open(init_cl)[1].header['TSTOP'] + centroid_t = fits.open(init_cl)[1].header['MJDREFI'] + fits.open(init_cl)[1].header['MJDREFF'] + ((tstart+tstop)/2)/86400 + exp_time = fits.open(init_cl)[1].header['EXPOSURE'] + +#first assuming the timing model, determine how much time (in d) has passed + orb_phase = (centroid_t-T0)%Porb/Porb + plt.errorbar(x=orb_phase,xerr=exp_time/(Porb*86400),y=0.0012 + (0.0003-0.0012)/380*i) + +a,b,c = np.genfromtxt(Lv0_dirs.NGC300_2020 + 'swift_shifted_folded_curve.txt',usecols=(0,1,2),unpack=True) +plt.errorbar(x=a,y=b,yerr=c,color='r',drawstyle='steps-mid') +plt.xlabel('Phase') +plt.ylabel('Rate (Counts/s)') +plt.axvline(x=0.2,lw=0.5,alpha=0.5,color='c') +plt.axvline(x=0.85,lw=0.5,alpha=0.5,color='c') +plt.annotate('off-eclipse',(0.4,0.0006)) + +plt.show() +""" + +""" +orig_file = fits.open('/Volumes/Samsung_T5/NICER-data/at2019wey/2008041401_filt_bary.evt')[1].data['TIME'] +first_file = fits.open('/Volumes/Samsung_T5/NICERsoft_outputs/merged_events/merged000027/merged000027_nicersoft_bary.evt')[1].data['TIME'] +mjdrefi = fits.open('/Volumes/Samsung_T5/NICER-data/at2019wey/2008041401_filt_bary.evt')[1].header['MJDREFI'] +mjdreff = fits.open('/Volumes/Samsung_T5/NICER-data/at2019wey/2008041401_filt_bary.evt')[1].header['MJDREFF'] + +print(mjdrefi + mjdreff + orig_file[-1]/86400) +print(mjdrefi + mjdreff + first_file[0]/86400) +""" + +""" +gtis = sorted(glob.glob('/Volumes/Samsung_T5/NICER-data/at2019wey/gtis/00064s_*gti')) +putting = [] +for i in range(len(gtis)): + gtiname = str(pathlib.Path(gtis[i]).name) + if float(gtiname[-10:-4]) > 73450: + putting.append(gtiname) + +print(len(putting)) +print(putting[0],putting[-1]) +""" + +""" +jsgrp = sorted(glob.glob('/Volumes/Samsung_T5/n300_ulx_2020/spectra_05d/jsgrp_58*_3C50_*pha')) +for i in range(len(jsgrp)): + input = jsgrp[i] + output = jsgrp[i][:-13] + '3C50xs_cl50.pha' + subprocess.run(['cp',input,output]) +""" + +""" +fparkey = open(Lv0_dirs.NGC300_2020 + 'spectra_05d/3C50xs_exposure.go','w') +spectra = sorted(glob.glob(Lv0_dirs.NGC300_2020 + 'spectra_05d/jsgrp_*_05d_3C50xs_cl50.pha')) +for i in range(len(spectra)): + mjd = str(pathlib.Path(spectra[i]).name)[-25:-20] + bg_file = Lv0_dirs.NGC300_2020 + 'spectra_05d/grp_' + mjd + '_05d_xsbg_cl50.pha' + exposure = fits.open(spectra[i])[1].header['EXPOSURE'] + fparkey.write('fparkey ' + str(exposure) + ' ' + bg_file + ' EXPOSURE' + '\n') +fparkey.close() +""" + +""" +period = np.array([1.37,0.42,1.1,31.6]) +pdot = np.array([-2e-10,-3.5e-11,-8e-10,-5.56e-7]) +freq = 1/period #order of M82 X-2, NGC 7793 P13, NGC 5907 ULX 1, NGC 300 ULX-1 +fdot = -pdot/period**2 +print(freq) +print(fdot) + +plt.plot(freq,fdot,'x') +plt.yscale('log') +plt.xscale('log') +plt.xlabel('Frequency (Hz)',fontsize=12) +plt.ylabel('Frequency Derivative (Hz/s)',fontsize=12) +plt.xlim([0,1000]) +plt.ylim([1e-18,1e-7]) +plt.show() +""" + +""" +xs_mjd,xs_s1,xs_s2,xs_a,xs_b,xs_c,xs_d,xs_in = np.genfromtxt(Lv0_dirs.NGC300_2020 + 'n300_ulx.xsbgsub_cl50_g2020norm_05d.fffphot',usecols=(0,1,2,3,4,5,6,7),unpack=True) +err_mjd,err_s1,err_s2,err_a,err_b,err_c,err_d,err_in = np.genfromtxt(Lv0_dirs.NGC300_2020 + 'n300_ulx.xbgsub_cl50_g2020err_norm_05d.fffphot',usecols=(0,1,2,3,4,5,6,7),unpack=True) +for i in range(len(xs_mjd)): + print(xs_mjd[i],round(xs_s1[i]+err_s1[i],4),round(xs_s2[i]+err_s2[i],4),round(xs_a[i]+err_a[i],4),round(xs_b[i]+err_b[i],4),round(xs_c[i]+err_c[i],4),round(xs_d[i]+err_d[i],4),round(xs_in[i]+err_in[i],4)) +""" + +""" +eventfile = Lv0_dirs.NICER_DATADIR + 'at2019wey/final.evt' +fitsfile = fits.open(eventfile)[1] +print(fitsfile.header['MJDREFI'] + fitsfile.header['MJDREFF'] + fitsfile.data['TIME'][-1]/86400) +""" + +""" +gtis = sorted(glob.glob(Lv0_dirs.NICER_DATADIR + 'at2019wey/accelsearch_GTIs/GTI*gti')) +gti_len = [] +for i in range(len(gtis)): + gti = fits.open(gtis[i])[1].data + gti_len.append(gti['STOP'][0]-gti['START'][0]) + +print(np.min(gti_len),np.max(gti_len)) +gti_len = np.array(gti_len) +print(sum(gti_len)) +filtered_gtis = gti_len[gti_len>64] +print(len(gti_len)) +print(len(filtered_gtis)) +print(np.median(filtered_gtis)) +""" + +""" +from pint.eventstats import sf_z2m,z2m,sig2sigma +z_vals = 144.37 +probs = sf_z2m(z_vals) +print(probs) +significances = sig2sigma(probs) +print(significances) +""" + +mjd = np.array([59149.0232,59149.0877,59149.2968,59149.6840,59149.7330,59150.3138,59150.3784,59150.7193]) +freqs = np.array([376.043646,376.056458,376.056901,376.045625,376.050446,376.041895,376.045996,376.05253]) +plt.plot(mjd,freqs,'rx-') +plt.show() timeend = time.time() diff --git a/test_timing.py b/test_timing.py new file mode 100644 index 0000000..6601e05 --- /dev/null +++ b/test_timing.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +Created on Wed Mar 18 7:29am 2019 + +Program for timing + +""" +from __future__ import division, print_function +import numpy as np +from astropy.io import fits +import Lv0_dirs,Lv1_data_gtis,Lv2_mkdir +from PyAstronomy.pyasl import foldAt +from scipy import stats +from scipy.optimize import curve_fit +from tqdm import tqdm +import matplotlib.pyplot as plt +import time +import pathlib + +Lv0_dirs.global_par() + +def linear_f(t,phi0,f0,T0): + return (phi0 + f0*(t-T0))%1 + +def get_phases(eventfile,f_pulse,shift): + """ + Folding the time series by the pulse frequency to obtain phase values + + eventfile - path to the event file. + f_pulse - the frequency of the pulse + shift - how much to shift the pulse by in the phase axis. + """ + raw_times = fits.open(eventfile)[1].data['TIME'] + times = raw_times - raw_times[0] + + period = 1/f_pulse + phases = foldAt(times,period,T0=shift*period) + + return phases + +def fit_to_linear(eventfile,f_pulse,shift,T0): + """ + Fitting the phases to a linear phase model + + eventfile - path to the event file. + f_pulse - the frequency of the pulse + shift - how much to shift the pulse by in the phase axis. + T0 - some reference T0 time + """ + raw_times = fits.open(eventfile)[1].data['TIME'] + times = raw_times - raw_times[0] + + phases = get_phases(eventfile,f_pulse,shift) + popt,pcov = curve_fit(linear_f,times,phases,p0=[shift,f_pulse,T0],bounds=([0.3,0.2085,40],[0.5,0.2095,60])) + + return popt,np.sqrt(np.diag(pcov)) + +if __name__ == "__main__": + eventfile = Lv0_dirs.NICERSOFT_DATADIR + '0034070101_pipe/ni0034070101_nicersoft_bary.evt' + raw_times = fits.open(eventfile)[1].data['TIME'] + times = raw_times - raw_times[0] + + phases = get_phases(eventfile,0.20879991,0.35705417) + + #phase_bins = np.linspace(0,1,21) + #summed_profile, bin_edges, binnumber = stats.binned_statistic(phases,np.ones(len(phases)),statistic='sum',bins=phase_bins) + + vars,unc = fit_to_linear(eventfile,0.2088,0.366,50) + + print(vars) + #plt.plot(times,linear_f(times,vars[0],vars[1],vars[2]),'rx') + resid_phases = phases - linear_f(times,vars[0],vars[1],vars[2]) + + resid_phases_plot = resid_phases[resid_phases>=-0.5] + times_plot = times[resid_phases>=-0.5] + plt.plot(times_plot,resid_phases_plot) + + #plt.plot(phase_bins[:-1],summed_profile,'rx') + plt.show() diff --git a/xte1739_1segs_128_5.701 b/xte1739_1segs_128_5.701 new file mode 100644 index 0000000..a46ff44 --- /dev/null +++ b/xte1739_1segs_128_5.701 @@ -0,0 +1,7 @@ +SIMPLE = T / file does conform to FITS standard BITPIX = 8 / number of bits per data pixel NAXIS = 0 / number of data axes EXTEND = T / FITS dataset may contain extensions COMMENT FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H END XTENSION= 'BINTABLE' / binary table extension BITPIX = 8 / 8-bit bytes NAXIS = 2 / 2-dimensional binary table NAXIS1 = 16 / width of table in bytes NAXIS2 = 128 / number of rows in table PCOUNT = 0 / size of special data area GCOUNT = 1 / one data group (required keyword) TFIELDS = 3 / number of fields in each row TTYPE1 = 'PERIOD ' / label for field 1 TFORM1 = 'D ' / data format of field: 8-byte DOUBLE TUNIT1 = 's ' / physical unit of field TTYPE2 = 'CHISQRD1' / label for field 2 TFORM2 = 'E ' / data format of field: 4-byte REAL TTYPE3 = 'ERROR1 ' / label for field 3 TFORM3 = 'E ' / data format of field: 4-byte REAL EXTNAME = 'RESULTS ' / name of this binary table extension DATE = '2020-02-17T17:06:20' / file creation date (YYYY-MM-DDThh:mm:ss UT) CREATOR = 'efsearch 1.1 (xronos5.22)' / Name of XRONOS program that created thisHDUCLASS= 'OGIP ' HDUCLAS1= 'TEMPORALDATA' HDUCLAS2= 'FOLDING SEARCH' HDUCLAS3= 'RESULTS ' CONTENT = 'XRONOS OUTPUT' ORIGIN = 'HEASARC/GSFC' OBJECT = 'XTE_J1739-285' TIMVERSN= 'OGIP/93-003' TSTARTI = 18892 / Start time for this extension TSTARTF = 0.6534693898029218 / Start time for this extension TSTOPI = 18893 / Stop time for this extension TSTOPF = 0.8630863826256245 / Stop time for this extension TIMEUNIT= 'd ' / Units for header timing keywords TIMEZERI= 18892 / Zero-point offset for TIME column TIMEZERF= 0.6534714517947577 / Zero-point offset for TIME column COMMENT TIMESYS keyword is not currently set. If the input lightcurve COMMENT contains the header keyword MJDREF, the time in the xronos COMMENT output is in TJD (JD-2440000.5) AVRGE_1 = 3.08325939E+01 / Avg, count/s in interval FREXP_1 = 1.00000000E+00 / Avg. Frac exposure in frame VAROB_1 = 7.75447935E-02 / observed variance VAREX_1 = 1.17695481E-01 / expected variance THRDM_1 = 2.12806407E-02 / third moment MININ_1 = 3.03981781E+01 / Minimun Intensity MAXIN_1 = 3.15407219E+01 / Maximun Intensity EXVAR_1 = -4.01506871E-02 / excess of variance CHI2_1 = 1.05937414E+01 / Chi squared RMS_1 = -6.49884855E-03 / RMS variability AVRGE_E1= 8.85797143E-02 / Error Avg count/s VAROB_E1= 2.83153560E-02 / Error observed variance VAREX_E1= 4.29763123E-02 / Error expected variance CHI2_E1 = 5.47722578E+00 / Error Chi2 RMS_E1 = 2.29158229E-03 / RMS variability END @ÇE8ï4ÖA)÷@hæ@Ç_oÒòA‰ƒÝ@¼Là@Çy¦µ A-‰@D ì@Ç“Ý—ö+A"L»@^<ò@Ç®záGA¡ªx@Ý^Â@ÇÈK]ÌcA›|%@Ôè@Çâ‚@·€A“þ«@ʦu@Çü¹#¢œA1V°@rÔ·@Èð¸A¤ë @áÒÐ@È1&éxÔA§"@äÛ:@ÈK]ÌcñA¥Üy@ãf@Èe”¯O A=ž@í¥@ÈË’:)AvÇ¢@¨õg@Èšu%EA—Ý«@Ïóq@È´9XbA @ÁÃ2@ÈÎp:û~AfÏE@žJ@Èè§æš@ðÜ@$è@ÉÞѶA3[Å@u˜Â@Éã¼ÓAH¤z@‰^Û@É7KƧïA3Ã@v&Ë@ÉQ‚©“ AÃ;'Aªc@Ék¹Œ~(AÍM„A ¬@É…ðoiDBÒüAM'º@É 'RT`Ašâé@Ô?@ɺ^5?|AãAn­@ÉÔ•*™AñµA%|µ@ÉîËûµAÏžåA%î@Ê ÞÑAk#í@ ýV@Ê#9ÀëíA¦êÖ@äœ@Ê=p£× +Aq„i@¥[@ÊW§†Â&A%Üê@c@ÊqÞi­BA/ @oª•@ÊŒL˜^A…‰¯@¶Ú­@ʦL/ƒ{A­îu@î*]@ÊÀƒn—A„Ú;@µên@ÊÚ¹õY³A›‚@9°+@ÊôðØDÏAÄ…XAŒt@Ë'»/ìAuR±@§ö@Ë)^žA‘Š@ÇI£@ËC•$A”gÑ@Ë6p@Ë]Ìcñ@A¤¨¿@áx@ËxFÜ]A»8îA.²@Ë’:)ÇyA3ÊÖ@v0Ø@ˬq ²•A“Lô@ɳ@ËƧï²A{#ê@«ñ«@ËàÞÒˆÎA”ëi@Ëê¢@ËûµsêA¡Æ~@Ý…"@ÌL˜_AÑ—ñA·@Ì/ƒ{J#AQe@$÷@ÌIº^5?A•7Æ@ÌS2@ÌcñA [AϬSA/ @Ì~($ wAK@‹ =@̘_ö”A¢[L@ÞPä@̲•éá°AꢖA ¤È@ÌÌÌÌÌÌAÄ;äAZ*@Ì篷èA‘û!@Çä‡@Í:’£@ü Í@,‘Ì@ÍquŽ!A“e¢@ÉÔè@Í5¨Xy=Ajû{@ á¥@ÍOß;dYAE¨@†ò®@ÍjOvA°µ¿@ñøV@Í„M:’AžVn@ØÐ@Ížƒä%®A®éQ@ïÞ@͸ºÇËA§O@åÏ@ÍÒñ©ûçAR!b@ÝÐ@Íí(ŒçA“/@ÉŠ/@Î_oÒA¶o”@ùσ@Î!–R½<@¿ ø@Û`@Î;Í5¨XAŠON@½cs@ÎV“tA`åµ@™ú@Îp:û~A„Ž@µ‚,@ΊqÞi­AI’@‰«š@Τ¨ÁTÉAÊA +aW@ξߤ?åAk˜@ éð@ÎÙ‡+Aeâ@,N@ÎóMjAE“§@‡E†@Ï „M:A°NŠ@ñk@Ï'»/ìVAW–B@“š0@ÏAò×rB ‚ÐA