<commit_before>#include "SpeedContest.hpp"
#include <stdlib.h>
#include <thread>
#include <math.h>
#include <mutex>
#include "../helper/Performance.hpp"
#include "../dct/Arai.hpp"
#include "../dct/DCT.hpp"

#ifdef _WIN32
#include <Windows.h>
#endif

// 1, 7, 3, 4, 5, 4, 3, 2
// one way transform gets:
// 10.253, 0.797218, -2.19761, -0.0377379, -1.76777, -2.75264, -2.53387, -1.13403

//  ---------------------------------------------------------------
// |
// |  Helper
// |
//  ---------------------------------------------------------------

float* createTestMatrix(size_t width, size_t height) {
	float *data = new float[width * height];
	for (size_t y = 0; y < height; y++) {
		for (size_t x = 0; x < width; x++) {
			data[y * width + x]= (float)((x+y*8) % 256);
		}
	}
	return data; // remember to delete[]
}

float* createOurTestMatrix(size_t w, size_t h) {
	float data[8] = {1, 7, 3, 4, 5, 4, 3, 2}; // generate our well known test matrix
	float *vls = new float[w * h];
	for (size_t y = 0; y < h; y++) {
		for (size_t x = 0; x < w; x++) {
			float &u = vls[y * w + x];
			if (y % 8 == 0) {
				u = data[x % 8];
			} else {
				if (x % 8 == 0) {
					u = data[y % 8];
				} else {
					u = 0;
				}
			}
		}
	}
	return vls;
}

void printFloatMatrix(float* &mat, size_t w, size_t h) {
	for (size_t i = 0; i < w * h; ++i) {
		if (i % (w*8) == 0) printf("\n");
		if (mat[i] < 0.0005F && mat[i] > -0.0005F) printf("%8d ", 0);
		else printf("%8.3f ", mat[i]);
		if (i % 8 == 7)   printf("   ");
		if (i % w == w-1) printf("\n");
	}
}

inline void copyArray(float* dst, float* src, size_t size) {
	memcpy(dst, src, size * sizeof(float));
//	while (size--) {
//		*(dst++) = *(src++);
//	}
}

void verify(const char* desc, float* originalMatrix, size_t width, size_t height, std::function<float*(float*)> func) {
	size_t size = width * height;
	float *vls = new float[size];
	copyArray(vls, originalMatrix, size);
	float *result = func(vls);

	printf("\n%s\n", desc);
	printFloatMatrix(result, width, height);
	printf("------------------------------------------------------------> ");

	// Check if result is correct
	bool inverseIsCorrect = true;
	float *out = new float[size];
	DCT::inverse(result, out, width, height);
	while (size--) {
		if (fabsf(originalMatrix[size] - out[size]) > 0.0005F )
			inverseIsCorrect = false;
	}
	delete [] vls;

	// Break on Error
	if (inverseIsCorrect) {
		printf("Inverse: CORRECT\n");
	} else {
		printf("Inverse: FAILED\nInverse:\n");
		printFloatMatrix(out, width, height);
		exit(EXIT_FAILURE);
	}
	delete [] out;
}

// ################################################################
// #
// #  CPU - Single Core
// #
// ################################################################

void runCPUSingleCore(float* matrix, size_t width, size_t height, double seconds) {
	size_t size = width * height;
	float* vls = new float[size];
	float* out = new float[size];

	copyArray(vls, matrix, size);
	Performance::howManyOperationsInSeconds(seconds, "Normal DCT", [&]{
		DCT::transform(vls, out, width, height);
	});
	delete [] out;

	copyArray(vls, matrix, size);
	Performance::howManyOperationsInSeconds(seconds, "Separated DCT", [&]{
		DCT::transform2(vls, width, height);
	});

	copyArray(vls, matrix, size);
	Performance::howManyOperationsInSeconds(seconds, "Arai inline transpose", [&]{
		Arai::transformInlineTranspose(vls, width, height);
	});

	copyArray(vls, matrix, size);
	Performance::howManyOperationsInSeconds(seconds, "Arai DCT", [&]{
		Arai::transform(vls, width, height);
	});

	delete [] vls;
}

// ################################################################
// #
// #  CPU - Multi Core
// #
// ################################################################

void testMultiThread(const char* desc, float* matrix, size_t width, size_t height, double seconds, std::function<void(float*,float*)> func) {
	static const unsigned int hwThreadCount = std::thread::hardware_concurrency();
	unsigned long* counters = new unsigned long[hwThreadCount];
	std::thread* threads = new std::thread[hwThreadCount];

	// Prepare an array of input images to have coalesced memory access
	// This wouldn't be necessary in a real life situation, since input
	// should be in general different images with different memory locations
	float** multiSrc = new float*[hwThreadCount];
	float** multiDst = new float*[hwThreadCount];
	unsigned int u = hwThreadCount;
	while (u--) {
		multiSrc[u] = new float[width * height];
		multiDst[u] = new float[width * height];
		copyArray(multiSrc[u], matrix, width * height);
	}

	// Start as many threads as supported
	unsigned int i = hwThreadCount;
	while (i--) {
		threads[i] = std::thread([multiSrc, multiDst, seconds, i, func, &counters, width, height]{
			Timer inner;
			unsigned long innerCounter = 0;
			while (inner.elapsed() < seconds) {
				func(multiSrc[i], multiDst[i]);
				++innerCounter;
			}
			counters[i] = innerCounter;
		});
	}
	Timer t;
	unsigned long totalIterations = 0;
	i = hwThreadCount;
	while (i--) {
		threads[i].join();
		totalIterations += counters[i];
	}

	double time = t.elapsed();
	PerformancePrintOperationsPerSecond(desc, time, totalIterations);

	// Cleanup
	u = hwThreadCount;
	while (u--) {
		delete [] multiSrc[u];
		delete [] multiDst[u];
	}
	delete [] counters;
	delete [] threads;
}

#ifdef _WIN32
CRITICAL_SECTION g_critSec;
#else
std::mutex lock;
#endif

unsigned long threadSyncedCounter = 0;
inline bool multiThreadShouldProcess(unsigned long val) {
#ifdef _WIN32
	EnterCriticalSection( &g_critSec );
#else
	lock.lock();
#endif
	if (val > threadSyncedCounter) {
#ifdef _WIN32
		LeaveCriticalSection( &g_critSec );
#else
		lock.unlock();
#endif
		return false;
	} else {
		threadSyncedCounter = val + 1;
#ifdef _WIN32
		LeaveCriticalSection( &g_critSec );
#else
		lock.unlock();
#endif
		return true;
	}
}

void testMultiThread2(const char* desc, float* matrix, size_t width, size_t height, double seconds, std::function<void(float*,float*,size_t)> func) {
	static const unsigned int hwThreadCount = std::thread::hardware_concurrency();
	unsigned long* counters = new unsigned long[hwThreadCount];
	std::thread* threads = new std::thread[hwThreadCount];

	float* src = new float[width * height];
	float* dst = new float[width * height];
	copyArray(src, matrix, width * height);

	// calc size and offset
	size_t heightPerThread = height / hwThreadCount;
	if (heightPerThread & 0b111) {
		heightPerThread -= heightPerThread & 0b111; // floor to full 8-float block
	}
	size_t threadHeight = height - (heightPerThread * (hwThreadCount - 1)); // height of last thread

	// Start as many threads as supported
	unsigned int i = hwThreadCount;
	Timer t;
	while (i--) {
		threads[i] = std::thread([heightPerThread, threadHeight, src, dst, seconds, i, func, &counters, width]{
			float* ptrSrc = &src[ i * width * heightPerThread ];
			float* ptrDst = &dst[ i * width * heightPerThread ];
			unsigned long innerCounter = 0;
			Timer inner;
			while (inner.elapsed() < seconds) {
				if (multiThreadShouldProcess(innerCounter)) {
					func(ptrSrc, ptrDst, threadHeight);
					++innerCounter;
				}
			}
			counters[i] = innerCounter;
		});
		threadHeight = heightPerThread;
	}

	i = hwThreadCount;
	while (i--) {
		threads[i].join();
	}

	double time = t.elapsed();
	PerformancePrintOperationsPerSecond(desc, time, threadSyncedCounter);

	// Cleanup
	delete [] counters;
	delete [] threads;
}

void runCPUMultiCore(float* matrix, size_t width, size_t height, double seconds) {
#ifdef _WIN32
	InitializeCriticalSection( &g_critSec );
#endif
	printf("Threading on single image:\n");
	testMultiThread2("Normal DCT", matrix, width, height, seconds, [width, height](float *in, float* out, size_t h){
		DCT::transform(in, out, width, h);
	});
	testMultiThread2("Separated DCT", matrix, width, height, seconds, [width, height](float *in, float*, size_t h){
		DCT::transform2(in, width, h);
	});
	testMultiThread2("Arai inline transpose", matrix, width, height, seconds, [width, height](float *in, float*, size_t h){
		Arai::transformInlineTranspose(in, width, h);
	});
	testMultiThread2("Arai DCT", matrix, width, height, seconds, [width, height](float *in, float*, size_t h){
		Arai::transform(in, width, h);
	});

	printf("\nThreading on image queue:\n");
	testMultiThread("Normal DCT", matrix, width, height, seconds, [width, height](float *in, float* out){
		DCT::transform(in, out, width, height);
	});
	testMultiThread("Separated DCT", matrix, width, height, seconds, [width, height](float *in, float*){
		DCT::transform2(in, width, height);
	});
	testMultiThread("Arai inline transpose", matrix, width, height, seconds, [width, height](float *in, float*){
		Arai::transformInlineTranspose(in, width, height);
	});
	testMultiThread("Arai DCT", matrix, width, height, seconds, [width, height](float *in, float*){
		Arai::transform(in, width, height);
	});

#ifdef _WIN32
	DeleteCriticalSection( &g_critSec );
#endif
}

// ################################################################
// #
// #  Main
// #
// ################################################################

void SpeedContest::run(double seconds, bool skipSingeCore) {
	size_t width = 256, height = 256;
	float *matrix = createTestMatrix(width, height); // (x+y*8) % 256;
	printf("Size: %lux%lu\n", width, height);
	if (skipSingeCore == false) {
		printf("\n== Single-Threaded ==\n");
		runCPUSingleCore(matrix, width, height, seconds);
	}

	printf("\n== Multi-Threading ==\n");
	printf("Threads: %d\n", std::thread::hardware_concurrency());
	runCPUMultiCore(matrix, width, height, seconds);

	printf("\n");

	delete [] matrix;
}

// ################################################################
// #
// #  Correctness Test
// #
// ################################################################

void SpeedContest::testForCorrectness(bool ourTestMatrix, bool use16x16, bool modifyData) {
	size_t width = 8, height = 8;
	if (use16x16) {
		width = 16; height = 16;
	}

	float* matrix = ( ourTestMatrix
					 ? createOurTestMatrix(width, height) // 1, 7, 3, 4, 5, 4, 3, 2
					 : createTestMatrix(width, height) );

	if (use16x16 && modifyData) {
		// modify some values to get different results, especially for 16 x 16
		matrix[8] = 0;
		matrix[8+1] = 4;
		matrix[8+width] = 4;
		matrix[2*width + 1] = 8;
		matrix[12*width + 1] = 1;
	}

	printf("\nInput:\n");
	printFloatMatrix(matrix, width, height);
	printf("------------------------------------------------------------------------\n");

	float *out = new float[width * height];
	verify("DCT Normal", matrix, width, height, [&](float* mat){
		DCT::transform(mat, out, width, height); return out;
	});
	verify("DCT Separated", matrix, width, height, [&](float* mat){
		DCT::transform2(mat, width, height); return mat;
	});
	verify("Arai", matrix, width, height, [&](float* mat){
		Arai::transform(mat, width, height); return mat;
	});
	verify("Arai Inline Transpose", matrix, width, height, [&](float* mat){
		Arai::transformInlineTranspose(mat, width, height); return mat;
	});

	printf("\nInverse:\n");
	DCT::transform2(matrix, width, height);
	DCT::inverse(matrix, out, width, height);
	printFloatMatrix(out, width, height);
	printf("-----------------------------------------------------------------> ALL CORRECT\n");
	delete [] out;
	delete [] matrix;
}
<commit_msg>Reset mutex to 0<commit_after>#include "SpeedContest.hpp"
#include <stdlib.h>
#include <thread>
#include <math.h>
#include <mutex>
#include "../helper/Performance.hpp"
#include "../dct/Arai.hpp"
#include "../dct/DCT.hpp"

#ifdef _WIN32
#include <Windows.h>
#endif

// 1, 7, 3, 4, 5, 4, 3, 2
// one way transform gets:
// 10.253, 0.797218, -2.19761, -0.0377379, -1.76777, -2.75264, -2.53387, -1.13403

//  ---------------------------------------------------------------
// |
// |  Helper
// |
//  ---------------------------------------------------------------

float* createTestMatrix(size_t width, size_t height) {
	float *data = new float[width * height];
	for (size_t y = 0; y < height; y++) {
		for (size_t x = 0; x < width; x++) {
			data[y * width + x]= (float)((x+y*8) % 256);
		}
	}
	return data; // remember to delete[]
}

float* createOurTestMatrix(size_t w, size_t h) {
	float data[8] = {1, 7, 3, 4, 5, 4, 3, 2}; // generate our well known test matrix
	float *vls = new float[w * h];
	for (size_t y = 0; y < h; y++) {
		for (size_t x = 0; x < w; x++) {
			float &u = vls[y * w + x];
			if (y % 8 == 0) {
				u = data[x % 8];
			} else {
				if (x % 8 == 0) {
					u = data[y % 8];
				} else {
					u = 0;
				}
			}
		}
	}
	return vls;
}

void printFloatMatrix(float* &mat, size_t w, size_t h) {
	for (size_t i = 0; i < w * h; ++i) {
		if (i % (w*8) == 0) printf("\n");
		if (mat[i] < 0.0005F && mat[i] > -0.0005F) printf("%8d ", 0);
		else printf("%8.3f ", mat[i]);
		if (i % 8 == 7)   printf("   ");
		if (i % w == w-1) printf("\n");
	}
}

inline void copyArray(float* dst, float* src, size_t size) {
	memcpy(dst, src, size * sizeof(float));
//	while (size--) {
//		*(dst++) = *(src++);
//	}
}

void verify(const char* desc, float* originalMatrix, size_t width, size_t height, std::function<float*(float*)> func) {
	size_t size = width * height;
	float *vls = new float[size];
	copyArray(vls, originalMatrix, size);
	float *result = func(vls);

	printf("\n%s\n", desc);
	printFloatMatrix(result, width, height);
	printf("------------------------------------------------------------> ");

	// Check if result is correct
	bool inverseIsCorrect = true;
	float *out = new float[size];
	DCT::inverse(result, out, width, height);
	while (size--) {
		if (fabsf(originalMatrix[size] - out[size]) > 0.0005F )
			inverseIsCorrect = false;
	}
	delete [] vls;

	// Break on Error
	if (inverseIsCorrect) {
		printf("Inverse: CORRECT\n");
	} else {
		printf("Inverse: FAILED\nInverse:\n");
		printFloatMatrix(out, width, height);
		exit(EXIT_FAILURE);
	}
	delete [] out;
}

// ################################################################
// #
// #  CPU - Single Core
// #
// ################################################################

void runCPUSingleCore(float* matrix, size_t width, size_t height, double seconds) {
	size_t size = width * height;
	float* vls = new float[size];
	float* out = new float[size];

	copyArray(vls, matrix, size);
	Performance::howManyOperationsInSeconds(seconds, "Normal DCT", [&]{
		DCT::transform(vls, out, width, height);
	});
	delete [] out;

	copyArray(vls, matrix, size);
	Performance::howManyOperationsInSeconds(seconds, "Separated DCT", [&]{
		DCT::transform2(vls, width, height);
	});

	copyArray(vls, matrix, size);
	Performance::howManyOperationsInSeconds(seconds, "Arai inline transpose", [&]{
		Arai::transformInlineTranspose(vls, width, height);
	});

	copyArray(vls, matrix, size);
	Performance::howManyOperationsInSeconds(seconds, "Arai DCT", [&]{
		Arai::transform(vls, width, height);
	});

	delete [] vls;
}

// ################################################################
// #
// #  CPU - Multi Core
// #
// ################################################################

void testMultiThread(const char* desc, float* matrix, size_t width, size_t height, double seconds, std::function<void(float*,float*)> func) {
	static const unsigned int hwThreadCount = std::thread::hardware_concurrency();
	unsigned long* counters = new unsigned long[hwThreadCount];
	std::thread* threads = new std::thread[hwThreadCount];

	// Prepare an array of input images to have coalesced memory access
	// This wouldn't be necessary in a real life situation, since input
	// should be in general different images with different memory locations
	float** multiSrc = new float*[hwThreadCount];
	float** multiDst = new float*[hwThreadCount];
	unsigned int u = hwThreadCount;
	while (u--) {
		multiSrc[u] = new float[width * height];
		multiDst[u] = new float[width * height];
		copyArray(multiSrc[u], matrix, width * height);
	}

	// Start as many threads as supported
	unsigned int i = hwThreadCount;
	Timer t;
	while (i--) {
		threads[i] = std::thread([multiSrc, multiDst, seconds, i, func, &counters, width, height]{
			Timer inner;
			unsigned long innerCounter = 0;
			while (inner.elapsed() < seconds) {
				func(multiSrc[i], multiDst[i]);
				++innerCounter;
			}
			counters[i] = innerCounter;
		});
	}

	unsigned long totalIterations = 0;
	i = hwThreadCount;
	while (i--) {
		threads[i].join();
		totalIterations += counters[i];
	}

	double time = t.elapsed();
	PerformancePrintOperationsPerSecond(desc, time, totalIterations);

	// Cleanup
	u = hwThreadCount;
	while (u--) {
		delete [] multiSrc[u];
		delete [] multiDst[u];
	}
	delete [] counters;
	delete [] threads;
}

#ifdef _WIN32
CRITICAL_SECTION g_critSec;
#else
std::mutex lock;
#endif

unsigned long threadSyncedCounter = 0;
inline bool multiThreadShouldProcess(unsigned long val) {
#ifdef _WIN32
	EnterCriticalSection( &g_critSec );
#else
	lock.lock();
#endif
	if (val > threadSyncedCounter) {
#ifdef _WIN32
		LeaveCriticalSection( &g_critSec );
#else
		lock.unlock();
#endif
		return false;
	} else {
		threadSyncedCounter = val + 1;
#ifdef _WIN32
		LeaveCriticalSection( &g_critSec );
#else
		lock.unlock();
#endif
		return true;
	}
}

void testMultiThread2(const char* desc, float* matrix, size_t width, size_t height, double seconds, std::function<void(float*,float*,size_t)> func) {
	static const unsigned int hwThreadCount = std::thread::hardware_concurrency();
	unsigned long* counters = new unsigned long[hwThreadCount];
	std::thread* threads = new std::thread[hwThreadCount];

	float* src = new float[width * height];
	float* dst = new float[width * height];
	copyArray(src, matrix, width * height);

	threadSyncedCounter = 0;

	// calc size and offset
	size_t heightPerThread = height / hwThreadCount;
	if (heightPerThread & 0b111) {
		heightPerThread -= heightPerThread & 0b111; // floor to full 8-float block
	}
	size_t threadHeight = height - (heightPerThread * (hwThreadCount - 1)); // height of last thread

	// Start as many threads as supported
	unsigned int i = hwThreadCount;
	Timer t;
	while (i--) {
		threads[i] = std::thread([heightPerThread, threadHeight, src, dst, seconds, i, func, &counters, width]{
			float* ptrSrc = &src[ i * width * heightPerThread ];
			float* ptrDst = &dst[ i * width * heightPerThread ];
			unsigned long innerCounter = 0;
			Timer inner;
			while (inner.elapsed() < seconds) {
				if (multiThreadShouldProcess(innerCounter)) {
					func(ptrSrc, ptrDst, threadHeight);
					++innerCounter;
				}
			}
			counters[i] = innerCounter;
		});
		threadHeight = heightPerThread;
	}

	i = hwThreadCount;
	while (i--) {
		threads[i].join();
	}

	double time = t.elapsed();
	PerformancePrintOperationsPerSecond(desc, time, threadSyncedCounter);

	// Cleanup
	delete [] counters;
	delete [] threads;
}

void runCPUMultiCore(float* matrix, size_t width, size_t height, double seconds) {
#ifdef _WIN32
	InitializeCriticalSection( &g_critSec );
#endif
	printf("Threading on single image:\n");
	testMultiThread2("Normal DCT", matrix, width, height, seconds, [width, height](float *in, float* out, size_t h){
		DCT::transform(in, out, width, h);
	});
	testMultiThread2("Separated DCT", matrix, width, height, seconds, [width, height](float *in, float*, size_t h){
		DCT::transform2(in, width, h);
	});
	testMultiThread2("Arai inline transpose", matrix, width, height, seconds, [width, height](float *in, float*, size_t h){
		Arai::transformInlineTranspose(in, width, h);
	});
	testMultiThread2("Arai DCT", matrix, width, height, seconds, [width, height](float *in, float*, size_t h){
		Arai::transform(in, width, h);
	});

	printf("\nThreading on image queue:\n");
	testMultiThread("Normal DCT", matrix, width, height, seconds, [width, height](float *in, float* out){
		DCT::transform(in, out, width, height);
	});
	testMultiThread("Separated DCT", matrix, width, height, seconds, [width, height](float *in, float*){
		DCT::transform2(in, width, height);
	});
	testMultiThread("Arai inline transpose", matrix, width, height, seconds, [width, height](float *in, float*){
		Arai::transformInlineTranspose(in, width, height);
	});
	testMultiThread("Arai DCT", matrix, width, height, seconds, [width, height](float *in, float*){
		Arai::transform(in, width, height);
	});

#ifdef _WIN32
	DeleteCriticalSection( &g_critSec );
#endif
}

// ################################################################
// #
// #  Main
// #
// ################################################################

void SpeedContest::run(double seconds, bool skipSingeCore) {
	size_t width = 256, height = 256;
	float *matrix = createTestMatrix(width, height); // (x+y*8) % 256;
	printf("Size: %lux%lu\n", width, height);
	if (skipSingeCore == false) {
		printf("\n== Single-Threaded ==\n");
		runCPUSingleCore(matrix, width, height, seconds);
	}

	printf("\n== Multi-Threading ==\n");
	printf("Threads: %d\n", std::thread::hardware_concurrency());
	runCPUMultiCore(matrix, width, height, seconds);

	printf("\n");

	delete [] matrix;
}

// ################################################################
// #
// #  Correctness Test
// #
// ################################################################

void SpeedContest::testForCorrectness(bool ourTestMatrix, bool use16x16, bool modifyData) {
	size_t width = 8, height = 8;
	if (use16x16) {
		width = 16; height = 16;
	}

	float* matrix = ( ourTestMatrix
					 ? createOurTestMatrix(width, height) // 1, 7, 3, 4, 5, 4, 3, 2
					 : createTestMatrix(width, height) );

	if (use16x16 && modifyData) {
		// modify some values to get different results, especially for 16 x 16
		matrix[8] = 0;
		matrix[8+1] = 4;
		matrix[8+width] = 4;
		matrix[2*width + 1] = 8;
		matrix[12*width + 1] = 1;
	}

	printf("\nInput:\n");
	printFloatMatrix(matrix, width, height);
	printf("------------------------------------------------------------------------\n");

	float *out = new float[width * height];
	verify("DCT Normal", matrix, width, height, [&](float* mat){
		DCT::transform(mat, out, width, height); return out;
	});
	verify("DCT Separated", matrix, width, height, [&](float* mat){
		DCT::transform2(mat, width, height); return mat;
	});
	verify("Arai", matrix, width, height, [&](float* mat){
		Arai::transform(mat, width, height); return mat;
	});
	verify("Arai Inline Transpose", matrix, width, height, [&](float* mat){
		Arai::transformInlineTranspose(mat, width, height); return mat;
	});

	printf("\nInverse:\n");
	DCT::transform2(matrix, width, height);
	DCT::inverse(matrix, out, width, height);
	printFloatMatrix(out, width, height);
	printf("-----------------------------------------------------------------> ALL CORRECT\n");
	delete [] out;
	delete [] matrix;
}
<|endoftext|>


<commit_before>// This file is a part of the OpenSurgSim project.
// Copyright 2013, SimQuest Solutions Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <memory>

#include "SurgSim/DataStructures/DataGroup.h"
#include "SurgSim/DataStructures/DataGroupBuilder.h"
#include "SurgSim/Devices/IdentityPoseDevice/IdentityPoseDevice.h"
#include "SurgSim/Devices/LabJack/LabJackDevice.h"
#include "SurgSim/Input/CommonDevice.h"
#include "SurgSim/Input/DeviceInterface.h"
#include "SurgSim/Input/InputConsumerInterface.h"
#include "SurgSim/Input/OutputProducerInterface.h"
#include "SurgSim/Math/RigidTransform.h"
#include "SurgSim/Math/Vector.h"
#include "SurgSim/Testing/VisualTestCommon/ToolSquareTest.h"

using SurgSim::DataStructures::DataGroup;
using SurgSim::DataStructures::DataGroupBuilder;
using SurgSim::Device::IdentityPoseDevice;
using SurgSim::Device::LabJackDevice;
using SurgSim::Input::DeviceInterface;
using SurgSim::Math::RigidTransform3d;
using SurgSim::Math::Vector3d;

class LabJackToPoseFilter : public SurgSim::Input::CommonDevice,
	public SurgSim::Input::InputConsumerInterface, public SurgSim::Input::OutputProducerInterface
{
public:
	LabJackToPoseFilter(const std::string& name, int firstTimerForQuadrature,
		int lineForPlusX, int lineForMinusX, double translationPerUpdate) :
		SurgSim::Input::CommonDevice(name),
		m_digitalInputPlusXIndex(-1),
		m_digitalInputMinusXIndex(-1),
		m_timerInputIndex(-1),
		m_pose(RigidTransform3d::Identity()),
		m_lineForPlusX(lineForPlusX),
		m_lineForMinusX(lineForMinusX),
		m_firstTimerForQuadrature(firstTimerForQuadrature),
		m_translationPerUpdate(translationPerUpdate)
	{
		DataGroupBuilder inputBuilder;
		inputBuilder.addPose(SurgSim::DataStructures::Names::POSE);
		getInputData() = inputBuilder.createData();
		getInitialInputData() = getInputData();
		m_poseIndex = getInputData().poses().getIndex(SurgSim::DataStructures::Names::POSE);
	}

	virtual ~LabJackToPoseFilter()
	{
		finalize();
	}

	bool initialize()
	{
		return true;
	}

	bool finalize()
	{
		return true;
	}

	void initializeInput(const std::string& device, const DataGroup& inputData)
	{
		m_digitalInputPlusXIndex = inputData.scalars().getIndex(SurgSim::DataStructures::Names::DIGITAL_INPUT_PREFIX +
			std::to_string(m_lineForPlusX));
		m_digitalInputMinusXIndex = inputData.scalars().getIndex(SurgSim::DataStructures::Names::DIGITAL_INPUT_PREFIX +
			std::to_string(m_lineForMinusX));
		m_timerInputIndex = inputData.scalars().getIndex(SurgSim::DataStructures::Names::TIMER_INPUT_PREFIX +
			std::to_string(m_firstTimerForQuadrature));

		inputFilter(inputData, &getInitialInputData());
		getInputData() = getInitialInputData();
	}

	void handleInput(const std::string& device, const DataGroup& inputData)
	{
		inputFilter(inputData, &getInputData());
		pushInput();
	}

	bool requestOutput(const std::string& device, DataGroup* outputData)
	{
		bool state = pullOutput();
		if (state)
		{
			outputFilter(getOutputData(), outputData);
		}
		return state;
	}

	void inputFilter(const DataGroup& dataToFilter, DataGroup* result)
	{
		// Turn LabJack inputs into a pose so it can control the sphere.
		if (m_digitalInputPlusXIndex >= 0)
		{
			double value;
			if (dataToFilter.scalars().get(m_digitalInputPlusXIndex, &value))
			{
				// If the device passed us this line's input, and the input is high...
				if (value > 0.5)
				{
					m_pose.translate(Vector3d::UnitX() * m_translationPerUpdate);
				}
			}
		}
		if (m_digitalInputPlusXIndex >= 0)
		{
			double value;
			if (dataToFilter.scalars().get(m_digitalInputMinusXIndex, &value))
			{
				// If the device passed us this line's input, and the input is high...
				if (value > 0.5)
				{
					m_pose.translate(-Vector3d::UnitX() * m_translationPerUpdate);
				}
			}
		}

		if (m_timerInputIndex >= 0)
		{
			double value;
			// For quadrature inputs, we only need the input value of the first of the timers.
			if (dataToFilter.scalars().get(m_timerInputIndex, &value))
			{
				m_pose.translation()[1] = value * m_translationPerUpdate;
			}
		}
		result->poses().set(m_poseIndex, m_pose);
	}

	void outputFilter(const DataGroup& dataToFilter, DataGroup* result)
	{
		*result = dataToFilter;
	}

private:
	int m_digitalInputPlusXIndex;
	int m_digitalInputMinusXIndex;
	int m_digitalOutputsIndex;
	int m_timerInputIndex;
	int m_poseIndex;
	RigidTransform3d m_pose;
	int m_lineForPlusX;
	int m_lineForMinusX;
	int m_firstTimerForQuadrature;
	double m_translationPerUpdate;
};

int main(int argc, char** argv)
{
	std::shared_ptr<LabJackDevice> toolDevice = std::make_shared<LabJackDevice>("LabJackDevice");
	toolDevice->setAddress(""); // Get the first-found of the specified type and connection.

	const int lineForPlusX = 0;
	const int lineForMinusX = 1;
	std::unordered_set<int> digitalInputChannels;
	digitalInputChannels.insert(lineForPlusX);
	digitalInputChannels.insert(lineForMinusX);
	toolDevice->setDigitalInputChannels(digitalInputChannels);

	toolDevice->setTimerCounterPinOffset(4); // the U3 requires the offset to be 4+.

	const int firstTimerForQuadrature = 0;
	std::unordered_map<int,SurgSim::Device::LabJackTimerMode> timers;
	timers[firstTimerForQuadrature] = SurgSim::Device::LABJACKTIMERMODE_QUAD;
	timers[firstTimerForQuadrature + 1] = SurgSim::Device::LABJACKTIMERMODE_QUAD;
	toolDevice->setTimers(timers);

	if (toolDevice->initialize())
	{
		const double translationPerUpdate = 0.001; // Millimeter per update.
		auto filter = std::make_shared<LabJackToPoseFilter>("LabJack to Pose filter", firstTimerForQuadrature,
			lineForPlusX, lineForMinusX, translationPerUpdate);
		toolDevice->setOutputProducer(filter);
		toolDevice->addInputConsumer(filter);
		filter->initialize();

		// The square is controlled by a second device.  For a simple test, we're using an IdentityPoseDevice--
		// a pretend device that doesn't actually move.
		std::shared_ptr<DeviceInterface> squareDevice = std::make_shared<IdentityPoseDevice>("IdentityPoseDevice");

		std::string text = "Set FIO0 low to move the sphere tool in positive x-direction. ";
		text += "Set FIO1 low to move in negative x. ";
		text += "Spin a quadrature encoder attached to FIO4 and FIO5 to move the sphere +/- y-direction.";

		runToolSquareTest(filter, squareDevice,
			//2345678901234567890123456789012345678901234567890123456789012345678901234567890
			text.c_str());
	}
	else
	{
		std::cout << std::endl << "Error initializing tool." << std::endl;
	}

	std::cout << std::endl << "Exiting." << std::endl;
	// Cleanup and shutdown will happen automatically as objects go out of scope.

	return 0;
}
<commit_msg>Fix LabJack visual test, initialInput data was removed from CommonDevice<commit_after>// This file is a part of the OpenSurgSim project.
// Copyright 2013, SimQuest Solutions Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <memory>

#include "SurgSim/DataStructures/DataGroup.h"
#include "SurgSim/DataStructures/DataGroupBuilder.h"
#include "SurgSim/Devices/IdentityPoseDevice/IdentityPoseDevice.h"
#include "SurgSim/Devices/LabJack/LabJackDevice.h"
#include "SurgSim/Input/CommonDevice.h"
#include "SurgSim/Input/DeviceInterface.h"
#include "SurgSim/Input/InputConsumerInterface.h"
#include "SurgSim/Input/OutputProducerInterface.h"
#include "SurgSim/Math/RigidTransform.h"
#include "SurgSim/Math/Vector.h"
#include "SurgSim/Testing/VisualTestCommon/ToolSquareTest.h"

using SurgSim::DataStructures::DataGroup;
using SurgSim::DataStructures::DataGroupBuilder;
using SurgSim::Device::IdentityPoseDevice;
using SurgSim::Device::LabJackDevice;
using SurgSim::Input::DeviceInterface;
using SurgSim::Math::RigidTransform3d;
using SurgSim::Math::Vector3d;

class LabJackToPoseFilter : public SurgSim::Input::CommonDevice,
	public SurgSim::Input::InputConsumerInterface, public SurgSim::Input::OutputProducerInterface
{
public:
	LabJackToPoseFilter(const std::string& name, int firstTimerForQuadrature,
		int lineForPlusX, int lineForMinusX, double translationPerUpdate) :
		SurgSim::Input::CommonDevice(name),
		m_digitalInputPlusXIndex(-1),
		m_digitalInputMinusXIndex(-1),
		m_timerInputIndex(-1),
		m_pose(RigidTransform3d::Identity()),
		m_lineForPlusX(lineForPlusX),
		m_lineForMinusX(lineForMinusX),
		m_firstTimerForQuadrature(firstTimerForQuadrature),
		m_translationPerUpdate(translationPerUpdate)
	{
		DataGroupBuilder inputBuilder;
		inputBuilder.addPose(SurgSim::DataStructures::Names::POSE);
		getInputData() = inputBuilder.createData();
		m_poseIndex = getInputData().poses().getIndex(SurgSim::DataStructures::Names::POSE);
	}

	virtual ~LabJackToPoseFilter()
	{
		finalize();
	}

	bool initialize()
	{
		return true;
	}

	bool finalize()
	{
		return true;
	}

	void initializeInput(const std::string& device, const DataGroup& inputData)
	{
		m_digitalInputPlusXIndex = inputData.scalars().getIndex(SurgSim::DataStructures::Names::DIGITAL_INPUT_PREFIX +
			std::to_string(m_lineForPlusX));
		m_digitalInputMinusXIndex = inputData.scalars().getIndex(SurgSim::DataStructures::Names::DIGITAL_INPUT_PREFIX +
			std::to_string(m_lineForMinusX));
		m_timerInputIndex = inputData.scalars().getIndex(SurgSim::DataStructures::Names::TIMER_INPUT_PREFIX +
			std::to_string(m_firstTimerForQuadrature));

		inputFilter(inputData, &getInputData());
	}

	void handleInput(const std::string& device, const DataGroup& inputData)
	{
		inputFilter(inputData, &getInputData());
		pushInput();
	}

	bool requestOutput(const std::string& device, DataGroup* outputData)
	{
		bool state = pullOutput();
		if (state)
		{
			outputFilter(getOutputData(), outputData);
		}
		return state;
	}

	void inputFilter(const DataGroup& dataToFilter, DataGroup* result)
	{
		// Turn LabJack inputs into a pose so it can control the sphere.
		if (m_digitalInputPlusXIndex >= 0)
		{
			double value;
			if (dataToFilter.scalars().get(m_digitalInputPlusXIndex, &value))
			{
				// If the device passed us this line's input, and the input is high...
				if (value > 0.5)
				{
					m_pose.translate(Vector3d::UnitX() * m_translationPerUpdate);
				}
			}
		}
		if (m_digitalInputPlusXIndex >= 0)
		{
			double value;
			if (dataToFilter.scalars().get(m_digitalInputMinusXIndex, &value))
			{
				// If the device passed us this line's input, and the input is high...
				if (value > 0.5)
				{
					m_pose.translate(-Vector3d::UnitX() * m_translationPerUpdate);
				}
			}
		}

		if (m_timerInputIndex >= 0)
		{
			double value;
			// For quadrature inputs, we only need the input value of the first of the timers.
			if (dataToFilter.scalars().get(m_timerInputIndex, &value))
			{
				m_pose.translation()[1] = value * m_translationPerUpdate;
			}
		}
		result->poses().set(m_poseIndex, m_pose);
	}

	void outputFilter(const DataGroup& dataToFilter, DataGroup* result)
	{
		*result = dataToFilter;
	}

private:
	int m_digitalInputPlusXIndex;
	int m_digitalInputMinusXIndex;
	int m_digitalOutputsIndex;
	int m_timerInputIndex;
	int m_poseIndex;
	RigidTransform3d m_pose;
	int m_lineForPlusX;
	int m_lineForMinusX;
	int m_firstTimerForQuadrature;
	double m_translationPerUpdate;
};

int main(int argc, char** argv)
{
	std::shared_ptr<LabJackDevice> toolDevice = std::make_shared<LabJackDevice>("LabJackDevice");
	toolDevice->setAddress(""); // Get the first-found of the specified type and connection.

	const int lineForPlusX = 0;
	const int lineForMinusX = 1;
	std::unordered_set<int> digitalInputChannels;
	digitalInputChannels.insert(lineForPlusX);
	digitalInputChannels.insert(lineForMinusX);
	toolDevice->setDigitalInputChannels(digitalInputChannels);

	toolDevice->setTimerCounterPinOffset(4); // the U3 requires the offset to be 4+.

	const int firstTimerForQuadrature = 0;
	std::unordered_map<int,SurgSim::Device::LabJackTimerMode> timers;
	timers[firstTimerForQuadrature] = SurgSim::Device::LABJACKTIMERMODE_QUAD;
	timers[firstTimerForQuadrature + 1] = SurgSim::Device::LABJACKTIMERMODE_QUAD;
	toolDevice->setTimers(timers);

	if (toolDevice->initialize())
	{
		const double translationPerUpdate = 0.001; // Millimeter per update.
		auto filter = std::make_shared<LabJackToPoseFilter>("LabJack to Pose filter", firstTimerForQuadrature,
			lineForPlusX, lineForMinusX, translationPerUpdate);
		toolDevice->setOutputProducer(filter);
		toolDevice->addInputConsumer(filter);
		filter->initialize();

		// The square is controlled by a second device.  For a simple test, we're using an IdentityPoseDevice--
		// a pretend device that doesn't actually move.
		std::shared_ptr<DeviceInterface> squareDevice = std::make_shared<IdentityPoseDevice>("IdentityPoseDevice");

		std::string text = "Set FIO0 low to move the sphere tool in positive x-direction. ";
		text += "Set FIO1 low to move in negative x. ";
		text += "Spin a quadrature encoder attached to FIO4 and FIO5 to move the sphere +/- y-direction.";

		runToolSquareTest(filter, squareDevice,
			//2345678901234567890123456789012345678901234567890123456789012345678901234567890
			text.c_str());
	}
	else
	{
		std::cout << std::endl << "Error initializing tool." << std::endl;
	}

	std::cout << std::endl << "Exiting." << std::endl;
	// Cleanup and shutdown will happen automatically as objects go out of scope.

	return 0;
}
<|endoftext|>


<commit_before>/*
 * This file is part of TelepathyQt4
 *
 * Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/>
 * Copyright (C) 2008 Nokia Corporation
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <TelepathyQt4/PendingContactAttributes>

#include "TelepathyQt4/_gen/pending-contact-attributes.moc.hpp"

#include <TelepathyQt4/Connection>
#include <TelepathyQt4/ReferencedHandles>

#include "TelepathyQt4/debug-internal.h"

namespace Tp
{

/**
 * \class PendingContactAttributes
 * \ingroup clientconn
 * \headerfile TelepathyQt4/pending-contact-attributes.h <TelepathyQt4/PendingContactAttributes>
 *
 * \brief Class containing the parameters of and the reply to an asynchronous
 * request for raw contact attributes, as used in the
 * Connection::contactAttributes() low-level convenience method wrapping the
 * Client::ConnectionInterfaceContactsInterface::GetContactAttributes() D-Bus
 * method.
 */

struct TELEPATHY_QT4_NO_EXPORT PendingContactAttributes::Private
{
    ConnectionPtr connection;
    UIntList contactsRequested;
    QStringList interfacesRequested;
    bool shouldReference;
    ReferencedHandles validHandles;
    UIntList invalidHandles;
    ContactAttributesMap attributes;
};

PendingContactAttributes::PendingContactAttributes(const ConnectionPtr &connection,
        const UIntList &handles, const QStringList &interfaces, bool reference)
    : PendingOperation(connection.data()),
      mPriv(new Private)
{
    mPriv->connection = connection;
    mPriv->contactsRequested = handles;
    mPriv->interfacesRequested = interfaces;
    mPriv->shouldReference = reference;
}

/**
 * Class destructor.
 */
PendingContactAttributes::~PendingContactAttributes()
{
    delete mPriv;
}

/**
 * Returns the Connection object through which the request was made.
 *
 * \return Pointer to the Connection.
 */
ConnectionPtr PendingContactAttributes::connection() const
{
    return mPriv->connection;
}

/**
 * Returns the contacts for which attributes were requested.
 *
 * \return Reference to a list with the handles of the contacts.
 */
const UIntList &PendingContactAttributes::contactsRequested() const
{
    return mPriv->contactsRequested;
}

/**
 * Returns the interfaces the corresponding attributes of which were requested.
 *
 * \return Reference to a list of D-Bus interface names.
 */
const QStringList &PendingContactAttributes::interfacesRequested() const
{
    return mPriv->interfacesRequested;
}

/**
 * Returns whether it was requested that the contact handles should be referenced in addition to
 * fetching their attributes. This corresponds to the reference argument to
 * Connection::contactAttributes().
 *
 * \return Whether the handles should be referenced or not.
 */
bool PendingContactAttributes::shouldReference() const
{
    return mPriv->shouldReference;
}

/**
 * If referencing the handles was requested (as indicated by shouldReference()), returns the
 * now-referenced handles resulting from the operation. If the operation has not (yet) finished
 * successfully (isFinished() returns false), or referencing was not requested, the
 * return value is undefined.
 *
 * Even if referencing was requested, the list will not always contain all of the handles in
 * contactsRequested(), only the ones which were valid. The valid handles will be in the same order
 * as in contactsRequested(), though.
 *
 * \return ReferencedHandles instance containing the handles.
 */
ReferencedHandles PendingContactAttributes::validHandles() const
{
    if (!isFinished()) {
        warning() << "PendingContactAttributes::validHandles() called before finished";
    } else if (isError()) {
        warning() << "PendingContactAttributes::validHandles() called when errored";
    } else if (!shouldReference()) {
        warning() << "PendingContactAttributes::validHandles() called but weren't asked to"
                  << "reference handles";
    }

    return mPriv->validHandles;
}

/**
 * Returns the handles which were found to be invalid while processing the operation. If the
 * operation has not (yet) finished successfully (isFinished() returns false), the
 * return value is undefined.
 *
 * \return A list with the invalid handles.
 */
UIntList PendingContactAttributes::invalidHandles() const
{
    if (!isFinished()) {
        warning() << "PendingContactAttributes::validHandles() called before finished";
    } else if (isError()) {
        warning() << "PendingContactAttributes::validHandles() called when errored";
    }

    return mPriv->invalidHandles;
}

/**
 * Returns a dictionary mapping the valid contact handles in contactsRequested() (when also
 * referencing, this means the contents of validHandles()) to contact attributes. If the operation
 * has not (yet) finished successfully (isFinished() returns false), the return value
 * is undefined.
 *
 * \return Mapping from handles to variant maps containing the attributes.
 */
ContactAttributesMap PendingContactAttributes::attributes() const
{
    if (!isFinished()) {
        warning() << "PendingContactAttributes::validHandles() called before finished";
    } else if (isError()) {
        warning() << "PendingContactAttributes::validHandles() called when errored";
    }

    return mPriv->attributes;
}

void PendingContactAttributes::onCallFinished(QDBusPendingCallWatcher* watcher)
{
    QDBusPendingReply<ContactAttributesMap> reply = *watcher;

    if (reply.isError()) {
        debug().nospace() << "GetCAs: error " << reply.error().name() << ": " << reply.error().message();
        setFinishedWithError(reply.error());
    } else {
        mPriv->attributes = reply.value();

        UIntList validHandles;
        foreach (uint contact, mPriv->contactsRequested) {
            if (mPriv->attributes.contains(contact)) {
                validHandles << contact;
            } else {
                mPriv->invalidHandles << contact;
            }
        }

        if (shouldReference()) {
            mPriv->validHandles = ReferencedHandles(mPriv->connection, HandleTypeContact,
                    validHandles);
        }

        setFinished();
    }

    mPriv->connection->handleRequestLanded(HandleTypeContact);

    watcher->deleteLater();
}

void PendingContactAttributes::failImmediately(const QString &error, const QString &errorMessage)
{
    setFinishedWithError(error, errorMessage);
}

} // Tp
<commit_msg>Don't make the Connection the parent in PendingCAI, we already hold a strong ref<commit_after>/*
 * This file is part of TelepathyQt4
 *
 * Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/>
 * Copyright (C) 2008 Nokia Corporation
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <TelepathyQt4/PendingContactAttributes>

#include "TelepathyQt4/_gen/pending-contact-attributes.moc.hpp"

#include <TelepathyQt4/Connection>
#include <TelepathyQt4/ReferencedHandles>

#include "TelepathyQt4/debug-internal.h"

namespace Tp
{

/**
 * \class PendingContactAttributes
 * \ingroup clientconn
 * \headerfile TelepathyQt4/pending-contact-attributes.h <TelepathyQt4/PendingContactAttributes>
 *
 * \brief Class containing the parameters of and the reply to an asynchronous
 * request for raw contact attributes, as used in the
 * Connection::contactAttributes() low-level convenience method wrapping the
 * Client::ConnectionInterfaceContactsInterface::GetContactAttributes() D-Bus
 * method.
 */

struct TELEPATHY_QT4_NO_EXPORT PendingContactAttributes::Private
{
    ConnectionPtr connection;
    UIntList contactsRequested;
    QStringList interfacesRequested;
    bool shouldReference;
    ReferencedHandles validHandles;
    UIntList invalidHandles;
    ContactAttributesMap attributes;
};

PendingContactAttributes::PendingContactAttributes(const ConnectionPtr &connection,
        const UIntList &handles, const QStringList &interfaces, bool reference)
    : PendingOperation(0),
      mPriv(new Private)
{
    mPriv->connection = connection;
    mPriv->contactsRequested = handles;
    mPriv->interfacesRequested = interfaces;
    mPriv->shouldReference = reference;
}

/**
 * Class destructor.
 */
PendingContactAttributes::~PendingContactAttributes()
{
    delete mPriv;
}

/**
 * Returns the Connection object through which the request was made.
 *
 * \return Pointer to the Connection.
 */
ConnectionPtr PendingContactAttributes::connection() const
{
    return mPriv->connection;
}

/**
 * Returns the contacts for which attributes were requested.
 *
 * \return Reference to a list with the handles of the contacts.
 */
const UIntList &PendingContactAttributes::contactsRequested() const
{
    return mPriv->contactsRequested;
}

/**
 * Returns the interfaces the corresponding attributes of which were requested.
 *
 * \return Reference to a list of D-Bus interface names.
 */
const QStringList &PendingContactAttributes::interfacesRequested() const
{
    return mPriv->interfacesRequested;
}

/**
 * Returns whether it was requested that the contact handles should be referenced in addition to
 * fetching their attributes. This corresponds to the reference argument to
 * Connection::contactAttributes().
 *
 * \return Whether the handles should be referenced or not.
 */
bool PendingContactAttributes::shouldReference() const
{
    return mPriv->shouldReference;
}

/**
 * If referencing the handles was requested (as indicated by shouldReference()), returns the
 * now-referenced handles resulting from the operation. If the operation has not (yet) finished
 * successfully (isFinished() returns false), or referencing was not requested, the
 * return value is undefined.
 *
 * Even if referencing was requested, the list will not always contain all of the handles in
 * contactsRequested(), only the ones which were valid. The valid handles will be in the same order
 * as in contactsRequested(), though.
 *
 * \return ReferencedHandles instance containing the handles.
 */
ReferencedHandles PendingContactAttributes::validHandles() const
{
    if (!isFinished()) {
        warning() << "PendingContactAttributes::validHandles() called before finished";
    } else if (isError()) {
        warning() << "PendingContactAttributes::validHandles() called when errored";
    } else if (!shouldReference()) {
        warning() << "PendingContactAttributes::validHandles() called but weren't asked to"
                  << "reference handles";
    }

    return mPriv->validHandles;
}

/**
 * Returns the handles which were found to be invalid while processing the operation. If the
 * operation has not (yet) finished successfully (isFinished() returns false), the
 * return value is undefined.
 *
 * \return A list with the invalid handles.
 */
UIntList PendingContactAttributes::invalidHandles() const
{
    if (!isFinished()) {
        warning() << "PendingContactAttributes::validHandles() called before finished";
    } else if (isError()) {
        warning() << "PendingContactAttributes::validHandles() called when errored";
    }

    return mPriv->invalidHandles;
}

/**
 * Returns a dictionary mapping the valid contact handles in contactsRequested() (when also
 * referencing, this means the contents of validHandles()) to contact attributes. If the operation
 * has not (yet) finished successfully (isFinished() returns false), the return value
 * is undefined.
 *
 * \return Mapping from handles to variant maps containing the attributes.
 */
ContactAttributesMap PendingContactAttributes::attributes() const
{
    if (!isFinished()) {
        warning() << "PendingContactAttributes::validHandles() called before finished";
    } else if (isError()) {
        warning() << "PendingContactAttributes::validHandles() called when errored";
    }

    return mPriv->attributes;
}

void PendingContactAttributes::onCallFinished(QDBusPendingCallWatcher* watcher)
{
    QDBusPendingReply<ContactAttributesMap> reply = *watcher;

    if (reply.isError()) {
        debug().nospace() << "GetCAs: error " << reply.error().name() << ": " << reply.error().message();
        setFinishedWithError(reply.error());
    } else {
        mPriv->attributes = reply.value();

        UIntList validHandles;
        foreach (uint contact, mPriv->contactsRequested) {
            if (mPriv->attributes.contains(contact)) {
                validHandles << contact;
            } else {
                mPriv->invalidHandles << contact;
            }
        }

        if (shouldReference()) {
            mPriv->validHandles = ReferencedHandles(mPriv->connection, HandleTypeContact,
                    validHandles);
        }

        setFinished();
    }

    mPriv->connection->handleRequestLanded(HandleTypeContact);

    watcher->deleteLater();
}

void PendingContactAttributes::failImmediately(const QString &error, const QString &errorMessage)
{
    setFinishedWithError(error, errorMessage);
}

} // Tp
<|endoftext|>


<commit_before>/**
 * This file is part of TelepathyQt4
 *
 * @copyright Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/>
 * @copyright Copyright (C) 2008 Nokia Corporation
 * @license LGPL 2.1
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <TelepathyQt4/PendingContactAttributes>

#include "TelepathyQt4/_gen/pending-contact-attributes.moc.hpp"

#include <TelepathyQt4/Connection>
#include <TelepathyQt4/ReferencedHandles>

#include "TelepathyQt4/debug-internal.h"

namespace Tp
{

/**
 * \class PendingContactAttributes
 * \ingroup clientconn
 * \headerfile TelepathyQt4/pending-contact-attributes.h <TelepathyQt4/PendingContactAttributes>
 *
 * \brief The PendingContactAttributes class represents the parameters of and
 * the reply to an asynchronous request for raw contact attributes, as used in
 * the Connection::contactAttributes() low-level convenience method wrapping the
 * Client::ConnectionInterfaceContactsInterface::GetContactAttributes() D-Bus
 * method.
 */

struct TELEPATHY_QT4_NO_EXPORT PendingContactAttributes::Private
{
    UIntList contactsRequested;
    QStringList interfacesRequested;
    bool shouldReference;
    ReferencedHandles validHandles;
    UIntList invalidHandles;
    ContactAttributesMap attributes;
};

PendingContactAttributes::PendingContactAttributes(const ConnectionPtr &connection,
        const UIntList &handles, const QStringList &interfaces, bool reference)
    : PendingOperation(connection),
      mPriv(new Private)
{
    mPriv->contactsRequested = handles;
    mPriv->interfacesRequested = interfaces;
    mPriv->shouldReference = reference;
}

/**
 * Class destructor.
 */
PendingContactAttributes::~PendingContactAttributes()
{
    delete mPriv;
}

/**
 * Return the Connection object through which the request was made.
 *
 * \return Pointer to the Connection.
 */
ConnectionPtr PendingContactAttributes::connection() const
{
    return ConnectionPtr(qobject_cast<Connection*>((Connection*) object().data()));
}

/**
 * Return the contacts for which attributes were requested.
 *
 * \return Reference to a list with the handles of the contacts.
 */
const UIntList &PendingContactAttributes::contactsRequested() const
{
    return mPriv->contactsRequested;
}

/**
 * Return the interfaces the corresponding attributes of which were requested.
 *
 * \return Reference to a list of D-Bus interface names.
 */
const QStringList &PendingContactAttributes::interfacesRequested() const
{
    return mPriv->interfacesRequested;
}

/**
 * Return whether it was requested that the contact handles should be referenced in addition to
 * fetching their attributes. This corresponds to the reference argument to
 * Connection::contactAttributes().
 *
 * \return Whether the handles should be referenced or not.
 */
bool PendingContactAttributes::shouldReference() const
{
    return mPriv->shouldReference;
}

/**
 * If referencing the handles was requested (as indicated by shouldReference()), returns the
 * now-referenced handles resulting from the operation. If the operation has not (yet) finished
 * successfully (isFinished() returns false), or referencing was not requested, the
 * return value is undefined.
 *
 * Even if referencing was requested, the list will not always contain all of the handles in
 * contactsRequested(), only the ones which were valid. The valid handles will be in the same order
 * as in contactsRequested(), though.
 *
 * \return ReferencedHandles instance containing the handles.
 */
ReferencedHandles PendingContactAttributes::validHandles() const
{
    if (!isFinished()) {
        warning() << "PendingContactAttributes::validHandles() called before finished";
    } else if (isError()) {
        warning() << "PendingContactAttributes::validHandles() called when errored";
    } else if (!shouldReference()) {
        warning() << "PendingContactAttributes::validHandles() called but weren't asked to"
                  << "reference handles";
    }

    return mPriv->validHandles;
}

/**
 * Return the handles which were found to be invalid while processing the operation. If the
 * operation has not (yet) finished successfully (isFinished() returns false), the
 * return value is undefined.
 *
 * \return A list with the invalid handles.
 */
UIntList PendingContactAttributes::invalidHandles() const
{
    if (!isFinished()) {
        warning() << "PendingContactAttributes::validHandles() called before finished";
    } else if (isError()) {
        warning() << "PendingContactAttributes::validHandles() called when errored";
    }

    return mPriv->invalidHandles;
}

/**
 * Return a dictionary mapping the valid contact handles in contactsRequested() (when also
 * referencing, this means the contents of validHandles()) to contact attributes. If the operation
 * has not (yet) finished successfully (isFinished() returns false), the return value
 * is undefined.
 *
 * \return Mapping from handles to variant maps containing the attributes.
 */
ContactAttributesMap PendingContactAttributes::attributes() const
{
    if (!isFinished()) {
        warning() << "PendingContactAttributes::validHandles() called before finished";
    } else if (isError()) {
        warning() << "PendingContactAttributes::validHandles() called when errored";
    }

    return mPriv->attributes;
}

void PendingContactAttributes::onCallFinished(QDBusPendingCallWatcher* watcher)
{
    QDBusPendingReply<ContactAttributesMap> reply = *watcher;

    if (reply.isError()) {
        debug().nospace() << "GetCAs: error " << reply.error().name() << ": " << reply.error().message();
        setFinishedWithError(reply.error());
    } else {
        mPriv->attributes = reply.value();

        UIntList validHandles;
        foreach (uint contact, mPriv->contactsRequested) {
            if (mPriv->attributes.contains(contact)) {
                validHandles << contact;
            } else {
                mPriv->invalidHandles << contact;
            }
        }

        if (shouldReference()) {
            mPriv->validHandles = ReferencedHandles(connection(), HandleTypeContact,
                    validHandles);
        }

        setFinished();
    }

    connection()->handleRequestLanded(HandleTypeContact);

    watcher->deleteLater();
}

void PendingContactAttributes::failImmediately(const QString &error, const QString &errorMessage)
{
    setFinishedWithError(error, errorMessage);
}

} // Tp
<commit_msg>PendingContactAttributes: Update docs.<commit_after>/**
 * This file is part of TelepathyQt4
 *
 * @copyright Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/>
 * @copyright Copyright (C) 2008 Nokia Corporation
 * @license LGPL 2.1
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <TelepathyQt4/PendingContactAttributes>

#include "TelepathyQt4/_gen/pending-contact-attributes.moc.hpp"

#include <TelepathyQt4/Connection>
#include <TelepathyQt4/ReferencedHandles>

#include "TelepathyQt4/debug-internal.h"

namespace Tp
{

/**
 * \class PendingContactAttributes
 * \ingroup clientconn
 * \headerfile TelepathyQt4/pending-contact-attributes.h <TelepathyQt4/PendingContactAttributes>
 *
 * \brief The PendingContactAttributes class represents the parameters of and
 * the reply to an asynchronous request for raw contact attributes, as used in
 * the ConnectionLowlevel::contactAttributes() low-level convenience method wrapping the
 * Client::ConnectionInterfaceContactsInterface::GetContactAttributes() D-Bus
 * method.
 *
 * See \ref async_model
 */

struct TELEPATHY_QT4_NO_EXPORT PendingContactAttributes::Private
{
    UIntList contactsRequested;
    QStringList interfacesRequested;
    bool shouldReference;
    ReferencedHandles validHandles;
    UIntList invalidHandles;
    ContactAttributesMap attributes;
};

PendingContactAttributes::PendingContactAttributes(const ConnectionPtr &connection,
        const UIntList &handles, const QStringList &interfaces, bool reference)
    : PendingOperation(connection),
      mPriv(new Private)
{
    mPriv->contactsRequested = handles;
    mPriv->interfacesRequested = interfaces;
    mPriv->shouldReference = reference;
}

/**
 * Class destructor.
 */
PendingContactAttributes::~PendingContactAttributes()
{
    delete mPriv;
}

/**
 * Return the connection through which the request was made.
 *
 * \return A pointer to the Connection object.
 */
ConnectionPtr PendingContactAttributes::connection() const
{
    return ConnectionPtr(qobject_cast<Connection*>((Connection*) object().data()));
}

/**
 * Return the contacts for which attributes were requested.
 *
 * \return Reference to a list with the handles of the contacts.
 */
const UIntList &PendingContactAttributes::contactsRequested() const
{
    return mPriv->contactsRequested;
}

/**
 * Return the interfaces the corresponding attributes of which were requested.
 *
 * \return Reference to a list of D-Bus interface names.
 */
const QStringList &PendingContactAttributes::interfacesRequested() const
{
    return mPriv->interfacesRequested;
}

/**
 * Return whether it was requested that the contact handles should be referenced in addition to
 * fetching their attributes. This corresponds to the reference argument to
 * Connection::contactAttributes().
 *
 * \return Whether the handles should be referenced or not.
 */
bool PendingContactAttributes::shouldReference() const
{
    return mPriv->shouldReference;
}

/**
 * If referencing the handles was requested (as indicated by shouldReference()), returns the
 * now-referenced handles resulting from the operation. If the operation has not (yet) finished
 * successfully (isFinished() returns false), or referencing was not requested, the
 * return value is undefined.
 *
 * Even if referencing was requested, the list will not always contain all of the handles in
 * contactsRequested(), only the ones which were valid. The valid handles will be in the same order
 * as in contactsRequested(), though.
 *
 * \return ReferencedHandles instance containing the handles.
 */
ReferencedHandles PendingContactAttributes::validHandles() const
{
    if (!isFinished()) {
        warning() << "PendingContactAttributes::validHandles() called before finished";
    } else if (isError()) {
        warning() << "PendingContactAttributes::validHandles() called when errored";
    } else if (!shouldReference()) {
        warning() << "PendingContactAttributes::validHandles() called but weren't asked to"
                  << "reference handles";
    }

    return mPriv->validHandles;
}

/**
 * Return the handles which were found to be invalid while processing the operation. If the
 * operation has not (yet) finished successfully (isFinished() returns false), the
 * return value is undefined.
 *
 * \return A list with the invalid handles.
 */
UIntList PendingContactAttributes::invalidHandles() const
{
    if (!isFinished()) {
        warning() << "PendingContactAttributes::validHandles() called before finished";
    } else if (isError()) {
        warning() << "PendingContactAttributes::validHandles() called when errored";
    }

    return mPriv->invalidHandles;
}

/**
 * Return a dictionary mapping the valid contact handles in contactsRequested() (when also
 * referencing, this means the contents of validHandles()) to contact attributes. If the operation
 * has not (yet) finished successfully (isFinished() returns false), the return value
 * is undefined.
 *
 * \return Mapping from handles to variant maps containing the attributes.
 */
ContactAttributesMap PendingContactAttributes::attributes() const
{
    if (!isFinished()) {
        warning() << "PendingContactAttributes::validHandles() called before finished";
    } else if (isError()) {
        warning() << "PendingContactAttributes::validHandles() called when errored";
    }

    return mPriv->attributes;
}

void PendingContactAttributes::onCallFinished(QDBusPendingCallWatcher* watcher)
{
    QDBusPendingReply<ContactAttributesMap> reply = *watcher;

    if (reply.isError()) {
        debug().nospace() << "GetCAs: error " << reply.error().name() << ": " << reply.error().message();
        setFinishedWithError(reply.error());
    } else {
        mPriv->attributes = reply.value();

        UIntList validHandles;
        foreach (uint contact, mPriv->contactsRequested) {
            if (mPriv->attributes.contains(contact)) {
                validHandles << contact;
            } else {
                mPriv->invalidHandles << contact;
            }
        }

        if (shouldReference()) {
            mPriv->validHandles = ReferencedHandles(connection(), HandleTypeContact,
                    validHandles);
        }

        setFinished();
    }

    connection()->handleRequestLanded(HandleTypeContact);

    watcher->deleteLater();
}

void PendingContactAttributes::failImmediately(const QString &error, const QString &errorMessage)
{
    setFinishedWithError(error, errorMessage);
}

} // Tp
<|endoftext|>


<commit_before>#include "Genome.h"
#include "SuffixArrayFuns.h"
#include "PackedArray.h"
#include "ErrorWarning.h"
#include "streamFuns.h"
#include "SharedMemory.h"
#include "genomeScanFastaFiles.h"

#include <time.h>
#include <cmath>
#include <unistd.h>
#include <sys/stat.h>

//arbitrary number for ftok function
#define SHM_projectID 23

Genome::Genome (Parameters &P, ParametersGenome &pGe): shmStart(NULL), P(P), pGe(pGe), sharedMemory(NULL)
{
    shmKey=ftok(pGe.gDir.c_str(),SHM_projectID);
    genomeOut.g=this;//will change if genomeOut is different from genomeMain
    genomeOut.convYes=false;
    sjdbOverhang = pGe.sjdbOverhang; //will be re-defined later if another value was used for the generated genome
    sjdbLength = pGe.sjdbOverhang==0 ? 0 : pGe.sjdbOverhang*2+1;
};

// Genome::~Genome()
// {
//     if (sharedMemory != NULL)
//         delete sharedMemory;
//     sharedMemory = NULL;
// }

void Genome::freeMemory(){//free big chunks of memory used by genome and suffix array

    if (pGe.gLoad=="NoSharedMemory") {//can deallocate only for non-shared memory
        delete[] G1;
        G1=NULL;
        SA.deallocateArray();
        SApass2.deallocateArray();
        SAi.deallocateArray();
    };
};

uint Genome::OpenStream(string name, ifstream & stream, uint size)
{
    stream.open((pGe.gDir+ "/" +name).c_str(), ios::binary);
    if (!stream.good()) {
        ostringstream errOut;
        errOut << "EXITING because of FATAL ERROR: could not open genome file: "<< pGe.gDir << "/" << name <<"\n";
        errOut << "SOLUTION: check that the path to genome files, specified in --genomeDir is correct and the files are present, and have user read permissions\n" <<flush;
        exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_GENOME_FILES, P);
    };

    if (size>0) {
        P.inOut->logMain << name << ": size given as a parameter = " << size <<"\n";
    } else {
        P.inOut->logMain << "Checking " << name << " size";
        stream.seekg (0, ios::end);
        int64 size1 = stream.tellg();
        if (size1<=0) {
            ostringstream errOut;
            errOut << "EXITING because of FATAL ERROR: failed reading from genome file: "<< pGe.gDir << "/" << name <<"\n";
            errOut << "SOLUTION: re-generate the genome index\n";
            exitWithError(errOut.str(),std::cerr, P.inOut->logMain, 1, P);
        };
        size=(uint) size1;
        stream.clear();
        stream.seekg (0, ios::beg);
        P.inOut->logMain << "file size: "<< size <<" bytes; state: good=" <<stream.good()\
                <<" eof="<<stream.eof()<<" fail="<<stream.fail()<<" bad="<<stream.bad()<<"\n"<<flush;
    };

    return size;
};

void Genome::HandleSharedMemoryException(const SharedMemoryException & exc, uint64 shmSize)
{
    ostringstream errOut;
    errOut << "Shared memory error: " << exc.GetErrorCode() << ", errno: " << strerror(exc.GetErrorDetail()) << "(" << errno << ")" << endl;

    int exitCode = EXIT_CODE_SHM;
    switch (exc.GetErrorCode())
    {
        case EOPENFAILED:
            errOut << "EXITING because of FATAL ERROR: problems with shared memory: error from shmget() or shm_open()." << endl << flush;
            errOut << "SOLUTION: check shared memory settings as explained in STAR manual, OR run STAR with --genomeLoad NoSharedMemory to avoid using shared memory" << endl << flush;
            break;
        case EEXISTS:
            errOut << "EXITING: fatal error from shmget() trying to allocate shared memory piece." << endl;
            errOut << "Possible cause 1: not enough RAM. Check if you have enough RAM of at least " << shmSize+2000000000 << " bytes" << endl;
            errOut << "Possible cause 2: not enough virtual memory allowed with ulimit. SOLUTION: run ulimit -v " <<  shmSize+2000000000 << endl;
            errOut << "Possible cause 3: allowed shared memory size is not large enough. SOLUTIONS: (i) consult STAR manual on how to increase shared memory allocation; " \
            "(ii) ask your system administrator to increase shared memory allocation; (iii) run STAR with --genomeLoad NoSharedMemory" << endl<<flush;
            break;
        case EFTRUNCATE:
            errOut << "EXITING: fatal error from ftruncate() error shared memory."  << endl;
            errOut << "Possible cause 1: not enough RAM. Check if you have enough RAM of at least " << shmSize+2000000000 << " bytes" << endl << flush;
            exitCode = EXIT_CODE_MEMORY_ALLOCATION;
            break;
        case EMAPFAILED:
            errOut << "EXITING because of FATAL ERROR: problems with shared memory: error from shmat() while trying to get address of the shared memory piece." << endl << flush;
            errOut << "SOLUTION: check shared memory settings as explained in STAR manual, OR run STAR with --genomeLoad NoSharedMemory to avoid using shared memory" << endl << flush;
            break;
        case ECLOSE:
            errOut << "EXITING because of FATAL ERROR: could not close the shared memory object." << endl << flush;
            break;
        case EUNLINK:
            #ifdef POSIX_SHARED_MEM
            errOut << "EXITING because of FATAL ERROR:  could not delete the shared object." << endl << flush;
            #else
            errOut << "EXITING because of FATAL ERROR: problems with shared memory: error from shmctl() while trying to remove shared memory piece." << endl << flush;
            errOut << "SOLUTION: check shared memory settings as explained in STAR manual, OR run STAR with --genomeLoad NoSharedMemory to avoid using shared memory" << endl << flush;
            #endif
            break;
        default:
            errOut << "EXITING because of FATAL ERROR: There was an issue with the shared memory allocation. Try running STAR with --genomeLoad NoSharedMemory to avoid using shared memory.";
            break;
    }

    try
    {
        if (sharedMemory != NULL)
            sharedMemory->Clean();
    }
    catch(...)
    {}

    exitWithError(errOut.str(),std::cerr, P.inOut->logMain, exitCode, P);
};

//////////////////////////////////////////////////////////////////////////////////////////
void Genome::chrInfoLoad() {//find chrStart,Length,nChr from Genome G

    //load chr names
    ifstream chrStreamIn ( (pGe.gDir+"/chrName.txt").c_str() );
    if (chrStreamIn.fail()) {
        ostringstream errOut;
        errOut << "EXITING because of FATAL error, could not open file " << (pGe.gDir+"/chrName.txt") <<"\n";
        errOut << "SOLUTION: re-generate genome files with STAR --runMode genomeGenerate\n";
        exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_INPUT_FILES, P);
    };

    char chrInChar[1000];

    while (chrStreamIn.good()) {
        string chrIn;
        chrStreamIn.getline(chrInChar,1000);
        chrIn=chrInChar;
        if (chrIn=="") break;
        chrName.push_back(chrIn);
    };
    chrStreamIn.close();
    nChrReal=chrName.size();

    P.inOut->logMain << "Number of real (reference) chromosomes= " << nChrReal <<"\n"<<flush;
    chrStart.resize(nChrReal+1);
    chrLength.resize(nChrReal);

    //load chr lengths
    chrStreamIn.open( (pGe.gDir+"/chrLength.txt").c_str() );
    if (chrStreamIn.fail()) {
        ostringstream errOut;
        errOut << "EXITING because of FATAL error, could not open file " << (pGe.gDir+"/chrLength.txt") <<"\n";
        errOut << "SOLUTION: re-generate genome files with STAR --runMode genomeGenerate\n";
        exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_INPUT_FILES, P);
    };

    for  (uint ii=0;ii<nChrReal;ii++) {
        chrStreamIn >> chrLength[ii];
    };
    chrStreamIn.close();

    //load chr starts
    chrStreamIn.open( (pGe.gDir+"/chrStart.txt").c_str() );
    if (chrStreamIn.fail()) {
        ostringstream errOut;
        errOut << "EXITING because of FATAL error, could not open file " << (pGe.gDir+"/chrStart.txt") <<"\n";
        errOut << "SOLUTION: re-generate genome files with STAR --runMode genomeGenerate\n";
        exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_INPUT_FILES, P);
    };

    for  (uint ii=0;ii<=nChrReal;ii++) {
        chrStreamIn >> chrStart[ii];
    };
    chrStreamIn.close();

    //log
    for (uint ii=0; ii<nChrReal;ii++) {
        P.inOut->logMain << ii+1 <<"\t"<< chrName[ii] <<"\t"<<chrLength[ii]<<"\t"<<chrStart[ii]<<"\n"<<flush;
        chrNameIndex[chrName[ii]]=ii;
    };

    //chr sets
    for (auto &cm: pGe.chrSet.mitoStrings) {
        uint64 ind1 = std::find(chrName.begin(), chrName.end(), cm) - chrName.begin();
        pGe.chrSet.mito.insert(ind1);
    };

};

//////////////////////////////////////////////////////////
void Genome::chrBinFill() {
    chrBinN = chrStart[nChrReal]/genomeChrBinNbases+1;
    chrBin = new uint [chrBinN];
    for (uint ii=0, ichr=1; ii<chrBinN; ++ii) {
        if (ii*genomeChrBinNbases>=chrStart[ichr]) ichr++;
        chrBin[ii]=ichr-1;
    };
};

//////////////////////////////////////////////////////////
void Genome::genomeSequenceAllocate(uint64 nGenomeIn, uint64 &nG1allocOut, char*& Gout, char*& G1out)
{
    nG1allocOut=(nGenomeIn + 100)*2; //extra 100 bytes at the beginning, just in case

    if (P.limitGenomeGenerateRAM < (nG1allocOut+nG1allocOut/3)) {//allocate nG1alloc/3 for SA generation
        ostringstream errOut;
        errOut <<"EXITING because of FATAL PARAMETER ERROR: limitGenomeGenerateRAM="<< (P.limitGenomeGenerateRAM) <<"is too small for your genome\n";
        errOut <<"SOLUTION: please specify --limitGenomeGenerateRAM not less than "<< nG1allocOut+nG1allocOut/3 <<" and make that much RAM available \n";
        exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_INPUT_FILES, P);
    };

    G1out=new char[nG1allocOut];
    Gout=G1out+100;

    memset(G1out,GENOME_spacingChar,nG1allocOut);//initialize to K-1 all bytes
};
<commit_msg>Increased entropy of shmKey to avoid collisions between genomes.<commit_after>#include "Genome.h"
#include "SuffixArrayFuns.h"
#include "PackedArray.h"
#include "ErrorWarning.h"
#include "streamFuns.h"
#include "SharedMemory.h"
#include "genomeScanFastaFiles.h"

#include <time.h>
#include <cmath>
#include <unistd.h>
#include <sys/stat.h>

Genome::Genome (Parameters &P, ParametersGenome &pGe): shmStart(NULL), P(P), pGe(pGe), sharedMemory(NULL)
{
    struct stat stbuf;
    stat(pGe.gDir.c_str(), &stbuf);
    shmKey=stbuf.st_ino;
    genomeOut.g=this;//will change if genomeOut is different from genomeMain
    genomeOut.convYes=false;
    sjdbOverhang = pGe.sjdbOverhang; //will be re-defined later if another value was used for the generated genome
    sjdbLength = pGe.sjdbOverhang==0 ? 0 : pGe.sjdbOverhang*2+1;
};

// Genome::~Genome()
// {
//     if (sharedMemory != NULL)
//         delete sharedMemory;
//     sharedMemory = NULL;
// }

void Genome::freeMemory(){//free big chunks of memory used by genome and suffix array

    if (pGe.gLoad=="NoSharedMemory") {//can deallocate only for non-shared memory
        delete[] G1;
        G1=NULL;
        SA.deallocateArray();
        SApass2.deallocateArray();
        SAi.deallocateArray();
    };
};

uint Genome::OpenStream(string name, ifstream & stream, uint size)
{
    stream.open((pGe.gDir+ "/" +name).c_str(), ios::binary);
    if (!stream.good()) {
        ostringstream errOut;
        errOut << "EXITING because of FATAL ERROR: could not open genome file: "<< pGe.gDir << "/" << name <<"\n";
        errOut << "SOLUTION: check that the path to genome files, specified in --genomeDir is correct and the files are present, and have user read permissions\n" <<flush;
        exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_GENOME_FILES, P);
    };

    if (size>0) {
        P.inOut->logMain << name << ": size given as a parameter = " << size <<"\n";
    } else {
        P.inOut->logMain << "Checking " << name << " size";
        stream.seekg (0, ios::end);
        int64 size1 = stream.tellg();
        if (size1<=0) {
            ostringstream errOut;
            errOut << "EXITING because of FATAL ERROR: failed reading from genome file: "<< pGe.gDir << "/" << name <<"\n";
            errOut << "SOLUTION: re-generate the genome index\n";
            exitWithError(errOut.str(),std::cerr, P.inOut->logMain, 1, P);
        };
        size=(uint) size1;
        stream.clear();
        stream.seekg (0, ios::beg);
        P.inOut->logMain << "file size: "<< size <<" bytes; state: good=" <<stream.good()\
                <<" eof="<<stream.eof()<<" fail="<<stream.fail()<<" bad="<<stream.bad()<<"\n"<<flush;
    };

    return size;
};

void Genome::HandleSharedMemoryException(const SharedMemoryException & exc, uint64 shmSize)
{
    ostringstream errOut;
    errOut << "Shared memory error: " << exc.GetErrorCode() << ", errno: " << strerror(exc.GetErrorDetail()) << "(" << errno << ")" << endl;

    int exitCode = EXIT_CODE_SHM;
    switch (exc.GetErrorCode())
    {
        case EOPENFAILED:
            errOut << "EXITING because of FATAL ERROR: problems with shared memory: error from shmget() or shm_open()." << endl << flush;
            errOut << "SOLUTION: check shared memory settings as explained in STAR manual, OR run STAR with --genomeLoad NoSharedMemory to avoid using shared memory" << endl << flush;
            break;
        case EEXISTS:
            errOut << "EXITING: fatal error from shmget() trying to allocate shared memory piece." << endl;
            errOut << "Possible cause 1: not enough RAM. Check if you have enough RAM of at least " << shmSize+2000000000 << " bytes" << endl;
            errOut << "Possible cause 2: not enough virtual memory allowed with ulimit. SOLUTION: run ulimit -v " <<  shmSize+2000000000 << endl;
            errOut << "Possible cause 3: allowed shared memory size is not large enough. SOLUTIONS: (i) consult STAR manual on how to increase shared memory allocation; " \
            "(ii) ask your system administrator to increase shared memory allocation; (iii) run STAR with --genomeLoad NoSharedMemory" << endl<<flush;
            break;
        case EFTRUNCATE:
            errOut << "EXITING: fatal error from ftruncate() error shared memory."  << endl;
            errOut << "Possible cause 1: not enough RAM. Check if you have enough RAM of at least " << shmSize+2000000000 << " bytes" << endl << flush;
            exitCode = EXIT_CODE_MEMORY_ALLOCATION;
            break;
        case EMAPFAILED:
            errOut << "EXITING because of FATAL ERROR: problems with shared memory: error from shmat() while trying to get address of the shared memory piece." << endl << flush;
            errOut << "SOLUTION: check shared memory settings as explained in STAR manual, OR run STAR with --genomeLoad NoSharedMemory to avoid using shared memory" << endl << flush;
            break;
        case ECLOSE:
            errOut << "EXITING because of FATAL ERROR: could not close the shared memory object." << endl << flush;
            break;
        case EUNLINK:
            #ifdef POSIX_SHARED_MEM
            errOut << "EXITING because of FATAL ERROR:  could not delete the shared object." << endl << flush;
            #else
            errOut << "EXITING because of FATAL ERROR: problems with shared memory: error from shmctl() while trying to remove shared memory piece." << endl << flush;
            errOut << "SOLUTION: check shared memory settings as explained in STAR manual, OR run STAR with --genomeLoad NoSharedMemory to avoid using shared memory" << endl << flush;
            #endif
            break;
        default:
            errOut << "EXITING because of FATAL ERROR: There was an issue with the shared memory allocation. Try running STAR with --genomeLoad NoSharedMemory to avoid using shared memory.";
            break;
    }

    try
    {
        if (sharedMemory != NULL)
            sharedMemory->Clean();
    }
    catch(...)
    {}

    exitWithError(errOut.str(),std::cerr, P.inOut->logMain, exitCode, P);
};

//////////////////////////////////////////////////////////////////////////////////////////
void Genome::chrInfoLoad() {//find chrStart,Length,nChr from Genome G

    //load chr names
    ifstream chrStreamIn ( (pGe.gDir+"/chrName.txt").c_str() );
    if (chrStreamIn.fail()) {
        ostringstream errOut;
        errOut << "EXITING because of FATAL error, could not open file " << (pGe.gDir+"/chrName.txt") <<"\n";
        errOut << "SOLUTION: re-generate genome files with STAR --runMode genomeGenerate\n";
        exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_INPUT_FILES, P);
    };

    char chrInChar[1000];

    while (chrStreamIn.good()) {
        string chrIn;
        chrStreamIn.getline(chrInChar,1000);
        chrIn=chrInChar;
        if (chrIn=="") break;
        chrName.push_back(chrIn);
    };
    chrStreamIn.close();
    nChrReal=chrName.size();

    P.inOut->logMain << "Number of real (reference) chromosomes= " << nChrReal <<"\n"<<flush;
    chrStart.resize(nChrReal+1);
    chrLength.resize(nChrReal);

    //load chr lengths
    chrStreamIn.open( (pGe.gDir+"/chrLength.txt").c_str() );
    if (chrStreamIn.fail()) {
        ostringstream errOut;
        errOut << "EXITING because of FATAL error, could not open file " << (pGe.gDir+"/chrLength.txt") <<"\n";
        errOut << "SOLUTION: re-generate genome files with STAR --runMode genomeGenerate\n";
        exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_INPUT_FILES, P);
    };

    for  (uint ii=0;ii<nChrReal;ii++) {
        chrStreamIn >> chrLength[ii];
    };
    chrStreamIn.close();

    //load chr starts
    chrStreamIn.open( (pGe.gDir+"/chrStart.txt").c_str() );
    if (chrStreamIn.fail()) {
        ostringstream errOut;
        errOut << "EXITING because of FATAL error, could not open file " << (pGe.gDir+"/chrStart.txt") <<"\n";
        errOut << "SOLUTION: re-generate genome files with STAR --runMode genomeGenerate\n";
        exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_INPUT_FILES, P);
    };

    for  (uint ii=0;ii<=nChrReal;ii++) {
        chrStreamIn >> chrStart[ii];
    };
    chrStreamIn.close();

    //log
    for (uint ii=0; ii<nChrReal;ii++) {
        P.inOut->logMain << ii+1 <<"\t"<< chrName[ii] <<"\t"<<chrLength[ii]<<"\t"<<chrStart[ii]<<"\n"<<flush;
        chrNameIndex[chrName[ii]]=ii;
    };

    //chr sets
    for (auto &cm: pGe.chrSet.mitoStrings) {
        uint64 ind1 = std::find(chrName.begin(), chrName.end(), cm) - chrName.begin();
        pGe.chrSet.mito.insert(ind1);
    };

};

//////////////////////////////////////////////////////////
void Genome::chrBinFill() {
    chrBinN = chrStart[nChrReal]/genomeChrBinNbases+1;
    chrBin = new uint [chrBinN];
    for (uint ii=0, ichr=1; ii<chrBinN; ++ii) {
        if (ii*genomeChrBinNbases>=chrStart[ichr]) ichr++;
        chrBin[ii]=ichr-1;
    };
};

//////////////////////////////////////////////////////////
void Genome::genomeSequenceAllocate(uint64 nGenomeIn, uint64 &nG1allocOut, char*& Gout, char*& G1out)
{
    nG1allocOut=(nGenomeIn + 100)*2; //extra 100 bytes at the beginning, just in case

    if (P.limitGenomeGenerateRAM < (nG1allocOut+nG1allocOut/3)) {//allocate nG1alloc/3 for SA generation
        ostringstream errOut;
        errOut <<"EXITING because of FATAL PARAMETER ERROR: limitGenomeGenerateRAM="<< (P.limitGenomeGenerateRAM) <<"is too small for your genome\n";
        errOut <<"SOLUTION: please specify --limitGenomeGenerateRAM not less than "<< nG1allocOut+nG1allocOut/3 <<" and make that much RAM available \n";
        exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_INPUT_FILES, P);
    };

    G1out=new char[nG1allocOut];
    Gout=G1out+100;

    memset(G1out,GENOME_spacingChar,nG1allocOut);//initialize to K-1 all bytes
};
<|endoftext|>


<commit_before>/** @file
    @brief Implementation

    @date 2015

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2015 Sensics, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Internal Includes
#include "HDKLedIdentifierFactory.h"
#include "HDKLedIdentifier.h"

// Library/third-party includes
#include <boost/assert.hpp>

// Standard includes
// - none

namespace osvr {
namespace vbtracker {

    /// @brief Helper for factory function.
    static inline LedIdentifierPtr
    createHDKLedIdentifier(const PatternStringList &patterns) {
        LedIdentifierPtr ret{new OsvrHdkLedIdentifier(patterns)};
        return ret;
    }

    // clang-format off
    /// @brief Determines the LED IDs for the OSVR HDK sensor 0 (face plate)
    static const std::vector<std::string>
        OsvrHdkLedIdentifier_SENSOR0_PATTERNS = {
              "..*.....*...*..."    //  7
            , "...*......*...*."    //  8
            , ".......*...*...*"    //  9
            , "......*...*..*.."    // 10
            , ".......*....*..*"    // 11
            , "..*.....*..*...."    // 12
            , "....*......*..*."    // 13
            , "....*..*....*..."    // 14
            , "..*...*........*"    // 15
            , "........*..*..*."    // 16
            , "..*..*.*........"    // 17
            , "....*...*.*....."    // 18
            , "...*.*........*."    // 19
            , "...*.....*.*...."    // 20
            , "....*.*......*.."    // 21
            , "*.......*.*....."    // 22
            , ".*........*.*..."    // 23
            , ".*.........*.*.."    // 24
            , "....*.*..*......"    // 25
            , ".*.*.*.........."    // 26
            , ".........*.**..."    // 27
            , "**...........*.."    // 28
            , ".*...**........."    // 29
            , ".........*....**"    // 30
            , "..*.....**......"    // 31
            , "*......**......."    // 32
            , "...*.......**..."    // 33
            , "...**.....*....."    // 34
            , ".**....*........"    // 35
            , "....**...*......"    // 36
            , "*...........**.."    // 37
            , "......**.*......"    // 38
            , ".............***"    // 39
            , "..........*....."    // 40
    };

    /// @brief Determines the LED IDs for the OSVR HDK sensor 1 (back plate)
    static const std::vector<std::string>
        OsvrHdkLedIdentifier_SENSOR1_PATTERNS = {
              "***...*........*"    //  1
            , "...****..*......"    //  2
            , "*.*..........***"    //  3
            , "**...........***"    //  4
            , "*....*....*....."    //  5
            , "...*....*...*..."    //  6
    };
    // clang-format on

    LedIdentifierPtr createHDKLedIdentifier(uint8_t sensor) {
        LedIdentifierPtr ret;
        switch (sensor) {
        case 0:
            ret = createHDKLedIdentifier(OsvrHdkLedIdentifier_SENSOR0_PATTERNS);
            break;
        case 1:
            ret = createHDKLedIdentifier(OsvrHdkLedIdentifier_SENSOR1_PATTERNS);
        default:
            BOOST_ASSERT_MSG(sensor < 2, "Valid sensors are only 0 or 1!");
            break;
        }
        return ret;
    }

    // clang-format off
    /// @brief Patterns found in the "HDK_random_images" folder, which has only
    /// 8 images for each and they are a random subset of the actual images.
    static const std::vector<std::string>
        OsvrHdkLedIdentifier_RANDOM_IMAGES_PATTERNS = {
              "..*....." // 7
            , "...*...." // 8
            , ".......*" // 9
            , "......*." // 10
            , ".......*" // 11
            , "..*....." // 12
            , "....*..." // 13
            , "....*..*" // 14
            , "********" // 15
            , "........" // 16
            , "********" // 17
            , "....*..." // 18
            , "...*.*.." // 19
            , "...*...." // 20
            , "....*.*." // 21
            , "...*.***" // 22
            , ".*......" // 23
            , "..*...*." // 24
            , "....*.*." // 25
            , ".*.*.*.." // 26
            , "........" // 27
            , "**......" // 28
            , ".*...**." // 29
            , "........" // 30
            , "..*....." // 31
            , "*......*" // 32
            , "...*...." // 33
            , "...**..." // 34
            , ".......*" // 35
            , "*..*..*." // 36
            , "*......." // 37
            , "......**" // 38
            , "........" // 39
            , "........" // 40
    };
    // clang-format on
    LedIdentifierPtr createRandomHDKLedIdentifier() {
        return createHDKLedIdentifier(
            OsvrHdkLedIdentifier_RANDOM_IMAGES_PATTERNS);
    }
} // End namespace vbtracker
} // End namespace osvr
<commit_msg>Starting to rearrange the LED patterns to match what is actually seen on the unit.<commit_after>/** @file
    @brief Implementation

    @date 2015

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2015 Sensics, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Internal Includes
#include "HDKLedIdentifierFactory.h"
#include "HDKLedIdentifier.h"

// Library/third-party includes
#include <boost/assert.hpp>

// Standard includes
// - none

namespace osvr {
namespace vbtracker {

    /// @brief Helper for factory function.
    static inline LedIdentifierPtr
    createHDKLedIdentifier(const PatternStringList &patterns) {
        LedIdentifierPtr ret{new OsvrHdkLedIdentifier(patterns)};
        return ret;
    }

    // clang-format off
    /// @brief Determines the LED IDs for the OSVR HDK sensor 0 (face plate)
    /// These estimates are from the original documentation, not from the
    /// as-built measurements.
    /// First number in comments is overall LED ID, second is LED ID in the
    /// sensor it was in
    static const std::vector<std::string>
        OsvrHdkLedIdentifier_SENSOR0_PATTERNS_ORIGINAL = {
              "..*.....*...*..."    //  7  1
            , "...*......*...*."    //  8  2
            , ".......*...*...*"    //  9  3
            , "......*...*..*.."    // 10  4
            , ".......*....*..*"    // 11  5
            , "..*.....*..*...."    // 12  6
            , "....*......*..*."    // 13  7
            , "....*..*....*..."    // 14  8
            , "..*...*........*"    // 15  9
            , "........*..*..*."    // 16 10
            , "..*..*.*........"    // 17 11
            , "....*...*.*....."    // 18 12
            , "...*.*........*."    // 19 13
            , "...*.....*.*...."    // 20 14
            , "....*.*......*.."    // 21 15
            , "*.......*.*....."    // 22 16
            , ".*........*.*..."    // 23 17
            , ".*.........*.*.."    // 24 18
            , "....*.*..*......"    // 25 19
            , ".*.*.*.........."    // 26 20
            , ".........*.**..."    // 27 21
            , "**...........*.."    // 28 22
            , ".*...**........."    // 29 23
            , ".........*....**"    // 30 24
            , "..*.....**......"    // 31 25
            , "*......**......."    // 32 26
            , "...*.......**..."    // 33 27
            , "...**.....*....."    // 34 28
            , ".**....*........"    // 35 29
            , "....**...*......"    // 36 30
            , "*...........**.."    // 37 31
            , "......**.*......"    // 38 32
            , ".............***"    // 39 33
            , "..........*....."    // 40 34
    };

    /// @brief Determines the LED IDs for the OSVR HDK sensor 1 (back plate)
    /// These estimates are from the original documentation, not from the
    /// as-built measurements.
    static const std::vector<std::string>
        OsvrHdkLedIdentifier_SENSOR1_PATTERNS_ORIGINAL = {
              "***...*........*"    //  1  1
            , "...****..*......"    //  2  2
            , "*.*..........***"    //  3  3
            , "**...........***"    //  4  4
            , "*....*....*....."    //  5  5
            , "...*....*...*..."    //  6  6
    };

    /// @brief Determines the LED IDs for the OSVR HDK sensor 0 (face plate)
    /// These are from the as-built measurements.
    /// First number in comments is overall LED ID, second is LED ID in the
    /// sensor it was in
    static const std::vector<std::string>
        OsvrHdkLedIdentifier_SENSOR0_PATTERNS = {
        /// @todo Not checked below here
          "***...*........*"    //  1  1
        , "...****..*......"    //  2  2
        , "*.*..........***"    //  3  3
        , "**...........***"    //  4  4
        , "*....*....*....."    //  5  5
        , "...*....*...*..."    //  6  6
        , "..*.....*...*..."    //  7  1
        , "...*......*...*."    //  8  2
        , ".......*...*...*"    //  9  3
        , "......*...*..*.."    // 10  4
        , ".......*....*..*"    // 11  5
        , "..*.....*..*...."    // 12  6
        , "....*......*..*."    // 13  7
        , "....*..*....*..."    // 14  8
        , "..*...*........*"    // 15  9
        , "........*..*..*."    // 16 10
        , "..*..*.*........"    // 17 11
        , "....*...*.*....."    // 18 12
        , "...*.*........*."    // 19 13
        , "...*.....*.*...."    // 20 14
        , "....*.*......*.."    // 21 15
        , "*.......*.*....."    // 22 16
        , ".*........*.*..."    // 23 17
        , ".*.........*.*.."    // 24 18
        , "....*.*..*......"    // 25 19
        , ".*.*.*.........."    // 26 20
        , ".........*.**..."    // 27 21
        , "**...........*.."    // 28 22
        , ".*...**........."    // 29 23
        , ".........*....**"    // 30 24
        , "..*.....**......"    // 31 25
        , "*......**......."    // 32 26
        , ".**....*........"    // 35 29
        , "....**...*......"    // 36 30
    };

    /// @brief Determines the LED IDs for the OSVR HDK sensor 1 (back plate)
    /// These are from the as-built measurements.
    static const std::vector<std::string>
        OsvrHdkLedIdentifier_SENSOR1_PATTERNS = {
          "*...........**.."    // 37 31
        , "...**.....*....."    // 34 28
        , "...*.......**..."    // 33 27
        , "..........*....."    // 40 34
        , ".............***"    // 39 33
        , "......**.*......"    // 38 32
    };
    // clang-format on

    LedIdentifierPtr createHDKLedIdentifier(uint8_t sensor) {
        LedIdentifierPtr ret;
        switch (sensor) {
        case 0:
            ret = createHDKLedIdentifier(OsvrHdkLedIdentifier_SENSOR0_PATTERNS);
            break;
        case 1:
            ret = createHDKLedIdentifier(OsvrHdkLedIdentifier_SENSOR1_PATTERNS);
        default:
            BOOST_ASSERT_MSG(sensor < 2, "Valid sensors are only 0 or 1!");
            break;
        }
        return ret;
    }

    // clang-format off
    /// @brief Patterns found in the "HDK_random_images" folder, which has only
    /// 8 images for each and they are a random subset of the actual images.
    static const std::vector<std::string>
        OsvrHdkLedIdentifier_RANDOM_IMAGES_PATTERNS = {
              "..*....." // 7
            , "...*...." // 8
            , ".......*" // 9
            , "......*." // 10
            , ".......*" // 11
            , "..*....." // 12
            , "....*..." // 13
            , "....*..*" // 14
            , "********" // 15
            , "........" // 16
            , "********" // 17
            , "....*..." // 18
            , "...*.*.." // 19
            , "...*...." // 20
            , "....*.*." // 21
            , "...*.***" // 22
            , ".*......" // 23
            , "..*...*." // 24
            , "....*.*." // 25
            , ".*.*.*.." // 26
            , "........" // 27
            , "**......" // 28
            , ".*...**." // 29
            , "........" // 30
            , "..*....." // 31
            , "*......*" // 32
            , "...*...." // 33
            , "...**..." // 34
            , ".......*" // 35
            , "*..*..*." // 36
            , "*......." // 37
            , "......**" // 38
            , "........" // 39
            , "........" // 40
    };
    // clang-format on
    LedIdentifierPtr createRandomHDKLedIdentifier() {
        return createHDKLedIdentifier(
            OsvrHdkLedIdentifier_RANDOM_IMAGES_PATTERNS);
    }
} // End namespace vbtracker
} // End namespace osvr
<|endoftext|>