geniomhe-oop-dnapp/include/GeneticCode.hpp

98 lines
2.4 KiB
C++
Raw Permalink Normal View History

2023-10-01 12:26:59 +02:00
/** Implement the genetic code as a thread-safe GeneticCode.
*
* @see https://refactoring.guru/design-patterns/GeneticCode/cpp/example#example-1
*/
#pragma once
#include <algorithm>
#include <complex>
#include <fstream>
#include <sstream>
#include <iostream>
#include <stdexcept>
#include <unordered_map>
#include <vector>
#include <mutex>
#include "Sequence.hpp"
#include "strutils.hpp"
class GeneticCode {
private:
static GeneticCode *pinstance_;
static std::mutex mutex_;
protected:
std::unordered_map<std::string, char> codon_table;
GeneticCode(): GeneticCode("./resources/codons.txt") {}
GeneticCode(std::string input_filename) {
std::ifstream input(input_filename);
if (!input.good()) {
throw std::invalid_argument("Error: could not read codon table from " + input_filename + " file.");
}
load_genetic_code(input);
}
void load_genetic_code(std::ifstream &input) {
if (!input.good()) {
throw std::invalid_argument("Error: Could not read the codon table from the text file.");
}
std::string line;
while(input.good()) {
std::getline(input, line);
std::vector<std::string> fields = split_string(line, '\t');
std::string codon = fields.at(0);
char amino_acid = fields.at(2)[0];
GeneticCode::codon_table.insert({codon, amino_acid});
}
}
public:
GeneticCode(GeneticCode &other) = delete;
void operator=(const GeneticCode &) = delete;
static GeneticCode *GetInstance();
static GeneticCode *GetInstance(std::string input_filename);
char get_amino_acid(std::string codon) {
replace_all(codon, 'U', 'T');
if (codon_table.find(codon) != codon_table.end()) {
return codon_table.at(codon);
} else {
throw std::invalid_argument("Error: codon '" + codon + "' not found in genetic code");
}
}
};
GeneticCode* GeneticCode::pinstance_{nullptr};
std::mutex GeneticCode::mutex_;
GeneticCode *GeneticCode::GetInstance()
{
std::lock_guard<std::mutex> lock(mutex_);
if (pinstance_ == nullptr)
{
pinstance_ = new GeneticCode();
}
return pinstance_;
}
GeneticCode *GeneticCode::GetInstance(std::string input_filename)
{
std::lock_guard<std::mutex> lock(mutex_);
if (pinstance_ == nullptr)
{
pinstance_ = new GeneticCode(input_filename);
}
return pinstance_;
}