diff --git a/3dna/RotTable.py b/3dna/RotTable.py new file mode 100644 index 0000000000000000000000000000000000000000..0f0b4b599a0581e705c63e224fc78f250ca2f8d0 --- /dev/null +++ b/3dna/RotTable.py @@ -0,0 +1,38 @@ +from copy import deepcopy +from json import load as json_load +from os import path as os_path + +here = os_path.abspath(os_path.dirname(__file__)) + +class RotTable: + """Represents the rotation table""" + + # 3 first values: 3 angle values + # 3 last values: SD values + __ORIGINAL_ROT_TABLE = json_load( + open(os_path.join(here, 'table.json')) + ) + + def __init__(self): + self.__Rot_Table = deepcopy(RotTable.__ORIGINAL_ROT_TABLE) + + + ################### + # WRITING METHODS # + ################### + + + ################### + # READING METHODS # + ################### + + def getTwist(self, dinucleotide): + return self.__Rot_Table[dinucleotide][0] + + def getWedge(self, dinucleotide): + return self.__Rot_Table[dinucleotide][1] + + def getDirection(self, dinucleotide): + return self.__Rot_Table[dinucleotide][2] + + ################### diff --git a/Traj3D.py b/3dna/Traj3D.py similarity index 52% rename from Traj3D.py rename to 3dna/Traj3D.py index eee71819327b28c570771dcdca2b603043a014b9..0ccf73c64fa217b48a59f4c7648d636ca39f7459 100644 --- a/Traj3D.py +++ b/3dna/Traj3D.py @@ -1,22 +1,25 @@ #For computing -import mathutils +from mathutils import ( + Matrix, + Vector +) import math #For drawing import numpy as np import matplotlib.pyplot as plt -from mpl_toolkits.mplot3d import Axes3D -from matplotlib import collections as mc class Traj3D: """Represents a 3D trajectory""" # Vertical translation (elevation) between two di-nucleotides - __MATRIX_T = mathutils.Matrix.Translation((0.0, 0.0, 3.38/2.0, 1.0)) + __MATRIX_T = Matrix.Translation((0.0, 0.0, 3.38/2.0, 1.0)) def __init__(self): self.__Traj3D = {} + self.fig = plt.figure() + self.ax = self.fig.add_subplot(111, projection='3d') def getTraj(self): return self.__Traj3D @@ -24,10 +27,10 @@ class Traj3D: def compute(self, dna_seq, rot_table): # Matrice cumulant l'ensemble des transformations géométriques engendrées par la séquence d'ADN - total_matrix = mathutils.Matrix() + total_matrix = Matrix() # On enregistre la position du premier nucléotide - self.__Traj3D = [mathutils.Vector((0.0, 0.0, 0.0, 1.0))] + self.__Traj3D = [Vector((0.0, 0.0, 0.0, 1.0))] matrices_Rz = {} matrices_Q = {} @@ -37,31 +40,36 @@ class Traj3D: dinucleotide = dna_seq[i-1]+dna_seq[i] # On remplit au fur et à mesure les matrices de rotation if dinucleotide not in matrices_Rz: - matrices_Rz[dinucleotide] = mathutils.Matrix.Rotation(math.radians(rot_table.getTwist(dinucleotide)/2), 4, 'Z') + matrices_Rz[dinucleotide] = Matrix.Rotation( + math.radians(rot_table.getTwist(dinucleotide)/2), 4, 'Z' + ) matrices_Q[dinucleotide] = \ - mathutils.Matrix.Rotation(math.radians((rot_table.getDirection(dinucleotide)-90)), 4, 'Z') \ - @ mathutils.Matrix.Rotation(math.radians((-rot_table.getWedge(dinucleotide))), 4, 'X') \ - @ mathutils.Matrix.Rotation(math.radians((90-rot_table.getDirection(dinucleotide))), 4, 'Z') + Matrix.Rotation( + math.radians((rot_table.getDirection(dinucleotide)-90)), 4, 'Z' + ) \ + @ Matrix.Rotation( + math.radians((-rot_table.getWedge(dinucleotide))), 4, 'X' + ) \ + @ Matrix.Rotation( + math.radians((90-rot_table.getDirection(dinucleotide))), 4, 'Z' + ) - - # On calcule les transformations géométrique selon le dinucleotide courant, et on les ajoute à la matrice totale - total_matrix = total_matrix @ \ + # On calcule les transformations géométriques selon le dinucleotide courant, et on les ajoute à la matrice totale + total_matrix @= \ self.__MATRIX_T \ @ matrices_Rz[dinucleotide] \ @ matrices_Q[dinucleotide] \ - @ matrices_Rz[dinucleotide] @ \ - self.__MATRIX_T + @ matrices_Rz[dinucleotide] \ + @ self.__MATRIX_T # On calcule la position du nucléotide courant en appliquant toutes les transformations géométriques à la position du premier nucléotide self.__Traj3D.append(total_matrix @ self.__Traj3D[0]) - - def draw(self, filename): + def draw(self): xyz = np.array(self.__Traj3D) - self.__Traj3D = [] x, y, z = xyz[:,0], xyz[:,1], xyz[:,2] - fig = plt.figure() - ax = fig.add_subplot(111, projection='3d') - ax.plot(x,y,z) + self.ax.plot(x,y,z) plt.show() - plt.savefig(filename) + + def write(self, filename): + self.fig.savefig(filename) \ No newline at end of file diff --git a/3dna/__main__.py b/3dna/__main__.py new file mode 100644 index 0000000000000000000000000000000000000000..0ba4cc37dbbfb858feaadf27681f5d085479273c --- /dev/null +++ b/3dna/__main__.py @@ -0,0 +1,28 @@ +from .RotTable import RotTable +from .Traj3D import Traj3D + +import argparse +parser = argparse.ArgumentParser() +parser.add_argument("filename", help="input filename of DNA sequence") +parser.parse_args() +args = parser.parse_args() + +def main(): + + rot_table = RotTable() + traj = Traj3D() + + # Read file + lineList = [line.rstrip('\n') for line in open(args.filename)] + # Formatting + seq = ''.join(lineList[1:]) + traj.compute(seq, rot_table) + + print(traj.getTraj()) + + traj.draw() + traj.write(args.filename+".png") + + +if __name__ == "__main__" : + main() diff --git a/3dna/table.json b/3dna/table.json new file mode 100644 index 0000000000000000000000000000000000000000..860b8f923b6fd4fd24c8f29e93ec6b049cdce2e5 --- /dev/null +++ b/3dna/table.json @@ -0,0 +1,18 @@ +{ + "AA": [35.62 , 7.2 , -154 , 0.06 , 0.6 , 0], + "AC": [34.4 , 1.1 , 143 , 1.3 , 5 , 0], + "AG": [27.7 , 8.4 , 2 , 1.5 , 3 , 0], + "AT": [31.5 , 2.6 , 0 , 1.1 , 2 , 0], + "CA": [34.5 , 3.5 , -64 , 0.9 , 34 , 0], + "CC": [33.67 , 2.1 , -57 , 0.07 , 2.1 , 0], + "CG": [29.8 , 6.7 , 0 , 1.1 , 1.5 , 0], + "CT": [27.7 , 8.4 , -2 , 1.5 , 3 , 0], + "GA": [36.9 , 5.3 , 120 , 0.9 , 6 , 0], + "GC": [40 , 5 , 180 , 1.2 , 1.275 , 0], + "GG": [33.67 , 2.1 , 57 , 0.07 , 2.1 , 0], + "GT": [34.4 , 1.1 , -143 , 1.3 , 5 , 0], + "TA": [36 , 0.9 , 0 , 1.1 , 2 , 0], + "TC": [36.9 , 5.3 , -120 , 0.9 , 6 , 0], + "TG": [34.5 , 3.5 , 64 , 0.9 , 34 , 0], + "TT": [35.62 , 7.2 , 154 , 0.06 , 0.6 , 0] +} \ No newline at end of file diff --git a/INSTALL.md b/INSTALL.md index 4aa8903cc1ccd6541fcbe530ea4c5cf5db3f3cc5..336490df0da231ba1f2634b7025b47013b182d1f 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -3,7 +3,7 @@ <img src="https://www.nicepng.com/png/full/506-5068487_open-install-png-logo.png" alt="Install" height="20"/> `docker build -t 3dna .` - <img src="https://icon-library.com/images/play-icon-white-png/play-icon-white-png-26.jpg" alt="Run" height="20"/> `docker run --rm -v $PWD:$PWD -w $PWD 3dna python Main.py` + <img src="https://icon-library.com/images/play-icon-white-png/play-icon-white-png-26.jpg" alt="Run" height="20"/> `docker run --rm -v $PWD:$PWD -w $PWD 3dna python -m 3dna data/plasmid_8k.fasta` <br/> <br/> @@ -15,10 +15,10 @@ Then, - <img src="https://icon-library.com/images/play-icon-white-png/play-icon-white-png-26.jpg" alt="Run" height="20"/> `conda run -n 3dna python Main.py` + <img src="https://icon-library.com/images/play-icon-white-png/play-icon-white-png-26.jpg" alt="Run" height="20"/> `conda run -n 3dna python -m 3dna data/plasmid_8k.fasta` or <img src="https://icon-library.com/images/play-icon-white-png/play-icon-white-png-26.jpg" alt="Run" height="20"/> `conda activate 3dna` - <img src="https://icon-library.com/images/play-icon-white-png/play-icon-white-png-26.jpg" alt="Run" height="20"/> `python Main.py` + <img src="https://icon-library.com/images/play-icon-white-png/play-icon-white-png-26.jpg" alt="Run" height="20"/> `python -m 3dna data/plasmid_8k.fasta` diff --git a/Main.py b/Main.py deleted file mode 100644 index 117218873e754bf86a1de4e51592c20defc4c271..0000000000000000000000000000000000000000 --- a/Main.py +++ /dev/null @@ -1,33 +0,0 @@ -from RotTable import * -from Traj3D import * - -import argparse -parser = argparse.ArgumentParser() -parser.add_argument("--filename", help="input filename of DNA sequence") -parser.parse_args() -args = parser.parse_args() - -def main(): - - rot_table = RotTable() - traj = Traj3D() - - if args.filename: - # Read file - lineList = [line.rstrip('\n') for line in open(args.filename)] - # Formatting - seq = ''.join(lineList[1:]) - traj.compute(seq, rot_table) - else: - traj.compute("AAAGGATCTTCTTGAGATCCTTTTTTTCTGCGCGTAATCTGCTGCCAGTAAACGAAAAAACCGCCTGGGGAGGCGGTTTAGTCGAAGGTTAAGTCAG", rot_table) - - print(traj.getTraj()) - - if args.filename: - traj.draw(args.filename+".png") - else: - traj.draw("sample.png") - - -if __name__ == "__main__" : - main() diff --git a/RotTable.py b/RotTable.py deleted file mode 100644 index 51a9cddd2c2d828af4db68252527f3e555681efb..0000000000000000000000000000000000000000 --- a/RotTable.py +++ /dev/null @@ -1,53 +0,0 @@ -import mathutils -import math - -class RotTable: - """Represents the rotation table""" - - # 3 first values: 3 angle values - # 3 last values: SD values - __ORIGINAL_ROT_TABLE = {\ - "AA": [35.62 , 7.2 , -154 , 0.06 , 0.6 , 0],\ - "AC": [34.4 , 1.1 , 143 , 1.3 , 5 , 0],\ - "AG": [27.7 , 8.4 , 2 , 1.5 , 3 , 0],\ - "AT": [31.5 , 2.6 , 0 , 1.1 , 2 , 0],\ - "CA": [34.5 , 3.5 , -64 , 0.9 , 34 , 0],\ - "CC": [33.67 , 2.1 , -57 , 0.07 , 2.1 , 0],\ - "CG": [29.8 , 6.7 , 0 , 1.1 , 1.5 , 0],\ - "CT": [27.7 , 8.4 , -2 , 1.5 , 3 , 0],\ - "GA": [36.9 , 5.3 , 120 , 0.9 , 6 , 0],\ - "GC": [40 , 5 , 180 , 1.2 , 1.275 , 0],\ - "GG": [33.67 , 2.1 , 57 , 0.07 , 2.1 , 0],\ - "GT": [34.4 , 1.1 , -143 , 1.3 , 5 , 0],\ - "TA": [36 , 0.9 , 0 , 1.1 , 2 , 0],\ - "TC": [36.9 , 5.3 , -120 , 0.9 , 6 , 0],\ - "TG": [34.5 , 3.5 , 64 , 0.9 , 34 , 0],\ - "TT": [35.62 , 7.2 , 154 , 0.06 , 0.6 , 0]\ - } - - def __init__(self): - self.__Rot_Table = {} - for dinucleotide in RotTable.__ORIGINAL_ROT_TABLE: - self.__Rot_Table[dinucleotide] = RotTable.__ORIGINAL_ROT_TABLE[dinucleotide][:3] - - - - ################### - # WRITING METHODS # - ################### - - - ################### - # READING METHODS # - ################### - - def getTwist(self, dinucleotide): - return self.__Rot_Table[dinucleotide][0] - - def getWedge(self, dinucleotide): - return self.__Rot_Table[dinucleotide][1] - - def getDirection(self, dinucleotide): - return self.__Rot_Table[dinucleotide][2] - - ################### diff --git a/plasmid_180k.fasta b/data/plasmid_180k.fasta similarity index 100% rename from plasmid_180k.fasta rename to data/plasmid_180k.fasta diff --git a/plasmid_8k.fasta b/data/plasmid_8k.fasta similarity index 100% rename from plasmid_8k.fasta rename to data/plasmid_8k.fasta