Exemple #1
0
def make_chisq_plots(filename, paramfilename, galaxyname, slitmaskname, startstar=0, globular=False):
	""" Plot chisq contours for stars whose [Mn/H] abundances have already been measured.

	Inputs:
	filename 		-- file with observed spectra
	paramfilename 	-- file with parameters of observed spectra
	galaxyname		-- galaxy name, options: 'scl'
	slitmaskname 	-- slitmask name, options: 'scl1'

	Keywords:
	globular 		-- if 'False', put into output path of galaxy; else, put into globular cluster path

	"""

	# Input filename
	if globular:
		file = '/raid/madlr/glob/'+galaxyname+'/'+slitmaskname+'.csv'
	else:
		file = '/raid/madlr/dsph/'+galaxyname+'/'+slitmaskname+'.csv'

	name  = np.genfromtxt(file, delimiter='\t', skip_header=1, usecols=0, dtype='str')
	mn    = np.genfromtxt(file, delimiter='\t', skip_header=1, usecols=8)
	mnerr = np.genfromtxt(file, delimiter='\t', skip_header=1, usecols=9)
	#dlam = np.genfromtxt(file, delimiter='\t', skip_header=1, usecols=8)
	#dlamerr = np.genfromtxt(file, delimiter='\t', skip_header=1, usecols=9)

	# Get number of stars in file with observed spectra
	Nstars = open_obs_file(filename)

	# Plot chi-sq contours for each star
	for i in range(startstar, Nstars):

		try:

			# Check if parameters are measured
			temp, logg, fe, alpha, fe_err = open_obs_file(filename, retrievespec=i, specparams=True)
			if np.isclose(1.5,logg) and np.isclose(fe,-1.5) and np.isclose(fe_err, 0.0):
				print('Bad parameter measurement! Skipped #'+str(i+1)+'/'+str(Nstars)+' stars')
				continue

			# Open star
			star = chi_sq.obsSpectrum(filename, paramfilename, i, False, galaxyname, slitmaskname, globular, 'new')

			# Check if star has already had [Mn/H] measured
			if star.specname in name:

				# If so, plot chi-sq contours if error is < 1 dex
				idx = np.where(name == star.specname)
				if mnerr[idx][0] < 1:
					params0 = [mn[idx][0], mnerr[idx][0]]
					best_mn, error = star.plot_chisq(params0, minimize=False, plots=True, save=True)

		except Exception as e:
			print(repr(e))
			print('Skipped star #'+str(i+1)+'/'+str(Nstars)+' stars')
			continue

		print('Finished star '+star.specname, '#'+str(i+1)+'/'+str(Nstars)+' stars')

	return
Exemple #2
0
def prep_run(
        filename,
        galaxyname,
        slitmaskname,
        membercheck=None,
        memberlist='/raid/caltech/articles/kirby_gclithium/table_catalog.dat',
        velmemberlist=None,
        globular=False):
    """ Get data in preparation for measuring chi-sq values.

	Inputs:
	filename 		-- file with observed spectra
	galaxyname		-- galaxy name, options: 'scl'
	slitmaskname 	-- slitmask name, options: 'scl1'

	Keywords:
	membercheck 	-- do membership check for this object
	memberlist		-- member list (from Evan's Li-rich giants paper)
	velmemberlist 	-- member list (from radial velocity check)
	globular 		-- if 'False' (default), put into output path of galaxy; else, put into globular cluster path

	Outputs:
	Nstars 			-- total number of stars in the data file
	RA, Dec 		-- coordinate arrays for stars in file
	membernames		-- list of all members (based on Evan's Li-rich giants paper and/or velocity check)
	galaxyname, slitmaskname, filename, membercheck -- from input

	"""

    # Prep for member check
    if membercheck is not None:

        # Check if stars are in member list from Evan's Li-rich giants paper
        table = ascii.read(memberlist)
        memberindex = np.where(table.columns[0] == membercheck)
        membernames = table.columns[1][memberindex]

        # Also check if stars are in member list from velocity cut
        if velmemberlist is not None:
            oldmembernames = membernames
            membernames = []
            velmembernames = np.genfromtxt(velmemberlist, dtype='str')
            for i in range(len(oldmembernames)):
                if oldmembernames[i] in velmembernames:
                    membernames.append(oldmembernames)

            membernames = np.asarray(membernames)

    else:
        membernames = None

    # Get number of stars in file
    Nstars = open_obs_file(filename)

    # Get coordinates of stars in file
    RA, Dec = open_obs_file(filename, coords=True)

    return galaxyname, slitmaskname, filename, Nstars, RA, Dec, membercheck, membernames, globular
Exemple #3
0
def mp_worker(i, filename, paramfilename, wvlcorr, galaxyname, slitmaskname,
              globular, lines, plots, Nstars, RA, Dec, membercheck,
              membernames, correctionslist, corrections):
    """ Function to parallelize: chi-sq fitting for a single star """

    try:
        # Get metallicity of star to use for initial guess
        print('Getting initial metallicity')
        temp, logg, fe, alpha, fe_err = open_obs_file(filename,
                                                      retrievespec=i,
                                                      specparams=True)

        # Get dlam (FWHM) of star to use for initial guess
        specname, obswvl, obsflux, ivar, dlam, zrest = open_obs_file(
            filename, retrievespec=i)

        # Check for bad parameter measurement
        if np.isclose(temp, 4750.) and np.isclose(fe, -1.5) and np.isclose(
                alpha, 0.2):
            print('Bad parameter measurement! Parameters: ' + str(temp) +
                  ', ' + str(fe) + ', ' + str(alpha) + ' Skipped #' +
                  str(i + 1) + '/' + str(Nstars) + ' stars')
            return None

        # Do membership check
        if membercheck is not None:
            if specname not in membernames:
                print('Not in member list! Skipped ' + specname)
                return None

        # Vary stellar parameters
        if correctionslist is not None:
            if int(specname) in np.asarray(correctionslist['ID']):
                idx = np.where(
                    np.asarray(correctionslist['ID']) == int(specname))[0]

                # Vary the quantity required
                if corrections[0] == 'Teff':
                    colstring = 'Teff' + str(int(np.abs(corrections[2])))
                    if corrections[1] == 'up':
                        temp = temp + corrections[
                            2]  # Make the correction go the right direction
                        fe = fe + float(
                            correctionslist['FeH_' + colstring][idx])
                    else:
                        temp = temp - corrections[2]
                        fe = fe - float(
                            correctionslist['FeH_' + colstring][idx])

                elif corrections[0] == 'logg':
                    colstring = 'logg0' + str(int(10 * np.abs(corrections[2])))
                    if corrections[1] == 'up':
                        logg = logg + corrections[
                            2]  # Make the correction go the right direction
                        fe = fe - float(
                            correctionslist['FeH_' + colstring][idx])
                    else:
                        logg = logg - corrections[2]
                        fe = fe + float(
                            correctionslist['FeH_' + colstring][idx])

            # Now determine the direction to vary alpha
            '''
			key = corrections[0]+str(corrections[2])
			if corrections[3] == 'up':
				alpha = alpha + float(correctionslist['MgFe_'+key][idx] + 4*correctionslist['SiFe_'+key][idx] + 2*correctionslist['CaFe_'+key][idx] + 6*correctionslist['TiFe_'+key][idx])/13
			else:
				alpha = alpha - float(correctionslist['MgFe_'+key][idx] + 4*correctionslist['SiFe_'+key][idx] + 2*correctionslist['CaFe_'+key][idx] + 6*correctionslist['TiFe_'+key][idx])/13
			'''

        else:
            print('No stellar parameter corrections listed!')

        # Run optimization code
        star = chi_sq.obsSpectrum(filename,
                                  paramfilename,
                                  i,
                                  wvlcorr,
                                  galaxyname,
                                  slitmaskname,
                                  globular,
                                  lines,
                                  RA[i],
                                  Dec[i],
                                  plot=True,
                                  specialparams=[temp, logg, fe, alpha])
        best_mn, error, finalchisq = star.plot_chisq(fe,
                                                     output=True,
                                                     plots=plots)

        print('Finished star ' + star.specname,
              '#' + str(i + 1) + '/' + str(Nstars) + ' stars')

        result = np.array([
            star.temp, star.logg, star.fe, star.fe_err, star.alpha, best_mn,
            error
        ],
                          dtype=object)
        for i in range(len(result)):
            if np.isscalar(result[i]) == False:
                result[i] = result[i][0]

        return star.specname, str(RA[i]), str(Dec[i]), str(result[0]), str(
            result[1]), str(result[2]), str(result[3]), str(result[4]), str(
                result[5]), str(result[6]), str(finalchisq)

    except Exception as e:
        print(repr(e))
        print('Skipped star #' + str(i + 1) + '/' + str(Nstars) + ' stars')
        return None
Exemple #4
0
    def __init__(self,
                 obsfilename,
                 paramfilename,
                 starnum,
                 wvlcorr,
                 galaxyname,
                 slitmaskname,
                 globular,
                 lines,
                 RA,
                 Dec,
                 obsspecial=None,
                 plot=False,
                 hires=None,
                 smooth=None,
                 specialparams=None):

        # Observed star
        self.obsfilename = obsfilename  # File with observed spectra
        self.paramfilename = paramfilename  # File with parameters of observed spectra
        self.starnum = starnum  # Star number
        self.galaxyname = galaxyname  # Name of galaxy
        self.slitmaskname = slitmaskname  # Name of slitmask
        self.globular = globular  # Parameter marking if globular cluster
        self.lines = lines  # Parameter marking whether or not to use revised or original linelist

        # If observed spectrum comes from moogify file (default), open observed file and continuum normalize as usual
        if obsspecial is None:

            # Output filename
            if self.globular:
                self.outputname = '/raid/madlr/glob/' + galaxyname + '/' + slitmaskname
            else:
                self.outputname = '/raid/madlr/dsph/' + galaxyname + '/' + slitmaskname

            # Open observed spectrum
            self.specname, self.obswvl, self.obsflux, self.ivar, self.dlam, self.zrest = open_obs_file(
                self.obsfilename, retrievespec=self.starnum)

            # Get measured parameters from observed spectrum
            self.temp, self.logg, self.fe, self.alpha, self.fe_err = open_obs_file(
                self.paramfilename,
                self.starnum,
                specparams=True,
                objname=self.specname,
                inputcoords=[RA, Dec])
            if specialparams is not None:
                self.temp = specialparams[0]
                self.logg = specialparams[1]
                self.fe = specialparams[2]
                self.alpha = specialparams[3]

            if plot:
                # Plot observed spectrum
                plt.figure()
                plt.plot(self.obswvl, self.obsflux, 'k-')
                plt.axvspan(4749, 4759, alpha=0.5, color='blue')
                plt.axvspan(4778, 4788, alpha=0.5, color='blue')
                plt.axvspan(4818, 4828, alpha=0.5, color='blue')
                plt.axvspan(5389, 5399, alpha=0.5, color='blue')
                plt.axvspan(5532, 5542, alpha=0.5, color='blue')
                plt.axvspan(6008, 6018, alpha=0.5, color='blue')
                plt.axvspan(6016, 6026, alpha=0.5, color='blue')
                plt.axvspan(4335, 4345, alpha=0.5, color='red')
                plt.axvspan(4856, 4866, alpha=0.5, color='red')
                plt.axvspan(6558, 6568, alpha=0.5, color='red')
                plt.savefig(self.outputname + '/' + self.specname + '_obs.png')
                plt.close()

            # Get synthetic spectrum, split both obs and synth spectra into red and blue parts
            synthfluxmask, obsfluxmask, obswvlmask, ivarmask, mask = mask_obs_for_division(
                self.obswvl,
                self.obsflux,
                self.ivar,
                temp=self.temp,
                logg=self.logg,
                fe=self.fe,
                alpha=self.alpha,
                dlam=self.dlam,
                lines=self.lines)

            if plot:
                # Plot spliced synthetic spectrum
                plt.figure()
                plt.plot(obswvlmask[0], synthfluxmask[0], 'b-')
                plt.plot(obswvlmask[1], synthfluxmask[1], 'r-')
                plt.savefig(self.outputname + '/' + self.specname +
                            '_synth.png')
                plt.close()

            # Compute continuum-normalized observed spectrum
            self.obsflux_norm, self.ivar_norm = divide_spec(
                synthfluxmask,
                obsfluxmask,
                obswvlmask,
                ivarmask,
                mask,
                sigmaclip=True,
                specname=self.specname,
                outputname=self.outputname)

            if plot:
                # Plot continuum-normalized observed spectrum
                plt.figure()
                plt.plot(self.obswvl, self.obsflux_norm, 'k-')
                plt.axvspan(4749, 4759, alpha=0.5, color='blue')
                plt.axvspan(4778, 4788, alpha=0.5, color='blue')
                plt.axvspan(4818, 4828, alpha=0.5, color='blue')
                plt.axvspan(5389, 5399, alpha=0.5, color='blue')
                plt.axvspan(5532, 5542, alpha=0.5, color='blue')
                plt.axvspan(6008, 6018, alpha=0.5, color='blue')
                plt.axvspan(6016, 6026, alpha=0.5, color='blue')
                plt.axvspan(4335, 4345, alpha=0.5, color='red')
                plt.axvspan(4856, 4866, alpha=0.5, color='red')
                plt.axvspan(6558, 6568, alpha=0.5, color='red')
                plt.ylim((0, 5))
                plt.savefig(self.outputname + '/' + self.specname +
                            '_obsnormalized.png')
                plt.close()
                np.savetxt(
                    self.outputname + '/' + self.specname +
                    '_obsnormalized.txt',
                    np.asarray((self.obswvl, self.obsflux_norm)).T)

            if wvlcorr:
                print('Doing wavelength correction...')

                try:
                    # Compute standard deviation
                    contdivstd = np.zeros(len(self.ivar_norm)) + np.inf
                    contdivstd[self.ivar_norm > 0] = np.sqrt(
                        np.reciprocal(self.ivar_norm[self.ivar_norm > 0]))

                    # Wavelength correction
                    self.obswvl = fit_wvl(self.obswvl, self.obsflux_norm,
                                          contdivstd, self.dlam, self.temp,
                                          self.logg, self.fe, self.alpha,
                                          self.specname, self.outputname + '/')

                    print('Done with wavelength correction!')

                except Exception as e:
                    print(repr(e))
                    print(
                        'Couldn\'t complete wavelength correction for some reason.'
                    )

            # Crop observed spectrum into regions around Mn lines
            self.obsflux_fit, self.obswvl_fit, self.ivar_fit, self.dlam_fit, self.skip = mask_obs_for_abundance(
                self.obswvl,
                self.obsflux_norm,
                self.ivar_norm,
                self.dlam,
                lines=self.lines)

        # Else, check if we need to open a hi-res file to get the spectrum
        elif hires is not None:

            # Output filename
            if self.globular:
                self.outputname = '/raid/madlr/glob/' + galaxyname + '/' + 'hires'
            else:
                self.outputname = '/raid/madlr/dsph/' + galaxyname + '/' + 'hires'

            # Open observed spectrum
            self.specname = hires
            self.obswvl, self.obsflux, self.dlam = open_obs_file(
                self.obsfilename, hires=True)

            # Get measured parameters from obsspecial keyword
            self.temp = obsspecial[0]
            self.logg = obsspecial[1]
            self.fe = obsspecial[2]
            self.alpha = obsspecial[3]
            self.fe_err = obsspecial[4]
            self.zrest = obsspecial[5]

            self.ivar = np.ones(len(self.obsflux))

            # Correct for wavelength
            self.obswvl = self.obswvl / (1. + self.zrest)
            print('Redshift: ', self.zrest)

            # Get synthetic spectrum, split both obs and synth spectra into red and blue parts
            synthfluxmask, obsfluxmask, obswvlmask, ivarmask, mask = mask_obs_for_division(
                self.obswvl,
                self.obsflux,
                self.ivar,
                temp=self.temp,
                logg=self.logg,
                fe=self.fe,
                alpha=self.alpha,
                dlam=self.dlam,
                lines=self.lines,
                hires=True)

            # Compute continuum-normalized observed spectrum
            self.obsflux_norm, self.ivar_norm = divide_spec(
                synthfluxmask,
                obsfluxmask,
                obswvlmask,
                ivarmask,
                mask,
                specname=self.specname,
                outputname=self.outputname,
                hires=True)

            if smooth is not None:

                # Crop med-res wavelength range to match hi-res spectrum
                smooth = smooth[np.where((smooth > self.obswvl[0])
                                         & (smooth < self.obswvl[-1]))]

                # Interpolate and smooth the synthetic spectrum onto the observed wavelength array
                self.dlam = np.ones(len(smooth)) * 0.7086
                self.obsflux_norm = smooth_gauss_wrapper(
                    self.obswvl, self.obsflux_norm, smooth, self.dlam)
                self.obswvl = smooth
                self.ivar_norm = np.ones(len(self.obswvl)) * 1.e4

            if plot:
                # Plot continuum-normalized observed spectrum
                plt.figure()
                plt.plot(self.obswvl, self.obsflux_norm, 'k-')
                plt.savefig(self.outputname + '/' + self.specname +
                            '_obsnormalized.png')
                plt.close()

            # Crop observed spectrum into regions around Mn lines
            self.obsflux_fit, self.obswvl_fit, self.ivar_fit, self.dlam_fit, self.skip = mask_obs_for_abundance(
                self.obswvl,
                self.obsflux_norm,
                self.ivar_norm,
                self.dlam,
                lines=self.lines,
                hires=True)

        # Else, take both spectrum and observed parameters from obsspecial keyword
        else:

            # Output filename
            self.outputname = '/raid/madlr/test/' + slitmaskname

            self.obsflux_fit = obsspecial[0]
            self.obswvl_fit = obsspecial[1]
            self.ivar_fit = obsspecial[2]
            self.dlam_fit = obsspecial[3]
            self.skip = obsspecial[4]
            self.temp = obsspecial[5]
            self.logg = obsspecial[6]
            self.fe = obsspecial[7]
            self.alpha = obsspecial[8]
            self.fe_err = obsspecial[9]

            self.specname = self.slitmaskname

        # Splice together Mn line regions of observed spectra
        print('Skip: ', self.skip)

        self.obsflux_final = np.hstack((self.obsflux_fit[self.skip]))
        self.obswvl_final = np.hstack((self.obswvl_fit[self.skip]))
        self.ivar_final = np.hstack((self.ivar_fit[self.skip]))
Exemple #5
0
def run_chisq(filename, paramfilename, galaxyname, slitmaskname, startstar=0, globular=False, lines='new', plots=False, wvlcorr=True, membercheck=None, memberlist=None, velmemberlist=None):
	""" Measure Mn abundances from a FITS file.

	Inputs:
	filename 		-- file with observed spectra
	paramfilename 	-- file with parameters of observed spectra
	galaxyname		-- galaxy name, options: 'scl'
	slitmaskname 	-- slitmask name, options: 'scl1'

	Keywords:
	startstar		-- if 0 (default), start at beginning of file and write new datafile;
						else, start at #startstar and just append to datafile
	globular 		-- if 'False' (default), put into output path of galaxy;
						else, put into globular cluster path
	lines 			-- if 'new' (default), use new revised linelist;
						else, use original linelist from Judy's code
	plots 			-- if 'False' (default), don't plot final fits/resids while doing the fits;
						else, plot them
	wvlcorr 		-- if 'True' (default), do linear wavelength corrections following G. Duggan's code for 900ZD data;
						else (for 1200B data), don't do corrections
	membercheck 	-- do membership check for this object
	memberlist		-- member list (from Evan's Li-rich giants paper)
	velmemberlist 	-- member list (from radial velocity check)

	"""

	# Output filename
	if globular:
		outputname = '/raid/madlr/glob/'+galaxyname+'/'+slitmaskname+'.csv'
	else:
		outputname = '/raid/madlr/dsph/'+galaxyname+'/'+slitmaskname+'.csv'

	# Open new file
	if startstar<1:
		with open(outputname, 'w+') as f:
			f.write('Name\tRA\tDec\tTemp\tlog(g)\t[Fe/H]\terror([Fe/H])\t[alpha/Fe]\t[Mn/H]\terror([Mn/H])\tchisq(reduced)\n')

	# Prep for member check
	if membercheck is not None:

		# Check if stars are in member list from Evan's Li-rich giants paper
		table = ascii.read(memberlist)
		memberindex = np.where(table.columns[0] == membercheck)
		membernames = table.columns[1][memberindex]

		# Also check if stars are in member list from velocity cut
		if velmemberlist is not None:
			oldmembernames = membernames
			membernames = []
			velmembernames = np.genfromtxt(velmemberlist,dtype='str')
			for i in range(len(oldmembernames)):
				if oldmembernames[i] in velmembernames:
					membernames.append(oldmembernames)

			membernames = np.asarray(membernames)

	# Get number of stars in file
	Nstars = open_obs_file(filename)

	# Get coordinates of stars in file
	RA, Dec = open_obs_file(filename, coords=True)

	# Run chi-sq fitting for all stars in file
	for i in range(startstar, Nstars):

		try:
			# Get metallicity of star to use for initial guess
			print('Getting initial metallicity')
			temp, logg, fe, alpha, fe_err = open_obs_file(filename, retrievespec=i, specparams=True)

			# Get dlam (FWHM) of star to use for initial guess
			specname, obswvl, obsflux, ivar, dlam, zrest = open_obs_file(filename, retrievespec=i)

			# Check for bad parameter measurement
			if np.isclose(temp, 4750.) and np.isclose(fe,-1.5) and np.isclose(alpha,0.2):
				print('Bad parameter measurement! Skipped #'+str(i+1)+'/'+str(Nstars)+' stars')
				continue

			# Do membership check
			if membercheck is not None:
				if specname not in membernames:
					print('Not in member list! Skipped '+specname)  #'+str(i+1)+'/'+str(Nstars)+' stars')
					continue

			# Run optimization code
			star = chi_sq.obsSpectrum(filename, paramfilename, i, wvlcorr, galaxyname, slitmaskname, globular, lines, RA[i], Dec[i], plot=True)
			best_mn, error, finalchisq = star.plot_chisq(fe, output=True, plots=plots)

		except Exception as e:
			print(repr(e))
			print('Skipped star #'+str(i+1)+'/'+str(Nstars)+' stars')
			continue

		print('Finished star '+star.specname, '#'+str(i+1)+'/'+str(Nstars)+' stars')
		#print('test', star.specname, RA[i], Dec[i], star.temp, star.logg, star.fe, star.fe_err, star.alpha, best_mn, error, finalchisq)

		with open(outputname, 'a') as f:
			f.write(star.specname+'\t'+str(RA[i])+'\t'+str(Dec[i])+'\t'+str(star.temp)+'\t'+str(star.logg)+'\t'+str(star.fe)+'\t'+str(star.fe_err)+'\t'+str(star.alpha)+'\t'+str(best_mn[0])+'\t'+str(error[0])+'\t'+str(finalchisq)+'\n')

	return
Exemple #6
0
def plot_fits_postfacto(filename, paramfilename, galaxyname, slitmaskname, startstar=0, globular=False, lines='new', mn_cluster=None):
	""" Plot fits, residuals, and ivar for stars whose [Mn/H] abundances have already been measured.

	Inputs:
	filename 		-- file with observed spectra
	paramfilename 	-- file with parameters of observed spectra
	galaxyname		-- galaxy name, options: 'scl'
	slitmaskname 	-- slitmask name, options: 'scl1'

	Keywords:
	startstar		-- if 0 (default), start at beginning of file and write new datafile;
						else, start at #startstar and just append to datafile
	globular 		-- if 'False' (default), put into output path of galaxy;
						else, put into globular cluster path
	lines 			-- if 'new' (default), use new revised linelist;
						else, use original linelist from Judy's code
	mn_cluster 		-- if not None (default), also plot spectrum with [Mn/H] = mean [Mn/H] of cluster

	"""

	# Input filename
	if globular:
		file = '/raid/madlr/glob/'+galaxyname+'/'+slitmaskname+'.csv'
	else:
		file = '/raid/madlr/dsph/'+galaxyname+'/'+slitmaskname+'.csv'

	# Output filepath
	if globular:
		outputname = '/raid/madlr/glob/'+galaxyname+'/'+slitmaskname
	else:
		outputname = '/raid/madlr/dsph/'+galaxyname+'/'+slitmaskname

	name  = np.genfromtxt(file, delimiter='\t', skip_header=1, usecols=0, dtype='str')
	mn    = np.genfromtxt(file, delimiter='\t', skip_header=1, usecols=8)
	mnerr = np.genfromtxt(file, delimiter='\t', skip_header=1, usecols=9)

	# Get number of stars in file with observed spectra
	Nstars = open_obs_file(filename)

	# Open file to store reduced chi-sq values
	chisqfile = outputname+'_chisq.txt'
	with open(chisqfile, 'w+') as f:
		print('made it here')
		f.write('Star'+'\t'+'Line'+'\t'+'redChiSq (best[Mn/H])'+'\t'+'redChiSq (best[Mn/H]+0.15)'+'\t'+'redChiSq (best[Mn/H]-0.15)'+'\n')

	# Plot spectra for each star
	for i in range(startstar, Nstars):

		try:

			# Check if parameters are measured
			temp, logg, fe, alpha, fe_err = open_obs_file(filename, retrievespec=i, specparams=True)
			if np.isclose(1.5,logg) and np.isclose(fe,-1.5) and np.isclose(fe_err, 0.0):
				print('Bad parameter measurement! Skipped #'+str(i+1)+'/'+str(Nstars)+' stars')
				continue

			# Open star
			star = chi_sq.obsSpectrum(filename, paramfilename, i, False, galaxyname, slitmaskname, globular, lines, plot=True)

			# Check if star has already had [Mn/H] measured
			if star.specname in name:

				# If so, open data file for star
				if globular:
					datafile = '/raid/madlr/glob/'+galaxyname+'/'+slitmaskname+'/'+str(star.specname)+'_data.csv'
				else:
					datafile = '/raid/madlr/dsph/'+galaxyname+'/'+slitmaskname+'/'+str(star.specname)+'_data.csv'

				# Get observed and synthetic spectra and inverse variance array
				obswvl 		= np.genfromtxt(datafile, delimiter=',', skip_header=2, usecols=0)
				obsflux 	= np.genfromtxt(datafile, delimiter=',', skip_header=2, usecols=1)
				synthflux 	= np.genfromtxt(datafile, delimiter=',', skip_header=2, usecols=2)
				#synthfluxup = np.genfromtxt(datafile, delimiter=',', skip_header=2, usecols=3)
				#synthfluxdown = np.genfromtxt(datafile, delimiter=',', skip_header=2, usecols=4)
				ivar 		= np.genfromtxt(datafile, delimiter=',', skip_header=2, usecols=5)

				idx = np.where(name == star.specname)

				synthfluxup 	= star.synthetic(obswvl, mn[idx] + 0.15, full=True)
				synthfluxdown 	= star.synthetic(obswvl, mn[idx] - 0.15, full=True)
				synthflux_nomn 	= star.synthetic(obswvl, -10.0, full=True)

				if mn_cluster is not None:
					synthflux_cluster = [mn_cluster, star.synthetic(obswvl, mn_cluster, full=True)]
				else:
					synthflux_cluster=None

				if mnerr[idx][0] < 1:
					# Run code to make plots
					make_plots(lines, star.specname+'_', obswvl, obsflux, synthflux, outputname, ivar=ivar, resids=True, synthfluxup=synthfluxup, synthfluxdown=synthfluxdown, synthflux_nomn=synthflux_nomn, synthflux_cluster=synthflux_cluster, title=None, savechisq=chisqfile)

					# Write all plotting data to a file
					hdr = 'Star '+str(star.specname)+'\n'+'obswvl\tobsflux\tsynthflux\tsynthfluxup\tsynthfluxdown\tsynthflux_nomn\n'
					np.savetxt(outputname+'/'+str(star.specname)+'_finaldata.csv', np.asarray((obswvl,obsflux,synthflux,synthfluxup,synthfluxdown,synthflux_nomn)).T, header=hdr)

		except Exception as e:
			print(repr(e))
			print('Skipped star #'+str(i+1)+'/'+str(Nstars)+' stars')
			continue

		print('Finished star '+star.specname, '#'+str(i+1)+'/'+str(Nstars)+' stars')

	return