예제 #1
0
    def perf(self, p):

        # Applying corrections to the observed spectrum
        self.data = np.loadtxt('spectrum.dat')
        self.data[:,0] = self.data[:,0] + self.xshift - self.data[:,0] * \
            (self.c / (self.vshift*1E13 + self.c) - 1.0)
        self.data[:,1] = self.data[:,1] * self.ymult + self.yadd
        self.data_target = self.am.x_set_limits(self.spec[0], self.spec[1],
                                                self.data)

        # Running MOOGSILENT
        self.write_params(p[0], p[1])
        m = moog.run(silent=True)

        # Evaluating the performance in a radius around the center of the line
        self.center_index = self.am.find_index(self.line_center,
                                               self.data_target[:,0])
        self.ci0 = self.center_index - self.radius
        self.ci1 = self.center_index + self.radius+1
        self.model = np.loadtxt('vm_smooth.out', skiprows=2)
        self.model_interp = np.interp(self.data_target[self.ci0:self.ci1,0],
                                      self.model[:,0],
                                      self.model[:,1])

        # Checking the fit on line wings
        self.check = self.data_target[self.ci0:self.ci1,1] - self.model_interp
        self.check = len(np.where(self.check > self.spec_sigma)[0])

        # Creating the weights vector
        self.w = np.zeros(2 * self.radius + 1, float)
        for i in range(self.radius):
            self.w[i] = self.bwing_w
            self.w[i + self.radius+1] = self.rwing_w
        self.w[self.radius] = self.center_w

        return np.sum(self.w[:] * (self.data_target[self.ci0:self.ci1,1] - \
                self.model_interp[:])**2) / np.sum(self.w)
예제 #2
0
    def perf(self, p):

        # Applying corrections to the observed spectrum
        self.data = np.loadtxt('spectrum.dat')
        self.data[:,0] = self.data[:,0] + self.xshift - self.data[:,0] * \
            (self.c / (self.vshift*1E13 + self.c) - 1.0)
        self.data[:, 1] = self.data[:, 1] * self.ymult + self.yadd
        self.data_target = self.am.x_set_limits(self.spec[0], self.spec[1],
                                                self.data)

        # Running MOOGSILENT
        self.write_params(p[0], p[1])
        m = moog.run(silent=True)

        # Evaluating the performance in a radius around the center of the line
        self.center_index = self.am.find_index(self.line_center,
                                               self.data_target[:, 0])
        self.ci0 = self.center_index - self.radius
        self.ci1 = self.center_index + self.radius + 1
        self.model = np.loadtxt('vm_smooth.out', skiprows=2)
        self.model_interp = np.interp(self.data_target[self.ci0:self.ci1, 0],
                                      self.model[:, 0], self.model[:, 1])

        # Checking the fit on line wings
        self.check = self.data_target[self.ci0:self.ci1, 1] - self.model_interp
        self.check = len(np.where(self.check > self.spec_sigma)[0])

        # Creating the weights vector
        self.w = np.zeros(2 * self.radius + 1, float)
        for i in range(self.radius):
            self.w[i] = self.bwing_w
            self.w[i + self.radius + 1] = self.rwing_w
        self.w[self.radius] = self.center_w

        return np.sum(self.w[:] * (self.data_target[self.ci0:self.ci1,1] - \
                self.model_interp[:])**2) / np.sum(self.w)
예제 #3
0
def full_auto(star, choice, interval, res_power, SN, **kwargs):

    # Spectrum chunk size. Default = 10. angstroms
    if ('chunk' in kwargs):
        chunk = kwargs['chunk']
        assert chunk > interval, 'Invalid chunk size'
    else:
        chunk = 10.0

    # Continuum correction: choose between 'single' or 'multi' wavelengths
    if ('continuum_correction' in kwargs):
        cont_type = kwargs['continuum_correction']
        assert cont_type == 'multi', 'Continuum correction type invalid'
    else:
        cont_type = 'single'

    # Radius of points to be used in finding the correction for the line center
    # Default = 3
    if ('r_1' in kwargs):
        radius_1 = kwargs['r_1']
        assert radius_1 > 0, 'Invalid radius for line center correction'
    else:
        radius_1 = 3

    # Radius in angstroms for the region around the target wavelength to be
    # analyzed for the continuum . Default = 3.0
    if ('r_2' in kwargs):
        radius_2 = kwargs['r_2']
        assert radius_2 > 0, 'Invalid radius of wavelength region'
    else:
        radius_2 = 3.0

    # Radius in points to be used in finding the correction for the continuum.
    # Default = 2
    if ('r_3' in kwargs):
        radius_3 = kwargs['r_3']
        assert radius_3 > 0, 'Invalid radius for continuum correction'
    else:
        radius_3 = 2

    # Radius in points to be used in evaluating the performance function
    # Default = 7
    if ('r_4' in kwargs):
        radius_4 = kwargs['r_4']
        assert radius_4 > 0, 'Invalid radius for performance evaluation'
    else:
        radius_4 = 7

    # Blue wing weight to be used on estimation. Default = 10.0
    if ('bw' in kwargs):
        bw = kwargs['bw']
        assert bw >= 0.0, 'Invalid weight for blue wing'
    else:
        bw = 10.0

    # Red wing weight to be used on estimation. Default = 5.0
    if ('rw' in kwargs):
        rw = kwargs['rw']
        assert rw >= 0.0, 'Invalid weight for red wing'
    else:
        rw = 5.0

    # Line center weight to be used on estimation. Default = 25.0
    if ('cw' in kwargs):
        cw = kwargs['cw']
        assert cw >= 0.0, 'Invalid weight for line center'
    else:
        cw = 25.0

    # Bad fit tolerance in number of points above the S/N ratio. Default = 2
    if ('tol' in kwargs):
        tol = kwargs['tol']
        assert tol >= 0, 'Invalid tolerance'
    else:
        tol = 2

    # 'plot' on window or 'save' as png? Default = plot on window
    if ('output' in kwargs):
        output = kwargs['output']
        assert output == 'save', 'Invalid radius for continuum correction'
    else:
        output = 'plot'

    # optimize will estimate vsini automatically. Default = True
    if ('optimize' in kwargs):
        optimize = kwargs['optimize']
    else:
        optimize = True

    # guess is a numpy.array([vsini,abund]), useful if optimize != True
    if ('guess' in kwargs):
        guess = kwargs['guess']
    else:
        guess = np.array([1.0, 0.0])

    choice = int(choice)

    # Synthesis parameters
    line_file = 'lines.dat'
    lines = np.loadtxt(line_file,skiprows=1,usecols=(0,1))

    # Star parameters
    star_info = np.genfromtxt('star.mod',skip_header=1,skip_footer=83,
                              usecols=(0,1),delimiter='/  ')
    T_star = star_info[0]
    v_macro = v_m(T_star)

    # Managing the data file
    spec_window = manage(choice, interval, lines, chunk)

    data = np.loadtxt('spectrum.dat')

    # The instrumental broadening
    gauss = np.mean(spec_window)/res_power

    # Finding the correction factors
    wl_shift, corr = correct(choice, data, lines, cont_type, radius_1, radius_2,
                             radius_3)

    # Instatiating the function to write parameters for MOOG
    r = estimate.vsini(
                spec_window,
                gauss,
                v_macro,
                line_file,
                choice,
                x_wl=wl_shift,
                y_mult=corr,
                bwing_w = bw,
                rwing_w = rw,
                center_w = cw,
                perf_radius=radius_4,
                SN=SN,
                badfit_tol = tol,
                star_name=star_names[star]
                )

    if output == 'plot':
        save = 'window'
    else:
        save = '%s_line%i.png'%(star_names[star],choice)

    if optimize == True:
        print "Now starting estimation of vsini..."
        vsini,abund,bfs = r.find(N=15,
                                max_i=20,
                                min_i=10,
                                limits=[0.05,0.001],
                                save=save)
        return vsini,abund,bfs
    else:
        print 'Running MOOG with the following values:'
        print 'vsini = %.2f' % guess[0]
        print 'abund = %.3f' % guess[1]
        r.write_params(guess[0],guess[1])
        moog.run(star_name = star_names[star])
예제 #4
0
    def find(self, **kwargs):

        # Number of points to try for each iteration
        if ('N' in kwargs):
            self.pts = kwargs['N']
        else:
            self.pts = 15

        # Narrowing factor when going to the next iteration
        # pace[0] = narrowing factor for vsini
        # pace[1] = narrowing factor for abundance
        if ('pace' in kwargs):
            self.pace = kwargs['pace']
        else:
            self.pace = np.array([1.5, 2.0])

        # Initial guess range for abundance. It has to be a numpy array of
        # length = 2
        if ('a_guess' in kwargs):
            self.a_guess = kwargs['a_guess']
        else:
            self.a_guess = np.array([-0.100, 0.100])

        # Initial guess range for vsini. It has to be a numpy array of
        # length = 2
        if ('v_guess' in kwargs):
            self.v_guess = kwargs['v_guess']
        else:
            self.v_guess = np.array([0.5, 10.0])

        # Minimum number of iterations
        if ('min_i' in kwargs):
            self.min_i = kwargs['min_i']
        else:
            self.min_i = 5

        # Maximum number of iterations
        if ('max_i' in kwargs):
            self.max_i = kwargs['max_i']
        else:
            self.max_i = 20

        # Convergence limits: a numpy array with length 2, corresponding to the
        # limits of vsini and abundance, respectively
        if ('limits' in kwargs):
            self.limits = kwargs['limits']
        else:
            self.limits = np.array([0.01, 0.001])

        # Plot the spectral line fit at the end?
        if ('plot' in kwargs):
            self.plot = kwargs['plot']
        else:
            self.plot = True

        # Lower limit of estimation of vsini
        if ('v_low_limit' in kwargs):
            self.v_low_limit = kwargs['v_low_limit']
        else:
            self.v_low_limit = 0.5

        # Set 'save' to a filename with an extension (e.g. png, eps)
        # Overrides 'plot' to False
        if ('save' in kwargs):
            self.save = kwargs['save']
            self.plot = False
        else:
            self.save = None

        # Do you want the program to be silent? Not very useful at the moment
        if ('silent' in kwargs):
            self.silent = kwargs['silent']
        else:
            self.silent = False

        if self.silent == False:
            print "\nStarting estimation of vsini and abundance...\n"
        self.t0 = time.time()
        self.best_a = np.mean(self.a_guess)
        self.best_v = np.mean(self.v_guess)
        self.it = 1
        self.finish = False
        #self.badfit_status = False

        while self.finish == False and self.it < self.max_i:

            # Evaluating vsini
            self.v_grid = np.linspace(self.v_guess[0], self.v_guess[1],
                                      self.pts)
            self.S = np.array([self.perf(np.array([self.v_grid[k],\
                self.best_a])) for k in range(self.pts)])
            self.best_v_ind = np.where(self.S == min(self.S))[0][0]
            self.best_v = self.v_grid[self.best_v_ind]

            # Evaluating abundance
            self.a_grid = np.linspace(self.a_guess[0], self.a_guess[1],
                                      self.pts)
            self.S= np.array([self.perf(np.array([self.best_v,self.a_grid[k]]))\
                for k in range(self.pts)])
            self.best_a_ind = np.where(self.S == min(self.S))[0][0]
            self.best_a = self.a_grid[self.best_a_ind]

            self.go_v = True
            self.go_a = True

            # Checking if the best values are too near the edges of the guess
            if self.best_v_ind == 0 or self.best_v_ind == self.pts - 1:
                self.go_v = False
            elif self.best_a_ind == 0 or self.best_a_ind == self.pts - 1:
                self.go_a = False

            # Calculating changes
            self.v_change = np.abs(self.best_v - np.mean(self.v_guess))
            self.a_change = np.abs(self.best_a - np.mean(self.a_guess))
            if self.silent == False:
                if self.v_change < self.limits[0] and self.a_change < \
                    self.limits[1] and self.it > self.min_i:
                    self.finish = True
                    print "final iteration = %i" % self.it
                else:
                    print "iteration = %i" % self.it
                print "best vsini = %.2f (changed %.3f)" % \
                    (self.best_v,self.v_change)
                print "best abund = %.3f (changed %.4f)\n" % \
                    (self.best_a,self.a_change)
            else:
                if self.v_change < self.limits[0] and self.a_change < \
                    self.limits[1] and self.it > self.min_i:
                    self.finish = True

            # Setting the new guess. If one of the best values are too near the
            # edges of the previous guess, it will not narrow its new guess
            # range.
            self.v_width = self.v_guess[1] - self.v_guess[0]
            self.a_width = self.a_guess[1] - self.a_guess[0]
            if self.go_v == True:
                self.v_guess = np.array([self.best_v-\
                    self.v_width/2/self.pace[0], self.best_v+\
                        self.v_width/2/self.pace[0]])
            else:
                self.v_guess = np.array([self.best_v-self.v_width/2,\
                    self.best_v+self.v_width/2])
            if self.go_a == True:
                self.a_guess = np.array([self.best_a-\
                    self.a_width/2/self.pace[1], self.best_a+\
                        self.a_width/2/self.pace[1]])

            # Checking if the v_guess contains vsini lower than v_low_limit.
            # If True, it will add a value to the array so that the lower limit
            # is equal to the v_low_limit
            if self.v_guess[0] < self.v_low_limit and self.silent == False:
                print "WARNING: vsini guess less than %.1f. I will shift it." \
                    % self.v_low_limit
                self.v_guess += self.v_low_limit - self.v_guess[0]

            else:
                self.best_a += np.random.normal(scale=0.001)
                self.a_guess = np.array([self.best_a-self.a_width/2,\
                    self.best_a+self.a_width/2])

            self.it += 1

        # Finalizing the routine
        if self.it == self.max_i and self.silent == False:
            print "Maximum number of iterations reached!\n"
        self.t1 = time.time()
        self.total_time = self.t1 - self.t0
        if self.silent == False:
            print "Estimation took %.3f seconds." % self.total_time
        self.write_params(self.best_v, self.best_a)

        if self.plot == True:
            m = moog.run(silent=False)
        elif (self.plot == False or self.silent == True) and self.save != None:
            m = moog.run(silent=False, save=self.save, star_name=self.name)
        else:
            m = moog.run(silent=True)

        self.S = self.perf(np.array([self.best_v, self.best_a]))

        # Trigger bad fit warning
        #if self.check > self.badfit_tol:
        #    self.badfit_status = True
        #    if self.silent == False:
        #        print """
        #It is possible that the estimation is bad. This is usually caused
        #by a slow-rotating star, line-blending, line center shift or bad continuum.
        #I suggest using a lower pace and more points, doing it manually or
        #discarding result for this particular line.
        #            """

        return self.best_v, self.best_a
예제 #5
0
    def find(self, **kwargs):

        # Number of points to try for each iteration
        if ('N' in kwargs):
            self.pts = kwargs['N']
        else:
            self.pts = 15

        # Narrowing factor when going to the next iteration
        # pace[0] = narrowing factor for vsini
        # pace[1] = narrowing factor for abundance
        if ('pace' in kwargs):
            self.pace = kwargs['pace']
        else:
            self.pace = np.array([1.5,2.0])

        # Initial guess range for abundance. It has to be a numpy array of
        # length = 2
        if ('a_guess' in kwargs):
            self.a_guess = kwargs['a_guess']
        else:
            self.a_guess = np.array([-0.100,0.100])

        # Initial guess range for vsini. It has to be a numpy array of
        # length = 2
        if ('v_guess' in kwargs):
            self.v_guess = kwargs['v_guess']
        else:
            self.v_guess = np.array([0.5,10.0])

        # Minimum number of iterations
        if ('min_i' in kwargs):
            self.min_i = kwargs['min_i']
        else:
            self.min_i = 5

        # Maximum number of iterations
        if ('max_i' in kwargs):
            self.max_i = kwargs['max_i']
        else:
            self.max_i = 20

        # Convergence limits: a numpy array with length 2, corresponding to the
        # limits of vsini and abundance, respectively
        if ('limits' in kwargs):
            self.limits = kwargs['limits']
        else:
            self.limits = np.array([0.01,0.001])

        # Plot the spectral line fit at the end?
        if ('plot' in kwargs):
            self.plot = kwargs['plot']
        else:
            self.plot = True
            
        # Lower limit of estimation of vsini
        if ('v_low_limit' in kwargs):
            self.v_low_limit = kwargs['v_low_limit']
        else:
            self.v_low_limit = 0.5

        # Set 'save' to a filename with an extension (e.g. png, eps)
        # Overrides 'plot' to False
        if ('save' in kwargs):
            self.save = kwargs['save']
            self.plot = False
        else:
            self.save = None

        # Do you want the program to be silent? Not very useful at the moment
        if ('silent' in kwargs):
            self.silent = kwargs['silent']
        else:
            self.silent = False

        if self.silent == False:
            print "\nStarting estimation of vsini and abundance...\n"
        self.t0 = time.time()
        self.best_a = np.mean(self.a_guess)
        self.best_v = np.mean(self.v_guess)
        self.it = 1
        self.finish = False
        #self.badfit_status = False

        while self.finish == False and self.it < self.max_i:

            # Evaluating vsini
            self.v_grid = np.linspace(self.v_guess[0],self.v_guess[1],self.pts)
            self.S = np.array([self.perf(np.array([self.v_grid[k],\
                self.best_a])) for k in range(self.pts)])
            self.best_v_ind = np.where(self.S == min(self.S))[0][0]
            self.best_v = self.v_grid[self.best_v_ind]

            # Evaluating abundance
            self.a_grid = np.linspace(self.a_guess[0],self.a_guess[1],self.pts)
            self.S= np.array([self.perf(np.array([self.best_v,self.a_grid[k]]))\
                for k in range(self.pts)])
            self.best_a_ind = np.where(self.S == min(self.S))[0][0]
            self.best_a = self.a_grid[self.best_a_ind]

            self.go_v = True
            self.go_a = True

            # Checking if the best values are too near the edges of the guess
            if self.best_v_ind == 0 or self.best_v_ind == self.pts-1:
                self.go_v = False
            elif self.best_a_ind == 0 or self.best_a_ind == self.pts-1:
                self.go_a = False

            # Calculating changes
            self.v_change = np.abs(self.best_v-np.mean(self.v_guess))
            self.a_change = np.abs(self.best_a-np.mean(self.a_guess))
            if self.silent == False:
                if self.v_change < self.limits[0] and self.a_change < \
                    self.limits[1] and self.it > self.min_i:
                    self.finish = True
                    print "final iteration = %i" % self.it
                else:
                    print "iteration = %i" % self.it
                print "best vsini = %.2f (changed %.3f)" % \
                    (self.best_v,self.v_change)
                print "best abund = %.3f (changed %.4f)\n" % \
                    (self.best_a,self.a_change)
            else:
                if self.v_change < self.limits[0] and self.a_change < \
                    self.limits[1] and self.it > self.min_i:
                    self.finish = True

            # Setting the new guess. If one of the best values are too near the
            # edges of the previous guess, it will not narrow its new guess 
            # range.
            self.v_width = self.v_guess[1]-self.v_guess[0]
            self.a_width = self.a_guess[1]-self.a_guess[0]
            if self.go_v == True:
                self.v_guess = np.array([self.best_v-\
                    self.v_width/2/self.pace[0], self.best_v+\
                        self.v_width/2/self.pace[0]])
            else:
                self.v_guess = np.array([self.best_v-self.v_width/2,\
                    self.best_v+self.v_width/2])
            if self.go_a == True:
                self.a_guess = np.array([self.best_a-\
                    self.a_width/2/self.pace[1], self.best_a+\
                        self.a_width/2/self.pace[1]])

            # Checking if the v_guess contains vsini lower than v_low_limit. 
            # If True, it will add a value to the array so that the lower limit 
            # is equal to the v_low_limit
            if self.v_guess[0] < self.v_low_limit and self.silent == False:
                print "WARNING: vsini guess less than %.1f. I will shift it." \
                    % self.v_low_limit
                self.v_guess += self.v_low_limit-self.v_guess[0]

            else:
                self.best_a += np.random.normal(scale=0.001)
                self.a_guess = np.array([self.best_a-self.a_width/2,\
                    self.best_a+self.a_width/2])

            self.it += 1

        # Finalizing the routine
        if self.it == self.max_i and self.silent == False:
            print "Maximum number of iterations reached!\n"
        self.t1 = time.time()
        self.total_time = self.t1-self.t0
        if self.silent == False:
            print "Estimation took %.3f seconds." % self.total_time
        self.write_params(self.best_v,self.best_a)

        if self.plot == True:
            m = moog.run(silent=False)
        elif (self.plot == False or self.silent == True) and self.save != None:
            m = moog.run(silent=False, save=self.save, star_name=self.name)
        else:
            m = moog.run(silent=True)

        self.S = self.perf(np.array([self.best_v,self.best_a]))
        
        # Trigger bad fit warning
        #if self.check > self.badfit_tol:
        #    self.badfit_status = True
        #    if self.silent == False:
        #        print """
    #It is possible that the estimation is bad. This is usually caused
    #by a slow-rotating star, line-blending, line center shift or bad continuum.
    #I suggest using a lower pace and more points, doing it manually or
    #discarding result for this particular line.
    #            """

        return self.best_v,self.best_a