<commit_before>#include "selected_bounds_gizmo.h"

#include <components/sprite_component.h>

#include "halley/core/graphics/material/material.h"
#include "halley/core/graphics/material/material_definition.h"
#include "halley/core/graphics/painter.h"
#include "halley/core/resources/resources.h"
using namespace Halley;

SelectedBoundsGizmo::SelectedBoundsGizmo(SnapRules snapRules, Resources& resources)
	: SceneEditorGizmo(snapRules)
{
	stencilMaterial = std::make_shared<Material>(resources.get<MaterialDefinition>("Halley/SelectionStencil"));
	outlineMaterial = std::make_shared<Material>(resources.get<MaterialDefinition>("Halley/SelectionOutline"));
}

void SelectedBoundsGizmo::update(Time time, const ISceneEditor& sceneEditor, const SceneEditorInputState& inputState)
{
}

void SelectedBoundsGizmo::draw(Painter& painter, const ISceneEditor& sceneEditor) const
{
	for (auto& e: getEntities()) {
		drawEntity(painter, e, sceneEditor);
	}
}

bool SelectedBoundsGizmo::shouldInclude(const Sprite& sprite, const ISceneEditor& sceneEditor) const
{
	if (!sprite.hasMaterial() || !sprite.isVisible()) {
		return false;
	}

	return sceneEditor.shouldDrawOutline(sprite);
}

void SelectedBoundsGizmo::drawEntity(Painter& painter, EntityRef entity, const ISceneEditor& sceneEditor) const
{
	painter.clear({}, {}, 0);
	drawStencilTree(painter, entity, sceneEditor);
	drawOutlineTree(painter, entity, sceneEditor);
}

void SelectedBoundsGizmo::drawStencilTree(Painter& painter, EntityRef entity, const ISceneEditor& sceneEditor) const
{
	if (const auto* sprite = entity.tryGetComponent<SpriteComponent>()) {
		if (shouldInclude(sprite->sprite, sceneEditor)) {
			drawStencilSprite(painter, sprite->sprite);
		}
	}
	for (const auto c: entity.getChildren()) {
		drawStencilTree(painter, c, sceneEditor);
	}
}

void SelectedBoundsGizmo::drawOutlineTree(Painter& painter, EntityRef entity, const ISceneEditor& sceneEditor) const
{
	if (const auto* sprite = entity.tryGetComponent<SpriteComponent>()) {
		if (shouldInclude(sprite->sprite, sceneEditor)) {
			drawOutlineSprite(painter, sprite->sprite);
		}
	}
	for (const auto c: entity.getChildren()) {
		drawOutlineTree(painter, c, sceneEditor);
	}
}

void SelectedBoundsGizmo::drawStencilSprite(Painter& painter, const Sprite& sprite) const
{
	Sprite s = sprite;
	s.setMaterial(stencilMaterial->clone());
	s.getMutableMaterial().set(0, sprite.getMaterial().getTexture(0));
	s.draw(painter);
}

void SelectedBoundsGizmo::drawOutlineSprite(Painter& painter, const Sprite& sprite) const
{
	const auto tex0 = sprite.getMaterial().getTexture(0);

	const auto zoom = getZoom();
	const float outline = 2 / zoom;
	const float padding = std::ceil(outline);

	const auto texelSize = Vector2f(1.0f, 1.0f) / Vector2f(tex0->getSize());
	const auto ro = padding * texelSize;
	const auto texRect1 = Rect4f(-ro, Vector2f(1, 1) + ro);
	const auto newSize = sprite.getSize() + 2 * Vector2f(padding, padding);

	const auto texGrad0 = texelSize / zoom;
	const auto texGrad1 = texRect1.getSize() / newSize;
	const auto texGrads = Vector4f(texGrad0.x, texGrad0.y, texGrad1.x, texGrad1.y);

	Sprite s = sprite;
	s.setMaterial(outlineMaterial->clone());
	s.setColour(Colour4f(1, 0, 1, 1));
	s.getMutableMaterial().set(0, tex0);
	s.setCustom0(texGrads);
	s.setTexRect1(Rect4f(0, 0, 1, 1));
	s.crop(Vector4f(-padding, -padding, -padding, -padding));

	s.draw(painter);
}
<commit_msg>Fix crash with scale 0 selected entities<commit_after>#include "selected_bounds_gizmo.h"

#include <components/sprite_component.h>

#include "halley/core/graphics/material/material.h"
#include "halley/core/graphics/material/material_definition.h"
#include "halley/core/graphics/painter.h"
#include "halley/core/resources/resources.h"
using namespace Halley;

SelectedBoundsGizmo::SelectedBoundsGizmo(SnapRules snapRules, Resources& resources)
	: SceneEditorGizmo(snapRules)
{
	stencilMaterial = std::make_shared<Material>(resources.get<MaterialDefinition>("Halley/SelectionStencil"));
	outlineMaterial = std::make_shared<Material>(resources.get<MaterialDefinition>("Halley/SelectionOutline"));
}

void SelectedBoundsGizmo::update(Time time, const ISceneEditor& sceneEditor, const SceneEditorInputState& inputState)
{
}

void SelectedBoundsGizmo::draw(Painter& painter, const ISceneEditor& sceneEditor) const
{
	for (auto& e: getEntities()) {
		drawEntity(painter, e, sceneEditor);
	}
}

bool SelectedBoundsGizmo::shouldInclude(const Sprite& sprite, const ISceneEditor& sceneEditor) const
{
	if (!sprite.hasMaterial() || !sprite.isVisible()) {
		return false;
	}

	const auto scale = sprite.getScale().abs();
	if (scale.x < 0.0001f || scale.y < 0.0001f) {
		return false;
	}

	return sceneEditor.shouldDrawOutline(sprite);
}

void SelectedBoundsGizmo::drawEntity(Painter& painter, EntityRef entity, const ISceneEditor& sceneEditor) const
{
	painter.clear({}, {}, 0);
	drawStencilTree(painter, entity, sceneEditor);
	drawOutlineTree(painter, entity, sceneEditor);
}

void SelectedBoundsGizmo::drawStencilTree(Painter& painter, EntityRef entity, const ISceneEditor& sceneEditor) const
{
	if (const auto* sprite = entity.tryGetComponent<SpriteComponent>()) {
		if (shouldInclude(sprite->sprite, sceneEditor)) {
			drawStencilSprite(painter, sprite->sprite);
		}
	}
	for (const auto c: entity.getChildren()) {
		drawStencilTree(painter, c, sceneEditor);
	}
}

void SelectedBoundsGizmo::drawOutlineTree(Painter& painter, EntityRef entity, const ISceneEditor& sceneEditor) const
{
	if (const auto* sprite = entity.tryGetComponent<SpriteComponent>()) {
		if (shouldInclude(sprite->sprite, sceneEditor)) {
			drawOutlineSprite(painter, sprite->sprite);
		}
	}
	for (const auto c: entity.getChildren()) {
		drawOutlineTree(painter, c, sceneEditor);
	}
}

void SelectedBoundsGizmo::drawStencilSprite(Painter& painter, const Sprite& sprite) const
{
	Sprite s = sprite;
	s.setMaterial(stencilMaterial->clone());
	s.getMutableMaterial().set(0, sprite.getMaterial().getTexture(0));
	s.draw(painter);
}

void SelectedBoundsGizmo::drawOutlineSprite(Painter& painter, const Sprite& sprite) const
{
	const auto tex0 = sprite.getMaterial().getTexture(0);

	const auto zoom = getZoom();
	const float outline = 2 / zoom;
	const float padding = std::ceil(outline);

	const auto texelSize = Vector2f(1.0f, 1.0f) / Vector2f(tex0->getSize());
	const auto ro = padding * texelSize;
	const auto texRect1 = Rect4f(-ro, Vector2f(1, 1) + ro);
	const auto newSize = sprite.getSize() + 2 * Vector2f(padding, padding);

	const auto texGrad0 = texelSize / zoom;
	const auto texGrad1 = texRect1.getSize() / newSize;
	const auto texGrads = Vector4f(texGrad0.x, texGrad0.y, texGrad1.x, texGrad1.y);

	Sprite s = sprite;
	s.setMaterial(outlineMaterial->clone());
	s.setColour(Colour4f(1, 0, 1, 1));
	s.getMutableMaterial().set(0, tex0);
	s.setCustom0(texGrads);
	s.setTexRect1(Rect4f(0, 0, 1, 1));
	s.crop(Vector4f(-padding, -padding, -padding, -padding));

	s.draw(painter);
}
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <iterator>
#include <ctime>
#include <unordered_map>
#include <algorithm>
#include <cmath>
#include <chrono>
#include <iostream>
#include <fstream>
#include <string>
#include <iterator>
#include <unordered_map>
#include <unordered_set>
#include <set>
#include <algorithm>
#include <chrono>
#include <map>
#include <set>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

using namespace std;

char randomNucleotide(){
	switch (rand() % 4){
		case 0:
			return 'A';
		case 1:
			return 'C';
		case 2:
			return 'G';
		case 3:
			return 'T';
	}
	return 'A';
}

string randomSequence(const uint length){
	string result(length, 'A');
	for(uint i(0); i < length; ++i){
		result[i] = randomNucleotide();
	}
	return result;
}

void insertion(double rate, string& result){
	uint dice(rand() % 100);
	if(dice < rate){
		char newNucleotide(randomNucleotide());
		result.push_back(newNucleotide);
		insertion(rate, result);
	}
}

string mutateSequence(const string& referenceSequence, uint maxMutRate=0, vector <double> ratioMutation={0.06,0.73,0.21}){
//~ string mutateSequence(const string& referenceSequence, uint maxMutRate=3, vector <double> ratioMutation={0.06,0.73,0.21}){
	string result;
	result.reserve(5 * referenceSequence.size());
	for(uint i(0); i < referenceSequence.size(); ++i){
		uint mutRate(maxMutRate);
		//~ uint mutRate(rand() % maxMutRate);
		double substitutionRate(mutRate * ratioMutation[0]);
		double insertionRate(mutRate * ratioMutation[1]);
		double deletionRate(mutRate * ratioMutation[2]);
		uint dice(rand() % 100);

		if (dice <substitutionRate ){
			//SUBSTITUTION
			char newNucleotide(randomNucleotide());
			while(newNucleotide == referenceSequence[i]){
				newNucleotide = randomNucleotide();
			}
			result.push_back(newNucleotide);
			continue;
		} else if(dice < deletionRate+substitutionRate){
			//DELETION
			uint dice2(rand() % 100);
			while (dice2 < deletionRate+substitutionRate){ // deletions larger than 1
				++i;
				dice2 = rand() % 100;
			}
			continue;
		} else if (dice < deletionRate + substitutionRate + insertionRate){
			//INSERTION
			char newNucleotide(randomNucleotide());
			result.push_back(referenceSequence[i]);
			result.push_back(newNucleotide);
			//~ --i;
			insertion(deletionRate + substitutionRate + insertionRate, result); // larger than 1 insertions

			continue;
		} else {
		//NO ERROR
			result.push_back(referenceSequence[i]);
		}

	}
	return result;
}

//~ vector<string> generateAlternativeTranscriptReferences(uint transcriptNumber=3, uint totalExonNumber=15, uint exonNumber=6, uint sizeExons=100){
vector<vector<string>> generateAlternativeTranscriptReferences(ifstream& refFile, uint referenceNumber, uint transcriptNumber=3, uint totalExonNumber=14, uint exonNumber=10, uint sizeExons=200){
	string sequence;
	vector<vector<string>> result;
	uint nbRef(0);
	uint position(0);
	string transcript;
	unordered_set<uint> selectedExons;
	while (not refFile.eof() and nbRef < referenceNumber){
        getline(refFile, sequence);
		getline(refFile, sequence);
		uint lengthExons;
		if (sequence.size()/sizeExons < totalExonNumber){
			lengthExons = sequence.size()/(totalExonNumber+1);
		} else {
			lengthExons = sizeExons;
		}
		if (lengthExons > 30){
			position = 0;
			vector<string> exonList;
			uint i(0);
			while (i < totalExonNumber and position < sequence.size()){ // creation of exons from genomic sequence
				string exon(sequence.substr(position, lengthExons));
				exonList.push_back(exon);
				position += lengthExons;
				++i;
			}
			++nbRef;
			vector<string> transcriptList;
			for(uint i(0); i < transcriptNumber; ++i){
				uint dice1(rand() % (totalExonNumber - 3));
				uint transcriptExonNumber(dice1 + 3);
				transcript = "";
				selectedExons = {};
				while(selectedExons.size() != transcriptExonNumber){
					selectedExons.insert(rand() % exonList.size());
				}
				for(uint ii(0); ii < exonList.size(); ++ii){
					if(selectedExons.count(ii) == 1){
						transcript += exonList[ii];
					}
				}
				transcriptList.push_back(transcript);
			}
			result.push_back(transcriptList);
		}
	}
	return result;
}

unordered_map<uint, uint> geneExpressionChunks(uint referencesNumber, uint numberReads){
	uint nbMidExpressed, nbHighlyExpressed;
	if (referencesNumber > 1){
		nbMidExpressed = referencesNumber * 0.6; // code 1
		nbHighlyExpressed = referencesNumber * 0.1+1; // code 0
	} else {
		nbMidExpressed = 0;
		nbHighlyExpressed = 1;
	}

	unordered_map<uint, uint> result;
	cout << "high:" << nbHighlyExpressed << " medium:" << nbMidExpressed << " low:" <<  referencesNumber - nbMidExpressed - nbHighlyExpressed << endl;
	unordered_set<uint> refs;
	for (uint i(0); i < referencesNumber; ++i){
		refs.insert(i);
	}
	uint i(0);
	for (auto j (refs.begin()); j != refs.end(), i < nbHighlyExpressed;){
			result.insert({*j, 0});
			j = refs.erase(j);
			++i;
	}
	//~ i = 0;
	for (auto j (refs.begin()); j != refs.end(), i < nbMidExpressed + nbHighlyExpressed;){
			result.insert({*j, 1});
			j = refs.erase(j);
			++i;
	}
	//~ cout << "check size " << refs.size();
	for (auto j (refs.begin()); j != refs.end(); ++j){

			result.insert({*j, 2});
	}
	return result;
}

void generateReads(uint numberReads, ifstream& inRef, uint referencesNumber=1, const string& outFileName="simulatedReads.fa", const string& outRefFileName="RefFile"){
	ofstream out(outFileName);
	ofstream outRef(outRefFileName);
	vector<vector<string>> referenceList(generateAlternativeTranscriptReferences(inRef, referencesNumber));

	int highly, regular, rare;
	if (referencesNumber >1){
		highly = numberReads*0.5;
		regular = numberReads*0.4;
		rare= numberReads - highly - regular;
	} else {
		highly = numberReads;
		regular = 0;
		rare = 0;
	}

	unordered_map<uint, uint> geneExpression(geneExpressionChunks(referencesNumber, numberReads));

	cout << "nb reads:" << numberReads << " nb rare reads:" << rare << " nb regular reads:"<< regular << " nb high reads:"<< highly << endl;

	for(uint i(0);i < referenceList.size(); ++i){
		string expr;
		switch (geneExpression[i]){
		case 0:
			expr = "highExpression";
			break;
		case 1:
			expr = "regularExpression";
			break;
		case 2:
			expr = "shallowExpression";
			break;
		}
		for(uint ii(0); ii<referenceList[i].size(); ++ii){
			outRef << ">referenceNumber:" << i << " alternativeNumber" << ii << " " <<  expr <<endl;
			outRef << referenceList[i][ii] << endl;
		}
	}

	string refRead,realRead;
	int hi(0), re(0), ra(0);
	while (hi < highly or re < regular or ra < rare){
		uint dice1(rand() % referencesNumber);
		uint dice2(rand() % (referenceList[dice1].size() ));
		int expr(geneExpression[dice1]);
		if (expr == 0 and hi < highly){
			++hi;
			string expression = "highExpression";
			refRead = referenceList[dice1][dice2];
			realRead = mutateSequence(refRead);
			out << ">referenceNumber:" << dice1 << " alternativeNumber:" << dice2  << " " << expression << endl;
			out << realRead << endl;
		}
		if (expr == 1 and re < regular){
			++re;
			string expression = "regularExpression";
			refRead = referenceList[dice1][dice2];
			realRead = mutateSequence(refRead);
			out << ">referenceNumber:" << dice1 << " alternativeNumber:" << dice2  << " " << expression << endl;
			out << realRead << endl;
		}
		if (expr == 2 and ra < rare){
			++ra;
			string expression = "lowExpression";
			refRead = referenceList[dice1][dice2];
			realRead = mutateSequence(refRead);
			out << ">referenceNumber:" << dice1 << " alternativeNumber:" << dice2  << " " << expression << endl;
			out << realRead << endl;
		}
	}
}

int main(int argc, char ** argv){
	if (argc > 1){
		string refName = argv[1];
		ifstream refFile(refName);
		srand (time(NULL));
		auto startChrono = chrono::system_clock::now();
		generateReads(100, refFile);
		auto end = chrono::system_clock::now(); auto waitedFor = end - startChrono;
		cout << "Time  in ms : " << (chrono::duration_cast<chrono::milliseconds>(waitedFor).count()) << endl;
	}
	return 0;
}
<commit_msg>variables as parameters<commit_after>#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <iterator>
#include <ctime>
#include <unordered_map>
#include <algorithm>
#include <cmath>
#include <chrono>
#include <iostream>
#include <fstream>
#include <string>
#include <iterator>
#include <unordered_map>
#include <unordered_set>
#include <set>
#include <algorithm>
#include <chrono>
#include <map>
#include <set>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

using namespace std;

char randomNucleotide(){
	switch (rand() % 4){
		case 0:
			return 'A';
		case 1:
			return 'C';
		case 2:
			return 'G';
		case 3:
			return 'T';
	}
	return 'A';
}

string randomSequence(const uint length){
	string result(length, 'A');
	for(uint i(0); i < length; ++i){
		result[i] = randomNucleotide();
	}
	return result;
}

void insertion(double rate, string& result){
	uint dice(rand() % 100);
	if(dice < rate){
		char newNucleotide(randomNucleotide());
		result.push_back(newNucleotide);
		insertion(rate, result);
	}
}

string mutateSequence(const string& referenceSequence, uint maxMutRate, vector <double> ratioMutation={0.06,0.73,0.21}){
//~ string mutateSequence(const string& referenceSequence, uint maxMutRate=3, vector <double> ratioMutation={0.06,0.73,0.21}){
	string result;
	result.reserve(5 * referenceSequence.size());
	for(uint i(0); i < referenceSequence.size(); ++i){
		uint mutRate(maxMutRate);
		//~ uint mutRate(rand() % maxMutRate);
		double substitutionRate(mutRate * ratioMutation[0]);
		double insertionRate(mutRate * ratioMutation[1]);
		double deletionRate(mutRate * ratioMutation[2]);
		uint dice(rand() % 100);

		if (dice <substitutionRate ){
			//SUBSTITUTION
			char newNucleotide(randomNucleotide());
			while(newNucleotide == referenceSequence[i]){
				newNucleotide = randomNucleotide();
			}
			result.push_back(newNucleotide);
			continue;
		} else if(dice < deletionRate+substitutionRate){
			//DELETION
			uint dice2(rand() % 100);
			while (dice2 < deletionRate+substitutionRate){ // deletions larger than 1
				++i;
				dice2 = rand() % 100;
			}
			continue;
		} else if (dice < deletionRate + substitutionRate + insertionRate){
			//INSERTION
			char newNucleotide(randomNucleotide());
			result.push_back(referenceSequence[i]);
			result.push_back(newNucleotide);
			//~ --i;
			insertion(deletionRate + substitutionRate + insertionRate, result); // larger than 1 insertions

			continue;
		} else {
		//NO ERROR
			result.push_back(referenceSequence[i]);
		}

	}
	return result;
}

//~ vector<string> generateAlternativeTranscriptReferences(uint transcriptNumber=3, uint totalExonNumber=15, uint exonNumber=6, uint sizeExons=100){
vector<vector<string>> generateAlternativeTranscriptReferences(ifstream& refFile, uint referenceNumber, uint transcriptNumber=3, uint totalExonNumber=15, uint exonNumber=10, uint sizeExons=200){
	string sequence;
	vector<vector<string>> result;
	uint nbRef(0);
	uint position(0);
	string transcript;
	unordered_set<uint> selectedExons;
	while (not refFile.eof() and nbRef < referenceNumber){
        getline(refFile, sequence);
		getline(refFile, sequence);
		uint lengthExons;
		if (sequence.size()/sizeExons < totalExonNumber){
			lengthExons = sequence.size()/(totalExonNumber+1);
		} else {
			lengthExons = sizeExons;
		}
		if (lengthExons > 30){
			position = 0;
			vector<string> exonList;
			uint i(0);
			while (i < totalExonNumber and position < sequence.size()){ // creation of exons from genomic sequence
				string exon(sequence.substr(position, lengthExons));
				exonList.push_back(exon);
				position += lengthExons;
				++i;
			}
			++nbRef;
			vector<string> transcriptList;
			for(uint i(0); i < transcriptNumber; ++i){
				uint dice1(rand() % (totalExonNumber - 3));
				uint transcriptExonNumber(dice1 + 3);
				transcript = "";
				selectedExons = {};
				while(selectedExons.size() != transcriptExonNumber){
					selectedExons.insert(rand() % exonList.size());
				}
				for(uint ii(0); ii < exonList.size(); ++ii){
					if(selectedExons.count(ii) == 1){
						transcript += exonList[ii];
					}
				}
				transcriptList.push_back(transcript);
			}
			result.push_back(transcriptList);
		}
	}
	return result;
}

unordered_map<uint, uint> geneExpressionChunks(uint referencesNumber, uint numberReads){
	uint nbMidExpressed, nbHighlyExpressed;
	if (referencesNumber > 1){
		nbMidExpressed = referencesNumber * 0.6; // code 1
		nbHighlyExpressed = referencesNumber * 0.1+1; // code 0
	} else {
		nbMidExpressed = 0;
		nbHighlyExpressed = 1;
	}

	unordered_map<uint, uint> result;
	cout << "high:" << nbHighlyExpressed << " medium:" << nbMidExpressed << " low:" <<  referencesNumber - nbMidExpressed - nbHighlyExpressed << endl;
	unordered_set<uint> refs;
	for (uint i(0); i < referencesNumber; ++i){
		refs.insert(i);
	}
	uint i(0);
	for (auto j (refs.begin()); j != refs.end(), i < nbHighlyExpressed;){
			result.insert({*j, 0});
			j = refs.erase(j);
			++i;
	}
	//~ i = 0;
	for (auto j (refs.begin()); j != refs.end(), i < nbMidExpressed + nbHighlyExpressed;){
			result.insert({*j, 1});
			j = refs.erase(j);
			++i;
	}
	//~ cout << "check size " << refs.size();
	for (auto j (refs.begin()); j != refs.end(); ++j){

			result.insert({*j, 2});
	}
	return result;
}

void generateReads(uint numberReads, uint mutRate, uint referencesNumber, ifstream& inRef, const string& outFileName="simulatedReads.fa", const string& outRefFileName="RefFile"){
	ofstream out(outFileName);
	ofstream outRef(outRefFileName);
	vector<vector<string>> referenceList(generateAlternativeTranscriptReferences(inRef, referencesNumber));

	int highly, regular, rare;
	if (referencesNumber >1){
		highly = numberReads*0.5;
		regular = numberReads*0.4;
		rare= numberReads - highly - regular;
	} else {
		highly = numberReads;
		regular = 0;
		rare = 0;
	}

	unordered_map<uint, uint> geneExpression(geneExpressionChunks(referencesNumber, numberReads));

	cout << "nb reads:" << numberReads << " nb rare reads:" << rare << " nb regular reads:"<< regular << " nb high reads:"<< highly << endl;

	for(uint i(0);i < referenceList.size(); ++i){
		string expr;
		switch (geneExpression[i]){
		case 0:
			expr = "highExpression";
			break;
		case 1:
			expr = "regularExpression";
			break;
		case 2:
			expr = "shallowExpression";
			break;
		}
		for(uint ii(0); ii<referenceList[i].size(); ++ii){
			outRef << ">referenceNumber:" << i << " alternativeNumber" << ii << " " <<  expr <<endl;
			outRef << referenceList[i][ii] << endl;
		}
	}

	string refRead,realRead;
	int hi(0), re(0), ra(0);
	uint indexRead(1);
	while (hi < highly or re < regular or ra < rare){
		uint dice1(rand() % referencesNumber);
		uint dice2(rand() % (referenceList[dice1].size() ));
		int expr(geneExpression[dice1]);
		if (expr == 0 and hi < highly){
			++hi;
			string expression = "highExpression";
			refRead = referenceList[dice1][dice2];
			realRead = mutateSequence(refRead, mutRate);
			out << ">" <<indexRead << "_referenceNumber:" << dice1 << " alternativeNumber:" << dice2  << " " << expression << endl;
			out << realRead << endl;
			++indexRead;
		}
		if (expr == 1 and re < regular){
			++re;
			string expression = "regularExpression";
			refRead = referenceList[dice1][dice2];
			realRead = mutateSequence(refRead, mutRate);
			out << ">" <<  indexRead << "_referenceNumber:" << dice1 << " alternativeNumber:" << dice2  << " " << expression << endl;
			out << realRead << endl;
			++indexRead;
		}
		if (expr == 2 and ra < rare){
			++ra;
			string expression = "lowExpression";
			refRead = referenceList[dice1][dice2];
			realRead = mutateSequence(refRead, mutRate);
			out << ">" << indexRead << "_referenceNumber:" << dice1 << " alternativeNumber:" << dice2  << " " << expression << endl;
			out << realRead << endl;
			++indexRead;
		}
	}
}

int main(int argc, char ** argv){
	if (argc > 4){
		string refName = argv[1];
		uint nbReads(stoi(argv[2]));
		uint mut(stoi(argv[3]));
		uint genes(stoi(argv[4]));
		ifstream refFile(refName);
		srand (time(NULL));
		auto startChrono = chrono::system_clock::now();
		generateReads(nbReads, mut, genes, refFile);
		auto end = chrono::system_clock::now(); auto waitedFor = end - startChrono;
		cout << "Time  in ms : " << (chrono::duration_cast<chrono::milliseconds>(waitedFor).count()) << endl;
	} else {
		cout << "usage: ./theCreator_ref <ref_file.fa> <number_of_reads> <mutation_rate> <number_of_genes>" << endl;
	}
	return 0;
}
<|endoftext|>


<commit_before>
#include "WordprocessingDocument.h"

#include "../../Common/DocxFormat/Source/SystemUtility/SystemUtility.h"
#include "../../Common/DocxFormat/Source/SystemUtility/FileSystem/Directory.h"

#include "../../DesktopEditor/raster/BgraFrame.h"

namespace ImageHelper
{
	inline static int CompareStrings (const wchar_t* str1, const wchar_t* str2)
	{
		CString cstr1; cstr1 = str1;
		CString cstr2; cstr2 = str2;

		if (cstr1 == cstr2)
			return 0;

		return 1;
	}
	inline bool SaveImageToFileFromDIB(unsigned char* buffer, int size, const std::wstring& file)
	{
		bool result = false;
		const BITMAPINFOHEADER* info =	(BITMAPINFOHEADER*)buffer;

		if (NULL != info && info->biSize == 40)
		{
			unsigned char* pBgraData = buffer + sizeof(BITMAPINFOHEADER);

			int nWidth	= info->biWidth;
			int nHeight = info->biHeight;

			CBgraFrame oFrame;
			oFrame.put_Data		(pBgraData);
			oFrame.put_Width	(nWidth);
			oFrame.put_Height	(nHeight);

			int nStride = info->biSizeImage / nHeight;
			oFrame.put_Stride( -nStride );

			result = oFrame.SaveFile(file, 4);

			oFrame.put_Data(NULL);

		}

		return result;
	}
}

namespace DocFileFormat
{
	WordprocessingDocument::WordprocessingDocument(const wchar_t* _pathOutput, const WordDocument* _docFile) : OpenXmlPackage( _docFile ), FontTableXML( _T( "" ) ), DocumentXML( _T( "" ) ),
		StyleSheetXML( _T( "" ) ), FootnotesXML ( _T( "" ) ), NumberingXML( _T( "" ) ),
		CommentsXML( _T( "" ) ), SettingsXML( _T( "" ) ), CommandTableXML ( _T( "" ) )
	{
		m_strOutputPath = std::wstring(_pathOutput);
	}

	WordprocessingDocument::~WordprocessingDocument()
	{
	}

	void WordprocessingDocument::SaveDocument()
	{
		OOX::CPath pathWord = CString(m_strOutputPath.c_str()) + FILE_SEPARATOR_STR + _T( "word" );
		FileSystem::Directory::CreateDirectory( pathWord.GetPath() );

		WritePackage();

		//Write main content. (word directory)

		SaveToFile(string2std_string(pathWord.GetPath()), wstring( _T("document.xml" ) ),		DocumentXML );
		SaveToFile(string2std_string(pathWord.GetPath()), wstring( _T( "fontTable.xml" ) ),		FontTableXML );
		SaveToFile(string2std_string(pathWord.GetPath()), wstring( _T( "styles.xml" ) ),		StyleSheetXML );
		SaveToFile(string2std_string(pathWord.GetPath()), wstring( _T( "footnotes.xml" ) ),		FootnotesXML );
		SaveToFile(string2std_string(pathWord.GetPath()), wstring( _T( "endnotes.xml" ) ),		EndnotesXML );
		SaveToFile(string2std_string(pathWord.GetPath()), wstring( _T( "numbering.xml" ) ),		NumberingXML );
		SaveToFile(string2std_string(pathWord.GetPath()), wstring( _T( "comments.xml" ) ),		CommentsXML );
		SaveToFile(string2std_string(pathWord.GetPath()), wstring( _T( "settings.xml" ) ),		SettingsXML );
		SaveToFile(string2std_string(pathWord.GetPath()), wstring( _T( "customizations.xml" ) ),CommandTableXML );

		if (!ImagesList.empty())
		{
			OOX::CPath pathMedia = pathWord + FILE_SEPARATOR_STR + _T( "media" );

			FileSystem::Directory::CreateDirectory( pathMedia.GetPath() );

			int i = 1;

			for (list<ImageFileStructure>::iterator iter = ImagesList.begin(); iter != ImagesList.end(); ++iter)
			{
				unsigned char* bytes = NULL;
				bytes = new unsigned char[iter->data.size()];
				if (bytes)
				{
					copy(iter->data.begin(), iter->data.end(), bytes);

					if (Global::msoblipDIB == iter->blipType)
					{//user_manual_v52.doc
						std::wstring file_name = string2std_string(pathMedia.GetPath()) + FILE_SEPARATOR_STR + _T("image") + FormatUtils::IntToWideString(i++) + iter->ext;
						ImageHelper::SaveImageToFileFromDIB(bytes, iter->data.size(), file_name);
					}
					else
					{
						SaveToFile(string2std_string(pathMedia.GetPath()), std::wstring(_T("image" )) + FormatUtils::IntToWideString(i++) + iter->ext, (void*)bytes, (unsigned int)iter->data.size());
					}

					RELEASEARRAYOBJECTS(bytes);
				}
			}
		}

		if (!OleObjectsList.empty())
		{
			OOX::CPath pathObjects = pathWord + FILE_SEPARATOR_STR + _T( "embeddings" );

			FileSystem::Directory::CreateDirectory( pathObjects.GetPath());

			int i = 1;
			for (list<OleObjectFileStructure>::iterator iter = OleObjectsList.begin(); iter != OleObjectsList.end(); ++iter)
			{
				std::wstring fileName = string2std_string(pathObjects.GetPath()) + FILE_SEPARATOR_STR  + _T( "oleObject" ) + FormatUtils::IntToWideString(i++) + iter->ext;

				if (!iter->data.empty())
				{
					SaveEmbeddedObject(fileName, iter->data);
				}
				else
				{
					SaveOLEObject( fileName, *iter );
				}
			}
		}

		int headersCount = 0;
		int footersCount = 0;

		for (list<wstring>::iterator iter = HeaderXMLList.begin(); iter != HeaderXMLList.end(); ++iter)
		{
			SaveToFile(string2std_string(pathWord.GetPath()), ( wstring( _T( "header" ) ) + FormatUtils::IntToWideString(++headersCount) + wstring( _T( ".xml" ) ) ), *iter);
		}

		for (list<wstring>::iterator iter = FooterXMLList.begin(); iter != FooterXMLList.end(); ++iter)
		{
			SaveToFile(string2std_string(pathWord.GetPath()), ( wstring( _T( "footer" ) ) + FormatUtils::IntToWideString(++footersCount) + wstring( _T( ".xml" ) ) ), *iter);
		}
	}
}
<commit_msg>DocFormatReader -  переопределение BITMAPINFOHEADER<commit_after>
#include "WordprocessingDocument.h"

#include "../../Common/DocxFormat/Source/SystemUtility/SystemUtility.h"
#include "../../Common/DocxFormat/Source/SystemUtility/FileSystem/Directory.h"

#include "../../DesktopEditor/raster/BgraFrame.h"

namespace ImageHelper
{
	typedef struct ___tagBITMAPINFOHEADER
	{
		DWORD      biSize;
		LONG       biWidth;
		LONG       biHeight;
		WORD       biPlanes;
		WORD       biBitCount;
		DWORD      biCompression;
		DWORD      biSizeImage;
		LONG       biXPelsPerMeter;
		LONG       biYPelsPerMeter;
		DWORD      biClrUsed;
		DWORD      biClrImportant;
	} ___BITMAPINFOHEADER;

	inline static int CompareStrings (const wchar_t* str1, const wchar_t* str2)
	{
		CString cstr1; cstr1 = str1;
		CString cstr2; cstr2 = str2;

		if (cstr1 == cstr2)
			return 0;

		return 1;
	}
	inline bool SaveImageToFileFromDIB(unsigned char* buffer, int size, const std::wstring& file)
	{
		bool result = false;
		const ___BITMAPINFOHEADER* info =	(___BITMAPINFOHEADER*)buffer;

		if (NULL != info && info->biSize == 40)
		{
			unsigned char* pBgraData = buffer + sizeof(___BITMAPINFOHEADER);

			int nWidth	= info->biWidth;
			int nHeight = info->biHeight;

			CBgraFrame oFrame;
			oFrame.put_Data		(pBgraData);
			oFrame.put_Width	(nWidth);
			oFrame.put_Height	(nHeight);

			int nStride = info->biSizeImage / nHeight;
			oFrame.put_Stride( -nStride );

			result = oFrame.SaveFile(file, 4);

			oFrame.put_Data(NULL);

		}

		return result;
	}
}

namespace DocFileFormat
{
	WordprocessingDocument::WordprocessingDocument(const wchar_t* _pathOutput, const WordDocument* _docFile) : OpenXmlPackage( _docFile ), FontTableXML( _T( "" ) ), DocumentXML( _T( "" ) ),
		StyleSheetXML( _T( "" ) ), FootnotesXML ( _T( "" ) ), NumberingXML( _T( "" ) ),
		CommentsXML( _T( "" ) ), SettingsXML( _T( "" ) ), CommandTableXML ( _T( "" ) )
	{
		m_strOutputPath = std::wstring(_pathOutput);
	}

	WordprocessingDocument::~WordprocessingDocument()
	{
	}

	void WordprocessingDocument::SaveDocument()
	{
		OOX::CPath pathWord = CString(m_strOutputPath.c_str()) + FILE_SEPARATOR_STR + _T( "word" );
		FileSystem::Directory::CreateDirectory( pathWord.GetPath() );

		WritePackage();

		//Write main content. (word directory)

		SaveToFile(string2std_string(pathWord.GetPath()), wstring( _T("document.xml" ) ),		DocumentXML );
		SaveToFile(string2std_string(pathWord.GetPath()), wstring( _T( "fontTable.xml" ) ),		FontTableXML );
		SaveToFile(string2std_string(pathWord.GetPath()), wstring( _T( "styles.xml" ) ),		StyleSheetXML );
		SaveToFile(string2std_string(pathWord.GetPath()), wstring( _T( "footnotes.xml" ) ),		FootnotesXML );
		SaveToFile(string2std_string(pathWord.GetPath()), wstring( _T( "endnotes.xml" ) ),		EndnotesXML );
		SaveToFile(string2std_string(pathWord.GetPath()), wstring( _T( "numbering.xml" ) ),		NumberingXML );
		SaveToFile(string2std_string(pathWord.GetPath()), wstring( _T( "comments.xml" ) ),		CommentsXML );
		SaveToFile(string2std_string(pathWord.GetPath()), wstring( _T( "settings.xml" ) ),		SettingsXML );
		SaveToFile(string2std_string(pathWord.GetPath()), wstring( _T( "customizations.xml" ) ),CommandTableXML );

		if (!ImagesList.empty())
		{
			OOX::CPath pathMedia = pathWord + FILE_SEPARATOR_STR + _T( "media" );

			FileSystem::Directory::CreateDirectory( pathMedia.GetPath() );

			int i = 1;

			for (list<ImageFileStructure>::iterator iter = ImagesList.begin(); iter != ImagesList.end(); ++iter)
			{
				unsigned char* bytes = NULL;
				bytes = new unsigned char[iter->data.size()];
				if (bytes)
				{
					copy(iter->data.begin(), iter->data.end(), bytes);

					if (Global::msoblipDIB == iter->blipType)
					{//user_manual_v52.doc
						std::wstring file_name = string2std_string(pathMedia.GetPath()) + FILE_SEPARATOR_STR + _T("image") + FormatUtils::IntToWideString(i++) + iter->ext;
						ImageHelper::SaveImageToFileFromDIB(bytes, iter->data.size(), file_name);
					}
					else
					{
						SaveToFile(string2std_string(pathMedia.GetPath()), std::wstring(_T("image" )) + FormatUtils::IntToWideString(i++) + iter->ext, (void*)bytes, (unsigned int)iter->data.size());
					}

					RELEASEARRAYOBJECTS(bytes);
				}
			}
		}

		if (!OleObjectsList.empty())
		{
			OOX::CPath pathObjects = pathWord + FILE_SEPARATOR_STR + _T( "embeddings" );

			FileSystem::Directory::CreateDirectory( pathObjects.GetPath());

			int i = 1;
			for (list<OleObjectFileStructure>::iterator iter = OleObjectsList.begin(); iter != OleObjectsList.end(); ++iter)
			{
				std::wstring fileName = string2std_string(pathObjects.GetPath()) + FILE_SEPARATOR_STR  + _T( "oleObject" ) + FormatUtils::IntToWideString(i++) + iter->ext;

				if (!iter->data.empty())
				{
					SaveEmbeddedObject(fileName, iter->data);
				}
				else
				{
					SaveOLEObject( fileName, *iter );
				}
			}
		}

		int headersCount = 0;
		int footersCount = 0;

		for (list<wstring>::iterator iter = HeaderXMLList.begin(); iter != HeaderXMLList.end(); ++iter)
		{
			SaveToFile(string2std_string(pathWord.GetPath()), ( wstring( _T( "header" ) ) + FormatUtils::IntToWideString(++headersCount) + wstring( _T( ".xml" ) ) ), *iter);
		}

		for (list<wstring>::iterator iter = FooterXMLList.begin(); iter != FooterXMLList.end(); ++iter)
		{
			SaveToFile(string2std_string(pathWord.GetPath()), ( wstring( _T( "footer" ) ) + FormatUtils::IntToWideString(++footersCount) + wstring( _T( ".xml" ) ) ), *iter);
		}
	}
}
<|endoftext|>


<commit_before>/*=========================================================================
*
*  Copyright Insight Software Consortium
*
*  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.txt
*
*  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 <itkSliceImageFilter.h>
#include <gtest/gtest.h>

#include "itkPhysicalPointImageSource.h"
#include "itkGaussianImageSource.h"
#include "itkImageRegionConstIterator.h"

// This test verifies the principle that the SliceImageFilter should
// not change the physical location of the signal. This is done by
// constructing an image of points, each corresponding to the phycical
// location of the center of the voxel, then verifying that the value
// still matches the physcial location.

namespace
{

// This function checks that all values in an image are equivalent to
// the physical point of the image.
template <typename TImageType>
bool CheckValueIsPhysicalPoint( const TImageType *img )
{

  using IteratorType = itk::ImageRegionConstIterator<TImageType>;
  IteratorType it(img, img->GetBufferedRegion() );

  bool match = true;

  typename TImageType::PointType pt;
  img->TransformIndexToPhysicalPoint( it.GetIndex(), pt );
  while( !it.IsAtEnd() )
    {
    img->TransformIndexToPhysicalPoint( it.GetIndex(), pt );
    for ( unsigned int i = 0; i < TImageType::ImageDimension; ++i )
      {
      EXPECT_DOUBLE_EQ( pt[i], it.Get()[i] ) << "Index: " << it.GetIndex() << " Point: " << pt << " Value: " << it.Get() << std::endl, match = false;
      }

    ++it;
    }
  return match;
}

template <typename TImageType>
typename TImageType::Pointer RunFilter( const TImageType *img,
                                        typename TImageType::IndexType start,
                                        typename TImageType::IndexType stop,
                                        int step[TImageType::ImageDimension]
  )
{
  using FilterType = itk::SliceImageFilter<TImageType, TImageType>;
  typename FilterType::Pointer sliceFilter = FilterType::New();

  sliceFilter->SetInput( img );
  sliceFilter->SetStart( start );
  sliceFilter->SetStop( stop );
  sliceFilter->SetStep( step );
  sliceFilter->UpdateLargestPossibleRegion();

  return sliceFilter->GetOutput();
}

}

TEST(SliceImageFilterTests, PhysicalPoint1)
{
  constexpr unsigned int ImageDimension = 2;
  using PixelType = itk::Point<double, ImageDimension>;
  using ImageType = itk::Image<PixelType, ImageDimension>;

  using SourceType = itk::PhysicalPointImageSource<ImageType>;
  SourceType::Pointer source = SourceType::New();

  // these size are chosen as a power of two and a prime number.
  SourceType::SizeValueType size[] = {128,127};
  source->SetSize( size );

  float origin[] = {1.1f, 2.22f};
  source->SetOrigin( origin );

  int step[ImageDimension];
  ImageType::IndexType start;
  ImageType::IndexType stop;
  stop[0] = size[0];
  stop[1] = size[1];

  for( start[0] = 0; start[0] < 10; ++start[0] )
    for( start[1] = 0; start[1] < 10; ++start[1] )
      for( step[0] = 1; step[0] < 10; ++step[0] )
        for( step[1] = 1; step[1] < 10; ++step[1] )
          {

          ImageType::Pointer img;

          img = RunFilter<ImageType>( source->GetOutput(), start, stop, step );

          EXPECT_TRUE( CheckValueIsPhysicalPoint( img.GetPointer() ) ) << "== Failed - step:" << step[0] << " " << step[1] << " start: " <<start[0] << " " << start[1] << std::endl;
          }

}

TEST(SliceImageFilterTests, PhysicalPoint2)
{
  constexpr unsigned int ImageDimension = 2;
  using PixelType = itk::Point<double, ImageDimension>;
  using ImageType = itk::Image<PixelType, ImageDimension>;

  using SourceType = itk::PhysicalPointImageSource<ImageType>;
  SourceType::Pointer source = SourceType::New();

  // these size are chosen as a power of two and a prime number.
  SourceType::SizeValueType size[] = {128,127};
  source->SetSize( size );

  float origin[] = {3.33f, 4.4444f};
  source->SetOrigin( origin );

  int step[ImageDimension] = {3,4};
  ImageType::IndexType start;
  ImageType::IndexType stop;

  ASSERT_TRUE(size[0] > 10);
  ASSERT_TRUE(size[1] > 10);

  for( start[0] = 0; start[0] < 10; ++start[0] )
    for( start[1] = 0; start[1] < 10; ++start[1] )
      for( stop[0] = size[0]; stop[0] > (ImageType::IndexValueType)(size[0] - 10); --stop[0] )
        for( stop[1] = size[1]; stop[1] > (ImageType::IndexValueType)(size[1] -10); --stop[1] )
          {

          ImageType::Pointer img;

          img = RunFilter<ImageType>( source->GetOutput(), start, stop, step );

          EXPECT_TRUE( CheckValueIsPhysicalPoint( img.GetPointer() ) ) <<
            "== Failed - step:" << step[0] << " " << step[1] << " start: " <<start[0] << " " << start[1]  <<
            " stop: " << stop[0] << " " << stop[1] << std::endl;
          }

}

TEST(SliceImageFilterTests, PhysicalPoint3)
{
  constexpr unsigned int ImageDimension = 2;
  using PixelType = itk::Point<double, ImageDimension>;
  using ImageType = itk::Image<PixelType, ImageDimension>;

  using SourceType = itk::PhysicalPointImageSource<ImageType>;
  SourceType::Pointer source = SourceType::New();

  // these size are chosen as a power of two and a prime number.
  SourceType::SizeValueType size[] = {16,17};
  source->SetSize( size );

  float origin[] = {3.33f, 4.4444f};
  source->SetOrigin( origin );

  int step[ImageDimension] = {-2,-2};
  ImageType::IndexType start;
  ImageType::IndexType stop;

  for( start[0] = 10; start[0] < 20; ++start[0] )
    for( start[1] = 10; start[1] < 20; ++start[1] )
      for( stop[0] = -5; stop[0] > 12; --stop[0] )
        for( stop[1] = -5; stop[1] > 12; --stop[1] )
          {

          ImageType::Pointer img;

          img = RunFilter<ImageType>( source->GetOutput(), start, stop, step );

          EXPECT_TRUE( CheckValueIsPhysicalPoint( img.GetPointer() ) ) <<
            "== Failed - step:" << step[0] << " " << step[1] <<
            " start: " << start[0] << " " << start[1]  << " stop: " << stop[0] << " " << stop[1] << std::endl;
          }

}

TEST(SliceImageFilterTests,Empty)
{
  constexpr unsigned int ImageDimension = 2;
  using PixelType = itk::Point<double, ImageDimension>;
  using ImageType = itk::Image<PixelType, ImageDimension>;

  using SourceType = itk::PhysicalPointImageSource<ImageType>;
  SourceType::Pointer source = SourceType::New();

  // these size are chosen as a power of two and a prime number.
  SourceType::SizeValueType size[] = {32,32};
  source->SetSize( size );

  int step[ImageDimension] = {1,1};
  ImageType::IndexType start;
  start.Fill( 10 );
  ImageType::IndexType stop;
  stop.Fill( 10 );

  ImageType::Pointer img;

  img = RunFilter<ImageType>( source->GetOutput(), start, stop, step );
  std::cout << img;

  for( unsigned int i = 0; i < ImageDimension; ++i)
    {
    EXPECT_EQ( 0u, img->GetLargestPossibleRegion().GetSize()[i] );
    }

  start[0] = 2;
  start[1] = 2;
  stop[0] = 10;
  stop[1] = 2;

  img = RunFilter<ImageType>( source->GetOutput(), start, stop, step );

  EXPECT_EQ( 8u, img->GetLargestPossibleRegion().GetSize()[0] );
  EXPECT_EQ( 0u, img->GetLargestPossibleRegion().GetSize()[1] );

}

TEST(SliceImageFilterTests,Coverage)
{
  constexpr unsigned int ImageDimension = 3;
  using ImageType = itk::Image<float, ImageDimension>;

  using FilterType = itk::SliceImageFilter<ImageType, ImageType>;

  FilterType::Pointer filter = FilterType::New();
  std::cout << filter;

  FilterType::IndexType idx;
  idx.Fill( 10 );

  filter->SetStart(idx);
  EXPECT_EQ( idx, filter->GetStart() );

  idx.Fill(11);
  filter->SetStart(11);
  EXPECT_EQ( idx, filter->GetStart() );

  idx.Fill(12);
  filter->SetStop(idx);
  EXPECT_EQ( idx, filter->GetStop() );

  idx.Fill(13);
  filter->SetStop(13);
  EXPECT_EQ( idx, filter->GetStop() );

  FilterType::ArrayType a;
  a.Fill(14);
  filter->SetStep(a);
  EXPECT_EQ( a, filter->GetStep() );

  a.Fill(15);
  filter->SetStep(15);
  EXPECT_EQ(a, filter->GetStep() );
}

TEST(SliceImageFilterTests,Sizes)
{
  constexpr unsigned int ImageDimension = 3;
  using ImageType = itk::Image<float, ImageDimension>;

  using SourceType = itk::GaussianImageSource<ImageType>;
  SourceType::Pointer source = SourceType::New();

  SourceType::SizeType size = {{64,64,64}};
  source->SetSize(size);
  source->ReleaseDataFlagOn();

  using FilterType = itk::SliceImageFilter<ImageType, ImageType>;

  FilterType::Pointer filter = FilterType::New();
  filter->SetInput( source->GetOutput() );
  // check with default start, stop, step
  EXPECT_NO_THROW(filter->Update());
  EXPECT_EQ(filter->GetOutput()->GetLargestPossibleRegion().GetSize(), size) << "Check full size for defaults";

  filter = FilterType::New();
  filter->SetInput( source->GetOutput() );
  filter->SetStart( 64 );
  filter->SetStop(-1);
  filter->SetStep(-1);
  EXPECT_NO_THROW(filter->Update());
  EXPECT_EQ(filter->GetOutput()->GetLargestPossibleRegion().GetSize(), size) << "Check full size for negative step";

  std::cout << "Filter size: " << filter->GetOutput()->GetLargestPossibleRegion() << std::endl;
  std::cout << "Filter buffered size: " << filter->GetOutput()->GetBufferedRegion() << std::endl;
  std::cout << "Input size: " << size << std::endl;
}

TEST(SliceImageFilterTests,ExceptionalCases)
{
  constexpr unsigned int ImageDimension = 3;
  using ImageType = itk::Image<float, ImageDimension>;

  using SourceType = itk::GaussianImageSource<ImageType>;
  SourceType::Pointer source = SourceType::New();

  using FilterType = itk::SliceImageFilter<ImageType, ImageType>;

  FilterType::Pointer filter = FilterType::New();
  filter->SetInput( source->GetOutput() );

  filter->SetStep( 0 );
  EXPECT_ANY_THROW( filter->Update() ) << "Check with 0 step";

  // for some reason after the above exception, the pipeline is not
  // clean, and Verify input information will not get executed again,
  // so just create a new filter...
  filter = FilterType::New();
  filter->SetInput( source->GetOutput() );
  filter->SetStart(10000);
  filter->SetStop(10001);
  EXPECT_NO_THROW( filter->Update() ) << "Check with over-sized start stop are clamped to zero";
  EXPECT_EQ( 0u, filter->GetOutput()->GetLargestPossibleRegion().GetNumberOfPixels() );

  filter = FilterType::New();
  filter->SetInput( source->GetOutput() );
  filter->SetStart(12);
  filter->SetStop(10);
  EXPECT_NO_THROW( filter->Update() ) << "Check stop is clamped";
  EXPECT_EQ( 0u, filter->GetOutput()->GetLargestPossibleRegion().GetNumberOfPixels() );

  filter = FilterType::New();
  filter->SetInput( source->GetOutput() );
  filter->SetStart(-12);
  filter->SetStop(-10);
  EXPECT_NO_THROW( filter->Update() ) << "Check undersized start and stop";
  EXPECT_EQ( 0u, filter->GetOutput()->GetLargestPossibleRegion().GetNumberOfPixels() );

  filter = FilterType::New();
  filter->SetInput( source->GetOutput() );
  filter->SetStart(-12);
  filter->SetStop(-10);
  filter->SetStep(-1);
  EXPECT_NO_THROW( filter->Update() ) << "Check undersized start and stop";
  EXPECT_EQ( 0u, filter->GetOutput()->GetLargestPossibleRegion().GetNumberOfPixels() );

}
<commit_msg>ENH: Add more test cases for the SliceImageFilter<commit_after>/*=========================================================================
*
*  Copyright Insight Software Consortium
*
*  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.txt
*
*  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 <itkSliceImageFilter.h>

#include "itkGTest.h"
#include "itkPhysicalPointImageSource.h"
#include "itkGaussianImageSource.h"
#include "itkImageRegionConstIterator.h"

// This test verifies the principle that the SliceImageFilter should
// not change the physical location of the signal. This is done by
// constructing an image of points, each corresponding to the physical
// location of the center of the voxel, then verifying that the value
// still matches the physical location.

namespace
{

// This function checks that all values in an image are equivalent to
// the physical point of the image.
template <typename TImageType>
bool CheckValueIsPhysicalPoint( const TImageType *img )
{

  using IteratorType = itk::ImageRegionConstIterator<TImageType>;
  IteratorType it(img, img->GetBufferedRegion() );

  bool match = true;

  typename TImageType::PointType pt;
  img->TransformIndexToPhysicalPoint( it.GetIndex(), pt );
  while( !it.IsAtEnd() )
    {
    img->TransformIndexToPhysicalPoint( it.GetIndex(), pt );
    for ( unsigned int i = 0; i < TImageType::ImageDimension; ++i )
      {
      EXPECT_DOUBLE_EQ( pt[i], it.Get()[i] ) << "Index: " << it.GetIndex() << " Point: " << pt << " Value: " << it.Get() << std::endl, match = false;
      }

    ++it;
    }
  return match;
}

template <typename TImageType>
typename TImageType::Pointer RunFilter( const TImageType *img,
                                        typename TImageType::IndexType start,
                                        typename TImageType::IndexType stop,
                                        int step[TImageType::ImageDimension]
  )
{
  using FilterType = itk::SliceImageFilter<TImageType, TImageType>;
  typename FilterType::Pointer sliceFilter = FilterType::New();

  sliceFilter->SetInput( img );
  sliceFilter->SetStart( start );
  sliceFilter->SetStop( stop );
  sliceFilter->SetStep( step );
  sliceFilter->UpdateLargestPossibleRegion();

  return sliceFilter->GetOutput();
}

}

TEST(SliceImageFilterTests, PhysicalPoint1)
{
  constexpr unsigned int ImageDimension = 2;
  using PixelType = itk::Point<double, ImageDimension>;
  using ImageType = itk::Image<PixelType, ImageDimension>;

  using SourceType = itk::PhysicalPointImageSource<ImageType>;
  SourceType::Pointer source = SourceType::New();

  // these size are chosen as a power of two and a prime number.
  SourceType::SizeValueType size[] = {128,127};
  source->SetSize( size );

  float origin[] = {1.1f, 2.22f};
  source->SetOrigin( origin );

  int step[ImageDimension];
  ImageType::IndexType start;
  ImageType::IndexType stop;
  stop[0] = size[0];
  stop[1] = size[1];

  for( start[0] = 0; start[0] < 10; ++start[0] )
    for( start[1] = 0; start[1] < 10; ++start[1] )
      for( step[0] = 1; step[0] < 10; ++step[0] )
        for( step[1] = 1; step[1] < 10; ++step[1] )
          {

          ImageType::Pointer img;

          img = RunFilter<ImageType>( source->GetOutput(), start, stop, step );

          EXPECT_TRUE( CheckValueIsPhysicalPoint( img.GetPointer() ) ) << "== Failed - step:" << step[0] << " " << step[1] << " start: " <<start[0] << " " << start[1] << std::endl;
          }

}

TEST(SliceImageFilterTests, PhysicalPoint2)
{
  constexpr unsigned int ImageDimension = 2;
  using PixelType = itk::Point<double, ImageDimension>;
  using ImageType = itk::Image<PixelType, ImageDimension>;

  using SourceType = itk::PhysicalPointImageSource<ImageType>;
  SourceType::Pointer source = SourceType::New();

  // these size are chosen as a power of two and a prime number.
  SourceType::SizeValueType size[] = {128,127};
  source->SetSize( size );

  float origin[] = {3.33f, 4.4444f};
  source->SetOrigin( origin );

  int step[ImageDimension] = {3,4};
  ImageType::IndexType start;
  ImageType::IndexType stop;

  ASSERT_TRUE(size[0] > 10);
  ASSERT_TRUE(size[1] > 10);

  for( start[0] = 0; start[0] < 10; ++start[0] )
    for( start[1] = 0; start[1] < 10; ++start[1] )
      for( stop[0] = size[0]; stop[0] > (ImageType::IndexValueType)(size[0] - 10); --stop[0] )
        for( stop[1] = size[1]; stop[1] > (ImageType::IndexValueType)(size[1] -10); --stop[1] )
          {

          ImageType::Pointer img;

          img = RunFilter<ImageType>( source->GetOutput(), start, stop, step );

          EXPECT_TRUE( CheckValueIsPhysicalPoint( img.GetPointer() ) ) <<
            "== Failed - step:" << step[0] << " " << step[1] << " start: " <<start[0] << " " << start[1]  <<
            " stop: " << stop[0] << " " << stop[1] << std::endl;
          }

}

TEST(SliceImageFilterTests, PhysicalPoint3)
{
  constexpr unsigned int ImageDimension = 2;
  using PixelType = itk::Point<double, ImageDimension>;
  using ImageType = itk::Image<PixelType, ImageDimension>;

  using SourceType = itk::PhysicalPointImageSource<ImageType>;
  SourceType::Pointer source = SourceType::New();

  // these size are chosen as a power of two and a prime number.
  SourceType::SizeValueType size[] = {16,17};
  source->SetSize( size );

  float origin[] = {3.33f, 4.4444f};
  source->SetOrigin( origin );

  int step[ImageDimension] = {-2,-2};
  ImageType::IndexType start;
  ImageType::IndexType stop;

  for( start[0] = 10; start[0] < 20; ++start[0] )
    for( start[1] = 10; start[1] < 20; ++start[1] )
      for( stop[0] = -5; stop[0] > 12; --stop[0] )
        for( stop[1] = -5; stop[1] > 12; --stop[1] )
          {

          ImageType::Pointer img;

          img = RunFilter<ImageType>( source->GetOutput(), start, stop, step );

          EXPECT_TRUE( CheckValueIsPhysicalPoint( img.GetPointer() ) ) <<
            "== Failed - step:" << step[0] << " " << step[1] <<
            " start: " << start[0] << " " << start[1]  << " stop: " << stop[0] << " " << stop[1] << std::endl;
          }

}

TEST(SliceImageFilterTests,Empty)
{
  constexpr unsigned int ImageDimension = 2;
  using PixelType = itk::Point<double, ImageDimension>;
  using ImageType = itk::Image<PixelType, ImageDimension>;

  using SourceType = itk::PhysicalPointImageSource<ImageType>;
  SourceType::Pointer source = SourceType::New();

  // these size are chosen as a power of two and a prime number.
  SourceType::SizeValueType size[] = {32,32};
  source->SetSize( size );

  int step[ImageDimension] = {1,1};
  ImageType::IndexType start;
  start.Fill( 10 );
  ImageType::IndexType stop;
  stop.Fill( 10 );

  ImageType::Pointer img;

  img = RunFilter<ImageType>( source->GetOutput(), start, stop, step );
  std::cout << img;

  for( unsigned int i = 0; i < ImageDimension; ++i)
    {
    EXPECT_EQ( 0u, img->GetLargestPossibleRegion().GetSize()[i] );
    }

  start[0] = 2;
  start[1] = 2;
  stop[0] = 10;
  stop[1] = 2;

  img = RunFilter<ImageType>( source->GetOutput(), start, stop, step );

  EXPECT_EQ( 8u, img->GetLargestPossibleRegion().GetSize()[0] );
  EXPECT_EQ( 0u, img->GetLargestPossibleRegion().GetSize()[1] );

}

TEST(SliceImageFilterTests,Coverage)
{
  constexpr unsigned int ImageDimension = 3;
  using ImageType = itk::Image<float, ImageDimension>;

  using FilterType = itk::SliceImageFilter<ImageType, ImageType>;

  FilterType::Pointer filter = FilterType::New();
  std::cout << filter;

  FilterType::IndexType idx;
  idx.Fill( 10 );

  filter->SetStart(idx);
  EXPECT_EQ( idx, filter->GetStart() );

  idx.Fill(11);
  filter->SetStart(11);
  EXPECT_EQ( idx, filter->GetStart() );

  idx.Fill(12);
  filter->SetStop(idx);
  EXPECT_EQ( idx, filter->GetStop() );

  idx.Fill(13);
  filter->SetStop(13);
  EXPECT_EQ( idx, filter->GetStop() );

  FilterType::ArrayType a;
  a.Fill(14);
  filter->SetStep(a);
  EXPECT_EQ( a, filter->GetStep() );

  a.Fill(15);
  filter->SetStep(15);
  EXPECT_EQ(a, filter->GetStep() );
}

TEST(SliceImageFilterTests,Sizes)
{
  constexpr unsigned int ImageDimension = 3;
  using ImageType = itk::Image<float, ImageDimension>;

  using SourceType = itk::GaussianImageSource<ImageType>;
  SourceType::Pointer source = SourceType::New();

  SourceType::SizeType size = {{64,64,64}};
  source->SetSize(size);
  source->ReleaseDataFlagOn();

  using FilterType = itk::SliceImageFilter<ImageType, ImageType>;

  FilterType::Pointer filter = FilterType::New();
  filter->SetInput( source->GetOutput() );
  // check with default start, stop, step
  EXPECT_NO_THROW(filter->Update());
  EXPECT_EQ(filter->GetOutput()->GetLargestPossibleRegion().GetSize(), size) << "Check full size for defaults";

  filter = FilterType::New();
  filter->SetInput( source->GetOutput() );
  filter->SetStart( 64 );
  filter->SetStop(-1);
  filter->SetStep(-1);
  EXPECT_NO_THROW(filter->Update());
  EXPECT_EQ(filter->GetOutput()->GetLargestPossibleRegion().GetSize(), size) << "Check full size for negative step";

  using namespace itk::GTest::TypedefsAndConstructors::Dimension3;

  source->SetSize(MakeSize(19,17,11));

  filter = FilterType::New();
  filter->SetInput( source->GetOutput() );
  filter->SetStep(2);
  EXPECT_NO_THROW( filter->Update() ) << "Check same start and stop";
  EXPECT_EQ( 10, filter->GetOutput()->GetLargestPossibleRegion().GetSize(0) );
  EXPECT_EQ( 9, filter->GetOutput()->GetLargestPossibleRegion().GetSize(1) );
  EXPECT_EQ( 6, filter->GetOutput()->GetLargestPossibleRegion().GetSize(2) );

  source->SetSize(MakeSize(5,2,3));

  std::cout << "CHECK" << std::endl;

  filter = FilterType::New();
  filter->SetInput( source->GetOutput() );
  filter->SetStep(2);
  EXPECT_NO_THROW( filter->Update() ) << "Check same start and stop";
  EXPECT_EQ( 3, filter->GetOutput()->GetLargestPossibleRegion().GetSize(0) );
  EXPECT_EQ( 1, filter->GetOutput()->GetLargestPossibleRegion().GetSize(1) );
  EXPECT_EQ( 2, filter->GetOutput()->GetLargestPossibleRegion().GetSize(2) );

}

TEST(SliceImageFilterTests,ExceptionalCases)
{
  constexpr unsigned int ImageDimension = 3;
  using ImageType = itk::Image<float, ImageDimension>;

  using SourceType = itk::GaussianImageSource<ImageType>;
  SourceType::Pointer source = SourceType::New();

  using FilterType = itk::SliceImageFilter<ImageType, ImageType>;

  FilterType::Pointer filter = FilterType::New();
  filter->SetInput( source->GetOutput() );

  filter->SetStep( 0 );
  EXPECT_ANY_THROW( filter->Update() ) << "Check with 0 step";

  // for some reason after the above exception, the pipeline is not
  // clean, and Verify input information will not get executed again,
  // so just create a new filter...
  filter = FilterType::New();
  filter->SetInput( source->GetOutput() );
  filter->SetStart(10000);
  filter->SetStop(10001);
  EXPECT_NO_THROW( filter->Update() ) << "Check with over-sized start stop are clamped to zero";
  EXPECT_EQ( 0u, filter->GetOutput()->GetLargestPossibleRegion().GetNumberOfPixels() );

  filter = FilterType::New();
  filter->SetInput( source->GetOutput() );
  filter->SetStart(12);
  filter->SetStop(10);
  EXPECT_NO_THROW( filter->Update() ) << "Check stop is clamped";
  EXPECT_EQ( 0u, filter->GetOutput()->GetLargestPossibleRegion().GetNumberOfPixels() );

  filter = FilterType::New();
  filter->SetInput( source->GetOutput() );
  filter->SetStart(-12);
  filter->SetStop(-10);
  EXPECT_NO_THROW( filter->Update() ) << "Check undersized start and stop";
  EXPECT_EQ( 0u, filter->GetOutput()->GetLargestPossibleRegion().GetNumberOfPixels() );

  filter = FilterType::New();
  filter->SetInput( source->GetOutput() );
  filter->SetStart(1);
  filter->SetStop(1);
  EXPECT_NO_THROW( filter->Update() ) << "Check same start and stop";
  EXPECT_EQ( 0u, filter->GetOutput()->GetLargestPossibleRegion().GetNumberOfPixels() );

  filter = FilterType::New();
  filter->SetInput( source->GetOutput() );
  filter->SetStart(1);
  filter->SetStop(1);
  filter->SetStep(2);
  EXPECT_NO_THROW( filter->Update() ) << "Check same start and stop";
  EXPECT_EQ( 0u, filter->GetOutput()->GetLargestPossibleRegion().GetNumberOfPixels() );

  filter = FilterType::New();
  filter->SetInput( source->GetOutput() );
  filter->SetStart(-12);
  filter->SetStop(-10);
  filter->SetStep(-1);
  EXPECT_NO_THROW( filter->Update() ) << "Check undersized start and stop";
  EXPECT_EQ( 0u, filter->GetOutput()->GetLargestPossibleRegion().GetNumberOfPixels() );

  filter = FilterType::New();
  filter->SetInput( source->GetOutput() );
  filter->SetStart(4);
  filter->SetStop(4);
  filter->SetStep(-1);
  EXPECT_NO_THROW( filter->Update() ) << "Check same start and stop with negative step";
  EXPECT_EQ( 0u, filter->GetOutput()->GetLargestPossibleRegion().GetNumberOfPixels() );

  filter = FilterType::New();
  filter->SetInput( source->GetOutput() );
  filter->SetStart(4);
  filter->SetStop(4);
  filter->SetStep(-3);
  EXPECT_NO_THROW( filter->Update() ) << "Check same start and stop with negative step";
  EXPECT_EQ( 0u, filter->GetOutput()->GetLargestPossibleRegion().GetNumberOfPixels() );
}
<|endoftext|>


<commit_before>/* -------------------------------------------------------------------------- *
 *                     OpenSim:  exampleHopperDevice.cpp                      *
 * -------------------------------------------------------------------------- *
 * The OpenSim API is a toolkit for musculoskeletal modeling and simulation.  *
 * See http://opensim.stanford.edu and the NOTICE file for more information.  *
 * OpenSim is developed at Stanford University and supported by the US        *
 * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA    *
 * through the Warrior Web program.                                           *
 *                                                                            *
 * Copyright (c) 2005-2017 Stanford University and the Authors                *
 * Author(s): Chris Dembia, Shrinidhi K. Lakshmikanth, Ajay Seth,             *
 *            Thomas Uchida                                                   *
 *                                                                            *
 * 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.                                             *
 * -------------------------------------------------------------------------- */

/* This example demonstrates some of the new features of the OpenSim 4.0 API.
The Component architecture allows us to join sub-assemblies to form larger
Models, with information flowing between Components via Inputs, Outputs, and
Sockets. For more information, please refer to the Component documentation.

This interactive example consists of three steps:
  Step 1. Build and simulate a single-legged hopping mechanism.
  Step 2. Build an assistive device and test it on a simple testbed.
  Step 3. Connect the device to the hopper to increase hop height.

To start working through this example, go to run() at the bottom of this file.
From there, you will be directed to specific files and methods in this project
that need to be completed. Now, hop to it! */

#include <OpenSim/OpenSim.h>
#include "defineDeviceAndController.h"
#include "helperMethods.h"

static const double SIGNAL_GEN_CONSTANT{ 0.33 };
static const double REPORTING_INTERVAL{ 0.2 };

static const std::string testbedAttachment1{"ground"};
static const std::string testbedAttachment2{"load"};

//TODO: Provide the name of the coordinate corresponding to the hopper's height.
//      Hint: the hopper's pelvis is attached to ground with a vertical slider
//      joint; see buildHopperModel.cpp and Component::printOutputInfo().
// [Step 1, Task A]
static const std::string hopperHeightCoord{"/Dennis/?????"}; //fill this in

//TODO: Provide the absolute path names of the PhysicalOffsetFrames defined on
//      the hopper for attaching the assistive device. See buildHopperModel.cpp
//      and Component::printSubcomponentInfo().
// [Step 3, Task A]
static const std::string thighAttachment{"/Dennis/?????"}; //fill this in
static const std::string shankAttachment{"/Dennis/?????"}; //fill this in

//TODO: To assist hopping, we will activate the knee device whenever the vastus
//      muscle is active. For convenience, we define a string "vastus" which
//      is the path to the vastus muscle.
// [Step 3, Task B]
static const std::string vastus{"/Dennis/?????"}; //fill this in

namespace OpenSim {

// Forward declarations for methods used below.
Model buildHopper(bool showVisualizer);    //defined in buildHopperModel.cpp
Model buildTestbed(bool showVisualizer);   //defined in helperMethods.h
Device* buildDevice();  //defined in buildDevice.cpp

//------------------------------------------------------------------------------
// Attach the device to any two PhysicalFrames in a model.
// [Step 2, Task D]
//------------------------------------------------------------------------------
void connectDeviceToModel(OpenSim::Device& device, OpenSim::Model& model,
    const std::string& modelFrameAname, const std::string& modelFrameBname)
{
    //TODO: Get writable references to the "anchor" joints in the device.

    //TODO: Recall that the child frame of each anchor (WeldJoint) was attached
    //      to the corresponding cuff. We will now attach the parent frames of
    //      the anchors to modelFrameA and modelFrameB. First get references to
    //      the two specified PhysicalFrames in model (i.e., modelFrameAname and
    //      modelFrameBname), then connect them to the parent frames of each
    //      anchor. (2 lines of code for each anchor.)

    // Add the device to the model.
    model.addComponent(&device);

    // Configure the device to wrap over the patella (if one exists; there is no
    // patella in the testbed).
    const std::string patellaPath("thigh/patellaFrame/patella");
    if (model.hasComponent<WrapCylinder>(patellaPath)) {
        auto& cable = model.updComponent<PathActuator>("device/cableAtoB");
        auto& wrapObject = model.updComponent<WrapCylinder>(patellaPath);
        cable.updGeometryPath().addPathWrap(wrapObject);
    }
}

//------------------------------------------------------------------------------
// Add a ConsoleReporter to the hopper model to display variables of interest.
// [Step 1, Task B]
//------------------------------------------------------------------------------
void addConsoleReporterToHopper(Model& hopper)
{
    //TODO: Create a new ConsoleReporter. Set its name and reporting interval.

    //TODO: Connect outputs from the hopper to the reporter's inputs. Try
    //      reporting the hopper's height, the vastus muscle's activation, the
    //      knee angle, and any other variables of interest.

    //TODO: Add the reporter to the model.
}

//------------------------------------------------------------------------------
// Add a SignalGenerator to a device.
// [Step 2, Task E]
//------------------------------------------------------------------------------
void addSignalGeneratorToDevice(Device& device)
{
    //TODO: Create a new SignalGenerator and set its name.

    // Try changing the constant value and/or the function (e.g., try a
    // LinearFunction).
    //signalGen->set_function(Constant(SIGNAL_GEN_CONSTANT));
    //device.addComponent(signalGen);

    //TODO: Connect the signal generator's output signal to the controller's
    //      activation input.
}

//------------------------------------------------------------------------------
// Add a ConsoleReporter to a model for displaying outputs from a device.
//------------------------------------------------------------------------------
void addDeviceConsoleReporterToModel(Model& model, Device& device,
    const std::vector<std::string>& deviceOutputs,
    const std::vector<std::string>& deviceControllerOutputs)
{
    // Create a new ConsoleReporter. Set its name and reporting interval.
    auto reporter = new ConsoleReporter();
    reporter->setName(model.getName() + "_" + device.getName() + "_results");
    reporter->set_report_time_interval(REPORTING_INTERVAL);

    // Loop through the desired device outputs and add them to the reporter.
    for (auto thisOutputName : deviceOutputs)
        reporter->addToReport(device.getOutput(thisOutputName));

    for (auto thisOutputName : deviceControllerOutputs)
        reporter->addToReport(
                device.getComponent("controller").getOutput(thisOutputName));

    // Add the reporter to the model.
    model.addComponent(reporter);
}

} // namespace OpenSim

void run(bool showVisualizer, bool simulateOnce);

int main(int argc, char* argv[]) {
    //==========================================================================
    // Command line argument parsing.
    //==========================================================================
    // Following are arguments to this executable:
    // (1) noVisualizer -- [Optional] Do not show visualizer. Default
    //                       behavior is to show visualizer.
    // (2) simulateOnce -- [Optional] Simulate once and exit the program.
    //                       Default behavior is to simulate multiple times
    //                       until user requests to stop.

    // Suppress/show visualizer.
    bool showVisualizer{true};
    // Simulate just once or until user stops.
    bool simulateOnce{false};
    for(int i = 0; i < argc; ++i)
        if(strcmp(argv[i], "noVisualizer") == 0)
            showVisualizer = false;
        else if(strcmp(argv[i], "simulateOnce") == 0)
            simulateOnce = true;

    try {
        run(showVisualizer, simulateOnce);
    }
    catch (const std::exception& ex) {
        std::cout << "Hopper Example Failed to run due to the following Exception: "
            << ex.what() << std::endl;
        return 1;
    }

    return 0;
}

//------------------------------------------------------------------------------
// START HERE! Toggle "if (false)" to "if (true)" to enable/disable each step in
// the exercise. The project should execute without making any changes (you
// should see the unassisted hopper hop slightly).
//------------------------------------------------------------------------------

void run(bool showVisualizer, bool simulateOnce)
{
    using namespace OpenSim;

    //==========================================================================
    // Step 1. Build and simulate a single-legged hopping mechanism.
    //==========================================================================
    if (true)
    {
        // Build the hopper.
        auto hopper = buildHopper(showVisualizer);
        // Update the hopper model's internal data members, which includes
        // identifying its subcomponents from its properties.
        hopper.finalizeFromProperties();

        // Show all Components in the model.
        hopper.printSubcomponentInfo();
        // Show only the Joints in the model.
        hopper.printSubcomponentInfo<Joint>();
        // Show the outputs generated by the thigh body.
        // The argument indicates if outputs of subcomponents should be printed.
        hopper.getComponent("/Dennis/thigh").printOutputInfo(false);

        // Step 1, Task A
        // ==============
        // Determine the name of the coordinate corresponding to the hopper's
        // height. The hopperHeightCoord string (at the top of this file) must
        // be filled in.

        // Step 1, Task B
        // ==============
        // Report the hopper's height and vastus muscle activation during the
        // simulation. The addConsoleReporterToHopper() method (in this file)
        // needs to be filled in.
        addConsoleReporterToHopper(hopper);

        // Create the system, initialize the state, and simulate.
        SimTK::State& sHop = hopper.initSystem();
        simulate(hopper, sHop, simulateOnce);
    }

    //==========================================================================
    // Step 2. Build an assistive device and test it on a simple testbed.
    //==========================================================================
    if (false)
    {
        // Build the testbed and device.
        auto testbed = buildTestbed(showVisualizer);
        testbed.finalizeFromProperties();

        // Step 2, Task A
        // ==============
        // Go to defineDeviceAndController.h and complete the "TODO"s in the
        // Device class.

        // Step 2, Task B
        // ==============
        // Go to defineDeviceAndController.h and complete the "TODO"s in the
        // PropMyoController class.

        // Step 2, Task C
        // ==============
        // Go to buildDeviceModel.cpp and complete the "TODO"s in buildDevice().
        auto device = buildDevice();
        device->finalizeFromProperties();

        // Show all Components in the device and testbed.
        device->printSubcomponentInfo();
        testbed.printSubcomponentInfo();
        // Show the outputs generated by the device.
        device->printOutputInfo(false);

        // Step 2, Task D
        // ==============
        // Connect the device to the testbed. The connectDeviceToModel() method
        // (in this file) needs to be filled in.
        //connectDeviceToModel(*device, testbed, testbedAttachment1,
        //                     testbedAttachment2);

        // Step 2, Task E
        // ==============
        // Use a SignalGenerator to create a control signal for testing the
        // device. The addSignalGeneratorToDevice() method (in this file) needs
        // to be filled in.
        addSignalGeneratorToDevice(*device);

        // List the device outputs we wish to display during the simulation.
        std::vector<std::string> deviceOutputs{ "length", "tension", "power" };
        std::vector<std::string> deviceControllerOutputs{ "myo_control" };

        // Add a ConsoleReporter to report deviceOutputs.
        //addDeviceConsoleReporterToModel(testbed, *device, deviceOutputs,
        //                                deviceControllerOutputs);

        // Create the system, initialize the state, and simulate.
        SimTK::State& sDev = testbed.initSystem();
        simulate(testbed, sDev, simulateOnce);
    }

    //==========================================================================
    // Step 3. Connect the device to the hopper to increase hop height.
    //==========================================================================
    if (false)
    {
        // Build the hopper and device.
        auto assistedHopper = buildHopper(showVisualizer);
        assistedHopper.finalizeFromProperties();
        auto kneeDevice = buildDevice();
        kneeDevice->finalizeFromProperties();

        // Step 3, Task A
        // ==============
        // Connect the device to the hopper. The thighAttachment and
        // shankAttachment strings (at the top of this file) must be filled in.
        //connectDeviceToModel(*kneeDevice, assistedHopper, thighAttachment,
        //                     shankAttachment);

        // Step 3, Task B
        // ==============
        // Use the vastus muscle's activation as the control signal for the
        // device. The vastus string (at the top of this file) must
        // be filled in.
        //kneeDevice->updComponent("controller").updInput("activation").connect(
        //    assistedHopper.getComponent(vastus).getOutput("activation"));

        // List the device outputs we wish to display during the simulation.
        std::vector<std::string> kneeDeviceOutputs{ "tension", "height" };
        std::vector<std::string> deviceControllerOutputs{ "myo_control" };

        // Add a ConsoleReporter to report deviceOutputs.
        //addDeviceConsoleReporterToModel(assistedHopper, *kneeDevice,
        //                                kneeDeviceOutputs, deviceControllerOutputs);

        // Create the system, initialize the state, and simulate.
        SimTK::State& sHD = assistedHopper.initSystem();
        simulate(assistedHopper, sHD, simulateOnce);
    }
};
<commit_msg>Remove now unnecessary call to Model::finalizeFromProperties() after construction.<commit_after>/* -------------------------------------------------------------------------- *
 *                     OpenSim:  exampleHopperDevice.cpp                      *
 * -------------------------------------------------------------------------- *
 * The OpenSim API is a toolkit for musculoskeletal modeling and simulation.  *
 * See http://opensim.stanford.edu and the NOTICE file for more information.  *
 * OpenSim is developed at Stanford University and supported by the US        *
 * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA    *
 * through the Warrior Web program.                                           *
 *                                                                            *
 * Copyright (c) 2005-2017 Stanford University and the Authors                *
 * Author(s): Chris Dembia, Shrinidhi K. Lakshmikanth, Ajay Seth,             *
 *            Thomas Uchida                                                   *
 *                                                                            *
 * 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.                                             *
 * -------------------------------------------------------------------------- */

/* This example demonstrates some of the new features of the OpenSim 4.0 API.
The Component architecture allows us to join sub-assemblies to form larger
Models, with information flowing between Components via Inputs, Outputs, and
Sockets. For more information, please refer to the Component documentation.

This interactive example consists of three steps:
  Step 1. Build and simulate a single-legged hopping mechanism.
  Step 2. Build an assistive device and test it on a simple testbed.
  Step 3. Connect the device to the hopper to increase hop height.

To start working through this example, go to run() at the bottom of this file.
From there, you will be directed to specific files and methods in this project
that need to be completed. Now, hop to it! */

#include <OpenSim/OpenSim.h>
#include "defineDeviceAndController.h"
#include "helperMethods.h"

static const double SIGNAL_GEN_CONSTANT{ 0.33 };
static const double REPORTING_INTERVAL{ 0.2 };

static const std::string testbedAttachment1{"ground"};
static const std::string testbedAttachment2{"load"};

//TODO: Provide the name of the coordinate corresponding to the hopper's height.
//      Hint: the hopper's pelvis is attached to ground with a vertical slider
//      joint; see buildHopperModel.cpp and Component::printOutputInfo().
// [Step 1, Task A]
static const std::string hopperHeightCoord{"/Dennis/?????"}; //fill this in

//TODO: Provide the absolute path names of the PhysicalOffsetFrames defined on
//      the hopper for attaching the assistive device. See buildHopperModel.cpp
//      and Component::printSubcomponentInfo().
// [Step 3, Task A]
static const std::string thighAttachment{"/Dennis/?????"}; //fill this in
static const std::string shankAttachment{"/Dennis/?????"}; //fill this in

//TODO: To assist hopping, we will activate the knee device whenever the vastus
//      muscle is active. For convenience, we define a string "vastus" which
//      is the path to the vastus muscle.
// [Step 3, Task B]
static const std::string vastus{"/Dennis/?????"}; //fill this in

namespace OpenSim {

// Forward declarations for methods used below.
Model buildHopper(bool showVisualizer);    //defined in buildHopperModel.cpp
Model buildTestbed(bool showVisualizer);   //defined in helperMethods.h
Device* buildDevice();  //defined in buildDevice.cpp

//------------------------------------------------------------------------------
// Attach the device to any two PhysicalFrames in a model.
// [Step 2, Task D]
//------------------------------------------------------------------------------
void connectDeviceToModel(OpenSim::Device& device, OpenSim::Model& model,
    const std::string& modelFrameAname, const std::string& modelFrameBname)
{
    //TODO: Get writable references to the "anchor" joints in the device.

    //TODO: Recall that the child frame of each anchor (WeldJoint) was attached
    //      to the corresponding cuff. We will now attach the parent frames of
    //      the anchors to modelFrameA and modelFrameB. First get references to
    //      the two specified PhysicalFrames in model (i.e., modelFrameAname and
    //      modelFrameBname), then connect them to the parent frames of each
    //      anchor. (2 lines of code for each anchor.)

    // Add the device to the model.
    model.addComponent(&device);

    // Configure the device to wrap over the patella (if one exists; there is no
    // patella in the testbed).
    const std::string patellaPath("thigh/patellaFrame/patella");
    if (model.hasComponent<WrapCylinder>(patellaPath)) {
        auto& cable = model.updComponent<PathActuator>("device/cableAtoB");
        auto& wrapObject = model.updComponent<WrapCylinder>(patellaPath);
        cable.updGeometryPath().addPathWrap(wrapObject);
    }
}

//------------------------------------------------------------------------------
// Add a ConsoleReporter to the hopper model to display variables of interest.
// [Step 1, Task B]
//------------------------------------------------------------------------------
void addConsoleReporterToHopper(Model& hopper)
{
    //TODO: Create a new ConsoleReporter. Set its name and reporting interval.

    //TODO: Connect outputs from the hopper to the reporter's inputs. Try
    //      reporting the hopper's height, the vastus muscle's activation, the
    //      knee angle, and any other variables of interest.

    //TODO: Add the reporter to the model.
}

//------------------------------------------------------------------------------
// Add a SignalGenerator to a device.
// [Step 2, Task E]
//------------------------------------------------------------------------------
void addSignalGeneratorToDevice(Device& device)
{
    //TODO: Create a new SignalGenerator and set its name.

    // Try changing the constant value and/or the function (e.g., try a
    // LinearFunction).
    //signalGen->set_function(Constant(SIGNAL_GEN_CONSTANT));
    //device.addComponent(signalGen);

    //TODO: Connect the signal generator's output signal to the controller's
    //      activation input.
}

//------------------------------------------------------------------------------
// Add a ConsoleReporter to a model for displaying outputs from a device.
//------------------------------------------------------------------------------
void addDeviceConsoleReporterToModel(Model& model, Device& device,
    const std::vector<std::string>& deviceOutputs,
    const std::vector<std::string>& deviceControllerOutputs)
{
    // Create a new ConsoleReporter. Set its name and reporting interval.
    auto reporter = new ConsoleReporter();
    reporter->setName(model.getName() + "_" + device.getName() + "_results");
    reporter->set_report_time_interval(REPORTING_INTERVAL);

    // Loop through the desired device outputs and add them to the reporter.
    for (auto thisOutputName : deviceOutputs)
        reporter->addToReport(device.getOutput(thisOutputName));

    for (auto thisOutputName : deviceControllerOutputs)
        reporter->addToReport(
                device.getComponent("controller").getOutput(thisOutputName));

    // Add the reporter to the model.
    model.addComponent(reporter);
}

} // namespace OpenSim

void run(bool showVisualizer, bool simulateOnce);

int main(int argc, char* argv[]) {
    //==========================================================================
    // Command line argument parsing.
    //==========================================================================
    // Following are arguments to this executable:
    // (1) noVisualizer -- [Optional] Do not show visualizer. Default
    //                       behavior is to show visualizer.
    // (2) simulateOnce -- [Optional] Simulate once and exit the program.
    //                       Default behavior is to simulate multiple times
    //                       until user requests to stop.

    // Suppress/show visualizer.
    bool showVisualizer{true};
    // Simulate just once or until user stops.
    bool simulateOnce{false};
    for(int i = 0; i < argc; ++i)
        if(strcmp(argv[i], "noVisualizer") == 0)
            showVisualizer = false;
        else if(strcmp(argv[i], "simulateOnce") == 0)
            simulateOnce = true;

    try {
        run(showVisualizer, simulateOnce);
    }
    catch (const std::exception& ex) {
        std::cout << "Hopper Example Failed to run due to the following Exception: "
            << ex.what() << std::endl;
        return 1;
    }

    return 0;
}

//------------------------------------------------------------------------------
// START HERE! Toggle "if (false)" to "if (true)" to enable/disable each step in
// the exercise. The project should execute without making any changes (you
// should see the unassisted hopper hop slightly).
//------------------------------------------------------------------------------

void run(bool showVisualizer, bool simulateOnce)
{
    using namespace OpenSim;

    //==========================================================================
    // Step 1. Build and simulate a single-legged hopping mechanism.
    //==========================================================================
    if (true)
    {
        // Build the hopper.
        auto hopper = buildHopper(showVisualizer);

        // Show all Components in the model.
        hopper.printSubcomponentInfo();
        // Show only the Joints in the model.
        hopper.printSubcomponentInfo<Joint>();
        // Show the outputs generated by the thigh body.
        // The argument indicates if outputs of subcomponents should be printed.
        hopper.getComponent("/Dennis/thigh").printOutputInfo(false);

        // Step 1, Task A
        // ==============
        // Determine the name of the coordinate corresponding to the hopper's
        // height. The hopperHeightCoord string (at the top of this file) must
        // be filled in.

        // Step 1, Task B
        // ==============
        // Report the hopper's height and vastus muscle activation during the
        // simulation. The addConsoleReporterToHopper() method (in this file)
        // needs to be filled in.
        addConsoleReporterToHopper(hopper);

        // Create the system, initialize the state, and simulate.
        SimTK::State& sHop = hopper.initSystem();
        simulate(hopper, sHop, simulateOnce);
    }

    //==========================================================================
    // Step 2. Build an assistive device and test it on a simple testbed.
    //==========================================================================
    if (false)
    {
        // Build the testbed and device.
        auto testbed = buildTestbed(showVisualizer);

        // Step 2, Task A
        // ==============
        // Go to defineDeviceAndController.h and complete the "TODO"s in the
        // Device class.

        // Step 2, Task B
        // ==============
        // Go to defineDeviceAndController.h and complete the "TODO"s in the
        // PropMyoController class.

        // Step 2, Task C
        // ==============
        // Go to buildDeviceModel.cpp and complete the "TODO"s in buildDevice().
        auto device = buildDevice();

        // Show all Components in the device and testbed.
        device->printSubcomponentInfo();
        testbed.printSubcomponentInfo();
        // Show the outputs generated by the device.
        device->printOutputInfo(false);

        // Step 2, Task D
        // ==============
        // Connect the device to the testbed. The connectDeviceToModel() method
        // (in this file) needs to be filled in.
        //connectDeviceToModel(*device, testbed, testbedAttachment1,
        //                     testbedAttachment2);

        // Step 2, Task E
        // ==============
        // Use a SignalGenerator to create a control signal for testing the
        // device. The addSignalGeneratorToDevice() method (in this file) needs
        // to be filled in.
        addSignalGeneratorToDevice(*device);

        // List the device outputs we wish to display during the simulation.
        std::vector<std::string> deviceOutputs{ "length", "tension", "power" };
        std::vector<std::string> deviceControllerOutputs{ "myo_control" };

        // Add a ConsoleReporter to report deviceOutputs.
        //addDeviceConsoleReporterToModel(testbed, *device, deviceOutputs,
        //                                deviceControllerOutputs);

        // Create the system, initialize the state, and simulate.
        SimTK::State& sDev = testbed.initSystem();
        simulate(testbed, sDev, simulateOnce);
    }

    //==========================================================================
    // Step 3. Connect the device to the hopper to increase hop height.
    //==========================================================================
    if (false)
    {
        // Build the hopper and device.
        auto assistedHopper = buildHopper(showVisualizer);
        auto kneeDevice = buildDevice();

        // Step 3, Task A
        // ==============
        // Connect the device to the hopper. The thighAttachment and
        // shankAttachment strings (at the top of this file) must be filled in.
        //connectDeviceToModel(*kneeDevice, assistedHopper, thighAttachment,
        //                     shankAttachment);

        // Step 3, Task B
        // ==============
        // Use the vastus muscle's activation as the control signal for the
        // device. The vastus string (at the top of this file) must
        // be filled in.
        //kneeDevice->updComponent("controller").updInput("activation").connect(
        //    assistedHopper.getComponent(vastus).getOutput("activation"));

        // List the device outputs we wish to display during the simulation.
        std::vector<std::string> kneeDeviceOutputs{ "tension", "height" };
        std::vector<std::string> deviceControllerOutputs{ "myo_control" };

        // Add a ConsoleReporter to report deviceOutputs.
        //addDeviceConsoleReporterToModel(assistedHopper, *kneeDevice,
        //                                kneeDeviceOutputs, deviceControllerOutputs);

        // Create the system, initialize the state, and simulate.
        SimTK::State& sHD = assistedHopper.initSystem();
        simulate(assistedHopper, sHD, simulateOnce);
    }
};
<|endoftext|>