コード例 #1
0
def process_model(model, data, vsini_model=None, resolution=None, vsini_primary=None,
                  maxvel=1000.0, debug=False, logspace=True):
    """
    Process a stellar model to prepare it for cross correlation

    Parameters:
    - model:          string, or kglib.utils.DataStructures.xypoint instance
                      If a string, should give the path to an ascii file with the model
                      Otherwise, should hold the model data

    - data:           list of kglib.utils.DataStructures.xypoint instances
                      The already-processed data.

    - vsini_model:    float
                      The rotational velocity to apply to the model spectrum

    - vsini_primary:  float
                      The rotational velocity of the primary star

    - resolution:     float
                      The detector resolution in $\lambda / \Delta \lambda$

    - maxvel:         float
                      The maximum velocity to include in the eventual CCF.
                      This is used to trim the data appropriately for each echelle order.

    - debug:          boolean
                      Print some extra stuff?

    - logspace:       boolean
                      Rebin the model to constant log-spacing?

    Returns:
    ========
    A list of kglib.utils.DataStructures.xypoint instances with the processed model.
    """
    # Read in the model if necessary
    if isinstance(model, str):
        if debug:
            print("Reading in the input model from %s" % model)
        x, y = np.loadtxt(model, usecols=(0, 1), unpack=True)
        x = x * u.angstrom.to(u.nm)
        y = 10 ** y
        left = np.searchsorted(x, data[0].x[0] - 10)
        right = np.searchsorted(x, data[-1].x[-1] + 10)
        model = DataStructures.xypoint(x=x[left:right], y=y[left:right])
    elif not isinstance(model, DataStructures.xypoint):
        raise TypeError(
            "Input model is of an unknown type! Must be a DataStructures.xypoint or a string with the filename.")


    # Linearize the x-axis of the model (in log-spacing)
    if logspace:
        if debug:
            print("Linearizing model")
        xgrid = np.logspace(np.log10(model.x[0]), np.log10(model.x[-1]), model.size())
        model = FittingUtilities.RebinData(model, xgrid)

    # Broaden
    if vsini_model is not None and vsini_model > 1.0 * u.km.to(u.cm):
        if debug:
            print("Rotationally broadening model to vsini = %g km/s" % (vsini_model * u.cm.to(u.km)))
        model = Broaden.RotBroad(model, vsini_model, linear=True)


    # Reduce resolution
    if resolution is not None and 5000 < resolution < 500000:
        if debug:
            print("Convolving to the detector resolution of %g" % resolution)
        model = FittingUtilities.ReduceResolutionFFT(model, resolution)

    # Divide by the same smoothing kernel as we used for the data
    if vsini_primary is not None:
        smoothed = HelperFunctions.astropy_smooth(model, vel=SMOOTH_FACTOR * vsini_primary, linearize=False)
        model.y += model.cont.mean() - smoothed
        model.cont = np.ones(model.size()) * model.cont.mean()


    # Rebin subsets of the model to the same spacing as the data
    model_orders = []
    model_fcn = spline(model.x, model.y)
    if debug:
        model.output("Test_model.dat")
    for i, order in enumerate(data):
        if debug:
            sys.stdout.write("\rGenerating model subset for order %i in the input data" % (i + 1))
            sys.stdout.flush()
        # Find how much to extend the model so that we can get maxvel range.
        dlambda = order.x[order.size() / 2] * maxvel * 1.5 / 3e5
        left = np.searchsorted(model.x, order.x[0] - dlambda)
        right = np.searchsorted(model.x, order.x[-1] + dlambda)
        right = min(right, model.size() - 2)

        # Figure out the log-spacing of the data
        logspacing = np.log(order.x[1] / order.x[0])

        # Finally, space the model segment with the same log-spacing
        start = np.log(model.x[left])
        end = np.log(model.x[right])
        xgrid = np.exp(np.arange(start, end + logspacing, logspacing))

        segment = DataStructures.xypoint(x=xgrid, y=model_fcn(xgrid))
        segment.cont = FittingUtilities.Continuum(segment.x, segment.y, lowreject=1.5, highreject=5, fitorder=2)
        model_orders.append(segment)

    print("\n")
    return model_orders
コード例 #2
0
def Process_Data_serial(input_data, badregions=[], interp_regions=[], extensions=True,
                 trimsize=1, vsini=None, logspacing=False, oversample=1.0, reject_outliers=True):
    """
    Prepare data for cross-correlation. This involves cutting out bad part of the spectrum
    and resampling to constant log-wavelength spacing.

    Parameters:
    ===========
    - input_data:         string, or list of kglib.utils.DataStructures.xypoint instances
                          If a string, should give the filename of the data
                          Otherwise, it should give the spectrum in each echelle order

    - badregions:         list of lists, where each sub-list has size 2
                          Regions to exclude (contains strong telluric or stellar line residuals).
                          Each sublist should give the start and end wavelength to exclude

    - interp_regions:     list of lists, where each sub-list has size 2
                          Regions to interpolate over.
                          Each sublist should give the start and end wavelength to exclude

    - extensions:         boolean
                          Is the fits file is separated into extensions?

    - trimsize:           integer
                          The number of pixels to exclude from both ends of every order
                          (where it is very noisy)

    - vsini:              float
                          The primary star vsini, in km/s. If given subtract an estimate
                          of the primary star model obtained by
                          denoising and smoothing with a kernel size set by the vsini.

    - logspacing:         boolean
                          If true, interpolate each order into a constant log-spacing.

    - oversample:         float
                          Oversampling factor to use if resampling to log-spacing.
                          The final number of pixels is oversample times the initial
                          number.

    - reject_outliers:    boolean
                          Should we search for and reject outliers from the processed data?
                          Useful when looking for companions with large flux ratios, but
                          not otherwise.

    Returns:
    ========
    A list of kglib.utils.DataStructures.xypoint instances with the processed data.
    """
    if isinstance(input_data, list) and all([isinstance(f, DataStructures.xypoint) for f in input_data]):
        orders = input_data
    else:
        if extensions:
            orders = HelperFunctions.ReadExtensionFits(input_data)

        else:
            orders = HelperFunctions.ReadFits(input_data, errors=2)

    numorders = len(orders)
    for i, order in enumerate(orders[::-1]):
        # Trim data, and make sure the wavelength spacing is constant
        if trimsize > 0:
            order = order[trimsize:-trimsize]

        # Smooth the data
        if vsini is not None:
            # make sure the x-spacing is linear
            xgrid = np.linspace(order.x[0], order.x[-1], order.size())
            order = FittingUtilities.RebinData(order, xgrid)

            smoothed = HelperFunctions.astropy_smooth(order, vel=SMOOTH_FACTOR * vsini, linearize=True)
            order.y += order.cont.mean() - smoothed
            order.cont = np.ones(order.size()) * order.cont.mean()

        # Remove bad regions from the data
        for region in badregions:
            left = np.searchsorted(order.x, region[0])
            right = np.searchsorted(order.x, region[1])
            if left > 0 and right < order.size():
                print("Warning! Bad region covers the middle of order %i" % i)
                print("Removing full order!")
                left = 0
                right = order.size()
            order.x = np.delete(order.x, np.arange(left, right))
            order.y = np.delete(order.y, np.arange(left, right))
            order.cont = np.delete(order.cont, np.arange(left, right))
            order.err = np.delete(order.err, np.arange(left, right))

        # Interpolate over interp_regions:
        for region in interp_regions:
            left = np.searchsorted(order.x, region[0])
            right = np.searchsorted(order.x, region[1])
            order.y[left:right] = order.cont[left:right]


        # Remove whole order if it is too small
        remove = False
        if order.x.size <= 1:
            remove = True
        else:
            velrange = 3e5 * (np.median(order.x) - order.x[0]) / np.median(order.x)
            if velrange <= 1050.0:
                remove = True
        if remove:
            print("Removing order %i" % (numorders - 1 - i))
            orders.pop(numorders - 1 - i)
        else:
            if reject_outliers:
                # Find outliers from e.g. bad telluric line or stellar spectrum removal.
                order.cont = FittingUtilities.Continuum(order.x, order.y, lowreject=3, highreject=3)
                outliers = HelperFunctions.FindOutliers(order, expand=10, numsiglow=5, numsighigh=5)
                # plt.plot(order.x, order.y / order.cont, 'k-')
                if len(outliers) > 0:
                    # plt.plot(order.x[outliers], (order.y / order.cont)[outliers], 'r-')
                    order.y[outliers] = order.cont[outliers]
                    order.cont = FittingUtilities.Continuum(order.x, order.y, lowreject=3, highreject=3)
                    order.y[outliers] = order.cont[outliers]

            # Save this order
            orders[numorders - 1 - i] = order.copy()

    # Rebin the data to a constant log-spacing (if requested)
    if logspacing:
        for i, order in enumerate(orders):
            start = np.log(order.x[0])
            end = np.log(order.x[-1])
            neworder = order.copy()
            neworder.x = np.logspace(start, end, order.size() * oversample, base=np.e)
            neworder = FittingUtilities.RebinData(order, neworder.x)
            orders[i] = neworder

    return orders