def test_sliced_input(self):
        # cython code chokes on non C contiguous arrays
        xx = np.linspace(-1, 1, 100)

        x = xx[::3]
        y = xx[::3]
        t = _augknt(x, 1)
        make_lsq_spline(x, y, t, k=1)
Example #2
0
    def robust_spline_fit(y):
        bspl = interp.make_lsq_spline(x=x, y=y, t=knots, k=order)
        resid = np.abs(bspl(x) - y)
        keep_idx = resid <= np.percentile(resid, (1 - q) * 100)
        bspl = interp.make_lsq_spline(
            x=x[keep_idx], y=y[keep_idx], t=knots, k=order)

        return bspl(x)
Example #3
0
    def test_sliced_input(self):
        # cython code chokes on non C contiguous arrays
        xx = np.linspace(-1, 1, 100)

        x = xx[::3]
        y = xx[::3]
        t = _augknt(x, 1)
        make_lsq_spline(x, y, t, k=1)
    def test_complex(self):
        # cmplx-valued `y`
        x, t, k = self.x, self.t, self.k
        yc = self.y * (1. + 2.j)

        b = make_lsq_spline(x, yc, t, k)
        b_re = make_lsq_spline(x, yc.real, t, k)
        b_im = make_lsq_spline(x, yc.imag, t, k)

        assert_allclose(b(x), b_re(x) + 1.j * b_im(x), atol=1e-15, rtol=1e-15)
Example #5
0
    def test_complex(self):
        # cmplx-valued `y`
        x, t, k = self.x, self.t, self.k
        yc = self.y * (1. + 2.j)

        b = make_lsq_spline(x, yc, t, k)
        b_re = make_lsq_spline(x, yc.real, t, k)
        b_im = make_lsq_spline(x, yc.imag, t, k)

        assert_allclose(b(x), b_re(x) + 1.j*b_im(x), atol=1e-15, rtol=1e-15)
    def test_weights(self):
        # weights = 1 is same as None
        x, y, t, k = self.x, self.y, self.t, self.k
        w = np.ones_like(x)

        b = make_lsq_spline(x, y, t, k)
        b_w = make_lsq_spline(x, y, t, k, w=w)

        assert_allclose(b.t, b_w.t, atol=1e-14)
        assert_allclose(b.c, b_w.c, atol=1e-14)
        assert_equal(b.k, b_w.k)
Example #7
0
    def test_weights(self):
        # weights = 1 is same as None
        x, y, t, k = self.x, self.y, self.t, self.k
        w = np.ones_like(x)

        b = make_lsq_spline(x, y, t, k)
        b_w = make_lsq_spline(x, y, t, k, w=w)

        assert_allclose(b.t, b_w.t, atol=1e-14)
        assert_allclose(b.c, b_w.c, atol=1e-14)
        assert_equal(b.k, b_w.k)
Example #8
0
def approximate_spline(time_from_starts, path, k=3, approx=INF):
    from scipy.interpolate import make_interp_spline, make_lsq_spline
    x = time_from_starts
    if approx == INF:
        positions = make_interp_spline(time_from_starts,
                                       path,
                                       k=k,
                                       t=None,
                                       bc_type='clamped')
        positions.x = positions.t[positions.k:-positions.k]
    else:
        # TODO: approximation near the endpoints
        # approx = min(approx, len(x) - 2*k)
        assert approx <= len(x) - 2 * k
        t = np.r_[
            (x[0], ) * (k + 1),
            # np.linspace(x[0]+1e-3, x[-1]-1e-3, num=approx, endpoint=True),
            np.linspace(x[0], x[-1], num=2 + approx, endpoint=True)[1:-1],
            (x[-1], ) * (k + 1)]
        # t = positions.t # Need to slice
        # w = np.zeros(...)
        w = None
        positions = make_lsq_spline(x, path, t, k=k, w=w)
    positions.x = positions.t[positions.k:-positions.k]
    return positions
    def lsq_interp(cls, x, y, degree=4, fraction_n=0.1):
        """Caller fot the scipy least squares method interpolator
        To call scipy.interpolate_make_lsq_spline():
        - x: abcissas
        - y: ordinates
        - t: knots, array-like with shape(n+k+1)
        - k: b-spline degree
        - w: weights for spline fitting
        - axis: interpolation axis, default is 0
        - check_finite: whether to check if the inputs contains only finite
        elements
        Inputs
        - x,y: one dimensional arrays
        - degree: integer, defines the polynomial fitting
        - fraction_n: number of points to be used, a fraction of the total
        number of points
        Returns
        - object, the interpolator

        NOTES:
        (*) number of data points must be larger than the spline degree
        (*) knots must be a subset of data points of x[j] such that
        t[j] < x[j] < t[j+k+1], for j=0,1..n-k-2
        (*) degree 4 works slightly better than lower values
        """
        # Number of points to be used
        naux = np.int(np.ceil(x.shape[0] * fraction_n))
        # By hand I set the use of all but 2 points at each end of the sample
        p1, p2 = 2, x.shape[0] - 3
        t = x[p1 : p2 : naux]
        t = np.r_[(x[0],) * (degree + 1), t, (x[-1],) * (degree + 1)]
        # Interpolate with the subset of points
        lsq_spline = interpolate.make_lsq_spline(x, y, t, degree)
        return lsq_spline
Example #10
0
def smooth(y, num_interactions):
    x = np.linspace(0, num_interactions, num_interactions)
    k = 4
    knots = np.linspace(x[0], x[-1], 1000)
    t = np.r_[(x[0], ) * k, knots, (x[-1], ) * k]
    spl = make_lsq_spline(x, y, t, k)
    return spl(x)
    def find_n_best_knots(self, init_spline, ranks):
        test_x = self.test_x
        knots = self.knots
        last_knot = len(knots) - 1
        indices_max = ranks.argsort()

        new_knots = []
        lsq_spline = ()
        lsq_err = 0

        for num in range(self.min_n, max(last_knot, len(self.x))):
            indices = np.sort(indices_max[-num:][::-1])

            new_knots = np.array([knots[i] for i in indices if i != last_knot and i != 0])

            new_knots = np.r_[(self.x[0],) * (self.degree + 1)
                              , new_knots
                              , (self.x[-1],) * (self.degree + 1)]

            lsq_spline = make_lsq_spline(self.x, self.y, new_knots)

            lsq_err = max(abs(lsq_spline(test_x) - init_spline(test_x)))

            if lsq_err <= self.cubic_spl_err:
                return new_knots[self.degree + 1: -(self.degree + 1)], lsq_spline, lsq_err

        return new_knots[self.degree + 1: -(self.degree + 1)], lsq_spline, lsq_err
Example #12
0
def test_minimize():
    """
    Compare least square minimization procedure to scipy's 
    """
    return
    npts = 60
    px = np.linspace(-3 + 1e-2, 3 - 1e-2, npts)
    py = np.exp(-px**2) + 0.01 * np.random.randn(npts)
    from scipy.interpolate import make_lsq_spline, BSpline

    n = 9
    p = 3
    t = np.linspace(-2, 2, 20)
    U = np.r_[(px[0], ) * (p + 1), t, (px[-1], ) * (p + 1)]

    P = sf.bspline.bspline_lsq(px, py, U, p)

    u = np.linspace(-3, 3, 100)
    z = []
    for ui in u:
        z.append(sf.bspline.curvepoint(p, U, P, ui))
    spl = make_lsq_spline(px, py, U, p)
    plt.clf()
    plt.plot(px, py, 'bo')
    plt.plot(u, spl(u), 'g-', lw=3, label='LSQ spline')
    plt.plot(u, z, 'k')
Example #13
0
def calligraphic_fit(points, loopiness):
    """Adds `loopiness` numer of loops along the curve where the curvature is highest."""
    CURVATURE_FLAT = 1
    LOOP_SIZE = 8

    ## normalize the points so that the paramters and constatns make more sense across different datasets
    points_means = points.mean(axis=0, keepdims=True)
    points_stds = points.std(axis=0, keepdims=True)
    points = (points - points_means) / points_stds

    ## fit a spline
    num_points = points.shape[0]
    u = np.linspace(0, 1, num_points)

    k = 3
    # the number of control points is about one third of the original number of points
    # determines the extend of the smoothing
    t = np.linspace(0, 1, num_points // 3)
    t = np.concatenate([[0] * k, t, [1] * k])

    spl = interp.make_lsq_spline(u, points, t, k=k)

    ## calc curvature and find extrema
    u2 = np.linspace(0, 1, num_points * 10)
    x = interp.splev(u2, spl)
    xdot = interp.splev(u2, spl, 1)
    xddot = interp.splev(u2, spl, 2)
    # see: https://www.math.tugraz.at/~wagner/Dreibein
    curvature = cross(xdot, xddot) / norm(xdot)**3

    mins, maxes = peakdet(curvature, delta=0)

    ## add `loopiness` number of loops where the curvature is highest
    peaks = np.concatenate([mins, maxes])
    peaks = sorted(peaks, key=lambda p: abs(curvature[p]), reverse=True)

    slices = []
    Slice = namedtuple("Slice", ["i", "j", "x"])
    for peak in peaks[:loopiness]:
        # find the first points left and right of the peak that have a low enough curvature
        for i in reversed(range(0, peak)):
            if np.sign(curvature[peak]) * curvature[i] <= CURVATURE_FLAT:
                break
        for j in range(peak + 1, len(curvature)):
            if np.sign(curvature[peak]) * curvature[j] <= CURVATURE_FLAT:
                break

        # extend the loop out from these low-curvature points
        C = line_line_intersect(x[i - 1], x[i], x[j], x[j + 1])
        # todo: maybe handle the case when there is no intersection
        loop = loop_the_loop(x[i], x[j], C, LOOP_SIZE)
        slices.append(Slice(i, j + 1, loop))

    x_new = replace_slices(x, slices)

    ## undo the normalization
    x_new = x_new * points_stds + points_means
    return x_new
def simple_lsq_spline(arr: xr.DataArray, order=3):
    xs = arr.coords[arr.dims[0]].values
    ys = arr.values

    knots = np.linspace(xs[0], xs[-1], order)
    t = np.r_[(xs[0],) * (order - 1), knots, (xs[-1],) * (order - 1)]

    spl = make_lsq_spline(xs, ys, t, order - 1)
    return spl
Example #15
0
def trajectory_to_coef(y, basis, basis_features, basis_dimension):
    """
    Given a trajectory, compute its associated coefficients for each
    state with respect to a functional basis.

    Inputs:
        - y: DataFrame
            Trajectory - Index has to start at 0
        - basis: string
            Name of the functional basis
        - basis_features: dict
            Contain information on the basis for each state
        - basis_dimension: dict
            Give the dimension of the basis for each state
    Output:
        - coef: list of pd.Series
            Each element of the list contains the coefficients of a
            state
    """
    # Define data on [0, 1] because each trajectory is considered as being
    # defined on [0,1]
    evaluation_points_nb = y.shape[0] - 1
    x = y.index / evaluation_points_nb
    coef = []
    if basis == 'legendre':
        # Compute coefficients for each state
        for state in basis_dimension:
            # NB: Use Legendre class to fix the domain of the basis
            least_square_fit = Legendre.fit(x,
                                            y[state],
                                            deg=basis_dimension[state]-1,
                                            domain=[0, 1])
            s = pd.Series(least_square_fit.coef, name=state)
            coef.append(s)
    elif basis == 'bspline':
        # Get internal knots
        t = basis_features['knots']
        # Compute coefficients for each state
        for state in basis_dimension:
            # Get degree
            k_state = basis_features[state]
            # Add external knots depending on the degree
            t_state = np.r_[(0,)*(k_state+1), t, (1,)*(k_state+1)]
            # Interpolate
            spl = make_lsq_spline(x, y[state], t_state, k_state)
            s = pd.Series(spl.c, name=state)
            coef.append(s)
    coef = np.array([c for series in coef for c in series.values])

    return coef
Example #16
0
    def test_lstsq(self):
        # check LSQ construction vs a full matrix version
        x, y, t, k = self.x, self.y, self.t, self.k

        c0, AY = make_lsq_full_matrix(x, y, t, k)
        b = make_lsq_spline(x, y, t, k)

        assert_allclose(b.c, c0)
        assert_equal(b.c.shape, (t.size - k - 1,))

        # also check against numpy.lstsq
        aa, yy = AY
        c1, _, _, _ = np.linalg.lstsq(aa, y)
        assert_allclose(b.c, c1)
    def test_lstsq(self):
        # check LSQ construction vs a full matrix version
        x, y, t, k = self.x, self.y, self.t, self.k

        c0, AY = make_lsq_full_matrix(x, y, t, k)
        b = make_lsq_spline(x, y, t, k)

        assert_allclose(b.c, c0)
        assert_equal(b.c.shape, (t.size - k - 1, ))

        # also check against numpy.lstsq
        aa, yy = AY
        c1, _, _, _ = np.linalg.lstsq(aa, y, rcond=-1)
        assert_allclose(b.c, c1)
Example #18
0
def test_1d_make_lsq(ndspline):
    N = 100
    stddev = 1E-3
    sample_x = np.sort(get_query_points(ndspline, n=N).squeeze())
    sample_y = ndspline(sample_x)
    signal_rms = (sample_y**2).sum(axis=0) / N
    snr_ratio = 10
    sample_y = sample_y + (signal_rms / snr_ratio) * np.random.random(
        sample_y.shape)
    # it was non-trivial to figure out the proper parameters for
    # scipy.interpolate. It needed specific knot sequence (possibly other
    # solutions) and sorted sample data. ndspline did not need either.
    for k in range(0, 4):
        knots = np.r_[(0.0, ) * (k + 1), 0.25, 0.5, 0.75, (1.0, ) * (k + 1)]

        # unweighted
        nspl = ndsplines.make_lsq_spline(sample_x, sample_y.copy(), [knots],
                                         [k])
        try:
            ispl = interpolate.make_lsq_spline(sample_x, sample_y.copy(),
                                               knots, k)
        except np.linalg.linalg.LinAlgError as e:
            if "leading minor" in e.__repr__():
                print(e)
        else:
            assert_allclose(nspl.coefficients.reshape(-1), ispl.c.reshape(-1))

        # random weights
        w = np.random.random(N)
        nspl = ndsplines.make_lsq_spline(sample_x, sample_y, [knots], [k], w)
        try:
            ispl = interpolate.make_lsq_spline(sample_x, sample_y, knots, k, w)
        except np.linalg.linalg.LinAlgError as e:
            if "leading minor" in e.__repr__():
                print(e)
        else:
            assert_allclose(nspl.coefficients.reshape(-1), ispl.c.reshape(-1))
Example #19
0
def bspline(X,Y,knots=8,k=3,lowclamp=False, highclamp=False):
    '''
    Returns a BSpline interpolation function
    of a provided 1D curve.
    With fewer knots, this will provide a
    smooth curve that ignores local wiggles.
    
    Parameters:
    -----------
    X,Y : np.ndarray
        1D arrays for the curve being interpolated.
    knots : int
        Number of INTERNAL knots, i.e. the number
        of breakpoints that are being considered
        when generating the BSpline.
    k : int
        Degree of the BSpline. Recommended to leave
        at 3.
    lowclamp : bool
        Enables or disables clamping at the lowest
        X-value.
    highclamp : bool
        Enables or disables clamping at the highest
        X-value.
        
    Returns:
    --------
    spl : scipy.interpolate._bsplines.BSpline
        Interpolation function that works over X's
        domain.
    '''
    
    # Creating the knots
    t_int = np.linspace(X.min(),X.max(),knots)  # Internal knots, incl. beginning and end points of domain.

    t_begin = np.linspace(X.min(),X.min(),k)
    t_end   = np.linspace(X.max(),X.max(),k)
    t = np.r_[t_begin,t_int,t_end]              # The entire knot vector.
    
    # Generating the spline
    w = np.zeros(X.shape)+1                     # Weights.
    if lowclamp==True:
        w[0]=X.max()*1000000                    # Setting a high weight for the X.min() term.
    if highclamp==True:
        w[-1]=X.max()*1000000                   # Setting a high weight for the X.max() term.
    spl = make_lsq_spline(X, Y, t, k,w)
    
    return spl
Example #20
0
def compute_spline(data, time, idx1, idx2, k):
    '''
    :param data: data
    :param time: time
    :param idx1: current index start
    :param idx2: current index end
    :param k: order of spline
    :return: t: knots
    '''
    idx2 = idx2-1
    variable = data[idx1:idx2]
    time = time[idx1:idx2]
    t = np.r_[(time[0],)*(k+1),  (time[-1],)*(k+1)]
    spl_lsq = make_lsq_spline(time, variable, t, k=k)
    residuals = np.power((variable - spl_lsq(time)),2)
    avg_sum_residuals = np.sum(residuals) #/ variable.shape[0] if uncomment do average per point
    return spl_lsq, avg_sum_residuals
Example #21
0
 def test_int_xy(self):
     x = np.arange(10).astype(np.int_)
     y = np.arange(10).astype(np.int_)
     t = _augknt(x, k=1)
     # cython chokes on "buffer type mismatch"
     make_lsq_spline(x, y, t, k=1)
Example #22
0
    def __getitem__(self, input_index):
        index = int(input_index % self.num_images)
        label_key = self.db_keys[index]
        label_key_idx = int(label_key.split("_")[1])
        images_start = label_key_idx - self.context_length + 1
        images_end = label_key_idx + 1
        packetrange = range(images_start, images_end)
        keys = ["image_%d" % (i, ) for i in packetrange]
        assert (keys[-1] == label_key)

        label = self.label_db_wrapper.getMultiAgentLabel(keys[-1])
        assert (keys[-1] + ".jpg" == label.image_tag.image_file)
        rtn_session_times = np.array(
            [p.session_time for p in label.ego_agent_trajectory.poses],
            dtype=np.float64)
        egopose = np.eye(4, dtype=np.float64)
        egopose[0:3, 3] = np.array([
            label.ego_agent_pose.translation.x,
            label.ego_agent_pose.translation.y,
            label.ego_agent_pose.translation.z
        ],
                                   dtype=np.float64)
        egopose[0:3, 0:3] = Rot.from_quat(
            np.array([
                label.ego_agent_pose.rotation.x,
                label.ego_agent_pose.rotation.y,
                label.ego_agent_pose.rotation.z,
                label.ego_agent_pose.rotation.w
            ],
                     dtype=np.float64)).as_matrix()
        egoposeinv = np.linalg.inv(egopose)

        raceline_local = np.matmul(egoposeinv,
                                   self.raceline_global)[0:3].transpose()
        #  print("raceline_local.shape: %s " % (str(raceline_local.shape),))
        raceline_distances = np.linalg.norm(raceline_local, ord=2, axis=1)
        # print("raceline_distances.shape: %s " % (str(raceline_distances.shape),))
        closestidx = np.argmin(raceline_distances)
        idxsamp = np.arange(closestidx - int(round(self.raceline_buffer / 3)),
                            closestidx + self.raceline_buffer + 1,
                            step=1,
                            dtype=np.int64) % raceline_local.shape[0]
        #   print("idxsamp.shape: %s " % (str(idxsamp.shape),))
        raceline_close = raceline_local[idxsamp]
        #    print("raceline_close.shape: %s " % (str(raceline_close.shape),))
        raceline_close = raceline_close[
            raceline_close[:, self.position_indices[0]] >= 0.0]
        raceline_close_dists = np.hstack([
            np.zeros(1, dtype=np.float64),
            np.cumsum(
                np.linalg.norm(raceline_close[1:] - raceline_close[:-1],
                               ord=2,
                               axis=1))
        ])
        k = 13
        spl: BSpline = make_lsq_spline(raceline_close_dists,
                                       raceline_close,
                                       sensibleKnots(raceline_close_dists, k),
                                       k=k)
        dsamp = np.linspace(0,
                            raceline_close_dists[-1],
                            num=rtn_session_times.shape[0])
        raceline_label = spl(dsamp)

        transform = self.transforms[int(input_index / self.num_images)]
        images_pil = [
            PILImage.fromarray(self.image_db_wrapper.getImage(key))
            for key in keys
        ]
        images_pil = [
            F.resize(transform(
                impil.crop([
                    0,
                    int(round(self.row_crop_ratio * impil.height)),
                    impil.width - 1, impil.height - 1
                ])),
                     self.image_size,
                     interpolation=PIL.Image.LANCZOS) for impil in images_pil
        ]
        images_torch = torch.stack([self.totensor(img) for img in images_pil])

        return images_torch, raceline_label[:, self.
                                            position_indices], dsamp, 0, 0, packetrange[
                                                -1]
Example #23
0
    def test_multiple_rhs(self):
        x, t, k, n = self.x, self.t, self.k, self.n
        y = np.random.random(size=(n, 5, 6, 7))

        b = make_lsq_spline(x, y, t, k)
        assert_equal(b.c.shape, (t.size-k-1, 5, 6, 7))
Example #24
0
def extract_oned_spec(path,
                      imgtype,
                      slit_along,
                      method='aper',
                      aper_param=None,
                      seeing=None,
                      order=None,
                      show=True,
                      save=True):
    '''
    '''

    filelist = sorted(glob(F'{path}/{imgtype}*.fits'))

    if len(filelist) == 0:
        raise FileExistsError(
            F'File {F"{path}/{imgtype}*.fits"} do not exist.')

    cnts_sc = list()
    errs_sc = list()
    cnts_bg = list()
    errs_bg = list()
    for i, f in enumerate(filelist):

        # Load image
        (img, err), _ = load_image(f, 0)

        # Transpose
        if slit_along == 'row':
            img = img.T
            err = err.T

        x = np.arange(img.shape[1])
        y = np.arange(img.shape[0])

        if method == 'median':
            print(
                F'[Extract 1-D Spectrum] Extract {i+1} of {len(filelist)} {imgtype} image [{method}]'
            )
            cnt_sc = np.median(img, axis=0)
            err_sc = np.sqrt((err**2).sum(axis=0)) / err.shape[0]

        elif method == 'aper':
            print(
                F'[Extract 1-D Spectrum] Estimate background for {i+1} of {len(filelist)} {imgtype} image [{method}]'
            )
            naper, aper_sc, aper_bg = aper_param
            guessidx = np.median(img, axis=1).argmax()
            maxidx = np.zeros(img.shape[1])
            for j in range(img.shape[1]):
                idxmin, idxmax = (guessidx - 1.5 * seeing).astype(int), (
                    guessidx + 1.5 * seeing).astype(int)
                maxidx[j] = idxmin + gaussian_filter(img[idxmin:idxmax, j],
                                                     sigma=seeing).argmax()


#             p = np.poly1d( np.polyfit( x, maxidx, 3 ) )
            knots = np.r_[(x[0], ) * (order + 1), (x[-1], ) * (order + 1)]
            spl = make_lsq_spline(x, maxidx, t=knots, k=order)
            maxloc = spl(x)

            locbgmin = (maxloc - aper_bg / 2)
            locbgmax = (maxloc + aper_bg / 2)

            cnt_tt = np.zeros([naper, img.shape[1]])
            err_tt = np.zeros([naper, img.shape[1]])
            cnt_bg = np.zeros([naper, img.shape[1]])
            err_bg = np.zeros([naper, img.shape[1]])
            img_bgsb = np.zeros(img.shape)
            apers = np.zeros([naper + 1, img.shape[1]])
            for j in range(img.shape[1]):
                # Background fitting
                idxbg = (y < locbgmin[j]) | (locbgmax[j] < y)
                p = np.poly1d(np.polyfit(y[idxbg], img[idxbg, j], 1))
                bg = p(y)
                # Extract 1-D spectra
                apers[:, j] = np.linspace(-aper_sc / 2, aper_sc / 2,
                                          naper + 1) + maxloc[j]
                locscmins, locscmaxs = apers[:-1, j], apers[1:, j]
                for k, (locscmin,
                        locscmax) in enumerate(zip(locscmins, locscmaxs)):
                    idxsc = (locscmin < y) & (y < locscmax)
                    # Background estimation
                    cnt_bg[k, j] = bg[idxsc].sum() + \
                                   bg[y[idxsc][ 0]-1] * ( y[idxsc][ 0] - locscmin ) + \
                                   bg[y[idxsc][-1]+1] * ( locscmax - y[idxsc][-1] )
                    # Background uncertainty
                    err_bg[k, j] = np.median(
                        err[idxbg, j]) * np.sqrt(locscmax - locscmin + 1)
                    # Total flux estimation
                    cnt_tt[k, j] = img[idxsc, j].sum() + \
                                   img[y[idxsc][ 0]-1, j] * ( y[idxsc][ 0] - locscmin ) +\
                                   img[y[idxsc][-1]+1, j] * ( locscmax - y[idxsc][-1] )
                    # Total flux uncertainty
                    err_tt[k, j] = np.sqrt( ( err[idxsc, j]**2 ).sum() + \
                                            ( err[y[idxsc][ 0]-1, j] * ( y[idxsc][ 0] - locscmin ) )**2 + \
                                            ( err[y[idxsc][-1]+1, j] * ( locscmax - y[idxsc][-1] ) )**2 )
                # Background subtraction
                img_bgsb[:, j] = img[:, j] - bg

            print(
                F'[Extract 1-D Spectrum] Estimate target flux and uncertainty for {i+1} of {len(filelist)} {imgtype} image [{method}]'
            )
            # Source flux estimation
            cnt_sc = cnt_tt - cnt_bg
            # Source flux uncertainty
            err_sc = np.sqrt(err_tt**2 + err_bg**2)

            cnts_bg.append(cnt_bg)
            errs_bg.append(err_bg)

            # 2-D plot
            title = F'2-D Background Subtracted {imgtype} image {str(i+1).zfill(len(str(len(filelist))))}'
            print(
                F'[Extract 1-D Spectrum] Plot 2-D background subtracted {imgtype} image from {i+1} of {len(filelist)} {imgtype} image',
                end='')

            fig, ax = plt.subplots(1, 1, figsize=(10, 8))
            fig.subplots_adjust(right=0.8)
            # Image
            vmin = -3 * np.std(img_bgsb, ddof=1)
            im = ax.imshow(img_bgsb,
                           vmin=vmin,
                           cmap='Greys_r',
                           origin='lower',
                           extent=(0.5, img_bgsb.shape[1] + 0.5, 0.5,
                                   img_bgsb.shape[0] + 0.5))
            # Background aperture
            ax.plot(x + 1, locbgmin + 1, 'lightskyblue', ls='--')
            ax.plot(x + 1, locbgmax + 1, 'lightskyblue', ls='--')
            # Target aperture
            for aper in apers:
                ax.plot(x + 1, aper + 1, 'yellow', ls='-')
            # Colorbar
            cax = fig.add_axes([
                ax.get_position().x1 + 0.02,
                ax.get_position().y0, 0.04,
                ax.get_position().height
            ])
            cb = fig.colorbar(im, cax=cax)
            # Settings
            ax.tick_params(which='major',
                           direction='in',
                           color='w',
                           top=True,
                           right=True,
                           length=7,
                           width=1.5,
                           labelsize=18)
            if slit_along == 'col':
                ax.set_xlabel('Dispersion', fontsize=22)
                ax.set_ylabel('Slit', fontsize=22)
            if slit_along == 'row':
                ax.set_xlabel('Slit', fontsize=22)
                ax.set_ylabel('Dispersion', fontsize=22)
            ax.set_title(title, fontsize=24)
            cb.ax.tick_params(which='major',
                              direction='in',
                              color='w',
                              right=True,
                              length=7,
                              width=1.5,
                              labelsize=18)
            cb.ax.set_ylabel('ADU', fontsize=22)
            if save:
                print(F' to `{ F"figs/{title}.png".replace( " ", "_" ) }`')
                if not os.path.exists('figs'): os.makedirs('figs')
                plt.savefig(F'figs/{title}.png'.replace(' ', '_'), dpi=144)
            else:
                print('')
            if show:
                print(F'[Extract 1-D Spectrum] Show plot')
                plt.show()
            plt.close()

        else:
            raise ValueError(
                'Unknown method. Only methods in [`median`, `aper`] are available.'
            )

        cnts_sc.append(cnt_sc)
        errs_sc.append(err_sc)

        # 1-D plot
        title = F'1-D Extracted {imgtype} Spectrum {str(i+1).zfill(len(str(len(filelist))))}'
        print(
            F'[Extract 1-D Spectrum] Plot 1-D spectrum extracted from {i+1} of {len(filelist)} {imgtype} image',
            end='')

        fig, ax = plt.subplots(1, 1, figsize=(12, 6))
        if method == 'median':
            # Target
            ax.step(x + 1, cnt_sc, where='mid', label='Target', zorder=3)
            ax.fill_between(x + 1,
                            cnt_sc - err_sc,
                            cnt_sc + err_sc,
                            color='C0',
                            alpha=0.2,
                            zorder=2)
        else:
            for m in range(cnt_sc.shape[0]):
                # Target
                if m == 0:
                    ax.step(x + 1,
                            cnt_sc[m],
                            where='mid',
                            color='C0',
                            zorder=3,
                            label='Target')
                else:
                    ax.step(x + 1,
                            cnt_sc[m],
                            where='mid',
                            color='C0',
                            zorder=3)
                ax.fill_between(x + 1,
                                cnt_sc[m] - err_sc[m],
                                cnt_sc[m] + err_sc[m],
                                color='C0',
                                alpha=0.2,
                                zorder=2)
            # Background
            ax.step(x + 1,
                    np.median(cnt_bg, axis=0),
                    where='mid',
                    color='C1',
                    label='Background',
                    zorder=1)
        # Settings
        ax.grid(axis='both', color='0.95', zorder=0)
        ax.set_xlim(x.min() + 1, x.max() + 1)
        ax.tick_params(which='major',
                       direction='in',
                       top=True,
                       right=True,
                       length=7,
                       width=1.5,
                       labelsize=18)
        ax.set_xlabel('Dispersion Direction [px]', fontsize=22)
        ax.set_ylabel('Counts', fontsize=22)
        ax.legend(fontsize=22)
        ax.set_title(title, fontsize=24)

        if save:
            print(F' to `{ F"figs/{title}.png".replace( " ", "_" ) }`')
            if not os.path.exists('figs'): os.makedirs('figs')
            plt.savefig(F'figs/{title}.png'.replace(' ', '_'), dpi=144)
        else:
            print('')
        if show:
            print('[Extract 1-D Spectrum] Show plot')
            plt.show()
        plt.close()

        # Write to file
        if not os.path.exists('bak'): os.makedirs('bak')
        file_path = F'bak/1-D_Extracted_{imgtype}_Spectrum_{str(i+1).zfill(len(str(len(filelist))))}.dat'
        print(
            F'[Extract 1-D Spectrum] Write 1-D spectrum extracted from {i+1} of {len(filelist)} {imgtype} image to `{file_path}`'
        )
        if method == 'median':
            np.savetxt(file_path, np.vstack([cnt_sc, err_sc]).T, fmt='%15.8e')
        else:
            np.savetxt(file_path,
                       np.vstack([cnt_sc, err_sc, cnt_bg, err_bg]).T,
                       fmt='%15.8e')

    if method == 'median':
        return (cnts_sc, errs_sc)
    else:
        return (cnts_sc, errs_sc), (cnts_bg, errs_bg)
    def compute_statistics(self, tf_dir=None):
        """
        Compute statistics of the transfer functions in a given directory.
        
        Statistics are:
            
            * one-lag autocorrelation coefficient, estimator for smoothness
            * average of errors on components
            * fit to a least-squres smooth curve
            * normalized standard deviation of the first derivative, another
              smoothness estimator
              
        :param tf_dir: path to directory of transfer functions
        :type tf_dir: string
        
        :returns: data frame of all the statistics estimated
        :rtype: pandas.DataFrame
        
        .. note:: Writes a file to the tf_dir named tf_quality_statistics.csv 
        """

        if tf_dir is not None:
            self.tf_dir = tf_dir

        edi_list = glob.glob('{0}\*.edi'.format(self.tf_dir))

        stat_array = np.zeros(len(edi_list),
                              dtype=[(key, np.float)
                                     for key in sorted(self.types)])
        station_list = []
        for kk, edi in enumerate(edi_list):
            mt_obj = mt.MT(edi)
            station_list.append(mt_obj.station)

            for ii in range(2):
                for jj in range(2):
                    flip = False
                    comp = self.z_dict[(ii, jj)]

                    ### locate bad points
                    bad_points_res = self.locate_bad_res_points(
                        mt_obj.Z.resistivity[:, ii, jj])
                    stat_array[kk]['bad_points_res_{0}'.format(comp)] = max(
                        [1, len(bad_points_res)])
                    bad_points_phase = self.locate_bad_phase_points(
                        mt_obj.Z.phase[:, ii, jj])
                    stat_array[kk]['bad_points_phase_{0}'.format(comp)] = max(
                        [1, len(bad_points_res)])
                    ### need to get the data points that are within the reasonable range
                    ### and not 0
                    nz_index = np.nonzero(mt_obj.Z.resistivity[:, ii, jj])
                    nz_index = np.delete(nz_index, bad_points_res)
                    nz_index = np.delete(nz_index, bad_points_phase)

                    f = mt_obj.Z.freq[nz_index]
                    res = mt_obj.Z.resistivity[nz_index, ii, jj]
                    res_err = mt_obj.Z.resistivity_err[nz_index, ii, jj]
                    phase = mt_obj.Z.phase[nz_index, ii, jj]
                    phase_err = mt_obj.Z.phase_err[nz_index, ii, jj]

                    if len(f) < 2:
                        print(mt_obj.station, comp, nz_index)
                        continue

                    # need to sort the array to be ordered with assending
                    # frequency.  Check to see if f is ascending, if not flip
                    if f[0] > f[1]:
                        flip = True
                        f = f[::-1]
                        res = res[::-1]
                        res_err = res_err[::-1]
                        phase = phase[::-1]
                        phase_err = phase_err[::-1]

                    ### make parameter for least squares fit
                    k = 7  # order of the fit
                    # knots, has to be at least to the bounds of f
                    t = np.r_[(f[0], ) * (k + 1), [min(1, f.mean())],
                              (f[-1], ) * (k + 1)]

                    ### estimate a least squares fit
                    try:
                        ls_res = interpolate.make_lsq_spline(f, res, t, k)
                        ls_phase = interpolate.make_lsq_spline(f, phase, t, k)

                        ### compute a standard deviation between the ls fit and data
                        stat_array[kk]['res_{0}_fit'.format(comp)] = (
                            res - ls_res(f)).std()
                        stat_array[kk]['phase_{0}_fit'.format(comp)] = (
                            phase - ls_phase(f)).std()
                    except (ValueError, np.linalg.LinAlgError) as error:
                        stat_array[kk]['res_{0}_fit'.format(comp)] = np.NaN
                        stat_array[kk]['phase_{0}_fit'.format(comp)] = np.NaN
                        print('{0} {1} {2}'.format(mt_obj.station, comp,
                                                   error))
                    ### taking median of the error is more robust
                    stat_array[kk]['res_{0}_std'.format(comp)] = np.median(
                        res_err)
                    stat_array[kk]['phase_{0}_std'.format(comp)] = np.median(
                        phase_err)

                    ### estimate smoothness
                    stat_array[kk]['res_{0}_corr'.format(comp)] = np.corrcoef(
                        res[0:-1], res[1:])[0, 1]
                    stat_array[kk]['phase_{0}_corr'.format(
                        comp)] = np.corrcoef(phase[0:-1], phase[1:])[0, 1]

                    ### estimate smoothness with difference
                    stat_array[kk]['res_{0}_diff'.format(comp)] = np.abs(
                        np.median(np.diff(res)))
                    stat_array[kk]['phase_{0}_diff'.format(comp)] = np.abs(
                        np.median(np.diff(phase)))

                    ### compute tipper
                    if ii == 0:
                        tcomp = self.t_dict[(0, jj)]
                        t_index = np.nonzero(mt_obj.Tipper.amplitude[:, 0, jj])
                        bad_points_t = self.locate_bad_tipper_points(
                            mt_obj.Tipper.amplitude[:, 0, jj])
                        stat_array[kk]['bad_points_tipper_{0}'.format(
                            tcomp)] = max([1, len(bad_points_t)])
                        t_index = np.delete(t_index, bad_points_t)
                        if t_index.size == 0:
                            continue
                        else:
                            tmag = mt_obj.Tipper.amplitude[t_index, 0, jj]
                            tmag_err = mt_obj.Tipper.amplitude_err[t_index, 0,
                                                                   jj]
                            tip_f = mt_obj.Tipper.freq[t_index]
                            if flip:
                                tmag = tmag[::-1]
                                tmag_err = tmag_err[::-1]
                                tip_f = tip_f[::-1]
                            tip_t = np.r_[(tip_f[0], ) * (k + 1),
                                          [min(1, tip_f.mean())],
                                          (tip_f[-1], ) * (k + 1)]
                            try:
                                ls_tmag = interpolate.make_lsq_spline(
                                    tip_f, tmag, tip_t, k)
                                stat_array[kk]['tipper_{0}_fit'.format(
                                    tcomp)] = np.std(tmag - ls_tmag(tip_f))
                            except (ValueError,
                                    np.linalg.LinAlgError) as error:

                                stat_array[kk]['tipper_{0}_fit'.format(
                                    tcomp)] = np.NaN
                                print('{0} {1} {2}'.format(
                                    mt_obj.station, tcomp, error))
                            stat_array[kk]['tipper_{0}_std'.format(
                                tcomp)] = tmag_err.mean()
                            stat_array[kk]['tipper_{0}_corr'.format(
                                tcomp)] = np.corrcoef(tmag[0:-1], tmag[1:])[0,
                                                                            1]
                            stat_array[kk]['tipper_{0}_diff'.format(
                                tcomp)] = np.std(np.diff(tmag)) / abs(
                                    np.mean(np.diff(tmag)))

        ### write file
        df = pd.DataFrame(stat_array, index=station_list)
        df = df.replace(0, np.NAN)
        df.to_csv(os.path.join(self.tf_dir, 'tf_quality_statistics.csv'),
                  index=True,
                  na_rep='NaN')

        return df
Example #26
0
def sens_func(wav,
              cnt,
              exp,
              seeing,
              sw,
              airmass,
              extfile,
              stdfile,
              wave_range,
              order,
              show=1,
              save=0):
    '''
    '''

    # Speed of light
    c = 2.99792458e+10  # [cm/s]

    inverse = False
    if wav[1] < wav[0]:
        wav = wav[::-1]
        cnt = cnt[::-1]
        inverse = True

    # Slit loss correction
    # --------------------
    print(
        F'[Sensitivity function] Slit loss correction: FWHM = {seeing:.2f} [px], Slit Width = {sw:.2f} [px]'
    )
    sl = get_slit_loss(fwhm=seeing, sw=sw)
    cnt = cnt / (1 - sl)

    # Atmospheric extinction correction
    # ---------------------------------
    print(
        '[Sensitivity function] Extinction correction: Load extinction coefficients'
    )
    wav_ext, ext = np.loadtxt(extfile).T
    print('[Sensitivity function] Extinction correction: Dereddening')
    ext = interp1d(wav_ext,
                   ext,
                   kind='quadratic',
                   bounds_error=False,
                   fill_value='extrapolate')(wav)
    ext_corr_factor = 10**(0.4 * airmass * ext)
    cnt = cnt * ext_corr_factor

    # Convert to counts/A/s
    # ---------------------
    # 1. Bandpass
    dwav = np.abs(np.diff(wav))
    dwav = np.hstack([dwav[0], dwav, dwav[-1]])
    dwav = (dwav[:-1] + dwav[1:]) / 2
    # 2. Convert
    cnt = cnt / dwav / exp

    # Sensitivity function
    # --------------------
    if not os.path.exists(os.path.join(os.getcwd(), stdfile)):
        if not os.path.exists(
                os.path.join(
                    os.path.split(os.path.realpath(__file__))[0], 'onedstds/',
                    stdfile)):
            raise FileNotFoundError('No standard file found.')
            sys.exit()
        else:
            stdfile = os.path.join(
                os.path.split(os.path.realpath(__file__))[0], 'onedstds/',
                stdfile)
    else:
        stdfile = os.path.join(os.getcwd(), stdfile)
    # 1. Load standard spectrum
    print('[Sensitivity function] Load archived standard spectrum')
    if os.path.split(os.path.split(stdfile)[0])[1] == 'calspec':
        tab = Table.read(stdfile)
        wav_mag = tab['WAVELENGTH'].data
        flx_mod = tab['FLUX'].data
        bp = tab['FWHM'].data
    else:
        stdspec = np.loadtxt(stdfile, skiprows=1).T
        if stdspec.shape[0] == 3:
            wav_mag, mag, bp = stdspec
        elif stdspec.shape[0] == 2:
            wav_mag, mag = stdspec
            dwav_mag = np.abs(np.diff(wav_mag))
            dwav_mag = np.hstack([dwav_mag[0], dwav_mag, dwav_mag[-1]])
            bp = (dwav_mag[:-1] + dwav_mag[1:]) / 2
        flx_mod = 10**(-0.4 *
                       mag) * 3631e-23 * c / wav_mag**2 * 1e8  # [erg/cm2/s/A]
    # 2. Comparision
    print('[Sensitivity function] Comparision')
    flx_obs = np.zeros(flx_mod.shape[0])
    bins = np.vstack([wav_mag - bp / 2, wav_mag + bp / 2]).T
    for i, bin in enumerate(bins):
        idx = (bin[0] < wav) & (wav < bin[1])
        edges = interp1d(wav,
                         cnt,
                         'linear',
                         bounds_error=False,
                         fill_value=np.nan)(bin)
        flx_obs[i] = np.trapz(np.hstack([edges[0], cnt[idx], edges[1]]),
                              x=np.hstack([bin[0], wav[idx], bin[1]
                                           ])) / (bin[1] - bin[0])
    sen = flx_obs / flx_mod
    # 3. Filter NaN
    idx = np.isnan(sen)
    wav_sen = wav_mag[~idx]
    sen = 2.5 * np.log10(sen[~idx])

    print('[Sensitivity function] Fitting')
    mask = ~np.isnan(sen) & (wave_range[0] < wav_sen) & (wav_sen <
                                                         wave_range[1])
    for i in range(5):
        knots = np.r_[(wav_sen[mask][0], ) * (order + 1),
                      (wav_sen[mask][-1], ) * (order + 1)]
        spl = make_lsq_spline(wav_sen[mask], sen[mask], t=knots, k=order)
        mask = mask & ~sigma_clip(
            sen - spl(wav_sen), sigma=0.5, maxiters=1, masked=True).mask

    sen_fit = spl(wav)

    # Plot
    print('[Sensitivity function] Plot fitted sensitivity function', end='')
    fig, ax = plt.subplots(2, 1, figsize=(12, 12))
    # Sensitivity function
    ax[0].plot(wav_sen[mask], sen[mask], '+', color='black', ms=10)
    ax[0].plot(wav_sen[~mask], sen[~mask], '+', color='lightgrey', ms=10)
    ax[0].plot(wav, sen_fit, '-', c='red', lw=2)
    # Settings
    ax[0].grid(axis='both', color='0.95', zorder=0)
    ax[0].set_xlim(wav.min(), wav.max())
    ax[0].tick_params(which='major',
                      direction='in',
                      top=True,
                      right=True,
                      length=7,
                      width=1.5,
                      labelsize=18)
    ax[0].set_ylabel('Sensitivity Function', fontsize=22)
    ax[0].set_title('Sensitivity Function', fontsize=24)

    ax[1].plot(wav_sen[mask], (sen - spl(wav_sen))[mask],
               '+',
               color='black',
               ms=10,
               zorder=1)
    ax[1].plot(wav_sen[~mask], (sen - spl(wav_sen))[~mask],
               '+',
               color='lightgrey',
               ms=10,
               zorder=0)
    ax[1].axhline(y=0, c='red', ls='--', zorder=2)
    # Settings
    ax[1].grid(axis='both', color='0.95')
    ax[1].set_xlim(wav.min(), wav.max())
    ax[1].set_ylim((sen - spl(wav_sen))[mask].min() * 0.8,
                   (sen - spl(wav_sen))[mask].max() * 1.2)
    ax[1].tick_params(which='major',
                      direction='in',
                      top=True,
                      right=True,
                      length=7,
                      width=1.5,
                      labelsize=18)
    ax[1].set_xlabel('Wavelength [$\\mathrm{\\AA}$]', fontsize=22)
    ax[1].set_ylabel('Residuals', fontsize=22)
    fig.align_ylabels()

    if save:
        print(' to `figs/Sensitivity_Function.png`')
        plt.savefig('figs/Sensitivity_Function.png', dpi=144)
    else:
        print('')

    if show:
        print('[Sensitivity function] Show plot')
        plt.show()
    plt.close()

    if inverse:
        sen_fit = sen_fit[::-1]
        wav = wav[::-1]
        cnt = cnt[::-1]

    # Write to file
    if not os.path.exists('cal'): os.makedirs('cal')
    file_path = F'cal/SensFunc.dat'
    print(
        F'[Sensitivity function] Write sensitivity function to `{file_path}`')
    np.savetxt(file_path, np.vstack([wav, sen_fit]).T, fmt='%15.8e')

    return sen_fit
Example #27
0
    def compute_statistics(self, tf_dir=None):
        """
        compute some statistics
        """

        if tf_dir is not None:
            self.tf_dir = tf_dir

        edi_list = glob.glob("{0}\*.edi".format(self.tf_dir))

        stat_array = np.zeros(len(edi_list),
                              dtype=[(key, np.float)
                                     for key in sorted(self.types)])
        station_list = []
        for kk, edi in enumerate(edi_list):
            mt_obj = mt.MT(edi)
            station_list.append(mt_obj.station)

            for ii in range(2):
                for jj in range(2):
                    comp = self.z_dict[(ii, jj)]
                    res = mt_obj.Z.resistivity[:, ii, jj]
                    ### need to get the data points that are within the reasonable range
                    ### and not 0
                    nz_index = np.where((res > 10e-5) & (res < 10e9)
                                        & (res != 0.0))

                    res = res[nz_index][::-1]
                    res_err = mt_obj.Z.resistivity_err[nz_index, ii,
                                                       jj][0][::-1]
                    phase = mt_obj.Z.phase[nz_index, ii, jj][0][::-1]
                    phase_err = mt_obj.Z.phase_err[nz_index, ii, jj][0][::-1]
                    f = mt_obj.Z.freq[nz_index][::-1]
                    ### make parameter for least squares fit
                    k = 7  # order of the fit
                    # knots, has to be at least to the bounds of f
                    t = np.r_[(f[0], ) * (k + 1), [1], (f[-1], ) * (k + 1)]

                    ### estimate a least squares fit
                    ls_res = interpolate.make_lsq_spline(f, res, t, k)
                    ls_phase = interpolate.make_lsq_spline(f, phase, t, k)

                    ### compute a standard deviation between the ls fit and data
                    stat_array[kk]["res_{0}_fit".format(comp)] = (
                        res - ls_res(f)).std()
                    stat_array[kk]["phase_{0}_fit".format(comp)] = (
                        phase - ls_phase(f)).std()

                    stat_array[kk]["res_{0}_std".format(comp)] = res_err.mean()
                    stat_array[kk]["phase_{0}_std".format(
                        comp)] = phase_err.mean()

                    ### estimate smoothness
                    stat_array[kk]["res_{0}_corr".format(comp)] = np.corrcoef(
                        res[0:-1], res[1:])[0, 1]
                    stat_array[kk]["phase_{0}_corr".format(
                        comp)] = np.corrcoef(phase[0:-1], phase[1:])[0, 1]

                    ### estimate smoothness with difference
                    stat_array[kk]["res_{0}_diff".format(comp)] = np.std(
                        np.diff(res)) / abs(np.mean(np.diff(res)))
                    stat_array[kk]["phase_{0}_diff".format(comp)] = np.std(
                        np.diff(phase)) / abs(np.mean(np.diff(phase)))
                    ### compute tipper
                    if ii == 0:
                        tcomp = self.t_dict[(0, jj)]
                        t_index = np.nonzero(mt_obj.Tipper.amplitude[:, 0, jj])
                        if t_index[0].size == 0:
                            continue
                        else:
                            tmag = mt_obj.Tipper.amplitude[t_index, 0,
                                                           jj][0][::-1]
                            tmag_err = mt_obj.Tipper.amplitude_err[t_index, 0,
                                                                   jj][0][::-1]
                            tf = mt_obj.Tipper.freq[t_index][::-1]
                            ls_tmag = interpolate.make_lsq_spline(
                                tf, tmag, t, k)
                            stat_array[kk]["tipper_{0}_fit".format(
                                tcomp)] = np.std(tmag - ls_tmag(tf))
                            stat_array[kk]["tipper_{0}_std".format(
                                tcomp)] = tmag_err.mean()
                            stat_array[kk]["tipper_{0}_corr".format(
                                tcomp)] = np.corrcoef(tmag[0:-1], tmag[1:])[0,
                                                                            1]
                            stat_array[kk]["tipper_{0}_diff".format(
                                tcomp)] = np.std(np.diff(tmag)) / abs(
                                    np.mean(np.diff(tmag)))

        ### write file
        df = pd.DataFrame(stat_array, index=station_list)
        df.to_csv(os.path.join(edi_dir, "data_quality_statistics.csv"),
                  index=True)

        return df
Example #28
0
    def get_zp_shift( self, order, show, save ):
        '''
        A method to get zeropoint shift along dispersion axis.

        Parameters
        ----------
        order : int
            Order used in polyfit.
        show : bool
            If `True`, the plot will be shown.
        save : bool
            If `True`, the plot will be written to file.

        Returns
        -------
        self.shift : array_like
            Fitted zeropoint shift.
        '''

        # Derive zeropoint shift
        # ----------------------
        shift = np.array([])
        for k, img in enumerate( self.imgs ):

            if self.slit_along == 'col': data = img * 1
            if self.slit_along == 'row': data = img.T

            # Find peaks
            # ----------
            print( F'[Zeropoint correction] Seeking for peaks in the {k+1}/{self.num} images' )
            peaks, properties = find_peaks( data.mean( axis = 0 ) / data.mean( axis = 0 ).max(), 
                                            height = ( 0.3, 0.8 ), 
                                            distance = data.shape[1] // 10,
                                            width = 0 )
            # Print peak info.
            tab = PrettyTable( hrules = HEADER, vrules = NONE )
            tab.field_names = [ 'CENTER', 'HEIGHT', 'WIDTH' ]
            for i, peak in enumerate( peaks ):
                tab.add_row([ peak, round( properties['peak_heights'][i], 2 ), int( properties['widths'][i] ) ])
            print( '\n' + tab.get_string() + '\n' )

            # Gaussian fitting
            x = np.arange( data.shape[1] )
            mu = np.zeros([ data.shape[0], len( peaks ) ])
            for i in range( data.shape[0] ):
                print( F'\r[Zeropoint correction] Peak center fitting in the ({i+1}/{data.shape[0]})-th row of {k+1}/{self.imgs.shape[0]} images', end = '', flush = True )
                for j, peak in enumerate( peaks ):
                    idxmin, idxmax = peak - int( properties['widths'][j] ), peak + int( properties['widths'][j] )
                    popt, pcov = curve_fit( Gaussian, 
                                            x[idxmin:idxmax], 
                                            data[i, idxmin:idxmax], 
                                            bounds = ( [data[i, idxmin:idxmax].max()*0.5, x[idxmin:idxmax].min(), 0 ], 
                                                       [data[i, idxmin:idxmax].max()*1.5, x[idxmin:idxmax].max(), x[idxmin:idxmax].shape[0] ] ) )
                    mu[i, j] = popt[1]
            # Convert to relative shift
            shift = np.hstack([ shift.reshape( mu.shape[0], -1 ), ( mu - mu[mu.shape[0]//2] ) ])
            print( '' )
        # Mean
        shift_mean = shift.mean( axis = 1 )

        # Polyfit to shift curve
        # ----------------------
        print( F'[Zeropoint correction] Fitting zeropoint shift iteratively (order = {order}, 5 iterations, nsigma = 1)' )
        y = np.arange( shift_mean.shape[0] ) + 1
        mask = np.ones( shift_mean.shape[0], dtype = bool )
        for k in range( 5 ):
            knots = np.r_[ ( y[mask][0], ) * ( order + 1 ), ( y[mask][-1], ) * ( order + 1 ) ]
            spl = make_lsq_spline( y[mask], shift_mean[mask], t = knots, k = order )
            mask = mask & ~sigma_clip( shift_mean - spl( y ), sigma = 1, maxiters = 1, masked = True ).mask
#             p = np.poly1d( np.polyfit( y[mask], shift_mean[mask], order ) )
#             shift_fit = p( y )
#             mask = mask & ( ~sigma_clip( shift_mean - shift_fit, sigma = 1, maxiters = 1, masked = True ).mask )
        self.shift = spl( y )

        # Write to file
        # -------------
        if not os.path.exists( 'bak' ): os.makedirs( 'bak' )
        np.savetxt( 'bak/zp_shift.dat', self.shift, fmt = '%15.8e' )

        # Plot
        # ----
        fig, ax = plt.subplots( 2, 1, figsize = ( 10, 8 ) )
        fig.subplots_adjust( hspace = 0 )
        
        # Shifts
        for i in range( shift.shape[1] ):
            ax[0].plot( y, shift[:, i], 'r+' )
        ax[0].plot( y[~mask], shift_mean[~mask], '+', c = 'grey' )
        ax[0].plot( y[mask], shift_mean[mask], 'k+' )
        # Fitted shifts
        ax[0].plot( self.shift, '-', c = 'yellow', lw = 2 )
        # Settings
        ax[0].set_xlim( y.min(), y.max() )
        ax[0].tick_params( which = 'major', direction = 'in', top = True, right = True, length = 7, width = 1.5, labelsize = 18 )
        ax[0].set_xticklabels([])
        ax[0].set_ylabel( 'Displacement [px]', fontsize = 22 )
        ax[0].set_title( 'Zeropoint Shift Curve Fitting', fontsize = 24 )
        
        # Residuals
        ax[1].plot( y[mask],  shift_mean[mask]  - self.shift[mask], 'k+' )
        ax[1].plot( y[~mask], shift_mean[~mask] - self.shift[~mask], '+', c = 'grey' )
        # Settings
        ax[1].axhline( y = 0, ls = '--', c = 'yellow', lw = 2 )
        ax[1].set_xlim( y.min(), y.max() )
        ax[1].tick_params( which = 'major', direction = 'in', top = True, right = True, length = 7, width = 1.5, labelsize = 18 )
        ax[1].set_xlabel( 'Slit', fontsize = 22 )
        ax[1].set_ylabel( 'Residuals [px]', fontsize = 22 )
        fig.align_ylabels()
        
        if save:
            fig_path = 'figs'
            print( F'[Zeropoint correction] Plot zeropoint shift curve fitting to `{ os.path.join( fig_path, "Zeropoint_shift_fitting.png" ) }`' )
            plt.savefig( os.path.join( fig_path, 'Zeropoint_shift_curve_fitting.png' ), dpi = 144 )
        if show:
            print( F'[Zeropoint correction] Show plot' )
            plt.show()
        plt.close()

        return deepcopy( self.shift )
    def test_multiple_rhs(self):
        x, t, k, n = self.x, self.t, self.k, self.n
        y = np.random.random(size=(n, 5, 6, 7))

        b = make_lsq_spline(x, y, t, k)
        assert_equal(b.c.shape, (t.size - k - 1, 5, 6, 7))
Example #30
0
def compute_bspline_dot_product_derivatives(basis_features, basis_dimension):
    """
    Compute dot products of B-splines and their derivatives.

    Input:
        - basis_features: dict
            Contain information on the basis for each state
        - basis_dimension: dict
            Give the number of basis functions for each state
    Outputs:
        - dot_product_12: ndarray
            Array containing the dot products of Legendre polynomials
            with their derivatives
        - dot_product_22: ndarray
            Array containing the dot products of Legendre polynomials
            derivatives
    """
    # Compute the dimension of the problem
    dimension = np.sum([basis_dimension[elt] for elt in basis_dimension])
    # Get the knots
    t = basis_features['knots']
    # FIXME: Consider small parameter to avoid vanishing of the last B-spline
    # at 1
    eps = 1e-16

    dot_product_12 = np.zeros([dimension, dimension])
    dot_product_22 = np.zeros([dimension, dimension])
    i, j = 0, 0
    # Loop over states
    for state1 in basis_dimension:
        # Get degree of the B-splines of state1
        k1 = basis_features[state1]
        # Add external knots depending on the degree
        t1 = np.r_[(0, ) * (k1 + 1), t, (1, ) * (k1 + 1)]
        for state2 in basis_dimension:
            # Get degree of the B-splines of state2
            k2 = basis_features[state2]
            # Add external knots depending on the degree
            t2 = np.r_[(0, ) * (k2 + 1), t, (1, ) * (k2 + 1)]
            for m in range(basis_dimension[state1]):
                # Define m-th B-spline of the state1 basis
                spl_m = BSpline.basis_element(t1[m:m + k1 + 2])
                # Reproduce the same spline for differenciation because of
                # differenciation problems with BSpline.basis_element()
                # FIXME: simplify if possible
                # Construct knots by first finding the internal knots and then
                # by adding the right numbers of external knots
                t1m = t1[m:m + k1 + 2]
                ind_min1 = np.max(np.argwhere(t1m == t1[m]))
                ind_max1 = np.min(np.argwhere(t1m == t1[m + k1 + 1]))
                t_m = np.r_[(t1m[ind_min1], ) * k1, t1m[ind_min1:ind_max1 + 1],
                            (t1m[ind_max1], ) * k1]
                x_m = np.linspace(t1m[0], t1m[-1] - eps, 50)
                spl_m = make_lsq_spline(x_m, spl_m(x_m), t_m, k1)
                # Compute derivative
                spl_m_deriv = spl_m.derivative(nu=1)
                for n in range(basis_dimension[state2]):
                    # Define n-th B-spline of the state2 basis
                    spl_n = BSpline.basis_element(t2[n:n + k2 + 2])
                    # FIXME: simplify if possible
                    # Construct knots by first finding the internal knots and
                    # then by adding the right numbers of external knots
                    t2n = t2[n:n + k2 + 2]
                    ind_min2 = np.max(np.argwhere(t2n == t2[n]))
                    ind_max2 = np.min(np.argwhere(t2n == t2[n + k2 + 1]))
                    t_n = np.r_[(t2n[ind_min2], ) * k2,
                                t2n[ind_min2:ind_max2 + 1],
                                (t2n[ind_max2], ) * k2]
                    x_n = np.linspace(t2n[0], t2n[-1] - eps, 50)
                    spl_n = make_lsq_spline(x_n, spl_n(x_n), t_n, k2)
                    # Compute derivative
                    spl_n_deriv = spl_n.derivative(nu=1)
                    max_t = max(t1[m], t2[n])
                    min_t = min(t1[m + k1 + 1], t2[n + k2 + 1])
                    # If intersection of supports then do computations
                    if max_t < min_t:
                        # Numerical integration
                        quad_int_12 = quad(lambda x: spl_m(x) * spl_n_deriv(x),
                                           max_t, min_t)
                        quad_int_22 = quad(
                            lambda x: spl_m_deriv(x) * spl_n_deriv(x), max_t,
                            min_t)
                        dot_product_12[i + m, j + n] += quad_int_12[0]
                        dot_product_22[i + m, j + n] += quad_int_22[0]
            j += basis_dimension[state2]
        j = 0
        i += basis_dimension[state1]

    return dot_product_12, dot_product_22
Example #31
0
 def spline_fit(y):
     bspl = interp.make_lsq_spline(x=x, y=y, t=knots, k=order)
     return bspl(x)
Example #32
0
import numpy as np

x = np.linspace(-15, 15, 200)
y = np.exp(-x**2) + 0.1 * np.random.randn(200)

from scipy.interpolate import make_lsq_spline, BSpline
t = [-1, 0, 1]
k = 4
t = np.r_[(x[0], ) * (k + 1), t, (x[-1], ) * (k + 1)]
print(t)
spl = make_lsq_spline(x, y, t, k)

from scipy.interpolate import make_interp_spline
spl_i = make_interp_spline(x, y)

import matplotlib.pyplot as plt
# xs = np.linspace(-3, 3, 100)
xs = x
plt.plot(x, y, 'ro', ms=5)
plt.plot(xs, spl(xs), 'g-', lw=3, label='LSQ spline')
plt.plot(xs, spl_i(xs), 'b-', lw=3, alpha=0.7, label='interp spline')
plt.legend(loc='best')
plt.show()
# Generate some noisy data:

x = np.linspace(-3, 3, 50)
y = np.exp(-x**2) + 0.1 * np.random.randn(50)

# Now fit a smoothing cubic spline with a pre-defined internal knots.
# Here we make the knot vector (k+1)-regular by adding boundary knots:

from scipy.interpolate import make_lsq_spline, BSpline
t = [-1, 0, 1]
k = 3
t = np.r_[(x[0], ) * (k + 1), t, (x[-1], ) * (k + 1)]
spl = make_lsq_spline(x, y, t, k)

# For comparison, we also construct an interpolating spline for the same
# set of data:

from scipy.interpolate import make_interp_spline
spl_i = make_interp_spline(x, y)

# Plot both:

import matplotlib.pyplot as plt
xs = np.linspace(-3, 3, 100)
plt.plot(x, y, 'ro', ms=5)
plt.plot(xs, spl(xs), 'g-', lw=3, label='LSQ spline')
plt.plot(xs, spl_i(xs), 'b-', lw=3, alpha=0.7, label='interp spline')
plt.legend(loc='best')
plt.show()

# **NaN handling**: If the input arrays contain ``nan`` values, the result is
 def test_int_xy(self):
     x = np.arange(10).astype(np.int_)
     y = np.arange(10).astype(np.int_)
     t = _augknt(x, k=1)
     # cython chokes on "buffer type mismatch"
     make_lsq_spline(x, y, t, k=1)
def apply_fitting_fields(plotgui):
    """
    Apply the set fitting parameters from the window.

    This routine reads the fitting parameters from the window and then
    applies the fitting.  Each time it is called a new data set should
    be generated, unless the fit order is too large for the number of
    points.  The fit order must be at most 1 less than the number
    of points, otherwise the routine just shows an error message
    pop-up and returns.

    Parameters
    ----------

        plotgui:   by assumption a matplotlib_user_interface object

    Returns
    -------

       None

    """
    fit_type = plotgui.set_fitting_fields[0].get()
    if 'Cubic Spline' in fit_type:
        fit_order = float(plotgui.set_fitting_fields[1].get())
    else:
        try:
            fit_order = int(plotgui.set_fitting_fields[1].get())
        except ValueError:
            str1 = 'Error: bad fit order (%s).  Settng to 4.' % (
                plotgui.set_fitting_fields[1].get())
            plotgui.fit_text.insert(Tk.END, str1)
            plotgui.fit_text.see(Tk.END)
            fit_order = 4
    set_number = plotgui.set_fitting_list_area.current()
    fit_flag = plotgui.fit_option.get()
    if fit_flag == 0:
        xvalues = numpy.copy(plotgui.xdata[set_number]['values'])
        yvalues = numpy.copy(plotgui.ydata[set_number]['values'])
    else:
        xvalues = numpy.copy(plotgui.ydata[set_number]['values'])
        yvalues = numpy.copy(plotgui.xdata[set_number]['values'])
    inds = numpy.argsort(xvalues)
    xvalues = xvalues[inds]
    yvalues = yvalues[inds]
    npoints = len(xvalues)
    if ('Spline' not in fit_type) and ('Internal' not in fit_type):
        if npoints + 1 <= fit_order:
            tkinter.messagebox.showinfo(
                'Error', 'The number of points is too few for the fit order.' +
                '  Please check your inputs.')
            return
    xmin = numpy.min(xvalues)
    xmax = numpy.max(xvalues)
    delx = xmax - xmin
    xstep = 1.2 * delx / 1201.
    xout = numpy.arange(xmin - delx / 10., xmax + delx / 10., xstep)
    if 'Internal' in fit_type:
        if npoints < 2:
            tkinter.messagebox.showinfo(
                'Error', 'The number of points is too few for a linear fit.' +
                '  Please check your inputs.')
            return
        if fit_flag == 0:
            yerrors = (plotgui.ydata[set_number]['lowerror'] +
                       plotgui.ydata[set_number]['higherror']) / 2.
        else:
            yerrors = (plotgui.xdata[set_number]['lowerror'] +
                       plotgui.xdata[set_number]['higherror']) / 2.
        if (numpy.min(yerrors) == 0.) and (numpy.max(yerrors) == 0.):
            yerrors = yerrors + 1.
        slope, intercept, slope_error, intercept_error, covariance, \
            correlation = general_utilities.slope_calculation(
                xvalues, yvalues, yerrors)
        if slope is None:
            tkinter.messagebox.showinfo('Error',
                                        'Error in the standard slope fit.\n')
            return
        yfit = intercept + xvalues * slope
        yout = intercept + xout * slope
        errorterm1 = xout * 0. + intercept_error
        errorterm2 = xout * slope_error
        youterror = numpy.sqrt(errorterm1 * errorterm1 +
                               errorterm2 * errorterm2)
        labelstring = 'Standard linear fit'
        rms = numpy.sqrt(numpy.mean((yvalues - yfit) * (yvalues - yfit)))
        str1 = 'Regression calculation results:\n'
        str1 = str1 + 'Slope: %g +/- %g\n' % (slope, slope_error)
        str1 = str1 + 'Intercept: %g +/- %g\n' % (intercept, intercept_error)
        str1 = str1 + 'Covariance: %f\n' % (covariance)
        str1 = str1 + 'Correlation: %f\n' % (correlation)
        str1 = str1 + 'RMS deviation: %f\n' % (rms)
        tkinter.messagebox.showinfo('Information', str1)
        outfile = open('fit_values.txt', 'a')
        print(str1, file=outfile)
        print(' ', file=outfile)
        outfile.close()
    if fit_type == 'Polynomial':
        fitpars = polynomial.polyfit(xvalues, yvalues, fit_order)
        yout = polynomial.polyval(xout, fitpars)
        yfit = polynomial.polyval(xvalues, fitpars)
        labelstring = 'Order %d polynomial fit' % (fit_order)
        general_utilities.list_polynomial_fitpars(fit_type, fit_order, fitpars)
    if fit_type == 'Legendre':
        fitpars = legendre.legfit(xvalues, yvalues, fit_order)
        yout = legendre.legval(xout, fitpars)
        yfit = legendre.legval(xvalues, fitpars)
        labelstring = 'Order %d Legendre polynomial fit' % (fit_order)
        general_utilities.list_polynomial_fitpars(fit_type, fit_order, fitpars)
    if fit_type == 'Laguerre':
        fitpars = laguerre.lagfit(xvalues, yvalues, fit_order)
        yout = laguerre.lagval(xout, fitpars)
        yfit = laguerre.lagval(xvalues, fitpars)
        labelstring = 'Order %d Laguerre polynomial fit' % (fit_order)
        general_utilities.list_polynomial_fitpars(fit_type, fit_order, fitpars)
    if fit_type == 'Chebyshev':
        fitpars = chebyshev.chebfit(xvalues, yvalues, fit_order)
        yout = chebyshev.chebval(xout, fitpars)
        yfit = chebyshev.chebval(xvalues, fitpars)
        labelstring = 'Order %d Chebyshev polynomial fit' % (fit_order)
        general_utilities.list_polynomial_fitpars(fit_type, fit_order, fitpars)
    if fit_type == 'Least-Squares Spline':
        if fit_flag == 0:
            yerrors = (plotgui.ydata[set_number]['lowerror'] +
                       plotgui.ydata[set_number]['higherror']) / 2.
        else:
            yerrors = (plotgui.xdata[set_number]['lowerror'] +
                       plotgui.xdata[set_number]['higherror']) / 2.
        if (numpy.min(yerrors) == 0.) and (numpy.max(yerrors) == 0.):
            yerrors = yerrors + 1.
        xmin1 = numpy.min(xvalues)
        xmax1 = numpy.max(xvalues)
        xrange = xmax1 - xmin1
        nknots = int(fit_order)
        if (nknots < 3) or (nknots > int(len(xvalues) / 2)):
            nknots = 3
        xstep = xrange / (nknots - 2)
        xknots = numpy.arange(
            numpy.min(xvalues) + xstep,
            numpy.max(xvalues) * 0.999999999, xstep)
        k = 3
        # Use cubic splines
        knotedges = numpy.r_[(xmin, ) * (k + 1), xknots, (xmax, ) * (k + 1)]
        weights = 1. / yerrors
        weights[yerrors == 0.] = 0.
        fitobject = make_lsq_spline(xvalues, yvalues, knotedges, k, w=weights)
        yout = fitobject(xout)
        yfit = fitobject(xvalues)
        labelstring = 'Least squares spline fit, sections = %d' % (nknots)
    if fit_type == 'Spline':
        fitpars = UnivariateSpline(xvalues,
                                   yvalues,
                                   k=1,
                                   s=None,
                                   bbox=[xmin - delx, xmax + delx])
        labelstring = 'Default spline fit'
        yout = fitpars(xout)
        yfit = fitpars(xvalues)
    if fit_type == 'Cubic Spline':
        if fit_order < 0.:
            str1 = 'Error: smoothing value %f (< 0) is not allowed.'\
                   + '  Settng to 0.0' % (fit_order)
            plotgui.fit_text.insert(Tk.END, str1)
            plotgui.fit_text.see(Tk.END)
            fit_order = 0.0
        fitpars = UnivariateSpline(xvalues,
                                   yvalues,
                                   k=3,
                                   bbox=[xmin - delx, xmax + delx],
                                   s=fit_order)
        yout = fitpars(xout)
        yfit = fitpars(xvalues)
        labelstring = 'Cubic spline fit, smoothing = %f' % (fit_order)
    rms = fit_statistics(yvalues, yfit)
    if 'Internal' in fit_type:
        if fit_flag == 0:
            xlowerror = youterror * 0.
            xhigherror = youterror * 0.
            ylowerror = youterror
            yhigherror = youterror
        else:
            xlowerror = youterror
            xhigherror = youterror
            ylowerror = youterror * 0.
            yhigherror = youterror * 0.
    else:
        xlowerror = xout * 0.
        xhigherror = xout * 0.
        ylowerror = yout * 0.
        yhigherror = yout * 0.
    xmin = numpy.min(xout)
    xmax = numpy.max(xout)
    ymin = numpy.min(yfit)
    ymax = numpy.max(yfit)
    if rms is not None:
        str1 = 'Fit: RMS = %g for %d points\n' % (rms, len(yfit))
        plotgui.fit_text.insert(Tk.END, str1)
        plotgui.fit_text.see(Tk.END)
    if fit_flag == 0:
        plotgui.xdata[plotgui.nsets] = {
            'values': xout,
            'lowerror': xlowerror,
            'higherror': xhigherror,
            'minimum': xmin,
            'maximum': xmax,
            'errors': False,
            'legend': True
        }
        plotgui.ydata[plotgui.nsets] = {
            'values': yout,
            'lowerror': ylowerror,
            'higherror': yhigherror,
            'minimum': ymin,
            'maximum': ymax,
            'errors': True,
            'legend': True
        }
    else:
        plotgui.xdata[plotgui.nsets] = {
            'values': yout,
            'lowerror': ylowerror,
            'higherror': yhigherror,
            'minimum': ymin,
            'maximum': ymax,
            'errors': False,
            'legend': True
        }
        plotgui.ydata[plotgui.nsets] = {
            'values': xout,
            'lowerror': xlowerror,
            'higherror': xhigherror,
            'minimum': xmin,
            'maximum': xmax,
            'errors': False,
            'legend': True
        }
    m = plotgui.nsets % 10
    n = int(math.floor(plotgui.nsets / 10))
    plotgui.set_properties[plotgui.nsets]['symbol'] = None
    plotgui.set_properties[plotgui.nsets]['linestyle'] = '-'
    plotgui.set_properties[plotgui.nsets]['colour'] = plotgui.colourset[m]
    plotgui.set_properties[plotgui.nsets]['symbolsize'] = 4.0 + 0.3 * n
    plotgui.set_properties[plotgui.nsets]['label'] = labelstring
    plotgui.nsets = plotgui.nsets + 1
    make_plot.make_plot(plotgui)
Example #36
0
"""
===============================
1-Dimensional Least Squares Fit
===============================
"""

import ndsplines
import matplotlib.pyplot as plt
import numpy as np
from scipy import interpolate

x = np.linspace(-3, 3, 50)
y = np.exp(-x**2) + 0.1 * np.random.randn(50)

t = [-1, 0, 1]
k = 3
t = np.r_[(x[0], ) * (k + 1), t, (x[-1], ) * (k + 1)]

ndspl = ndsplines.make_lsq_spline(x[:, None], y[:, None], [t], np.array([k]))
ispl = interpolate.make_lsq_spline(x, y, t, k)

xs = np.linspace(-3, 3, 100)
plt.figure()
plt.plot(x, y, 'o', ms=5)
plt.plot(xs, ndspl(xs).squeeze(), label='LSQ ND spline')
plt.plot(xs, ispl(xs), '--', label='LSQ scipy.interpolate spline')
plt.legend(loc='best')
plt.show()

print("Computed coefficients close?", np.allclose(ndspl.coefficients, ispl.c))