vector<DataPoint*> RapidFitIntegrator::getGSLIntegrationPoints( unsigned int number, vector<double> maxima, vector<double> minima, DataPoint* templateDataPoint, vector<string> doIntegrate, PhaseSpaceBoundary* thisBound )
{
	pthread_mutex_lock( &GSL_DATAPOINT_GET_THREADLOCK );

	bool pointsGood = true;
	if( !_global_doEval_points.empty() )
	{
		if( _global_doEval_points[0] != NULL )
		{
			vector<string> allConsts = thisBound->GetDiscreteNames();
			for( unsigned int i=0; i< allConsts.size(); ++i )
			{
				double haveVal = _global_doEval_points[0]->GetObservable( allConsts[i] )->GetValue();
				double wantVal = templateDataPoint->GetObservable( allConsts[i] )->GetValue();

				if( haveVal != wantVal )
				{
					pointsGood = false;
					break;
				}
			}
		}
	}

	if( ( number != _global_doEval_points.size() ) || (( ( _global_range_minima != minima ) || ( _global_range_maxima != maxima ) ) || !pointsGood ) )
	{
		clearGSLIntegrationPoints();
		_global_doEval_points = initGSLDataPoints( number, maxima, minima, templateDataPoint, doIntegrate );
		_global_range_minima = minima;
		_global_range_maxima = maxima;
		_global_observable_names = doIntegrate;
	}

	vector<string> allObs = _global_doEval_points[0]->GetAllNames();
	for( unsigned int i=0; i< _global_doEval_points.size(); ++i )
	{
		DataPoint* thisPoint = _global_doEval_points[i];
		for( unsigned int j=0; j< allObs.size(); ++j )
		{
			Observable* thisObs = thisPoint->GetObservable( j );
			thisObs->SetBinNumber( -1 );
			thisObs->SetBkgBinNumber( -1 );
		}
		thisPoint->ClearPerEventData();
	}

	pthread_mutex_unlock( &GSL_DATAPOINT_GET_THREADLOCK );
	return _global_doEval_points;
}
double Bd2JpsiKstar_sWave_Fs::angularFactor( )
{
	double returnValue=0.;

	int globalbin=-1;
	int xbin=-1, ybin=-1, zbin=-1;
	double num_entries_bin=-1.;

	//Observable* cos1Obs = cos1Obs = _datapoint->GetObservable( cosPsiName );
	Observable* cos1Obs = _datapoint->GetObservable( cosPsiName );

	if( cos1Obs->GetBkgBinNumber() != -1 )
	{
		return cos1Obs->GetBkgAcceptance();
	}
	else
	{
		Observable* cos2Obs = _datapoint->GetObservable( cosThetaName );
		Observable* phiObs = _datapoint->GetObservable( phiName );

		//Find global bin number for values of angles, find number of entries per bin, divide by volume per bin and normalise with total number of entries in the histogram
		xbin = xaxis->FindFixBin( cosPsi ); if( xbin > nxbins ) xbin = nxbins; if( xbin == 0 ) xbin = 1;
		ybin = yaxis->FindFixBin( cosTheta ); if( ybin > nybins ) ybin = nybins; if( ybin == 0 ) ybin = 1;
		zbin = zaxis->FindFixBin( phi ); if( zbin > nzbins ) zbin = nzbins; if( zbin == 0 ) zbin = 1;

		globalbin = histo->GetBin( xbin, ybin, zbin );
		num_entries_bin = (double)histo->GetBinContent(globalbin);

		//Angular factor normalized with phase space of histogram and total number of entries in the histogram
		returnValue = (double)num_entries_bin;// / (deltax * deltay * deltaz) / (double)total_num_entries;
		//returnValue = (double)num_entries_bin / histo->Integral();

		cos1Obs->SetBkgBinNumber( xbin ); cos1Obs->SetBkgAcceptance( returnValue );
		cos2Obs->SetBkgBinNumber( ybin ); cos2Obs->SetBkgAcceptance( returnValue );
		phiObs->SetBkgBinNumber( zbin ); phiObs->SetBkgAcceptance( returnValue );
	}

	return returnValue;
}
vector<DataPoint*> RapidFitIntegrator::initGSLDataPoints( unsigned int number, vector<double> maxima, vector<double> minima, DataPoint* templateDataPoint, vector<string> doIntegrate )
{
	vector<DataPoint*> doEval_points;
	pthread_mutex_lock( &GSL_DATAPOINT_MANAGEMENT_THREADLOCK );

#ifdef __RAPIDFIT_USE_GSL

	unsigned int nDim = (unsigned) minima.size();

	unsigned int npoint = number;
	vector<double> * integrationPoints = new vector<double>[ nDim ];

	//pthread_mutex_lock( &gsl_mutex );
	//cout << "Allocating GSL Integration Tool. nDim " << nDim << endl;
	gsl_qrng * q = NULL;
	try
	{
		//q = gsl_qrng_alloc( gsl_qrng_sobol, (unsigned)nDim );
		q = gsl_qrng_alloc( gsl_qrng_niederreiter_2, (unsigned)nDim );
	}
	catch(...)
	{
		cout << "Can't Allocate Integration Tool for GSL Integral." << endl;
		cout << " Dim: " << nDim << endl;
		exit(-742);
	}

	if( q == NULL )
	{
		cout << "Can't Allocate Integration Tool for GSL Integral." << endl;
		cout << " Dim: " << nDim << endl;
		exit(-741);
	}

	double* v = new double[ nDim ];
	for( unsigned int i = 0; i < npoint; i++)
	{
		gsl_qrng_get( q, v );
		for( unsigned int j = 0; j < nDim; j++)
		{
			integrationPoints[j].push_back( v[j] );
		}
	}
	delete v;
	gsl_qrng_free(q);
	//cout << "Freed GSL Integration Tool" << endl;
	//pthread_mutex_unlock( &gsl_mutex );

	/*vector<double> minima_v, maxima_v;
	  for( unsigned int i=0; i< nDim; ++i )
	  {
	  minima_v.push_back( minima[i] );
	  maxima_v.push_back( maxima[i] );
	  }*/
	//cout << "Constructing Functions" << endl;
	//IntegratorFunction* quickFunction = new IntegratorFunction( functionToWrap, NewDataPoint, doIntegrate, dontIntegrate, NewBoundary, componentIndex, minima_v, maxima_v );

	for (unsigned int i = 0; i < integrationPoints[0].size(); ++i)
	{
		double* point = new double[ nDim ];
		for ( unsigned int j = 0; j < nDim; j++)
		{
			//cout << doIntegrate[j] << " " << maxima[j] << " " << minima[j] << " " << integrationPoints[j][i] << endl;
			point[j] = integrationPoints[j][i]*(maxima[j]-minima[j])+minima[j];
		}

		DataPoint* thisPoint = new DataPoint( *templateDataPoint );

		thisPoint->ClearPerEventData();
		vector<string> allObs=thisPoint->GetAllNames();
		for( unsigned int j=0; j<allObs.size(); ++j )
		{
			Observable* thisObs = thisPoint->GetObservable( j );
			thisObs->SetBinNumber(-1);
			thisObs->SetBkgBinNumber(-1);
		}

		for( unsigned int k=0; k< doIntegrate.size(); ++k )
		{
			thisPoint->SetObservable( doIntegrate[k], point[k], "noUnitsHere" );
		}

		doEval_points.push_back( thisPoint );
		//result += quickFunction->DoEval( point );
		delete[] point;
	}

	delete[] integrationPoints;
#endif

	(void) maxima; (void) minima; (void) number;
	pthread_mutex_unlock( &GSL_DATAPOINT_MANAGEMENT_THREADLOCK );
	return doEval_points;
}