Esempio n. 1
0
void quadratic_fit(void) {

	int i, n;
	double xi, yi, ei, chisq;
	gsl_matrix *X, *cov;
	gsl_vector *y, *w, *c;

	n = 7;
	double x_vec[] = { 0, 100, 200, 300, 400, 500, 600 };
	double y_vec[] = { 0, 12.5, 50.0, 112.5, 200.0, 312.5, 450.0 };
	double e_vec[] = { 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 };

	X = gsl_matrix_alloc(n, 3);
	y = gsl_vector_alloc(n);
	w = gsl_vector_alloc(n);

	c = gsl_vector_alloc(3);
	cov = gsl_matrix_alloc(3, 3);

	for (i = 0; i < n; i++) {
		xi = x_vec[i];
		yi = y_vec[i];
		ei = e_vec[i];

		printf("%g %g +/- %g\n", xi, yi, ei);

		gsl_matrix_set(X, i, 0, 1.0);
		gsl_matrix_set(X, i, 1, xi);
		gsl_matrix_set(X, i, 2, xi * xi);

		gsl_vector_set(y, i, yi);
		gsl_vector_set(w, i, 1.0 / (ei * ei));
	}

	{
		gsl_multifit_linear_workspace * work = gsl_multifit_linear_alloc(n, 3);
		gsl_multifit_wlinear(X, w, y, c, cov, &chisq, work);
		gsl_multifit_linear_free(work);
	}

#define C(i) (gsl_vector_get(c,(i)))
#define COV(i,j) (gsl_matrix_get(cov,(i),(j)))

	{
		printf("# best fit: Y = %g + %g X + %g X^2\n", C(0), C(1), C(2));

		printf("# covariance matrix:\n");
		printf("[ %+.5e, %+.5e, %+.5e  \n", COV(0,0), COV(0,1), COV(0,2));
		printf("  %+.5e, %+.5e, %+.5e  \n", COV(1,0), COV(1,1), COV(1,2));
		printf("  %+.5e, %+.5e, %+.5e ]\n", COV(2,0), COV(2,1), COV(2,2));
		printf("# chisq = %g\n", chisq);
	}

	gsl_matrix_free(X);
	gsl_vector_free(y);
	gsl_vector_free(w);
	gsl_vector_free(c);
	gsl_matrix_free(cov);
}
Esempio n. 2
0
TGraphErrors *getUnc(TMatrixDSym COV, TF1 *fit, TH1F *h)
{
  int N = COV.GetNrows();
  float vx[200],vy[200],vex[200],vey[200];
  float dx = (h->GetBinLowEdge(h->GetNbinsX())+h->GetBinWidth(1)-h->GetBinLowEdge(1))/200;
  for(int b=0;b<200;b++) {
    vx[b]  = h->GetBinLowEdge(1)+b*dx;
    vy[b]  = fit->Eval(vx[b]);
    vex[b] = 0.0;
    float sum(0.0);
    for(int i=0;i<N;i++) {
      for(int j=0;j<N;j++) {
        sum += pow(vx[b],i)*pow(vx[b],j)*COV(i,j);
      }
    }
    vey[b] = sqrt(sum);
  }  
  TGraphErrors *g = new TGraphErrors(200,vx,vy,vex,vey);
  return g;
}
Esempio n. 3
0
int
main (int argc, char **argv)
{
  int i, n;
  double xi, yi, ei, chisq;
  gsl_matrix *X, *cov;
  gsl_vector *y, *w, *c;

  if (argc != 2)
    {
      fprintf (stderr,"usage: fit n < data\n");
      exit (-1);
    }

  n = atoi (argv[1]);

  X = gsl_matrix_alloc (n, 3);
  y = gsl_vector_alloc (n);
  w = gsl_vector_alloc (n);

  c = gsl_vector_alloc (3);
  cov = gsl_matrix_alloc (3, 3);

  for (i = 0; i < n; i++)
    {
      int count = fscanf (stdin, "%lg %lg %lg",
                          &xi, &yi, &ei);

      if (count != 3)
        {
          fprintf (stderr, "error reading file\n");
          exit (-1);
        }

      printf ("%g %g +/- %g\n", xi, yi, ei);
      
      gsl_matrix_set (X, i, 0, 1.0);
      gsl_matrix_set (X, i, 1, xi);
      gsl_matrix_set (X, i, 2, xi*xi);
      
      gsl_vector_set (y, i, yi);
      gsl_vector_set (w, i, 1.0/(ei*ei));
    }

  {
    gsl_multifit_linear_workspace * work 
      = gsl_multifit_linear_alloc (n, 3);
    gsl_multifit_wlinear (X, w, y, c, cov,
                          &chisq, work);
    gsl_multifit_linear_free (work);
  }

#define C(i) (gsl_vector_get(c,(i)))
#define COV(i,j) (gsl_matrix_get(cov,(i),(j)))

  {
    printf ("# best fit: Y = %g + %g X + %g X^2\n", 
            C(0), C(1), C(2));

    printf ("# covariance matrix:\n");
    printf ("[ %+.5e, %+.5e, %+.5e  \n",
               COV(0,0), COV(0,1), COV(0,2));
    printf ("  %+.5e, %+.5e, %+.5e  \n", 
               COV(1,0), COV(1,1), COV(1,2));
    printf ("  %+.5e, %+.5e, %+.5e ]\n", 
               COV(2,0), COV(2,1), COV(2,2));
    printf ("# chisq = %g\n", chisq);
  }

  gsl_matrix_free (X);
  gsl_vector_free (y);
  gsl_vector_free (w);
  gsl_vector_free (c);
  gsl_matrix_free (cov);

  return 0;
}
int main(int argc, char **argv) {
	int i;
	size_t n;
	const size_t p = 2; /* linear fit */
	gsl_matrix *X, *cov;

	gsl_vector *x, *y, *c, *c_ols;
	const double a = 1.48; /* slope */
	const double b = 3.88; /* intercept */
	gsl_rng *r;

	if (argc != 2) {
		fprintf(stderr, "usage: robfit n\n");
		exit(-1);
	}

	n = atoi(argv[1]);

	X = gsl_matrix_alloc(n, p);
	x = gsl_vector_alloc(n);
	y = gsl_vector_alloc(n);

	c = gsl_vector_alloc(p);
	c_ols = gsl_vector_alloc(p);
	cov = gsl_matrix_alloc(p, p);

	r = gsl_rng_alloc(gsl_rng_default);

	/* generate linear dataset */
	for (i = 0; i < n - 3; i++) {
		double dx = 10.0 / (n - 1.0);
		double ei = gsl_rng_uniform(r);
		double xi = -5.0 + i * dx;
		double yi = a * xi + b;
		gsl_vector_set(x, i, xi);
		gsl_vector_set(y, i, yi + ei);
	}

	/* add a few outliers */
	gsl_vector_set(x, n - 3, 4.7);
	gsl_vector_set(y, n - 3, -8.3);

	gsl_vector_set(x, n - 2, 3.5);
	gsl_vector_set(y, n - 2, -6.7);

	gsl_vector_set(x, n - 1, 4.1);
	gsl_vector_set(y, n - 1, -6.0);

	/* construct design matrix X for linear fit */
	for (i = 0; i < n; ++i) {
		double xi = gsl_vector_get(x, i);

		gsl_matrix_set(X, i, 0, 1.0);
		gsl_matrix_set(X, i, 1, xi);
	}

	/* perform robust and OLS fit */
	dofit(gsl_multifit_robust_ols, X, y, c_ols, cov);
	dofit(gsl_multifit_robust_bisquare, X, y, c, cov);

	/* output data and model */
	for (i = 0; i < n; ++i) {
		double xi = gsl_vector_get(x, i);
		double yi = gsl_vector_get(y, i);
		gsl_vector_view v = gsl_matrix_row(X, i);
		double y_ols, y_rob, y_err;

		gsl_multifit_robust_est(&v.vector, c, cov, &y_rob, &y_err);
		gsl_multifit_robust_est(&v.vector, c_ols, cov, &y_ols, &y_err);

		printf("%g %g %g %g\n", xi, yi, y_rob, y_ols);
	}

#define C(i) (gsl_vector_get(c,(i)))
#define COV(i,j) (gsl_matrix_get(cov,(i),(j)))

	{
		printf("# best fit: Y = %g + %g X\n", C(0), C(1));

		printf("# covariance matrix:\n");
		printf("# [ %+.5e, %+.5e\n", COV(0, 0), COV(0, 1));
		printf("#%+.5e, %+.5e\n", COV(1, 0), COV(1, 1));
	}

	gsl_matrix_free(X);
	gsl_vector_free(x);
	gsl_vector_free(y);
	gsl_vector_free(c);
	gsl_vector_free(c_ols);
	gsl_matrix_free(cov);
	gsl_rng_free(r);

	return 0;
}
Esempio n. 5
0
QFFitAlgorithm::FitResult QFFitAlgorithmLMFit::intFit(double* paramsOut, double* paramErrorsOut, const double* initialParams, QFFitAlgorithm::Functor* model, const double* paramsMin, const double* paramsMax) {
    QFFitAlgorithm::FitResult result;

    qDebug()<<"QFFitAlgorithmLMFit::intFit  1";

    int paramCount=model->get_paramcount(); // number of parameters
    memcpy(paramsOut, initialParams, paramCount*sizeof(double));

    qDebug()<<"QFFitAlgorithmLMFit::intFit  2";
    //double param=getParameter("param_name").toDouble();


    lm_status_struct status;
    lm_control_struct control = lm_control_double;
    control.verbosity = 0; // monitor status (+1) and parameters (+2)
    control.ftol=getParameter("ftol").toDouble();
    control.xtol=getParameter("xtol").toDouble();
    control.gtol=getParameter("gtol").toDouble();
    control.epsilon=getParameter("epsilon").toDouble();
    control.stepbound=getParameter("stepbound").toDouble();
    control.patience=getParameter("max_iterations").toInt();
    qDebug()<<"QFFitAlgorithmLMFit::intFit  3";

    QFFItAlgorithmGSL_evalData d;
    d.model=model;
    d.paramsMin=paramsMin;
    d.paramsMax=paramsMax;
    d.pcount=paramCount;
    d.p=(double*)qfMalloc(paramCount*sizeof(double));
    qDebug()<<"QFFitAlgorithmLMFit::intFit  4";

    lmmin( paramCount, paramsOut, model->get_evalout(), &d, lmfit_eval, &control, &status );
    qDebug()<<"QFFitAlgorithmLMFit::intFit  5";

    if ( paramsMin && paramsMax) {
        for (int i=0; i<paramCount; i++) {
            const double& par=paramsOut[i];
            if (par>paramsMax[i]) paramsOut[i]=paramsMax[i];
            if (par<paramsMin[i]) paramsOut[i]=paramsMin[i];
        }
    }

    result.addNumber("error_sum", status.fnorm);
    result.addNumber("iterations", status.nfev);
    qDebug()<<"QFFitAlgorithmLMFit::intFit  6";

    QVector<double> J(model->get_evalout()*model->get_paramcount());
    QVector<double> COV(model->get_paramcount()*model->get_paramcount());
    qDebug()<<"QFFitAlgorithmLMFit::intFit  7";
    model->evaluateJacobian(J.data(), paramsOut);
    qDebug()<<"QFFitAlgorithmLMFit::intFit  8";
    double chi2=status.fnorm;
    qDebug()<<"QFFitAlgorithmLMFit::intFit  9";
    if (QFFitAlgorithm::functorHasWeights(model) && !QFFitAlgorithm::functorAllWeightsOne(model)) statisticsGetFitProblemCovMatrix(COV.data(), J.data(), model->get_evalout(), model->get_paramcount());
    else statisticsGetFitProblemVarCovMatrix(COV.data(), J.data(), model->get_evalout(), model->get_paramcount(), chi2);
    qDebug()<<"QFFitAlgorithmLMFit::intFit  10";

    result.addNumberMatrix("covariance_matrix", COV.data(), model->get_paramcount(), model->get_paramcount());
    qDebug()<<"QFFitAlgorithmLMFit::intFit  11";

    for (int i=0; i<model->get_paramcount(); i++) {
        qDebug()<<"QFFitAlgorithmLMFit::intFit  12: "<<i;

        paramErrorsOut[i]=statisticsGetFitProblemParamErrors(i, COV.data(), model->get_paramcount());
    }
    qDebug()<<"QFFitAlgorithmLMFit::intFit  13";

    if (status.outcome>=0) {
        result.fitOK=QString(lm_infmsg[status.outcome]).contains("success") || QString(lm_infmsg[status.outcome]).contains("converged");
        result.message=QString(lm_infmsg[status.outcome]);
        result.messageSimple=QString(lm_infmsg[status.outcome]);
    } else {
        result.fitOK=true;
        result.message="";
        result.messageSimple="";
    }
    qDebug()<<"QFFitAlgorithmLMFit::intFit  14";

    if (d.p) qfFree(d.p);
    qDebug()<<"QFFitAlgorithmLMFit::intFit  15 ... DONE";

    return result;
}
QFFitAlgorithm::FitResult QFFitAlgorithmGSLSimplex::intFit(double* paramsOut, double* paramErrorsOut, const double* initialParams, QFFitAlgorithm::Functor* model, const double* paramsMin, const double* paramsMax) {
    QFFitAlgorithm::FitResult result;

    int paramCount=model->get_paramcount(); // number of parameters


    if (paramCount<=0) {
        result.fitOK=false;
        result.message=QObject::tr("no parameters to optimize");
        result.messageSimple=result.message;
        return result;
    }
    QFFItAlgorithmGSL_evalData d;
    d.model=model;
    d.paramsMin=paramsMin;
    d.paramsMax=paramsMax;
    d.pcount=paramCount;
    d.out=gsl_vector_alloc(model->get_evalout());
    d.out_ast=gsl_vector_alloc(model->get_evalout());
    d.params=gsl_vector_alloc(paramCount);
    d.params_ast=gsl_vector_alloc(paramCount);

    int iter = 0;
    int maxIter = getParameter("max_iterations").toInt();
    int status;

    //const gsl_multimin_fdfminimizer_type *T;
    //gsl_multimin_fdfminimizer *s;

    gsl_multimin_fminimizer *s;

    // set starting value to initial parameters
    gsl_vector *x=QFFitAlgorithmGSL_transformParams(initialParams, paramCount, paramsMin, paramsMax);

    //gsl_multimin_function_fdf my_func;
    gsl_multimin_function my_func;
    my_func.n = paramCount;
    my_func.f = QFFitAlgorithmGSL_f;
    //my_func.df = QFFitAlgorithmGSL_df;
    //my_func.fdf = QFFitAlgorithmGSL_fdf;
    my_func.params = &d;


    // initialize minimizer

    //s = gsl_multimin_fdfminimizer_alloc (T, paramCount);
    s = gsl_multimin_fminimizer_alloc (T, paramCount);

    /* Set initial step sizes to 1 */
    gsl_vector *ss = gsl_vector_alloc(paramCount);
    gsl_vector_set_all (ss, getParameter("stepsize").toDouble());


    //gsl_multimin_fdfminimizer_set(s, &my_func, x, getParameter("stepsize").toDouble(), getParameter("tol").toDouble());
    gsl_multimin_fminimizer_set(s, &my_func, x, ss);

    do {
        iter++;
        //status = gsl_multimin_fdfminimizer_iterate (s);
        status = gsl_multimin_fminimizer_iterate (s);
        //qDebug()<<"it "<<iter<<": "<<arrayToString(gsl_vector_ptr(s->x, 0), paramCount);
        //qDebug()<<"       f = "<<s->fval;
        //qDebug()<<"       status = "<<status;

        if (status) break;

        //status = gsl_multimin_test_gradient (s->gradient, 1e-3);
        double size = gsl_multimin_fminimizer_size (s);
        status = gsl_multimin_test_size (size, 1e-2);

        //if (status == GSL_SUCCESS) qDebug()<<"       Minimum found !!!";



    } while (status == GSL_CONTINUE && iter < maxIter);


    /*for (int i=0; i<paramCount; i++) {
        const double par=gsl_vector_get(s->x, i);
        paramsOut[i]=par;
        if (par>paramsMax[i]) paramsOut[i]=paramsMax[i];
        if (par<paramsMin[i]) paramsOut[i]=paramsMin[i];
    }*/
    QFFitAlgorithmGSL_backTransformParams(paramsOut, paramCount, s->x, paramsMin, paramsMax);

    QVector<double> J(model->get_evalout()*model->get_paramcount());
    QVector<double> COV(model->get_paramcount()*model->get_paramcount());
    model->evaluateJacobian(J.data(), paramsOut);
    double chi2=s->fval;
    if (QFFitAlgorithm::functorHasWeights(model) && !QFFitAlgorithm::functorAllWeightsOne(model)) statisticsGetFitProblemCovMatrix(COV.data(), J.data(), model->get_evalout(), model->get_paramcount());
    else statisticsGetFitProblemVarCovMatrix(COV.data(), J.data(), model->get_evalout(), model->get_paramcount(), chi2);

    result.addNumberMatrix("covariance_matrix", COV.data(), model->get_paramcount(), model->get_paramcount());

    for (int i=0; i<model->get_paramcount(); i++) {
        paramErrorsOut[i]=statisticsGetFitProblemParamErrors(i, COV.data(), model->get_paramcount());
    }


    result.addNumber("error_sum", s->fval);
    result.addNumber("iterations", iter);

    result.fitOK=false;
    result.message=QObject::tr("error during optimization");
    result.messageSimple=result.message;
    if (status == GSL_SUCCESS) {
        result.fitOK=true;
        result.message=QObject::tr("success after %1 iterations").arg(iter);
        result.messageSimple=result.message;
    } else if (status == GSL_ENOPROG) {
        result.fitOK=true;
        result.message=QObject::tr("no more optimization progress after %1 iterations").arg(iter);
        result.messageSimple=result.message;
    }



    //gsl_multimin_fdfminimizer_free (s);
    gsl_multimin_fminimizer_free (s);
    gsl_vector_free (x);
    gsl_vector_free(d.params);
    gsl_vector_free(d.params_ast);
    gsl_vector_free(d.out);
    gsl_vector_free(d.out_ast);

    return result;
}
Esempio n. 7
0
std::vector<float> compute_ec_features( USImageType::Pointer input_image,  USImageType::Pointer inp_labeled, int number_of_rois, unsigned short thresh, int surr_dist, int inside_dist ){

	std::vector< float > qfied_num;
	std::vector< USImageType::PixelType > labelsList;
	std::vector< double > quantified_numbers_cell;

	typedef itk::ExtractImageFilter< USImageType, UShortImageType > LabelExtractType;
	typedef itk::ImageRegionConstIterator< UShortImageType > ConstIteratorType;
	typedef itk::ImageRegionIteratorWithIndex< USImageType > IteratorType;
	typedef itk::SignedDanielssonDistanceMapImageFilter<FloatImageType, FloatImageType > DTFilter;
	typedef itk::ImageRegionIteratorWithIndex< FloatImageType > IteratorTypeFloat;
	typedef itk::LabelGeometryImageFilter< USImageType > GeometryFilterType;
	typedef GeometryFilterType::LabelIndicesType labelindicestype;

	itk::SizeValueType sz_x, sz_y, sz_z;
	sz_x = input_image->GetLargestPossibleRegion().GetSize()[0];
	sz_y = input_image->GetLargestPossibleRegion().GetSize()[1];
	sz_z = input_image->GetLargestPossibleRegion().GetSize()[2];

	if( sz_x==1 || sz_y==1 || sz_z==1 ){
		LabelExtractType::Pointer deFilter = LabelExtractType::New();
		USImageType::RegionType dRegion = inp_labeled->GetLargestPossibleRegion();
		dRegion.SetSize(2,0);
		deFilter->SetExtractionRegion(dRegion);
		deFilter->SetInput( inp_labeled );
		deFilter->SetDirectionCollapseToIdentity();
		try{
			deFilter->Update();
		}
		catch( itk::ExceptionObject & excep ){
			std::cerr << "Exception caught !" << std::endl;
			std::cerr << excep << std::endl;
		}
		//Dialate input first
		WholeCellSeg *dialate_filter = new WholeCellSeg;
		dialate_filter->set_nuc_img( deFilter->GetOutput() );
		dialate_filter->set_radius( surr_dist );
		dialate_filter->RunSegmentation();
		UShortImageType::Pointer input_lab = dialate_filter->getSegPointer();

		USImageType::Pointer input_labeled = USImageType::New();
		USImageType::PointType origint;
		origint[0] = 0;
		origint[1] = 0;
		origint[2] = 0;
		input_labeled->SetOrigin( origint );
		USImageType::IndexType startt;
		startt[0] = 0;  // first index on X
		startt[1] = 0;  // first index on Y
		startt[2] = 0;  // first index on Z
		USImageType::SizeType  sizet;
		sizet[0] = inp_labeled->GetLargestPossibleRegion().GetSize()[0];  // size along X
		sizet[1] = inp_labeled->GetLargestPossibleRegion().GetSize()[1];  // size along Y
		sizet[2] = inp_labeled->GetLargestPossibleRegion().GetSize()[2];  // size along Z
		USImageType::RegionType regiont;
		regiont.SetSize( sizet );
		regiont.SetIndex( startt );
		input_labeled->SetRegions( regiont );
		input_labeled->Allocate();
		input_labeled->FillBuffer(0);
		input_labeled->Update();

		ConstIteratorType pix_buf1( input_lab, input_lab->GetRequestedRegion() );
		IteratorType iterator2 ( input_labeled, input_labeled->GetRequestedRegion() );
		iterator2.GoToBegin();
		for ( pix_buf1.GoToBegin(); !pix_buf1.IsAtEnd(); ++pix_buf1 ){
			iterator2.Set( pix_buf1.Get() );
			++iterator2;
		}

		std::vector< float > quantified_numbers;

		typedef itk::LabelGeometryImageFilter< USImageType > GeometryFilterType;
		typedef GeometryFilterType::LabelIndicesType labelindicestype;

		GeometryFilterType::Pointer geomfilt1 = GeometryFilterType::New();

		geomfilt1->SetInput( input_labeled );
		geomfilt1->SetCalculatePixelIndices( true );
		geomfilt1->Update();
		labelsList = geomfilt1->GetLabels();

		bool zp=false;
		for( USImageType::PixelType i=0; i < labelsList.size(); ++i ){
			if( labelsList[i] == 0 ){ zp=true; continue; }
			std::vector<float> quantified_numbers_cell;
			for( unsigned j=0; j<number_of_rois; ++j ) quantified_numbers_cell.push_back((float)0.0);
			double centroid_x = geomfilt1->GetCentroid(labelsList[i])[0];
			double centroid_y = geomfilt1->GetCentroid(labelsList[i])[1];
			labelindicestype indices1;
			indices1 = geomfilt1->GetPixelIndices(labelsList[i]);
			for( labelindicestype::iterator itPixind = indices1.begin(); itPixind!=indices1.end(); ++itPixind ){
				IteratorType iterator1 ( input_image, input_image->GetRequestedRegion() );
				iterator1.SetIndex( *itPixind );
				if( iterator1.Get() < thresh )
					continue;
				double x = iterator1.GetIndex()[0];
				double y = iterator1.GetIndex()[1];
				double angle = atan2((centroid_y-y),fabs(centroid_x-x));
				if( (centroid_x-x)>0 )
					angle += M_PI_2;
				else
					angle = M_PI+M_PI-(angle+M_PI_2);
				angle = ((number_of_rois-1)*angle)/(2*M_PI);
				double angle_fraction[1];
				unsigned angular_index;
				if( modf( angle, angle_fraction ) > 0.5 )
					angular_index = ceil( angle );
				else
					angular_index = floor( angle );
				
				quantified_numbers_cell[angular_index] += iterator1.Get();
			}
			for( unsigned j=0; j<number_of_rois; ++j ) quantified_numbers.push_back(quantified_numbers_cell[j]);
		}
		unsigned qnum_sz = zp? (labelsList.size()-1) : (labelsList.size());
		for( unsigned i=0; i<qnum_sz; ++i ){
			unsigned counter=0;
			for( unsigned j=0; j<number_of_rois; ++j ){
				if( quantified_numbers[(i*number_of_rois+j)] > (255.0*surr_dist) )
					++counter;
			}
			qfied_num.push_back(counter);
		}
	}
	else{
		GeometryFilterType::Pointer geomfilt1 = GeometryFilterType::New();
		geomfilt1->SetInput( inp_labeled );
		geomfilt1->SetCalculatePixelIndices( true );
		geomfilt1->Update();
		labelsList = geomfilt1->GetLabels();
		std::cout<<std::endl<<"The size is: "<<labelsList.size();
		if( labelsList.size() == 1 )
		{
			qfied_num.clear();
			return qfied_num;
		}
		bool zp=false; USPixelType zero;
		//Check if the background is also included
		for( USPixelType i=0; i<labelsList.size(); ++i ) if( labelsList[i] == 0 ){ zp=true; zero = i; }

		USImageType::SizeType  sizee;
		sizee[0] = inp_labeled->GetLargestPossibleRegion().GetSize()[0];  // size along X
		sizee[1] = inp_labeled->GetLargestPossibleRegion().GetSize()[1];  // size along Y
		sizee[2] = inp_labeled->GetLargestPossibleRegion().GetSize()[2];  // size along Z

		itk::SizeValueType roi_list_size = zp ?
					((itk::SizeValueType)number_of_rois*(labelsList.size()-1)*2) : 
					((itk::SizeValueType)number_of_rois*labelsList.size()*2);
		std::vector<double> quantified_numbers_cell((roi_list_size),0.0
			);
		std::cout<<"Bounding boxes computed"<<std::endl;

#ifdef _OPENMP
itk::MultiThreader::SetGlobalDefaultNumberOfThreads(1);
#pragma omp parallel for
#if _OPENMP < 200805L
		for( int i=0; i<labelsList.size(); ++i )
#else
		for( USImageType::PixelType i=0; i<labelsList.size(); ++i )
#endif
#else
		for( USImageType::PixelType i=0; i<labelsList.size(); ++i )
#endif
		{
			itk::SizeValueType ind;
			if( zp && (zero==i) ) continue;
			if( zp && (i>zero)  ) ind = i-1;
			else ind = i;
			//Get label indices
			labelindicestype indices1;
			double centroid_x,centroid_y,centroid_z;
			GeometryFilterType::BoundingBoxType boundbox;
			#pragma omp critical
			{
				indices1 = geomfilt1->GetPixelIndices(labelsList[i]);
				//Get Centroid
				centroid_x = geomfilt1->GetCentroid(labelsList[i])[0];
				centroid_y = geomfilt1->GetCentroid(labelsList[i])[1];
				centroid_z = geomfilt1->GetCentroid(labelsList[i])[2];
				//Create an image with bounding box + 2 * outside distance + 2
				//and get distance map for the label
				boundbox = geomfilt1->GetBoundingBox(labelsList[i]);
			}
			//Create vnl array 3xN( label indicies )
			vnl_matrix<double> B(3,indices1.size());

			FloatImageType::Pointer inp_lab = FloatImageType::New();
			FloatImageType::PointType origint; origint[0] = 0; origint[1] = 0; origint[2] = 0;
			inp_lab->SetOrigin( origint );
			FloatImageType::IndexType startt;
			startt[0] = 0;  // first index on X
			startt[1] = 0;  // first index on Y
			startt[2] = 0;  // first index on Z
			FloatImageType::SizeType  sizet;
			sizet[0] = boundbox[1]-boundbox[0]+2*surr_dist+2;  // size along X
			sizet[1] = boundbox[3]-boundbox[2]+2*surr_dist+2;  // size along Y
			sizet[2] = boundbox[5]-boundbox[4]+2*surr_dist+2;  // size along Z
			FloatImageType::RegionType regiont;
			regiont.SetSize( sizet );
			regiont.SetIndex( startt );
			inp_lab->SetRegions( regiont );
			inp_lab->Allocate();
			inp_lab->FillBuffer(0.0);
			inp_lab->Update();
			IteratorTypeFloat iterator444 ( inp_lab, inp_lab->GetRequestedRegion() );

			//Populate matrix with deviations from the centroid for principal axes and
			//at the same time set up distance-transform computation
			itk::SizeValueType ind1=0;
			for( labelindicestype::iterator itPixind = indices1.begin(); itPixind!=indices1.end(); ++itPixind ){
				IteratorType iterator3( input_image, input_image->GetRequestedRegion() );
				iterator3.SetIndex( *itPixind );
				B(0,(ind1)) = iterator3.GetIndex()[0]-centroid_x;
				B(1,(ind1)) = iterator3.GetIndex()[1]-centroid_y;
				B(2,(ind1)) = iterator3.GetIndex()[2]-centroid_z;
				FloatImageType::IndexType cur_in;
				cur_in[0] = iterator3.GetIndex()[0]-boundbox[0]+1+surr_dist;
				cur_in[1] = iterator3.GetIndex()[1]-boundbox[2]+1+surr_dist;
				cur_in[2] = iterator3.GetIndex()[2]-boundbox[4]+1+surr_dist;
				iterator444.SetIndex( cur_in );
				iterator444.Set( 255.0 );
				++ind1;
			}

			//Compute distance transform for the current object
			DTFilter::Pointer dt_obj= DTFilter::New() ;
			dt_obj->SetInput( inp_lab );
			dt_obj->SquaredDistanceOff();
			dt_obj->InsideIsPositiveOff();
			try{
				dt_obj->Update() ;
			} catch( itk::ExceptionObject & err ){
				std::cerr << "Error in Distance Transform: " << err << std::endl;
			}
			FloatImageType::Pointer dist_im = dt_obj->GetOutput();

			//Use KLT to compute pricipal axes
			vnl_matrix<double> B_transp((int)indices1.size(),3);
			B_transp = B.transpose();
			vnl_matrix<double>  COV(3,3);
			COV = B * B_transp;
			double norm = 1.0/(double)indices1.size();
			COV = COV * norm;
			//Eigen decomposition
			vnl_real_eigensystem Eyegun( COV );
			vnl_matrix<vcl_complex<double> > EVals = Eyegun.D;
			double Eval1 = vnl_real(EVals)(0,0); double Eval2 = vnl_real(EVals)(1,1); double Eval3 = vnl_real(EVals)(2,2);
			vnl_double_3x3 EVectMat = Eyegun.Vreal;
			double V1[3],V2[3],EP_norm[3];
			if( Eval1 >= Eval3 && Eval2 >= Eval3 ){
				if( Eval1 >= Eval2 ){
					V1[0] = EVectMat(0,0); V1[1] = EVectMat(1,0); V1[2] = EVectMat(2,0);
					V2[0] = EVectMat(0,1); V2[1] = EVectMat(1,1); V2[2] = EVectMat(2,1);
				} else {
					V2[0] = EVectMat(0,0); V2[1] = EVectMat(1,0); V2[2] = EVectMat(2,0);
					V1[0] = EVectMat(0,1); V1[1] = EVectMat(1,1); V1[2] = EVectMat(2,1);
				}
			} else if( Eval1 >= Eval2 && Eval3 >= Eval2 ) {
				if( Eval1 >= Eval3 ){
					V1[0] = EVectMat(0,0); V1[1] = EVectMat(1,0); V1[2] = EVectMat(2,0);
					V2[0] = EVectMat(0,2); V2[1] = EVectMat(1,2); V2[2] = EVectMat(2,2);
				} else {
					V2[0] = EVectMat(0,0); V2[1] = EVectMat(1,0); V2[2] = EVectMat(2,0);
					V1[0] = EVectMat(0,2); V1[1] = EVectMat(1,2); V1[2] = EVectMat(2,2);
				}
			} else {
				if( Eval2 >= Eval3 ){
					V1[0] = EVectMat(0,1); V1[1] = EVectMat(1,1); V1[2] = EVectMat(2,1);
					V2[0] = EVectMat(0,2); V2[1] = EVectMat(1,2); V2[2] = EVectMat(2,2);
				} else {
					V2[0] = EVectMat(0,1); V2[1] = EVectMat(1,1); V2[2] = EVectMat(2,1);
					V1[0] = EVectMat(0,2); V1[1] = EVectMat(1,2); V1[2] = EVectMat(2,2);
				}
			}
			double n_sum = sqrt( V1[0]*V1[0]+V1[1]*V1[1]+V1[2]*V1[2] );
			V1[0] /= n_sum; V1[1] /= n_sum; V1[2] /= n_sum;
			n_sum = sqrt( V2[0]*V2[0]+V2[1]*V2[1]+V2[2]*V2[2] );
			V2[0] /= n_sum; V2[1] /= n_sum; V2[2] /= n_sum;
			//Get the normal to the plane formed by the biggest two EVs
			EP_norm[0] = V1[1]*V2[2]-V1[2]*V2[1];
			EP_norm[1] = V1[2]*V2[0]-V1[0]*V2[2];
			EP_norm[2] = V1[0]*V2[1]-V1[1]*V2[0];
			//Reassign V2 so that it is orthogonal to both EP_norm and V1
			V2[0] = V1[1]*EP_norm[2]-V1[2]*EP_norm[1];
			V2[1] = V1[2]*EP_norm[0]-V1[0]*EP_norm[2];
			V2[2] = V1[0]*EP_norm[1]-V1[1]*EP_norm[0];
			//Now we have the point normal form; EP_norm is the normal and
			//centroid_x, centroid_y, centroid_z is the point
			//The equation to the plane is EP_norm[0](x-centroid_x)+EP_norm[1](y-centroid_y)+EP_norm[2](z-centroid_z)=0
			double dee = (centroid_x*EP_norm[0]+centroid_y*EP_norm[1]+centroid_z*EP_norm[2])*(-1.00);

			//Iterate through and assign values to each region
			typedef itk::ImageRegionConstIterator< FloatImageType > ConstIteratorTypeFloat;
			ConstIteratorTypeFloat pix_buf2( dist_im, dist_im->GetRequestedRegion() );
			IteratorType iterator44( input_image, input_image->GetRequestedRegion() );

			for ( pix_buf2.GoToBegin(); !pix_buf2.IsAtEnd(); ++pix_buf2 ){
				//Use pixels that are only within the defined radius from the nucleus
				double current_distance = pix_buf2.Get();
				if( (current_distance <= (double)surr_dist) && (current_distance>=(-1*inside_dist)) ){
					USImageType::IndexType cur_in;//,cur_in_cpy;
					double n_vec[3];
					cur_in[0] = pix_buf2.GetIndex()[0]+boundbox[0]-1-surr_dist;
					cur_in[1] = pix_buf2.GetIndex()[1]+boundbox[2]-1-surr_dist;
					cur_in[2] = pix_buf2.GetIndex()[2]+boundbox[4]-1-surr_dist;
					//cur_in_cpy[0] = cur_in[0]; cur_in_cpy[1] = cur_in[1]; cur_in_cpy[2] = cur_in[2];
					if( cur_in[0] < 0 || cur_in[1] < 0 || cur_in[2] < 0 ) continue;
					if( cur_in[0] >= sizee[0] || cur_in[1] >= sizee[1] || cur_in[2] >= sizee[2] ) continue;
					iterator44.SetIndex( cur_in );
					USImageType::PixelType pixel_intensity;
					pixel_intensity = iterator44.Get();
					if( pixel_intensity < thresh ) continue;

					//The projection of the point on the plane formed by the fist two major axes
					double xxx, yyy, zzz;
					xxx = cur_in[0] - EP_norm[0]*((EP_norm[0]*cur_in[0]+EP_norm[1]*cur_in[1]+EP_norm[2]*cur_in[2]+dee)
									/(EP_norm[0]*EP_norm[0]+EP_norm[1]*EP_norm[1]+EP_norm[2]*EP_norm[2]));
					yyy = cur_in[1] - EP_norm[1]*((EP_norm[0]*cur_in[0]+EP_norm[1]*cur_in[1]+EP_norm[2]*cur_in[2]+dee)
									/(EP_norm[0]*EP_norm[0]+EP_norm[1]*EP_norm[1]+EP_norm[2]*EP_norm[2]));
					zzz = cur_in[2] - EP_norm[2]*((EP_norm[0]*cur_in[0]+EP_norm[1]*cur_in[1]+EP_norm[2]*cur_in[2]+dee)
									/(EP_norm[0]*EP_norm[0]+EP_norm[1]*EP_norm[1]+EP_norm[2]*EP_norm[2]));
					//The vector from the centroid to the projected point
					n_vec[0] = centroid_x-xxx;
					n_vec[1] = centroid_y-yyy;
					n_vec[2] = centroid_z-zzz;
					n_sum = sqrt( n_vec[0]*n_vec[0] + n_vec[1]*n_vec[1] + n_vec[2]*n_vec[2] );
					n_vec[0] /= n_sum; n_vec[1] /= n_sum; n_vec[2] /= n_sum;
					//n_vec is the normalized vect in the direction of the projected point
					//V1 is the largest eigenvector
					//Get the dot and cross product between the two
					double doooot, crooos,fin_est_angle;
					doooot = n_vec[0]*V1[0]+n_vec[1]*V1[1]+n_vec[2]*V1[2];
					crooos = n_vec[0]*V2[0]+n_vec[1]*V2[1]+n_vec[2]*V2[2];

					fin_est_angle = atan2( crooos, doooot );
					USPixelType bin_num;
					//Compute bin num
					if( fin_est_angle<0 )
						fin_est_angle += (2*M_PI);
					bin_num = floor(fin_est_angle*number_of_rois/(2*M_PI));

					//Check which side of the plane the point lies on
					double v_norm = (cur_in[0]-centroid_x)*(cur_in[0]-centroid_x)
									+(cur_in[1]-centroid_y)*(cur_in[1]-centroid_y)
									+(cur_in[2]-centroid_z)*(cur_in[2]-centroid_z);
					v_norm = sqrt( v_norm );
					double doot   = (cur_in[0]-centroid_x)*EP_norm[0]/v_norm + (cur_in[1]-centroid_y)*EP_norm[1]/v_norm + (cur_in[2]-centroid_z)*EP_norm[2]/v_norm;

					if( doot<0 )
						bin_num += number_of_rois;
					quantified_numbers_cell.at((ind*(2*number_of_rois)+bin_num)) += pixel_intensity;
				}
			}
		}
		number_of_rois = number_of_rois*2;
		if( labelsList.size() == 1 )
		{
			qfied_num.clear();
			return qfied_num;
		}
		std::vector<double> quantified_numbers_cell_cpy(roi_list_size);
		std::copy(quantified_numbers_cell.begin(), quantified_numbers_cell.end(), quantified_numbers_cell_cpy.begin() );
		//Run k-means
		//Most of the code is adapted from mul/mbl/mbl_k_means.cxx
		std::sort(quantified_numbers_cell.begin(), quantified_numbers_cell.end());
	
		bool skipKmeans;
		double Positive_thresh;
		if( quantified_numbers_cell.at(0) == quantified_numbers_cell.at(quantified_numbers_cell.size()-1) )
			skipKmeans = true;

		if( !skipKmeans ){
			std::cout<<"Starting k-means\n";
			std::cout<<"First:"<<quantified_numbers_cell.at(0)<<" Last:"<<quantified_numbers_cell.at(quantified_numbers_cell.size()-1)<<std::endl;
			unsigned k = 2;
			//Vectors and matrices for k-means
			std::vector< USImageType::PixelType > partition( roi_list_size, 0 );
			std::vector< double > sums   ( k, 0.0 );
			std::vector< double > centers( k, 0.0 );
			std::vector< USImageType::PixelType > nNearest( k, 0 );

			//Use the elements that are evenly spaced to get the intial centers
			for( unsigned i=0; i<k; ++i ){
				double index = ((double)(i)*roi_list_size)/(k+1);
				centers.at(i) = quantified_numbers_cell.at((itk::SizeValueType)index);
				bool duplicated;
				std::cout<<"Initializing centers\n"<<std::flush;
				if(i){
					if( centers.at((i-1)) == centers.at(i) ){
						duplicated = true;
						itk::SizeValueType ind=i+1;
						while( centers.at((i-1))==quantified_numbers_cell.at(ind) )
							++ind;
						centers.at(i) = quantified_numbers_cell.at(ind);
						sums.at(i)    = quantified_numbers_cell.at(ind);
					}
				}
				if(!duplicated)
					sums.at(i) = quantified_numbers_cell.at((i+1)/(k+1));
				++nNearest[i];
			}

			bool changed = true;
			std::cout<<"Waiting for kmeans to converge\n"<<std::flush;
			while(changed){
				changed = false;
				for(itk::SizeValueType i=0; i<roi_list_size; ++i){
					unsigned bestCentre = 0;
					double bestDist = fabs((centers.at(0)-quantified_numbers_cell.at(i)));
					for(unsigned j=1; j<k; ++j){
						double dist = fabs((centers.at(j)-quantified_numbers_cell.at(i)));
						if( dist < bestDist ){
							bestDist = dist; bestCentre = j;
						}
					}
					sums[bestCentre] += quantified_numbers_cell.at(i);
					++ nNearest[bestCentre];
					if( bestCentre != partition.at(i) ){
						changed = true;
						partition.at(i) = bestCentre;
					}
				}
				for( unsigned j=0; j<k; ++j) centers.at(j)  = sums.at(j)/nNearest.at(j);
				for( unsigned j=0; j<k; ++j) sums.at(j)     = 0;
				for( unsigned j=0; j<k; ++j) nNearest.at(j) = 0;
			}
			for( unsigned i=0; i<k; ++i )
				std::cout<<"Center "<<i<<" "<<centers.at(i)<<"\n";

			Positive_thresh = ((centers.at(0)+centers.at(1))/2) < (255.0*thresh)?
						 ((centers.at(0)+centers.at(1))/2) : (255.0*thresh); //Arbitrary upper thresh
		}
		else
			Positive_thresh = 255.0*thresh;

		std::cout<<"Positive_thresh "<<Positive_thresh<<"\n";

		std::cout<<"Done k-means\n";
		itk::SizeValueType ind = 0;
		for( USPixelType i=0; i<labelsList.size(); ++i ){
			if( zp && (zero==i) ) continue;
			int num_positive_rois = 0;
			for( unsigned j=0; j<number_of_rois; ++j ){
				itk::SizeValueType index_of_roi = ind*number_of_rois+j;
				if( quantified_numbers_cell_cpy.at(index_of_roi)>Positive_thresh )
					++num_positive_rois;
			}
			qfied_num.push_back(num_positive_rois);
			++ind;
		}
	}
	std::cout<<"Done surroundedness\n"<<std::flush;
	return qfied_num;
}