Converting DNA Strands to Amino Acid Chains
Converting DNA Strands to Amino Acid Chains
Introduction
Introduction
DNA is well-known as the “code of life” in all living organisms. It’s a genetic code, made up of a string of molecules. In the process of protein synthesis, DNA is transcribed into mRNA and translated into a chain of amino acids. This chain of amino acids later folds into a protein, which then does the necessary work in living organisms.
I created a function that reads in a template strand of DNA, and then outputs an image of the resulting amino acid chain created. Below is an example of this function used on the DNA strand “GTATACTGGTCATAGCATTGACTGGTCCATGTACTGTACATCGCT”.
In[]:=
DNAtoAminoAcid["GTATACTGGTCATAGCATTGACTGGTCCATGTACTGTACATCGCT"]
,,,,,,,,,,,,
Out[]=
From DNA to Amino Acids
From DNA to Amino Acids
The first step in creating this function was to write code that would translate a DNA strand into the appropriate amino acids. To do this, I first used rules to create the complementary RNA strand for the input DNA, and then split the RNA strand into 3-letter codons. These codons were translated into the matching amino acids based on a rule chart.
However, the directionality of DNA matters as well. The initial DNA template strand is read from 5’ to 3’, meaning the mRNA goes from 3’ to 5’. Since ribosomes scan mRNA from 5’ to 3’, the mRNA strand actually gets reversed when it’s read. I wrote a function to take all this into account, called reader.
reader takes in an input strand of DNA and outputs a list of the corresponding amino acids:
In[]:=
reader[in_String]:= Module[{chart={"UUU""LPhenylalanine","UUC""LPhenylalanine","UUA""LLeucine","UUG""LLeucine","UCU""LSerine","UCC""LSerine","UCA""LSerine","UCG""LSerine","UAU""LTyrosine","UAC""LTyrosine","UAA""STOP","UAG""STOP","UGU""LCysteine","UGC""LCysteine","UGA""STOP","UGG""LTryptophan","CUU""LLeucine","CUC""LLeucine","CUA""LLeucine","CUG""LLeucine","CCU""LProline","CCC""LProline","CCA""LProline","CCG""LProline","CAU""LHistidine","CAC""LHistidine","CAA""LGlutamine","CAG""LGlutamine","CGU""LArginine","CGC""LArginine","CGA""LArginine","CGG""LArginine","AUU""LIsoleucine","AUC""LIsoleucine","AUA""LIsoleucine","AUG""LMethionine","ACU""LThreonine","ACC""LThreonine","ACA""LThreonine","ACG""LThreonine","AAU""LAsparagine","AAC""LAsparagine","AAA""LLysine","AAG""LLysine","AGU""LSerine","AGC""LSerine","AGA""LArginine","AGG""LArginine","GUU""LValine","GUC""LValine","GUA""LValine","GUG""LValine","GCU""LAlanine","GCC""LAlanine","GCA""LAlanine","GCG""LAlanine","GAU""LAsparticAcid","GAC""LAsparticAcid","GAA""LGlutamicAcid","GAG""LGlutamicAcid","GGU""Glycine","GGC""Glycine","GGA""Glycine","GGG""Glycine"}},StringJoin[#," "]&/@((StringJoin[#]&/@Partition[Reverse[Characters[in]/.{"A""U","G""C","T""A","C""G"}],3])/.chart)]
Testing reader on the input template strand of DNA yields the proper amino acids.
In[]:=
reader["AGTCGTAGTACGGATT"]
Out[]=
{LAsparagine ,LProline ,LTyrosine ,LTyrosine ,LAsparticAcid }
However, DNA to amino acid transcription and translation follows certain rules:
◼
there must be a start codon (AUG which codes for methionine)
◼
there must be a stop codon (UGA, UAA, and UAG all code for STOP)
These start and stop codons allow for protein synthesis to occur for the correct portion of the DNA sequence. Therefore, I needed a way to make sure the resulting amino acid chain started with methionine and preferably ended with a stop codon. Since people often don’t include the stop codons, I made this optional— the code will run properly with or without it.
I created two functions, called start and end, to do this. The start function is applied before reader, and it finds the location of the last “CAT” sequence in the DNA strand, which codes for methionine. Specifically, a “CAT” sequence on the template DNA strand is read as “GUA” on the mRNA strand, which is in turn read by the ribosome as “AUG”, the methionine start codon. Since ribosomes scan DNA from 5’ to 3’ (as explained above), the last “CAT” sequence in the DNA strand represents the starting codon/methionine. By doing so, the code ensures that the DNA strand is translated in the proper reading frame. If there is no “CAT” sequence present, start returns “No amino acid chain”.
The end function checks the amino acid sequence from reader and ensures the proper amino acid chain ends either at the end of the input strand or at the presence of a stop codon.
start checks the initial DNA strand to set up the correct reading frame in the presence of a “CAT” sequence:
In[]:=
start[in_String]:=If[Length[Flatten[StringPosition[in,"CAT"]]]!=0,StringTake[in,Last[Flatten[StringPosition[in,"CAT"]]]],"No amino acid chain"]
Running start on an input DNA strand gives:
In[]:=
start["TTGACTACTTCAGGTACATGT"]
Out[]=
TTGACTACTTCAGGTACAT
end returns the proper amino acid chain from reader that ends either at the end or with a STOP codon:
In[]:=
end[ls_List]:= Module[{end=0},If[MemberQ[ls,"STOP "],end=Flatten[Position[ls,"STOP "]][[1]],end=-1];If[end≠-1,StringJoin[ls[[1;;end-1]]],StringJoin[ls[[1;;]]]]]
Running end on an example string on amino acids gives:
In[]:=
end[{"Serine ","Alanine ","Methionine ","Leucine ","STOP ",}]
Out[]=
Serine Alanine Methionine Leucine
Finally, I needed to ensure that the input strand of DNA was a valid input strand, meaning it didn’t contain letters other than A, T, C, and G. The function checker runs this and returns true if it’s invalid and false if it’s valid.
checker ensures that the input DNA strand is valid:
In[]:=
checker[in_String]:= Module[{not={"B","D","E","F","H","I","J","K","L","M","N","O","P","Q","R","S","U","V","W","X","Y","Z"}, temp},temp=MemberQ[not,#]&/@Characters[ToUpperCase[in]];AnyTrue[temp,#True&]]
Testing checker on a valid and invalid DNA strand provides the following results.
In[]:=
checker["ACTAGGG"]checker["AODPUAJE"]
Out[]=
False
Out[]=
True
Finally, I put these four functions together in a cumulative function, convert. This function returns “Incorrect input” if the DNA strand is invalid, and if the DNA strand is valid, it outputs a list of the entities of amino acids. The entity output makes it easier for further visualization.
convert returns a list of amino acids (as entities) or “Invalid input”/”No amino acid chain”:
In[]:=
convert[in_String]:= Which[checker[in],"Incorrect input",start[ToUpperCase[in]]=="No amino acid chain","No amino acid chain",True,Entity["Chemical",#]&/@StringSplit[end[reader[start[ToUpperCase[in]]]]," "]]
Running this function on the input DNA strand “TACATTCTTTCGTCCGGTATACATT” returns the appropriate chain of amino acids.
In[]:=
convert["TACATTCTTTCGTCCGGTATACATT"]
Out[]=
,,,,,,,
From Amino Acids to Visualizations
From Amino Acids to Visualizations
convert creates the correct list of amino acids, which is excellent, but I took it a step further. The Wolfram Function Repository has a function called BioSequenceMoleculePlot. Using this resource function on the input list creates a lovely illustration of what the amino acid chain looks like. As such, I created another function visualization, that visualizes the output amino acid chain.
visualization returns an image of the amino acid chain using the resource function BioSequenceMoleculePlot:
In[]:=
visualization[ls_List]:= ResourceFunction["BioSequenceMoleculePlot"][BioSequence["Peptide",ls]]
After combining the two functions and adding a few details, I had my final function, DNAtoAminoAcid, which returns the list of amino acids from a strand of DNA and also outputs a visualization of the resulting amino acid chain.
DNAtoAminoAcid outputs a list of amino acids and a visualization of the amino acid chain from a DNA strand:
In[]:=
DNAtoAminoAcid[dna_String]:= Module[{},If[Or[checker[dna],start[ToUpperCase[dna]]=="No amino acid chain"],convert[dna],Print[convert[dna]];visualization[convert[dna]]]]
Running this function on the input DNA strand “TACATTCTTTCGTCCGGTATACATT” returns the following, as desired.
Demonstration
Demonstration
Below, I ran DNAtoAminoAcid on multiple DNA strands to check many cases, including a proper DNA strand, an invalid DNA strand, a strand with no methionine, a strand with and a strand without a STOP codon.
Conclusion
Conclusion
Ultimately, DNAtoAminoAcid is a DNA to amino acid converter, that takes into account start and stop codons, and the validity of a DNA strand. I hope it’ll be a useful tool for many out there!
I also exported this function to the Wolfram cloud, for others to use, at the link https://www.wolframcloud.com/obj/sami.nat975/DNA%20to%20Amino%20Acid%20Converter.
And of course, I thank the Wolfram Student Ambassador Program and its wonderful mentor Zach Shelton!