001/*
002 *                    BioJava development code
003 *
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 *
009 *      http://www.gnu.org/copyleft/lesser.html
010 *
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 *
014 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 *
018 *      http://www.biojava.org/
019 *
020 */
021package org.biojava.nbio.aaproperties.xml;
022
023import javax.xml.bind.annotation.XmlAccessType;
024import javax.xml.bind.annotation.XmlAccessorType;
025import javax.xml.bind.annotation.XmlElement;
026import javax.xml.bind.annotation.XmlRootElement;
027import java.util.HashMap;
028import java.util.List;
029import java.util.Map;
030import java.util.Set;
031
032
033@XmlRootElement(name="compoundtable", namespace="http://biojava.org")
034@XmlAccessorType(XmlAccessType.NONE)
035public class AminoAcidCompositionTable {
036
037        /**
038         * Contains the list of amino acid composition
039         */
040        @XmlElement(name = "compound", required = true)
041        private List<AminoAcidComposition> aminoacid;
042
043        /**
044         * Defines the amino acid compound set unique to this table
045         */
046        private ModifiedAminoAcidCompoundSet modifiedAminoAcidCompoundSet;
047
048        /**
049         * Stores the mapping of amino acid symbol to its molecular weight
050         */
051        private Map<Character, Double> aaSymbol2MolecularWeight;
052
053        public AminoAcidCompositionTable(){}
054
055        public AminoAcidCompositionTable(List<AminoAcidComposition> aaList){
056                this.setAminoacid(aaList);
057        }
058
059        public ModifiedAminoAcidCompoundSet getAminoAcidCompoundSet(){
060                return this.modifiedAminoAcidCompoundSet;
061        }
062
063        public List<AminoAcidComposition> getAminoacid() {
064                return aminoacid;
065        }
066
067        public void setAminoacid(List<AminoAcidComposition> aminoacid) {
068                this.aminoacid = aminoacid;
069        }
070
071        public Set<Character> getSymbolSet(){
072                return this.aaSymbol2MolecularWeight.keySet();
073        }
074
075        private void generatesAminoAcidCompoundSet(){
076                this.modifiedAminoAcidCompoundSet = new ModifiedAminoAcidCompoundSet(this.aminoacid, this.aaSymbol2MolecularWeight);
077        }
078
079        /**
080         * Computes and store the molecular weight of each amino acid by its symbol in aaSymbol2MolecularWeight.
081         *
082         * @param eTable
083         *              Stores the mass of elements and isotopes
084         */
085        public void computeMolecularWeight(ElementTable eTable){
086                this.aaSymbol2MolecularWeight = new HashMap<Character, Double>();
087                for(AminoAcidComposition a:aminoacid){
088                        //Check to ensure that the symbol is of single character
089                        if(a.getSymbol().length() != 1){
090                                throw new Error(a.getSymbol() + " is not allowed. Symbols must be single character.\r\nPlease check AminoAcidComposition XML file");
091                        }
092                        //Check to ensure that the symbols are not repeated
093                        char c = a.getSymbol().charAt(0);
094                        if(this.aaSymbol2MolecularWeight.keySet().contains(c)){
095                                throw new Error("Symbol " + c + " is repeated.\r\n" +
096                                                "Please check AminoAcidComposition XML file to ensure there are no repeated symbols. Note that this is case-insensitive.\r\n" +
097                                                "This means that having 'A' and 'a' would be repeating.");
098                        }
099                        double total = 0.0;
100                        if(a.getElementList() != null){
101                                for(Name2Count element:a.getElementList()){
102                                        element.getName();
103                                        if(eTable.getElement(element.getName()) == null){
104                                                throw new Error("Element " + element.getName() + " could not be found. " +
105                                                                "\r\nPlease ensure that its name is correct in AminoAcidComposition.xml and is defined in ElementMass.xml.");
106                                        }
107                                        eTable.getElement(element.getName()).getMass();
108                                        total += eTable.getElement(element.getName()).getMass() * element.getCount();
109                                }
110                        }
111                        if(a.getIsotopeList() != null){
112                                for(Name2Count isotope:a.getIsotopeList()){
113                                        isotope.getName();
114                                        if(eTable.getIsotope(isotope.getName()) == null){
115                                                throw new Error("Isotope " + isotope.getName() + " could not be found. " +
116                                                        "\r\nPlease ensure that its name is correct in AminoAcidComposition.xml and is defined in ElementMass.xml.");
117                                        }
118                                        eTable.getIsotope(isotope.getName()).getMass();
119                                        total += eTable.getIsotope(isotope.getName()).getMass() * isotope.getCount();
120                                }
121                        }
122                        c = a.getSymbol().charAt(0);
123                        this.aaSymbol2MolecularWeight.put(c, total);
124                }
125                generatesAminoAcidCompoundSet();
126        }
127
128        /**
129         * @param aaSymbol
130         *      Standard symbol of Amino Acid
131         * @return the molecular weight given its symbol
132         * @throws NullPointerException
133         *      thrown if AminoAcidCompositionTable.computeMolecularWeight(ElementTable) is not called before this method
134         */
135        public double getMolecularWeight(Character aaSymbol) throws NullPointerException{
136                if(this.aaSymbol2MolecularWeight == null){
137                        throw new NullPointerException("Please call AminoAcidCompositionTable.computeMolecularWeight(ElementTable) before this method");
138                }
139                Double d = this.aaSymbol2MolecularWeight.get(aaSymbol);
140                if(d == null)
141                        return 0;
142                else
143                        return d;
144        }
145}