Closed ValentijnBroeken closed 5 years ago
Thanks for the nice report, I am convinced that something is weird. I'll try to sort it our asap (there is a chance that it is due to the special way codon harmonization is defined and optimized in dnachisel. It is unclear to me what to do with codon harmonization, see #2 in case you have a comment on the issue).
That's an actual bug and I found it (indices that referred to codon positions were wrongly used as nucleotide positions, so for instance the 8th codon was considered at position 8 in the sequence, instead of ~24). That's why only the first third was considered needing optimization.
I'll do a few more fixes and add tests and push that.
Thank you very much for your quick response! Great you directly managed to find the bug.
Regarding #2: The method doesn't appear to me as codon harmonization, which for each amino acid replaces the most used codon from the original organism by the most used codon of the receiving organism, and the second by the second, etc. That thus depends on the codon usage table from the donor organism as well, and would not (necessarily) map to the exact codon distribution of the species specified. I'd say the current 'harmonized' mode is more a mode mimicking the distribution, so maybe 'distribution' would be a better name.
One way or the other, it's a very useful method to have.
Ok, I am starting to get some clarity on this. In your case, are you after codon harmonization (based on rankings in respective organisms) or codon redistribution (having codon frequencies match)?
I'm mainly interested in the codon redistribution, so the method already implemented.
Ok this is fixed on Github and PyPI. I have also changed the code so that now you have the convenient compare_frequencies
method to check the final result:
from dnachisel import *
protein = "DDDKKKKKK"
sequence = reverse_translate(protein)
harmonization = CodonOptimize(species='b_subtilis', mode='harmonized')
problem = DnaOptimizationProblem(
sequence=sequence,
constraints=[EnforceTranslation()],
objectives=[harmonization]
)
print ('Sequence_before:', sequence)
problem.optimize()
print ('New sequence:', problem.sequence)
comparison = harmonization.compare_frequencies(problem.sequence, text_mode=True)
print (comparison)
Output:
Sequence_before: GACGACGACAAAAAAAAAAAAAAAAAA
New sequence: GACGATGATAAAAAGAAAAAAAAAAAG
K:
total: 6
AAA:
sequence: 0.67
table: 0.7
AAG:
sequence: 0.33
table: 0.3
D:
total: 3
GAC:
sequence: 0.33
table: 0.36
GAT:
sequence: 0.67
table: 0.64
Note that for this particular optimization there is a risk that DnaChisel introduces a bit of codon bias, because it solves left-to-right (which may cause spatial bias) and because reverse_translate
always uses the same codons. to be clear, I am not certain this is the case. In any case I have added an option to randomize the codons when reverse-translating the protein sequence: reverse_translate(sequence, randomize_codons=True)
.
Let me know if that works for you!
Regarding the naming, I am thinking of changing the terms in the future to "rank_harmonize" (match codon ranks in original host and target) and "frequence_harmonize" (the current algorithm). I'll make the necessary version bumps and warnings.
Hey did that work for you, can I close this issue?
My apologies! Hadn't had the chance to run the full comparison with the new method yet. Yes, it works like a charm, thank you very much for the quick help.
I now tested the difference between the reverse_translate
with or without the randomize_codons=True
(which is by itself a very nice function to have). Both seem to work equally fine, without any obvious biases to me. The order in which the optimize_objective
function optimizes the codons (i.e. the locations
list) is namely randomized, so both work equally well. But please keep both functionalities of the reverse_translate
function anyway!
I'll close the issue. Thanks again!
Using the CodonOptimize 'harmonized' functionality, I do not get a codon distribution similar to the one I specified. It seems that the second 2/3s of a sequence are never optimized.
A minimal example:
This sequence encodes DDDKKKKKK and gives as output:
It does well for Aspartic Acid (D), as this has a GAT 0.64 / GAC 0.36 ratio, but for K with a AAA 0.7 / AAG 0.3 ratio, it does nothing at all. This is position dependent, as a sequence encoding KKKDDDDDD does the opposite.
While trying to debug, I printed all variants that were used during exhaustive search for this sequence (line 454 of DnaOptimizationProblem.py) , which are:
This again points to the fact that the later positions are never included in the variants to be analysed.
I'm using the latest version, dnachisel 1.1.
It would be great if you could find out where the problem is and come up with a quick fix, so I can use your library for my thesis. Thank you!