libz 0.7__tar.gz → 0.9__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. {libz-0.7 → libz-0.9}/PKG-INFO +1 -1
  2. libz-0.9/libz/BIO/__init__.py +14 -0
  3. libz-0.9/libz/BIO/prac1.py +186 -0
  4. libz-0.9/libz/BIO/prac2.py +215 -0
  5. libz-0.9/libz/BIO/prac3.py +77 -0
  6. libz-0.9/libz/BIO/prac4.py +97 -0
  7. libz-0.9/libz/BIO/prac5.py +151 -0
  8. libz-0.9/libz/BIO/prac6.py +292 -0
  9. libz-0.9/libz/BIO/prac7.py +117 -0
  10. libz-0.9/libz/BIO/prac8.py +55 -0
  11. libz-0.9/libz/DL/__init__.py +15 -0
  12. libz-0.9/libz/DL/prac8.py +73 -0
  13. {libz-0.7 → libz-0.9}/libz/DL/prac9.py +73 -73
  14. libz-0.9/libz/DLG/__init__.py +16 -0
  15. {libz-0.7 → libz-0.9}/libz/__init__.py +1 -1
  16. {libz-0.7 → libz-0.9}/libz/_core.py +56 -50
  17. {libz-0.7 → libz-0.9}/libz.egg-info/PKG-INFO +1 -1
  18. {libz-0.7 → libz-0.9}/libz.egg-info/SOURCES.txt +0 -2
  19. {libz-0.7 → libz-0.9}/pyproject.toml +1 -1
  20. libz-0.7/libz/BIO/__init__.py +0 -3
  21. libz-0.7/libz/BIO/prac1.py +0 -4
  22. libz-0.7/libz/BIO/prac10.py +0 -4
  23. libz-0.7/libz/BIO/prac2.py +0 -4
  24. libz-0.7/libz/BIO/prac3.py +0 -4
  25. libz-0.7/libz/BIO/prac4.py +0 -4
  26. libz-0.7/libz/BIO/prac5.py +0 -4
  27. libz-0.7/libz/BIO/prac6.py +0 -4
  28. libz-0.7/libz/BIO/prac7.py +0 -4
  29. libz-0.7/libz/BIO/prac8.py +0 -4
  30. libz-0.7/libz/BIO/prac9.py +0 -4
  31. libz-0.7/libz/DL/__init__.py +0 -15
  32. libz-0.7/libz/DL/prac8.py +0 -73
  33. libz-0.7/libz/DLG/__init__.py +0 -16
  34. {libz-0.7 → libz-0.9}/README.md +0 -0
  35. {libz-0.7 → libz-0.9}/libz/AWT/__init__.py +0 -0
  36. {libz-0.7 → libz-0.9}/libz/AWT/prac1.py +0 -0
  37. {libz-0.7 → libz-0.9}/libz/AWT/prac10.py +0 -0
  38. {libz-0.7 → libz-0.9}/libz/AWT/prac2.py +0 -0
  39. {libz-0.7 → libz-0.9}/libz/AWT/prac3.py +0 -0
  40. {libz-0.7 → libz-0.9}/libz/AWT/prac4.py +0 -0
  41. {libz-0.7 → libz-0.9}/libz/AWT/prac5.py +0 -0
  42. {libz-0.7 → libz-0.9}/libz/AWT/prac6.py +0 -0
  43. {libz-0.7 → libz-0.9}/libz/AWT/prac7.py +0 -0
  44. {libz-0.7 → libz-0.9}/libz/AWT/prac8.py +0 -0
  45. {libz-0.7 → libz-0.9}/libz/AWT/prac9.py +0 -0
  46. {libz-0.7 → libz-0.9}/libz/BDA/__init__.py +0 -0
  47. {libz-0.7 → libz-0.9}/libz/BDA/prac1.py +0 -0
  48. {libz-0.7 → libz-0.9}/libz/BDA/prac10.py +0 -0
  49. {libz-0.7 → libz-0.9}/libz/BDA/prac2.py +0 -0
  50. {libz-0.7 → libz-0.9}/libz/BDA/prac3.py +0 -0
  51. {libz-0.7 → libz-0.9}/libz/BDA/prac4.py +0 -0
  52. {libz-0.7 → libz-0.9}/libz/BDA/prac5.py +0 -0
  53. {libz-0.7 → libz-0.9}/libz/BDA/prac6.py +0 -0
  54. {libz-0.7 → libz-0.9}/libz/BDA/prac7.py +0 -0
  55. {libz-0.7 → libz-0.9}/libz/BDA/prac8.py +0 -0
  56. {libz-0.7 → libz-0.9}/libz/BDA/prac9.py +0 -0
  57. {libz-0.7 → libz-0.9}/libz/DL/prac1.py +0 -0
  58. {libz-0.7 → libz-0.9}/libz/DL/prac2.py +0 -0
  59. {libz-0.7 → libz-0.9}/libz/DL/prac3.py +0 -0
  60. {libz-0.7 → libz-0.9}/libz/DL/prac4.py +0 -0
  61. {libz-0.7 → libz-0.9}/libz/DL/prac5.py +0 -0
  62. {libz-0.7 → libz-0.9}/libz/DL/prac6.py +0 -0
  63. {libz-0.7 → libz-0.9}/libz/DL/prac7.py +0 -0
  64. {libz-0.7 → libz-0.9}/libz/DLG/prac1.py +0 -0
  65. {libz-0.7 → libz-0.9}/libz/DLG/prac2.py +0 -0
  66. {libz-0.7 → libz-0.9}/libz/DLG/prac3.py +0 -0
  67. {libz-0.7 → libz-0.9}/libz/DLG/prac4.py +0 -0
  68. {libz-0.7 → libz-0.9}/libz/DLG/prac5.py +0 -0
  69. {libz-0.7 → libz-0.9}/libz/DLG/prac6.py +0 -0
  70. {libz-0.7 → libz-0.9}/libz/DLG/prac7.py +0 -0
  71. {libz-0.7 → libz-0.9}/libz/_update.py +0 -0
  72. {libz-0.7 → libz-0.9}/libz.egg-info/dependency_links.txt +0 -0
  73. {libz-0.7 → libz-0.9}/libz.egg-info/top_level.txt +0 -0
  74. {libz-0.7 → libz-0.9}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: libz
3
- Version: 0.7
3
+ Version: 0.9
4
4
  Summary: A lightweight Python utility toolkit.
5
5
  Requires-Python: >=3.7
6
6
  Description-Content-Type: text/markdown
@@ -0,0 +1,14 @@
1
+ from libz._core import register
2
+
3
+ TITLES = {
4
+ 1: "Retrieval from GenBank, BLASTN / BLASTP search, sequence manipulation",
5
+ 2: "Pairwise sequence alignment - Smith Waterman / Needleman Wunsch",
6
+ 3: "Dynamic programming algorithm for pairwise sequence alignment",
7
+ 4: "Sequence alignment and phylogenetic reconstruction",
8
+ 5: "BLASTP search - unmatched amino acids, % matching, amino acid count",
9
+ 6: "Protein structure analysis - homology modelling",
10
+ 7: "Regular expression of protein sequences from different organisms",
11
+ 8: "GenBank record FJ966082 - comments, translation, FASTA format",
12
+ }
13
+
14
+ register(__name__, globals(), TITLES)
@@ -0,0 +1,186 @@
1
+ # uv add biopython
2
+
3
+ from Bio.Seq import Seq
4
+
5
+ dna = Seq(
6
+ "AATTCTAGGCCGTCCTGGCGATAAAGGTGAGCCAGGTAAACATGTGCCCGGAGTTGCACCACCAGGACCA"
7
+ "CCAGGTCGACCGGGTGATATGGGACCACCTGGACCACCTGGGCCACCAGGCGAGAAAGGAAAACCTGGAA"
8
+ "CAAAAGGCCCAATAGGACCACCGGGAGACCAAGGAAATCCAGGTATTTATATTCGTAGTTAATGCTTGAT"
9
+ "TCGAGAATT"
10
+ )
11
+
12
+ print("Complement:", dna.complement())
13
+
14
+ print("Reverse complement:", dna.reverse_complement())
15
+
16
+ rna = dna.transcribe()
17
+ print("RNA:", rna)
18
+
19
+ print("DNA to protein:", dna.translate())
20
+ print("RNA to protein:", rna.translate())
21
+
22
+ import random
23
+
24
+ random.choices("HT", weights=[0.5, 0.5], k=5)
25
+
26
+ import random
27
+ import numpy as np
28
+
29
+ def generate_random_sequence(sequence_length, probability_distribution):
30
+ sequence = ""
31
+ for i in range(0, sequence_length):
32
+ sequence = (
33
+ sequence
34
+ + random.choices(
35
+ ["A", "C", "G", "T"], weights=probability_distribution, k=1
36
+ )[0]
37
+ )
38
+ return sequence
39
+
40
+ our_random_seq = generate_random_sequence(100, [0.25, 0.25, 0.25, 0.25])
41
+ print(our_random_seq)
42
+
43
+ from Bio.Seq import Seq
44
+
45
+ my_dna = Seq("ATCGATGATAGGATA")
46
+ type(my_dna)
47
+
48
+ my_protein = Seq("KGLYQRGD")
49
+
50
+ a_sub_sequence = my_dna[3:7]
51
+ the_sequence_length = len(my_dna)
52
+
53
+ print(the_sequence_length, a_sub_sequence)
54
+
55
+ the_rev_comp = my_dna.reverse_complement()
56
+
57
+ print(the_rev_comp)
58
+
59
+ print(my_dna.transcribe())
60
+ print(my_dna.translate())
61
+
62
+ def verify(sequence):
63
+ # This code verifies if a sequence is a DNA or RNA
64
+ seq = set(sequence)
65
+
66
+ if seq == {"A", "T", "C", "G"}.union(seq):
67
+ return "DNA"
68
+ elif seq == {"A", "U", "C", "G"}.union(seq):
69
+ return "RNA"
70
+ else:
71
+ return "Invalid"
72
+
73
+ seq1 = "ATGCAGCTGTGTTACGCGAT"
74
+ seq2 = "UGGCGGAUAAGCGCA"
75
+ seq3 = "TYHGGHHHHH"
76
+
77
+ print(seq1 + " is " + verify(seq1))
78
+ print(seq2 + " is " + verify(seq2))
79
+ print(seq3 + " is " + verify(seq3))
80
+
81
+ def verify(sequence):
82
+ # This code verifies if a sequence is a DNA or RNA
83
+ seq = set(sequence)
84
+
85
+ if seq == {"A", "T", "C", "G"}.union(seq):
86
+ return "DNA"
87
+ elif seq == {"A", "U", "C", "G"}.union(seq):
88
+ return "RNA"
89
+ else:
90
+ return "Invalid"
91
+
92
+ def rev_comp_st(seq):
93
+ # This function returns a reverse complement of a DNA or RNA strand
94
+ verified = verify(seq)
95
+ if verified == "DNA":
96
+
97
+ # complement strand
98
+ seq = (
99
+ seq.replace("A", "t").replace("C", "g").replace("T", "a").replace("G", "c")
100
+ )
101
+ seq = seq.upper()
102
+
103
+ # reverse strand
104
+ seq = seq[::-1]
105
+ return seq
106
+
107
+ elif verified == "RNA":
108
+
109
+ # complement strand
110
+ seq = (
111
+ seq.replace("A", "u").replace("C", "g").replace("U", "a").replace("G", "c")
112
+ )
113
+ seq = seq.upper()
114
+
115
+ # reverse strand
116
+ seq = seq[::-1]
117
+ return seq
118
+ else:
119
+ return "Invalid"
120
+
121
+ # test variables
122
+ seq1 = "ATGCAGCTGTGTTACGCGAT"
123
+ seq2 = "UGGCGGAUAAGCGCA"
124
+ seq3 = "TYHGGHHHHH"
125
+
126
+ print("The reverse complementary strand of " + seq1 + " is " + rev_comp_st(seq1))
127
+ print("The reverse complementary strand of " + seq2 + " is " + rev_comp_st(seq2))
128
+ print("The reverse complementary strand of " + seq3 + " is " + rev_comp_st(seq3))
129
+
130
+ def verify(sequence):
131
+ # This code verifies if a sequence is a DNA or RNA
132
+ seq = set(sequence)
133
+
134
+ if seq == {"A", "T", "C", "G"}.union(seq):
135
+ return "DNA"
136
+ elif seq == {"A", "U", "C", "G"}.union(seq):
137
+ return "RNA"
138
+ else:
139
+ return "Invalid"
140
+
141
+ def rev_comp_if(seq):
142
+ comp = []
143
+ if verify(seq) == "DNA":
144
+ for base in seq:
145
+ if base == "A":
146
+ comp.append("T")
147
+ elif base == "G":
148
+ comp.append("C")
149
+ elif base == "T":
150
+ comp.append("A")
151
+ elif base == "C":
152
+ comp.append("G")
153
+ elif verify(seq) == "RNA":
154
+ for base in seq:
155
+ if base == "U":
156
+ comp.append("A")
157
+ elif base == "G":
158
+ comp.append("C")
159
+ elif base == "A":
160
+ comp.append("U")
161
+ elif base == "C":
162
+ comp.append("G")
163
+ else:
164
+ return "Invalid"
165
+
166
+ # reverse the sequence
167
+ comp_rev = comp[::-1]
168
+
169
+ # convert list to string
170
+ comp_rev = "".join(comp_rev)
171
+ return comp_rev
172
+
173
+ seq1 = "ATGCAGCTGTGTTACGCGAT"
174
+ seq2 = "UGGCGGAUAAGCGCA"
175
+ seq3 = "TYHGGHHHHH"
176
+
177
+ print("The reverse complementary strand of " + seq1 + " is " + rev_comp_if(seq1))
178
+ print("The reverse complementary strand of " + seq2 + " is " + rev_comp_if(seq2))
179
+ print("The reverse complementary strand of " + seq3 + " is " + rev_comp_if(seq3))
180
+
181
+ from Bio.Seq import Seq
182
+
183
+ messenger_rna = Seq("AUGGCCAUUGUAAUGGGCCGCUGAAAGGGUGCCCGAUAG")
184
+ print(messenger_rna)
185
+
186
+ print(messenger_rna.translate())
@@ -0,0 +1,215 @@
1
+ # uv add biopython
2
+
3
+ from Bio import pairwise2
4
+ from Bio import Align
5
+
6
+ aligner = Align.PairwiseAligner()
7
+
8
+ aligner.match_score = 1.0
9
+
10
+ target = "GAACT"
11
+ query = "GAT"
12
+
13
+ score = aligner.score(target, query)
14
+ print(score)
15
+
16
+ alignments = aligner.align(target, query)
17
+
18
+ alignment = alignments[0]
19
+ print(alignment)
20
+
21
+ for alignment in alignments:
22
+ print(alignment)
23
+
24
+ print(alignment.score)
25
+ print(alignment.target)
26
+ print(alignment.query)
27
+
28
+ alignment = alignments[0]
29
+
30
+ print(alignment.coordinates)
31
+
32
+ print(len(alignment))
33
+ print(alignment.length)
34
+
35
+ alignment = alignments[1]
36
+ print(alignment)
37
+
38
+ print(alignment.aligned)
39
+
40
+ aligner.mode = "global"
41
+ aligner.mismatch_score = -10
42
+
43
+ alignments = aligner.align("AAACAAA", "AAAGAAA")
44
+
45
+ print(len(alignments))
46
+
47
+ print(alignments[0])
48
+
49
+ print(alignments[0].aligned)
50
+
51
+ print(alignments[1])
52
+
53
+ print(alignments[1].aligned)
54
+
55
+ aligner.mode = "local"
56
+ aligner.open_gap_score = -1
57
+ aligner.extend_gap_score = 0
58
+
59
+ chromosome = "AAAAAAAACCCCCCCAAAAAAAAAAAGGGGGGAAAAAAAA"
60
+ transcript = "CCCCCCCGGGGGG"
61
+
62
+ alignments1 = aligner.align(chromosome, transcript)
63
+
64
+ print(len(alignments1))
65
+
66
+ alignment1 = alignments1[0]
67
+ print(alignment1)
68
+
69
+ sequence = "CCCCGGGG"
70
+
71
+ alignments2 = aligner.align(transcript, sequence)
72
+
73
+ print(len(alignments2))
74
+
75
+ alignment2 = alignments2[0]
76
+ print(alignment2)
77
+
78
+ mapped_alignment = alignment1.map(alignment2)
79
+
80
+ print(mapped_alignment)
81
+
82
+ format(mapped_alignment, "psl")
83
+
84
+ from Bio.Seq import Seq
85
+
86
+ alignment1.target = Seq(None, len(alignment1.target))
87
+ alignment1.query = Seq(None, len(alignment1.query))
88
+
89
+ alignment2.target = Seq(None, len(alignment2.target))
90
+ alignment2.query = Seq(None, len(alignment2.query))
91
+
92
+ mapped_alignment = alignment1.map(alignment2)
93
+
94
+ format(mapped_alignment, "psl")
95
+
96
+ aligner.mode = "local"
97
+
98
+ target = "AGAACTC"
99
+ query = "GAACT"
100
+
101
+ score = aligner.score(target, query)
102
+
103
+ print(score)
104
+
105
+ alignments = aligner.align(target, query)
106
+
107
+ for alignment in alignments:
108
+ print(alignment)
109
+
110
+ from Bio import Align
111
+
112
+ aligner = Align.PairwiseAligner(
113
+ match_score=1.0,
114
+ mode="local"
115
+ )
116
+
117
+ print(aligner.algorithm)
118
+ print(aligner)
119
+
120
+ aligner = Align.PairwiseAligner()
121
+
122
+ print(aligner.match_score)
123
+
124
+ score = aligner.score("ACGT", "ACAT")
125
+ print(score)
126
+
127
+ aligner.match_score = 1.0
128
+ aligner.mismatch_score = -2.0
129
+ aligner.gap_score = -2.5
130
+
131
+ score = aligner.score("ACGT", "ACAT")
132
+
133
+ print(score)
134
+
135
+ import numpy as np
136
+
137
+ def nw(x, y, match=1, mismatch=1, gap=1):
138
+ nx = len(x)
139
+ ny = len(y)
140
+
141
+ F = np.zeros((nx + 1, ny + 1))
142
+ F[:,0] = np.linspace(0, -nx * gap, nx + 1)
143
+ F[0,:] = np.linspace(0, -ny * gap, ny + 1)
144
+
145
+ P = np.zeros((nx + 1, ny + 1))
146
+ P[:,0] = 3
147
+ P[0,:] = 4
148
+
149
+ t = np.zeros(3)
150
+
151
+ for i in range(nx):
152
+ for j in range(ny):
153
+
154
+ if x[i] == y[j]:
155
+ t[0] = F[i,j] + match
156
+ else:
157
+ t[0] = F[i,j] - mismatch
158
+
159
+ t[1] = F[i,j+1] - gap
160
+ t[2] = F[i+1,j] - gap
161
+
162
+ tmax = np.max(t)
163
+ F[i+1,j+1] = tmax
164
+
165
+ if t[0] == tmax:
166
+ P[i+1,j+1] += 2
167
+ if t[1] == tmax:
168
+ P[i+1,j+1] += 3
169
+ if t[2] == tmax:
170
+ P[i+1,j+1] += 4
171
+
172
+ i = nx
173
+ j = ny
174
+
175
+ rx = []
176
+ ry = []
177
+
178
+ while i > 0 or j > 0:
179
+
180
+ if P[i,j] in [2,5,6,9]:
181
+ rx.append(x[i-1])
182
+ ry.append(y[j-1])
183
+ i -= 1
184
+ j -= 1
185
+
186
+ elif P[i,j] in [3,5,7,9]:
187
+ rx.append(x[i-1])
188
+ ry.append('-')
189
+ i -= 1
190
+
191
+ elif P[i,j] in [4,6,7,9]:
192
+ rx.append('-')
193
+ ry.append(y[j-1])
194
+ j -= 1
195
+
196
+ rx = ''.join(rx)[::-1]
197
+ ry = ''.join(ry)[::-1]
198
+
199
+ return '\n'.join([rx, ry])
200
+
201
+ x = "GATTACA"
202
+ y = "GCATGCU"
203
+
204
+ print(nw(x, y))
205
+
206
+ np.random.seed(42)
207
+
208
+ x = np.random.choice(['A','T','G','C'],50)
209
+ y = np.random.choice(['A','T','G','C'],50)
210
+
211
+ print(nw(x, y, gap=0))
212
+
213
+ print(nw(x, y, gap=1))
214
+
215
+ print(nw(x, y, gap=2))
@@ -0,0 +1,77 @@
1
+ def needleman_wunsch_score(seq1, seq2, match=2, mismatch=-1, gap=-2):
2
+ m, n = len(seq1), len(seq2)
3
+
4
+ dp = [[0] * (n + 1) for _ in range(m + 1)]
5
+
6
+ # Initialize first row and column
7
+ for i in range(1, m + 1):
8
+ dp[i][0] = i * gap
9
+
10
+ for j in range(1, n + 1):
11
+ dp[0][j] = j * gap
12
+
13
+ # Fill DP table
14
+ for i in range(1, m + 1):
15
+ for j in range(1, n + 1):
16
+ score = match if seq1[i - 1] == seq2[j - 1] else mismatch
17
+
18
+ dp[i][j] = max(
19
+ dp[i - 1][j - 1] + score,
20
+ dp[i - 1][j] + gap,
21
+ dp[i][j - 1] + gap
22
+ )
23
+
24
+ return dp[m][n], dp
25
+
26
+
27
+ def print_table(dp):
28
+ for row in dp:
29
+ print(row)
30
+
31
+ seq1 = "GAATTC"
32
+ seq2 = "GATAC"
33
+
34
+ score, table = needleman_wunsch_score(seq1, seq2)
35
+
36
+ print("Needleman-Wunsch DP Table:")
37
+ print_table(table)
38
+
39
+ print("\nGlobal Alignment Score:", score)
40
+
41
+ def smith_waterman_score(seq1, seq2, match=2, mismatch=-1, gap=-2):
42
+ m, n = len(seq1), len(seq2)
43
+
44
+ dp = [[0] * (n + 1) for _ in range(m + 1)]
45
+
46
+ max_score = 0
47
+
48
+ # Fill DP table
49
+ for i in range(1, m + 1):
50
+ for j in range(1, n + 1):
51
+
52
+ score = match if seq1[i - 1] == seq2[j - 1] else mismatch
53
+
54
+ dp[i][j] = max(
55
+ 0,
56
+ dp[i - 1][j - 1] + score,
57
+ dp[i - 1][j] + gap,
58
+ dp[i][j - 1] + gap
59
+ )
60
+
61
+ max_score = max(max_score, dp[i][j])
62
+
63
+ return max_score, dp
64
+
65
+ def print_table(dp):
66
+ for row in dp:
67
+ print(row)
68
+
69
+ seq1 = "GAATTC"
70
+ seq2 = "GATAC"
71
+
72
+ score, table = smith_waterman_score(seq1, seq2)
73
+
74
+ print("Smith-Waterman DP Table:")
75
+ print_table(table)
76
+
77
+ print("\nLocal Alignment Score:", score)
@@ -0,0 +1,97 @@
1
+ import pandas as pd
2
+ import numpy as np
3
+
4
+ import matplotlib.pyplot as plt
5
+ from scipy.cluster.hierarchy import linkage, dendrogram
6
+ from scipy.spatial.distance import squareform
7
+
8
+ data = {
9
+ "Human": "ATCGGCTA",
10
+ "Chimp": "ATCGGCTA",
11
+ "Monkey": "ATCGACTA",
12
+ "Mouse": "TTAGACTG"
13
+ }
14
+
15
+ species_names = list(data.keys())
16
+ sequences = list(data.values())
17
+ n = len(species_names)
18
+
19
+ def calculate_metrics(seq1, seq2):
20
+ matches = sum(1 for a, b in zip(seq1, seq2) if a == b)
21
+ total_positions = len(seq1)
22
+ similarity = matches / total_positions
23
+ distance = 1 - similarity
24
+ return similarity * 100, distance
25
+
26
+ similarity_matrix = np.zeros((n, n))
27
+ distance_matrix = np.zeros((n, n))
28
+
29
+ for i in range(n):
30
+ for j in range(n):
31
+ sim, dist = calculate_metrics(sequences[i], sequences[j])
32
+ similarity_matrix[i][j] = sim
33
+ distance_matrix[i][j] = dist
34
+
35
+ df_similarity = pd.DataFrame(similarity_matrix, index=species_names, columns=species_names)
36
+ df_distance = pd.DataFrame(distance_matrix, index=species_names, columns=species_names)
37
+
38
+ print("--- Similarity Matrix (%) ---")
39
+ print(df_similarity)
40
+ print("\n--- Distance Matrix ---")
41
+ print(df_distance)
42
+
43
+ flattened_distances = df_distance.where(np.triu(np.ones(df_distance.shape), k=1).astype(bool)).stack()
44
+ closest_pair = flattened_distances.idxmin()
45
+ min_dist = flattened_distances.min()
46
+
47
+ print(f"Interpretation: The closest pair is {closest_pair} with a distance of {min_dist}.")
48
+ print("Following the workflow, these would be the first to cluster in a phylogenetic tree.")
49
+
50
+ import pandas as pd
51
+ import numpy as np
52
+
53
+ import matplotlib.pyplot as plt
54
+ from scipy.cluster.hierarchy import linkage, dendrogram
55
+ from scipy.spatial.distance import squareform
56
+
57
+ data = {
58
+ "Human": "ATCGGCTA",
59
+ "Chimp": "ATCGGCTA",
60
+ "Monkey": "ATCGACTA",
61
+ "Mouse": "TTAGACTG"
62
+ }
63
+
64
+ species_names = list(data.keys())
65
+ sequences = list(data.values())
66
+ n = len(species_names)
67
+
68
+ def calculate_distance(seq1, seq2):
69
+ matches = sum(1 for a, b in zip(seq1, seq2) if a == b)
70
+ similarity = matches / len(seq1)
71
+ return 1 - similarity
72
+
73
+ dist_matrix = np.zeros((n, n))
74
+ for i in range(n):
75
+ for j in range(n):
76
+ dist_matrix[i][j] = calculate_distance(sequences[i], sequences[j])
77
+
78
+ condensed_dist = squareform(dist_matrix)
79
+
80
+ linked = linkage(condensed_dist, method='average')
81
+
82
+ plt.figure(figsize=(8, 5))
83
+ dendrogram(linked,
84
+ labels=species_names,
85
+ orientation='left',
86
+ distance_sort='descending')
87
+
88
+ plt.title("Phylogenetic Tree (Based on Source Data)")
89
+ plt.xlabel("Evolutionary Distance")
90
+ plt.ylabel("Species")
91
+ plt.grid(axis='x', linestyle='--', alpha=0.7)
92
+ plt.show()
93
+
94
+ print("Tree Iteration Logic:")
95
+ print("1. Cluster 1: Human and Chimp (Distance = 0.0)")
96
+ print("2. Cluster 2: Add Monkey (Distance to Human/Chimp = 0.125)")
97
+ print("3. Cluster 3: Add Mouse (Greatest distance)")