def scintillation_parameters(self,
                                 plotbound=1.0,
                                 maxr=None,
                                 maxc=None,
                                 savefig=None,
                                 show=True,
                                 full_output=False,
                                 simple=False,
                                 eta=0.2,
                                 cmap=cm.binary,
                                 finitescintleerrors=True):
        if self.acf is None:
            self.acf2d()
        if self.dT is None:
            dT = 1
        else:
            dT = self.dT
        if self.dF is None:
            dF = 1
        else:
            dF = self.dF

        acfshape = np.shape(self.acf)
        centerrind = acfshape[0] // 2
        centercind = acfshape[1] // 2

        if simple:  # Do 1D slices
            NF = len(self.F)
            Faxis = (np.arange(-(NF - 1), NF, dtype=np.float) * np.abs(dF)
                     )  #why abs?
            NT = len(self.T)
            Taxis = (np.arange(-(NT - 1), NT, dtype=np.float) *
                     np.abs(dT))[1:-1]  #???

            #try:
            pout, errs = ffit.gaussianfit(Taxis[NT // 2:3 * NT // 2],
                                          self.acf[centerrind,
                                                   NT // 2:3 * NT // 2],
                                          baseline=True)
            f = interpolate.interp1d(
                Taxis,
                ffit.funcgaussian(pout, Taxis, baseline=True) -
                (pout[3] + pout[0] / np.e))
            delta_t_d = optimize.brentq(f, 0, Taxis[-1])
            #except:
            #    delta_t_d = 0.0
            #    print "dtd",pout
            #    plt.plot(Taxis,self.acf[centerrind,:])
            #    plt.plot(Taxis,f(Taxis))
            #    plt.show()

            #try:
            pout, errs = ffit.gaussianfit(Faxis[NF // 2:3 * NF // 2],
                                          self.acf[NF // 2:3 * NF // 2,
                                                   centercind],
                                          baseline=True)
            f = interpolate.interp1d(
                Faxis,
                ffit.funcgaussian(pout, Faxis, baseline=True) -
                (pout[3] + pout[0] / 2))
            delta_nu_d = optimize.brentq(f, 0, Faxis[-1])
            #except:
            #    delta_nu_d = 0
            #print "dnud",pout,Faxis[-1],dF
            #print Faxis
            #raise SystemExit
            #plt.plot(Faxis,self.acf[:,centercind])
            #plt.plot(Faxis,f(Faxis))
            #plt.show()

            #following Glenn's code and Cordes 1986 (Space Velocities...)
            # Errors from finite scintle effect:
            bw = self.getBandwidth()
            T = self.getTspan()
            if delta_t_d == 0.0:
                N_d = (1 + eta * bw / delta_nu_d)
            elif delta_nu_d == 0.0:
                N_d = (1 + eta * T / delta_t_d)
            else:
                N_d = (1 + eta * bw / delta_nu_d) * (1 + eta * T / delta_t_d)
            fse_nu_d = delta_nu_d / (2 * np.log(2) * np.sqrt(N_d)
                                     )  #log because of FWHM?
            fse_t_d = delta_t_d / (2 * np.sqrt(N_d))

            err_nu_d = fse_nu_d
            err_t_d = fse_t_d  #need to add in fitting errors

            if full_output:
                return delta_t_d, err_t_d, delta_nu_d, err_nu_d
            return delta_t_d, delta_nu_d

        # Look for the central peak in the ACF
        MIN = np.min(self.acf)
        if MIN < 0:  #The min value is approximately from a gaussian distribution
            MIN = np.abs(MIN)
        else:
            #center,hist = u.histogram(acf.flatten(),interval=0.001) #relies on 0.001
            #MIN = center[np.argmax(hist)]
            MIN = u.RMS(self.acf.flatten())
        if maxr is None:
            rslice = self.acf[centerrind:, centercind]
            maxr = np.where(rslice <= MIN)[0][0]
        if maxc is None:
            cslice = self.acf[centerrind, centercind:]
            maxc = np.where(cslice <= MIN)[0][0]

        plotacf = self.acf[int(centerrind - plotbound * maxr +
                               1):int(centerrind + plotbound * maxr),
                           int(centercind - plotbound * maxc +
                               1):int(centercind + plotbound * maxc + 1)]

        params, pcov = ffit.fitgaussian2d(
            plotacf)  #pcov already takes into account s_sq issue
        SHAPE = np.shape(plotacf)

        fit = ffit.gaussian2d(*params)
        amplitude, center_x, center_y, width_x, width_y, rotation, baseline = params

        paramnames = [
            "amplitude", "center_x", "center_y", "width_x", "width_y",
            "rotation", "baseline"
        ]
        if pcov is not None:
            paramerrors = np.sqrt(np.diagonal(pcov))
        else:
            paramerrors = np.zeros_like(params)
        if self.verbose:
            for i, param in enumerate(params):
                print("%s: %0.2e+/-%0.2e" %
                      (paramnames[i], param, paramerrors[i]))

        #Solve for scintillation parameters numerically

        try:
            delta_t_d = (optimize.brentq(
                lambda y: fit(SHAPE[0] // 2, y) - baseline - amplitude / np.e,
                (SHAPE[1] - 1) // 2, SHAPE[1] * 2) -
                         (SHAPE[1] - 1) // 2) * dT  #FWHM test
            if self.verbose:
                print("delta_t_d %0.3f %s" % (delta_t_d, self.Tunit))
        except ValueError:
            if self.verbose:
                print("ERROR in delta_t_d")
            delta_t_d = SHAPE[1] * dT
        if pcov is not None:
            err_t_d = paramerrors[3] * dT  #assume no rotaton for now
        else:
            err_t_d = None

        try:
            delta_nu_d = (optimize.brentq(
                lambda x: fit(x, SHAPE[1] // 2) - baseline - amplitude / 2.0,
                (SHAPE[0] - 1) // 2, SHAPE[0]) - (SHAPE[0] - 1) // 2) * dF
            if self.verbose:
                print("delta_nu_d %0.3f %s" % (delta_nu_d, self.Funit))
        except ValueError:
            if self.verbose:
                print("ERROR in delta_nu_d")
            delta_nu_d = SHAPE[0] * dF
        if pcov is not None:
            err_nu_d = paramerrors[4] * dF  #assume no rotaton for now
        else:
            err_nu_d = None

        err_rot = paramerrors[5]

        #finite-scintle errors
        if finitescintleerrors:
            bw = self.getBandwidth()
            T = self.getTspan()
            if delta_t_d == 0.0:
                N_d = (1 + eta * bw / delta_nu_d)
            elif delta_nu_d == 0.0:
                N_d = (1 + eta * T / delta_t_d)
            else:
                N_d = (1 + eta * bw / delta_nu_d) * (1 + eta * T / delta_t_d)
            fse_nu_d = delta_nu_d / (2 * np.log(2) * np.sqrt(N_d)
                                     )  #log because of FWHM?
            fse_t_d = delta_t_d / (2 * np.sqrt(N_d))

            fse_rot = rotation * np.sqrt((fse_nu_d / delta_nu_d)**2 +
                                         (fse_t_d / delta_t_d)**2)

            err_nu_d = np.sqrt(err_nu_d**2 + fse_nu_d**2)
            err_t_d = np.sqrt(err_t_d**2 + fse_t_d**2)
            err_rot = np.sqrt(err_rot**2 + fse_rot**2)

        if self.verbose:
            f = (dF / dT) * np.tan(rotation)
            df = (dF / dT) * np.cos(rotation)**2 * err_rot
            print("dnu/dt %0.3e+/-%0.3e %s/%s" %
                  (f, df, self.Funit, self.Tunit))  #((dF/dT)*np.tan(rotation))

        if show or savefig is not None:
            fig = plt.figure()
            ax = fig.add_subplot(211)
            u.imshow(self.data, cmap=cmap)
            ax = fig.add_subplot(212)

            u.imshow(plotacf, cmap=cmap)
            plt.colorbar()
            levels = (amplitude * np.array([1.0, 0.5, 1.0 / np.e])) + baseline
            levels = (amplitude * np.array([0.5])) + baseline
            #print(levels)

            ax.contour(fit(*np.indices(plotacf.shape)), levels, colors='k')
            #ax.set_xlim(len(xs)-20,len(xs)+20)
            #ax.set_ylim(len(ys)-10,len(ys)+10)
            if savefig is not None:
                plt.savefig(savefig)
            if show:
                plt.show()
        if full_output:
            return delta_t_d, err_t_d, delta_nu_d, err_nu_d, rotation, err_rot
        return delta_t_d, delta_nu_d, rotation
Esempio n. 2
0
    def spline_smoothing(self, sigma=None, lam=None, **kwargs):
        """ Cubic Spline Interplation
        sigma: phase bin error bars
        lam: (0,1], 1 = maximize fitting through control points (knots), 0 = minimize curvature of spline
        """

        tdata = self.bins
        ydata = u.normalize(self.data, simple=True)
        N = len(ydata)

        noise = self.getOffpulseNoise()
        if lam is None or (lam > 1 or lam <= 0):
            lam = 1 - noise**2
        mu = 2 * float(1 - lam) / (3 * lam)

        ### Define knot locations

        # Rotate the pulse so the peak is at the edges of the spline
        shift = -np.argmax(ydata)
        yshift = np.roll(ydata, shift)

        # Add periodic point
        tdata = np.concatenate((tdata, [tdata[-1] + np.diff(tdata)[0]]))
        yshift = np.concatenate((yshift, [yshift[0]]))

        knots = u.subdivide(tdata, yshift, noise, **kwargs)
        knots = np.array(np.sort(knots), dtype=np.int)
        knots = np.concatenate(([0], knots, [N]))  #Add endpoints

        if sigma is None:
            setsigma = True

        #for passnum in range(2):
        while True:
            Nknots = len(knots)
            Narcs = Nknots - 1
            t = np.array(tdata[knots], dtype=np.float)

            # Determine the knot y-values.
            y = np.zeros_like(t)
            y[0] = yshift[0]
            y[-1] = yshift[-1]
            for i in range(1, len(knots) - 1):
                knotL = knots[i - 1]
                knotR = knots[i + 1]
                dt = tdata[knotL:knotR]
                dy = yshift[knotL:knotR]
                p = np.polyfit(
                    dt, dy, 3
                )  #Fit a preliminary cubic over the data to place the point.
                f = np.poly1d(p)
                y[i] = f(tdata[knots[i]])

            if setsigma:
                sigma = np.ones(len(y), dtype=np.float)
            Sigma = np.diag(sigma[:-1])  #matrix

            # Smoothing with Cubic Splines by D.S.G. Pollock 1999
            h = t[1:] - t[:-1]
            r = 3.0 / h

            f = np.zeros_like(h)
            p = np.zeros_like(h)
            #q = np.zeros_like(h)

            p[0] = 2 * (h[0] + h[-1])
            #q[0] = 3*(y[1] - y[0])/h[0] - 3*(y[-1] - y[-2])/h[-1] #note the indices
            f[0] = -(r[-1] + r[0])
            for i in range(1, Narcs):
                p[i] = 2 * (h[i] + h[i - 1])
                #q[i] = 3*(y[i+1] - y[i])/h[i] - 3*(y[i] - y[i-1])/h[i-1]
                f[i] = -(r[i - 1] + r[i])

            # Build projection matrices
            R = np.zeros((Narcs, Narcs))
            Qp = np.zeros((Narcs, Narcs))

            for i in range(Narcs):
                #for j in range(Narcs):
                #    if i == j:
                R[i, i] = p[i]
                Qp[i, i] = f[i]
                if i != Narcs - 1:
                    R[i + 1, i] = h[i]
                    R[i, i + 1] = h[i]
                    Qp[i + 1, i] = r[i]
                    Qp[i, i + 1] = r[i]
            R[0, -1] = h[-1]
            R[-1, 0] = h[-1]
            Qp[0, -1] = r[-1]
            Qp[-1, 0] = r[-1]
            Q = np.transpose(Qp)

            A = mu * np.dot(np.dot(Qp, Sigma), Q) + R

            b = np.linalg.solve(A, np.dot(Qp, y[:-1]))
            d = y[:-1] - mu * np.dot(np.dot(Sigma, Q), b)
            a = np.zeros(Narcs)
            c = np.zeros(Narcs)

            i = Narcs - 1
            a[i] = (b[0] - b[i]) / (3 * h[i])
            for i in range(Narcs - 1):
                a[i] = (b[i + 1] - b[i]) / (3 * h[i])

            i = Narcs - 1
            c[i] = (d[0] - d[i]) / h[i] - a[i] * h[i]**2 - b[i] * h[i]
            for i in range(Narcs - 1):
                c[i] = (d[i + 1] - d[i]) / h[i] - a[i] * h[i]**2 - b[i] * h[i]

            # Build polynomials
            S = []
            for i in range(Narcs):
                S.append(np.poly1d([a[i], b[i], c[i], d[i]]))

            ytemp = np.zeros_like(yshift)
            for i in range(Narcs):
                ts = np.arange(t[i], t[i + 1])
                hs = ts - t[i]
                yS = S[i](hs)
                ytemp[int(t[i]):int(t[i + 1])] = yS

            ytemp[-1] = ytemp[0]
            resids = yshift - ytemp
            #print resids,noise
            rms_resids = u.RMS(resids)
            #inds = np.where(np.abs(resids)>4*rms_resids)[0]
            inds = np.where(
                np.logical_and(yshift > 3 * noise,
                               np.abs(resids) > 4 * rms_resids)
            )[0]  #require the intensity to be "significant", and the residuals
            if len(inds) == 0:
                break

            #newinds = np.sort(np.abs(resids))
            newinds = np.argsort(np.abs(resids))
            #print np.argmax(np.abs(resids))
            #print newinds
            #raise SystemExit
            #newind = np.argmax(np.abs(resids))

            newind = newinds[-1]
            i = 1
            addknot = True
            while newind in knots and np.any(np.abs(knots - newind) <= 4):
                if i == N:
                    addknot = False
                    break
                i += 1
                newind = newinds[-i]
            '''
            for newind in newinds:
                if newind in knots:
                    continue
                elif np.all(np.abs(newind-knots)<=1):
                    continue
                print newind
                break
            '''
            if addknot:
                #print newind
                knots = np.sort(np.concatenate((knots, [newind])))
            else:
                break

        resids = yshift - ytemp
        rms_resids = u.RMS(resids)

        tdata = tdata[:-1]
        #yshift = yshift[:-1]
        ytemp = ytemp[:-1]

        #yshift = np.roll(yshift,-shift)
        ytemp = np.roll(ytemp, -shift)
        ytemp /= np.max(ytemp)

        return ytemp
Esempio n. 3
0
    def scintillation_parameters(self,
                                 plotbound=1.0,
                                 maxr=None,
                                 maxc=None,
                                 savefig=None,
                                 show=True,
                                 full_output=False):
        if self.acf is None:
            self.acf2d()
        if self.dT is None:
            dT = 1
        else:
            dT = self.dT
        if self.dF is None:
            dF = 1
        else:
            dF = self.dF

        acfshape = np.shape(self.acf)
        centerrind = acfshape[0] // 2
        centercind = acfshape[1] // 2

        # Look for the central peak in the ACF

        MIN = np.min(self.acf)
        if MIN < 0:  #The min value is approximately from a gaussian distribution
            MIN = np.abs(MIN)
        else:
            #center,hist = u.histogram(acf.flatten(),interval=0.001) #relies on 0.001
            #MIN = center[np.argmax(hist)]
            MIN = u.RMS(self.acf.flatten())
        if maxr is None:
            rslice = self.acf[centerrind:, centercind]
            maxr = np.where(rslice <= MIN)[0][0]
        if maxc is None:
            cslice = self.acf[centerrind, centercind:]
            maxc = np.where(cslice <= MIN)[0][0]

        plotacf = self.acf[centerrind - plotbound * maxr + 1:centerrind +
                           plotbound * maxr, centercind - plotbound * maxc +
                           1:centercind + plotbound * maxc + 1]

        params, pcov = ffit.fitgaussian2d(
            plotacf)  #pcov already takes into account s_sq issue
        SHAPE = np.shape(plotacf)

        fit = ffit.gaussian2d(*params)
        amplitude, center_x, center_y, width_x, width_y, rotation, baseline = params
        if self.verbose:
            paramnames = [
                "amplitude", "center_x", "center_y", "width_x", "width_y",
                "rotation", "baseline"
            ]
            if pcov is not None:
                paramerrors = np.sqrt(np.diagonal(pcov))
            else:
                paramerrors = np.zeros_like(params)
            for i, param in enumerate(params):
                print("%s: %0.2e+/-%0.2e" %
                      (paramnames[i], param, paramerrors[i]))

        #Solve for scintillation parameters numerically

        try:
            delta_t_d = (optimize.brentq(
                lambda y: fit(SHAPE[0] // 2, y) - baseline - amplitude / np.e,
                (SHAPE[1] - 1) // 2, SHAPE[1] * 2) -
                         (SHAPE[1] - 1) // 2) * dT  #FWHM test
            if self.verbose:
                print("delta_t_d %0.3f minutes" % delta_t_d)
        except ValueError:
            if self.verbose:
                print("ERROR in delta_t_d")
            delta_t_d = SHAPE[1] * dT
        if pcov is not None:
            err_t_d = paramerrors[3] * dT  #assume no rotaton for now
        else:
            err_t_d = None

        try:
            delta_nu_d = (optimize.brentq(
                lambda x: fit(x, SHAPE[1] // 2) - baseline - amplitude / 2.0,
                (SHAPE[0] - 1) // 2, SHAPE[0]) - (SHAPE[0] - 1) // 2) * dF
            if self.verbose:
                print("delta_nu_d %0.3f MHz" % delta_nu_d)
        except ValueError:
            if self.verbose:
                print("ERROR in delta_nu_d")
            delta_nu_d = SHAPE[0] * dF
        if pcov is not None:
            err_nu_d = paramerrors[4] * dF  #assume no rotaton for now
        else:
            err_nu_d = None

        err_rot = paramerrors[5]

        if self.verbose:
            print("dnu/dt %0.3f MHz/min" %
                  ((dF / dT) * np.tan(rotation)))  #((dF/dT)*np.tan(rotation))

        if show or savefig is not None:
            fig = plt.figure()
            ax = fig.add_subplot(211)
            u.imshow(self.data)
            ax = fig.add_subplot(212)

            u.imshow(plotacf)
            plt.colorbar()
            levels = (amplitude * np.array([1.0, 0.5, 1.0 / np.e])) + baseline
            levels = (amplitude * np.array([0.5])) + baseline
            print(levels)

            ax.contour(fit(*np.indices(plotacf.shape)), levels, colors='k')
            #ax.set_xlim(len(xs)-20,len(xs)+20)
            #ax.set_ylim(len(ys)-10,len(ys)+10)
            if savefig is not None:
                plt.savefig(savefig)
            if show:
                plt.show()
        if full_output:
            return delta_t_d, err_t_d, delta_nu_d, err_nu_d, rotation, err_rot
        return delta_t_d, delta_nu_d, rotation