Browse Source

Add proteome system, along with genome component and proteome component

master
C. J. Howard 2 years ago
parent
commit
c3fc332113
10 changed files with 330 additions and 63 deletions
  1. +0
    -1
      CMakeLists.txt
  2. +50
    -0
      src/entity/components/genome.hpp
  3. +39
    -0
      src/entity/components/proteome.hpp
  4. +34
    -0
      src/entity/systems/morphogenesis.cpp
  5. +60
    -0
      src/entity/systems/morphogenesis.hpp
  6. +74
    -0
      src/entity/systems/proteome.cpp
  7. +55
    -0
      src/entity/systems/proteome.hpp
  8. +5
    -3
      src/game/bootloader.cpp
  9. +2
    -0
      src/game/game-context.hpp
  10. +11
    -59
      src/game/states/play-state.cpp

+ 0
- 1
CMakeLists.txt View File

@ -1,6 +1,5 @@
cmake_minimum_required(VERSION 3.7)
option(VERSION_STRING "Project version string" "0.0.0")
project(antkeeper VERSION ${VERSION_STRING} LANGUAGES CXX)

+ 50
- 0
src/entity/components/genome.hpp View File

@ -0,0 +1,50 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_ENTITY_COMPONENT_GENOME_HPP
#define ANTKEEPER_ENTITY_COMPONENT_GENOME_HPP
#include <string>
#include <vector>
namespace entity {
namespace component {
/// Complete set of genetic material in an organism.
struct genome
{
/**
* Number of complete sets of chromosomes in a cell.
*
* A value of `1` indicates the organism is haploid, `2` is diploid, `3` is triploid, etc.
*/
unsigned int ploidy;
/**
* Set of DNA base sequences for every chromosomes in the genome.
*
* A DNA base sequence is a string of IUPAC DNA base symbols. Homologous chromosomes should be stored consecutively, such that in a diploid organism, a chromosome with an even index is homologous to the following chromosome.
*/
std::vector<std::string> chromosomes;
};
} // namespace component
} // namespace entity
#endif // ANTKEEPER_ENTITY_COMPONENT_GENOME_HPP

+ 39
- 0
src/entity/components/proteome.hpp View File

@ -0,0 +1,39 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_ENTITY_COMPONENT_PROTEOME_HPP
#define ANTKEEPER_ENTITY_COMPONENT_PROTEOME_HPP
#include <string>
#include <vector>
namespace entity {
namespace component {
/// Set of all proteins that can be expressed by an organism.
struct proteome
{
/// Set of amino acid sequences of every protein in the proteome.
std::vector<std::string> proteins;
};
} // namespace component
} // namespace entity
#endif // ANTKEEPER_ENTITY_COMPONENT_PROTEOME_HPP

+ 34
- 0
src/entity/systems/morphogenesis.cpp View File

@ -0,0 +1,34 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "entity/systems/morphogenesis.hpp"
#include "entity/id.hpp"
namespace entity {
namespace system {
morphogenesis::morphogenesis(entity::registry& registry):
updatable(registry)
{}
void morphogenesis::update(double t, double dt)
{}
} // namespace system
} // namespace entity

+ 60
- 0
src/entity/systems/morphogenesis.hpp View File

@ -0,0 +1,60 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_ENTITY_SYSTEM_MORPHOGENESIS_HPP
#define ANTKEEPER_ENTITY_SYSTEM_MORPHOGENESIS_HPP
#include "entity/systems/updatable.hpp"
namespace entity {
namespace system {
/**
* Constructs the forms of organisms from their genetic codes.
*
* Algorithm:
*
* 1. Consider inital egg cell as a sphere at the origin.
* 2. Use the marching cubes algorithm to generate a mesh from the isosurface formed by the sum of all cells.
* 3. Generate evenly-distributed points across surface area of the mesh (Poisson sample?).
* 4. For each point, evaluate morphogenic genes to determine type, direction, and color of the next cell.
* 5. Create new cells given the output of step 4.
* 6. Go to step 2 and repeat.
*/
class morphogenesis:
public updatable
{
public:
morphogenesis(entity::registry& registry);
/**
* Scales then adds the timestep `dt` to the current time, then recalculates the positions of morphogenesising bodies.
*
* @param t Time, in seconds.
* @param dt Delta time, in seconds.
*/
virtual void update(double t, double dt);
private:
};
} // namespace system
} // namespace entity
#endif // ANTKEEPER_ENTITY_SYSTEM_MORPHOGENESIS_HPP

+ 74
- 0
src/entity/systems/proteome.cpp View File

@ -0,0 +1,74 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "entity/systems/proteome.hpp"
#include "entity/components/proteome.hpp"
#include "genetics/sequence.hpp"
#include "genetics/standard-code.hpp"
namespace entity {
namespace system {
proteome::proteome(entity::registry& registry):
updatable(registry)
{
registry.on_construct<entity::component::genome>().connect<&proteome::on_genome_construct>(this);
registry.on_replace<entity::component::genome>().connect<&proteome::on_genome_replace>(this);
}
void proteome::update(double t, double dt)
{}
void proteome::on_genome_construct(entity::registry& registry, entity::id entity_id, entity::component::genome& genome)
{
on_genome_replace(registry, entity_id, genome);
}
void proteome::on_genome_replace(entity::registry& registry, entity::id entity_id, entity::component::genome& genome)
{
// Allocate a proteome component
entity::component::proteome proteome_component;
// For each chromosome in the genome
for (const std::string& chromosome: genome.chromosomes)
{
// Find the first ORF in the chromosome
auto orf = genetics::sequence::find_orf(chromosome.begin(), chromosome.end(), genetics::standard_code);
// While the ORF is valid
while (orf.start != chromosome.end())
{
// Translate the base sequence into an amino acid sequence (protein)
std::string protein;
genetics::sequence::translate(orf.start, orf.stop, std::back_inserter(protein), genetics::standard_code);
// Append protein to the proteome
proteome_component.proteins.push_back(protein);
// Find the next ORF
orf = genetics::sequence::find_orf(orf.stop, chromosome.end(), genetics::standard_code);
}
}
// Assign or replace the entity's proteome component
registry.assign_or_replace<entity::component::proteome>(entity_id, proteome_component);
}
} // namespace system
} // namespace entity

+ 55
- 0
src/entity/systems/proteome.hpp View File

@ -0,0 +1,55 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_ENTITY_SYSTEM_PROTEOME_HPP
#define ANTKEEPER_ENTITY_SYSTEM_PROTEOME_HPP
#include "entity/systems/updatable.hpp"
#include "entity/components/genome.hpp"
#include "entity/id.hpp"
namespace entity {
namespace system {
/**
* Generates proteomes for every genome.
*/
class proteome:
public updatable
{
public:
proteome(entity::registry& registry);
/**
* Scales then adds the timestep `dt` to the current time, then recalculates the positions of proteomeing bodies.
*
* @param t Time, in seconds.
* @param dt Delta time, in seconds.
*/
virtual void update(double t, double dt);
private:
void on_genome_construct(entity::registry& registry, entity::id entity_id, entity::component::genome& genome);
void on_genome_replace(entity::registry& registry, entity::id entity_id, entity::component::genome& genome);
};
} // namespace system
} // namespace entity
#endif // ANTKEEPER_ENTITY_SYSTEM_PROTEOME_HPP

+ 5
- 3
src/game/bootloader.cpp View File

@ -77,6 +77,7 @@
#include "entity/systems/blackbody.hpp"
#include "entity/systems/atmosphere.hpp"
#include "entity/systems/orbit.hpp"
#include "entity/systems/proteome.hpp"
#include "entity/components/marker.hpp"
#include "entity/commands.hpp"
#include "utility/paths.hpp"
@ -878,6 +879,9 @@ void setup_systems(game_context* ctx)
// Setup astronomy system
ctx->astronomy_system = new entity::system::astronomy(*ctx->entity_registry);
// Setup proteome system
ctx->proteome_system = new entity::system::proteome(*ctx->entity_registry);
// Set time scale
float time_scale = 60.0f;
if (ctx->config->has("time_scale"))
@ -1277,7 +1281,7 @@ void setup_callbacks(game_context* ctx)
ctx->constraint_system->update(t, dt);
ctx->tracking_system->update(t, dt);
ctx->painting_system->update(t, dt);
ctx->proteome_system->update(t, dt);
//(*ctx->focal_point_tween)[1] = ctx->orbit_cam->get_focal_point();
@ -1295,8 +1299,6 @@ void setup_callbacks(game_context* ctx)
ctx->application_controls->update();
ctx->menu_controls->update();
ctx->camera_controls->update();
}
);

+ 2
- 0
src/game/game-context.hpp View File

@ -99,6 +99,7 @@ namespace entity
class nest;
class render;
class samara;
class proteome;
}
}
@ -255,6 +256,7 @@ struct game_context
entity::system::atmosphere* atmosphere_system;
entity::system::astronomy* astronomy_system;
entity::system::orbit* orbit_system;
entity::system::proteome* proteome_system;
// Game
biome* biome;

+ 11
- 59
src/game/states/play-state.cpp View File

@ -26,6 +26,7 @@
#include "entity/components/copy-transform.hpp"
#include "entity/components/copy-translation.hpp"
#include "entity/components/model.hpp"
#include "entity/components/genome.hpp"
#include "entity/components/snap.hpp"
#include "entity/components/terrain.hpp"
#include "entity/components/tool.hpp"
@ -362,13 +363,20 @@ void play_state_enter(game_context* ctx)
// Place larva in chamber
{
auto larva = larva_archetype->create(entity_registry);
entity::command::assign_render_layers(entity_registry, larva, 1);
entity::command::warp_to(entity_registry, larva, {50, 0.1935f, 0});
auto larva_eid = larva_archetype->create(entity_registry);
entity::command::assign_render_layers(entity_registry, larva_eid, 1);
entity::command::warp_to(entity_registry, larva_eid, {50, 0.1935f, 0});
//auto& transform = entity_registry.get<entity::component::transform>(larva_entity);
//transform.transform = math::identity_transform<float>;
//transform.transform.translation = nest->get_shaft_position(*central_shaft, central_shaft->depth[1]);
//transform.transform.translation.y -= 1.0f;
// Construct larva genome
entity::component::genome genome;
genome.ploidy = 2;
const std::string antp = "ATGACCATGAGCACCAACAACTGCGAAAGCATGACCAGCTATTTTACCAACAGCTATATGGGCGCGGATATGCATCATGGCCATTATCCGGGCAACGGCGTGACCGATCTGGATGCGCAGCAGATGCATCATTATAGCCAGAACGCGAACCATCAGGGCAACATGCCGTATCCGCGCTTTCCGCCGTATGATCGCATGCCGTATTATAACGGCCAGGGCATGGATCAGCAGCAGCAGCATCAGGTGTATAGCCGCCCGGATAGCCCGAGCAGCCAGGTGGGCGGCGTGATGCCGCAGGCGCAGACCAACGGCCAGCTGGGCGTGCCGCAGCAGCAGCAGCAGCAGCAGCAGCAGCCGAGCCAGAACCAGCAGCAGCAGCAGGCGCAGCAGGCGCCGCAGCAGCTGCAGCAGCAGCTGCCGCAGGTGACCCAGCAGGTGACCCATCCGCAGCAGCAGCAGCAGCAGCCGGTGGTGTATGCGAGCTGCAAACTGCAGGCGGCGGTGGGCGGCCTGGGCATGGTGCCGGAAGGCGGCAGCCCGCCGCTGGTGGATCAGATGAGCGGCCATCATATGAACGCGCAGATGACCCTGCCGCATCATATGGGCCATCCGCAGGCGCAGGTGCATCAGAACCATCATAACATGGGCATGTATCAGCAGCAGAGCGGCGTGCCGCCGGTGGGCGCGCCGCCGCAGGGCATGATGCATCAGGGCCAGGGCCCGCCGCAGATGCATCAGGGCCATCCGGGCCAGCATACCCCGCCGAGCCAGAACCCGAACAGCCAGAGCAGCGGCATGCCGAGCCCGCTGTATCCGTGGATGCGCAGCCAGTTTGAACGCAAACGCGGCCGCCAGACCTATACCCGCTATCAGACCCTGGAACTGGAAAAAGAATTTCATTTTAACCGCTATCTGACCCGCCGCCGCCGCATTGAAATTGCGCATGCGCTGTGCCTGACCGAACGCCAGATTAAAATTTGGTTTCAGAACCGCCGCATGAAATGGAAAAAAGAAAACAAAACCAAAGGCGAACCGGGCAGCGGCGGCGAAGGCGATGAAATTACCCCGCCGAACAGCCCGCAGTAG";
genome.chromosomes.push_back(antp);
entity_registry.assign<entity::component::genome>(larva_eid, genome);
}
entity::system::control* control_system = ctx->control_system;
@ -382,62 +390,6 @@ void play_state_enter(game_context* ctx)
std::string biome_name = (*ctx->strings)[ctx->biome->name];
logger->log("Entered biome \"" + biome_name + "\"");
std::srand(std::time(nullptr));
//auto rng = [](){ return std::rand(); };
std::random_device rd;
std::mt19937 rng(rd());
std::string sequence_a = "CCTTGCCCTTTGGGTCGCCCCCCTAG";
std::string sequence_b = "ATGTTTCCCGAAGGGTAG";
std::string sequence_c = "AAATGCCCCCCCCCCCCCCCCCCCCCCCCCCCTAGAAAAAAAAA";
std::string orf_a;
std::string protein_a;
std::string protein_b;
std::string protein_c;
std::cout << "sequence a: " << sequence_a << std::endl;
genetics::sequence::transcribe(sequence_a.begin(), sequence_a.end(), sequence_a.begin());
std::cout << "sequence a: " << sequence_a << std::endl;
std::string complement;
genetics::sequence::rna::complement(sequence_a.begin(), sequence_a.end(), std::back_inserter(complement));
std::cout << "complement: " << complement << std::endl;
auto orf = genetics::sequence::find_orf(sequence_a.begin(), sequence_a.end(), genetics::standard_code);
if (orf.start != sequence_a.end())
{
std::copy(orf.start, orf.stop, std::back_inserter(orf_a));
std::cout << "orf a: " << orf_a << std::endl;
genetics::sequence::translate(orf.start, orf.stop, std::back_inserter(protein_a), genetics::standard_code);
std::cout << "protein a: " << protein_a << std::endl;
}
protein_b = "MFFFFP";
protein_c = "MFFFYP";
int score;
std::cout << std::endl;
std::cout << "protein_b: " << protein_b << std::endl;
std::cout << "protein_c: " << protein_c << std::endl;
score = genetics::protein::score(protein_b.begin(), protein_b.end(), protein_c.begin(), genetics::matrix::blosum62<int>);
std::cout << "score blosum62: " << score << std::endl;
score = genetics::protein::score(protein_b.begin(), protein_b.end(), protein_c.begin(), genetics::matrix::blosum80<int>);
std::cout << "score blosum80: " << score << std::endl;
std::cout << "identity : " << genetics::protein::identity<float>(protein_b.begin(), protein_b.end(), protein_c.begin()) << std::endl;
std::cout << "similarity62: " << genetics::protein::similarity<float>(protein_b.begin(), protein_b.end(), protein_c.begin(), genetics::matrix::blosum62<int>) << std::endl;
std::cout << "similarity80: " << genetics::protein::similarity<float>(protein_b.begin(), protein_b.end(), protein_c.begin(), genetics::matrix::blosum80<int>) << std::endl;
}
void play_state_exit(game_context* ctx)

Loading…
Cancel
Save