/**
 * \brief TODO
 */
double
DistributionMixtureModel::getComponentProb(const std::vector<double>& instance,
        const size_t component) const {
  size_t K = this->numberOfComponents();
  if (instance.size() != 1) {
    stringstream msg;
    msg << "DistributionMixtureModel - instance must be "
        << "described by single value, but found " << instance.size();
    throw MixtureModelException(msg.str());
  }
  double val = instance[0];

  // calculate z's
  vector<double> z;
  for (size_t k=0; k<K; k++) {
    z.push_back(log(this->mixing[k]) + this->ds[k]->loglikelihood(val));
  }

  // find max z and get sum over k
  double m = *max_element(z.begin(), z.end());
  double d = 0;
  for (size_t k=0; k<K; k++) d += exp(z[k] - m);

  return exp(z[component] - m) / d;
}
Example #2
0
int main(int argc, char** argv) {
  bool usage = static_cast<bool>(pick_option(&argc, argv, "h", nullptr));
  bool bar = static_cast<bool>(pick_option(&argc, argv, "b", nullptr));
  float m = static_cast<float>(atof(pick_option(&argc, argv, "m", "nan")));
  float M = static_cast<float>(atof(pick_option(&argc, argv, "M", "nan")));
  if (usage) {
    cerr << "usage: " << argv[0] << " [mask [output]] [-m minval] " <<
        "[-M maxval] [-b]" << endl;
    return EXIT_SUCCESS;
  }

  Image mask = read_image(argc > 1 ? argv[1] : "-");
  if (std::isnan(m)) m = *min_element(mask.begin(), mask.end());
  if (std::isnan(M)) M = *max_element(mask.begin(), mask.end());

  if (mask.channels() != 1) {
    cerr << "The mask should have one channel." << endl;
    return EXIT_FAILURE;
  }

  if (m >= M) {
    cerr << "m should be smaller than M." << endl;
    return EXIT_FAILURE;
  }

  Image out = apply_colormap(mask, m, M, bar);
  save_image(out, argc > 2 ? argv[2] : "TIFF:-");

  return EXIT_SUCCESS;
}
Example #3
0
void CDrawGraph::OnPaint()
{
	CPaintDC dc(this); // device context for painting

	CConvertToSPEXDoc* pDoc = GetMyDocument();

	dc.MoveTo(0,0);
//	dc.LineTo(10,10);

	if(pDoc->fpdata.empty())
		return;

	float f1 = *min_element(pDoc->fpdata.begin(), pDoc->fpdata.end()); 
	float f2 = *max_element(pDoc->fpdata.begin(), pDoc->fpdata.end()); 
	if(f1 == f2)
		f2++;

	CRect cr;
	GetWindowRect(cr);
	float w = cr.Width();
	float h = cr.Height();

	dc.MoveTo(0,h - (pDoc->fpdata[0]-f1)/(f1-f2)*h);

	for(int i=0; i < pDoc->fpdata.size(); i++)
	{
		dc.LineTo( i*w/pDoc->fpdata.size() , (pDoc->fpdata[i]-f1)/(f2-f1)*-h +h );
	}

}
Example #4
0
    void Lock(const size_t threadNum)
    {
        choosing[threadNum] = true; 
        turn[threadNum] = *max_element(turn, turn + MAX_THREADS_COUNT) + 1; 
        choosing[threadNum] = false; 

        for (size_t i = 0; i < MAX_THREADS_COUNT; ++i)
        {
            while (choosing[i]);
            while (turn[i] != 0 && (turn[i] < turn[threadNum] || (turn[i] == turn[threadNum] && i < threadNum)));
        }
    }
/**
 * \brief log-likelihood that a given vector of observations was produced
 *        by this mixture
 * \note  we scale values in log-space to avoid an underflow
 */
double
DistributionMixtureModel::loglikelihood(const std::vector<double> &obs) const {
  size_t N = obs.size(), K = this->numberOfComponents();
  double sum = 0;
  for (size_t i=0; i<N; i++) {
    // calculate z's for this i
    vector<double> z;
    for (size_t k=0; k<K; k++) {
      double zi = log(this->mixing[k]) + this->ds[k]->loglikelihood(obs[i]);
      z.push_back(zi);
    }

    // find max z and get sum over k
    double m = *max_element(z.begin(), z.end());
    double d = 0;
    for (size_t k=0; k<K; k++) d += exp(z[k] - m);

    // add contribution from ith observation
    sum += (m + log(d));
  }

  return sum;
}
Example #6
0
MzSpectrum normalize(MzSpectrum const &mzSpectrum,
    types::intensity_t const normalizeTo) {
    
    using std::make_pair;
    using std::max_element;
    using types::intensity_t;
    using types::intensity_store_t;

    MzSpectrum normalizedSpectrum(mzSpectrum);

    intensity_t const maxInt = (max_element(mzSpectrum.begin(), 
        mzSpectrum.end(),
        smallerIntensity))->second;

    // The spectrum's max intensity 
    intensity_store_t const maxScale = normalizeTo/maxInt;
    
    for(auto &mzSpecPair : normalizedSpectrum) {
        mzSpecPair.second = mzSpecPair.second * maxScale;

    }

    return normalizedSpectrum;
}
size_t ArgMax(const VectorL<T>& v)
{
    return v.beginRow_ +
           distance(v.storage_.begin(), max_element(v.storage_.begin(), v.storage_.end()));
}
T Max(const VectorL<T>& v)
{
    return *max_element(v.storage_.begin(), v.storage_.end());
}
Example #9
0
void AnalogSnapshot::append_payload_to_envelope_levels()
{
	Envelope &e0 = _envelope_levels[0];
	uint64_t prev_length;
	EnvelopeSample *dest_ptr;

	// Expand the data buffer to fit the new samples
	prev_length = e0.length;
	e0.length = _sample_count / EnvelopeScaleFactor;

	// Break off if there are no new samples to compute
	if (e0.length == prev_length)
		return;

	reallocate_envelope(e0);

	dest_ptr = e0.samples + prev_length;

	// Iterate through the samples to populate the first level mipmap
	const float *const end_src_ptr = (float*)_data +
		e0.length * EnvelopeScaleFactor;
	for (const float *src_ptr = (float*)_data +
		prev_length * EnvelopeScaleFactor;
		src_ptr < end_src_ptr; src_ptr += EnvelopeScaleFactor)
	{
		const EnvelopeSample sub_sample = {
			*min_element(src_ptr, src_ptr + EnvelopeScaleFactor),
			*max_element(src_ptr, src_ptr + EnvelopeScaleFactor),
		};

		*dest_ptr++ = sub_sample;
	}

	// Compute higher level mipmaps
	for (unsigned int level = 1; level < ScaleStepCount; level++)
	{
		Envelope &e = _envelope_levels[level];
		const Envelope &el = _envelope_levels[level-1];

		// Expand the data buffer to fit the new samples
		prev_length = e.length;
		e.length = el.length / EnvelopeScaleFactor;

		// Break off if there are no more samples to computed
		if (e.length == prev_length)
			break;

		reallocate_envelope(e);

		// Subsample the level lower level
		const EnvelopeSample *src_ptr =
			el.samples + prev_length * EnvelopeScaleFactor;
		const EnvelopeSample *const end_dest_ptr = e.samples + e.length;
		for (dest_ptr = e.samples + prev_length;
			dest_ptr < end_dest_ptr; dest_ptr++)
		{
			const EnvelopeSample *const end_src_ptr =
				src_ptr + EnvelopeScaleFactor;

			EnvelopeSample sub_sample = *src_ptr++;
			while (src_ptr < end_src_ptr)
			{
				sub_sample.min = min(sub_sample.min, src_ptr->min);
				sub_sample.max = max(sub_sample.max, src_ptr->max);
				src_ptr++;
			}

			*dest_ptr = sub_sample;
		}
	}
}
Example #10
0
int main(int argc, char **argv)
{
    //Create a CMT object
    Config config("FAST", "BRISK","RANSAC",0.5);
    CMT cmt(config);

    //Initialization bounding box
    Rect rect;

    //Parse args
    int challenge_flag = 0;
    int loop_flag = 0;
    int verbose_flag = 0;
    int bbox_flag = 0;
    int skip_frames = 0;
    int skip_msecs = 0;
    int output_flag = 0;
    string input_path;
    string output_path;

    const int detector_cmd = 1000;
    const int descriptor_cmd = 1001;
    const int bbox_cmd = 1002;
    const int no_scale_cmd = 1003;
    const int with_rotation_cmd = 1004;
    const int skip_cmd = 1005;
    const int skip_msecs_cmd = 1006;
    const int output_file_cmd = 1007;

    struct option longopts[] =
    {
        //No-argument options
        {"challenge", no_argument, &challenge_flag, 1},
        {"loop", no_argument, &loop_flag, 1},
        {"verbose", no_argument, &verbose_flag, 1},
        {"no-scale", no_argument, 0, no_scale_cmd},
        {"with-rotation", no_argument, 0, with_rotation_cmd},
        //Argument options
        {"bbox", required_argument, 0, bbox_cmd},
        {"detector", required_argument, 0, detector_cmd},
        {"descriptor", required_argument, 0, descriptor_cmd},
        {"output-file", required_argument, 0, output_file_cmd},
        {"skip", required_argument, 0, skip_cmd},
        {"skip-msecs", required_argument, 0, skip_msecs_cmd},
        {0, 0, 0, 0}
    };

    int index = 0;
    int c;
    while((c = getopt_long(argc, argv, "v", longopts, &index)) != -1)
    {
        switch (c)
        {
            case 'v':
                verbose_flag = true;
                break;
            case bbox_cmd:
                {
                    //TODO: The following also accepts strings of the form %f,%f,%f,%fxyz...
                    string bbox_format = "%f,%f,%f,%f";
                    float x,y,w,h;
                    int ret = sscanf(optarg, bbox_format.c_str(), &x, &y, &w, &h);
                    if (ret != 4)
                    {
                        cerr << "bounding box must be given in format " << bbox_format << endl;
                        return 1;
                    }

                    bbox_flag = 1;
                    rect = Rect(x,y,w,h);
                }
                break;
            case detector_cmd:
                cmt.str_detector = optarg;
                break;
            case descriptor_cmd:
                cmt.str_descriptor = optarg;
                break;
            case output_file_cmd:
                output_path = optarg;
                output_flag = 1;
                break;
            case skip_cmd:
                {
                    int ret = sscanf(optarg, "%d", &skip_frames);
                    if (ret != 1)
                    {
                      skip_frames = 0;
                    }
                }
                break;
            case skip_msecs_cmd:
                {
                    int ret = sscanf(optarg, "%d", &skip_msecs);
                    if (ret != 1)
                    {
                      skip_msecs = 0;
                    }
                }
                break;
            case no_scale_cmd:
                cmt.consensus.estimate_scale = false;
                break;
            case with_rotation_cmd:
                cmt.consensus.estimate_rotation = true;
                break;
            case '?':
                return 1;
        }

    }

    // Can only skip frames or milliseconds, not both.
    if (skip_frames > 0 && skip_msecs > 0)
    {
      cerr << "You can only skip frames, or milliseconds, not both." << endl;
      return 1;
    }

    //One argument remains
    if (optind == argc - 1)
    {
        input_path = argv[optind];
    }

    else if (optind < argc - 1)
    {
        cerr << "Only one argument is allowed." << endl;
        return 1;
    }

    //Set up logging
    FILELog::ReportingLevel() = verbose_flag ? logDEBUG : logINFO;
    Output2FILE::Stream() = stdout; //Log to stdout

    //Challenge mode
    if (challenge_flag)
    {
        //Read list of images
        ifstream im_file("images.txt");
        vector<string> files;
        string line;
        while(getline(im_file, line ))
        {
            files.push_back(line);
        }

        //Read region
        ifstream region_file("region.txt");
        vector<float> coords = getNextLineAndSplitIntoFloats(region_file);

        if (coords.size() == 4) {
            rect = Rect(coords[0], coords[1], coords[2], coords[3]);
        }

        else if (coords.size() == 8)
        {
            //Split into x and y coordinates
            vector<float> xcoords;
            vector<float> ycoords;

            for (size_t i = 0; i < coords.size(); i++)
            {
                if (i % 2 == 0) xcoords.push_back(coords[i]);
                else ycoords.push_back(coords[i]);
            }

            float xmin = *min_element(xcoords.begin(), xcoords.end());
            float xmax = *max_element(xcoords.begin(), xcoords.end());
            float ymin = *min_element(ycoords.begin(), ycoords.end());
            float ymax = *max_element(ycoords.begin(), ycoords.end());

            rect = Rect(xmin, ymin, xmax-xmin, ymax-ymin);
            cout << "Found bounding box" << xmin << " " << ymin << " " <<  xmax-xmin << " " << ymax-ymin << endl;
        }

        else {
            cerr << "Invalid Bounding box format" << endl;
            return 0;
        }

        //Read first image
        Mat im0 = imread(files[0]);
        Mat im0_gray;
        cvtColor(im0, im0_gray, CV_BGR2GRAY);

        //Initialize cmt
        cmt.initialize(im0_gray, rect);

        //Write init region to output file
        ofstream output_file("output.txt");
        output_file << rect.x << ',' << rect.y << ',' << rect.width << ',' << rect.height << std::endl;

        //Process images, write output to file
        for (size_t i = 1; i < files.size(); i++)
        {
            FILE_LOG(logINFO) << "Processing frame " << i << "/" << files.size();
            Mat im = imread(files[i]);
            Mat im_gray;
            cvtColor(im, im_gray, CV_BGR2GRAY);
            cmt.processFrame(im_gray);
            if (verbose_flag)
            {
                display(im, cmt);
            }
            rect = cmt.bb_rot.boundingRect();
            output_file << rect.x << ',' << rect.y << ',' << rect.width << ',' << rect.height << std::endl;
        }

        output_file.close();

        return 0;
    }

    //Normal mode

    //Create window
    namedWindow(WIN_NAME);

    VideoCapture cap;

    bool show_preview = true;

    //If no input was specified
    if (input_path.length() == 0)
    {
        cap.open(0); //Open default camera device
    }

    //Else open the video specified by input_path
    else
    {
        cap.open(input_path);

        if (skip_frames > 0)
        {
          cap.set(CV_CAP_PROP_POS_FRAMES, skip_frames);
        }

        if (skip_msecs > 0)
        {
          cap.set(CV_CAP_PROP_POS_MSEC, skip_msecs);

          // Now which frame are we on?
          skip_frames = (int) cap.get(CV_CAP_PROP_POS_FRAMES);
        }

        show_preview = false;
    }

    //If it doesn't work, stop
    if(!cap.isOpened())
    {
        cerr << "Unable to open video capture." << endl;
        return -1;
    }

    //Show preview until key is pressed
    while (show_preview)
    {
        Mat preview;
        cap >> preview;

        screenLog(preview, "Press a key to start selecting an object.");
        imshow(WIN_NAME, preview);

        char k = waitKey(10);
        if (k != -1) {
            show_preview = false;
        }
    }

    //Get initial image
    Mat im0;
    cap >> im0;

    //If no bounding was specified, get it from user
    if (!bbox_flag)
    {
        rect = getRect(im0, WIN_NAME);
    }

    FILE_LOG(logINFO) << "Using " << rect.x << "," << rect.y << "," << rect.width << "," << rect.height
        << " as initial bounding box.";

    //Convert im0 to grayscale
    Mat im0_gray;
    if (im0.channels() > 1) {
        cvtColor(im0, im0_gray, CV_BGR2GRAY);
    } else {
        im0_gray = im0;
    }

    //Initialize CMT
    cmt.initialize(im0_gray, rect);

    int frame = skip_frames;

    //Open output file.
    ofstream output_file;

    if (output_flag)
    {
        int msecs = (int) cap.get(CV_CAP_PROP_POS_MSEC);

        output_file.open(output_path.c_str());
        output_file << OUT_FILE_COL_HEADERS << endl;
        output_file << frame << "," << msecs << ",";
        output_file << cmt.points_active.size() << ",";
        output_file << write_rotated_rect(cmt.bb_rot) << endl;
    }

    //Main loop
    while (true)
    {
        frame++;

        Mat im;

        //If loop flag is set, reuse initial image (for debugging purposes)
        if (loop_flag) im0.copyTo(im);
        else cap >> im; //Else use next image in stream

        if (im.empty()) break; //Exit at end of video stream

        Mat im_gray;
        if (im.channels() > 1) {
            cvtColor(im, im_gray, CV_BGR2GRAY);
        } else {
            im_gray = im;
        }

        //Let CMT process the frame
        cmt.processFrame(im_gray);

        //Output.
        if (output_flag)
        {
            int msecs = (int) cap.get(CV_CAP_PROP_POS_MSEC);
            output_file << frame << "," << msecs << ",";
            output_file << cmt.points_active.size() << ",";
            output_file << write_rotated_rect(cmt.bb_rot) << endl;
        }
        else
        {
            //TODO: Provide meaningful output
            FILE_LOG(logINFO) << "#" << frame << " active: " << cmt.points_active.size();
        }

        //Display image and then quit if requested.
        char key = display(im, cmt);
        if(key == 'q') break;
    }

    //Close output file.
    if (output_flag) output_file.close();

    return 0;
}
Example #11
0
void PathInfo::calcLBAndNextEdge(const AdjMat& c) 
{
	// information about the useable matrix
	struct MatrixInfo info(c.size);

	// calculate the initial LB from edges already included
	// also, set any edges that would create a subtour as infinite
	this->setAvailAndLB(c, info);

	// reduce the matrix, increment the lower bound from the reduction
	this->lowerBound += info.reduceMatrix(c, *this);

	// find all the zeros in the matrix
	vector<Edge> zeros;
	for(unsigned int i = 0; i < c.size; ++i)
	{
		if(info.rowAvail[i])
		{
			for(unsigned int j = 0; j < c.size; ++j)
			{
				if(info.colAvail[j] && !this->isInfinite(i, j))
				{
					if(c(i, j) - info.rowReds[i] - 
						info.colReds[j] == 0)
					{
						zeros.push_back({ i, j });
					}
				}
			}
		}
	}
	
	
	// get a penalty associated with each zero
	vector<unsigned int> penalties(zeros.size());
	unsigned int counter = 0;
	for(const Edge zero : zeros)
	{
		bool foundMinCol = false;
		bool foundMinRow = false;
		unsigned int minCol = infinity;
		unsigned int minRow = infinity;

		// check for largest distance in row
		for(unsigned int i = 0; i < c.size; ++i)
		{
			// INVARIANT: column is always available
			if(info.rowAvail[i] && 
				!this->isInfinite(i, zero.second) && 
				i != zero.first && c(i, zero.second) - 
				info.rowReds[i] - info.colReds[zero.second] < minRow)
			{
				minRow = c(i, zero.second) - info.rowReds[i] - 
					info.colReds[zero.second];
				foundMinRow = true;
			}
		}

		// check largest distance in col
		for(unsigned int j = 0; j < c.size; ++j)
		{
			// INVARIANT: row is always available
			if(info.colAvail[j] && 
				!this->isInfinite(zero.first, j) && 
				zero.second != j && c(zero.first, j) - 
				info.rowReds[zero.first] - info.colReds[j] < minCol)
			{
				minCol = c(zero.first, j) - info.rowReds[zero.first] -
					info.colReds[j];
				foundMinCol = true;
			}
		}

		// 3 cases
		// 1. base case
		if(c.size - this->include.size() == 2)
		{
			penalties[counter++] = infinity;
			break;
		}

		// 2. case when excluding the node creates a disconnected graph
		else if(foundMinCol != foundMinRow && 
			c.size - this->include.size() != 2)
		{
			// we must choose this edge and cannot branch
			this->next = zero;
			this->bothBranches = false;
			return;
		}
		// 3. normal case, there is both an include and exclude branch
		else
		{
			penalties[counter++] = minRow + minCol;
		}
	}

	// set the next edge as the zero with the highest penalty
	auto maxPenaltyIt = max_element(penalties.begin(), penalties.end());
	unsigned int index = maxPenaltyIt - penalties.begin();

	// handle the base case
	if(c.size - this->include.size() == 2)
	{
		this->addInclude(zeros[index]);
		info.rowAvail[zeros[index].first] = false;
		info.colAvail[zeros[index].second] = false;
		unsigned int row = 0;
		unsigned int col = 0;

		// INVARIANT: only one valid edge left, find it
		for(unsigned int i = 0; i < info.rowAvail.size(); ++i)
		{
			if(info.rowAvail[i])
			{
				row = i;
				break;
			}
		}
		for(unsigned int j = 0; j < info.colAvail.size(); ++j)
		{
			if(info.colAvail[j])
			{
				col = j;
				break;
			}
		}
		this->addInclude({ row, col });
		// recalculate LB, the length of the TSP tour
		this->setAvailAndLB(c, info);
		throw NoNextEdge();
	}

	// for any other case, set the next edge to branch on
	// and set the flag that calculations have been completed
	this->next = zeros[index];
	this->foundLBAndEdge = true;
} 
Example #12
0
//! Execute random walk simulator application mode.
void executeRandomWalkSimulator( 
    const std::string databasePath, 
    const tudat::input_output::parsed_data_vector_utilities::ParsedDataVectorPtr parsedData )
{
    ///////////////////////////////////////////////////////////////////////////

    // Declare using-statements.

    using std::advance;
    using std::cerr;
    using std::cout;
    using std::endl;
    using std::max_element;
    using std::min_element;
    using std::numeric_limits;
    using std::ofstream;
    using std::ostringstream;
    using std::setprecision;
    using std::string;

    using boost::iequals;
    using namespace boost::filesystem; 
    using boost::make_shared;   

    using namespace assist::astrodynamics;
    using namespace assist::basics;
    using namespace assist::mathematics;

    using namespace tudat::basic_astrodynamics::orbital_element_conversions;
    using namespace tudat::basic_mathematics::mathematical_constants;
    using namespace tudat::input_output;
    using namespace tudat::input_output::dictionary;
    using namespace tudat::statistics;

    using namespace stomi::astrodynamics;
    using namespace stomi::database;
    using namespace stomi::input_output;

    ///////////////////////////////////////////////////////////////////////////

    // Extract input parameters.

    // Get dictionary.
    const DictionaryPointer dictionary = getRandomWalkSimulatorDictionary( );

    // Print database path to console.
    cout << "Database                                                  " 
         << databasePath << endl;

    // Extract required parameters. 
    const string randomWalkRunName = extractParameterValue< string >(
                parsedData->begin( ), parsedData->end( ), 
                findEntry( dictionary, "RANDOMWALKRUN" ) );
    cout << "Random walk run                                           "  
         << randomWalkRunName << endl;  

    // Extract optional parameters. 
    const int numberOfThreads = extractParameterValue< int >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "NUMBEROFTHREADS" ), 1 );
    cout << "Number of threads                                         " 
         << numberOfThreads << endl;  

    const string outputMode = extractParameterValue< string >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "OUTPUTMODE" ), "DATABASE" );
    cout << "Output mode                                               "
         << outputMode << endl;          

    const string fileOutputDirectory = extractParameterValue< string >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "FILEOUTPUTDIRECTORY" ), "" ) + "/";
    cout << "File output directory                                     "
         << fileOutputDirectory << endl;

    const string randomWalkSimulations = extractParameterValue< string >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "RANDOMWALKSIMULATIONS" ), "ALL" );
    cout << "Random walk simulations                                   "
         << randomWalkSimulations << endl;         

    const string randomWalkRunTableName = extractParameterValue< string >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "RANDOMWALKRUNTABLENAME" ), "random_walk_run" );
    cout << "Random walk run table                                     " 
         << randomWalkRunTableName << endl;

    const string randomWalkInputTableName = extractParameterValue< string >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "RANDOMWALKINPUTTABLENAME" ), "random_walk_input" );
    cout << "Random walk input table                                   " 
         << randomWalkInputTableName << endl;         

    const string randomWalkPerturberTableName = extractParameterValue< string >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "RANDOMWALKPERTURBERTABLENAME" ),
                "random_walk_perturbers" );
    cout << "Random walk perturber table                               "
         << randomWalkPerturberTableName << endl;

    const string randomWalkOutputTableName = extractParameterValue< string >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "RANDOMWALKOUTPUTTABLENAME" ), "random_walk_output" );
    cout << "Random walk output table                                  "
              << randomWalkOutputTableName << endl; 

    const string testParticleCaseTableName = extractParameterValue< string >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "TESTPARTICLECASETABLENAME" ), "test_particle_case" );
    cout << "Test particle case table                                  "
         << testParticleCaseTableName << endl;                

    const string testParticleKickTableName = extractParameterValue< string >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "TESTPARTICLEKICKTABLENAME" ), "test_particle_kicks" );
    cout << "Test particle kick table                                  "
         << testParticleKickTableName << endl;          

    // Retrieve and store random walk run data from database.
    RandomWalkRunPointer randomWalkRun;

    // Random walk run data is extracted in local scope from the database, with overwritten
    // parameters extracted from the input file, to ensure that none of these parameters are used
    // globally elsewhere in this file.
    {
        const RandomWalkRunPointer retrievedRandomWalkRun = getRandomWalkRun( 
            databasePath, randomWalkRunName, randomWalkRunTableName ); 

        const double perturberRingNumberDensity = extractParameterValue< double >(
                    parsedData->begin( ), parsedData->end( ),
                    findEntry( dictionary, "PERTURBERRINGNUMBERDENSITY" ),
                    retrievedRandomWalkRun->perturberRingNumberDensity );    
        cout << "Perturber ring number density                             " 
             << perturberRingNumberDensity << " perturbers per R_Hill" << endl;

        const double perturberRingMass = extractParameterValue< double >(
                    parsedData->begin( ), parsedData->end( ),
                    findEntry( dictionary, "PERTURBERRINGMASS" ),
                    retrievedRandomWalkRun->perturberRingMass );    
        cout << "Perturber ring mass                                       "
             << perturberRingMass << " M_PerturbedBody" << endl;              

        const double observationPeriod = extractParameterValue< double >(
                    parsedData->begin( ), parsedData->end( ),
                    findEntry( dictionary, "OBSERVATIONPERIOD" ),
                    retrievedRandomWalkRun->observationPeriod, &convertJulianYearsToSeconds );
        cout << "Observation period                                        "
             << convertSecondsToJulianYears( observationPeriod ) << " yrs" << endl; 

        const unsigned int numberOfEpochWindows = extractParameterValue< unsigned int >(
                    parsedData->begin( ), parsedData->end( ),
                    findEntry( dictionary, "NUMBEROFEPOCHWINDOWS" ),
                    retrievedRandomWalkRun->numberOfEpochWindows );    
        cout << "Number of epoch windows                                   "
             << numberOfEpochWindows << endl;                                                 

        const double epochWindowSize = extractParameterValue< double >(
                    parsedData->begin( ), parsedData->end( ),
                    findEntry( dictionary, "EPOCHWINDOWSIZE" ),
                    retrievedRandomWalkRun->epochWindowSize, &convertJulianDaysToSeconds  );
        cout << "Epoch window size                                         "
             << convertSecondsToJulianDays( epochWindowSize ) << " days" << endl;     

        // Store random walk run data with possible overwritten data.
        randomWalkRun = make_shared< RandomWalkRun >( 
            retrievedRandomWalkRun->randomWalkRunId, randomWalkRunName, 
            retrievedRandomWalkRun->testParticleCaseId, perturberRingNumberDensity,
            perturberRingMass, observationPeriod, numberOfEpochWindows, epochWindowSize );
    }

    // Check that all required parameters have been set.
    checkRequiredParameters( dictionary );

    ///////////////////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////////////////

    // Fetch test particle case and random walk input data from database.

    cout << endl;
    cout << "****************************************************************************" << endl;
    cout << "Database operations" << endl;
    cout << "****************************************************************************" << endl;
    cout << endl;

    // Generate output message.
    cout << "Fetching test particle case data from database ..." << endl;      

    // Retrieve and store test particle case data.
    const TestParticleCasePointer testParticleCaseData = getTestParticleCase( 
        databasePath, randomWalkRun->testParticleCaseId, testParticleCaseTableName ); 

    // Generate output message to indicate that test particle case data was fetched successfully.
    cout << "Test particle case data fetched successfully from database!" << endl;   

    // Generate output message.
    cout << "Fetching random walk input data from database ..." << endl;   

    // Check if all incomplete random walk simulations are to be executed and fetch the random
    // walk input table, else only fetch the requested random walk simulation IDs.
    RandomWalkInputTable randomWalkInputTable;

    if ( iequals( randomWalkSimulations, "ALL" )  )
    {
        cout << "Fetching all incomplete random walk Monte Carlo runs ..." << endl;    

        // Get entire random walk input table from database.
        randomWalkInputTable = getCompleteRandomWalkInputTable(
                    databasePath, randomWalkRun->randomWalkRunId, 
                    randomWalkInputTableName, randomWalkPerturberTableName );
    }

    else
    {
        cout << "Fetching all requested random walk Monte Carlo runs ..." << endl;    

        // Get selected random walk input table from database.
        randomWalkInputTable = getSelectedRandomWalkInputTable(
                    databasePath, randomWalkRun->randomWalkRunId, randomWalkSimulations, 
                    randomWalkInputTableName, randomWalkPerturberTableName );
    }

    // Generate output message to indicate that the input table was fetched successfully.
    cout << "Random walk input data (" << randomWalkInputTable.size( )
         << " rows) fetched successfully from database!" << endl;    

    ///////////////////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////////////////

    // Compute derived parameters.

    cout << endl;
    cout << "****************************************************************************" << endl;
    cout << "Derived parameters" << endl;
    cout << "****************************************************************************" << endl;
    cout << endl;

    // Compute epoch window spacing [s].
    const double epochWindowSpacing 
        = randomWalkRun->observationPeriod / ( randomWalkRun->numberOfEpochWindows - 1 );
    cout << "Epoch window spacing                                      " 
         << convertSecondsToJulianDays( epochWindowSpacing ) << " days" << endl;

    // Compute mass of perturbed body [kg].
    const double perturbedBodyMass = computeMassOfSphere(
                testParticleCaseData->perturbedBodyRadius, 
                testParticleCaseData->perturbedBodyBulkDensity );
    cout << "Perturbed body mass                                       " 
         << perturbedBodyMass << " kg" << endl;

    // Compute perturbed body's gravitational parameter [m^3 s^-2].
    const double perturbedBodyGravitationalParameter
            = computeGravitationalParameter( perturbedBodyMass );
    cout << "Perturbed body gravitational parameter                    " 
         << perturbedBodyGravitationalParameter << " m^3 s^-2" << endl;
         
    // Compute perturber population using density and semi-major axis distribution limits.
    // Note, in the floor() function, adding 0.5 is a workaround for the fact that there is no
    // round() function in C++03 (it is available in C++11).
    ConvertHillRadiiToMeters convertHillRadiiToMeters( 
        testParticleCaseData->centralBodyGravitationalParameter, 
        perturbedBodyGravitationalParameter, 
        testParticleCaseData->perturbedBodyStateInKeplerianElementsAtT0( semiMajorAxisIndex ) );
    const double perturberRingNumberDensityInMeters 
        = randomWalkRun->perturberRingNumberDensity / convertHillRadiiToMeters( 1.0 );
    const unsigned int perturberPopulation = std::floor( 
        2.0 * testParticleCaseData->semiMajorAxisDistributionLimit 
        * perturberRingNumberDensityInMeters + 0.5 );
    cout << "Perturber population                                      " 
         << perturberPopulation << endl;

    // Compute perturber mass ratio.
    // Note, for the random walk simulations, the mass ratio is equal for all perturbers.
    const double perturberMassRatio = randomWalkRun->perturberRingMass / perturberPopulation;
    cout << "Perturber mass ratio                                      "
         << perturberMassRatio << endl;

    ///////////////////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////////////////

    // Execute Monte Carlo simulation.
    cout << endl;
    cout << "****************************************************************************" << endl;
    cout << "Simulation loop" << endl;
    cout << "****************************************************************************" << endl;
    cout << endl;

    // Execute simulation loop.
    cout << "Starting simulation loop ... " << endl;
    cout << randomWalkInputTable.size( ) << " random walk simulations queued for execution ..." 
         << endl;
    cout << endl;    

    // Loop over input table.
#pragma omp parallel for num_threads( numberOfThreads )
    for ( unsigned int i = 0; i < randomWalkInputTable.size( ); i++ )
    {
        ///////////////////////////////////////////////////////////////////////////

        // Set input table iterator and emit output message.

        // Set input table iterator for current simulation wrt to start of input table and counter.
        RandomWalkInputTable::iterator iteratorRandomWalkInputTable 
            = randomWalkInputTable.begin( );
        advance( iteratorRandomWalkInputTable, i );

        // Emit output message.
#pragma omp critical( outputToConsole )
        {
            cout << "Random walk simulation " 
                 << iteratorRandomWalkInputTable->randomWalkSimulationId 
                 << " on thread " << omp_get_thread_num( ) + 1 << " / " 
                 << omp_get_num_threads( ) << endl;
        }

        ///////////////////////////////////////////////////////////////////////////

        ///////////////////////////////////////////////////////////////////////////

        // Fetch test particle kick table based on test particle simulation IDs for random walk 
        // simulation.
        TestParticleKickTable testParticleKickTable;
#pragma omp critical( databaseOperations )
        {        
            testParticleKickTable = getTestParticleKickTable( 
                databasePath, testParticleCaseData->randomWalkSimulationPeriod,
                iteratorRandomWalkInputTable->testParticleSimulationIds, 
                testParticleKickTableName );
        }

        // Check if output mode is set to "FILE".
        // If so, open output file and write test particle kick table data.
        // Check if the output directory exists: if not, create it.
        if ( iequals( outputMode, "FILE" ) )
        {
            // Check if output directory exists.
            if ( !exists( fileOutputDirectory ) )
            {
               cerr << "Directory does not exist. Will be created." << endl;
               create_directories( fileOutputDirectory );
            }        

            // Declare file handler.
            ofstream testParticleKickTableFile;

            // Set up and write file header to file.
            ostringstream testParticleKickTableFilename;
            testParticleKickTableFilename << fileOutputDirectory << "randomWalkSimulation" 
                                          << iteratorRandomWalkInputTable->randomWalkSimulationId 
                                          << "_testParticleKickTable.csv";    

            testParticleKickTableFile.open( testParticleKickTableFilename.str( ).c_str( ) );

            testParticleKickTableFile 
                << "kickId,simulationId,conjunctionEpoch,conjunctionDistance,"
                << "preConjunctionEpoch,preConjunctionDistance,"
                << "preConjunctionSemiMajorAxis,preConjunctionEccentricity,"
                << "preConjunctionInclination,preConjunctionArgumentOfPeriapsis,"
                << "preConjunctionLongitudeOfAscendingNode,preConjunctionTrueAnomaly"
                << "postConjunctionEpoch,postConjunctionDistance,"
                << "postConjunctionSemiMajorAxis,postConjunctionEccentricity,"
                << "postConjunctionInclination,postConjunctionArgumentOfPeriapsis,"
                << "postConjunctionLongitudeOfAscendingNode,postConjunctionTrueAnomaly"
                << endl;
            testParticleKickTableFile 
                << "# [-],[-],[s],[m],[s],[m],[m],[-],[rad],[rad],[rad],[rad]," 
                << "[s],[m],[m],[-],[rad],[rad],[rad],[rad]" << endl;       

            // Write test particle kick table to file.
            for ( TestParticleKickTable::iterator iteratorTestParticleKicks 
                    = testParticleKickTable.begin( );
                  iteratorTestParticleKicks != testParticleKickTable.end( );
                  iteratorTestParticleKicks++ )
            {
                testParticleKickTableFile 
                    << iteratorTestParticleKicks->testParticleKickId << "," 
                    << iteratorTestParticleKicks->testParticleSimulationId << ",";
                testParticleKickTableFile
                    << setprecision( numeric_limits< double >::digits10 )
                    << iteratorTestParticleKicks->conjunctionEpoch << ","
                    << iteratorTestParticleKicks->conjunctionDistance << ","
                    << iteratorTestParticleKicks->preConjunctionEpoch << ","
                    << iteratorTestParticleKicks->preConjunctionDistance << ","
                    << iteratorTestParticleKicks->preConjunctionStateInKeplerianElements( 
                        semiMajorAxisIndex ) << ","
                    << iteratorTestParticleKicks->preConjunctionStateInKeplerianElements( 
                        eccentricityIndex ) << ","
                    << iteratorTestParticleKicks->preConjunctionStateInKeplerianElements( 
                        inclinationIndex ) << ","
                    << iteratorTestParticleKicks->preConjunctionStateInKeplerianElements( 
                        argumentOfPeriapsisIndex ) << ","
                    << iteratorTestParticleKicks->preConjunctionStateInKeplerianElements( 
                        longitudeOfAscendingNodeIndex ) << ","
                    << iteratorTestParticleKicks->preConjunctionStateInKeplerianElements( 
                        trueAnomalyIndex ) << ","
                    << iteratorTestParticleKicks->postConjunctionEpoch << ","
                    << iteratorTestParticleKicks->postConjunctionDistance << ","
                    << iteratorTestParticleKicks->postConjunctionStateInKeplerianElements( 
                        semiMajorAxisIndex ) << ","
                    << iteratorTestParticleKicks->postConjunctionStateInKeplerianElements( 
                        eccentricityIndex ) << ","
                    << iteratorTestParticleKicks->postConjunctionStateInKeplerianElements( 
                        inclinationIndex ) << ","
                    << iteratorTestParticleKicks->postConjunctionStateInKeplerianElements( 
                        argumentOfPeriapsisIndex ) << ","
                    << iteratorTestParticleKicks->postConjunctionStateInKeplerianElements( 
                        longitudeOfAscendingNodeIndex ) << ","
                    << iteratorTestParticleKicks->postConjunctionStateInKeplerianElements( 
                        trueAnomalyIndex ) << endl;
            }                 

            // Close file handler.
            testParticleKickTableFile.close( );
        }

        ///////////////////////////////////////////////////////////////////////////

        ///////////////////////////////////////////////////////////////////////////

        // Execute random walk simulation.

        // Declare perturbed body propagation history. This stores the propagation history of the
        // action variables only (semi-major axis, eccentricity, inclination).
        DoubleKeyVector3dValueMap keplerianActionElementsHistory;

        // Set perturbed body initial state (actions) in Keplerian elements.
        keplerianActionElementsHistory[ 0.0 ]
                = testParticleCaseData->perturbedBodyStateInKeplerianElementsAtT0.segment( 0, 3 );

        // Declare iterator to previous state in Keplerian elements.
        DoubleKeyVector3dValueMap::iterator iteratorPreviousKeplerianElements
                = keplerianActionElementsHistory.begin( );

        // Loop through aggregate kick table and execute kicks on perturbed body. 
        for ( TestParticleKickTable::iterator iteratorKickTable = testParticleKickTable.begin( );
              iteratorKickTable != testParticleKickTable.end( ); iteratorKickTable++ )
        {
            // Execute kick and store results in propagation history.
            keplerianActionElementsHistory[ iteratorKickTable->conjunctionEpoch ]
                    = executeKick( iteratorPreviousKeplerianElements->second,
                                   iteratorKickTable, perturberMassRatio );

            advance( iteratorPreviousKeplerianElements, 1 );
        }

        // Check if output mode is set to "FILE".
        // If so, open output file and write header content.
        if ( iequals( outputMode, "FILE" ) )
        {
            ostringstream keplerianActionElementsFilename;
            keplerianActionElementsFilename << "randomWalkSimulation" 
                                            << iteratorRandomWalkInputTable->randomWalkSimulationId
                                            << "_keplerianActionElements.csv"; 
            
            ostringstream keplerianActionElementsFileHeader;
            keplerianActionElementsFileHeader << "epoch,semiMajorAxis,eccentricity,inclination" 
                                              << endl;
            keplerianActionElementsFileHeader << "# [s],[m],[-],[rad]" << endl;

            writeDataMapToTextFile( keplerianActionElementsHistory,
                                    keplerianActionElementsFilename.str( ),
                                    fileOutputDirectory, 
                                    keplerianActionElementsFileHeader.str( ),
                                    numeric_limits< double >::digits10, 
                                    numeric_limits< double >::digits10,
                                    "," ); 
        }        

        ///////////////////////////////////////////////////////////////////////////

        ///////////////////////////////////////////////////////////////////////////

        // Compute average longitude residual and maximum longitude residual change in observation
        // period.

        // Declare average longitude residual in observation period [-].
        double averageLongitudeResidual = TUDAT_NAN;

        // Declare maximum longitude residual change in observation period [-].
        double maximumLongitudeResidualChange = TUDAT_NAN;

        // Declare map of average longitude residuals per window [rad].
        DoubleKeyDoubleValueMap averageLongitudeResiduals;

        {
            // Populate temporary map with epochs and semi-major axes.
            DoubleKeyDoubleValueMap semiMajorAxisHistory;

            for ( DoubleKeyVector3dValueMap::iterator iteratorKeplerianActionElements 
                  = keplerianActionElementsHistory.begin( );
                  iteratorKeplerianActionElements != keplerianActionElementsHistory.end( );
                  iteratorKeplerianActionElements++ )
            {
                semiMajorAxisHistory[ iteratorKeplerianActionElements->first ]
                    = iteratorKeplerianActionElements->second( semiMajorAxisIndex );
            }  

            // Compute longitude history.
            DoubleKeyDoubleValueMap longitudeHistory
                    = computeLongitudeHistory( 
                        semiMajorAxisHistory,
                        testParticleCaseData->centralBodyGravitationalParameter );      

            // Compute reduced longitude history (data is reduced to only the epoch windows).
            DoubleKeyDoubleValueMap reducedLongitudeHistory
                    = reduceLongitudeHistory( 
                        longitudeHistory, 
                        iteratorRandomWalkInputTable->observationPeriodStartEpoch,
                        epochWindowSpacing, 
                        randomWalkRun->epochWindowSize,
                        randomWalkRun->numberOfEpochWindows ); 

            // Set input data for simple linear regression.
            SimpleLinearRegression longitudeHistoryRegression( reducedLongitudeHistory );
         
            // Compute linear fit.
            longitudeHistoryRegression.computeFit( );        
                
            // Store longitude residuals history.
            DoubleKeyDoubleValueMap longitudeResidualsHistory;

            // Generate longitude history residuals by subtracting linear fit from data.
            for ( DoubleKeyDoubleValueMap::iterator iteratorReducedLongitudeHistory
                    = reducedLongitudeHistory.begin( );
                  iteratorReducedLongitudeHistory != reducedLongitudeHistory.end( );
                  iteratorReducedLongitudeHistory++ )
            {
                longitudeResidualsHistory[ iteratorReducedLongitudeHistory->first ]
                        = iteratorReducedLongitudeHistory->second
                          - longitudeHistoryRegression.getCoefficientOfConstantTerm( )
                          - longitudeHistoryRegression.getCoefficientOfLinearTerm( )
                          * iteratorReducedLongitudeHistory->first;
            }           

            // Loop over observation period and compute average longitude residuals per epoch window.
            for ( int windowNumber = 0; 
                  windowNumber < randomWalkRun->numberOfEpochWindows; 
                  windowNumber++ )
            {
                const double epochWindowCenter 
                    = iteratorRandomWalkInputTable->observationPeriodStartEpoch 
                      + windowNumber * epochWindowSpacing;

                averageLongitudeResiduals[ epochWindowCenter ] 
                    = computeStepFunctionWindowAverage( 
                        longitudeResidualsHistory, 
                        epochWindowCenter - 0.5 * randomWalkRun->epochWindowSize, 
                        epochWindowCenter + 0.5 * randomWalkRun->epochWindowSize );
            }

             // Compute average longitude residual during propagation history.
            double sumLongitudeResiduals = 0.0;

            for ( DoubleKeyDoubleValueMap::iterator iteratorAverageLongitudeResiduals 
                    = averageLongitudeResiduals.begin( );
                  iteratorAverageLongitudeResiduals != averageLongitudeResiduals.end( );
                  iteratorAverageLongitudeResiduals++ )
            {
                sumLongitudeResiduals += iteratorAverageLongitudeResiduals->second;
            }

            averageLongitudeResidual 
                = sumLongitudeResiduals / randomWalkRun->numberOfEpochWindows;

            // Compute maximum longitude residual change during propagation history.
            maximumLongitudeResidualChange 
                = ( max_element( averageLongitudeResiduals.begin( ), 
                                 averageLongitudeResiduals.end( ),
                                 CompareDoubleKeyDoubleValueMapValues( ) ) )->second
                  - ( min_element( averageLongitudeResiduals.begin( ), 
                                   averageLongitudeResiduals.end( ),
                                   CompareDoubleKeyDoubleValueMapValues( ) ) )->second;            

            // Check if output mode is set to "FILE".
            // If so, open output file and write header content.
            if ( iequals( outputMode, "FILE" ) )
            {
                ostringstream longitudeHistoryFilename;
                longitudeHistoryFilename << "randomWalkSimulation"
                                         << iteratorRandomWalkInputTable->randomWalkSimulationId
                                         << "_longitudeHistory.csv"; 
                
                ostringstream longitudeHistoryFileHeader;
                longitudeHistoryFileHeader << "epoch,longitude" << endl;
                longitudeHistoryFileHeader << "# [s],[rad]" << endl;

                writeDataMapToTextFile( longitudeHistory,
                                        longitudeHistoryFilename.str( ),
                                        fileOutputDirectory, 
                                        longitudeHistoryFileHeader.str( ),
                                        numeric_limits< double >::digits10, 
                                        numeric_limits< double >::digits10,
                                        "," );             

                ostringstream reducedLongitudeHistoryFilename;
                reducedLongitudeHistoryFilename 
                    << "randomWalkSimulation" 
                    << iteratorRandomWalkInputTable->randomWalkSimulationId
                    << "_reducedLongitudeHistory.csv"; 
                
                ostringstream reducedLongitudeHistoryFileHeader;
                reducedLongitudeHistoryFileHeader << "epoch,longitude" << endl;
                reducedLongitudeHistoryFileHeader << "# [s],[rad]" << endl;

                writeDataMapToTextFile( reducedLongitudeHistory,
                                        reducedLongitudeHistoryFilename.str( ),
                                        fileOutputDirectory, 
                                        reducedLongitudeHistoryFileHeader.str( ),
                                        numeric_limits< double >::digits10, 
                                        numeric_limits< double >::digits10,
                                        "," );            

                ostringstream longitudeResidualsFilename;
                longitudeResidualsFilename << "randomWalkSimulation"
                                           << iteratorRandomWalkInputTable->randomWalkSimulationId
                                           << "_longitudeResiduals.csv"; 
                
                ostringstream longitudeResidualsFileHeader;
                longitudeResidualsFileHeader << "epoch,longitudeResidual" << endl;
                longitudeResidualsFileHeader << "# [s],[rad]" << endl;      

                writeDataMapToTextFile( longitudeResidualsHistory,
                                        longitudeResidualsFilename.str( ),
                                        fileOutputDirectory, 
                                        longitudeResidualsFileHeader.str( ),
                                        numeric_limits< double >::digits10, 
                                        numeric_limits< double >::digits10,
                                        "," );                                                 
            }                       
        }

        ///////////////////////////////////////////////////////////////////////////        

        ///////////////////////////////////////////////////////////////////////////

        // Compute average eccentricity and maximum eccentricity change in observation window.

        // Declare average eccentricity in observation period [-].
        double averageEccentricity = TUDAT_NAN;

        // Declare maximum eccentricity change in observation period [-].
        double maximumEccentricityChange = TUDAT_NAN;

        // Declare map of average eccentricities per window [-].
        DoubleKeyDoubleValueMap averageEccentricities;

        {
            // Populate temporary map with epochs and eccentricities.
            DoubleKeyDoubleValueMap eccentricityHistory;

            for ( DoubleKeyVector3dValueMap::iterator iteratorKeplerianActionElements 
                  = keplerianActionElementsHistory.begin( );
                  iteratorKeplerianActionElements != keplerianActionElementsHistory.end( );
                  iteratorKeplerianActionElements++ )
            {
                eccentricityHistory[ iteratorKeplerianActionElements->first ]
                    = iteratorKeplerianActionElements->second( eccentricityIndex );
            }            

            // Loop over observation period and compute average eccentricities per epoch window.
            for ( int windowNumber = 0; 
                  windowNumber < randomWalkRun->numberOfEpochWindows; 
                  windowNumber++ )
            {
                const double epochWindowCenter 
                    = iteratorRandomWalkInputTable->observationPeriodStartEpoch
                      + windowNumber * epochWindowSpacing;

                averageEccentricities[ epochWindowCenter ] 
                    = computeStepFunctionWindowAverage( 
                        eccentricityHistory, 
                        epochWindowCenter - 0.5 * randomWalkRun->epochWindowSize, 
                        epochWindowCenter + 0.5 * randomWalkRun->epochWindowSize );
            }

            // Compute average eccentricity during propagation history.
            double sumEccentricities = 0.0;

            for ( DoubleKeyDoubleValueMap::iterator iteratorAverageEccentricities 
                    = averageEccentricities.begin( );
                  iteratorAverageEccentricities != averageEccentricities.end( );
                  iteratorAverageEccentricities++ )
            {
                sumEccentricities += iteratorAverageEccentricities->second;
            }

            averageEccentricity = sumEccentricities / randomWalkRun->numberOfEpochWindows;

            // Compute maximum eccentricity change during propagation history.
            maximumEccentricityChange 
                = ( max_element( averageEccentricities.begin( ), 
                                 averageEccentricities.end( ),
                                 CompareDoubleKeyDoubleValueMapValues( ) ) )->second
                  - ( min_element( averageEccentricities.begin( ), 
                                   averageEccentricities.end( ),
                                   CompareDoubleKeyDoubleValueMapValues( ) ) )->second;            
        }

        ///////////////////////////////////////////////////////////////////////////

        ///////////////////////////////////////////////////////////////////////////

        // Compute average inclination and maximum inclination change in observation window.

        // Declare average inclination in observation period [rad].
        double averageInclination = TUDAT_NAN;

        // Declare maximum inclination change in observation period [rad].
        double maximumInclinationChange = TUDAT_NAN;

        // Declare map of average inclinations per window [rad].
        DoubleKeyDoubleValueMap averageInclinations;        

        {
            // Populate temporary map with epochs and inclinations.
            DoubleKeyDoubleValueMap inclinationHistory;

            for ( DoubleKeyVector3dValueMap::iterator iteratorKeplerianActionElements 
                  = keplerianActionElementsHistory.begin( );
                  iteratorKeplerianActionElements != keplerianActionElementsHistory.end( );
                  iteratorKeplerianActionElements++ )
            {
                inclinationHistory[ iteratorKeplerianActionElements->first ]
                    = iteratorKeplerianActionElements->second( inclinationIndex );
            }            

            // Loop over observation period and compute average inclinations per epoch window.
            for ( int windowNumber = 0; 
                  windowNumber < randomWalkRun->numberOfEpochWindows; 
                  windowNumber++ )
            {
                const double epochWindowCenter 
                    = iteratorRandomWalkInputTable->observationPeriodStartEpoch
                      + windowNumber * epochWindowSpacing;

                averageInclinations[ epochWindowCenter ] 
                    = computeStepFunctionWindowAverage( 
                        inclinationHistory, 
                        epochWindowCenter - randomWalkRun->epochWindowSize * 0.5, 
                        epochWindowCenter + randomWalkRun->epochWindowSize * 0.5 );
            }

            // Compute average inclination during propagation history.
            double sumInclinations = 0.0;

            for ( DoubleKeyDoubleValueMap::iterator iteratorAverageInclinations 
                    = averageInclinations.begin( );
                  iteratorAverageInclinations != averageInclinations.end( );
                  iteratorAverageInclinations++ )
            {
                sumInclinations += iteratorAverageInclinations->second;
            }

            averageInclination = sumInclinations / randomWalkRun->numberOfEpochWindows;

            // Compute maximum inclination change during propagation history.
            maximumInclinationChange 
                = ( max_element( averageInclinations.begin( ), 
                                 averageInclinations.end( ),
                                 CompareDoubleKeyDoubleValueMapValues( ) ) )->second
                  - ( min_element( averageInclinations.begin( ), 
                                   averageInclinations.end( ),
                                   CompareDoubleKeyDoubleValueMapValues( ) ) )->second;        
        }

        ///////////////////////////////////////////////////////////////////////////

        ///////////////////////////////////////////////////////////////////////////

        // Write epoch-windoow average values to file.

        // Check if output mode is set to "FILE".
        // If so, open output file and write header content.
        if ( iequals( outputMode, "FILE" ) )
        {
            // Declare file handler.
            ofstream epochWindowAveragesFile;   

            ostringstream epochWindowAveragesFilename;
            epochWindowAveragesFilename << fileOutputDirectory << "randomWalkRun" 
                                        << iteratorRandomWalkInputTable->randomWalkSimulationId
                                        << "_epochWindowAverages.csv";
            
            epochWindowAveragesFile.open( epochWindowAveragesFilename.str( ).c_str( ) );

            epochWindowAveragesFile << "epoch,longitudeResidual,eccentricity,inclination" << endl;
            epochWindowAveragesFile << "# [s],[rad],[-],[rad]" << endl; 

            // Loop through epoch-window averages and write data to file.
            DoubleKeyDoubleValueMap::iterator iteratorEpochWindowAverageLongitudeResiduals
                = averageLongitudeResiduals.begin( );
            DoubleKeyDoubleValueMap::iterator iteratorEpochWindowAverageEccentricities
                = averageEccentricities.begin( );
            DoubleKeyDoubleValueMap::iterator iteratorEpochWindowAverageInclinations
                = averageInclinations.begin( );
                                                
            for ( int i = 0; i < randomWalkRun->numberOfEpochWindows; i++ )
            {
                epochWindowAveragesFile 
                    << setprecision( numeric_limits< double >::digits10 )
                    << iteratorEpochWindowAverageLongitudeResiduals->first << ","
                    << iteratorEpochWindowAverageLongitudeResiduals->second << ","
                    << iteratorEpochWindowAverageEccentricities->second << ","
                    << iteratorEpochWindowAverageInclinations->second << endl;

                iteratorEpochWindowAverageLongitudeResiduals++;    
                iteratorEpochWindowAverageEccentricities++;
                iteratorEpochWindowAverageInclinations++;
            }

            // Close file handler.
            epochWindowAveragesFile.close( );
        }        

        ///////////////////////////////////////////////////////////////////////////

        ///////////////////////////////////////////////////////////////////////////

        // Write random walk output to database. To avoid locking of the database, this section is
        // thread-critical, so will be executed one-by-one by multiple threads.

        // Check if output mode is set to "DATABASE".
        if ( iequals( outputMode, "DATABASE" ) )
        {
    #pragma omp critical( databaseOperations )
            {
                // Populate output table in database.
                populateRandomWalkOutputTable( 
                    databasePath, iteratorRandomWalkInputTable->randomWalkSimulationId,
                    averageLongitudeResidual, maximumLongitudeResidualChange,
                    averageEccentricity, maximumEccentricityChange,
                    averageInclination, maximumInclinationChange,
                    randomWalkOutputTableName, randomWalkInputTableName );
            }
        }

        /////////////////////////////////////////////////////////////////
    } // simulation for-loop

    ///////////////////////////////////////////////////////////////////
}
bool absLess(int a, int b) {
  return abs(a) < abs(b);
}



BEGIN_TEST(NonModifyingAlgorithm, MinMaxElem, @);
  deque<int> con;
  insertElements(con, 1, 10);
  insertElements(con, -5, 5);
  printContainer(con);	// con: 1 2 3 4 5 6 7 8 9 10 -5 -4 -3 -2 -1 0 1 2 3 4 5

  auto minPos = min_element(con.begin(), con.end());
  EXPECT_EQ(-5, *minPos);
  auto maxPos = max_element(con.begin(), con.end());
  EXPECT_EQ(10, *maxPos);

  auto absMinPos = min_element(con.begin(), con.end(), absLess);
  EXPECT_EQ(0, *absMinPos);
  auto absMaxPos = max_element(con.begin(), con.end(), absLess);
  EXPECT_EQ(10, *absMaxPos);
END_TEST;




BEGIN_TEST(NonModifyingAlgorithm, Find, @);
  list<int> con;
  insertElements(con, 0, 10);
  insertElements(con, 0, 5);
/**
 * \brief Given a set of observations, fit this mixture using
 *        expectation maximization
 */
void DistributionMixtureModel::estimateParamsEM(const vector<double>& obs,
                                                bool verbose) {
  bool debug = false;
  double oldLogLike = 0;
  bool first = true;
  bool done = false;
  size_t numIter = 0;
  
  size_t K = this->numberOfComponents();
  
  // only one component? easy peasy..
  if (K == 1) {
    this->ds[0]->estimateParams(obs, verbose);
    this->mixing[0] = 1;
    return;
  }

  // fail if there are more components in this mixture than there are 
  // distinct observation values -- we can't fit that!
  set<double> unique(obs.begin(), obs.end());
  if (obs.size() < this->ds.size()) {
    stringstream s;
    s << "cannot fit mixture model with " << this->ds.size()
        << " using only " << obs.size() << " data points!";
    throw MixtureModelException(s.str().c_str());
  }

  // make an initial random guess 
  for (size_t k=0; k<K; k++) this->ds[k]->randomise();

  if (verbose)
    cout << endl << "initial mixture starting point: " << this->toString()
         << endl;

  while (!done) {
    // expectation step -- compute weights given current params
    vector<vector<double> > w;
    for (size_t i = 0; i < obs.size(); i++) {
      // calculate z's for this i
      vector<double> z;
      for (size_t k = 0; k<K; k++) {
        z.push_back(log(this->mixing[k]) + this->ds[k]->loglikelihood(obs[i]));
      }

      // find max z and denominator for w
      double m = *max_element(z.begin(), z.end());
      double d = 0;
      for (size_t k=0; k<K; k++) {
        d += exp(z[k] - m);
      }
      
      // calc weights for each component
      vector<double> wi;
      for (size_t k = 0; k<K; k++) {
        wi.push_back(exp(z[k] - m) / d);
      }
      w.push_back(wi);
    }
    if (debug) {
      for (size_t k = 0; k<K; k++) {
        for (size_t i = 0; i < obs.size(); i++) {
          cout << w[i][k] << ", "
              << this->ds[k]->loglikelihood(obs[i]) << " (" << obs[i]
              << "," << this->ds[k]->getParams()[0] << ","
              << this->ds[k]->getParams()[1] << ") " << ", ";
        }
        cout << endl;
      }
    }

    // maximisation step -- update model parameters
    mixing.clear();
    for (size_t k=0; k<K; k++) {
      // update kth component 
      vector<double> wk;
      for (size_t i = 0; i < obs.size(); i++)
        wk.push_back(w[i][k]);
      this->ds[k]->estimateParams(obs, wk);
      // update mixing parameter for kth component
      double sum = 0;
      for (size_t i = 0; i < obs.size(); i++)
        sum += w[i][k];
      mixing.push_back(sum / obs.size());
    }
    if (debug)
      cout << "after maximisation step, model is: " << this->toString() << endl;

    // set a lower bound on mixing params
    for (size_t k=0; k<K; k++) {
      if (this->mixing[k] < this->mixingLowerBound)
        this->mixing[k] = this->mixingLowerBound;
    }
    double total = 0;
    for (size_t i = 0; i < this->mixing.size(); i++)
      total += this->mixing[i];
    for (size_t k = 0; k<K; k++)
      this->mixing[k] = this->mixing[k] / total;

    // finished because likelihood is stable?
    double newLogLike = this->loglikelihood(obs);
    if (verbose) {
      cout << this->toString() << endl;
      cout << "new loglike: " << newLogLike << " old loglike: " << oldLogLike
           << endl;
    }
    if ((!first) && (fabs(newLogLike - oldLogLike) < this->stoppingEM))
      done = true;
    first = false;
    oldLogLike = newLogLike;

    // finished because we're giving up?
    numIter++;
    if (numIter >= this->emMaxIter)
      done = true;
  }
}