def adjust_fold_frequency(self, phasebins, profs=None, shiftsubs=False): """ adjust_fold_frequency(phasebins, profs=None, shiftsubs=False): Linearly shift the intervals by phasebins over the course of the observation in order to change the apparent folding frequency. Return a 2D array containing the de-dispersed profiles as a function of time (i.e. shape = (npart, proflen)), and the reduced chi^2 of the resulting summed profile. If profs is not None, then use profs instead of self.profs. If shiftsubs is not False, then actually correct the subbands instead of a 2D projection of them. """ if not self.__dict__.has_key('subdelays'): print "Dedispersing first..." self.dedisperse() if shiftsubs: print "Shifting all the subbands..." if profs is None: profs = self.profs for ii in range(self.npart): bins_to_shift = int(round(float(ii) / self.npart * phasebins)) for jj in range(self.nsub): profs[ii, jj] = psr_utils.rotate(profs[ii, jj], bins_to_shift) redchi = self.calc_redchi2(prof=profs.sum(0).sum(0)) else: print "Shifting just the projected intervals (not individual subbands)..." if profs is None: profs = self.profs.sum(1) for ii in range(self.npart): bins_to_shift = int(round(float(ii) / self.npart * phasebins)) profs[ii] = psr_utils.rotate(profs[ii], bins_to_shift) redchi = self.calc_redchi2(prof=profs.sum(0)) print "New reduced-chi^2 =", redchi return profs, redchi
def estimate_offsignal_redchi2(self, numtrials=20): """ estimate_offsignal_redchi2(): Estimate the reduced-chi^2 off of the signal based on randomly shifting and summing all of the component profiles. """ redchi2s = [] for count in range(numtrials): prof = Num.zeros(self.proflen, dtype='d') for ii in range(self.npart): for jj in range(self.nsub): tmpprof = copy.copy(self.profs[ii][jj]) prof += psr_utils.rotate(tmpprof, random.randrange(0,self.proflen)) redchi2s.append(self.calc_redchi2(prof=prof)) return Num.mean(redchi2s)
def plot_chi2_vs_DM(self, loDM, hiDM, N=100, interp=0, device='/xwin'): """ plot_chi2_vs_DM(self, loDM, hiDM, N=100, interp=0, device='/xwin'): Plot (and return) an array showing the reduced-chi^2 versus DM (N DMs spanning loDM-hiDM). Use sinc_interpolation if 'interp' is non-zero. """ # Sum the profiles in time sumprofs = self.profs.sum(0) if not interp: profs = sumprofs else: profs = Num.zeros(Num.shape(sumprofs), dtype='d') DMs = psr_utils.span(loDM, hiDM, N) chis = Num.zeros(N, dtype='f') subdelays_bins = self.subdelays_bins.copy() for ii, DM in enumerate(DMs): subdelays = psr_utils.delay_from_DM(DM, self.barysubfreqs) hifreqdelay = subdelays[-1] subdelays = subdelays - hifreqdelay delaybins = subdelays * self.binspersec - subdelays_bins if interp: interp_factor = 16 for jj in range(self.nsub): profs[jj] = psr_utils.interp_rotate(sumprofs[jj], delaybins[jj], zoomfact=interp_factor) # Note: Since the interpolation process slightly changes the values of the # profs, we need to re-calculate the average profile value avgprof = (profs / self.proflen).sum() else: new_subdelays_bins = Num.floor(delaybins + 0.5) for jj in range(self.nsub): profs[jj] = psr_utils.rotate(profs[jj], int(new_subdelays_bins[jj])) subdelays_bins += new_subdelays_bins avgprof = self.avgprof sumprof = profs.sum(0) chis[ii] = self.calc_redchi2(prof=sumprof, avg=avgprof) # Now plot it Pgplot.plotxy(chis, DMs, labx="DM", laby=r"Reduced-\gx\u2\d", device=device) return (chis, DMs)
def shift_channels(self, bins, padval=0): """Shift each channel to the left by the corresponding value in bins, an array. Inputs: bins: An array containing the number of bins to shift each channel by. padval: Value to use when shifting near the edge of a channel. This can be a numeric value, 'median', 'mean', or 'rotate'. The values 'median' and 'mean' refer to the median and mean of the channel. The value 'rotate' takes values from one end of the channel and shifts them to the other. Outputs: None *** Shifting happens in-place *** """ assert self.numchans == len(bins) for ii in range(self.numchans): chan = self.get_chan(ii) # Use 'chan[:]' so update happens in-place # this way the change effects self.data chan[:] = psr_utils.rotate(chan, bins[ii]) if padval != 'rotate': # Get padding value if padval == 'mean': pad = np.mean(chan) elif padval == 'median': pad = np.median(chan) else: pad = padval # Replace rotated values with padval if bins[ii] > 0: chan[-bins[ii]:] = pad elif bins[ii] < 0: chan[:-bins[ii]] = pad
def adjust_period(self, p=None, pd=None, pdd=None, interp=0): """ adjust_period(p=*bestp*, pd=*bestpd*, pdd=*bestpdd*): Rotate (internally) the profiles so that they are adjusted to the given period and period derivatives. By default, use the 'best' values as determined by prepfold's seaqrch. This should orient all of the profiles so that they are almost identical to what you see in a prepfold plot which used searching. Use FFT-based interpolation if 'interp' is non-zero. (NOTE: It is off by default, as in prepfold!) """ if self.fold_pow == 1.0: bestp = self.bary_p1 bestpd = self.bary_p2 bestpdd = self.bary_p3 else: bestp = self.topo_p1 bestpd = self.topo_p2 bestpdd = self.topo_p3 if p is None: p = bestp if pd is None: pd = bestpd if pdd is None: pdd = bestpdd # Cast to single precision and back to double precision to # emulate prepfold_plot.c, where parttimes is of type "float" # but values are upcast to "double" during computations. # (surprisingly, it affects the resulting profile occasionally.) parttimes = self.start_secs.astype('float32').astype('float64') # Get delays f_diff, fd_diff, fdd_diff = self.freq_offsets(p, pd, pdd) delays = psr_utils.delay_from_foffsets(f_diff, fd_diff, fdd_diff, parttimes) # Convert from delays in phase to delays in bins bin_delays = Num.fmod(delays * self.proflen, self.proflen) - self.pdelays_bins if interp: new_pdelays_bins = bin_delays else: new_pdelays_bins = Num.floor(bin_delays + 0.5) # Rotate subintegrations for ii in range(self.nsub): for jj in range(self.npart): tmp_prof = self.profs[jj, ii, :] # Negative sign in num bins to shift because we calculated delays # Assuming +ve is shift-to-right, psr_utils.rotate assumes +ve # is shift-to-left if interp: self.profs[jj, ii] = psr_utils.fft_rotate( tmp_prof, -new_pdelays_bins[jj]) else: self.profs[jj,ii] = psr_utils.rotate(tmp_prof, \ -new_pdelays_bins[jj]) self.pdelays_bins += new_pdelays_bins if interp: # Note: Since the rotation process slightly changes the values of the # profs, we need to re-calculate the average profile value self.avgprof = (self.profs / self.proflen).sum() self.sumprof = self.profs.sum(0).sum(0) if Num.fabs((self.sumprof / self.proflen).sum() - self.avgprof) > 1.0: print("self.avgprof is not the correct value!") # Save current p, pd, pdd self.curr_p1, self.curr_p2, self.curr_p3 = p, pd, pdd
sumprof *= Num.sqrt(current_pfd.DOF_corr()) / offpulse.std() print("\nSummed profile approx SNR = %.3f" % sum(sumprof)) if SEFD: avg_S /= len(pfdfilenms) if pulsebins is None: SNR = sumprof.sum() # integrate everything else: SNR = sumprof[pulsebins].sum() S = SEFD * SNR / Num.sqrt(2.0 * BW * Tpostrfi / numbins) / numbins print(" Approx sum profile flux density = %.3f mJy" % S) print(" Avg of individual flux densities = %.3f mJy" % avg_S) print(" Total (RFI cleaned) integration = %.0f s (%.2f hrs)" % \ (Tpostrfi, Tpostrfi/3600.0)) # Rotate the summed profile so that the max value is at the phase ~ 0.25 mark sumprof = psr_utils.rotate(sumprof, -len(sumprof) / 4) Pgplot.plotxy(sumprof, Num.arange(numbins), labx="Pulse Phase", laby="Relative Flux") Pgplot.closeplot() print("\n Writing profile to '%s'..." % (outfilenm), end=' ') outfile = open(outfilenm, "w") for ii, val in enumerate(sumprof): outfile.write("%04d %20.15g\n" % (ii, val)) outfile.close() print("Done\n")
def calc_features_from_pfd(pfd_filepath): pfd_data = prepfold.pfd(str(pfd_filepath)) if pfd_filepath.parent.name == 'positive': label = 1 elif pfd_filepath.parent.name == 'negative': label = 0 else: label = -1 # return (label, 0, 0, 0, 0, 0, 0, 0, 0, 0, # np.empty(shape=(0,)), np.empty(shape=(0,0)), # np.empty(shape=(0,0)), np.empty(shape=(0,))) pfd_data.dedisperse() #### As done in: prepfold.pfd.plot_sumprofs profile = pfd_data.sumprof profile = normalise_1d(profile) #### profiles_sum_axis0 = pfd_data.profs.sum(0) #### As done in: prepfold.pfd.plot_chi2_vs_DM loDM = 0 hiDM = pfd_data.numdms N = pfd_data.numdms profs = profiles_sum_axis0.copy() # = pfd_data.profs.sum(0) DMs = psr_utils.span(loDM, hiDM, N) chis = np.zeros(N, dtype='f') subdelays_bins = pfd_data.subdelays_bins.copy() for ii, DM in enumerate(DMs): subdelays = psr_utils.delay_from_DM(DM, pfd_data.barysubfreqs) hifreqdelay = subdelays[-1] subdelays = subdelays - hifreqdelay delaybins = subdelays * pfd_data.binspersec - subdelays_bins new_subdelays_bins = np.floor(delaybins + 0.5) for jj in range(pfd_data.nsub): profs[jj] = psr_utils.rotate(profs[jj], int(new_subdelays_bins[jj])) subdelays_bins += new_subdelays_bins sumprof = profs.sum(0) chis[ii] = pfd_data.calc_redchi2(prof=sumprof, avg=pfd_data.avgprof) #### # best_dm = pfd_data.bestdm # crop_radius = 100 # best_dm_index = np.searchsorted(DMs, best_dm) # Not accurate, but close. # bloated_chis = np.insert(chis, N, np.full(crop_radius, chis[-1])) # bloated_chis = np.insert(bloated_chis, 0, np.full(crop_radius, chis[0])) # cropped_chis = bloated_chis[ best_dm_index : best_dm_index+2*crop_radius ] # chis = cropped_chis #### As done in: prepfold.pfd.plot_intervals intervals = pfd_data.profs.sum(1) intervals = normalise_2d_rowwise(intervals) #### #### As done in: prepfold.pfd.plot_subbands subbands = profiles_sum_axis0.copy() # = pfd_data.profs.sum(0) subbands = normalise_2d_rowwise(subbands) #### return label, profile, intervals, subbands, chis