Example #1
0
def make_entry(match,SI,intercept,SI_err,intercept_err,g_stats,accept_type,low_resids,chired):
	'''Gather all of the information together in to a format that can easily be read in to create
	the output VOTable'''
	source = mkl.get_srcg(match)
	source.SI = SI
	source.intercept = intercept
	source.SI_err = SI_err
	source.intercept_err = intercept_err
	source.low_resids = low_resids
	sources.append(source)
	g_stats.accept_type = accept_type
	sources_stats.append(g_stats)
	source.chi_resid = chired
Example #2
0
def make_entry(match, SI, intercept, SI_err, intercept_err, g_stats,
               accept_type, low_resids, chired, match_type):
    '''Gather all of the information together in to a format that can easily be read in to create
	the output FITS or VOTable'''
    source = mkl.get_srcg(match)
    source.SI = SI
    source.intercept = intercept
    source.SI_err = SI_err
    source.intercept_err = intercept_err
    source.low_resids = low_resids
    sources.append(source)
    g_stats.accept_type = accept_type
    g_stats.match_type = match_type
    sources_stats.append(g_stats)
    source.chi_resid = chired
    for cat, name in zip(source.cats[1:], source.names[1:]):
        source.matched_names.append((cat, name))
Example #3
0
def single_match_test(src_all, comp, accepted_matches, accepted_inds, g_stats,
                      num_matches, repeated_cats, matches):
    '''Takes a combination of sources, one from each catalogue, with positional probabilities,
	and determines whether they are a match or not - Algorithm 2 in the write up'''
    match = accepted_matches[0]
    prob = float(match[-1])

    ##calculate_resids needs a list of matches - calculate parameters
    jstat_resids, params, bses, chi_resids = mkl.calculate_resids([match])

    ##Gather source information
    src_g = mkl.get_srcg(match)

    ##Play the prob trick again to work out which match has been accepted
    match_probs = [float(m.split()[-1]) for m in matches]
    dom_num = match_probs.index(prob) + 1
    match_crit = "Combination (%d)\npossible\n%s repeated cats" % (
        dom_num, repeated_cats)

    ##Check to see if all matched sources are within the closeness test - create an
    ##error ellipse by combined closeness with base cat error
    ##Need to convert closeness in to an RA offset, due to spherical trigonometry
    dr = np.pi / 180.0
    delta_RA = np.arccos(
        (np.cos(closeness * dr) - np.sin(src_all.decs[0] * dr)**2) /
        np.cos(src_all.decs[0] * dr)**2) / dr

    ##Make a list of the ras and decs of the sources to distance test
    ras_test = [ra for ra in src_g.ras if ra != -100000.0]
    dec_test = [dec for dec in src_g.decs if dec != -100000.0]

    small_test = []
    for ra, dec in zip(ras_test, dec_test):
        ##We set up delta_RA to give us the equivalent offset in RA that corresponds to the
        ##resolution, so we use the offset in RA, not the arcdistance
        prim_ra = src_all.ras[0]
        ra_dist = ra - prim_ra
        ##Code to cope if one source 359.9, other 0.1 etc.
        if abs(ra_dist) > 180.0:
            if ra > 180.0:
                ra -= 360.0
                ra_dist = prim_ra - ra
            else:
                prim_ra -= 360.0
                ra_dist = ra - prim_ra

        dec_dist = src_all.decs[0] - dec
        ra_axis = src_all.rerrs[0] + abs(delta_RA)
        dec_axis = src_all.derrs[0] + closeness

        ##Test to see if the source lies with an error ellipse created using semi-major
        ##and minor axes defined by the ra and dec error of the base cat + half the resolution
        ##of the base cat (closeness)
        ell_test = (ra_dist / ra_axis)**2 + (dec_dist / dec_axis)**2
        if ell_test <= 1:
            small_test.append('yes')
        else:
            ##Otherwise, fails
            small_test.append('no')
            #no_names.append(repeat_name)  #Note the name of the sources that are far away

    #Fail the positional test if a source is outside of the resolution plus position error
    close_test = 'passed'
    if 'no' in small_test: close_test = 'failed'

    ##If prob is higher than threshold, ignore position of sources and accept the match
    if prob > high_prob:
        ##Accept the source, put it in a way that can be read when constructing the final table
        if chi_resids[0] <= 2:
            make_entry(match, params[0][0], params[0][1], bses[0][0],
                       bses[0][1], g_stats, 'position', 0, chi_resids[0],
                       'isolated')
        else:
            make_entry(match, params[0][0], params[0][1], bses[0][0],
                       bses[0][1], g_stats, 'position', 1, chi_resids[0],
                       'isolated')

        make_accept(comp, g_stats, 'position', accepted_inds)
    else:
        ##look to see if all sources are within the resolution of the
        ##base catalogue or above some probability theshold, if so check with a spec test else reject them
        if close_test == 'passed' or prob > low_prob:
            ##IF below eith threshold, append with the applicable fit label
            if jstat_resids[0] <= jstat_thresh or chi_resids[0] <= chi_thresh:
                if chi_resids[0] <= 2:
                    make_entry(match, params[0][0], params[0][1], bses[0][0],
                               bses[0][1], g_stats, 'spectral', 0,
                               chi_resids[0], 'isolated')
                else:
                    make_entry(match, params[0][0], params[0][1], bses[0][0],
                               bses[0][1], g_stats, 'spectral', 1,
                               chi_resids[0], 'isolated')
                make_accept(comp, g_stats, 'spectral', accepted_inds)
            else:
                g_stats.retained_matches = 1
                ##Put accepted inds as [0] just to have something outputted to the investigate text file -
                ##accepted_inds is empty is rejecting at this stage
                make_rejection(comp, g_stats, 'spectral', [0])
        else:
            g_stats.retained_matches = 1
            make_rejection(comp, g_stats, 'position', [0])
Example #4
0
    ##If just one combo positionally possible, do a single combo check
    elif len(accepted_matches) == 1:
        single_match_test(src_all, comp, accepted_matches, accepted_inds,
                          g_stats, len(matches), repeated_cats, matches)

    ##If more than one combination is positionally possible:
    else:
        ##Check for a dominant source. The combination must be the only one with high position prob,
        ##all others with low positional proability, and must dominate spectrally

        num_cat = len(set([cat for cat in src_all.cats if cat != '-100000.0']))

        dom_source = mkl.spec_pos_agree(jstats, chi_reds, accepted_probs,
                                        num_cat)
        src_g = mkl.get_srcg(accepted_matches[0])
        ##If it finds a dominant source, accept it - counts as a spectral match
        if dom_source != 'none':
            jstat_resids, params, bses, chi_resids = mkl.calculate_resids(
                [accepted_matches[dom_source]])
            if chi_resids[0] <= 2:
                make_entry(accepted_matches[dom_source], params[0][0],
                           params[0][1], bses[0][0], bses[0][1], g_stats,
                           'spectral', 0, chi_resids[0], 'dominant')
            else:
                make_entry(accepted_matches[dom_source], params[0][0],
                           params[0][1], bses[0][0], bses[0][1], g_stats,
                           'spectral', 1, chi_resids[0], 'dominant')
            make_accept(comp, g_stats, 'spectral', accepted_inds)
        ##If nothing dominates, send to check if a combined source works
        else:
def create_plot(comp,accepted_inds,match_crit,dom_crit,outcome):
	'''The main plotting function that takes the relevant data and plots the outcome'''
	###Split the information up as needed
	chunks = comp.split('START_COMP')
	all_info = chunks[0].split('\n')
	
	##FOR SOME REASON CAN'T DO BOTH OF THESE LINES IN THE SAME FOR LOOP?!?!?!
	for entry in all_info:   
		if entry=='': del all_info[all_info.index(entry)]
	for entry in all_info:
		if 'START' in entry: del all_info[all_info.index(entry)]

	matches = chunks[1].split('\n')
	del matches[0],matches[-2:]

	##See how many matches there are, and set up the number of plots needed. If there are
	##more than 16 matches, only plot the top 15 and print how many more matches there 
	##were - saves heaps of tiny little plots from appearing
	num_matches = len(matches)
	skip_16 = 'no'
	if num_matches==1:
		width = 1
		height = 2
	elif num_matches>16:
		width = 4
		height = 4
		skip_16 = 'yes'
	else:
		width = int(num_matches**0.5)
		height = num_matches/width
		if num_matches%width==0:
			pass
		else:
			height+=1
	
	##Sets up a grid layout for the whole of the figure. We'll use half later on for
	##the individual plots
	gs = gridspec.GridSpec(height,2*width)
	
	##Need a big plot!
	fig = plt.figure(figsize = (18,11))

	##Find out the ra,dec of the base catalogue source
	info=all_info[0].split()
	ra_main = float(info[2])
	dec_main = float(info[4])
	
	##Set up dedicated left plots
	main_dims = [0.16, 0.5, 0.29, 0.35]
	spec_dims = [0.16, 0.1, 0.29, 0.35]
	ax_main,ax_spectral,tr_fk5,wcs = make_left_plots(fig,main_dims,spec_dims,ra_main,dec_main)
	
	##Find the limits out to search area - have to do each edge individual,
	##because of the arcdistance projection malarky
	##Even at the same dec, 3 arcmins apart in RA doesn't translate to 3arcmin arcdist - projection
	##fun. Can use law of cosines on a sphere to work out appropriate delta RA. Use this to define plot
	##limits for a nice looking plot
	delta_RA = np.arccos((np.cos((2*closeness)*dr)-np.sin(dec_main*dr)**2)/np.cos(dec_main*dr)**2)/dr
	plot_lim = (2*closeness) + (0.1/60.0)
	ra_up_lim = ra_main + delta_RA + (0.1/60.0)
	ra_down_lim = ra_main - delta_RA - (0.1/60.0)
	dec_up_lim = dec_main + plot_lim
	dec_down_lim = dec_main - plot_lim
	
	##Plot the individual combination plots - do this first so the error bars go over
	##the top of the line plots
	spec_labels = []
	SIs = []
	for i in xrange(height):
		for j in range(width,2*width):
			if i*j == 21:
				if skip_16=='yes':
					ax = plt.subplot(gs[i,j])
					ax.set_xticklabels([])
					ax.set_yticklabels([])
					ax.text(0.5,0.5,"And %d\nother\nplots" %(num_matches-15),transform=ax.transAxes,verticalalignment='center',horizontalalignment='center',fontsize=16)
			else:
				try:
					ind = (i*width)+(j-width)
					match = matches[ind]
					ax = plt.subplot(gs[i,j])
					ax.set_xticklabels([])
					ax.set_yticklabels([])
					##TODO - if plot centred on or close to RA,Dec = 0,0 then going to get wrapping problems. Should be able to pull the need
					##for a wrap from ra_down_lim,ra_up_lim - one should be <0.0, or >360.0. Need to happen inside plot_ind
					prob,resid,spec_plot,params = plot_ind(match,ax,ind,ax_spectral,ra_down_lim,ra_up_lim,dec_down_lim,dec_up_lim,dom_crit,outcome)
					if spec_plot=='na':
						pass
					else:
						SIs.append([params[0],str(ind+1)])
						spec_labels.append(spec_plot)
				except IndexError:
					pass
	
	#===========================================================#
	##Plot the matching criteria information
	match1 = matches[0].split()
	src_g = mkl.get_srcg(match1)
	
	text_axes = fig.add_axes([0.45,0.5,0.125,0.35])
	text_axes.axis('off')

	##Plot the matching information
	props = dict(boxstyle='round', facecolor='w',lw='1.5')
	text_axes.text(0.5,0.5,'Match Criteria:\n%s\n\nDominace Test:\n%s\n\nOutcome:\n%s' %(match_crit,dom_crit,outcome),
		bbox=props,transform=text_axes.transAxes,verticalalignment='center',horizontalalignment='center',fontsize=16)
	
	all_fluxs = []
	##Fill the left hand plots with information goodness
	all_freqs = fill_left_plots(all_info,ra_main,dec_main,ax_main,ax_spectral,tr_fk5,wcs,all_fluxs,ra_down_lim,ra_up_lim,dec_down_lim,dec_up_lim,delta_RA)
	
	##If no repeated catalogues to combine, skip
	if num_matches==0 or num_matches==1:
		pass
	##Otherwise, plot the combined fluxes
	else:
		##Calculate and plot the combined fluxes of the two sources, even if source one or two has been accepted
		##just as a guide
		src_all = mkl.get_allinfo(all_info)
		
		##If positionally impossible don't plot combined info
		if accepted_inds=='Nope':
			pass
		##If only one position possible, don't plot combined info
		elif len(accepted_inds) == 1:
			pass
		##Otherwise, see what the combined fluxes look like
		else:
			comb_crit, ra_ws, rerr_ws, dec_ws, derr_ws, temp_freqs, comb_freqs, comb_fluxs, comb_ferrs, comb_fit, comb_jstat, comb_chi_red, combined_names, set_freqs, set_fluxs, set_fits = mkl.combine_flux(src_all,src_g,accepted_inds,'plot=yes',len(matches))
		
		##If the criteria sent the double to be combined, actually plot the fitted line
		if dom_crit == 'No dom. source':
			
			for freq,flux in zip(set_freqs,set_fluxs):
				ax_spectral.plot(freq,flux,linestyle='--',linewidth=1,color='r')
			
			split_colors = ['#AE70ED','#FFB60B','#62A9FF','#59DF00']
			for fit in set_fits:
				ind = set_fits.index(fit)
				ax_spectral.plot(set_freqs[ind],set_fluxs[ind],linestyle='--',linewidth=1.0,color=split_colors[ind],alpha=0.7)
				split_p, = ax_spectral.plot(temp_freqs,np.exp(fit.params[1] + np.log(temp_freqs)*fit.params[0]),linestyle='-',linewidth=1.5,color=split_colors[ind])
				spec_labels.append(split_p)
				SIs.append([fit.params[0],'split %d' %(ind+1)])
			
			bright_colours = ['#FF6600','#33FF33','#FF47A3','#00ebb3']
			
			for freq in xrange(len(comb_freqs)):
				plot_errors_comb('*',bright_colours[freq],comb_freqs[freq],comb_fluxs[freq],comb_ferrs[freq],'combo',16,ax_spectral)
			comb_p, = ax_spectral.plot(temp_freqs,np.exp(comb_fit.fittedvalues),linestyle='--',linewidth=1.5,color='k')
			spec_labels.append(comb_p)
			SIs.append([comb_fit.params[0],'comb'])
			
			##Send the combined fluxes to the all_fluxs so that ax_spectral is scaled appropriately
			for flux in comb_fluxs:
				all_fluxs.append(flux)
			
			for pos in xrange(len(ra_ws)):
				patch = plot_pos_comb('*',bright_colours[pos],ra_ws[pos],dec_ws[pos],rerr_ws[pos],derr_ws[pos],combined_names[pos],16,ax_main,ax_main.get_transform("fk5"))
				
	scale_spectral(all_fluxs,all_freqs,ax_spectral)

	##==============================================================

	fig.tight_layout()
	fig.subplots_adjust(bottom=0.1)
	fig.subplots_adjust(left=0.15)
	
	##Make room at the top of the plot for a legend for ax_main, make the legend
	fig.subplots_adjust(top=0.85)
	
	leg_labels = [r'$\alpha_{%s}$ = %.2f' %(SI[1],SI[0]) for SI in SIs]
	main_handles,main_labels = ax_main.get_legend_handles_labels()
	
	main_leg = fig.add_axes([0.05,0.87,0.9,0.05])
	main_leg.axis('off')
	main_leg.legend(main_handles,main_labels,loc='lower center',prop={'size':12},ncol=8) #,bbox_to_anchor=(0,1.02),
	
	spec_leg = fig.add_axes([0.45,0.1,0.125,0.35])
	spec_leg.axis('off')

	##Stop the legend from having so many entries that it goes off the plot	
	if len(spec_labels)>11:
		trim_labels = spec_labels[:10]
		trim_labels.append(spec_labels[-1])
		trim_legs = leg_labels[:10]
		trim_legs.append(leg_labels[-1])
		spec_leg.legend(trim_labels,trim_legs,loc='center',prop={'size':14},fancybox=True)
	else:
		spec_leg.legend(spec_labels,leg_labels,loc='center',prop={'size':14},fancybox=True)
	
	##Create an axes to contain patches for an ellipse legend
	patch_leg = fig.add_axes([0.015,0.1,0.06,0.75])
	patch_leg.set_xticks([])
	patch_leg.set_yticks([])
	patch_leg.set_xticklabels([])
	patch_leg.set_yticklabels([])
	
	##See what catalogues are present in the match
	present_cats = [cat for cat in set(src_g.cats) if cat!='-100000.0']
	##Scale accordingly
	increment = 1.0/(2+len(present_cats))
	ell_positions = np.arange(increment/2,1,increment)
	
	##Find the axes coord transform
	patch_trans = patch_leg.transAxes
	##Plot and name the resolution ellipse
	ell = patches.Ellipse((0.5,ell_positions[-2]),0.9,increment-0.05,angle=0,
		transform=patch_trans, linestyle='dashed',fc='none',lw=1.1,color='gray')
	patch_leg.add_patch(ell)
	patch_leg.text(0.5,ell_positions[-2],'Resolution\n+ error',
		transform=patch_trans,verticalalignment='center',horizontalalignment='center',fontsize=14)
	
	##Plot and name the search ellipse
	ell = patches.Ellipse((0.5,ell_positions[-1]),0.9,increment-0.05,angle=0,
		transform=patch_trans, linestyle='dashdot',fc='none',lw=1.1,color='k')
	patch_leg.add_patch(ell)
	patch_leg.text(0.5,ell_positions[-1],'Search\nradius',
		transform=patch_trans,verticalalignment='center',horizontalalignment='center',fontsize=14)
	
	##Use the same method as plot_all - for some reason was getting transform errors.
	##so do it separately here (sigh)
	for cat in present_cats:
		col_ind = matched_cats.index(cat)
		position_ind = present_cats.index(cat)
		patch_leg.errorbar(0.5,ell_positions[position_ind],0.01,0.075,marker=markers[col_ind],ms=8,mfc=marker_colours[col_ind],
			mec=marker_colours[col_ind],ecolor=marker_colours[col_ind],markeredgewidth=1,label='meh',linestyle='None',transform=patch_trans)
		
		ell = patches.Ellipse((0.5,ell_positions[position_ind]),0.9,increment-0.05,angle=0, transform=patch_trans,
			fc=ell_colours1[col_ind],color=ell_colours2[col_ind],alpha=alphas[col_ind])
		patch_leg.add_patch(ell)
		
		patch_leg.text(0.5,ell_positions[position_ind]-(increment/2-0.04),cat,
			transform=patch_trans,verticalalignment='center',horizontalalignment='center',fontsize=16)
	
	if save_plots:
		plt.savefig('%s-pumaplot.png' %all_info[0].split()[1],bbox_inches='tight',dpi=100)
		plt.close()
			
	else:
		plt.show()
Example #6
0
def make_plots(comp, i):
    ##Get the information into nice usable forms, and get rid of empty/pointless
    ##entries
    chunks = comp.split("START_COMP")
    all_info = chunks[0].split("\n")

    ##FOR SOME REASON CAN'T DO BOTH OF THESE LINES IN THE SAME FOR LOOP?!?!?!
    for entry in all_info:
        if entry == "":
            del all_info[all_info.index(entry)]
    for entry in all_info:
        if "START" in entry:
            del all_info[all_info.index(entry)]

    matches = chunks[1].split("\n")
    del matches[0], matches[-2:]

    ##Put the information for every source in the matched group in one source_group() class
    ##(see apply_criteria_lib for source_group())
    src_all = mkl.get_allinfo(all_info)

    # print src_all.names[0]

    ##This line applies positional criteria, and tells us if a simple one catalogue repeat source, returning
    ##how many combinations are possible and statistics on them
    repeated_cats, accepted_matches, accepted_inds, accepted_probs, jstats, chi_reds, g_stats = mkl.matches_retained(
        src_all, matches
    )
    match_crit = "%d of %d \ncombinations \npossible \n%s repeated cats" % (
        len(accepted_matches),
        len(matches),
        repeated_cats,
    )

    ##If no combinations are possible, reject all info (goes into the eyeball document)
    if len(accepted_matches) == 0:
        i = plot_accept_type(
            comp,
            accepted_inds,
            match_crit,
            "Positionally\nimpossible",
            "N/A",
            len(matches),
            plot_reject,
            src_all,
            "position",
            i,
        )

        ##If just one combo positionally possible, do a single combo check
    elif len(accepted_matches) == 1:
        i = single_match_test(
            src_all, comp, accepted_matches, accepted_inds, g_stats, len(matches), repeated_cats, matches, i
        )
        ##(Any plotting gets done within single_match_test)

        ##If more than one combination is positionally possible:
    else:
        ##Check for a dominant source. The combination must be the only one with high position prob,
        ##all others with low positional proability, and must dominate spectrally
        num_cat = len(set([cat for cat in src_all.cats if cat != "-100000.0"]))

        dom_source = mkl.spec_pos_agree(jstats, chi_reds, accepted_probs, num_cat)
        src_g = mkl.get_srcg(accepted_matches[0])
        ##If it finds a dominant source, accept it - counts as a spectral match
        if dom_source != "none":
            jstat_resids, params, bses, chi_resids = mkl.calculate_resids([accepted_matches[dom_source]])
            ##Find the probs of all the matches, and use the prob of the dom match to see what number match was accepted
            all_probs = [float(match.split()[-1]) for match in matches]
            accepted_prob = accepted_probs[dom_source]
            dom_num = all_probs.index(accepted_prob)

            i = plot_accept_type(
                comp,
                accepted_inds,
                match_crit,
                "Dom source (%d)" % (dom_num + 1),
                "Accept dom.\nsource",
                len(matches),
                plot_accept,
                src_all,
                "spectral",
                i,
            )

            ##If nothing dominates, send to check if a combined source works
        else:
            comb_crit, comb_source, comb_jstat, comb_chi_red = mkl.combine_flux(
                src_all, src_g, accepted_inds, "plot=no", len(matches)
            )
            ##See whether combined or split
            if "split" in comb_crit:
                accept_type = "split"
            else:
                accept_type = "combine"
                ##Plot the combine or split, based on whether accepted or retained to investigate
            if "Accepted" in comb_crit:
                i = plot_accept_type(
                    comp,
                    accepted_inds,
                    match_crit,
                    "No dom. source",
                    comb_crit,
                    len(matches),
                    plot_accept,
                    src_all,
                    accept_type,
                    i,
                )
            else:
                i = plot_accept_type(
                    comp,
                    accepted_inds,
                    match_crit,
                    "No dom. source",
                    comb_crit,
                    len(matches),
                    plot_eyeball,
                    src_all,
                    accept_type,
                    i,
                )
    return i
Example #7
0
def single_match_test(src_all, comp, accepted_matches, accepted_inds, g_stats, num_matches, repeated_cats, matches, i):
    """Takes a combination of sources, one from each catalogue, with positional probabilities,
	and determines whether they are a match or not - Algorithm 2 in the write up"""
    match = accepted_matches[0]
    prob = float(match[-1])
    ##calculate_resids needs a list of matches - calculate parameters
    jstat_resids, params, bses, chi_resids = mkl.calculate_resids([match])
    src_g = mkl.get_srcg(match)

    ##Play the prob trick again to work out which match has been accepted
    match_probs = [float(m.split()[-1]) for m in matches]
    dom_num = match_probs.index(prob) + 1
    match_crit = "Combination (%d)\npossible\n%s repeated cats" % (dom_num, repeated_cats)

    ##Check to see if all matched sources are within the closeness test - create an
    ##error ellipse by combined closeness with base cat error
    ##Need to convert closeness in to an RA offset, due to spherical trigonometry
    dr = np.pi / 180.0
    delta_RA = (
        np.arccos((np.cos(closeness * dr) - np.sin(src_all.decs[0] * dr) ** 2) / np.cos(src_all.decs[0] * dr) ** 2) / dr
    )

    ##Make a list of the ras and decs of the sources to distance test
    ras_test = [ra for ra in src_g.ras if ra != -100000.0]
    dec_test = [dec for dec in src_g.decs if dec != -100000.0]

    small_test = []
    for ra, dec in zip(ras_test, dec_test):
        ##We set up delta_RA to give us the equivalent offset in RA that corresponds to the
        ##resolution, so we use the offset in RA, not the arcdistance
        prim_ra = src_all.ras[0]
        ra_dist = ra - prim_ra
        ##Code to cope if one source 359.9, other 0.1 etc.
        if abs(ra_dist) > 180.0:
            if ra > 180.0:
                ra -= 360.0
                ra_dist = prim_ra - ra
            else:
                prim_ra -= 360.0
                ra_dist = ra - prim_ra

        dec_dist = src_all.decs[0] - dec
        ra_axis = src_all.rerrs[0] + abs(delta_RA)
        dec_axis = src_all.derrs[0] + closeness

        ##Test to see if the source lies with an error ellipse created using semi-major
        ##and minor axes defined by the ra and dec error of the base cat + half the resolution
        ##of the base cat (closeness)
        ell_test = (ra_dist / ra_axis) ** 2 + (dec_dist / dec_axis) ** 2
        if ell_test <= 1:
            small_test.append("yes")
        else:
            ##Otherwise, fails
            small_test.append("no")
            # no_names.append(repeat_name)  #Note the name of the sources that are far away

            # Fail the positional test if a source is outside of the resolution plus position error
    close_test = "passed"
    if "no" in small_test:
        close_test = "failed"

    ##If prob is higher than threshold, ignore position of sources and accept the match
    if prob > high_prob:
        i = plot_accept_type(
            comp,
            accepted_inds,
            match_crit,
            "N/A",
            "Pos. accepted\nby $P>P_u$",
            num_matches,
            plot_accept,
            src_all,
            "position",
            i,
        )
    else:
        ##look to see if all sources are within the resolution of the
        ##base catalogue or above some probability theshold, if so check with a spec test else reject them
        if close_test == "passed" or prob > low_prob:
            ##IF below either threshold, append with the applicable fit label
            if jstat_resids[0] <= jstat_thresh or chi_resids[0] <= chi_thresh:
                i = plot_accept_type(
                    comp,
                    accepted_inds,
                    match_crit,
                    "Spec. passed",
                    "Accept by spec",
                    num_matches,
                    plot_accept,
                    src_all,
                    "spectral",
                    i,
                )
            else:
                i = plot_accept_type(
                    comp,
                    accepted_inds,
                    match_crit,
                    "Spec. failed",
                    "Reject by spec",
                    num_matches,
                    plot_reject,
                    src_all,
                    "spectral",
                    i,
                )
        else:
            i = plot_accept_type(
                comp,
                accepted_inds,
                match_crit,
                "N/A",
                "pos reject by $P<P_l$",
                num_matches,
                plot_reject,
                src_all,
                "position",
                i,
            )
    return i
Example #8
0
def create_plot(comp,accepted_inds,match_crit,dom_crit,outcome):
    '''The main plotting function that takes the relevant data and plots the outcome'''
    ###Split the information up as needed
    chunks = comp.split('START_COMP')
    all_info = chunks[0].split('\n')

    ##FOR SOME REASON CAN'T DO BOTH OF THESE LINES IN THE SAME FOR LOOP?!?!?!
    for entry in all_info:
        if entry=='': del all_info[all_info.index(entry)]
    for entry in all_info:
        if 'START' in entry: del all_info[all_info.index(entry)]

    matches = chunks[1].split('\n')
    del matches[0],matches[-2:]

    ##See how many matches there are, and set up the number of plots needed. If there are
    ##more than 16 matches, only plot the top 15 and print how many more matches there
    ##were - saves heaps of tiny little plots from appearing
    num_matches = len(matches)
    skip_16 = 'no'
    if num_matches==1:
        width = 1
        height = 2
    elif num_matches>16:
        width = 4
        height = 4
        skip_16 = 'yes'
    else:
        width = int(num_matches**0.5)
        height = num_matches/width
        if num_matches%width==0:
            pass
        else:
            height+=1

    ##Sets up a grid layout for the whole of the figure. We'll use half later on for
    ##the individual plots
    gs = gridspec.GridSpec(int(round(height)),2*width)

    ##Need a big plot!
    fig = plt.figure(figsize = (18,11))

    ##Find out the ra,dec of the base catalogue source
    info=all_info[0].split()
    ra_main = float(info[2])
    dec_main = float(info[4])

    ##Set up dedicated left plots
    main_dims = [0.15, 0.5, 0.29, 0.35]
    spec_dims = [0.15, 0.1, 0.29, 0.35]
    ax_main,ax_spectral,tr_fk5,wcs = make_left_plots(fig,main_dims,spec_dims,ra_main,dec_main)

    ##Find the limits out to search area - have to do each edge individual,
    ##because of the arcdistance projection malarky
    ##Even at the same dec, 3 arcmins apart in RA doesn't translate to 3arcmin arcdist - projection
    ##fun. Can use law of cosines on a sphere to work out appropriate delta RA. Use this to define plot
    ##limits for a nice looking plot
    delta_RA = np.arccos((np.cos((2*closeness)*dr)-np.sin(dec_main*dr)**2)/np.cos(dec_main*dr)**2)/dr
    plot_lim = (2*closeness) + (0.1/60.0)
    ra_up_lim = ra_main + delta_RA + (0.1/60.0)
    ra_down_lim = ra_main - delta_RA - (0.1/60.0)
    dec_up_lim = dec_main + plot_lim
    dec_down_lim = dec_main - plot_lim

    ###Plot the individual combination plots - do this first so the error bars go over
    ##the top of the line plots
    spec_labels = []
    SIs = []
    for i in np.arange(height):
        for j in range(width,2*width):
            if i*j == 21:
                if skip_16=='yes':
                    ax = plt.subplot(gs[int(round(i)),int(round(j))])
                    ax.set_xticklabels([])
                    ax.set_yticklabels([])
                    ax.text(0.5,0.5,"And %d\nother\nplots" %(num_matches-15),transform=ax.transAxes,verticalalignment='center',horizontalalignment='center',fontsize=16)
            else:
                try:
                    ind = (i*width)+(j-width)
                    match = matches[int(round(ind))]
                    ax = plt.subplot(gs[int(round(i)),int(round(j))])
                    ax.set_xticklabels([])
                    ax.set_yticklabels([])
                    ##TODO - if plot centred on or close to RA,Dec = 0,0 then going to get wrapping problems. Should be able to pull the need
                    ##for a wrap from ra_down_lim,ra_up_lim - one should be <0.0, or >360.0. Need to happen inside plot_ind
                    prob,resid,spec_plot,params,bse = plot_ind(match,ax,ind,ax_spectral,ra_down_lim,ra_up_lim,dec_down_lim,dec_up_lim,dom_crit,outcome)
                    if spec_plot=='na':
                        pass
                    else:
                        SI_err = '%.2f' %bse[0]
                        if SI_err == 'inf': SI_err = 'N/A'

                        SIs.append([params[0],SI_err,str(ind+1)])
                        spec_labels.append(spec_plot)
                except IndexError:
                    pass

    #===========================================================#
    ##Plot the matching criteria information
    match1 = matches[0].split()
    src_g = mkl.get_srcg(match1)

    #spec_leg = fig.add_axes([0.435,0.1,0.125,0.35])
    text_axes = fig.add_axes([0.445,0.5,0.125,0.35])
    text_axes.axis('off')

    ##Plot the matching information
    props = dict(boxstyle='round', facecolor='w',lw='1.5')
    text_axes.text(0.5,0.5,'Match Criteria:\n%s\n\nDominace Test:\n%s\n\nOutcome:\n%s' %(match_crit,dom_crit,outcome),
        bbox=props,transform=text_axes.transAxes,verticalalignment='center',horizontalalignment='center',fontsize=16)

    all_fluxs = []
    ##Fill the left hand plots with information goodness
    all_freqs = fill_left_plots(all_info,ra_main,dec_main,ax_main,ax_spectral,tr_fk5,wcs,all_fluxs,ra_down_lim,ra_up_lim,dec_down_lim,dec_up_lim,delta_RA)

    ##If no repeated catalogues to combine, skip
    if num_matches==0 or num_matches==1:
        pass
    ##Otherwise, plot the combined fluxes
    else:
        ##Calculate and plot the combined fluxes of the two sources, even if source one or two has been accepted
        ##just as a guide
        src_all = mkl.get_allinfo(all_info)

        ##If positionally impossible don't plot combined info
        if accepted_inds=='Nope':
            pass
        ##If only one position possible, don't plot combined info
        elif len(accepted_inds) == 1:
            pass
        ##Otherwise, see what the combined fluxes look like
        else:
            comb_crit, ra_ws, rerr_ws, dec_ws, derr_ws, temp_freqs, comb_freqs, comb_fluxs, comb_ferrs, comb_fit, comb_jstat, comb_chi_red, comb_bse, combined_names, set_freqs, set_fluxs, set_fits, set_bses = mkl.combine_flux(src_all,src_g,accepted_inds,'plot=yes',len(matches))

        ##If the criteria sent the double to be combined, actually plot the fitted line
        if dom_crit == 'No dom. source':

            for freq,flux in zip(set_freqs,set_fluxs):
                ax_spectral.plot(freq,flux,linestyle='--',linewidth=1,color='r')

            split_colors = ['#AE70ED','#FFB60B','#62A9FF','#59DF00']
            for fit,bse in zip(set_fits,set_bses):
                ind = set_fits.index(fit)
                ax_spectral.plot(set_freqs[ind],set_fluxs[ind],linestyle='--',linewidth=1.0,color=split_colors[ind],alpha=0.7)
                split_p, = ax_spectral.plot(temp_freqs,np.exp(fit.params[1] + np.log(temp_freqs)*fit.params[0]),linestyle='-',linewidth=1.5,color=split_colors[ind])
                spec_labels.append(split_p)
                SI_err = '%.2f' %bse[0]
                if SI_err == 'inf': SI_err = 'N/A'
                SIs.append([fit.params[0],SI_err,'split %d' %(ind+1)])

            bright_colours = ['#FF6600','#33FF33','#FF47A3','#00ebb3']

            for freq in np.arange(len(comb_freqs)):
                plot_errors_comb('*',bright_colours[freq],comb_freqs[freq],comb_fluxs[freq],comb_ferrs[freq],'combo',16,ax_spectral)
            comb_p, = ax_spectral.plot(temp_freqs,np.exp(comb_fit.fittedvalues),linestyle='--',linewidth=1.5,color='k')
            spec_labels.append(comb_p)

            SI_err = '%.2f' %comb_bse[0]
            if SI_err == 'inf': SI_err = 'N/A'
            SIs.append([comb_fit.params[0],SI_err,'comb'])

            ##Send the combined fluxes to the all_fluxs so that ax_spectral is scaled appropriately
            for flux in comb_fluxs:
                all_fluxs.append(flux)

            for pos in np.arange(len(ra_ws)):
                patch = plot_pos_comb('*',bright_colours[pos],ra_ws[pos],dec_ws[pos],rerr_ws[pos],derr_ws[pos],combined_names[pos],16,ax_main,ax_main.get_transform("fk5"))

    scale_spectral(all_fluxs,all_freqs,ax_spectral)

    ##==============================================================

    fig.tight_layout()
    fig.subplots_adjust(bottom=0.1)
    fig.subplots_adjust(left=0.15)

    ##Make room at the top of the plot for a legend for ax_main, make the legend
    fig.subplots_adjust(top=0.85)

    leg_labels = [r'$\alpha_{%s}$ = %.2f$\pm$%s' %(SI[2],SI[0],SI[1]) for SI in SIs]
    main_handles,main_labels = ax_main.get_legend_handles_labels()

    main_leg = fig.add_axes([0.05,0.87,0.9,0.05])
    main_leg.axis('off')
    main_leg.legend(main_handles,main_labels,loc='lower center',prop={'size':12},ncol=8) #,bbox_to_anchor=(0,1.02),

    spec_leg = fig.add_axes([0.445,0.1,0.125,0.35])
    spec_leg.axis('off')

    ##Stop the legend from having so many entries that it goes off the plot
    if len(spec_labels)>11:
        trim_labels = spec_labels[:10]
        trim_labels.append(spec_labels[-1])
        trim_legs = leg_labels[:10]
        trim_legs.append(leg_labels[-1])
        spec_leg.legend(trim_labels,trim_legs,loc='center',prop={'size':14},fancybox=True)
    else:
        spec_leg.legend(spec_labels,leg_labels,loc='center',prop={'size':14},fancybox=True)

    ##Create an axes to contain patches for an ellipse legend
    patch_leg = fig.add_axes([0.015,0.1,0.06,0.75])
    patch_leg.set_xticks([])
    patch_leg.set_yticks([])
    patch_leg.set_xticklabels([])
    patch_leg.set_yticklabels([])

    ##See what catalogues are present in the match
    present_cats = [cat for cat in set(src_g.cats) if cat!='-100000.0']
    ##Scale accordingly
    increment = 1.0/(2+len(present_cats))
    ell_positions = np.arange(increment/2,1,increment)

    ##Find the axes coord transform
    patch_trans = patch_leg.transAxes
    ##Plot and name the resolution ellipse
    ell = patches.Ellipse((0.5,ell_positions[-2]),0.9,increment-0.05,angle=0,
        transform=patch_trans, linestyle='dashed',fc='none',lw=1.1,color='gray')
    patch_leg.add_patch(ell)
    patch_leg.text(0.5,ell_positions[-2],'Resolution\n+ error',
        transform=patch_trans,verticalalignment='center',horizontalalignment='center',fontsize=14)

    ##Plot and name the search ellipse
    ell = patches.Ellipse((0.5,ell_positions[-1]),0.9,increment-0.05,angle=0,
        transform=patch_trans, linestyle='dashdot',fc='none',lw=1.1,color='k')
    patch_leg.add_patch(ell)
    patch_leg.text(0.5,ell_positions[-1],'Search\nradius',
        transform=patch_trans,verticalalignment='center',horizontalalignment='center',fontsize=14)

    ##Use the same method as plot_all - for some reason was getting transform errors.
    ##so do it separately here (sigh)
    for cat in present_cats:
        col_ind = matched_cats.index(cat)
        position_ind = present_cats.index(cat)
        patch_leg.errorbar(0.5,ell_positions[position_ind],0.01,0.075,marker=markers[col_ind],ms=8,mfc=marker_colours[col_ind],
            mec=marker_colours[col_ind],ecolor=marker_colours[col_ind],markeredgewidth=1,label='meh',linestyle='None',transform=patch_trans)

        ell = patches.Ellipse((0.5,ell_positions[position_ind]),0.9,increment-0.05,angle=0, transform=patch_trans,
            fc=ell_colours1[col_ind],color=ell_colours2[col_ind],alpha=alphas[col_ind])
        patch_leg.add_patch(ell)

        patch_leg.text(0.5,ell_positions[position_ind]-(increment/2-0.04),cat,
            transform=patch_trans,verticalalignment='center',horizontalalignment='center',fontsize=16)

    if save_plots:
        plt.savefig('%s-pumaplot.png' %all_info[0].split()[1],bbox_inches='tight',dpi=75)
        plt.close()

    else:
        plt.show()
Example #9
0
	##Get the information into nice usable forms, and get rid of empty/pointless
	##entries
	chunks = comp.split('START_COMP')
	all_info = chunks[0].split('\n')
	##FOR SOME REASON CAN'T DO BOTH OF THESE LINES IN THE SAME FOR LOOP?!?!?!
	for entry in all_info:   
		if entry=='': del all_info[all_info.index(entry)]
	for entry in all_info:
		if 'START' in entry: del all_info[all_info.index(entry)]
	matches = chunks[1].split('\n')
	del matches[0],matches[-1]
	stats = matches[-1]
	del matches[-2:]

	match1 = matches[0].split()
	src_g = mkl.get_srcg(match1)
	##Get some info and find which catalogues are present 
	src_all = mkl.get_allinfo(all_info)
	
	try:
		if src_all.names[0] in extended_names:
			present_cats = [cat for cat in src_all.cats if cat!='-100000.0']
			
			meh,num_matches,accept_matches,accepted_inds,accept_type,stage = stats.split()
			
			image_num = bayes_comp.index(comp)+1
			image_locs = "./extended_fits"
			image_cats = [cat for cat in ['gleam','vlssr','sumss','nvss'] if os.path.exists("%s/%s_%s.fits" %(image_locs,src_all.names[0],cat))==True]
			image_files =["%s/%s_%s.fits" %(image_locs,src_all.names[0],cat) for cat in ['gleam','vlssr','sumss','nvss'] if os.path.exists("%s/%s_%s.fits" %(image_locs,src_all.names[0],cat))==True]
			
			fig = do_plot_image(all_info,image_cats,image_files,present_cats,src_all.names,src_g,matches)
Example #10
0
def make_plots(comp, i):
    ##Get the information into nice usable forms, and get rid of empty/pointless
    ##entries
    chunks = comp.split('START_COMP')
    all_info = chunks[0].split('\n')

    ##FOR SOME REASON CAN'T DO BOTH OF THESE LINES IN THE SAME FOR LOOP?!?!?!
    for entry in all_info:
        if entry == '': del all_info[all_info.index(entry)]
    for entry in all_info:
        if 'START' in entry: del all_info[all_info.index(entry)]

    matches = chunks[1].split('\n')
    del matches[0], matches[-2:]

    ##Put the information for every source in the matched group in one source_group() class
    ##(see apply_criteria_lib for source_group())
    src_all = mkl.get_allinfo(all_info)

    #print src_all.names[0]

    ##This line applies positional criteria, and tells us if a simple one catalogue repeat source, returning
    ##how many combinations are possible and statistics on them
    repeated_cats, accepted_matches, accepted_inds, accepted_probs, jstats, chi_reds, g_stats = mkl.matches_retained(
        src_all, matches)
    match_crit = "%d of %d \ncombinations \npossible \n%s repeated cats" % (
        len(accepted_matches), len(matches), repeated_cats)

    ##If no combinations are possible, reject all info (goes into the eyeball document)
    if len(accepted_matches) == 0:
        i = plot_accept_type(comp, accepted_inds,
                             match_crit, 'Positionally\nimpossible', 'N/A',
                             len(matches), plot_reject, src_all, 'position', i)

    ##If just one combo positionally possible, do a single combo check
    elif len(accepted_matches) == 1:
        i = single_match_test(src_all, comp, accepted_matches, accepted_inds,
                              g_stats, len(matches), repeated_cats, matches, i)
        ##(Any plotting gets done within single_match_test)

    ##If more than one combination is positionally possible:
    else:
        ##Check for a dominant source. The combination must be the only one with high position prob,
        ##all others with low positional proability, and must dominate spectrally
        num_cat = len(set([cat for cat in src_all.cats if cat != '-100000.0']))

        dom_source = mkl.spec_pos_agree(jstats, chi_reds, accepted_probs,
                                        num_cat)
        src_g = mkl.get_srcg(accepted_matches[0])
        ##If it finds a dominant source, accept it - counts as a spectral match
        if dom_source != 'none':
            jstat_resids, params, bses, chi_resids = mkl.calculate_resids(
                [accepted_matches[dom_source]])
            ##Find the probs of all the matches, and use the prob of the dom match to see what number match was accepted
            all_probs = [float(match.split()[-1]) for match in matches]
            accepted_prob = accepted_probs[dom_source]
            dom_num = all_probs.index(accepted_prob)

            i = plot_accept_type(comp, accepted_inds, match_crit,
                                 'Dom source (%d)' % (dom_num + 1),
                                 'Accept dom.\nsource', len(matches),
                                 plot_accept, src_all, 'spectral', i)

        ##If nothing dominates, send to check if a combined source works
        else:
            comb_crit, comb_source, comb_jstat, comb_chi_red = mkl.combine_flux(
                src_all, src_g, accepted_inds, 'plot=no', len(matches))
            ##See whether combined or split
            if 'split' in comb_crit:
                accept_type = 'split'
            else:
                accept_type = 'combine'
            ##Plot the combine or split, based on whether accepted or retained to investigate
            if 'Accepted' in comb_crit:
                i = plot_accept_type(comp, accepted_inds,
                                     match_crit, 'No dom. source', comb_crit,
                                     len(matches), plot_accept, src_all,
                                     accept_type, i)
            else:
                i = plot_accept_type(comp, accepted_inds,
                                     match_crit, 'No dom. source', comb_crit,
                                     len(matches), plot_eyeball, src_all,
                                     accept_type, i)
    return i
Example #11
0
def single_match_test(src_all,comp,accepted_matches,accepted_inds,g_stats,num_matches,repeated_cats,matches):
	'''Takes a combination of sources, one from each catalogue, with positional probabilities,
	and determines whether they are a match or not - Algorithm 2 in the write up'''
	match = accepted_matches[0]
	prob = float(match[-1])
	
	##calculate_resids needs a list of matches - calculate parameters
	jstat_resids,params,bses,chi_resids = mkl.calculate_resids([match])

	##Gather source information
	src_g = mkl.get_srcg(match)
	
	##Play the prob trick again to work out which match has been accepted
	match_probs = [float(m.split()[-1]) for m in matches]
	dom_num = match_probs.index(prob)+1
	match_crit = "Combination (%d)\npossible\n%s repeated cats" %(dom_num,repeated_cats)
	
	##Check to see if all matched sources are within the closeness test - create an
	##error ellipse by combined closeness with base cat error
	##Need to convert closeness in to an RA offset, due to spherical trigonometry
	dr=np.pi/180.0
	delta_RA = np.arccos((np.cos(closeness*dr)-np.sin(src_all.decs[0]*dr)**2)/np.cos(src_all.decs[0]*dr)**2)/dr
	
	##Make a list of the ras and decs of the sources to distance test
	ras_test = [ra for ra in src_g.ras if ra!=-100000.0]
	dec_test = [dec for dec in src_g.decs if dec!=-100000.0]
	
	small_test = []
	for ra,dec in zip(ras_test,dec_test):
		##Even though at same dec, 3arcmis offset in RA isn't neccessarily 3arcmins arcdistance 
		ra_dist = mkl.arcdist(src_all.ras[0],ra,src_all.decs[0],src_all.decs[0])
		dec_dist = src_all.decs[0] - dec
		ra_axis = src_all.rerrs[0] + abs(delta_RA)
		dec_axis = src_all.derrs[0] + closeness

		##Test to see if the source lies with an error ellipse created using semi-major
		##and minor axes defined by the ra and dec error of the base cat + half the resolution
		##of the base cat (closeness)
		ell_test = (ra_dist/ra_axis)**2 + (dec_dist/dec_axis)**2
		if ell_test <= 1:
			small_test.append('yes')
		else:
			##Otherwise, fails
			small_test.append('no')
			#no_names.append(repeat_name)  #Note the name of the sources that are far away
	
	#Fail the positional test if a source is outside of the resolution plus position error
	close_test = 'passed'
	if 'no' in small_test: close_test = 'failed'
	
	##If prob is higher than threshold, ignore position of sources and accept the match
	if prob>high_prob:
		##Accept the source, put it in a way that can be read when constructing the final table
		if chi_resids[0]<=2:
			make_entry(match,params[0][0],params[0][1],bses[0][0],bses[0][1],g_stats,'position',0,chi_resids[0])
		else:
			make_entry(match,params[0][0],params[0][1],bses[0][0],bses[0][1],g_stats,'position',1,chi_resids[0])
			
		make_accept(comp,g_stats,'position',accepted_inds)
	else:
		##look to see if all sources are within the resolution of the
		##base catalogue or above some probability theshold, if so check with a spec test else reject them
		if close_test=='passed' or prob>low_prob:  
			##IF below eith threshold, append with the applicable fit label
			if jstat_resids[0]<=jstat_thresh or chi_resids[0]<=chi_thresh:
				if chi_resids[0]<=2:
					make_entry(match,params[0][0],params[0][1],bses[0][0],bses[0][1],g_stats,'spectral',0,chi_resids[0])
				else:
					make_entry(match,params[0][0],params[0][1],bses[0][0],bses[0][1],g_stats,'spectral',1,chi_resids[0])
				make_accept(comp,g_stats,'spectral',accepted_inds)
			else:
				g_stats.retained_matches = 1
				##Put accepted inds as [0] just to have something outputted to the investigate text file - 
				##accepted_inds is empty is rejecting at this stage
				make_rejection(comp,g_stats,'spectral',[0])
		else:
			g_stats.retained_matches = 1
			make_rejection(comp,g_stats,'position',[0])
Example #12
0
		repeated_inds = [i for i in xrange(len(cats)) if cats.count(cats[i])>1]
		make_rejection(comp,g_stats,'position',repeated_inds)

	##If just one combo positionally possible, do a single combo check
	elif len(accepted_matches)==1:
		single_match_test(src_all,comp,accepted_matches,accepted_inds,g_stats,len(matches),repeated_cats,matches)
		
	##If more than one combination is positionally possible:
	else:
		##Check for a dominant source. The combination must be the only one with high position prob,
		##all others with low positional proability, and must dominate spectrally
		
		num_cat = len(set([cat for cat in src_all.cats if cat!='-100000.0']))
		
		dom_source = mkl.spec_pos_agree(jstats,chi_reds,accepted_probs,num_cat)
		src_g = mkl.get_srcg(accepted_matches[0])
		##If it finds a dominant source, accept it - counts as a spectral match 
		if dom_source!='none':
			jstat_resids,params,bses,chi_resids = mkl.calculate_resids([accepted_matches[dom_source]])
			if chi_resids[0]<=2:
				make_entry(accepted_matches[dom_source],params[0][0],params[0][1],bses[0][0],bses[0][1],g_stats,'spectral',0,chi_resids[0])
			else:
				make_entry(accepted_matches[dom_source],params[0][0],params[0][1],bses[0][0],bses[0][1],g_stats,'spectral',1,chi_resids[0])
			make_accept(comp,g_stats,'spectral',accepted_inds)
		##If nothing dominates, send to check if a combined source works
		else:
			comb_crit, comb_source, comb_jstat, comb_chi_red = mkl.combine_flux(src_all,src_g,accepted_inds,'plot=no',len(matches))
				
			if 'Accepted' in comb_crit:
				##If source was combined, add one new source with combine in the g_stat
				if len(comb_source)==1: