pmcsqs.cpp

来自「MS-Clustering is designed to rapidly clu」· C++ 代码 · 共 1,870 行 · 第 1/4 页

CPP
1,870
字号
#include "PMCSQS.h"
#include "auxfun.h"


void PMCSQS_Scorer::set_sqs_mass_thresholds()
{
	sqs_mass_thresholds.clear();
	sqs_mass_thresholds.push_back(800);
	sqs_mass_thresholds.push_back(1200);
}


void PMCSQS_Scorer::set_default_sqs_correct_factors()
{
	sqs_correction_factors.resize(4);
	sqs_mult_factors.resize(4);

	sqs_correction_factors[1].push_back(0);
	sqs_correction_factors[1].push_back(-0.1);
	sqs_correction_factors[1].push_back(-0.15);

	sqs_correction_factors[2].push_back(0);
	sqs_correction_factors[2].push_back(0.05);
	sqs_correction_factors[2].push_back(0.05);

	sqs_correction_factors[2].push_back(0);
	sqs_correction_factors[2].push_back(0.05);
	sqs_correction_factors[2].push_back(0.05);

	int i;
	for (i=0; i<4; i++)
	{
		int j;
		for (j=0; j<sqs_correction_factors.size(); j++)
			sqs_mult_factors[i].push_back(1.0/(1.0+sqs_correction_factors[i][j]));
	}
}


void PMCSQS_Scorer::init_sqs_correct_factors(int max_charge, int num_sizes)
{
	sqs_correction_factors.resize(max_charge+max_charge);
	sqs_mult_factors.resize(max_charge+1);

	int i;
	for (i=1; i<=max_charge; i++)
	{
		sqs_correction_factors[i].clear();
		sqs_correction_factors[i].resize(num_sizes,0);
		sqs_mult_factors[i].clear();
		sqs_mult_factors[i].resize(num_sizes,1);
	}
}





/***************************************************************************
Gives detailed m/z and prob values for the different charges.
Returns the highest sqs probability found for a spectrum.
****************************************************************************/
float PMCSQS_Scorer::get_pmcsqs_results_for_spectrum(Config *config, 
													 const BasicSpectrum& bs,
													 vector<PmcSqsChargeRes>& res)
{
	static ME_Regression_Sample sqs_sam;

	if (! init_for_current_spec(config,bs))
		return 0; // corrupt file

	calculate_curr_spec_pmc_values(bs,bin_increment);

	const int num_charges = pmc_rank_models.size();
	const int sqs_size_idx = this->get_sqs_size_idx(bs.ssf->m_over_z);

	if (res.size()<num_charges)
		res.resize(num_charges);

	
	vector<float> min_comp_probs;		// the minimal probability when used in a comparison model
	min_comp_probs.resize(num_charges,1.0);
	min_comp_probs[0]=0;

	if (ind_initialized_sqs)
	{
		fill_fval_vector_with_SQS(bs, sqs_sam);
	
		int charge;
		for (charge=1; charge<num_charges; charge++)
		{
			
			float prob = sqs_models[charge][0][sqs_size_idx]->p_y_given_x(0,sqs_sam);

			// correct prob
			prob += sqs_correction_factors[charge][sqs_size_idx];
			prob *= sqs_mult_factors[charge][sqs_size_idx];
			if (prob<0.0)
				prob=0.0;

			res[charge].sqs_prob=prob;
		}
		
		int c;
		for (c=1; c<num_charges-1; c++)
		{
			float comp_prob = 2.0;
			int d;
			for (d=c+1; d<num_charges; d++)
			{
				if (! sqs_models[d][c][sqs_size_idx])
					continue;

				comp_prob=sqs_models[d][c][sqs_size_idx]->p_y_given_x(0,sqs_sam);

				if (comp_prob<min_comp_probs[d])
					min_comp_probs[d]=comp_prob;

				const float one_minus_prob = 1.0-comp_prob;
				if (one_minus_prob<min_comp_probs[c])
					min_comp_probs[c]=one_minus_prob;
			}
		}	
	}
	else // give the max prob charge to the input charge, the rest get 0
	{
		if (bs.ssf->charge<=0)
		{
			cout << "Error: no SQS model was read, so charge must be supplied in the spectrum!" << endl;
			exit(1);
		}

		int c;
		for (c=1; c<num_charges; c++)
			if (c != bs.ssf->charge)
				min_comp_probs[c]=0;
	}

	int charge;
	for (charge=0; charge<min_comp_probs.size(); charge++)
	{
	//	if (min_comp_probs[charge]>1.5)
	//		min_comp_probs[charge]=0;
//		cout << charge << "\t" << min_comp_probs[c] << endl;
	}


	float max_prob=0;
	for (charge=1; charge<num_charges; charge++)
	{
		

		const float prob = min_comp_probs[charge];
		if (prob>max_prob)
			max_prob=prob;

		res[charge].min_comp_prob = prob;

		if (prob>0.02)
		{
			find_best_mz_values_from_rank_model(bs,charge,res[charge]);
		}
		else // only give one guess, the second one will come from another charge
		{
			res[charge].mz1=bs.ssf->m_over_z;
			res[charge].score1=0;
			res[charge].mz2=NEG_INF;
			res[charge].score2=NEG_INF;
		}
	}
	

	return max_prob;
}


/********************************************************************
Computes the best sqs value for the spectrum. It is faster than the charge
m/z function since it only looks at a few mass positions. 
*********************************************************************
float PMCSQS_Scorer::get_sqs_for_spectrum(Config *config, 
										  const BasicSpectrum& bs, 
										  int *max_charge,
										  bool verbose)
{
	static vector<PmcSqsChargeRes> res;

	if (! this->ind_initialized_pmcr)
	{
		cout << "Error: no PMC model was read!" << endl;
		if (bs.ssf->charge <=0)
			cout << "Spectrum was read with charge <=0, so charge selection is needed!" << endl;
		exit(1);
	}

	get_pmcsqs_results_for_spectrum(config,bs,res);

	float best_prob=-1;
	int best_charge=0;

	int charge;
	for (charge =1; charge<=max_model_charge; charge++)
		if (res[charge].min_comp_prob>best_prob)
		{
			best_charge = charge;
			best_prob = res[charge].min_comp_prob;
		}

	if (max_charge)
		*max_charge = best_charge;

	return best_prob;
}*/

/********************************************************************
Computes the best sqs value for the spectrum. It is faster than the charge
m/z function since it only looks at a few mass positions. 
*********************************************************************/
float PMCSQS_Scorer::get_sqs_for_spectrum(Config *config, 
										  const BasicSpectrum& bs, 
										  int *max_charge,
										  bool verbose)
{
	static ME_Regression_Sample sqs_sam;
	static vector<QCPeak> sqs_peaks;
	static int num_sqs_peaks = 0;
	BasicSpectrum sqs_bs;

	if (verbose)
	{
		cout << "ORG spectrum: " << bs.num_peaks << endl;
//		bs.print_peaks();
		cout << endl;
	}

	if (num_sqs_peaks< 2000 || num_sqs_peaks<bs.num_peaks)
	{
		num_sqs_peaks = (int)(bs.num_peaks * 1.5);
		if (num_sqs_peaks<2000)
			num_sqs_peaks = 2000;
		
		if (num_sqs_peaks>100000)
		{
			cout << "Error: too many peak in spectrum: " << bs.num_peaks << endl;
			exit(1);
		}
		sqs_peaks.resize(num_sqs_peaks);
	}

	sqs_bs.peaks = &sqs_peaks[0];
	sqs_bs.ssf = bs.ssf;

	int best_charge=0;

	// filter peaks to acheive the required peak density for the models

	int new_num_peaks =0;
	create_filtered_peak_list_for_sqs(bs.peaks,bs.num_peaks,sqs_bs.peaks,new_num_peaks);
	sqs_bs.num_peaks= new_num_peaks;

	if (verbose)
	{
		cout << "ATER FILTERING: " << new_num_peaks << endl;
//		sqs_bs.print_peaks();
		cout << endl;
	}

	if (! init_for_current_spec(config,sqs_bs))
		return 0; // corrupt spectrum

	calculate_curr_spec_pmc_values(sqs_bs,bin_increment*3);

	const int num_charges = pmc_rank_models.size();
	const int sqs_size_idx = this->get_sqs_size_idx(sqs_bs.ssf->m_over_z);

	float max_prob=-1;
	
	fill_fval_vector_with_SQS(sqs_bs, sqs_sam);
	
	int charge;
	for (charge=1; charge<num_charges; charge++)
	{
			
		float prob = sqs_models[charge][0][sqs_size_idx]->p_y_given_x(0,sqs_sam);

		// correct prob
		prob += sqs_correction_factors[charge][sqs_size_idx];
		prob *= sqs_mult_factors[charge][sqs_size_idx];
		if (prob<0.0)
			prob=0.0;

		if (prob>max_prob)
		{
			max_prob=prob;
			best_charge=charge;
		}
	}

	if (max_charge)
		*max_charge = best_charge;

	return max_prob;
}



/******************************************************************************
Selects the the two best values of charges 1,2,3
returns the max prob found
*******************************************************************************/
float PMCSQS_Scorer::get_best_mz_charge(Config *config, const BasicSpectrum& bs, 
						   mass_t* mz1, int* charge1, float *prob1,
						   mass_t* mz2, int* charge2, float *prob2,
						   vector<PmcSqsChargeRes>* all_res)
{
	static vector<PmcSqsChargeRes> res;

	if (! this->ind_initialized_pmcr)
	{
		cout << "Error: no PMC model was read!" << endl;
		if (bs.ssf->charge <=0)
			cout << "Spectrum was read with charge <=0, so charge selection is needed!" << endl;
		exit(1);
	}

	get_pmcsqs_results_for_spectrum(config,bs,res);

	float best_prob=-1;
	int best_charge=0;

	int charge;
	for (charge =1; charge<=max_model_charge; charge++)
		if (res[charge].min_comp_prob>best_prob)
		{
			best_charge = charge;
			best_prob = res[charge].min_comp_prob;
		}

	const PmcSqsChargeRes& cr = res[best_charge];
	float second_best_prob=1.0 - (cr.score1-cr.score2)/(fabs(cr.score1)+fabs(cr.score2)+2.0);
	int   second_best_charge = best_charge;
	
	for (charge =1; charge<=max_model_charge; charge++)
		if (charge != best_charge && res[charge].min_comp_prob>second_best_prob)
		{
			second_best_charge = charge;
			second_best_prob = res[charge].min_comp_prob;
		}

	*mz1 = (mass_t)res[best_charge].mz1;
	*charge1 = best_charge;
	*prob1 = best_prob;

	if (mz2 && charge2)
	{
		*charge2 = second_best_charge;
		*prob2   = second_best_prob;
		if (second_best_charge == best_charge)
		{
			*mz2 = (mass_t)res[best_charge].mz2;
		}
		else
			*mz2 = (mass_t)res[second_best_charge].mz1;
	}

	if (all_res)
		*all_res = res;

	return best_prob;
}



/********************************************************************
Select a set of mzs nd charges that have high probabilities.
If add_one_Da_offsets is set, add -1,-2,+1,+2 mzs (if there are many
mzs, not all these offfsets will be added)
Uses emprically set probability threhsolds to chose corrected pms.
*********************************************************************/
void PMCSQS_Scorer::select_pms_and_charges(Config *config, 
								const BasicSpectrum& bs,
								vector<mass_t>& pms_with_19,
								vector<int>&    charges,
								bool	add_one_Da_offsets,
								vector<PmcSqsChargeRes>* all_res)
{
	static const mass_t offsets[]={-MASS_PROTON,MASS_PROTON};
	static const int num_all_offsets = sizeof(offsets)/sizeof(mass_t);
	static const float min_comp_prob_for_adding_second = 0.04;
	static const float min_sqs_prob_for_adding_second = 0.05;

	const int spec_charge = bs.ssf->charge;
	const mass_t spec_mz = bs.ssf->m_over_z;
	const mass_t half_tol = config->get_tolerance() * 0.5;

	pms_with_19.clear();
	charges.clear();
	int    specific_charge=0;
	mass_t specific_mz=0;
	

	if (config->get_use_spectrum_charge())
		specific_charge=spec_charge;

	static vector<PmcSqsChargeRes> res;
	int max_charge=0;
	float max_prob = 0;
	if (config->get_use_spectrum_charge() && (config->get_use_spectrum_mz() || config->get_pm_tolerance()<0.1))
	{
		pms_with_19.push_back(spec_mz * spec_charge - (spec_charge-1)*MASS_PROTON);
		charges.push_back(spec_charge);
		max_charge=spec_charge;
	}
	else
	{
		if (! this->ind_initialized_pmcr)
		{
			cout << "Error: no PMC model was read!" << endl;
			if (bs.ssf->charge <=0)
				cout << "Spectrum was read with charge <=0, so charge selection is needed!" << endl;
			exit(1);
		}

		get_pmcsqs_results_for_spectrum(config,bs,res);

		if (specific_charge>0)
		{
			max_charge = spec_charge;
			max_prob = res[spec_charge].min_comp_prob;
		}
		else
		{
			int c;
			for (c=1; c<res.size(); c++)
			{
				if (res[c].min_comp_prob>max_prob)
				{
					max_prob = res[c].min_comp_prob;
					max_charge = c;
				}
			}
		}

		pms_with_19.push_back(res[max_charge].mz1 * max_charge - (max_charge-1)*MASS_PROTON);
		charges.push_back(max_charge);
		if (res[max_charge].mz2>0)
		{
			pms_with_19.push_back(res[max_charge].mz2 * max_charge - (max_charge-1)*MASS_PROTON);
			charges.push_back(max_charge);
		}

	}

	


	// only added to the first pm_with_19, check that it doesn't overlap with others
	if (add_one_Da_offsets)
	{
		int num_offsets = num_all_offsets;
		int i;
		for (i=0; i<num_offsets; i++)
		{
			const mass_t pm_with_19 = pms_with_19[0] + offsets[i];
			int j;
			for (j=0; j<pms_with_19.size(); j++)
				if (charges[j]==max_charge && fabs(pm_with_19 - pms_with_19[j])<half_tol)
					break;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?