001/*
002 $Id: ObservedModification.java 4512 2013-08-15 15:14:34Z fredrik $
003
004 */
005package org.proteios.core;
006
007import org.proteios.core.SearchModification.TerminalSpecificity;
008import org.proteios.core.data.ObservedModificationData;
009
010import java.util.ArrayList;
011import java.util.List;
012import java.util.Set;
013
014/**
015 * This class represent observedModifications.
016 * 
017 * @author Fredrik
018 * @version 2.0
019 */
020public class ObservedModification
021                extends Modification<ObservedModificationData>
022{
023        /**
024         * The type of item represented by this class.
025         * 
026         * @see Item#PROTEIOS_OBSERVEDMODIFICATION
027         * @see #getType()
028         */
029        public static final Item TYPE = Item.PROTEIOS_OBSERVEDMODIFICATION;
030
031
032        /**
033         * Get an <code>ObservedModification</code> item when you know the id.
034         * 
035         * @param dc The <code>DbControl</code> which will be used for permission
036         *        checking and database access.
037         * @param id The id of the item to load
038         * @return The <code>ObservedModification</code> item
039         * @throws ItemNotFoundException If an item with the specified id is not
040         *         found
041         * @throws PermissionDeniedException If the logged in observed doesn't have
042         *         read permission to the item
043         * @throws BaseException If there is another error
044         */
045        public static ObservedModification getById(DbControl dc, int id)
046                        throws ItemNotFoundException, PermissionDeniedException,
047                        BaseException
048        {
049                ObservedModification bs = dc.loadItem(ObservedModification.class, id);
050                if (bs == null)
051                        throw new ItemNotFoundException(
052                                "ObservedModification[id=" + id + "]");
053                return bs;
054        }
055
056
057        /**
058         * Get a query that returns observedModification items.
059         * 
060         * @return An {@link ItemQuery} object.
061         */
062        public static ItemQuery<ObservedModification> getQuery()
063        {
064                return new ItemQuery<ObservedModification>(ObservedModification.class);
065        }
066
067
068        ObservedModification(ObservedModificationData observedModificationData)
069        {
070                super(observedModificationData);
071        }
072
073
074        /*
075         * From the Identifiable interface
076         * -------------------------------------------
077         */
078        public Item getType()
079        {
080                return TYPE;
081        }
082
083
084        // -------------------------------------------
085        /**
086         * Always null.
087         */
088        public Set<Annotatable> getAnnotatableParents()
089                        throws BaseException
090        {
091                return null;
092        }
093
094
095        /*
096         * From the BasicItem class -------------------------------------------
097         */
098        /**
099         * Check that:
100         * <ul>
101         * <li>no {@link Sample} has been created from this observedModification
102         * </ul>
103         */
104        @Override
105        public boolean isUsed()
106                        throws BaseException
107        {
108                return false;
109        }
110
111
112        /**
113         * @return Returns the modifiedAminoAcid.
114         */
115        public char getModifiedAminoAcid()
116        {
117                return getData().getModifiedAminoAcid();
118        }
119
120
121        /**
122         * @param modifiedAminoAcid The modifiedAminoAcid to set.
123         */
124        public void setModifiedAminoAcid(char modifiedAminoAcid)
125        {
126                getData().setModifiedAminoAcid(modifiedAminoAcid);
127        }
128
129
130        /**
131         * This function will process a string formatted as a peptide hit
132         * description and return the modifications in the peptide sequence. It will
133         * return both variable and fixed modifications. They will be be formated as
134         * PSI mods. Returned modification positions start at 1.
135         */
136        public static List<ObservedModification> getPsiModList(String description,
137                        List<SearchModification> fixedMods, ItemFactory factory)
138        {
139                List<ObservedModification> retVal = getModList(description, fixedMods,
140                        factory);
141                for (ObservedModification om : retVal)
142                {
143                        toPsiMod(om);
144                }
145                return retVal;
146        }
147
148
149        /**
150         * This function will process a string formatted as a peptide hit
151         * description and return the modifications in the peptide sequence. It will
152         * return both variable and fixed modifications. Note that returned
153         * modification positions start at 0.
154         */
155        public static List<ObservedModification> getModList(String description,
156                        List<SearchModification> fixedMods, ItemFactory factory)
157        {
158                if (description == null)
159                        return new ArrayList<ObservedModification>();
160                if (!description.contains(" "))
161                {
162                        return getModList(description, null, fixedMods, factory);
163                }
164                String[] s = description.split(" ", 2);
165                return getModList(s[0], s[1], fixedMods, factory);
166        }
167
168
169        /**
170         * This function will process a peptide sequence and a string formatted as
171         * the rest of a peptide hit description and return the modifications in the
172         * peptide sequence. It will return both variable and fixed modifications.
173         * Note that returned modification positions start at 0.
174         * 
175         * @param sequence The peptide sequence
176         * @param modString The peptide modification string
177         * @param fixedMods The possible modifications
178         */
179        public static List<ObservedModification> getModList(String sequence,
180                        String modString, List<SearchModification> fixedMods,
181                        ItemFactory factory)
182        {
183                List<ObservedModification> mods = new ArrayList<ObservedModification>();
184                // First check for fixed mods
185                for (SearchModification sm : fixedMods)
186                {
187                        if (sm.getAminoAcidSpecificity() != null)
188                        {
189                                char[] specs = sm.getAminoAcidSpecificity().toCharArray();
190                                for (char c : specs)
191                                {
192                                        int fromIndex = 0;
193                                        int pos = -1;
194                                        while ((pos = sequence.indexOf(c, fromIndex)) != -1)
195                                        {
196                                                ObservedModification om = factory
197                                                        .create(ObservedModification.class);
198                                                om.setModifiedAminoAcid(c);
199                                                om.setMonoisotopicDeltaMass(sm
200                                                        .getMonoisotopicDeltaMass());
201                                                om.setName(sm.getName());
202                                                om.setDiffFormula(sm.getDiffFormula());
203                                                om.setPosition(pos);
204                                                fromIndex = pos + 1;
205                                                mods.add(om);
206                                        }
207                                }
208                        }
209                        else if (sm.getTerminalSpecificity().equals(
210                                TerminalSpecificity.peptide_N_terminus))
211                        {
212                                ObservedModification om = factory
213                                        .create(ObservedModification.class);
214                                om.setModifiedAminoAcid(sequence.charAt(0));
215                                om.setMonoisotopicDeltaMass(sm.getMonoisotopicDeltaMass());
216                                om.setName(sm.getName());
217                                om.setDiffFormula(sm.getDiffFormula());
218                                om.setPosition(0);
219                                mods.add(om);
220                        }
221                        else if (sm.getTerminalSpecificity().equals(
222                                TerminalSpecificity.peptide_C_terminus))
223                        {
224                                ObservedModification om = factory
225                                        .create(ObservedModification.class);
226                                om.setModifiedAminoAcid(sequence.charAt(sequence.length() - 1));
227                                om.setMonoisotopicDeltaMass(sm.getMonoisotopicDeltaMass());
228                                om.setName(sm.getName());
229                                om.setDiffFormula(sm.getDiffFormula());
230                                om.setPosition(sequence.length() - 1);
231                                mods.add(om);
232                        }
233                }
234                // And then the variable ones
235                if (modString != null && modString.length() > 1)
236                {
237                        String[] parts = modString.split(" ");
238                        if (modString.contains(" @"))
239                        {
240                                // Mascot
241                                for (int i = 0; i < parts.length; i++)
242                                {
243                                        if (parts[i].startsWith("@"))
244                                        {
245                                                char[] modPos = parts[i].substring(3,
246                                                        parts[i].length() - 2).toCharArray();
247                                                for (int j = 0; j < modPos.length; j++)
248                                                {
249                                                        if (modPos[j] != '0')
250                                                        {
251                                                                ObservedModification om = factory
252                                                                        .create(ObservedModification.class);
253                                                                om.setPosition(j);
254                                                                om.setModifiedAminoAcid(sequence.charAt(j));
255                                                                for (int k = 1; k < i; k++)
256                                                                {
257                                                                        if (parts[k].startsWith("(") && parts[k]
258                                                                                .indexOf(om.getModifiedAminoAcid()) > -1)
259                                                                        {
260                                                                                om.setName(parts[k - 1]);
261                                                                        }
262                                                                }
263                                                                mods.add(om);
264                                                        }
265                                                }
266                                        }
267                                }
268                        }
269                        else
270                        {
271                                // X!Tandem
272                                for (int i = 0; i < parts.length; i++)
273                                {
274                                        if (parts[i].contains("@"))
275                                        {
276                                                ObservedModification om = factory
277                                                        .create(ObservedModification.class);
278                                                om.setName(getModNameFromTandem(parts[i]));
279                                                om.setMonoisotopicDeltaMass(Double.parseDouble(parts[i]
280                                                        .substring(0, parts[i].indexOf("@"))));
281                                                String pos = parts[i]
282                                                        .substring(parts[i].indexOf("@") + 2);
283                                                om.setModifiedAminoAcid(parts[i].charAt(parts[i]
284                                                        .indexOf("@") + 1));
285                                                if (!pos.equals(""))
286                                                {
287                                                        om.setPosition(Integer.parseInt(pos) - 1);
288                                                }
289                                                else
290                                                {
291                                                        om.setPosition(sequence.indexOf(om
292                                                                .getModifiedAminoAcid()));
293                                                }
294                                                mods.add(om);
295                                        }
296                                }
297                        }
298                }
299                return mods;
300        }
301
302}