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)
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)
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])
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
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