Repository: moshi4/FastDTLmapper (language: python)

Issue:
Change current direcotory strucuture to pytest testable & packageable
Current project cannot use pytest and packaging is impossible.
I'd like to resolve this problem, so change current project directory structure.


Discussion / hints:

Fix patch:
diff --git a/bin/OrthoFinder/scripts_of/__init__.py b/fastdtlmapper/__init__.py
similarity index 100%
rename from bin/OrthoFinder/scripts_of/__init__.py
rename to fastdtlmapper/__init__.py
diff --git a/fastdtlmapper/angst/__init__.py b/fastdtlmapper/angst/__init__.py
new file mode 100644
index 0000000..f25ca46
--- /dev/null
+++ b/fastdtlmapper/angst/__init__.py
@@ -0,0 +1,10 @@
+from fastdtlmapper.angst.event_map import AngstEventMap
+from fastdtlmapper.angst.model import NodeEvent, Transfer
+from fastdtlmapper.angst.transfer_gene import AngstTransferGene
+
+__all__ = [
+    "AngstEventMap",
+    "AngstTransferGene",
+    "NodeEvent",
+    "Transfer",
+]
diff --git a/lib/angst/event_map.py b/fastdtlmapper/angst/event_map.py
similarity index 98%
rename from lib/angst/event_map.py
rename to fastdtlmapper/angst/event_map.py
index c47f30a..1bd9868 100644
--- a/lib/angst/event_map.py
+++ b/fastdtlmapper/angst/event_map.py
@@ -4,7 +4,7 @@
 
 from Bio import Phylo
 from Bio.Phylo.BaseTree import Tree
-from lib.angst.model import NodeEvent, Transfer
+from fastdtlmapper.angst.model import NodeEvent, Transfer
 
 
 @dataclass
diff --git a/lib/angst/model.py b/fastdtlmapper/angst/model.py
similarity index 100%
rename from lib/angst/model.py
rename to fastdtlmapper/angst/model.py
diff --git a/fastdtlmapper/angst/model/__init__.py b/fastdtlmapper/angst/model/__init__.py
new file mode 100644
index 0000000..a987b52
--- /dev/null
+++ b/fastdtlmapper/angst/model/__init__.py
@@ -0,0 +1,7 @@
+from fastdtlmapper.angst.model.node_event import NodeEvent
+from fastdtlmapper.angst.model.transfer import Transfer
+
+__all__ = [
+    "NodeEvent",
+    "Transfer",
+]
diff --git a/fastdtlmapper/angst/model/node_event.py b/fastdtlmapper/angst/model/node_event.py
new file mode 100644
index 0000000..5cbed17
--- /dev/null
+++ b/fastdtlmapper/angst/model/node_event.py
@@ -0,0 +1,78 @@
+from __future__ import annotations
+
+from dataclasses import dataclass, field
+from typing import List, Optional
+
+from fastdtlmapper.angst.model.transfer import Transfer
+
+
+@dataclass
+class NodeEvent:
+    """Node Event DataClass"""
+
+    node_id: int
+    brn_num: int = 0
+    dup_num: int = 0
+    los_num: int = 0
+    trn_num: int = 0
+    trn_detail_list: List[Transfer] = field(default_factory=list)
+    gene_num: Optional[int] = None
+
+    @property
+    def gain_num(self) -> int:
+        """Number of (Brn + Dup + Trn) event"""
+        return self.brn_num + self.dup_num + self.trn_num
+
+    @property
+    def as_dtl_text(self) -> str:
+        """DTL event text"""
+        text = ""
+        text += f"{self.gene_num} ["
+        text += f"brn={self.brn_num} "
+        text += f"dup={self.dup_num} "
+        text += f"los={self.los_num} "
+        text += f"trn={self.trn_num}]"
+        return text
+
+    @property
+    def as_gain_loss_text(self) -> str:
+        """Gain-Loss event text"""
+        text = ""
+        text += f"{self.gene_num} ["
+        text += f"gain={self.gain_num} "
+        text += f"los={self.los_num}]"
+        return text
+
+    @property
+    def as_csv_format(self) -> str:
+        """Node event csv format text"""
+        trn_detail_text = ""
+        for trn_detail in self.trn_detail_list:
+            trn_detail_text += trn_detail.as_text + "|"
+        trn_detail_text = trn_detail_text.rstrip("|")
+        csv_text = (
+            f"{self.node_id},{self.gene_num},{self.gain_num},{self.brn_num},"
+            + f"{self.dup_num},{self.trn_num},{self.los_num},{trn_detail_text}"
+        )
+        return csv_text
+
+    @property
+    def as_tsv_format(self) -> str:
+        """Node event tsv format text"""
+        csv_text = self.as_csv_format
+        return csv_text.replace(",", "\t")
+
+    def __add__(self, other: NodeEvent):
+        if not isinstance(other, self.__class__) and self.node_id != other.node_id:
+            raise NotImplementedError()
+
+        ret_obj = NodeEvent(self.node_id)
+        ret_obj.brn_num = self.brn_num + other.brn_num
+        ret_obj.dup_num = self.dup_num + other.dup_num
+        ret_obj.los_num = self.los_num + other.los_num
+        ret_obj.trn_num = self.trn_num + other.trn_num
+        ret_obj.gene_num = self.gene_num + other.gene_num
+        ret_obj.trn_detail_list.extend(self.trn_detail_list)
+        ret_obj.trn_detail_list.extend(other.trn_detail_list)
+
+        return ret_obj
diff --git a/fastdtlmapper/angst/model/transfer.py b/fastdtlmapper/angst/model/transfer.py
new file mode 100644
index 0000000..42c2505
--- /dev/null
+++ b/fastdtlmapper/angst/model/transfer.py
@@ -0,0 +1,19 @@
+from dataclasses import dataclass
+from typing import Union
+
+
+@dataclass
+class Transfer:
+    """Transfer DataClass"""
+
+    donor_node_id: Union[int, str]
+    recipient_node_id: Union[int, str]
+    direction: bool = True
+
+    @property
+    def as_text(self) -> str:
+        """Transfer as text format (e.g. 1 -> 2)"""
+        if self.direction:
+            return f"{self.donor_node_id} -> {self.recipient_node_id}"
+        else:
+            return f"{self.donor_node_id} <-> {self.recipient_node_id}"
diff --git a/lib/angst/transfer_gene.py b/fastdtlmapper/angst/transfer_gene.py
similarity index 100%
rename from lib/angst/transfer_gene.py
rename to fastdtlmapper/angst/transfer_gene.py
diff --git a/bin/AnGST_wrapper.py b/fastdtlmapper/bin/AnGST_wrapper.py
similarity index 100%
rename from bin/AnGST_wrapper.py
rename to fastdtlmapper/bin/AnGST_wrapper.py
diff --git a/bin/OrthoFinder/License.md b/fastdtlmapper/bin/OrthoFinder/License.md
similarity index 100%
rename from bin/OrthoFinder/License.md
rename to fastdtlmapper/bin/OrthoFinder/License.md
diff --git a/bin/OrthoFinder/README.md b/fastdtlmapper/bin/OrthoFinder/README.md
similarity index 100%
rename from bin/OrthoFinder/README.md
rename to fastdtlmapper/bin/OrthoFinder/README.md
diff --git a/bin/OrthoFinder/orthofinder.py b/fastdtlmapper/bin/OrthoFinder/orthofinder.py
similarity index 100%
rename from bin/OrthoFinder/orthofinder.py
rename to fastdtlmapper/bin/OrthoFinder/orthofinder.py
diff --git a/bin/OrthoFinder/tools/__init__.py b/fastdtlmapper/bin/OrthoFinder/scripts_of/__init__.py
similarity index 100%
rename from bin/OrthoFinder/tools/__init__.py
rename to fastdtlmapper/bin/OrthoFinder/scripts_of/__init__.py
diff --git a/bin/OrthoFinder/scripts_of/__main__.py b/fastdtlmapper/bin/OrthoFinder/scripts_of/__main__.py
similarity index 100%
rename from bin/OrthoFinder/scripts_of/__main__.py
rename to fastdtlmapper/bin/OrthoFinder/scripts_of/__main__.py
diff --git a/bin/OrthoFinder/scripts_of/bin/diamond b/fastdtlmapper/bin/OrthoFinder/scripts_of/bin/diamond
similarity index 100%
rename from bin/OrthoFinder/scripts_of/bin/diamond
rename to fastdtlmapper/bin/OrthoFinder/scripts_of/bin/diamond
diff --git a/bin/OrthoFinder/scripts_of/bin/fastme b/fastdtlmapper/bin/OrthoFinder/scripts_of/bin/fastme
similarity index 100%
rename from bin/OrthoFinder/scripts_of/bin/fastme
rename to fastdtlmapper/bin/OrthoFinder/scripts_of/bin/fastme
diff --git a/bin/OrthoFinder/scripts_of/bin/mcl b/fastdtlmapper/bin/OrthoFinder/scripts_of/bin/mcl
similarity index 100%
rename from bin/OrthoFinder/scripts_of/bin/mcl
rename to fastdtlmapper/bin/OrthoFinder/scripts_of/bin/mcl
diff --git a/bin/OrthoFinder/scripts_of/blast_file_processor.py b/fastdtlmapper/bin/OrthoFinder/scripts_of/blast_file_processor.py
similarity index 100%
rename from bin/OrthoFinder/scripts_of/blast_file_processor.py
rename to fastdtlmapper/bin/OrthoFinder/scripts_of/blast_file_processor.py
diff --git a/bin/OrthoFinder/scripts_of/config.json b/fastdtlmapper/bin/OrthoFinder/scripts_of/config.json
similarity index 100%
rename from bin/OrthoFinder/scripts_of/config.json
rename to fastdtlmapper/bin/OrthoFinder/scripts_of/config.json
diff --git a/bin/OrthoFinder/scripts_of/consensus_tree.py b/fastdtlmapper/bin/OrthoFinder/scripts_of/consensus_tree.py
similarity index 100%
rename from bin/OrthoFinder/scripts_of/consensus_tree.py
rename to fastdtlmapper/bin/OrthoFinder/scripts_of/consensus_tree.py
diff --git a/bin/OrthoFinder/scripts_of/files.py b/fastdtlmapper/bin/OrthoFinder/scripts_of/files.py
similarity index 100%
rename from bin/OrthoFinder/scripts_of/files.py
rename to fastdtlmapper/bin/OrthoFinder/scripts_of/files.py
diff --git a/bin/OrthoFinder/scripts_of/matrices.py b/fastdtlmapper/bin/OrthoFinder/scripts_of/matrices.py
similarity index 100%
rename from bin/OrthoFinder/scripts_of/matrices.py
rename to fastdtlmapper/bin/OrthoFinder/scripts_of/matrices.py
diff --git a/bin/OrthoFinder/scripts_of/mcl.py b/fastdtlmapper/bin/OrthoFinder/scripts_of/mcl.py
similarity index 100%
rename from bin/OrthoFinder/scripts_of/mcl.py
rename to fastdtlmapper/bin/OrthoFinder/scripts_of/mcl.py
diff --git a/bin/OrthoFinder/scripts_of/newick.py b/fastdtlmapper/bin/OrthoFinder/scripts_of/newick.py
similarity index 100%
rename from bin/OrthoFinder/scripts_of/newick.py
rename to fastdtlmapper/bin/OrthoFinder/scripts_of/newick.py
diff --git a/bin/OrthoFinder/scripts_of/orthologues.py b/fastdtlmapper/bin/OrthoFinder/scripts_of/orthologues.py
similarity index 100%
rename from bin/OrthoFinder/scripts_of/orthologues.py
rename to fastdtlmapper/bin/OrthoFinder/scripts_of/orthologues.py
diff --git a/bin/OrthoFinder/scripts_of/parallel_task_manager.py b/fastdtlmapper/bin/OrthoFinder/scripts_of/parallel_task_manager.py
similarity index 100%
rename from bin/OrthoFinder/scripts_of/parallel_task_manager.py
rename to fastdtlmapper/bin/OrthoFinder/scripts_of/parallel_task_manager.py
diff --git a/bin/OrthoFinder/scripts_of/probroot.py b/fastdtlmapper/bin/OrthoFinder/scripts_of/probroot.py
similarity index 100%
rename from bin/OrthoFinder/scripts_of/probroot.py
rename to fastdtlmapper/bin/OrthoFinder/scripts_of/probroot.py
diff --git a/bin/OrthoFinder/scripts_of/program_caller.py b/fastdtlmapper/bin/OrthoFinder/scripts_of/program_caller.py
similarity index 100%
rename from bin/OrthoFinder/scripts_of/program_caller.py
rename to fastdtlmapper/bin/OrthoFinder/scripts_of/program_caller.py
diff --git a/bin/OrthoFinder/scripts_of/resolve.py b/fastdtlmapper/bin/OrthoFinder/scripts_of/resolve.py
similarity index 100%
rename from bin/OrthoFinder/scripts_of/resolve.py
rename to fastdtlmapper/bin/OrthoFinder/scripts_of/resolve.py
diff --git a/bin/OrthoFinder/scripts_of/stag.py b/fastdtlmapper/bin/OrthoFinder/scripts_of/stag.py
similarity index 100%
rename from bin/OrthoFinder/scripts_of/stag.py
rename to fastdtlmapper/bin/OrthoFinder/scripts_of/stag.py
diff --git a/bin/OrthoFinder/scripts_of/stride.py b/fastdtlmapper/bin/OrthoFinder/scripts_of/stride.py
similarity index 100%
rename from bin/OrthoFinder/scripts_of/stride.py
rename to fastdtlmapper/bin/OrthoFinder/scripts_of/stride.py
diff --git a/bin/OrthoFinder/scripts_of/tree.py b/fastdtlmapper/bin/OrthoFinder/scripts_of/tree.py
similarity index 100%
rename from bin/OrthoFinder/scripts_of/tree.py
rename to fastdtlmapper/bin/OrthoFinder/scripts_of/tree.py
diff --git a/bin/OrthoFinder/scripts_of/trees2ologs_dlcpar.py b/fastdtlmapper/bin/OrthoFinder/scripts_of/trees2ologs_dlcpar.py
similarity index 100%
rename from bin/OrthoFinder/scripts_of/trees2ologs_dlcpar.py
rename to fastdtlmapper/bin/OrthoFinder/scripts_of/trees2ologs_dlcpar.py
diff --git a/bin/OrthoFinder/scripts_of/trees2ologs_of.py b/fastdtlmapper/bin/OrthoFinder/scripts_of/trees2ologs_of.py
similarity index 100%
rename from bin/OrthoFinder/scripts_of/trees2ologs_of.py
rename to fastdtlmapper/bin/OrthoFinder/scripts_of/trees2ologs_of.py
diff --git a/bin/OrthoFinder/scripts_of/trees_msa.py b/fastdtlmapper/bin/OrthoFinder/scripts_of/trees_msa.py
similarity index 100%
rename from bin/OrthoFinder/scripts_of/trees_msa.py
rename to fastdtlmapper/bin/OrthoFinder/scripts_of/trees_msa.py
diff --git a/bin/OrthoFinder/scripts_of/trim.py b/fastdtlmapper/bin/OrthoFinder/scripts_of/trim.py
similarity index 100%
rename from bin/OrthoFinder/scripts_of/trim.py
rename to fastdtlmapper/bin/OrthoFinder/scripts_of/trim.py
diff --git a/bin/OrthoFinder/scripts_of/util.py b/fastdtlmapper/bin/OrthoFinder/scripts_of/util.py
similarity index 100%
rename from bin/OrthoFinder/scripts_of/util.py
rename to fastdtlmapper/bin/OrthoFinder/scripts_of/util.py
diff --git a/bin/OrthoFinder/scripts_of/wrapper_phyldog.py b/fastdtlmapper/bin/OrthoFinder/scripts_of/wrapper_phyldog.py
similarity index 100%
rename from bin/OrthoFinder/scripts_of/wrapper_phyldog.py
rename to fastdtlmapper/bin/OrthoFinder/scripts_of/wrapper_phyldog.py
diff --git a/lib/__init__.py b/fastdtlmapper/bin/OrthoFinder/tools/__init__.py
similarity index 100%
rename from lib/__init__.py
rename to fastdtlmapper/bin/OrthoFinder/tools/__init__.py
diff --git a/bin/OrthoFinder/tools/convert_orthofinder_tree_ids.py b/fastdtlmapper/bin/OrthoFinder/tools/convert_orthofinder_tree_ids.py
similarity index 100%
rename from bin/OrthoFinder/tools/convert_orthofinder_tree_ids.py
rename to fastdtlmapper/bin/OrthoFinder/tools/convert_orthofinder_tree_ids.py
diff --git a/bin/OrthoFinder/tools/make_ultrametric.py b/fastdtlmapper/bin/OrthoFinder/tools/make_ultrametric.py
similarity index 100%
rename from bin/OrthoFinder/tools/make_ultrametric.py
rename to fastdtlmapper/bin/OrthoFinder/tools/make_ultrametric.py
diff --git a/bin/OrthoFinder/tools/orthogroup_gene_count.py b/fastdtlmapper/bin/OrthoFinder/tools/orthogroup_gene_count.py
similarity index 100%
rename from bin/OrthoFinder/tools/orthogroup_gene_count.py
rename to fastdtlmapper/bin/OrthoFinder/tools/orthogroup_gene_count.py
diff --git a/bin/OrthoFinder/tools/primary_transcript.py b/fastdtlmapper/bin/OrthoFinder/tools/primary_transcript.py
similarity index 100%
rename from bin/OrthoFinder/tools/primary_transcript.py
rename to fastdtlmapper/bin/OrthoFinder/tools/primary_transcript.py
diff --git a/bin/OrthoFinder/version_2.5.2 b/fastdtlmapper/bin/OrthoFinder/version_2.5.2
similarity index 100%
rename from bin/OrthoFinder/version_2.5.2
rename to fastdtlmapper/bin/OrthoFinder/version_2.5.2
diff --git a/bin/angst/angst_lib/AnGST.py b/fastdtlmapper/bin/angst/angst_lib/AnGST.py
similarity index 100%
rename from bin/angst/angst_lib/AnGST.py
rename to fastdtlmapper/bin/angst/angst_lib/AnGST.py
diff --git a/bin/angst/angst_lib/AnGSTHelper.py b/fastdtlmapper/bin/angst/angst_lib/AnGSTHelper.py
similarity index 100%
rename from bin/angst/angst_lib/AnGSTHelper.py
rename to fastdtlmapper/bin/angst/angst_lib/AnGSTHelper.py
diff --git a/bin/angst/angst_lib/AnGSTInput.py b/fastdtlmapper/bin/angst/angst_lib/AnGSTInput.py
similarity index 100%
rename from bin/angst/angst_lib/AnGSTInput.py
rename to fastdtlmapper/bin/angst/angst_lib/AnGSTInput.py
diff --git a/bin/angst/angst_lib/PyVM.py b/fastdtlmapper/bin/angst/angst_lib/PyVM.py
similarity index 100%
rename from bin/angst/angst_lib/PyVM.py
rename to fastdtlmapper/bin/angst/angst_lib/PyVM.py
diff --git a/bin/angst/angst_lib/output.py b/fastdtlmapper/bin/angst/angst_lib/output.py
similarity index 100%
rename from bin/angst/angst_lib/output.py
rename to fastdtlmapper/bin/angst/angst_lib/output.py
diff --git a/bin/angst/angst_lib/reconcile.py b/fastdtlmapper/bin/angst/angst_lib/reconcile.py
similarity index 100%
rename from bin/angst/angst_lib/reconcile.py
rename to fastdtlmapper/bin/angst/angst_lib/reconcile.py
diff --git a/bin/angst/tree_lib/branch.py b/fastdtlmapper/bin/angst/tree_lib/branch.py
similarity index 100%
rename from bin/angst/tree_lib/branch.py
rename to fastdtlmapper/bin/angst/tree_lib/branch.py
diff --git a/bin/angst/tree_lib/multitree.py b/fastdtlmapper/bin/angst/tree_lib/multitree.py
similarity index 100%
rename from bin/angst/tree_lib/multitree.py
rename to fastdtlmapper/bin/angst/tree_lib/multitree.py
diff --git a/bin/angst/tree_lib/node.py b/fastdtlmapper/bin/angst/tree_lib/node.py
similarity index 100%
rename from bin/angst/tree_lib/node.py
rename to fastdtlmapper/bin/angst/tree_lib/node.py
diff --git a/bin/iqtree b/fastdtlmapper/bin/iqtree
similarity index 100%
rename from bin/iqtree
rename to fastdtlmapper/bin/iqtree
diff --git a/bin/mafft/mafft b/fastdtlmapper/bin/mafft/mafft
similarity index 100%
rename from bin/mafft/mafft
rename to fastdtlmapper/bin/mafft/mafft
diff --git a/bin/mafft/mafftdir/bin/mafft b/fastdtlmapper/bin/mafft/mafftdir/bin/mafft
similarity index 100%
rename from bin/mafft/mafftdir/bin/mafft
rename to fastdtlmapper/bin/mafft/mafftdir/bin/mafft
diff --git a/bin/mafft/mafftdir/libexec/addsingle b/fastdtlmapper/bin/mafft/mafftdir/libexec/addsingle
similarity index 100%
rename from bin/mafft/mafftdir/libexec/addsingle
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/addsingle
diff --git a/bin/mafft/mafftdir/libexec/contrafoldwrap b/fastdtlmapper/bin/mafft/mafftdir/libexec/contrafoldwrap
similarity index 100%
rename from bin/mafft/mafftdir/libexec/contrafoldwrap
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/contrafoldwrap
diff --git a/bin/mafft/mafftdir/libexec/countlen b/fastdtlmapper/bin/mafft/mafftdir/libexec/countlen
similarity index 100%
rename from bin/mafft/mafftdir/libexec/countlen
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/countlen
diff --git a/bin/mafft/mafftdir/libexec/dash_alignments b/fastdtlmapper/bin/mafft/mafftdir/libexec/dash_alignments
similarity index 100%
rename from bin/mafft/mafftdir/libexec/dash_alignments
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/dash_alignments
diff --git a/bin/mafft/mafftdir/libexec/dash_client b/fastdtlmapper/bin/mafft/mafftdir/libexec/dash_client
similarity index 100%
rename from bin/mafft/mafftdir/libexec/dash_client
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/dash_client
diff --git a/bin/mafft/mafftdir/libexec/dash_sequences.fa b/fastdtlmapper/bin/mafft/mafftdir/libexec/dash_sequences.fa
similarity index 100%
rename from bin/mafft/mafftdir/libexec/dash_sequences.fa
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/dash_sequences.fa
diff --git a/bin/mafft/mafftdir/libexec/disttbfast b/fastdtlmapper/bin/mafft/mafftdir/libexec/disttbfast
similarity index 100%
rename from bin/mafft/mafftdir/libexec/disttbfast
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/disttbfast
diff --git a/bin/mafft/mafftdir/libexec/dndblast b/fastdtlmapper/bin/mafft/mafftdir/libexec/dndblast
similarity index 100%
rename from bin/mafft/mafftdir/libexec/dndblast
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/dndblast
diff --git a/bin/mafft/mafftdir/libexec/dndfast7 b/fastdtlmapper/bin/mafft/mafftdir/libexec/dndfast7
similarity index 100%
rename from bin/mafft/mafftdir/libexec/dndfast7
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/dndfast7
diff --git a/bin/mafft/mafftdir/libexec/dndpre b/fastdtlmapper/bin/mafft/mafftdir/libexec/dndpre
similarity index 100%
rename from bin/mafft/mafftdir/libexec/dndpre
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/dndpre
diff --git a/bin/mafft/mafftdir/libexec/dvtditr b/fastdtlmapper/bin/mafft/mafftdir/libexec/dvtditr
similarity index 100%
rename from bin/mafft/mafftdir/libexec/dvtditr
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/dvtditr
diff --git a/bin/mafft/mafftdir/libexec/f2cl b/fastdtlmapper/bin/mafft/mafftdir/libexec/f2cl
similarity index 100%
rename from bin/mafft/mafftdir/libexec/f2cl
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/f2cl
diff --git a/bin/mafft/mafftdir/libexec/filter b/fastdtlmapper/bin/mafft/mafftdir/libexec/filter
similarity index 100%
rename from bin/mafft/mafftdir/libexec/filter
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/filter
diff --git a/bin/mafft/mafftdir/libexec/getlag b/fastdtlmapper/bin/mafft/mafftdir/libexec/getlag
similarity index 100%
rename from bin/mafft/mafftdir/libexec/getlag
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/getlag
diff --git a/bin/mafft/mafftdir/libexec/hat3 b/fastdtlmapper/bin/mafft/mafftdir/libexec/hat3
similarity index 100%
rename from bin/mafft/mafftdir/libexec/hat3
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/hat3
diff --git a/bin/mafft/mafftdir/libexec/hex2maffttext b/fastdtlmapper/bin/mafft/mafftdir/libexec/hex2maffttext
similarity index 100%
rename from bin/mafft/mafftdir/libexec/hex2maffttext
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/hex2maffttext
diff --git a/bin/mafft/mafftdir/libexec/mafft-distance b/fastdtlmapper/bin/mafft/mafftdir/libexec/mafft-distance
similarity index 100%
rename from bin/mafft/mafftdir/libexec/mafft-distance
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/mafft-distance
diff --git a/bin/mafft/mafftdir/libexec/mafft-homologs.1 b/fastdtlmapper/bin/mafft/mafftdir/libexec/mafft-homologs.1
similarity index 100%
rename from bin/mafft/mafftdir/libexec/mafft-homologs.1
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/mafft-homologs.1
diff --git a/bin/mafft/mafftdir/libexec/mafft-profile b/fastdtlmapper/bin/mafft/mafftdir/libexec/mafft-profile
similarity index 100%
rename from bin/mafft/mafftdir/libexec/mafft-profile
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/mafft-profile
diff --git a/bin/mafft/mafftdir/libexec/mafft.1 b/fastdtlmapper/bin/mafft/mafftdir/libexec/mafft.1
similarity index 100%
rename from bin/mafft/mafftdir/libexec/mafft.1
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/mafft.1
diff --git a/bin/mafft/mafftdir/libexec/mafftash_premafft.pl b/fastdtlmapper/bin/mafft/mafftdir/libexec/mafftash_premafft.pl
similarity index 100%
rename from bin/mafft/mafftdir/libexec/mafftash_premafft.pl
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/mafftash_premafft.pl
diff --git a/bin/mafft/mafftdir/libexec/maffttext2hex b/fastdtlmapper/bin/mafft/mafftdir/libexec/maffttext2hex
similarity index 100%
rename from bin/mafft/mafftdir/libexec/maffttext2hex
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/maffttext2hex
diff --git a/bin/mafft/mafftdir/libexec/makedirectionlist b/fastdtlmapper/bin/mafft/mafftdir/libexec/makedirectionlist
similarity index 100%
rename from bin/mafft/mafftdir/libexec/makedirectionlist
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/makedirectionlist
diff --git a/bin/mafft/mafftdir/libexec/mccaskillwrap b/fastdtlmapper/bin/mafft/mafftdir/libexec/mccaskillwrap
similarity index 100%
rename from bin/mafft/mafftdir/libexec/mccaskillwrap
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/mccaskillwrap
diff --git a/bin/mafft/mafftdir/libexec/multi2hat3s b/fastdtlmapper/bin/mafft/mafftdir/libexec/multi2hat3s
similarity index 100%
rename from bin/mafft/mafftdir/libexec/multi2hat3s
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/multi2hat3s
diff --git a/bin/mafft/mafftdir/libexec/nodepair b/fastdtlmapper/bin/mafft/mafftdir/libexec/nodepair
similarity index 100%
rename from bin/mafft/mafftdir/libexec/nodepair
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/nodepair
diff --git a/bin/mafft/mafftdir/libexec/pairash b/fastdtlmapper/bin/mafft/mafftdir/libexec/pairash
similarity index 100%
rename from bin/mafft/mafftdir/libexec/pairash
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/pairash
diff --git a/bin/mafft/mafftdir/libexec/pairlocalalign b/fastdtlmapper/bin/mafft/mafftdir/libexec/pairlocalalign
similarity index 100%
rename from bin/mafft/mafftdir/libexec/pairlocalalign
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/pairlocalalign
diff --git a/bin/mafft/mafftdir/libexec/regtable2seq b/fastdtlmapper/bin/mafft/mafftdir/libexec/regtable2seq
similarity index 100%
rename from bin/mafft/mafftdir/libexec/regtable2seq
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/regtable2seq
diff --git a/bin/mafft/mafftdir/libexec/replaceu b/fastdtlmapper/bin/mafft/mafftdir/libexec/replaceu
similarity index 100%
rename from bin/mafft/mafftdir/libexec/replaceu
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/replaceu
diff --git a/bin/mafft/mafftdir/libexec/restoreu b/fastdtlmapper/bin/mafft/mafftdir/libexec/restoreu
similarity index 100%
rename from bin/mafft/mafftdir/libexec/restoreu
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/restoreu
diff --git a/bin/mafft/mafftdir/libexec/score b/fastdtlmapper/bin/mafft/mafftdir/libexec/score
similarity index 100%
rename from bin/mafft/mafftdir/libexec/score
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/score
diff --git a/bin/mafft/mafftdir/libexec/seekquencer_premafft.pl b/fastdtlmapper/bin/mafft/mafftdir/libexec/seekquencer_premafft.pl
similarity index 100%
rename from bin/mafft/mafftdir/libexec/seekquencer_premafft.pl
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/seekquencer_premafft.pl
diff --git a/bin/mafft/mafftdir/libexec/seq2regtable b/fastdtlmapper/bin/mafft/mafftdir/libexec/seq2regtable
similarity index 100%
rename from bin/mafft/mafftdir/libexec/seq2regtable
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/seq2regtable
diff --git a/bin/mafft/mafftdir/libexec/setcore b/fastdtlmapper/bin/mafft/mafftdir/libexec/setcore
similarity index 100%
rename from bin/mafft/mafftdir/libexec/setcore
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/setcore
diff --git a/bin/mafft/mafftdir/libexec/setdirection b/fastdtlmapper/bin/mafft/mafftdir/libexec/setdirection
similarity index 100%
rename from bin/mafft/mafftdir/libexec/setdirection
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/setdirection
diff --git a/bin/mafft/mafftdir/libexec/sextet5 b/fastdtlmapper/bin/mafft/mafftdir/libexec/sextet5
similarity index 100%
rename from bin/mafft/mafftdir/libexec/sextet5
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/sextet5
diff --git a/bin/mafft/mafftdir/libexec/splittbfast b/fastdtlmapper/bin/mafft/mafftdir/libexec/splittbfast
similarity index 100%
rename from bin/mafft/mafftdir/libexec/splittbfast
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/splittbfast
diff --git a/bin/mafft/mafftdir/libexec/tbfast b/fastdtlmapper/bin/mafft/mafftdir/libexec/tbfast
similarity index 100%
rename from bin/mafft/mafftdir/libexec/tbfast
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/tbfast
diff --git a/bin/mafft/mafftdir/libexec/version b/fastdtlmapper/bin/mafft/mafftdir/libexec/version
similarity index 100%
rename from bin/mafft/mafftdir/libexec/version
rename to fastdtlmapper/bin/mafft/mafftdir/libexec/version
diff --git a/bin/parallel b/fastdtlmapper/bin/parallel
similarity index 100%
rename from bin/parallel
rename to fastdtlmapper/bin/parallel
diff --git a/bin/trimal b/fastdtlmapper/bin/trimal
similarity index 100%
rename from bin/trimal
rename to fastdtlmapper/bin/trimal
diff --git a/lib/config.py b/fastdtlmapper/config.py
similarity index 99%
rename from lib/config.py
rename to fastdtlmapper/config.py
index 57715e7..5bdbec9 100644
--- a/lib/config.py
+++ b/fastdtlmapper/config.py
@@ -98,7 +98,7 @@ def _delete_prev_stderr_log(self) -> None:
     def _add_bin_path(self) -> None:
         """Add bin programs path"""
         # Bin path list
-        bin_path = Path(__file__).parent.parent / "bin"
+        bin_path = Path(__file__).parent / "bin"
         mafft_path = bin_path / "mafft"
         ortho_finder_path = bin_path / "OrthoFinder"
         ortho_finder_tool_path = ortho_finder_path / "tools"
diff --git a/fastdtlmapper/goea/__init__.py b/fastdtlmapper/goea/__init__.py
new file mode 100644
index 0000000..857f79e
--- /dev/null
+++ b/fastdtlmapper/goea/__init__.py
@@ -0,0 +1,7 @@
+from fastdtlmapper.goea.goea import GOEA
+from fastdtlmapper.goea.og_go_association import OgGoAssociation
+
+__all__ = [
+    "GOEA",
+    "OgGoAssociation",
+]
diff --git a/lib/goea/goea.py b/fastdtlmapper/goea/goea.py
similarity index 100%
rename from lib/goea/goea.py
rename to fastdtlmapper/goea/goea.py
diff --git a/lib/goea/og_go_association.py b/fastdtlmapper/goea/og_go_association.py
similarity index 100%
rename from lib/goea/og_go_association.py
rename to fastdtlmapper/goea/og_go_association.py
diff --git a/lib/input_check.py b/fastdtlmapper/input_check.py
similarity index 99%
rename from lib/input_check.py
rename to fastdtlmapper/input_check.py
index a95860a..f2e539b 100644
--- a/lib/input_check.py
+++ b/fastdtlmapper/input_check.py
@@ -5,7 +5,7 @@
 from Bio import Phylo
 from Bio.Phylo.BaseTree import Tree
 
-from lib.util import UtilSeq
+from fastdtlmapper.util import UtilSeq
 
 
 @dataclass
diff --git a/lib/reconcilation.py b/fastdtlmapper/reconcilation.py
similarity index 98%
rename from lib/reconcilation.py
rename to fastdtlmapper/reconcilation.py
index 80f39e7..281461f 100644
--- a/lib/reconcilation.py
+++ b/fastdtlmapper/reconcilation.py
@@ -4,8 +4,8 @@
 from Bio import Phylo
 from Bio.Phylo.BaseTree import Tree
 
-from lib.angst import NodeEvent, Transfer
-from lib.util import UtilSeq
+from fastdtlmapper.angst.model import NodeEvent, Transfer
+from fastdtlmapper.util import UtilSeq
 
 
 @dataclass
diff --git a/FastDTLgoea.py b/fastdtlmapper/scripts/FastDTLgoea.py
similarity index 95%
rename from FastDTLgoea.py
rename to fastdtlmapper/scripts/FastDTLgoea.py
index 0806501..651b7a5 100755
--- a/FastDTLgoea.py
+++ b/fastdtlmapper/scripts/FastDTLgoea.py
@@ -10,28 +10,20 @@
 from typing import Tuple
 
 import pandas as pd
+from fastdtlmapper.goea import GOEA, OgGoAssociation
 
-from lib.goea import GOEA, OgGoAssociation
 
+def main():
+    """Run GOEA(GO Enrichment Analysis) for FastDTLmapper result"""
+    # Get arguments
+    args = get_args()
+    indir = args.indir
+    plot_pvalue_thr = args.plot_pvalue_thr
+    plot_max_num = args.plot_max_num
+    plot_format = args.plot_format
+    plot_color = args.plot_color
+    use_adjusted_pvalue = args.adjusted_pvalue
 
-def main(
-    indir: Path,
-    plot_pvalue_thr: float,
-    plot_max_num: int,
-    plot_format: str,
-    plot_color: str,
-    use_adjusted_pvalue: bool,
-):
-    """Run GOEA(GO Enrichment Analysis) for FastDTLmapper result
-
-    Args:
-        indir (Path): FastDTLmapper result directory
-        plot_pvalue_thr (float): Plot GOterm pvalue threshold
-        plot_max_num (int): Plot GOterm max number
-        plot_format (str): Plot file format
-        plot_color (str): Plot specified hexcolor
-        use_adjusted_pvalue (bool): Use adjusted pvalue or not
-    """
     # Output directory
     outdir = indir / "04_functional_analysis"
     go_annotation_dir = outdir / "go_annotation"
@@ -412,12 +404,4 @@ def format_significant_go_dataframe(
 
 
 if __name__ == "__main__":
-    args = get_args()
-    main(
-        args.indir,
-        args.plot_pvalue_thr,
-        args.plot_max_num,
-        args.plot_format,
-        args.plot_color,
-        args.adjusted_pvalue,
-    )
+    main()
diff --git a/FastDTLmapper.py b/fastdtlmapper/scripts/FastDTLmapper.py
similarity index 97%
rename from FastDTLmapper.py
rename to fastdtlmapper/scripts/FastDTLmapper.py
index e5a0a2e..c7b4db0 100755
--- a/FastDTLmapper.py
+++ b/fastdtlmapper/scripts/FastDTLmapper.py
@@ -5,15 +5,17 @@
 from collections import defaultdict
 from typing import Dict, List
 
-from lib.angst import AngstEventMap, AngstTransferGene, NodeEvent
-from lib.config import Config, get_config
-from lib.input_check import InputCheck
-from lib.reconcilation import Reconciliation as Rec
-from lib.util import UtilSeq, UtilTree
+from fastdtlmapper.angst import AngstEventMap, AngstTransferGene, NodeEvent
+from fastdtlmapper.config import Config, get_config
+from fastdtlmapper.input_check import InputCheck
+from fastdtlmapper.reconcilation import Reconciliation as Rec
+from fastdtlmapper.util import UtilSeq, UtilTree
 
 
-def main(config: Config):
+def main():
     """Main function"""
+    # Get run config
+    config = get_config()
     # Check user input
     InputCheck(config.indir, config.tree_file).run()
     # # 00. Prepare analysis data
@@ -34,6 +36,8 @@ def main(config: Config):
     output_aggregate_map_results(config, group_id2all_node_event)
     output_aggregate_transfer_results(config)
 
+    config.output_run_config_log()
+
 
 def format_user_tree(config: Config) -> None:
     """Format user newick tree file (Make ultrametric & Add node id)"""
@@ -307,6 +311,4 @@ def output_aggregate_transfer_results(config: Config) -> None:
 
 
 if __name__ == "__main__":
-    config = get_config()
-    main(config)
-    config.output_run_config_log()
+    main()
diff --git a/fastdtlmapper/util/__init__.py b/fastdtlmapper/util/__init__.py
new file mode 100644
index 0000000..821a693
--- /dev/null
+++ b/fastdtlmapper/util/__init__.py
@@ -0,0 +1,7 @@
+from fastdtlmapper.util.seq import UtilSeq
+from fastdtlmapper.util.tree import UtilTree
+
+__all__ = [
+    "UtilSeq",
+    "UtilTree",
+]
diff --git a/lib/util/seq.py b/fastdtlmapper/util/seq.py
similarity index 100%
rename from lib/util/seq.py
rename to fastdtlmapper/util/seq.py
diff --git a/lib/util/tree.py b/fastdtlmapper/util/tree.py
similarity index 98%
rename from lib/util/tree.py
rename to fastdtlmapper/util/tree.py
index 30c3023..ddf4154 100644
--- a/lib/util/tree.py
+++ b/fastdtlmapper/util/tree.py
@@ -3,7 +3,7 @@
 
 from Bio import Phylo, SeqIO
 from Bio.Phylo.BaseTree import Tree
-from lib.angst.model import NodeEvent
+from fastdtlmapper.angst.model import NodeEvent
 
 
 @dataclass
diff --git a/lib/angst/__init__.py b/lib/angst/__init__.py
deleted file mode 100644
index a1b04a0..0000000
--- a/lib/angst/__init__.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from lib.angst.event_map import AngstEventMap
-from lib.angst.model import NodeEvent, Transfer
-from lib.angst.transfer_gene import AngstTransferGene
-
-__all__ = [
-    "AngstEventMap",
-    "AngstTransferGene",
-    "NodeEvent",
-    "Transfer",
-]
diff --git a/lib/goea/__init__.py b/lib/goea/__init__.py
deleted file mode 100644
index b9b0e1b..0000000
--- a/lib/goea/__init__.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from lib.goea.goea import GOEA
-from lib.goea.og_go_association import OgGoAssociation
-
-__all__ = [
-    "GOEA",
-    "OgGoAssociation",
-]
diff --git a/lib/util/__init__.py b/lib/util/__init__.py
deleted file mode 100644
index 23bee21..0000000
--- a/lib/util/__init__.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from lib.util.seq import UtilSeq
-from lib.util.tree import UtilTree
-
-__all__ = [
-    "UtilSeq",
-    "UtilTree",
-]
diff --git a/poetry.lock b/poetry.lock
index 16e2306..5704064 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -20,6 +20,28 @@ importlib-metadata = {version = ">=0.23,<5", markers = "python_version == \"3.7\
 [package.extras]
 test = ["coverage", "flake8", "pexpect", "wheel"]
 
+[[package]]
+name = "atomicwrites"
+version = "1.4.0"
+description = "Atomic file writes."
+category = "main"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+
+[[package]]
+name = "attrs"
+version = "21.2.0"
+description = "Classes Without Boilerplate"
+category = "main"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+
+[package.extras]
+dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit"]
+docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"]
+tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface"]
+tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"]
+
 [[package]]
 name = "backcall"
 version = "0.2.0"
@@ -110,10 +132,24 @@ importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
 name = "colorama"
 version = "0.4.4"
 description = "Cross-platform colored terminal text."
-category = "dev"
+category = "main"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
 
+[[package]]
+name = "coverage"
+version = "6.0"
+description = "Code coverage measurement for Python"
+category = "main"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+tomli = {version = "*", optional = true, markers = "extra == \"toml\""}
+
+[package.extras]
+toml = ["tomli"]
+
 [[package]]
 name = "debugpy"
 version = "1.4.3"
@@ -192,7 +228,7 @@ python-versions = ">=3.5"
 name = "importlib-metadata"
 version = "4.8.1"
 description = "Read metadata from Python packages"
-category = "dev"
+category = "main"
 optional = false
 python-versions = ">=3.6"
 
@@ -205,6 +241,14 @@ docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"]
 perf = ["ipython"]
 testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"]
 
+[[package]]
+name = "iniconfig"
+version = "1.1.1"
+description = "iniconfig: brain-dead simple config-ini parsing"
+category = "main"
+optional = false
+python-versions = "*"
+
 [[package]]
 name = "ipykernel"
 version = "6.4.1"
@@ -359,6 +403,17 @@ category = "main"
 optional = false
 python-versions = ">=3.7,<3.11"
 
+[[package]]
+name = "packaging"
+version = "21.0"
+description = "Core utilities for Python packages"
+category = "main"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+pyparsing = ">=2.0.2"
+
 [[package]]
 name = "pandas"
 version = "1.3.3"
@@ -441,6 +496,21 @@ python-versions = ">=3.6"
 docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"]
 test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"]
 
+[[package]]
+name = "pluggy"
+version = "1.0.0"
+description = "plugin and hook calling mechanisms for python"
+category = "main"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
+
+[package.extras]
+dev = ["pre-commit", "tox"]
+testing = ["pytest", "pytest-benchmark"]
+
 [[package]]
 name = "prompt-toolkit"
 version = "3.0.20"
@@ -464,7 +534,7 @@ python-versions = "*"
 name = "py"
 version = "1.10.0"
 description = "library with cross-python path, ini-parsing, io, code, log facilities"
-category = "dev"
+category = "main"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
 
@@ -533,6 +603,43 @@ category = "main"
 optional = false
 python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
 
+[[package]]
+name = "pytest"
+version = "6.2.5"
+description = "pytest: simple powerful testing with Python"
+category = "main"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
+attrs = ">=19.2.0"
+colorama = {version = "*", markers = "sys_platform == \"win32\""}
+importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
+iniconfig = "*"
+packaging = "*"
+pluggy = ">=0.12,<2.0"
+py = ">=1.8.2"
+toml = "*"
+
+[package.extras]
+testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"]
+
+[[package]]
+name = "pytest-cov"
+version = "3.0.0"
+description = "Pytest plugin for measuring coverage."
+category = "main"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+coverage = {version = ">=5.2.1", extras = ["toml"]}
+pytest = ">=4.6"
+
+[package.extras]
+testing = ["fields", "hunter", "process-tests", "six", "pytest-xdist", "virtualenv"]
+
 [[package]]
 name = "python-dateutil"
 version = "2.8.2"
@@ -644,11 +751,19 @@ build = ["cython (>=0.29)"]
 develop = ["cython (>=0.29)"]
 docs = ["sphinx", "nbconvert", "jupyter-client", "ipykernel", "matplotlib", "nbformat", "numpydoc", "pandas-datareader"]
 
+[[package]]
+name = "toml"
+version = "0.10.2"
+description = "Python Library for Tom's Obvious, Minimal Language"
+category = "main"
+optional = false
+python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
+
 [[package]]
 name = "tomli"
 version = "1.2.1"
 description = "A lil' TOML parser"
-category = "dev"
+category = "main"
 optional = false
 python-versions = ">=3.6"
 
@@ -683,7 +798,7 @@ python-versions = "*"
 name = "typing-extensions"
 version = "3.10.0.2"
 description = "Backported and Experimental Type Hints for Python 3.5+"
-category = "dev"
+category = "main"
 optional = false
 python-versions = "*"
 
@@ -736,7 +851,7 @@ python-versions = ">=3.4"
 name = "zipp"
 version = "3.5.0"
 description = "Backport of pathlib-compatible object wrapper for zip files"
-category = "dev"
+category = "main"
 optional = false
 python-versions = ">=3.6"
 
@@ -747,7 +862,7 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytes
 [metadata]
 lock-version = "1.1"
 python-versions = ">=3.7.1,<3.10"
-content-hash = "03e9635c174513dbe16dc5d51cfe7713909a9d1b8d88b45c0c204de21b1acd0c"
+content-hash = "7c33edf824cba1181e290b0fed5eed9f03167c8a3be390a9bb9641d9a2611f90"
 
 [metadata.files]
 appnope = [
@@ -758,6 +873,14 @@ argcomplete = [
     {file = "argcomplete-1.12.3-py2.py3-none-any.whl", hash = "sha256:291f0beca7fd49ce285d2f10e4c1c77e9460cf823eef2de54df0c0fec88b0d81"},
     {file = "argcomplete-1.12.3.tar.gz", hash = "sha256:2c7dbffd8c045ea534921e63b0be6fe65e88599990d8dc408ac8c542b72a5445"},
 ]
+atomicwrites = [
+    {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"},
+    {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"},
+]
+attrs = [
+    {file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"},
+    {file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"},
+]
 backcall = [
     {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"},
     {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"},
@@ -856,6 +979,43 @@ colorama = [
     {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
     {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
 ]
+coverage = [
+    {file = "coverage-6.0-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:3dfb23cc180b674a11a559183dff9655beb9da03088f3fe3c4f3a6d200c86f05"},
+    {file = "coverage-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b5dd5ae0a9cd55d71f1335c331e9625382239b8cede818fb62d8d2702336dbf8"},
+    {file = "coverage-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8426fec5ad5a6e8217921716b504e9b6e1166dc147e8443b4855e329db686282"},
+    {file = "coverage-6.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:aa5d4d43fa18cc9d0c6e02a83de0b9729b5451a9066574bd276481474f0a53ab"},
+    {file = "coverage-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b78dd3eeb8f5ff26d2113c41836bac04a9ea91be54c346826b54a373133c8c53"},
+    {file = "coverage-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:581fddd2f883379bd5af51da9233e0396b6519f3d3eeae4fb88867473be6d56e"},
+    {file = "coverage-6.0-cp310-cp310-win32.whl", hash = "sha256:43bada49697a62ffa0283c7f01bbc76aac562c37d4bb6c45d56dd008d841194e"},
+    {file = "coverage-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:fa816e97cfe1f691423078dffa39a18106c176f28008db017b3ce3e947c34aa5"},
+    {file = "coverage-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:5c191e01b23e760338f19d8ba2470c0dad44c8b45e41ac043b2db84efc62f695"},
+    {file = "coverage-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:274a612f67f931307706b60700f1e4cf80e1d79dff6c282fc9301e4565e78724"},
+    {file = "coverage-6.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a9dbfcbc56d8de5580483cf2caff6a59c64d3e88836cbe5fb5c20c05c29a8808"},
+    {file = "coverage-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e63490e8a6675cee7a71393ee074586f7eeaf0e9341afd006c5d6f7eec7c16d7"},
+    {file = "coverage-6.0-cp36-cp36m-win32.whl", hash = "sha256:72f8c99f1527c5a8ee77c890ea810e26b39fd0b4c2dffc062e20a05b2cca60ef"},
+    {file = "coverage-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:88f1810eb942e7063d051d87aaaa113eb5fd5a7fd2cda03a972de57695b8bb1a"},
+    {file = "coverage-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:befb5ffa9faabef6dadc42622c73de168001425258f0b7e402a2934574e7a04b"},
+    {file = "coverage-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7dbda34e8e26bd86606ba8a9c13ccb114802e01758a3d0a75652ffc59a573220"},
+    {file = "coverage-6.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:b4ee5815c776dfa3958ba71c7cd4cdd8eb40d79358a18352feb19562fe4408c4"},
+    {file = "coverage-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d82cbef1220703ce56822be7fbddb40736fc1a928ac893472df8aff7421ae0aa"},
+    {file = "coverage-6.0-cp37-cp37m-win32.whl", hash = "sha256:d795a2c92fe8cb31f6e9cd627ee4f39b64eb66bf47d89d8fcf7cb3d17031c887"},
+    {file = "coverage-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:6e216e4021c934246c308fd3e0d739d9fa8a3f4ea414f584ab90ef9c1592f282"},
+    {file = "coverage-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8305e14112efb74d0b5fec4df6e41cafde615c2392a7e51c84013cafe945842c"},
+    {file = "coverage-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4865dc4a7a566147cbdc2b2f033a6cccc99a7dcc89995137765c384f6c73110b"},
+    {file = "coverage-6.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:25df2bc53a954ba2ccf230fa274d1de341f6aa633d857d75e5731365f7181749"},
+    {file = "coverage-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:08fd55d2e00dac4c18a2fa26281076035ec86e764acdc198b9185ce749ada58f"},
+    {file = "coverage-6.0-cp38-cp38-win32.whl", hash = "sha256:11ce082eb0f7c2bbfe96f6c8bcc3a339daac57de4dc0f3186069ec5c58da911c"},
+    {file = "coverage-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:7844a8c6a0fee401edbf578713c2473e020759267c40261b294036f9d3eb6a2d"},
+    {file = "coverage-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bea681309bdd88dd1283a8ba834632c43da376d9bce05820826090aad80c0126"},
+    {file = "coverage-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e735ab8547d8a1fe8e58dd765d6f27ac539b395f52160d767b7189f379f9be7a"},
+    {file = "coverage-6.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:7593a49300489d064ebb6c58539f52cbbc4a2e6a4385de5e92cae1563f88a425"},
+    {file = "coverage-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:adb0f4c3c8ba8104378518a1954cbf3d891a22c13fd0e0bf135391835f44f288"},
+    {file = "coverage-6.0-cp39-cp39-win32.whl", hash = "sha256:8da0c4a26a831b392deaba5fdd0cd7838d173b47ce2ec3d0f37be630cb09ef6e"},
+    {file = "coverage-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:7af2f8e7bb54ace984de790e897f858e88068d8fbc46c9490b7c19c59cf51822"},
+    {file = "coverage-6.0-pp36-none-any.whl", hash = "sha256:82b58d37c47d93a171be9b5744bcc96a0012cbf53d5622b29a49e6be2097edd7"},
+    {file = "coverage-6.0-pp37-none-any.whl", hash = "sha256:fff04bfefb879edcf616f1ce5ea6f4a693b5976bdc5e163f8464f349c25b59f0"},
+    {file = "coverage-6.0.tar.gz", hash = "sha256:17983f6ccc47f4864fd16d20ff677782b23d1207bf222d10e4d676e4636b0872"},
+]
 debugpy = [
     {file = "debugpy-1.4.3-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:88b17d7c2130968f75bdc706a33f46a8a6bb90f09512ea3bd984659d446ee4f4"},
     {file = "debugpy-1.4.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5ded60b402f83df46dee3f25ae5851809937176afdafd3fdbaab60b633b77cad"},
@@ -902,6 +1062,10 @@ importlib-metadata = [
     {file = "importlib_metadata-4.8.1-py3-none-any.whl", hash = "sha256:b618b6d2d5ffa2f16add5697cf57a46c76a56229b0ed1c438322e4e95645bd15"},
     {file = "importlib_metadata-4.8.1.tar.gz", hash = "sha256:f284b3e11256ad1e5d03ab86bb2ccd6f5339688ff17a4d797a0fe7df326f23b1"},
 ]
+iniconfig = [
+    {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
+    {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
+]
 ipykernel = [
     {file = "ipykernel-6.4.1-py3-none-any.whl", hash = "sha256:a3f6c2dda2ecf63b37446808a70ed825fea04790779ca524889c596deae0def8"},
     {file = "ipykernel-6.4.1.tar.gz", hash = "sha256:df3355e5eec23126bc89767a676c5f0abfc7f4c3497d118c592b83b316e8c0cd"},
@@ -974,6 +1138,10 @@ numpy = [
     {file = "numpy-1.21.2-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d96a6a7d74af56feb11e9a443150216578ea07b7450f7c05df40eec90af7f4a7"},
     {file = "numpy-1.21.2.zip", hash = "sha256:423216d8afc5923b15df86037c6053bf030d15cc9e3224206ef868c2d63dd6dc"},
 ]
+packaging = [
+    {file = "packaging-21.0-py3-none-any.whl", hash = "sha256:c86254f9220d55e31cc94d69bade760f0847da8000def4dfe1c6b872fd14ff14"},
+    {file = "packaging-21.0.tar.gz", hash = "sha256:7dc96269f53a4ccec5c0670940a4281106dd0bb343f47b7471f779df49c2fbe7"},
+]
 pandas = [
     {file = "pandas-1.3.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68408a39a54ebadb9014ee5a4fae27b2fe524317bc80adf56c9ac59e8f8ea431"},
     {file = "pandas-1.3.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86b16b1b920c4cb27fdd65a2c20258bcd9c794be491290660722bb0ea765054d"},
@@ -1021,6 +1189,10 @@ platformdirs = [
     {file = "platformdirs-2.3.0-py3-none-any.whl", hash = "sha256:8003ac87717ae2c7ee1ea5a84a1a61e87f3fbd16eb5aadba194ea30a9019f648"},
     {file = "platformdirs-2.3.0.tar.gz", hash = "sha256:15b056538719b1c94bdaccb29e5f81879c7f7f0f4a153f46086d155dffcd4f0f"},
 ]
+pluggy = [
+    {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
+    {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
+]
 prompt-toolkit = [
     {file = "prompt_toolkit-3.0.20-py3-none-any.whl", hash = "sha256:6076e46efae19b1e0ca1ec003ed37a933dc94b4d20f486235d436e64771dcd5c"},
     {file = "prompt_toolkit-3.0.20.tar.gz", hash = "sha256:eb71d5a6b72ce6db177af4a7d4d7085b99756bf656d98ffcc4fecd36850eea6c"},
@@ -1061,6 +1233,14 @@ pyparsing = [
     {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"},
     {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"},
 ]
+pytest = [
+    {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"},
+    {file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"},
+]
+pytest-cov = [
+    {file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"},
+    {file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"},
+]
 python-dateutil = [
     {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
     {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
@@ -1219,6 +1399,10 @@ statsmodels = [
     {file = "statsmodels-0.12.2-cp39-none-win_amd64.whl", hash = "sha256:94d3632d56c13eebebaefb52bd4b43144ad5a131337b57842f46db826fa7d2d3"},
     {file = "statsmodels-0.12.2.tar.gz", hash = "sha256:8ad7a7ae7cdd929095684118e3b05836c0ccb08b6a01fe984159475d174a1b10"},
 ]
+toml = [
+    {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
+    {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
+]
 tomli = [
     {file = "tomli-1.2.1-py3-none-any.whl", hash = "sha256:8dd0e9524d6f386271a36b41dbf6c57d8e32fd96fd22b6584679dc569d20899f"},
     {file = "tomli-1.2.1.tar.gz", hash = "sha256:a5b75cb6f3968abb47af1b40c1819dc519ea82bcc065776a866e8d74c5ca9442"},
diff --git a/pyproject.toml b/pyproject.toml
index 527d5ca..bcec9e3 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,6 +4,10 @@ version = "0.1.0"
 description = "Fast genome-wide DTL(Duplication-Transfer-Loss) event mapping tool"
 authors = ["moshi"]
 
+[tool.poetry.scripts]
+FastDTLmapper = "fastdtlmapper.scripts.FastDTLmapper:main"
+FastDTLgoea = "fastdtlmapper.scripts.FastDTLgoea:main"
+
 [tool.poetry.dependencies]
 python = ">=3.7.1,<3.10"
 biopython = "^1.79"
@@ -11,6 +15,8 @@ scipy = "^1.7.1"
 goatools = "^1.1.6"
 pandas = "^1.3.3"
 numpy = "^1.21.2"
+pytest = "^6.2.5"
+pytest-cov = "^3.0.0"
 
 [tool.poetry.dev-dependencies]
 flake8 = "^3.9.2"


Test patch:
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/angst/__init__.py b/tests/angst/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/angst/model/__init__.py b/tests/angst/model/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/angst/model/test_node_event.py b/tests/angst/model/test_node_event.py
new file mode 100644
index 0000000..b264fc7
--- /dev/null
+++ b/tests/angst/model/test_node_event.py
@@ -0,0 +1,41 @@
+from fastdtlmapper.angst.model import NodeEvent, Transfer
+
+
+def test_gain_num():
+    """gain_num test"""
+    node_event = NodeEvent(0, 1, 1, 1, 0, [], 0)
+    assert node_event.gain_num == 2
+
+
+def test_as_dtl_text():
+    """as_dtl_text test"""
+    node_event = NodeEvent(0, 1, 3, 1, 0, [], 5)
+    assert node_event.as_dtl_text == "5 [brn=1 dup=3 los=1 trn=0]"
+
+
+def test_as_gain_loss_text():
+    """as_gain_loss_text test"""
+    node_event = NodeEvent(0, 1, 3, 1, 0, [], 5)
+    assert node_event.as_gain_loss_text == "5 [gain=4 los=1]"
+
+
+def test_as_csv_format():
+    """as_csv_format test"""
+    node_event = NodeEvent(0, 1, 3, 1, 0, [], 5)
+    assert node_event.as_csv_format == "0,5,4,1,3,0,1,"
+
+
+def test_as_tsv_format():
+    """as_tsv_format test"""
+    node_event = NodeEvent(0, 1, 3, 1, 0, [], 5)
+    assert node_event.as_tsv_format == "0\t5\t4\t1\t3\t0\t1\t"
+
+
+def test___add__():
+    """__add__ test"""
+    node_event1 = NodeEvent(0, 1, 3, 1, 0, [Transfer(10, 20)], 5)
+    node_event2 = NodeEvent(0, 0, 2, 1, 1, [Transfer(30, 40)], 5)
+
+    assert node_event1 + node_event2 == NodeEvent(
+        0, 1, 5, 2, 1, [Transfer(10, 20), Transfer(30, 40)], 10
+    )
diff --git a/tests/angst/model/test_transfer.py b/tests/angst/model/test_transfer.py
new file mode 100644
index 0000000..3d83ca2
--- /dev/null
+++ b/tests/angst/model/test_transfer.py
@@ -0,0 +1,13 @@
+from fastdtlmapper.angst.model import Transfer
+
+
+def test_as_text_with_direction():
+    """as_text with direction test"""
+    transfer = Transfer(1, 2)
+    assert transfer.as_text == "1 -> 2"
+
+
+def test_as_text_with_no_direction():
+    """as_text with no direction test"""
+    transfer = Transfer(1, 2, False)
+    assert transfer.as_text == "1 <-> 2"