{"id":21412739,"url":"https://github.com/souris-dev/genomeassembly","last_synced_at":"2025-03-16T18:22:28.299Z","repository":{"id":72830090,"uuid":"258974331","full_name":"souris-dev/GenomeAssembly","owner":"souris-dev","description":"Genome Assembly using De-Bruijn Graphs","archived":false,"fork":false,"pushed_at":"2020-05-10T00:19:31.000Z","size":51,"stargazers_count":1,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-23T05:14:22.288Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/souris-dev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-04-26T08:04:33.000Z","updated_at":"2024-06-05T02:34:46.000Z","dependencies_parsed_at":"2023-02-26T23:15:40.988Z","dependency_job_id":null,"html_url":"https://github.com/souris-dev/GenomeAssembly","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/souris-dev%2FGenomeAssembly","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/souris-dev%2FGenomeAssembly/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/souris-dev%2FGenomeAssembly/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/souris-dev%2FGenomeAssembly/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/souris-dev","download_url":"https://codeload.github.com/souris-dev/GenomeAssembly/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243910763,"owners_count":20367544,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-22T18:15:25.598Z","updated_at":"2025-03-16T18:22:28.292Z","avatar_url":"https://github.com/souris-dev.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Genome Assembly Using De-Bruijn Graphs\n\n## Initial Implementation: The Overall Algorithm\n\n1. Input the value of 'k'. Then, input the number of reads that the user shall provide to the program.\n2. For each of the reads, generate k-mers. Do note that all the reads may not be of the same length. \n3. For each of the k-mers, generate left and right (k-1)-mers.\n\n4. Build the De Bruijn graph (more on this below) using the (k-1)-mers.\n\n5. Connect the last node of the De Bruijn graph with the first node.\n\n6. Perform an Eulerian walk on the De Bruijn graph.\n\n   a. While we visit the nodes during the Eulerian walk, take the whole string of the first node, and append the last letter of the consecutive nodes to it.\n   \n   b. Ignore the last edge (as the last edge connects the last node with the first node, due to step 5).\n\n   c. For example, a walk like:\n\n\t_(ATF) -\u003e (TFB) -\u003e (FBI) -\u003e (BII) -\u003e (IIT) -\u003e (ATF)_ (remember the last node IIT is connected to the first node ATF, because of step 5)\n\n\twould yield the complete string as: ATFBIIT (disregard the last edge, hence don't append 'F' from ATF again; or do it and then remove it, whichever is easier.)\n\n7. Et voila! You've the original string. Just change those arbitrary letters in the reads to bases and you get a genome (that's upto the user)!\n\n\n## Next Implementation\n\nIn the next version, we shall do all the above steps first by taking the value of k as that given by the user, then change the value of k to **(initial value of k) + 1**, then repeat the whole process again. We do it the third time, this time by changing the value of k to **(initial value of k) - 1**. This will give us 3 strings.\n\nShow the string that occurs 2 times (or more) out of the three. If all the 3 strings are different, show them all.\n\n**The steps are described in detail below:**\n\n## Class Design\n\n### Taking Input\n\nThis is quite a simple task: ask the user for the value of `k`, and the number of reads. Then, take in the reads.\nAfter that, create a `KMerifier` object with that value of k and the reads, and let the workflow continue.\n\n### Processing the Input\n\nFollowing good design, there shall be a `class KMerifier` that takes a value `k`, and a `vector\u003cstring\u003e` in its constructor.\nAn object of this class will help to generate the k-mers **and** (k-1)-mers, from the given `vector\u003cstring\u003e`.\n\nThis class will also help to generate a set of **unique (k-1)-mers**.\n\nThe design of the class will be something like this:\n\n```cpp\nclass KMerifier\n{\nprivate:\n\tint k;\n\tint k_minus_1;\n\tvector\u003cstring\u003e reads;\n\npublic:\n\tKMerifier(int Kay, vector\u003cstring\u003e Reads); // constructor\n\t\n\tunordered_map\u003cint, string\u003e getKMers(); // returns KMers of the reads, in order\n\tunordered_map\u003cint, string\u003e getKMinusOneMers(); // returns (K-1)-Mers of the reads in order\n\t\n\t// using unordered_map above instead of a vector has some benefits here\n\n\tunordered_set\u003cstring\u003e getUniqueKMinusOneMers(); // returns unique (k-1)-mers\n\n\tint getK(); // returns value of k\n\tvoid setK(int kay); // sets the value of k\n};\n```\nFor a general idea of how this needs to be done, have a look at `src/reference.cpp`.\n\n\n### Building the De Bruijn Graph\n\nA De-Bruijn graph is a **directed multi-graph** (can have more than one edge between 2 nodes) that is always Eulerian (always has an Eulerian path).\nWe shall use an **Adjacency List** representation for the De-Bruijn graph. \n\nRemember that here, the nodes of the DeBruijn graph are `string`s.\n\nA class DeBruijnGraph would be handy for this.\n\n**A `DeBruijnGraph` object's nodes should be initialized by either of these methods:**\n**1. Creating a KMerifier object and then passing it to a function `initNodesFromKMerifier`, which takes that object as an argument.**\n**2. Creating a KMerifier object and then passing it to the constructor of the class `DeBruijnGraph`, so that it gets initialized at the time of creation.**\n\nThe adjacency list will be an unordered_map (for easy access of elements using []).\n\nIt (the adjacency list) can be hence represented like this:\n{\"a\" : {\"a0\", \"a1\", \"a2\", ...},\n\"b\" : {\"b0\", \"b1\", \"b2\", ...}, ...}\n\nso that saying `adjList[\"b\"][0]` would mean `\"b0\"`. This needs to be done because the nodes are strings.\n\n__(Note: Please see the `#define` directive in the beginning.)__\n\n```cpp\n#define Node string\n// The above line replaces each instance of the word Node with string, like find and replace\n// Node in the lines after this is just string.\n\nclass DeBruijnGraph\n{\nprivate:\n\tunordered_map \u003cNode, vector\u003cNode\u003e\u003e adjList;\n\tunordered_map \u003cint, Node\u003e nodes; // associates a number to each Node\n\tunordered_map \u003cNode, int\u003e edgeCounts; // stores the number of edges each node has EMERGING from it\n\t\n\tvoid connectLastAndFirst(); // connects the last node with the first node\n\tvoid countEdges(); // counts the number of edges each node has EMERGING from it (populates edge_counts)\n\npublic:\n\tDeBruijnGraph(); // empty constructor\n\tDeBruijnGraph(KMerifier kmf); // constructor to directly initialize the graph with a KMerifier object\n\n\tvoid addEdge(Node node1, Node node2);\n\tvoid addNode(Node node);\n\n\tbool contains(Node node); // returns true if the string node is there in the graph\n\n\tvoid initNodesFromKMerifier(KMerifier kmf); // initializes the nodes from an object of the KMerifier class type. \n\t// Use the addEdge and addNode functions from inside this function.\n\n\tvoid printAdjList(); // for debugging purposes\n\n\tstring DoEulerianWalk(); // implementation of the Heirholzer's algorithm. This function returns the original string.\n\n\t// ... other functions may be added, for example, for debugging.\n};\n```\n\nThe Eulerian walk of the `DeBruijnGraph` will be performed by calling the `DoEulerianWalk()` function. This function returns us the complete string.\nThe algorithm used to do this is: [Hierholzer's Algorithm](https://www.geeksforgeeks.org/hierholzers-algorithm-directed-graph/) (a linear time algorithm).\n\n\n## Main Workflow Design\n\n1. Take in `k` and the reads, then create a `KMerifier` object.\n2. Create a `DeBruijnGraph` object and initialize its nodes using the `KMerifier` class object (created in step 1).\n3. Use `DoEulerianWalk()` of the `DeBruijnGraph` object to get the complete string.\n4. **Next Implementation**: Do the above three steps for different values of `k` (instead of asking the user for `k` again, use *k(initial) + 1* and *k(initial) - 1* as `k` values, as mentioned before).\n   Show the string that occurs 2 times (or more) out of the three. If all the 3 strings are different, show them all.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsouris-dev%2Fgenomeassembly","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsouris-dev%2Fgenomeassembly","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsouris-dev%2Fgenomeassembly/lists"}