#ifndef GTGEN_CELL_H
#define GTGEN_CELL_H

#include <vector>
#include <i3d/image3d.h>

#include <ini/iniparser.h>

#include "settings.h"
#include "molecule.h"
#include "scheduler.h"
#include "toolbox/bp_lists.h"
#include "toolbox/rnd_generators.h"

// The frequency of restarting the chromatin (texture)
// note: set high number to disable it
//#ifndef GTGEN_WITH_SOFA
	//#define RESTART_PERIOD 4
//#else
	#define RESTART_PERIOD 1000
//#endif

/**
 * A helper function to provide IDs for objects which guarantees their uniqueness
 * within the whole scene throughout the whole simulation.
 */
template <class ID_TYPE> ID_TYPE GetNewCellID(void);

/// prototype of a class defined in file 'scheduler.h'
template <class MV, class PV> class Scheduler;

/// prototype of a struct defined in file 'scheduler.h'
template <class TYPE> struct TrackRecord;

/**
 * Basic class defining live 'cell'
 * MV ... mask voxel datatype
 * PV ... phantom voxel datatype
 */
template <class MV, class PV> class Cell
{
  public:
			 /**
			  * Constructor:
			  * \param[in] _configIni		the parameters of newly created/born cell
			  * \param[in] controller		the context (scene) in which the cell lives
			  * \param[in] birthTimePoint		initial timepoint of the cell evolution
			  * \param[in] parenttID		ID of the parent (for GT tracking purposes only)
			  * 
			  * The noFramesPerCellCycle should slightly vary between cells to simulate
			  * non-uniformity of cells in population.
			  */
			 Cell(const IniHandler &_configIni,
					Scheduler<MV, PV> &controller,
			      const size_t birthTimePoint,
			      const MV parenttID=0) :
					configIni(_configIni),
					parentID(parenttID),
					centrosomeA(NULL),
					centrosomeB(NULL),
					scheduler(controller),
					timePoint(birthTimePoint), 
					currentPhase(G2Phase), // from types.h
					// do not initialize chrDotList and chrCentres here
					// otherwise the system starts wasting IDs
					scmCellPolarityVector(i3d::Vector3d<float>(1.0f,0.0f,0.0f)),
					duplicatedCell1(NULL),
					duplicatedCell2(NULL),
					delay(0),
					scmLastScmUsed(INT_MAX),
					SOFA_InitialPosition(0.f),
					SOFA_InitialRotation(0.f),
					scmCometState(noComet),
					scmCometVector(i3d::Vector3d<float>(0.f,0.f,0.f))
					{
						DEBUG_REPORT("cell params loading started");
						// load data from ini structure
						cellCycleLength = 
								  (int) configIni["cell"]["number of frames per cell cycle"];
						chrCount = (int) configIni["cell"]["chromosome count"];

						//resize the vectors in advance to avoid their incremental increasing, which is slow
						//(and copies the early dots over and over again... which breaks fluency of IDs :-)
						chrCentres.reserve(chrCount);
						//
						// this way we create continuous ascending sequence of unique IDs
						for (size_t i=0; i<chrCount; i++)
							 chrCentres.push_back(Dot());

						chrSpreads = std::vector<float>(chrCount, 0.0f);
						chrDensities = std::vector<float>(chrCount, 0.0f);
						
						durationOfG1Phase = configIni["cell"]["duration of G1 phase"];
						durationOfSPhase = configIni["cell"]["duration of S phase"];
						durationOfG2Phase = configIni["cell"]["duration of G2 phase"]; 
						durationOfProphase = configIni["cell"]["duration of prophase"];
						durationOfMetaphase = configIni["cell"]["duration of metaphase"];
						durationOfAnaphase = configIni["cell"]["duration of anaphase"];
						durationOfTelophase = configIni["cell"]["duration of telophase"];
						durationOfCytokinesis = configIni["cell"]["duration of cytokinesis"];
						coverage = configIni["cell"]["coverage"];
						cellDiameter = configIni["cell"]["cell diameter"];
						nucleolusDiameter = configIni["cell"]["nucleolus diameter"];
						cellMagnitudeOfMovementPerFrame = 
								  configIni["cell"]["cell magnitude of movement per frame"];
						cometCellMagnitudeOfMovementPerFrame =
								  configIni["cell"]["comet cell magnitude of movement per frame"];
						cellNonRigidDeformation =
								  configIni["cell"]["cell nonrigid deformation"];
						cellNonRigidStrongDeformation =
								  configIni["cell"]["cell nonrigid strong deformation"];
						cellSparseNonRigidDeformations = 
						  (strcmp(configIni
									 ["cell"]
									 ["cell sparse nonrigid deformations"],"true") == 0) ?
						  true : false;
						cellLookDistance = configIni["cell"]["cell look distance"];

						DEBUG_REPORT("cell params loaded");


						//ID
						ID=GetNewCellID<MV>();

						//Non-rigid deformation stuff
						scmPnHints.MakeRoom(0,0,0);

						//set up "strong" deformation, if it is not forbidden:
						if (cellNonRigidStrongDeformation > 0.f) {
							//the "strong" deformation will occur during the initial G2 phase
							//note: cell starts its life at the beginning of G2
							float PnStrongInitDelay=cellCycleLength*durationOfG2Phase/100.f;

							if (configIni["testing"].present("strong deformation delay"))
							{
								REPORT("TESTING MODE: enforcing average strong deformation delay to "
									<< (int)configIni["testing"]["strong deformation delay"] << " frames.");
								PnStrongInitDelay=(float)configIni["testing"]["strong deformation delay"];
							}

							scmPnNextStrongUsage=timePoint
								+(size_t)std::max(
								  GetRandomGauss(PnStrongInitDelay,PnStrongInitDelay/4),
								  1.f);
							DEBUG_REPORT("first stronger non-rigid will occur at frame " << scmPnNextStrongUsage);
						} else {
							//hopefully value big enough...
							scmPnNextStrongUsage=1000000000;
							DEBUG_REPORT("stronger non-rigid is disabled");
						}

						//Rigid motion stuff
						scmLastRotationAngle=0.f;
						scmLastTranslationVector=i3d::Vector3d<float>(0.f,0.f,0.f);

						//the cell and dots are generated with the functions
						//GenerateMaskInG2Phase() and GenerateDotDistributionInG2Phase()

						REPORT("new cell created with ID=" << ID << " and timePoint=" << timePoint);

						scheduler.tracker[ID] = TrackRecord<MV>(birthTimePoint, INT_MAX, parentID);

			  			// The noFramesPerCellCycle should slightly vary between cells to simulate
			  			//  non-uniformity of cells in population.
						cellCycleLength = (size_t) floorf(GetRandomGauss(cellCycleLength, 
																						 0.17f*cellCycleLength));
						REPORT("new cell has cycle length " << cellCycleLength << " frames");
					}

			 /// destructor
			 ~Cell() 
			 {
				  if (centrosomeA) delete centrosomeA;
				  if (centrosomeB) delete centrosomeB;

			 	  if (duplicatedCell1) delete duplicatedCell1;
			 	  if (duplicatedCell2) delete duplicatedCell2;
				  
				  scheduler.tracker[ID].toTimeStamp = timePoint;
			 };

			 /// initial generation of cells (when the system starts)
			 void GenerateMaskInG2Phase();

			 /**
			  * This function takes two times (inital time of fluorophore
			  * molecule and the current time point) and computes the decay
			  * cause by photobleaching
			  */
			 float GetBleachFactor(size_t initialTime, size_t currentTime);

			 /**
			  * initial copy of cell from given scene mask (when the system starts)
			  *
			  * The \e cellMask may contain (usually contains) more cell masks,
			  * the \e templateID instructs the function which mask to choose.
			  *
			  * \param[in] cellMask		image with cell masks
			  * \param[in] templateID	choose a mask with this ID
			  */
			 void ReadMaskInG2Phase(const i3d::Image3d<MV> &cellMask,
			 								const MV templateID);

			 /// initial generation of cell (when the system starts)
			 void GenerateDotDistributionInG2Phase();

			 /// perform one atomic phase of cell cycle
			 void DoNextPhase(void);

			 /// perform one atomic phase of cell cycle
			 void DoProphase(const size_t noFrames);

			 /// perform one atomic phase of cell cycle
			 void DoMetaphase(const size_t noFrames);

			 /// perform one atomic phase of cell cycle
			 void DoAnaphase(const size_t noFrames);

			 /// perform one atomic phase of cell cycle
			 void DoTelophase(const size_t noFrames);

			 /// perform one atomic phase of cell cycle
			 void DoCytokinesis(const size_t noFrames);

			 /**
			  * perform one atomic phase of cell cycle
			  *
			  * Since this phase spans over many frames, given
			  * in \e noFrames, it is executed in a from
			  * of several subsequent calls, each of which
			  * must prepare the given interval of total frame
			  * budget. The interval bounds are inclusive.
			  *
			  * \param[in] noFrames		total frame budget for this phase
			  * \param[in] fromFrames	begining of the currently processed portion
			  * \param[in] toFrames		end of the currently processed portion
			  */
			 void DoG1Phase(const size_t noFrames,
			 		const size_t fromFrame,
			 		const size_t toFrame);

			 /*
			  * perform one atomic phase of cell cycle
			  *
			  * See Cell::DoG1Phase() for further explanation.
			  */
			 void DoSPhase(const size_t noFrames,
			 	       const size_t fromFrame,
				       const size_t toFrame);

			 /// perform one atomic phase of cell cycle
			 void DoG2Phase(const size_t noFrames);

			 /// get identifier
			 MV GetID() const { return ID; };

			 /// get timePoint
			 size_t GetTimePoint() const { return timePoint; };

			 /// set phase of the cell 
			 void SetPhase(const ListOfPhases &phase) { currentPhase = phase; };

			 /// show phase of the cell 
			 ListOfPhases GetCurrentPhase() const { return currentPhase; };

			 /// show the expected phase of the cell
			 ListOfPhases GetNextPhase() const;

			 /**
			  * Find out (without generating any cell) how any frames
			  * are needed in the provided phase based on the concrete
			  * value of this->cellCycleLength. Different instances may
			  * return slightly different values for the same phases as
			  * the this->cellCycleLength is slightly randomized from
			  * the Scheduler::framesPerCycle.
			  *
			  * \param[in] phase		the phase whose length is questioned
			  */
			 int GetPhaseFrameBudget(const ListOfPhases &phase);

			 /**
			  * extends (prolong) the comming phase by \e noFrames frames
			  *
			  * At the very begining when cell is in the 'newBorn' phase,
			  * the next phase (G2) will \b take \b exactly \e noFrames frames.
			  */
			 void SetDelay(size_t noFrames) { delay = noFrames; REPORT("delay: " << delay); };

			 /// returns cell centre position in microns
			 i3d::Vector3d<float> GetCellCentrePosition(void) const { return scmCellBPCentre; };

			 /**
			  * the cell is asked to become comet towards given boundary \e dir
			  *
			  * For details about cell comets, see docs of the StateOfComet type.
			  */
			 void BecomeComet(const TypeOfComet dir) { scmCometType=dir; scmCometState=hesitating; };

			 /// returns comet type
			 StateOfComet GetCometState(void) const { return scmCometState; };

			 /**
			  * SOFA: initial export
			  */
			 void SOFA_InitialExport(void);

			 /**
			  * SOFA: next import (for regular imports during simulation)
			  */
			 void SOFA_NextImport(const size_t T);

  private:
			 /// structure loaded external ini file
			 const IniHandler &configIni;
			 
			 /// my identifier
			 MV ID;

			 /// identifier of my parent; zero value means no parent
			 MV parentID;

			 /// position of centrosomes
			 Dot *centrosomeA, *centrosomeB;

			 /// my scene context
			 Scheduler<MV, PV> &scheduler;

			 /// how long should it take me to complete one cell cycle
			 size_t cellCycleLength;

			 /// so far the last finished time point in the evolution of the cell
			 size_t timePoint;

			 /// information about the currently finished phase of cell cycle
			 ListOfPhases currentPhase;

			 //
			 // DOTS/MOLECULES STUFF
			 //

			 /// number of chromosomes
			 size_t chrCount;

			 /**
			  * number of fluorophore molecules (signals) forming the chromosome;
			  * it must always hold: chrCount * chrDots == chrDotList.size()
			  */
			 size_t chrDots;

			 /// list of positions of all fluorophore molecules forming the chromosome
			 std::vector<Molecule> chrDotList;

			 /// list of positions of all chromosome centres (centre of mass) 
			 std::vector<Dot> chrCentres;

			 /**
			  * deviation of fluophore molecules in the neighbourhood 
			  * of one chromosome centre
			  */
			 std::vector<float> chrSpreads; 

			 /**
			  * density in the vicinity of one chromosome centre
			  *
			  * It should be proportional to the number of chromosome molecules
			  * present in a small volume centered at the respective chromosome centre.
			  */
			 std::vector<float> chrDensities;

			 /// relative ratios (=percentage) of lengths of cell phases
			 float durationOfG1Phase,
					 durationOfSPhase,
					 durationOfG2Phase,
					 durationOfProphase, 
					 durationOfMetaphase,
					 durationOfAnaphase,
					 durationOfTelophase,
					 durationOfCytokinesis;

			 /// amount of fluorophore molecules filling the nucleus interior (in percents)
			 float coverage;

			 /// diameter of this cell (in microns)
			 float cellDiameter;

			 /// diameter of nucleus of this cell (in microns)
			 float nucleolusDiameter;

			 /// how far a cell can normally move between frames (in microns)
			 float cellMagnitudeOfMovementPerFrame;

			 /**
			  * How far a cell can normally move between frames (in microns)
			  * if the cell is cometing. Refer to the type StateOfComet for
			  * details about cometing.
			  */
			 float cometCellMagnitudeOfMovementPerFrame;

			 ///how much a cell maximally locally deform between frames (in microns)
			 float cellNonRigidDeformation;

			 /**
			  * How much a cell _occasionally_, more distinguished, locally deform
			  * between frames (in microns)?
			  */
			 float cellNonRigidStrongDeformation;

			 /**
			  * Shall the non-rigid deformation happen after every frame (when false)
			  * or every 2nd frame (when true)?
			  */
			 bool cellSparseNonRigidDeformations;

			 /// how far a cell investigates its surrounding when looking for a "right" move?
			 float cellLookDistance;

#ifdef ENABLE_NUCLEOLI
			 /**
			  * Create the mask of one nucleolus within 
			  * the given mask of cell nucleus
			  *
			  * \param[in,out] nucleusMask			input mask
			  * \param[in] nucleolusSize		diameter of nucleolus (in microns)
			  * \param[out] nucleolusMask	generated mask of nucleolus	
			  */
			 void GenerateNucleolus(i3d::Image3d<bool> &nucleusMask,
											float nucleolusSize,
											i3d::Image3d<bool> &nucleolusMask);
#endif

			/**
			 * Fills in the output list of dots Cell::chrDotList according to the distribution file \e mask.
			 * The number of dots is given as the number of pixels/voxels in the mask image times the
			 * \e density divided by 100%. The parameter \e density is given as percentage allowing the user
			 * to tune the density of generated dots.
			 *
			 * Dots in one dot sub-sequence will be overlaing. One have to do several iterations of Brownian
			 * motion to spread the dots around all over the \e maskImage.
			 *
			 * The function also updates the Cell::chrCentres and zeros the Cell::chrSpreads.
			 *
			 * The \e mask is treated as a binary image.
			 *
			 * \param[in] mask			input binary mask image
			 * \param[in] density		percentage of how many molecules should be emitted
			 */
			 void ChrInitialDistribution(const i3d::Image3d<bool> &mask, const float density);

			 /**
			  * Updates Cell:chrCentres and Cell:chrSpreads respecting the most
			  * recent status of Cell::chrDotList. For each chromosome, firstly,
			  * geometric centres are computed and, secondly, distances of individual
			  * molecules from the centre are sorted such that given \e percentil can
			  * be stored in the Cell::chrSpreads.
			  * 
			  * The function also updates Cell:chrDensities respecting the most recent status
			  * of Cell::chrDotList. It currently calculates the number of chromosome
			  * molecules that are not further than 0.2 mu from respective chromocentre.
			  *
			  * \param[in] percentil	percentil to be used, should be within [0,1] interval
			  */
			 void ChrUpdateStats(const float percentil=0.90);

			 /// Calculates centre of mass (in contrast to a geometric centre).
			 void ChrGetCentreOfMass(i3d::Vector3d<float>& centre);

			 /// Calculates centre of low density (aka centre of 1/mass)
			 void ChrGetCentreOfLowDensity(i3d::Vector3d<float>& centre);

			 /**
			  * Reports current micron positions of all Cell:chrCentres with Cell::chrSpreads
			  * in microns, and Cell::chrDensities in molecules per unit micron volume.
			  */
			 void ChrReportStats(void);

			 /// Reports current micron differences between closests chromocentres.
			 void ChrReportClosests(void);

			 /**
			  * Move chromosome with specified \e chrID (all its molecules) by the vector
			  * \e shift but keep molecules within the \e mask. Uses mask image of the
			  * template type MV.
			  */
			 void ChrMoveByVector(const size_t chrID, 
										 i3d::Vector3d<float> const &shift,
										 i3d::Image3d<MV> const &mask, 
										 i3d::Image3d<float>* &dmOfBackground,
										 const MV value);

			 /**
			  * Move chromosome with specified \e chrID (all its molecules) by the vector
			  * \e shift but keep molecules within the \e mask. Uses binary (bool) mask.
			  */
			 void ChrMoveByVectorBM(const size_t chrID, 
											i3d::Vector3d<float> const &shift,
											i3d::Image3d<bool> const &mask, 
											i3d::Image3d<float>* &dmOfBackground,
											const bool value=true);

			 /**
			  * Perform movement of molecules belonging to chromosome specified by \e chrID
			  * while considering the \e mask. The magnitude of performed movement is controlled
			  * with the parameter \e step. Uses mask image of the template type MV.
			  */
			 void ChrMoveWithBrown(const size_t chrID, 
										  const i3d::Vector3d<float> step,
										  i3d::Image3d<MV> const &mask, 
										  i3d::Image3d<float>* &dmOfBackground,
										  const MV value);

			 /// wrapper for low level function
			 void ChrMoveWithBrown(const size_t chrID, 
										  const float step,
										  i3d::Image3d<MV> const &mask, 
										  i3d::Image3d<float>* &dmOfBackground,
										  const MV value)
			 {
				  ChrMoveWithBrown(chrID, 
										 i3d::Vector3d<float>(step, step, step),
										 mask,
										 dmOfBackground,
										 value);
			 }

			 /**
			  * Perform movement of molecules belonging to chromosome specified by \e chrID
			  * while considering the \e mask. The magnitude of performed movement is controlled
			  * with the parameter \e step. Uses binary (bool) mask.
			  */
			 void ChrMoveWithBrownBM(const size_t chrID, 
											 const i3d::Vector3d<float> step,
											 i3d::Image3d<bool> const &mask, 
											 i3d::Image3d<float>* &dmOfBackground,
											 const bool value=true);

			 /// wrapper for low level function
			 void ChrMoveWithBrownBM(const size_t chrID, 
											 const float step,
											 i3d::Image3d<bool> const &mask, 
											 i3d::Image3d<float>* &dmOfBackground,
											 const bool value=true)
			 {
				  ChrMoveWithBrownBM(chrID,
											i3d::Vector3d<float>(step, step, step),
											mask,
											dmOfBackground,
											value);
			 }

			 /**
			  * Perform gathering of molecules belonging to chromosome specified by \e chrID
			  * within the given \e mask. The magnitude of performed movement is controlled
			  * with the parameter \e step. Uses mask image of the template type MV.
			  */
			 void ChrMoveWithGravity(const size_t chrID, 
											 const float step,
											 i3d::Image3d<MV> const &mask, 
											 i3d::Image3d<float>* &dmOfBackground,
											 const MV value);

			 /**
			  * Perform gathering of molecules belonging to chromosome specified by \e chrID
			  * within the given \e mask. The magnitude of performed movement is controlled
			  * with the parameter \e step. Uses binary (bool) mask.
			  */
			 void ChrMoveWithGravityBM(const size_t chrID, 
												const float step,
												i3d::Image3d<bool> const &mask, 
												i3d::Image3d<float>* &dmOfBackground,
												const bool value=true);

			 /**
			  * Perform movement of all dots using optical flow \e FF but keep the dots
			  * within the \e mask. Uses mask image of the template type MV.
			  */
			 void ChrMoveByFlow(FlowField<float> const &FF,
									  i3d::Image3d<MV> const &mask, 
									  i3d::Image3d<float>* &dmOfBackground,
									  const MV value);
			 /**
			  * Perform movement of dots specified by \e chrID using optical flow \e FF
			  * but keep the dots within the \e mask. Uses mask image of the template 
			  * type MV.
			  */
			 void ChrMoveByFlow(const size_t chrID,
									  FlowField<float> const &FF,
									  i3d::Image3d<MV> const &mask, 
									  i3d::Image3d<float>* &dmOfBackground,
									  const MV value);

			 /**
			  * Perform movement of all dots using optical flow \e FF but keep the dots
			  * within the \e mask. Uses binary (bool) mask.
			  */
			 void ChrMoveByFlowBM(FlowField<float> const &FF,
										 i3d::Image3d<bool> const &mask, 
										 i3d::Image3d<float>* &dmOfBackground,
										 const bool value=true);


			 /**
			  * Perform movement of both centrosomes (if exist) using the flow field \e FF
			  * and keep them within the \e mask.
			  *
			  * If \e doCorrection is false, the params \e dmOfBackground
			  * and \e value are ignored completely.
			  */
			 void ChrCentrosomesMoveByFlow(FlowField<float> const &FF,
									  i3d::Image3d<MV> const &mask, 
									  i3d::Image3d<float>* &dmOfBackground,
									  const MV value, const bool doCorrection=true);
			 /**
			  * Perform movement of both centrosomes (if exist) using the flow field \e FF
			  * and keep them within the \e mask. Uses binary (bool) mask.
			  *
			  * If \e doCorrection is false, the params \e dmOfBackground
			  * and \e value are ignored completely.
			  */
			 void ChrCentrosomesMoveByFlowBM(FlowField<float> const &FF,
										 i3d::Image3d<bool> const &mask, 
										 i3d::Image3d<float>* &dmOfBackground,
										 const bool value=true, const bool doCorrection=true);

			 /**
			  * Process the \e chrDotList and draw the dots into the output \e phantoms image.
			  * The molecules are, however, placed into their positions updated according
			  * to the input vector flow field \e FF. It is assumed that molecules are within
			  * the cell mask and, therefore, it is not tested again.
			  *
			  * A molecule is drawn by actually increasing intensity level of a respectitive
			  * pixel by one.
			  *
			  * \param[in,out] phantoms	phantom image into which place the molecules
			  * \param[in] FF					flow field to (temporarily) update molecule coordinates
			  *
			  * \note If the macro GTGEN_WITH_CHRCENTRESINPHANTHOMS is enabled/defined, the
			  * function additionally increases level of pixels at positions \e Cell::chrCentres
			  * by std::numeric_limits<PV>::max()/2 in order to "highlight" chromosome centres.
			  */
			 void ChrRenderIntoPhantoms(i3d::Image3d<PV> &phantoms,FlowField<float> const &FF);

			 /**
			  * Process the \e chrDotList and draw the dots into the output \e phantoms image.
			  * It is assumed that molecules are within the cell mask and, therefore, it is not
			  * tested again.
			  *
			  * A molecule is drawn by actually increasing intensity level of a respectitive
			  * pixel by one.
			  *
			  * \param[in,out] phantoms	phantom image into which place the molecules
			  *
			  * \note If the macro GTGEN_WITH_CHRCENTRESINPHANTHOMS is enabled/defined, the
			  * function additionally increases level of pixels at positions \e Cell::chrCentres
			  * by std::numeric_limits<PV>::max()/2 in order to "highlight" chromosome centres.
			  */
			 void ChrRenderIntoPhantoms(i3d::Image3d<PV> &phantoms);

			 /**
			  * Process the \e chrDotList and draw the dots into the output \e territories image.
			  * The molecules are, however, placed into their positions updated according
			  * to the input vector flow field \e FF. It is assumed that molecules are within
			  * the cell mask and, therefore, it is not tested again.
			  *
			  * A territory is drawn by setting value of the respectitive pixel to
			  * the number of chromosome that this molecule represents. Note that the cell
			  * has \e Cell::chrCount chromosomes each of which consisting of \e Cell::chrDots
			  * molecules.
			  *
			  * \param[in,out] territories	territory image into which draw 
			  * \param[in] FF						flow field to (temporarily) update molecule coordinates
			  */
			 void ChrRenderIntoTerritories(i3d::Image3d<PV> &territories,FlowField<float> const &FF);

			 /**
			  * Process the \e chrDotList and draw the dots into the output \e territories image.
			  * It is assumed that molecules are within the cell mask and, therefore, it is not
			  * tested again.
			  *
			  * A territory is drawn by setting value of the respectitive pixel to
			  * the number of chromosome that this molecule represents. Note that the cell
			  * has \e Cell::chrCount chromosomes each of which consisting of \e Cell::chrDots
			  * molecules.
			  *
			  * \param[in,out] territories	territory image into which draw 
			  */
			 void ChrRenderIntoTerritories(i3d::Image3d<PV> &territories);

			 //
			 // HELPER PIXEL LISTS REPRESENTING MASKS OF THE CELL
			 // and
			 // SCM (GLOBAL FLOW) MOTION STUFF
			 //
			 // LISTS: 

			 /**
			  * list of positions (in microns with respect to the scene) that represent
			  * current boundary pixels of the cell in the Scheduler::sceneMasks
			  *
			  * This list should be synchronized after every single frame is generated,
			  * that is, the synchronization must occur even during the processing of any
			  * cell cycle phase function (e.g., Cell::DoProphase() ).
			  *
			  * This list is ment for keeping the mask of the cell "digital" (as any
			  * transformation of mask tends to smooth mask boundaries, making it to look
			  * "analog"-like ;-). The list also enables to deal with the global (floating)
			  * cell movement because it compactly represents the cell within
			  * the Scheduler::sceneMasks.
			  *
			  * This list must never be empty.
			  *
			  * The list logically consists of two parts: the list of, so called, outer boundary
			  * points and the list of inner boundary points (points are represented with their vector
			  * positions). The number of outer boundary points is stored in Cell::scmCellOuterBPNumber.
			  * See the ResetBoundaryPoints() and RenderBPListIntoMask() functions to learn why is that.
			  */
			 std::vector< i3d::Vector3d<float> /**/> scmCellBPList;

			 /// the number of outer (see ResetBoundaryPoints()) boundary points in the Cell::scmCellBPList
			 size_t scmCellOuterBPNumber;

			 /**
			  * geometric centre position (in microns with respect to the scene) of the
			  * positions in Cell:scmCellBPCentre
			  */
			 i3d::Vector3d<float> scmCellBPCentre;

			 /**
			  * vector along the major axis of the cell, so called the polarity of the cell
			  */
			 i3d::Vector3d<float> scmCellPolarityVector;

			 /**
			  * list of positions (in microns with respect to the scene) that represent
			  * current boundary pixels of the cell nucleus, if it exists
			  *
			  * It serves the same purposes as the Cell::scmCellBPList. This one, however,
			  * may be empty (size()==0) indicating that nucleous is currently not present
			  * in the cell.
			  */
			 std::vector< i3d::Vector3d<float> /**/> scmNucleusBPList;

			 /// the number of outer (see ResetBoundaryPoints()) boundary points in the Cell::scmNucleusBPList
			 size_t scmNucleusOuterBPNumber;

			 /**
			  * geometric centre position (in microns with respect to the scene) of the
			  * positions in Cell:scmNucleusBPList
			  */
			 i3d::Vector3d<float> scmNucleusBPCentre;

#ifdef ENABLE_NUCLEOLI
			 /**
			  * list of positions (in microns with respect to the scene) that represent
			  * current boundary pixels of the cell nucleolus, if it exists
			  *
			  * It serves the same purposes as the Cell::scmCellBPList. This one, however,
			  * may be empty (size()==0) indicating that nucleolus is currently not present
			  * in the cell.
			  */
			 std::vector< i3d::Vector3d<float> /**/> scmNucleoli1BPList;

			 /// the number of outer (see ResetBoundaryPoints()) boundary points in the Cell::scmNucleoli1BPList
			 size_t scmNucleoli1OuterBPNumber;

			 /**
			  * geometric centre position (in microns with respect to the scene) of the
			  * positions in Cell:scmNucleoli1BPList
			  */
			 i3d::Vector3d<float> scmNucleoli1BPCentre;

			 /**
			  * list of positions (in microns with respect to the scene) that represent
			  * current boundary pixels of the cell nucleolus, if it exists
			  *
			  * It serves the same purposes as the Cell::scmCellBPList. This one, however,
			  * may be empty (size()==0) indicating that nucleolus is currently not present
			  * in the cell.
			  */
			 std::vector< i3d::Vector3d<float> /**/> scmNucleoli2BPList;

			 /// the number of outer (see ResetBoundaryPoints()) boundary points in the Cell::scmNucleoli2BPList
			 size_t scmNucleoli2OuterBPNumber;

			 /**
			  * geometric centre position (in microns with respect to the scene) of the
			  * positions in Cell:scmNucleoli2BPList
			  */
			 i3d::Vector3d<float> scmNucleoli2BPCentre;
#endif

			 /**
			  * the structures defined in newly created daughter cells
			  * in the mother cell during telophase
			  */
			 typedef struct 
			 {
				  // cell membrane
			 	  std::vector< i3d::Vector3d<float> /**/> scmCellBPList;
				  size_t  scmCellOuterBPNumber;
				  i3d::Vector3d<float> scmCellBPCentre;

				  // nucleus
				  std::vector< i3d::Vector3d<float> /**/> scmNucleusBPList;
				  size_t scmNucleusOuterBPNumber;
				  i3d::Vector3d<float> scmNucleusBPCentre;

#ifdef ENABLE_NUCLEOLI
				  // nucleolus (1)
				  std::vector< i3d::Vector3d<float> /**/> scmNucleoli1BPList;
				  size_t scmNucleoli1OuterBPNumber;
				  i3d::Vector3d<float> scmNucleoli1BPCentre;

				  // nucleolus (2)
				  std::vector< i3d::Vector3d<float> /**/> scmNucleoli2BPList;
				  size_t scmNucleoli2OuterBPNumber;
				  i3d::Vector3d<float> scmNucleoli2BPCentre;
#endif
			 } NewCell;

			 NewCell *duplicatedCell1, *duplicatedCell2;

			 /*
			  * by how many frames extend the comming cell phase except for
			  * when the cell is in the 'newBorn' phase, in which case the
			  * coming phase (G2) takes exactly the \e delay frames
			  */
			 size_t delay;

			 /**
			  * By the end of Cytokinesis phase, there actually already exists
			  * two daughter cells both still driven by their mother (this cell).
			  * It is so in order to enforce smooth finish of the cytokinesis process.
			  *
			  * This function merges both cell outer boundary lists, which are stored
			  * within the Cell::NewCell structures, into this->scmCellBPListl so that
			  * the Cell::ScmUniversalMovement() can be used as usual. Also the
			  * scmCellBPCentre is modified appropriately.
			  */
			 void ScmMergeCellBPLists(void);

			 /**
			  * Removes the mask of the cell from the given input \e mask image. That is,
			  * all pixels in \e mask with intensity of Cell::ID are set to zero.
			  */
			 void ScmRemoveCellFromMask(i3d::Image3d<MV> &mask);

			 /**
			  * Fills in the \e mask image using the list of boundary points Cell::scmCellBPList,
			  * which are drawn into the image using the nearest neighborhood pixel, and using the
			  * central point Cell:scmCellBPCentre, which is used to seed a flood fill routine.
			  * In fact, the RenderBPListIntoMask() does the job.
			  *
			  * The \e mask image must be initialized already. It is not tested whether we are not
			  * overwritting something in the \e mask nor values are added to existing pixel values.
			  *
			  * If the cell is not in Metaphase, Anaphase, or Telophase and the macro
			  * GTGEN_WITH_NUCLEIMASKS is set, the cell nucleus should be placed into
			  * *(this->scheduler.sceneNuclei[this->timePoint+1]) as well. This is when
			  * the parameter \e Nmask should be used, it should point to the appropriate
			  * sceneNuclei.
			  *
			  * \param[in] mask	mask image into which a cell mask should be rendered
			  * \param[in] Nmask	mask image into which a nucleus mask should be rendered
			  *
			  * Default value for \e Nmask is NULL -- meaning do not render nucleus mask.
			  */
			 void ScmRenderCellIntoMask(i3d::Image3d<MV> &mask,
			 			    i3d::Image3d<MV> *Nmask=NULL);

			 /**
			  * Sets the Cell::scmCellPolarityVector according to the current state
			  * of the Cell::scmCellBPList.
			  */
			 void ScmResetCellPolarityVector(void);

			 //
			 // HELPER PIXEL LISTS REPRESENTING MASKS OF THE CELL
			 // and
			 // SCM (GLOBAL FLOW) MOTION STUFF
			 //
			 // MOTION: 

			 /// translation vector along which the cell moved last time
			 i3d::Vector3d<float> scmLastTranslationVector;

			 /// rotation angle (clockwise, in radians) by which the cell rotated last time
			 float scmLastRotationAngle;

			 /**
			  * when happened this "last time", see docs of the Cell::scmLastTranslationVector
			  * and Cell::scmLastRotationAngle; simply put: time at which cell movement happened
			  * according to the two variables
			  *
			  * This is merely a helper identicator for the ScmUniversalMovement()
			  * functions which uses it to findout whether it this function was used
			  * also for generation of the cell movement in the last but one generated frame.
			  */
			 size_t scmLastScmUsed;

			 //-------- SOFA start -------- 
			 /**
			  * The cell, whenever it is imported from the SOFA framework,
			  * it is repositioned such that the contemporary cell centre appears
			  * at Cell::SOFA_InitialPosition. The repositioning includes also
			  * rotation of the cell by Cell::SOFA_InitialRotation.
			  *
			  * The new position is called the reference position. In G2, all
			  * cumulated rigid movement of the cell is considered relative
			  * to this reference position.
			  *
			  * Given in microns and radians.
			  */
			 i3d::Vector3d<float> SOFA_InitialPosition;

			 /// here also applies the Cell::SOFA_InitialPosition docs
			 float SOFA_InitialRotation;

			 ///since-last-sync rotation further from SOFA_InitialRotation
			 float slsRotation;
			 ///since-last-sync translation further from SOFA_InitialPosition
			 i3d::Vector3d<float> slsTranslation;

			 /**
			  * The freshly imported points are first translated such that their
			  * contemporary centre appears at (0,0,0), are then rotated and
			  * shifted so that their contemporary centre arrives at the
			  * Cell::SOFA_InitialPosition. The cell gets at the reference
			  * position in this way.
			  *
			  * This is applied on all points that are handled in
			  * the Cell::SOFA_NextImport() function.
			  */
			 void SOFA_MoveImportedToReferencePosition(void);

			 /**
			  * Basically, the same as Cell::SOFA_MoveImportedToReferencePosition()
			  * but with freshly imported Cell::scmCellBPList points.
			  *
			  * The method counts on the fact that cell BPs is imported
			  * from the same file as nucleus BPs.
			  */
			 void SOFA_MoveInitialToReferencePosition(void);

			 /**
			  * This function sets up both Cell::SOFA_InitialPosition
			  * and Cell::SOFA_InitialRotation. It looks into configuration
			  * file into the [sofa] section for records such as
			  * "ID03 initial position = 10 20 30" and "ID03 initial rotation = 45",
			  * former in microns while later in degrees (!). If some of them is not
			  * found, default values are used, which is no rotation and translation
			  * relative to the position found in the SOFA import files.
			  */
			 void SOFA_InitReferencePosition(void);

			 /**
			  * Helper functions, but actually these are the workhorses for
			  * rigid movements of cells under SOFA enabled in the CMake.
			  *
			  * This one works with cell boundary points.
			  *
			  * Performs rotation by \e rotAngle (in radians) around the centre
			  * at \e preRotTrans and then shifts the cell by \e postRotTrans - \e preRotTrans
			  * (both in microns).
			  *
			  * \param[in] preRotTrans
			  * \param[in] rotAngle
			  * \param[in] postRotTrans
			  */
			 void SOFA_TransformCellBPs(const i3d::Vector3d<float> preRotTrans,
										 const float rotAngle,
										 const i3d::Vector3d<float> postRotTrans);
			 /**
			  * Same as Cell::SOFA_TransformCellBPs() except that this one
			  * deals with nucleus and nuclei boundary points.
			  */
			 void SOFA_TransformNuclStarBPs(const i3d::Vector3d<float> preRotTrans,
										 const float rotAngle,
										 const i3d::Vector3d<float> postRotTrans);
			 /**
			  * Same as Cell::SOFA_TransformCellBPs() except that this one
			  * deals with chromatin points.
			  */
			 void SOFA_TransformChromatinPs(const i3d::Vector3d<float> preRotTrans,
										 const float rotAngle,
										 const i3d::Vector3d<float> postRotTrans);
			 //-------- SOFA end -------- 

			 ///if the cell is comet, this represents its state
			 StateOfComet scmCometState;

			 /// if the cell is comet, this represents its type
			 TypeOfComet scmCometType;

			 /**
			  * if the cell is active comet (scmCometState != hesitating),
			  * this represents the 'biasing' vector, in microns
			  *
			  * For details about cell comets, see docs of the StateOfComet type.
			  */
			 i3d::Vector3d<float> scmCometVector;

			 /**
			  * encodes time-lapse boundary points deformation forces 
			  *
			  * The x-size of the image must be equal to the Cell::scmCellOuterBPNumber.
			  * A column at certain x-index describes time-lapse 'history' of forces to be
			  * applied on point Cell::scmCellBPList at the x-index.
			  * 
			  * The i3d::Image3d::offset.y to store number of next-to-be-used line.
			  *
			  * \note The \e Hints image becomes invalid whenever Cell::scmCellBPList is
			  * reinitialized!
			  */
			 i3d::Image3d<float> scmPnHints;

			 /**
			  * similarly to the scmLastScmUsed but in the future
			  *
			  * Basically, the ScmSuggestNonrigidDeformation() deforms the cell
			  * according to the constant cellNonRigidDeformation (which drives
			  * severity of the deformation) all the time but from time to time
			  * it deforms the cell more severely. This variable indicates the
			  * next time point when the severe deformation should occur again.
			  * The function ScmSuggestNonrigidDeformation() then updates it again.
			  */
			 size_t scmPnNextStrongUsage;

			 /**
			  * The function considers current scene, i.e., this->scheduler.sceneMasks[timePoint+1],
			  * and suggests some natural looking-like cell motion. The motion typically consists
			  * of translation, rotation, and some decent non-rigid deformation. When appropriate,
			  * coherency in the motion is supported by considering some scm* state variables in this class.
			  * The function updates these variables afterwards.
			  *
			  * The flow field must be initialized and allocated, that is the size, offset, and
			  * resolution must be set. The function adds the suggested flow field to the original content.
			  *
			  * The returned flow field \e FF will not lead to collision (the function tests it).
			  * The function uses the current content of the Cell::scmCellBPList for the representation
			  * of the cell. For the other cells, the sceneMasks[] image is considered.
			  *
			  * \param[in,out] FF	output flow field with suggested cell motion
			  */
			 void ScmUniversalMovement(FlowField<float> &FF);

			 /**
			  * This is a lot lighter and simplier version of the Cell::ScmUniversalMovement()
			  * function. This one considers only translational movement. Moreover, only
			  * translations in the x- and y-axes are considered, no movement along the z-axis.
			  * The vector should be a Brownian one with average magnitude around
			  * the 'cellMagnitudeOfMovementPerFrame' constant.
			  */
			 void ScmXYTranslationalMovement(FlowField<float> &FF);

			 /**
			  * Tests if the scmCellBPList after it \b would be translated with the given vector \e v
			  * is not colliding with any cell in the current scheduler.sceneMasks[this->timePoint+1].
			  *
			  * To improve time demand, only the first Cell::scmCellOuterBPNumber points is tested.
			  *
			  * \param[in] v	suggested translation vector
			  *
			  * \return Returns true if translated boundary pixels would appear on some pixel with
			  * value other than 0 and this->ID, i.e., if it appears in the mask of some other cell.
			  * It returns true also when the cell would got outside the mask image.
			  *
			  * \note The points in the scmCellBPList are not changed, this function realizes no
			  * movement at all. It only tests.
			  */
			 bool ScmNewCellPositionCollide(i3d::Vector3d<float> const &v);

			 /**
			  * Tests if the scmCellBPList after it \b would be rotated by \e angle around \e centre
			  * and than translated by vector \e v is not colliding with any cell in the current
			  * scheduler.sceneMasks[this->timePoint+1].
			  *
			  * To improve time demand, only the first Cell::scmCellOuterBPNumber points is tested.
			  *
			  * \param[in] centre	rotation centre, in microns
			  * \param[in] angle	rotation angle, in radians, clockwise direction
			  * \param[in] v	suggested translation vector in microns
			  *
			  * \return Returns true if translated boundary pixels would appear on some pixel with
			  * value other than 0 and this->ID, i.e., if it appears in the mask of some other cell.
			  * It returns true also when the cell would got outside the mask image.
			  *
			  * \note The points in the scmCellBPList are not changed, this function realizes no
			  * movement at all. It only tests.
			  */
			 bool ScmNewCellPositionCollide(i3d::Vector3d<float> const &centre, const float angle,
			 				i3d::Vector3d<float> const &v);

			 /** 
			  * Tests if the scmCellBPList after it \b would be moved according to the
			  * given flow field \e FF is not colliding with any cell in the current
			  * scheduler.sceneMasks[this->timePoint+1].
			  *
			  * To improve time demand, only the first Cell::scmCellOuterBPNumber points is tested.
			  *
			  * \param[in] FF	suggested flow field
			  *
			  * \return Returns true if moved boundary pixels would appear on some pixel with
			  * value other than 0 and this->ID, i.e., if it appears in the mask of some other cell.
			  * It returns true also when the cell would got outside the mask image.
			  *
			  * \note The points in the scmCellBPList are not changed, this function realizes no
			  * movement at all. It only tests.
			  */
			 bool ScmNewCellPositionCollide(FlowField<float> const &FF);

			 /**
			  * Returns a preference map \e MovsMask with suggestions in what directions move
			  * the cell so that the cell will head towards empty region in the current
			  * scheduler.sceneMasks situation. The Cell::scmCellBPList and Cell::scmCellOuterBPNumber
			  * are considered for current representation of a cell.
			  *
			  * This function basically extracts rather tight VOI around the cell from the
			  * sceneMasks image (tightness is controlled with the cellLookDistance constant)
			  * and prepares a binary mask of possible positions of the cell in the mask
			  * using a FFT-enabled (hence the _FT suffix) convolution as a correlation.
			  *
			  * The binary mask is distance transformed in order to turn it into a preference map
			  * from which only central portion is returned in the \e MovsMask image. In the map,
			  * the higher the value for certain direction, the wider empty region resides there.
			  * Hence, the higher the chance for a cell to escape from populated surroundings.
			  *
			  * It works fully in 3D. The returned \e MovsMask, however, will be only 3 pixels
			  * thick (in z-axis).
			  *
			  * \param[out] MovsMask	image encoding translational vectors towards lowest
			  * 				cell density region
			  */
			 void ScmSuggestTranslationsTowardsEmpty_FT(i3d::Image3d<float> &MovsMask);

			 /**
			  * Returns a preference map \e MovsMask with suggestions in what directions move
			  * the cell so that the cell will head towards empty region in the current
			  * scheduler.sceneMasks situation. The Cell::scmCellBPList and Cell::scmCellOuterBPNumber
			  * are considered for current representation of a cell.
			  *
			  * This function basically only tests (hence, _SS (SimpleSolution) suffix) several
			  * translation vectors (up to length of cellLookDistance constant) using which the
			  * cell will not collide in the current scene. This produces a binary mask.
			  *
			  * The binary mask is distance transformed in order to turn it into a preference map
			  * from which only central portion is returned in the \e MovsMask image. In the map,
			  * the higher the value for certain direction, the wider empty region resides there.
			  * Hence, the higher the chance for a cell to escape from populated surroundings.
			  *
			  * It works fully in 3D. The returned \e MovsMask, however, will be only 3 pixels
			  * thick (in z-axis).
			  *
			  * \param[out] MovsMask	image encoding translational vectors towards lowest
			  * 				cell density region
			  *
			  * \return Returns the number of discovered movements, which can be interpreted also
			  * as if it managed to find at least one possible movement. Otherwise
			  * it returns zero indicating that not only no translational movement is possible with
			  * the current shape and orientation of the cell, but also even that the current cell
			  * position is in collision (as a result of some neighboring cell moved to the same
			  * locality sooner due to scheduler planning movement of the other cell before this one)
			  */
			 int ScmSuggestTranslationsTowardsEmpty_SS(i3d::Image3d<float> &MovsMask);

			 /**
			  * Suggests translation vector \e V for the cell. The function considers,
			  * if it is present (not NULL), the preference map \e MovsMask of possible
			  * translations. It the map is present, it must not be empty.
			  *
			  * The map is then modified to accomodate for decreasing certainty of a cell
			  * to move along longer translation vectors (to simulate that a cell "sees"
			  * less reliably/more fuzzy into further distances) and for decresing preference
			  * to directions declining too much from the previously used translation
			  * vector Cell::scmLastTranslationVector (to simulate a weak coherency of cell
			  * translational movement). The scmLastTranslationVector is considered only if
			  * Cell::scmLastScmUsed equals this->timePoint. The function does not modify
			  * scmLastTranslationVector.
			  *
			  * If the number of possible translations \e availTrans stored in the
			  * preference map is less than 5, the coherency-preserving actions are
			  * not taken.
			  *
			  * \param[out] V		suggested vector afterall
			  * \param[in] MovsMask		a preference map of translation vectors
			  * \param[in] availTrans	number of translations stored in the initial \e MovsMask
			  *
			  * Default value for \e availTrans is 99999, meaning do try to preserve
			  * coherency for every \e MovsMask.
			  */
			 void ScmSuggestTranslationVector(i3d::Vector3d<float> &V,
			 				  const i3d::Image3d<float> *MovsMask=NULL,
							  const size_t availTrans=99999);

			 /**
			  * Suggests how much to rotate the cell in clockwise orientation in
			  * \e ang radians. The function considers previous rotation saved in
			  * the Cell::scmLastRotationAngle, which was applied last time in the frame
			  * Cell::scmLastScmUsed. The scmLastRotationAngle is considered only of
			  * Cell::scmLastScmUsed equals this->timePoint. Anyway, the function always
			  * updates the scmLastRotationAngle.
			  *
			  * Angle is given in radians.
			  *
			  * \param[out] ang	output suggested angle
			  */
			 void ScmSuggestRotationAngle(float &ang);

			 /**
			  * The function tries several combinations of xy-plane movements and 7-deg stepped 
			  * -35deg to +35deg rotations (also in xy-plane). The translation vectors are encoded
			  * using the xy-plane coordinates from which coordinate of image centre is subtracted.
			  * The z-axis coordinate encodes the rotation. The function first fills the preference
			  * map \e MovsMask binary, i.e. if given combination collides or not. The image is then
			  * distance transformed, which enables us to see combination that is far from colliding
			  * combinations. This is what the function returns.
			  *
			  * The function is similar to the ScmSuggestTranslationsTowardsEmpty_SS().
			  *
			  * \param[out] MovsMask	created image with the preference map 
			  *
			  * \returns It returns the number of discovered possible solutions. If it returns
			  * zero then everything is lost.
			  */
			 int ScmSuggestRigidTowardsEmpty_SS(i3d::Image3d<float> &MovsMask);

			 /**
			  * Suggests non-rigid deformation flow field.
			  *
			  * Basically, it considers the Cell::scmPnHints image whose information
			  * it converts in the output flow field \e FF. It internally manages
			  * to find out what line of the scmPnHints image was used last time.
			  *
			  * If the currently prepared time point equals to the Cell::scmPnNextStrongUsage,
			  * the values currently read out from the Cell::scmPnHints and "re-stretched"
			  * to cellNonRigidStrongDeformation interval to simulate a more severe non-rigid
			  * deformation of the cell. The function then sets some new future time point
			  * to the Cell::scmPnNextStrongUsage.
			  *
			  * \param[out] FF	non-rigid deformation output flow field
			  */
			 void ScmSuggestNonrigidDeformation(FlowField<float> &FF);

			 /**
			  * Creates area where cell can live
			  *
			  * \param[in] mask	cell mask (binary image)
			  * \param[out] domain	provided space, where cell can move, rotate, etc
			  * \param[in] nFrames	number of frames needed for this phase
			  */
			 void ShowDomainForThisPhase(const i3d::Image3d<bool> &mask,
												 i3d::Image3d<bool> &domain,
												 size_t noFrames);

			 /**
			  * Reinitialize the distribution of chromocenters while keeping the distribution
			  * of individual chromosome territories
			  *
			  * \param[in] maskNucleus	nucleus mask (indexed image)
			  * \param[in,out] dmOfBackground	an image where the pixel intensity
			  * 		defines the distance of this pixel to the nearest foreground object
			  * \param[in] value		the value filling the nucleus interior
			  * 		(excluding the nucleoli)
			  */
			 void ChrRepairDistribution(const i3d::Image3d<MV> &maskNucleus,
												 i3d::Image3d<float>* &dmOfBackground,
												 const MV value = MV(1));

			 /**
			  * Reinitialize the distribution of chromocenters while keeping the distribution
			  * of individual chromosome territories. The selected chromocenters are
			  * forced to be reinitialized, while the otehr are left unchagned.
			  *
			  * \param[in] maskNucleus	nucleus mask (indexed image)
			  * \param[in] overcowded		vector of points that belong (true) / do not belong 
			  * 		(false) to the overcrowded area
			  * \param[in,out] dmOfBackground	an image where the pixel intensity
			  * 		defines the distance of this pixel to the nearest foreground object
			  * \param[in] value		the value filling the nucleus interior
			  * 		(excluding the nucleoli)
			  */
			 void ChrRepairDistrLocally(const i3d::Image3d<MV> &maskNucleus,
												 const std::vector<bool> &overcrowded,
												 i3d::Image3d<float>* &dmOfBackground,
												 const MV value = MV(1)); 
			 
			 /**
			  * Reinitialize the distribution of chromocenters while keeping the distribution
			  * of individual chromosome territories. The shift of chromosomes is not absolute.
			  * It is weighted according to the density (internal variable of class 'cell')
			  * in which the inspected chromocenter occurs.
			  * The chromocenters in high density region moves very fast.
			  * The chromocenters in low density regions are almost fixed in their position.
			  *
			  * \param[in] maskNucleus	nucleus mask (indexed image)
			  * \param[in,out] dmOfBackground	an image where the pixel intensity
			  * 		defines the distance of this pixel to the nearest foreground object
			  * \param[in] value		the value filling the nucleus interior
			  * 		(excluding the nucleoli)
			  */
			 void ChrRepairDistrWeighted(const i3d::Image3d<MV> &maskNucleus,
												  i3d::Image3d<float>* &dmOfBackground,
												  const MV value = MV(1));

			 /**
			  * A function responsible for initial distribution of chromatin
			  * chains within the cell nucleus
			  *
			  * \param[in] chrID number of chromosome
			  * \param[in] step step size of random walk algorithm (microns)
			  * \param[in] radius max allowed radius of area covered by 
			  * 		random walk 
			  * \param[in] tolerance the fuzziness of radius
			  * \param[in] mask nucleus mask (indexex/bool image)
			  * \param[in,out] dmOfBackground	an image where the pixel intensity
			  * 		defines the distance of this pixel to the nearest 
			  * 		foreground object
			  * \param[in] value the value of index in the indexed image 
			  * 		than we are interested in
			  */
			 template <class T> 
						void ChrRandomWalk(const size_t chrID,
												 float step,
												 float radius,
												 float tolerance,
												 i3d::Image3d<T> const &mask,
												 i3d::Image3d<float>* &dmOfBackground,
												 const T value);
};

//---------------------------------------------------------------
/**
 * Calculates SVD from the true-valued voxels in the \e cellMask
 * and returns the eigen vector associated with the largest eigen value.
 * The output vector \e polVec should then (hopefully) tell the major
 * axis of the mask/cell. Also the geometrical \e centre is reported.
 *
 * \param[in] cellMask	input mask image
 * \param[out] polVec	the output polarity vector of unit length
 * \param[out] centre	the output centre position in microns
 */
void GetCellPolarityAndCentreVector(const i3d::Image3d<bool> &cellMask,
												i3d::Vector3d<float> &polVec,
												i3d::Vector3d<float> &centre);

//---------------------------------------------------------------
/**
 * A function generating two independent centrosomes in the given
 * cell mask.
 *
 * \param[in] cellMask	input image mask
 * \param[out] centrosomeA	first centrosome position
 * \param[out] centrosomeB second centrosome position
 */
void GenerateCentrosomes(const i3d::Image3d<bool> &cellMask,
								 i3d::Vector3d<float> &centrosomeA,
								 i3d::Vector3d<float> &centrosomeB);

//-------------------------------------------------------------------
/**
 * A function expectes two lists of Dots understood as input list
 * and output list. The function solves the min assignment problem
 * between these to lists. Finall the sequence of moving Dots from
 * the inital state (input list) to the final state (output list)
 * is generated. Number of seqeunce steps is the third parameter 
 * of the function.
 *
 * \param[in]	chromocenters	input list
 * \param[in]	chromocentersAligned	output list
 * \param[in]	numberOfSteps	length of generated sequence
 * \param[out]	movementOfChromocenters	output sequence of moving Dots
 */
void GenerateMovementOfChromocenters
	(const std::vector< Dot > &chromocenters,
	 const std::vector< Dot > &chromocentersAligned,
	 size_t numberOfSteps,
	 std::vector < std::vector<Dot> > &movementOfChromocenters);

//----------------------------------------------------------------------
/** A function that generates required number of points into
 * given mask.
 *
 * \param[in]	mask	given mask
 * \param[in]	count	number of points
 * \param[out]	positions	array of newly generated points
 * \param[in] label label of mask to be used
 */
template <class T>
void GenerateRandomPositions(const i3d::Image3d<T> &mask,
									  const size_t count,
									  std::vector<Dot>& positions,
									  const T label = T(1));

//---------------------------------------------------------------
/** A function that take tow 3d points (centrosomes), generates
 * corresponding metaphase plate a splits the image according
 * to this plate.
 *
 * \param[in] cellMask input image mask
 * \param[in] centrosomeA first centrosome position
 * \param[in] centrosomeB second centrosome position
 * \param[out] leftMask one half of the orignal image
 * \param[out] rightMask one half of the original image
 */
//----------------------------------------------------------------------
void SplitMaskIntoTwoHalves(const i3d::Image3d<bool> &cellMask,
									 i3d::Image3d<bool> &leftMask,
									 i3d::Image3d<bool> &rightMask,
									 const i3d::Vector3d<float> &centrosomeA,
									 const i3d::Vector3d<float> &centrosomeB);

//-------------------------------------------------------------------
/**
 * Resample array with nearest neighbour strategy with right alignment!
 * We need right alignment as the array contains time sequence and we are
 * interested in the most recent (the right most) states of the objects.
 *
 * Type <T> might be an image, i.e. the upsampling will replicate some images,
 * while downsampling deletes some images.
 *
 * \param[in,out] array resampled array
 * \param[in] samples required number of samples
 */
//-------------------------------------------------------------------
template <class T>
void ResampleArrayNN(std::vector<T> &array, size_t samples);

//-------------------------------------------------------------------
/**
 * This function sorts the second array of Dots in a way that the
 * dots in both arrays (oldDots, newDots) in corresponding
 * positions have globaly the shortest distance one to each other.
 *
 * \param[in] oldDots first array of dots
 * \param[in,out] newDots second array that should be sorted
 */
//-------------------------------------------------------------------
void AssignNearestDots(const std::vector<Dot> &oldDots,
							  std::vector<Dot> &newDots);

//-------------------------------------------------------------------
/// For storing the sequence of images			 
typedef std::vector<i3d::Image3d<bool>/**/> ArrayOfMasks;

/// for testing:
static std::map<size_t, size_t> remapped;

#endif
