def _make_xselect_commands(infile, outfile, elow, ehigh, usrgti=False): ''' Helper script to generate the xselect commands to make an image in a given NuSTAR range ''' xsel = open("xsel.xco", "w") xsel.write("session1\n") xsel.write("read events \n") evdir = os.path.dirname(infile) xsel.write(f'{evdir} \n ') evfile = os.path.basename(infile) xsel.write(f'{evfile} \n ') xsel.write('yes \n') pi_low = energy_to_chan(elow) pi_high = energy_to_chan(ehigh) if usrgti is not False: xsel.write(f'filter time \n') xsel.write('file \n') xsel.write(f'{usrgti}\n') xsel.write('extract events\n') xsel.write('filter pha_cutoff {} {} \n'.format(pi_low, pi_high)) xsel.write('set xybinsize 1\n') xsel.write("extract image\n") xsel.write("save image\n") xsel.write("%s \n" % outfile) xsel.write('exit\n') xsel.write('n \n') xsel.close() return 'xsel.xco'
def _make_xselect_commands_det1(infile, outfile, elow, ehigh): ''' Helper script to generate the xselect commands to make an image in a given NuSTAR energy range ''' import glob for oldfile in glob.glob("session1*"): os.system(f"rm {oldfile}") xsel = open("xsel.xco", "w") xsel.write("session1\n") xsel.write("read events \n") evdir = os.path.dirname(infile) xsel.write(f'{evdir} \n ') evfile = os.path.basename(infile) xsel.write(f'{evfile} \n ') xsel.write('yes \n') xsel.write('set xyname\n') xsel.write('DET1X\n') xsel.write('DET1Y\n') pi_low = energy_to_chan(elow) pi_high = energy_to_chan(ehigh) xsel.write('filter pha_cutoff {} {} \n'.format(pi_low, pi_high)) xsel.write('set xybinsize 1\n') xsel.write("extract image\n") xsel.write("save image\n") xsel.write("%s \n" % outfile) xsel.write('exit\n') xsel.write('n \n') xsel.close() return 'xsel.xco'
def make_det1_lightcurve(infile, mod, obs, time_bin=100 * u.s, mode='01', elow=3, ehigh=20, stemout=False, gtifile=False): ''' Generate a script to run nuproducts to make a lightcurve using the whole FoV and turning off all vignetting and PSF effects. Assumes that infile has already been filtered using extract_det1_events(). Parameters ---------- infile: str Full path to the input event file. This should be pre-filtered by by extract_det1_events mod: str 'A' or 'B' obs: nustar_gen.info.Observation Observation meta data Other Parameters ------------------- elow: float, optional, default = 3 keV Low-energy bound ehigh: float, optional, default is 20 keV High-energy bound mode: str, optional, default is '01' Optional. Used to specify stemout if you're doing mode06 analysis and want to specify output names that are more complicated. gtifile: str Path to a GTI file. If this is set, then this is passed to nuproducts. stemout: str, optional Use the specified stemout string when calling nuproducts. Otherwise uses the default value. ''' from astropy.io.fits import getheader # Make sure environment is set up properly _check_environment() # Check to see that all files exist: assert os.path.isfile( infile), 'make_det1_lightcurve: infile does not exist!' # evdir = os.path.dirname(infile) evdir = obs.evdir seqid = obs.seqid # seqid = os.path.basename(os.path.dirname(evdir)) outdir = obs.out_path # if outpath is None: # outdir = evdir # else: # outdir = outpath hdr = getheader(infile) ra = hdr['RA_OBJ'] dec = hdr['DEC_OBJ'] time_bin = int((time_bin.to(u.s)).value) if stemout is False: stemout = f'nu{seqid}{mod}{mode}_full_FoV_{elow}to{ehigh}_{time_bin}s' lc_script = f'{outdir}/rundet1lc_{stemout}.sh' pi_low = energy_to_chan(elow) pi_high = energy_to_chan(ehigh) with open(lc_script, 'w') as f: f.write('nuproducts phafile=NONE bkgphafile=NONE imagefile=NONE ') f.write(f'infile={infile} ') f.write('runmkarf=no runmkrmf=no ') f.write(f'indir={evdir} outdir={outdir} instrument=FPM{mod} ') f.write(f'steminputs=nu{seqid} stemout={stemout} ') f.write(f'pilow={pi_low} pihigh={pi_high} ') f.write(f'bkgextract=no ') f.write(f'binsize={time_bin} ') f.write( f'srcra={ra} srcdec={dec} srcregionfile=DEFAULT srcradius=299 ') # Turn off all of the time-dependent corrections for the pointing here f.write(f'lcpsfflag=no lcexpoflag=no lcvignflag=no ') if (gtifile != False): f.write(f'usrgtifile={gtifile} ') f.write('clobber=yes') os.chmod(lc_script, stat.S_IRWXG + stat.S_IRWXU) return lc_script
def make_lightcurve(infile, mod, src_reg, barycorr=False, time_bin=100 * u.s, mode='01', bgd_reg='None', outpath='None', elow=3, ehigh=20): ''' Generate a script to run nuproducts Parameters ---------- infile: str Full path to the input event file. mod: str 'A' or 'B' src_reg: str Full path to source region. Other Parameters ------------------- bgd_reg: str If not 'None', then must be the full path to the background region file barycorr: bool Default is 'False'. If 'True', then queries the infile for the OBJ J2000 coordinates and uses these for the barycenter correction. elow: float Low-eneryg bound. Default is 3 keV. ehigh: float High-energy bound. Default is 20 keV. outpath: str Optional. Default is to put the lightcurves in the same location as infile mode: str Optional. Used primarily if you're doing mode06 analysis and need to specify output names that are more complicated. ''' from astropy.io.fits import getheader # Make sure environment is set up properly _check_environment() # Check to see that all files exist: assert os.path.isfile(infile), 'make_lightcurve: infile does not exist!' assert os.path.isfile(src_reg), 'make_lightcurve: src_reg does not exist!' if bgd_reg != 'None': assert os.path.isfile( bgd_reg), 'make_lightcurve: bgd_reg does not exist!' bkgextract = 'yes' else: bkgextract = 'no' reg_base = os.path.basename(src_reg) reg_base = os.path.splitext(reg_base)[0] evdir = os.path.dirname(infile) seqid = os.path.basename(os.path.dirname(evdir)) if outpath == 'None': outdir = evdir else: outdir = outpath try: os.makedirs(outdir) except FileExistsError: # directory already exists pass time_bin = (time_bin.to(u.s)).value stemout = f'nu{seqid}{mod}{mode}_{reg_base}_{elow}to{ehigh}_{time_bin:3.4}s' lc_script = outdir + f'/runlc_{stemout}.sh' pi_low = energy_to_chan(elow) pi_high = energy_to_chan(ehigh) with open(lc_script, 'w') as f: f.write('nuproducts phafile=NONE bkgphafile=NONE imagefile=NONE ') f.write(f'runmkarf=no runmkrmf=no pilow={pi_low} pihigh={pi_high} ') f.write(f'indir={evdir} outdir={outdir} instrument=FPM{mod} ') f.write(f'steminputs=nu{seqid} stemout={stemout} ') f.write(f'srcregionfile={src_reg} ') if bkgextract == 'no': f.write(f'bkgextract=no ') else: f.write(f'bkgextract=yes bkgregionfile={bgd_reg} ') f.write(f'binsize={time_bin} ') if barycorr: attorb = evdir + f'/nu{seqid}{mod}.attorb' hdr = getheader(infile) ra = hdr['RA_OBJ'] dec = hdr['DEC_OBJ'] f.write(f'barycorr=yes srcra_barycorr={ra} srcdec_barycorr={dec} ') f.write(f'orbitfile={attorb} ') f.write('clobber=yes') os.chmod(lc_script, stat.S_IRWXG + stat.S_IRWXU) return lc_script
def make_det1_lightcurve(infile, mod, barycorr=False, time_bin=100 * u.s, mode='01', outpath=None, elow=3, ehigh=20): ''' Generate a script to run nuproducts to make a lightcurve using the whole FoV and turning off all vignetting and PSF effects. Assumes that infile has already been filtered using extract_det1_events(). Parameters ---------- infile: str Full path to the input event file. mod: str 'A' or 'B' Optional Parameters ------------------- bgd_reg: str If not 'None', then must be the full path to the background region file barycorr: bool Default is 'False'. If 'True', then queries the infile for the OBJ J2000 coordinates and uses these for the barycenter correction. elow: float Low-eneryg bound. Default is 3 keV. ehigh: float High-energy bound. Default is 20 keV. outpath: str Optional. Default is to put the lightcurves in the same location as infile mode: str Optional. Used primarily if you're doing mode06 analysis and need to specify output names that are more complicated. ''' from astropy.io.fits import getheader # Make sure environment is set up properly _check_environment() # Check to see that all files exist: assert os.path.isfile( infile), 'make_det1_lightcurve: infile does not exist!' evdir = os.path.dirname(infile) seqid = os.path.basename(os.path.dirname(evdir)) if outpath is None: outdir = evdir else: outdir = outpath hdr = getheader(infile) ra = hdr['RA_OBJ'] dec = hdr['DEC_OBJ'] time_bin = int((time_bin.to(u.s)).value) stemout = f'nu{seqid}{mod}{mode}_full_FoV_{elow}to{ehigh}_{time_bin}s' lc_script = f'{outdir}/rundet1lc_{stemout}.sh' pi_low = energy_to_chan(elow) pi_high = energy_to_chan(ehigh) with open(lc_script, 'w') as f: f.write('nuproducts phafile=NONE bkgphafile=NONE imagefile=NONE ') f.write(f'infile={infile} ') f.write('runmkarf=no runmkrmf=no ') f.write(f'indir={evdir} outdir={outdir} instrument=FPM{mod} ') f.write(f'steminputs=nu{seqid} stemout={stemout} ') f.write(f'pilow={pi_low} pihigh={pi_high} ') f.write(f'bkgextract=no ') f.write(f'binsize={time_bin} ') f.write( f'srcra={ra} srcdec={dec} srcregionfile=DEFAULT srcradius=299 ') # Turn off all of the time-dependent corrections for the pointing here f.write(f'lcpsfflag=no lcexpoflag=no lcvignflag=no ') if barycorr: attorb = evdir + f'/nu{seqid}{mod}.attorb' f.write(f'barycorr=yes srcra_barycorr={ra} srcdec_barycorr={dec} ') f.write(f'orbitfile={attorb} ') f.write('clobber=yes') os.chmod(lc_script, stat.S_IRWXG + stat.S_IRWXU) return lc_script
def make_straylight_arf(det1im, regfile, filt_file, mod, obs): ''' Produces an ARF for a given observation. Currently uses counts-weighting to determine the contribution of the detabs parameters for each detector. SHOULD PROBABLY BE MOVED TO WRAPPERS OR SOMETHING? Parameters ---------- det1im : str Full path to the DET1 exposure image file. regfil : str Full path to the region file, assumed to be a ds9 region file in "IMAGE" coordinates filt_file : str Full path to the DET1 screened event file (i.e. output of nustar_gen.wrappers.extract_det1_events() ). This used to scale the ARF by the number of 3--10 keV counts on each detector. mod : str 'A' or 'B' obs: nustar_gen.info.Observation Observation meta data Returns ------- out_arf: string Full path to the new arf file ''' from astropy.io import fits import glob from nustar_gen import io from nustar_gen.utils import energy_to_chan # Check to see that all files exist: assert os.path.isfile(det1im), \ f'straylight_area: DET1 exposure map not found: {det1im}' assert os.path.isfile(regfile), \ f'straylight_area: Region file not found: {regfile}' assert os.path.isfile(filt_file), \ f'straylight_area: Event file not found: {evf}' outdir = obs.out_path out_arf = outdir+'/'+os.path.splitext(os.path.basename(filt_file))[0]+'.arf' # Get the effective are target: area = straylight_area(det1im, regfile, filt_file) # Use counts relative scaling to blend the ARFs: ev_hdu = fits.open(filt_file) evts = ev_hdu[1].data scale_evts = evts[ (evts['PI']>energy_to_chan(3.)) & (evts['PI'] < energy_to_chan(10.) )] dethist, detedges = np.histogram(scale_evts['DET_ID'], range=[0, 3],bins = 4) totcts = dethist.sum() scale = [ float(x) / totcts for x in dethist] ev_hdu.close() # Load the base ARF file: arf_file = io.find_arf_template() arf_hdu = fits.open(arf_file) arf = arf_hdu[1].data arf_header = arf_hdu[1].header # Trim header arf_hdu[1].header = arf_header[0:26] # Mock up an ARF that's flat with just the detector area arf['SPECRESP'] = [area.value for x in arf['SPECRESP']] caldb = os.environ['CALDB'] detabs_files = glob.glob(caldb+f'/**/nu{mod}detabs*', recursive=True) use = len(detabs_files)-1 detabs_hdu = fits.open(detabs_files[use]) for detind, isc in enumerate(scale): detabs = detabs_hdu[detind+1].data if detind == 0: arfabs = detabs['DETABS'] * isc else: arfabs += detabs['DETABS'] * isc arf['SPECRESP'] *= arfabs detabs_hdu.close() be_file = io.find_be_arf() be_arf = fits.getdata(be_file, 1) arf['SPECRESP'] *= be_arf['SPECRESP'] arf_hdu.writeto(out_arf, overwrite=True) arf_hdu.close() return out_arf