def SNRcalc(self, pulsar, pop, accelsearch=False, jerksearch=False, rratssearch=False): """Calculate the S/N ratio of a given pulsar in the survey""" # if not in region, S/N = 0 # if we have a list of pointings, use this bit of code # haven't tested yet, but presumably a lot slower # (loops over the list of pointings....) if rratssearch: if pulsar.br is None: print "Population doesn't have a burst rate" print "Use populate with --singlepulse" sys.exit() pulsar.pop_time = np.random.poisson(pulsar.br * self.tobs) if pulsar.dead: return 0. # otherwise check if pulsar is in entire region if self.inRegion(pulsar): # If pointing list is provided, check how close nearest # pointing is if self.pointingslist is not None: # convert offset from degree to arcmin offset = self.inPointing_new(pulsar) * 60.0 else: # calculate offset as a random offset within FWHM/2 offset = self.fwhm * math.sqrt(random.random()) / 2.0 else: return -2 if rratssearch == True and pulsar.pop_time < 1.0: return -3 # Get degfac depending on self.gainpat if self.gainpat == 'airy': conv = math.pi / (60 * 180.) # Conversion arcmins -> radians eff_diam = 3.0e8 / (self.freq * self.fwhm * conv * 1.0e6 ) # Also MHz -> Hz a = eff_diam / 2. # Effective radius of telescope lamda = 3.0e8 / (self.freq * 1.0e6) # Obs. wavelength kasin = (2 * math.pi * a / lamda) * np.sin(offset * conv) degfac = 4 * (j1(kasin) / kasin)**2 else: degfac = math.exp(-2.7726 * offset * offset / (self.fwhm * self.fwhm)) # calc dispersion smearing across single channel tdm = self._dmsmear(pulsar) # calculate bhat et al scattering time (inherited from GalacticOps) # in units of ms if hasattr(pulsar, 't_scatter'): tscat = go.scale_bhat(pulsar.t_scatter, self.freq, pulsar.scindex) else: tscat = go.scatter_bhat(pulsar.dm, pulsar.scindex, self.freq) # Calculate the effective width width_ms = pulsar.width_degree * pulsar.period / 360.0 weff_ms = math.sqrt(width_ms**2 + self.tsamp**2 + tdm**2 + tscat**2) # calculate duty cycle (period is in ms) delta = weff_ms / pulsar.period # if pulse is smeared out, return -1.0 if delta > 1.0: #and pulsar.pop_time >= 1.0: # print width_ms, self.tsamp, tdm, tscat return -1 # radiometer signal to noise if rratssearch == False: sig_to_noise = rad.calcSNR(self.calcflux(pulsar, pop.ref_freq), self.beta, self.tsys, self.tskypy(pulsar), self.gain, self.npol, self.tobs, self.bw, delta) else: #find number of times the pulse will pop up! #pop_time=int(pulsar.br*self.tobs) if pulsar.pop_time >= 1.0: pulse_snr = np.zeros(pulsar.pop_time) fluxes = np.zeros(pulsar.pop_time) lums = [] mu = math.log10(pulsar.lum_inj_mu) sig = mu / pulsar.lum_sig # Draw from luminosity dist. for burst_times in range(pulsar.pop_time): pulsar.lum_1400 = dist.drawlnorm(mu, sig) lums.append(pulsar.lum_1400) flux = self.calcflux(pulsar, pop.ref_freq) fluxes[burst_times] = flux pulse_snr[burst_times] = rad.single_pulse_snr( self.npol, self.bw, weff_ms * 1e-3, (self.tsys + self.tskypy(pulsar)), self.gain, flux, self.beta) pulsar.lum_1400 = np.max(lums) sig_to_noise = np.max(pulse_snr) if sig_to_noise >= self.SNRlimit: pulsar.det_pulses = fluxes[pulse_snr >= self.SNRlimit] pulsar.det_nos = len(pulsar.det_pulses) else: pulsar.det_pulses = None pulsar.det_nos = 0 else: return -3 # account for aperture array, if needed if self.AA and sig_to_noise > 0.0: sig_to_noise *= self._AA_factor(pulsar) # account for binary motion if pulsar.is_binary: # print "the pulsar is a binary!" if jerksearch: print "jerk" gamma = degradation.gamma3(pulsar, self.tobs, 1) elif accelsearch: print "accel" gamma = degaadation.gamma2(pulsar, self.tobs, 1) else: print "norm" gamma = degradation.gamma1(pulsar, self.tobs, 1) print "gamma harm1 = ", gamma gamma = degradation.gamma1(pulsar, self.tobs, 2) print "gamma harm2 = ", gamma gamma = degradation.gamma1(pulsar, self.tobs, 3) print "gamma harm3 = ", gamma gamma = degradation.gamma1(pulsar, self.tobs, 4) print "gamma harm4 = ", gamma # return the S/N accounting for beam offset return sig_to_noise * degfac
def SNRcalc(self, pulsar, pop, accelsearch=False, jerksearch=False): """Calculate the S/N ratio of a given pulsar in the survey""" # if not in region, S/N = 0 # if we have a list of pointings, use this bit of code # haven't tested yet, but presumably a lot slower # (loops over the list of pointings....) if pulsar.dead: return 0. # otherwise check if pulsar is in entire region if self.inRegion(pulsar): # If pointing list is provided, check how close nearest # pointing is if self.pointingslist is not None: # convert offset from degree to arcmin offset = self.inPointing_new(pulsar) * 60.0 else: # calculate offset as a random offset within FWHM/2 offset = self.fwhm * math.sqrt(random.random()) / 2.0 else: return -2 # Get degfac depending on self.gainpat if self.gainpat == 'airy': conv = math.pi/(60*180.) # Conversion arcmins -> radians eff_diam = 3.0e8/(self.freq*self.fwhm*conv*1.0e6) # Also MHz -> Hz a = eff_diam/2. # Effective radius of telescope lamda = 3.0e8/(self.freq*1.0e6) # Obs. wavelength kasin = (2*math.pi*a/lamda)*np.sin(offset*conv) degfac = 4*(j1(kasin)/kasin)**2 else: degfac = math.exp( -2.7726 * offset * offset / (self.fwhm * self.fwhm)) # calc dispersion smearing across single channel tdm = self._dmsmear(pulsar) # calculate bhat et al scattering time (inherited from GalacticOps) # in units of ms if hasattr(pulsar, 't_scatter'): tscat = go.scale_bhat(pulsar.t_scatter, self.freq, pulsar.scindex) else: tscat = go.scatter_bhat(pulsar.dm, pulsar.scindex, self.freq) # Calculate the effective width width_ms = pulsar.width_degree * pulsar.period / 360.0 weff_ms = math.sqrt(width_ms**2 + self.tsamp**2 + tdm**2 + tscat**2) # calculate duty cycle (period is in ms) delta = weff_ms / pulsar.period # if pulse is smeared out, return -1.0 if delta > 1.0: # print width_ms, self.tsamp, tdm, tscat return -1 # radiometer signal to noise sig_to_noise = rad.calcSNR(self.calcflux(pulsar, pop.ref_freq), self.beta, self.tsys, self.tskypy(pulsar), self.gain, self.npol, self.tobs, self.bw, delta) # account for aperture array, if needed if self.AA: sig_to_noise *= self._AA_factor(pulsar) # account for binary motion if pulsar.is_binary: # print "the pulsar is a binary!" if jerksearch: print "jerk" gamma = degradation.gamma3(pulsar, self.tobs, 1) elif accelsearch: print "accel" gamma = degradation.gamma2(pulsar, self.tobs, 1) else: print "norm" gamma = degradation.gamma1(pulsar, self.tobs, 1) print "gamma harm1 = ", gamma gamma = degradation.gamma1(pulsar, self.tobs, 2) print "gamma harm2 = ", gamma gamma = degradation.gamma1(pulsar, self.tobs, 3) print "gamma harm3 = ", gamma gamma = degradation.gamma1(pulsar, self.tobs, 4) print "gamma harm4 = ", gamma # return the S/N accounting for beam offset return sig_to_noise * degfac
def SNRcalc(self, pulsar, pop, accelsearch=False, jerksearch=False): """Calculate the S/N ratio of a given pulsar in the survey""" # if not in region, S/N = 0 # if we have a list of pointings, use this bit of code # haven't tested yet, but presumably a lot slower # (loops over the list of pointings....) if pulsar.dead: return 0. # otherwise check if pulsar is in entire region if self.inRegion(pulsar): # If pointing list is provided, check how close nearest # pointing is if self.pointingslist is not None: # convert offset from degree to arcmin offset = self.inPointing_new(pulsar) * 60.0 else: # calculate offset as a random offset within FWHM/2 offset = self.fwhm * math.sqrt(random.random()) / 2.0 else: return -2 # Get degfac depending on self.gainpat if self.gainpat == 'airy': conv = math.pi / (60 * 180.) # Conversion arcmins -> radians eff_diam = 3.0e8 / (self.freq * self.fwhm * conv * 1.0e6 ) # Also MHz -> Hz a = eff_diam / 2. # Effective radius of telescope lamda = 3.0e8 / (self.freq * 1.0e6) # Obs. wavelength kasin = (2 * math.pi * a / lamda) * np.sin(offset * conv) degfac = 4 * (j1(kasin) / kasin)**2 else: degfac = math.exp(-2.7726 * offset * offset / (self.fwhm * self.fwhm)) # calc dispersion smearing across single channel tdm = self._dmsmear(pulsar) # calculate bhat et al scattering time (inherited from GalacticOps) # in units of ms if hasattr(pulsar, 't_scatter'): tscat = go.scale_bhat(pulsar.t_scatter, self.freq, pulsar.scindex) else: tscat = go.scatter_bhat(pulsar.dm, pulsar.scindex, self.freq) # Calculate the effective width width_ms = pulsar.width_degree * pulsar.period / 360.0 weff_ms = math.sqrt(width_ms**2 + self.tsamp**2 + tdm**2 + tscat**2) # calculate duty cycle (period is in ms) delta = weff_ms / pulsar.period # if pulse is smeared out, return -1.0 if delta > 1.0: #print width_ms, self.tsamp, tdm, tscat return -1 #radiometer signal to noise sig_to_noise = rad.calcSNR(self.calcflux(pulsar, pop.ref_freq), self.beta, self.tsys, self.tskypy(pulsar), self.gain, self.npol, self.tobs, self.bw, delta) # account for aperture array, if needed if self.AA: sig_to_noise *= self._AA_factor(pulsar) # account for binary motion if pulsar.is_binary: #print "the pulsar is a binary!" if jerksearch: print "jerk" gamma = degradation.gamma3(pulsar, self.tobs, 1) elif accelsearch: print "accel" gamma = degradation.gamma2(pulsar, self.tobs, 1) else: print "norm" gamma = degradation.gamma1(pulsar, self.tobs, 1) print "gamma harm1 = ", gamma gamma = degradation.gamma1(pulsar, self.tobs, 2) print "gamma harm2 = ", gamma gamma = degradation.gamma1(pulsar, self.tobs, 3) print "gamma harm3 = ", gamma gamma = degradation.gamma1(pulsar, self.tobs, 4) print "gamma harm4 = ", gamma # return the S/N accounting for beam offset return sig_to_noise * degfac
def SNRcalc(self, pulsar, pop, accelsearch=False, jerksearch=False, rratssearch=False, giantpulse=False): """Calculate the S/N ratio of a given pulsar in the survey""" # if not in region, S/N = 0 # if we have a list of pointings, use this bit of code # haven't tested yet, but presumably a lot slower # (loops over the list of pointings....) if rratssearch: if pulsar.br is None: print("Population doesn't have a burst rate") print("Use populate with --singlepulse") sys.exit() pulsar.pop_time = np.random.poisson(pulsar.br * self.tobs) if pulsar.dead: return 0. # otherwise check if pulsar is in entire region if self.inRegion(pulsar): # If pointing list is provided, check how close nearest # pointing is if self.pointingslist is not None: # convert offset from degree to arcmin offset = self.inPointing_new(pulsar) * 60.0 else: # calculate offset as a random offset within FWHM/2 offset = self.fwhm * math.sqrt(random.random()) / 2.0 else: return -2 if rratssearch == True and pulsar.pop_time < 1.0: return -3 # Get degfac depending on self.gainpat if self.gainpat == 'airy': conv = math.pi / (60 * 180.) # Conversion arcmins -> radians eff_diam = 3.0e8 / (self.freq * self.fwhm * conv * 1.0e6 ) # Also MHz -> Hz a = eff_diam / 2. # Effective radius of telescope lamda = 3.0e8 / (self.freq * 1.0e6) # Obs. wavelength kasin = (2 * math.pi * a / lamda) * np.sin(offset * conv) degfac = 4 * (j1(kasin) / kasin)**2 else: degfac = math.exp(-2.7726 * offset * offset / (self.fwhm * self.fwhm)) # calc dispersion smearing across single channel tdm = self._dmsmear(pulsar) # calculate bhat et al scattering time (inherited from GalacticOps) # in units of ms if hasattr(pulsar, 't_scatter'): tscat = go.scale_bhat(pulsar.t_scatter, self.freq, pulsar.scindex) else: tscat = go.scatter_bhat(pulsar.dm, pulsar.scindex, self.freq) # Calculate the effective width width_ms = pulsar.width_degree * pulsar.period / 360.0 weff_ms = math.sqrt(width_ms**2 + self.tsamp**2 + tdm**2 + tscat**2) # calculate duty cycle (period is in ms) delta = weff_ms / pulsar.period # if pulse is smeared out, return -1.0 #don't really get smearing with giant pulse or rrat search right? if (delta > 1.0) & (not giantpulse) & ( not rratssearch): #and pulsar.pop_time >= 1.0: # print width_ms, self.tsamp, tdm, tscat return -1 # radiometer signal to noise if (rratssearch == False) & (giantpulse == False): if self.surveyName == 'CHIME': #print('CHIME') sig_to_noise = rad.single_pulse_snr( self.npol, self.bw, weff_ms * 1e3, (self.tsys + self.tskypy(pulsar)), self.gain, self.calcflux(pulsar, pop.ref_freq), self.beta) else: sig_to_noise = rad.calcSNR(self.calcflux(pulsar, pop.ref_freq), self.beta, self.tsys, self.tskypy(pulsar), self.gain, self.npol, self.tobs, self.bw, delta) elif giantpulse: #check how many times it burst #use 0.001 as the fraction of periods to emit a GP for now - place holder #values here currently taken from Popov et al 2007 if pulsar.period < 100: pulses = 0.001 * (self.tobs / (1e-3 * pulsar.period)) GP_flux = np.zeros(int(pulses)) GP_lum = np.zeros(int(pulses)) GP_snr = np.zeros(int(pulses)) if pulses > 1: for i in range(int(pulses)): #parameters needs to be changed for later #working in units of Jy us fluence = dist.power_law_dual(1000, 11000, 2000, 200, -3.2, -1.9) #use pulse width of 55ms for now #the flux calculated here is for the Crab, so we'll have to use a different distance measure. average_flux = fluence / (55) #2 kpc away to get luminosity at 1400Mhz from 1200 Mhz, hard code this for now lum_1400 = average_flux * (2**2) * ( 1400 / 1200)**pulsar.spindex #scale down/up to survey frequency flux = self._GPFlux(pulsar, lum_1400, 1400) GP_lum[i] = lum_1400 GP_flux[i] = flux GP_snr[i] = rad.single_pulse_snr( self.npol, self.bw, weff_ms * 1e3, (self.tsys + self.tskypy(pulsar)), self.gain, flux, self.beta) pulsar.lum_1400 = np.max(GP_lum) sig_to_noise = np.max(GP_snr) if sig_to_noise >= self.SNRlimit: pulsar.det_pulses = GP_flux[GP_snr >= self.SNRlimit] pulsar.det_nos = len(pulsar.det_pulses) else: pulsar.det_pulses = None pulsar.det_nos = 0 else: return -3 else: return -3 elif rratssearch: #find number of times the pulse will pop up! #pop_time=int(pulsar.br*self.tobs) #Need to optimise this code... if pulsar.pop_time >= 1.0: pulse_snr = np.zeros(pulsar.pop_time) fluxes = np.zeros(pulsar.pop_time) lums = [] mu = math.log10(pulsar.lum_inj_mu) sig = mu / pulsar.lum_sig # Draw from luminosity dist. #ADAM EDIT it would be nice to make this run on multiple cores... chime has so much observation time for burst_times in range(pulsar.pop_time): pulsar.lum_1400 = dist.drawlnorm(mu, sig) lums.append(pulsar.lum_1400) flux = self.calcflux(pulsar, pop.ref_freq) fluxes[burst_times] = flux #ADAM EDIT: width changed to seconds instead of miliseconds??? pulse_snr[burst_times] = rad.single_pulse_snr( self.npol, self.bw, weff_ms * 1e3, (self.tsys + self.tskypy(pulsar)), self.gain, flux, self.beta) pulsar.lum_1400 = np.max(lums) sig_to_noise = np.max(pulse_snr) if sig_to_noise >= self.SNRlimit: pulsar.det_pulses = fluxes[pulse_snr >= self.SNRlimit] pulsar.det_nos = len(pulsar.det_pulses) else: pulsar.det_pulses = None pulsar.det_nos = 0 else: return -3 # account for aperture array, if needed if self.AA and sig_to_noise > 0.0: sig_to_noise *= self._AA_factor(pulsar) # account for binary motion if pulsar.is_binary: # print "the pulsar is a binary!" if jerksearch: #print "jerk" gamma = degradation.gamma3(pulsar, self.tobs, 1) elif accelsearch: #print "accel" #Adam fix bug gamma = degradation.gamma2(pulsar, self.tobs, 1) else: #print "norm" gamma = degradation.gamma1(pulsar, self.tobs, 1) #print "gamma harm1 = ", gamma gamma = degradation.gamma1(pulsar, self.tobs, 2) #print "gamma harm2 = ", gamma gamma = degradation.gamma1(pulsar, self.tobs, 3) #print "gamma harm3 = ", gamma gamma = degradation.gamma1(pulsar, self.tobs, 4) #print "gamma harm4 = ", gamma # return the S/N accounting for beam offset return sig_to_noise * degfac