void WeightedAverage::operator()(Data * dt, int ** classification, Classifier ** classifiers, int numClassifiers)
{
	int i, j, k;
	int chosen;
	std::vector<float> averages(dt->getNLabels(), 0.0f);
	for (i = 0; i < dt->getNSamples(); i++)
	{
		for (float & av : averages)
			av = 0.0f;
		for (j = 0; j < numClassifiers; j++)
		{
			for (k = 0; k < dt->getNLabels(); k++)
			{
				if(classifiers[j]->hasScore())
				{
					averages[k] += classifiers[j]->getScore(i, k) * weight[j];  
				}
			}
		}

		chosen = 0;
		for (j = 0; j < dt->getNLabels(); j++)
		{
			if (averages[j] > averages[chosen])
				chosen = j;
		}
		dt->setClassificationLabel(i, chosen + 1);

	}
}
Beispiel #2
0
QVi RegionService::calcAverage(const MatSet& matSet, QLP region) {
    QVi averages(9,0);
   
    if(!region.size()) {
        qDebug() << "region.count()=0";
        return averages;
    }

    QVi sumOfValue = countSum(matSet, region);

    for(int i=0; i<9; i++) {
        averages[i] = sumOfValue[i] / region.count();
    }

    return averages;
}
Beispiel #3
0
void RegionService::calcMedianAndTolerance(const MatSet& matSet, QLPs regions, vint& medians, vint& upperTolerances, vint& underTolerances) {
    int pixelSum=0;
    vint averages(9,0);

    int greenFrequency[256] = {0};
    int yFrequency[256] = {0};
    int crFrequency[256] = {0};
    int cbFrequency[256] = {0};
    for(QLP region : regions) {
        for(Point point : region) {

            greenFrequency[G(matSet.bgr(), point.x, point.y)]++;
            yFrequency[B(matSet.ycrcb(), point.x, point.y)]++;
            crFrequency[G(matSet.ycrcb(), point.x, point.y)]++;
            cbFrequency[R(matSet.ycrcb(), point.x, point.y)]++;
            pixelSum++;
        }
    }

    int harfOfPixelSum = (int)((double)pixelSum/2.0);
    int underOfPixelSum = (int)((double)pixelSum*0.05);
    int upperOfPixelSum = (int)((double)pixelSum*0.95);

    int greenPixelCount = 0;
    int greenMedian = 0;
    int greenUpperTolerance = 0;
    int greenUnderTolerance = 0;

    for(int bin =0; bin<256; bin++ ) {
        greenPixelCount = greenPixelCount + greenFrequency[bin];
        if(greenPixelCount <= underOfPixelSum) {
            greenUnderTolerance = bin;
            continue;
        }
        if(greenPixelCount <= harfOfPixelSum) {
            greenMedian = bin;
            continue;
        }
        if(greenPixelCount >= upperOfPixelSum) {
            greenUpperTolerance = bin;
            break;
        }

    }
    int yPixelCount = 0;
    int yMedian = 0;
    int yUpperTolerance = 0;
    int yUnderTolerance = 0;
    for(int bin =0; bin<256; bin++ ) {
        yPixelCount = yPixelCount + yFrequency[bin];
        if(yPixelCount <= underOfPixelSum) {
            yUnderTolerance = bin;
            continue;
        }
        if(yPixelCount <= harfOfPixelSum) {
            yMedian = bin;
            continue;
        }
        if(yPixelCount >= upperOfPixelSum) {
            yUpperTolerance = bin;
            break;
        }
    }
    int crPixelCount = 0;
    int crMedian = 0;
    int crUpperTolerance = 0;
    int crUnderTolerance = 0;
    for(int bin =0; bin<256; bin++ ) {
        crPixelCount = crPixelCount + crFrequency[bin];
        if(crPixelCount <= underOfPixelSum) {
            crUnderTolerance = bin;
            continue;
        }
        if(crPixelCount <= harfOfPixelSum) {
            crMedian = bin;
            continue;
        }
        if(crPixelCount >= upperOfPixelSum) {
            crUpperTolerance = bin;
            break;
        }
    }
    int cbPixelCount = 0;
    int cbMedian = 0;
    int cbUpperTolerance = 0;
    int cbUnderTolerance = 0;
    for(int bin =0; bin<256; bin++ ) {
        cbPixelCount = cbPixelCount + cbFrequency[bin];
        if(cbPixelCount <= underOfPixelSum) {
            cbUnderTolerance = bin;
            continue;
        }
        if(cbPixelCount <= harfOfPixelSum) {
            cbMedian = bin;
            continue;
        }
        if(cbPixelCount >= upperOfPixelSum) {
            cbUpperTolerance = bin;
            break;
        }

    }
    
    medians[1] = greenMedian;
    medians[6] = yMedian;
    medians[7] = crMedian;
    medians[8] = cbMedian;
    upperTolerances[1] = greenUpperTolerance;
    upperTolerances[6] = yUpperTolerance;
    upperTolerances[7] = crUpperTolerance;
    upperTolerances[8] = cbUpperTolerance;
    underTolerances[1] = greenUnderTolerance;
    underTolerances[6] = yUnderTolerance;
    underTolerances[7] = crUnderTolerance;
    underTolerances[8] = cbUnderTolerance;

    
}
Beispiel #4
0
void CF<FactorizerType>::GetRecommendations(const size_t numRecs,
                                            arma::Mat<size_t>& recommendations,
                                            arma::Col<size_t>& users)
{
  // Generate new table by multiplying approximate values.
  rating = w * h;

  // Now, we will use the decomposed w and h matrices to estimate what the user
  // would have rated items as, and then pick the best items.

  // Temporarily store feature vector of queried users.
  arma::mat query(rating.n_rows, users.n_elem);

  // Select feature vectors of queried users.
  for (size_t i = 0; i < users.n_elem; i++)
    query.col(i) = rating.col(users(i));

  // Temporary storage for neighborhood of the queried users.
  arma::Mat<size_t> neighborhood;

  // Calculate the neighborhood of the queried users.
  // This should be a templatized option.
  neighbor::AllkNN a(rating);
  arma::mat resultingDistances; // Temporary storage.
  a.Search(query, numUsersForSimilarity, neighborhood, resultingDistances);

  // Temporary storage for storing the average rating for each user in their
  // neighborhood.
  arma::mat averages = arma::zeros<arma::mat>(rating.n_rows, query.n_cols);

  // Iterate over each query user.
  for (size_t i = 0; i < neighborhood.n_cols; ++i)
  {
    // Iterate over each neighbor of the query user.
    for (size_t j = 0; j < neighborhood.n_rows; ++j)
      averages.col(i) += rating.col(neighborhood(j, i));
    // Normalize average.
    averages.col(i) /= neighborhood.n_rows;
  }

  // Generate recommendations for each query user by finding the maximum numRecs
  // elements in the averages matrix.
  recommendations.set_size(numRecs, users.n_elem);
  recommendations.fill(cleanedData.n_rows); // Invalid item number.
  arma::mat values(numRecs, users.n_elem);
  values.fill(-DBL_MAX); // The smallest possible value.
  for (size_t i = 0; i < users.n_elem; i++)
  {
    // Look through the averages column corresponding to the current user.
    for (size_t j = 0; j < averages.n_rows; ++j)
    {
      // Ensure that the user hasn't already rated the item.
      if (cleanedData(j, users(i)) != 0.0)
        continue; // The user already rated the item.

      // Is the estimated value better than the worst candidate?
      const double value = averages(j, i);
      if (value > values(values.n_rows - 1, i))
      {
        // It should be inserted.  Which position?
        size_t insertPosition = values.n_rows - 1;
        while (insertPosition > 0)
        {
          if (value <= values(insertPosition - 1, i))
            break; // The current value is the right one.
          insertPosition--;
        }

        // Now insert it into the list.
        InsertNeighbor(i, insertPosition, j, value, recommendations,
            values);
      }
    }

    // If we were not able to come up with enough recommendations, issue a
    // warning.
    if (recommendations(values.n_rows - 1, i) == cleanedData.n_rows + 1)
      Log::Warn << "Could not provide " << values.n_rows << " recommendations "
          << "for user " << users(i) << " (not enough un-rated items)!"
          << std::endl;
  }
}
int main(int argn, char* args[])
{
	static char *desc[] = {
		"This script will read the xtc trajectory from an MD simulation",
		"performed by GROMACS and output all data related to the analysis",
		"of preferential interactions.",
		"[PAR]",
		"Generated: Thu Aug 20 16:49:21 EDT 2015.[BR]",
		"Last updated: Thu Aug 27 17:26:01 EDT 2015.",
		"[PAR]",
		"Future Developments:[BR]",
		"[BB]1.[bb] Partition calculation into groups (constituent amino acids).[BR]",
		"[BB]2.[bb] Calculate residence times.[BR]",
		"[BB]3.[bb] Include a measure for geometric orientation.[BR]",
		"[BB]4.[bb] Calculate molecular distributions.[BR]",
		"[BB]5.[bb] Parallelize it.",
		"[PAR]",
		"Remember to check the dependencie of the results on the number of block",
		" used by using [TT]-block[tt].",
		"Also, check that your simulation has been properly equilibrated by using [TT]-f0[tt].",
		"In terms of reducing the computational cost of the analysis, use the option",
		"[TT]-skip[tt] to only use every nr[TT]-th[tt] frame from the trajectory."
	};
	
	unsigned int protein_sequence=20; 	/* parse tpr.itp for info 			*/
        unsigned int N_co=4; 			/* look at topology for number of co-solvents 	*/
        unsigned int num_sol=7906; 		/* look at topology as well 			*/
	unsigned int skip_nr=1;
	unsigned int granularity=2*100;
	unsigned int f0=0;
	bool bIndex=false;

	t_pargs pa[] = {
		{"-start", FALSE, etINT, {&f0}, "Start after n-th frame."},
		{"-skip", FALSE, etINT, {&skip_nr}, "Only write every nr-th frame."},
		{"-grid", FALSE, etINT, {&granularity}, "Number points to calculate."},
		{"-seq", FALSE, etINT,{&protein_sequence}, "Number of amino acids in protein sequence."},
		{"-Nco", FALSE, etINT,{&N_co}, "Number of cosolvent molecules."},
		{"-Sol", FALSE, etINT,{&num_sol}, "Number of water molecules."}
	};	

	char 		title[STRLEN];	
	t_topology 	top;
	int		ePBC;
	rvec		*xtop;
	matrix		box;
	
	t_filenm fnm[] = { 			/* See filenm.h */
		{ efTOP, NULL,  NULL, ffREAD  },
		{ efTPS, NULL, NULL, ffREAD },	/*  topology 	*/
		{ efTRX, "-f", NULL, ffREAD },	/*  trajcetory  */
		{ efNDX, "-n", NULL, ffOPTRD }  /*  index file  */
	};

#define NFILE asize(fnm)

/* Interface. Adds default options. */	
CopyRight(stderr,args[0]);
parse_common_args(&argn,args,PCA_CAN_TIME | PCA_CAN_VIEW, NFILE,fnm,asize(pa),pa,asize(desc),desc,0,NULL);
read_tps_conf( ftp2fn(efTPS, NFILE, fnm), title, &top, &ePBC, &xtop, NULL, box, TRUE);
sfree(xtop);

/*******************************************************************************************************************/
/*
int iter;
for (iter=0;iter<top.atoms.nr/100;++iter)
{
printf("Atom name: %s\tAtom charge: %f\n", *(top.atoms.atomname[iter]), top.atoms.atom[iter].q );
printf("Atom type: %d\tAtomic Residue NUmber: %d\n", top.atoms.atom[iter].type, top.atoms.atom[iter].resnr );
printf("Chain Identifier: %u\tNr of residues names: %d\n", top.atoms.atom[iter].ptype, top.atoms.nres );
printf("Residue name: %s\n\n", *(top.atoms.resname[iter]) );
}
*/
/*******************************************************************************************************************/

int status;
t_trxframe fr;
int flags = TRX_READ_X;

/* Count Number of Frames */
        unsigned int bframes=0, frames=0;	
	int bwrite;
	read_first_frame(&status, ftp2fn(efTRX,NFILE,fnm), &fr, flags);
        do {
		bwrite = bframes % skip_nr; 
		++bframes; 
		if ((bframes>f0) && (bwrite==0)){ ++frames; }
	} while ( read_next_frame(status,&fr) );

/* Preparing Block Analysis */
	bIndex = ftp2bSet(efNDX,NFILE,fnm);
	std::vector<int> blocks_list;
	if (bIndex)
	{
		FILE *fp = ffopen(opt2fn("-n",NFILE,fnm),"r");
		int numblock;
		while(fscanf(fp,"%d",&numblock)!=EOF)
		{
			blocks_list.push_back(numblock);
		}
		fclose(fp);
	} else {
		blocks_list.push_back(1);
	}

/* Actual Calculation */
	std::vector<Info> protein;
        std::vector<Info> cosolvent;
	std::vector<Info> solvent;

	std::vector<double> cutoff, coefficients;
	double molals=0, molars=0;

/* BLOCK AVERAGE */
typedef std::vector<double> Row;
typedef std::vector<Row> Matrix;
unsigned int num_blocks;
/////////////
//////////// std::ofstream test_partition("partition.txt");

for (unsigned int iter=0; iter<blocks_list.size(); ++iter)
{
	num_blocks = blocks_list[iter];

	unsigned int partition = (frames)/num_blocks;
	unsigned int frame_counter=0;
	std::vector<double> positions(granularity), averages(granularity), averages_sqr(granularity), sigma(granularity);
	Matrix values(num_blocks,Row(granularity)), values_sqr(num_blocks,Row(granularity));

	unsigned int frame=0, twrite=0;
	read_first_frame(&status, ftp2fn(efTRX,NFILE,fnm), &fr, flags);
	do 
	{
		twrite = frame % skip_nr;	/* if twrite==0 then read frame. */
		++frame;
		if ((frame > f0) && (twrite==0))
		{
		/* READING */
			unsigned int protein_co=protein_sequence+N_co;
			unsigned int solvated=protein_co+num_sol;	
			for (unsigned int n=0; n<top.atoms.nr; ++n)
			{
				/* Parsing */
				Info atomo;
				atomo.setAtom( (std::string) *(top.atoms.atomname[n]) );
				atomo.setResnum( (unsigned int) top.atoms.atom[n].resnr );
				atomo.setResname( (std::string) *(top.atoms.resname[atomo.getResnum()]) );
				atomo.setCoords( (double) fr.x[n][XX], (double) fr.x[n][YY], (double) fr.x[n][ZZ] );
					
				/* Testing for partition of groups */
			///////	atomo.print(test_partition);
					
	
				/* Appending */
				// if 
				if ( atomo.getAtom()[0]!='H')   // atomo.atom[0]!='H')
				{
					if ( atomo.getResnum() < protein_sequence ){ 
						protein.push_back(atomo);
					} else if ( (atomo.getResnum() >= protein_sequence) && (atomo.getResnum() < protein_co) ){ 
						cosolvent.push_back(atomo); 
					} else if ( (atomo.getResnum() >= protein_co) && (atomo.getResnum() < solvated) ){
						// if (atomo.getResname().compare("SOL")!=0)
						// we want to avoid inputing number of waters for analysis
						solvent.push_back(atomo);
					}
				}					
			}
		/* MAIN */      
			double box_size = fr.box[0][0];

	        	/* Local calculation for cosolvents */
                	std::vector<double> close_co;                                     /* Stores Distances of closest */
			for (unsigned int i=0; i<N_co; ++i)
                	{
                	        std::vector<double> local_co;
                	        double minimum_calculated = box_size*box_size;
				unsigned int Nco_size=cosolvent.size()/N_co;
                	        for (unsigned int n=(i*Nco_size); n<((i+1)*Nco_size); ++n)
                	        {
                	                for (unsigned int j=0; j<protein.size(); ++j)
                	                {
                	                        double dist = cosolvent[n].distance(protein[j],box_size);
                	                        if (dist < minimum_calculated ){ minimum_calculated = dist; }
                	                }
                	                local_co.push_back(minimum_calculated);
                	        }
                	        close_co.push_back( *min_element(local_co.begin(), local_co.end()) );
                	}	
			/* Local calculation for water */
                	std::vector<double> local_wat;
                	for (unsigned int i=0; i<solvent.size(); ++i)
                	{
                	        double minimum_calculated = box_size*box_size;
                	        for (unsigned int j=0; j<protein.size(); ++j)
                	        {
                        	        double dist = solvent[i].distance(protein[j],box_size);
                        	        if (dist < minimum_calculated){ minimum_calculated = dist; }
         	                }
         	                local_wat.push_back(minimum_calculated);
                	} 

			/* Preferential Interaction Coefficient */
                	double N_wat = solvent.size();
			linspace(0,box_size,granularity,cutoff);
                	for (unsigned int x=0; x<granularity; ++x)
                	{
                        	unsigned int n3=0, n1=0;
                        	for (unsigned int i=0; i<close_co.size(); ++i){ if (close_co[i] < (cutoff[x]*cutoff[x])) ++n3; }
                        	for (unsigned int i=0; i<local_wat.size(); ++i){ if (local_wat[i] < (cutoff[x]*cutoff[x])) ++n1; }
                        	coefficients.push_back(pref_coef(N_co, N_wat, n3, n1));
                	}
			molals+= molality(N_co, (int) N_wat);
                	molars+= molarity(N_co, box_size);

	        	/* Storage */
	        	for (unsigned int i=0; i<granularity; ++i){ positions[i] += cutoff[i]; }
                	for (unsigned int j=0; j<granularity; ++j)
                	{
                	        values[(int) (frame_counter/(partition+1))][j] += coefficients[j];
                	        values_sqr[(int) (frame_counter/(partition+1))][j] += coefficients[j]*coefficients[j];
                	}


			cutoff.clear();
        		coefficients.clear();
			protein.clear();
			cosolvent.clear();
			solvent.clear();
	
			++frame_counter;
		}
	} while ( read_next_frame(status,&fr) );
	//thanx(stderr);

	/* FINAL REUSLTS */
        double normalization = partition;
        molals /= (num_blocks*normalization);
        molars /= (num_blocks*normalization);
        for (unsigned int i=0; i<granularity; ++i){ positions[i] /= (num_blocks*normalization); }
        for (unsigned int i=0; i<num_blocks; ++i)
	{
        	for (unsigned int j=0; j<granularity; ++j)
                {
                	values[i][j] /= normalization;
                        values_sqr[i][j] /= normalization;
                }
        }

	/* AVERAGES */
        for (unsigned int i=0; i<granularity; ++i)
        {
                for (unsigned int j=0; j<num_blocks; ++j)
                {
                        averages[i] += values[j][i];
                        averages_sqr[i] += values_sqr[j][i];
                }
                averages[i] /= (double) num_blocks;
                averages_sqr[i] /= (double) num_blocks;
        }

	/* STANDARD DEVIATIONS */
       for (unsigned int i=0; i<granularity; ++i)
        {
                sigma[i] += sqrt( averages_sqr[i] - averages[i]*averages[i] );
        }

	/* OUTPUT */
        std::ofstream distances("dimensions.dat");
        for (unsigned int i=0; i<granularity/2; ++i){ distances << std::setw(1) << positions[i] <<'\n'; }
        distances.close();

        std::string output1="preferential_val.dat";
        std::string output2="preferential_sig.dat";
        std::string result;
        std::ostringstream convert;
        convert << num_blocks; //skip;
        result = convert.str();
        output1.insert(16,result);
        output2.insert(16,result);
        std::ofstream pic1(output1.c_str());
        std::ofstream pic2(output2.c_str());
        for (unsigned int i=0; i<granularity/2; ++i)
        {
                pic1 << std::setw(10)<< averages[i] <<'\n';
                pic2 << std::setw(10)<< sigma[i] <<'\n';
        }
        pic1.close();
        pic2.close();

        std::ofstream concentrations("concentrations.dat");
        concentrations<< std::setw(10) << "Molality" <<'\t'<< std::setw(10) << "Molarity" <<'\n';
        concentrations<< std::setw(10) << molals <<'\t'<< std::setw(10) << molars << '\n';
        concentrations.close();

        std::cout << "ANALYSIS COMPLETED!" <<'\n';
	std::cout<<"Total number of frames: "<<frame_counter<<'\n';
}

//////////////// test_partition.close();

thanx(stderr);
return 0;
}
void CViGrA_Watershed::Segmentation(TImage_In &Input, TImage_Out &Output, double Scale, bool bEdges)
{
	typedef typename vigra::NumericTraits<typename TImage_In::value_type>::RealPromote	TmpType;

	vigra::BasicImage<TmpType>	gradientx	(Get_NX(), Get_NY());
	vigra::BasicImage<TmpType>	gradienty	(Get_NX(), Get_NY());
	vigra::FImage				gradientmag	(Get_NX(), Get_NY());
	vigra::IImage				labels		(Get_NX(), Get_NY());

	//-----------------------------------------------------
	// calculate the x- and y-components of the image gradient at given scale
	Process_Set_Text(_TL("calculate gradients"));

	recursiveFirstDerivativeX	(srcImageRange(Input)		, destImage(gradientx), Scale);
	recursiveSmoothY			(srcImageRange(gradientx)	, destImage(gradientx), Scale);

	recursiveFirstDerivativeY	(srcImageRange(Input)		, destImage(gradienty), Scale);
	recursiveSmoothX			(srcImageRange(gradienty)	, destImage(gradienty), Scale);

	//-----------------------------------------------------
	// transform components into gradient magnitude
	Process_Set_Text(_TL("calculate gradient magnitude"));

	combineTwoImages(
		srcImageRange(gradientx),
		srcImage(gradienty),
		destImage(gradientmag),
		GradientSquaredMagnitudeFunctor()
	);

	//-----------------------------------------------------
	// find the local minima of the gradient magnitude (might be larger than one pixel)
	Process_Set_Text(_TL("find local minima"));

	labels	= 0;

	extendedLocalMinima(srcImageRange(gradientmag), destImage(labels), 1);

	//-----------------------------------------------------
	// label the minima just found
	Process_Set_Text(_TL("label minima"));

	int max_region_label	= labelImageWithBackground(srcImageRange(labels), destImage(labels), false, 0);

	//-----------------------------------------------------
	// create a statistics functor for region growing
	vigra::ArrayOfRegionStatistics<vigra::SeedRgDirectValueFunctor<float> >gradstat(max_region_label);

	//-----------------------------------------------------
	// perform region growing, starting from the minima of the gradient magnitude;
	// as the feature (first input) image contains the gradient magnitude,
	// this calculates the catchment basin of each minimum
	Process_Set_Text(_TL("perform region growing"));

	seededRegionGrowing(srcImageRange(gradientmag), srcImage(labels), destImage(labels), gradstat);

	//-----------------------------------------------------
	// initialize a functor to determine the average gray-value or color for each region (catchment basin) just found
	vigra::ArrayOfRegionStatistics<vigra::FindAverage<TmpType> >averages(max_region_label);

	//-----------------------------------------------------
	// calculate the averages
	Process_Set_Text(_TL("calculate averages"));

	inspectTwoImages(srcImageRange(Input), srcImage(labels), averages);

	//-----------------------------------------------------
	// write the averages into the destination image (the functor 'averages' acts as a look-up table)
	transformImage(srcImageRange(labels), destImage(Output), averages);

	//-----------------------------------------------------
	// mark the watersheds (region boundaries) black
	if( bEdges )
	{
		regionImageToEdgeImage(srcImageRange(labels), destImage(Output), vigra::NumericTraits<typename TImage_Out::value_type>::zero());
	}
}
Beispiel #7
0
void NETWORK::get_coordinates( double _z, double _dx, double _dy, std::vector<double>& _lrc, std::vector<double>& _x, std::vector<double>& _y ) const
{
  /// create reachable set sizes
  std::vector<double> rss( Order, 0.0 );
  for(int i=0; i<Order; i++)
    rss[i] = (double)Order * _lrc[i];

  /// make levels
  // sort local reaching centralities
  std::vector<int> ids( Order, 0 );
  for(int i=0; i<Order; i++)
    ids[i] = i;
  int len = Order;
  double rss_elem;
  int id;
  bool swapped = false;
  do
  {
    swapped = false;
    for(int i=1; i<len; i++)
    {
      if( rss[i-1] > rss[i] )
      {
        rss_elem = rss[i-1];
        rss[i-1] = rss[i];
        rss[i] = rss_elem;
        id = ids[i-1];
        ids[i-1] = ids[i];
        ids[i] = id;
        swapped = true;
      }
    }
    len--;
  } while( swapped );

  // network reaching centrality mean and variance
  double global_av = 0.0;
  double global_sd = 0.0;
  double threshold = 0.0;
  for(int i=0; i<Order; i++)
  {
    global_av += rss[i];
    global_sd += rss[i]*rss[i];
  }
  global_av /= (double)Order;
  global_sd = sqrt( fabs(global_sd/(double)Order - global_av*global_av) );
  threshold = _z * global_sd + 0.00001; // in case of GRC = 0

  // sort nodes in levels
  int number_of_levels = 0;
  int level_first_node = 0;
  int current_node = 1;
  std::vector<int> levels( Order, -1 );
  levels[0] = 0;
  // start putting nodes in level until we reach last node
  while( current_node < Order )
  {
    // pick the next node and calculate level average and standard deviation
    double level_av = 0.0;
    double level_sd = 0.0;
    for(int i=level_first_node; i<=current_node; i++)
    {
      level_av += rss[i];
      level_sd += rss[i]*rss[i];
    }
    level_av /= 1 + current_node - level_first_node;
    level_sd = sqrt( fabs(level_sd/double(1+current_node-level_first_node) - level_av*level_av) );

    // if level deviation is lower than the threshold, keep node, otherwise start new level and put node there
    if( level_sd < threshold )
    {
      levels[current_node] = number_of_levels;
      current_node++;
    }
    else
    {
      levels[current_node] = number_of_levels + 1;
      number_of_levels++;
      level_first_node = current_node;
      current_node++;
    }
  }
  number_of_levels++;

  /// set y coordinates
  std::vector<int> nodes_per_level( number_of_levels, 0 );
  // calculate level averages
  std::vector<double> averages( number_of_levels, 0.0 );
  for(int i=0; i<Order; i++)
  {
    averages[levels[i]] += rss[i];
    nodes_per_level[levels[i]]++;
  }
  for(int i=0; i<number_of_levels; i++)
    averages[i] /= nodes_per_level[i];

  std::vector<double> y_differences( number_of_levels, 0.0 );
  std::vector<double> y_coordinates( number_of_levels, 0.0 );
  y_differences[0] = 0.0;
  y_coordinates[0] = 0.0;
  double minimum_difference = _dy * (double)Order;
  for(int i=1; i<number_of_levels; i++)
  {
    y_differences[i] = log( averages[i]-averages[i-1] + 1.0 );

    if( y_differences[i] < minimum_difference )
      minimum_difference = y_differences[i];
  }
  for(int i=1; i<number_of_levels; i++)
    y_coordinates[i] = y_coordinates[i-1] + _dy*y_differences[i]/minimum_difference;

  _y.assign( Order, 0.0 );
  for(int i=0; i<Order; i++)
    _y[ids[i]] = y_coordinates[levels[i]];

  /// set x coordinates
  std::vector<double> x_coordinate_starts( number_of_levels, 0.0 );
  for(int i=0; i<number_of_levels; i++)
  {
    x_coordinate_starts[i] = -0.5 * _dx * (nodes_per_level[i] - 1);
    nodes_per_level[i] = 0;
  }
  _x.assign( Order, 0.0 );
  for(int i=0; i<Order; i++)
  {
    _x[ids[i]] = x_coordinate_starts[levels[i]] + _dx * nodes_per_level[levels[i]];
    nodes_per_level[levels[i]]++;
  }
}