/* * EuroCarbDB, a framework for carbohydrate bioinformatics * * Copyright (c) 2006-2009, Eurocarb project, or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU * Lesser General Public License, as published by the Free Software Foundation. * A copy of this license accompanies this distribution in the file LICENSE.txt. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * Last commit: $Rev: 1210 $ by $Author: glycoslave $ on $Date:: 2009-06-12 #$ */ package org.eurocarbdb.applications.ms.glycopeakfinder.calculation; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import org.eurocarbdb.applications.ms.glycopeakfinder.calculation.storage.AnnotationEntity; import org.eurocarbdb.applications.ms.glycopeakfinder.calculation.storage.CalculationIon; import org.eurocarbdb.applications.ms.glycopeakfinder.calculation.storage.CalculationMolecule; import org.eurocarbdb.applications.ms.glycopeakfinder.calculation.storage.CalculationParameter; import org.eurocarbdb.applications.ms.glycopeakfinder.calculation.storage.CalculationPeak; import org.eurocarbdb.applications.ms.glycopeakfinder.calculation.storage.CalculationDerivatisation; import org.eurocarbdb.applications.ms.glycopeakfinder.calculation.storage.CalculationFragment; import org.eurocarbdb.applications.ms.glycopeakfinder.calculation.storage.PeakAnnotation; import org.eurocarbdb.applications.ms.glycopeakfinder.calculation.storage.ResidueSpecial; import org.eurocarbdb.applications.ms.glycopeakfinder.calculation.storage.Scan; import org.eurocarbdb.applications.ms.glycopeakfinder.calculation.storage.SpectraType; import org.eurocarbdb.applications.ms.glycopeakfinder.calculation.util.ComparatorCalculationPeak; import org.eurocarbdb.applications.ms.glycopeakfinder.calculation.util.ComparatorMolecule; /** * Does the glycopeakfinder calculation * * @author Logan * */ public class GlycoPeakfinder { // calculation internal variables // aus testParameter double m_dNonReducingFragmentAbzug = 0; double m_dMassExchangeIon = 0; double m_dMinResidueMass = 0; double m_dChargeCount = 1; // maxima int m_iMaxChargeCount = 0; int m_iMaxExchangeCount = 0; int m_iMaxFragmentCount = 0; int m_iMaxAnnotationCount = 0; CalculationParameter m_objParameter = null; // variables set by the parameter objects double m_dErgaenzungRed = 0; double m_dErgaenzungNonRed = 0; double m_dMassShift = 0; ArrayList<CalculationDerivatisation> m_aDerivates = null; ArrayList<ResidueSpecial> m_aResidues = null; ArrayList<CalculationIon> m_aIons = null; ArrayList<CalculationIon> m_aExchangeIons = null; ArrayList<CalculationFragment> m_aFragmentsRed = null; ArrayList<CalculationFragment> m_aFragmentsNonRed = null; ArrayList<CalculationMolecule> m_aGain = null; ArrayList<CalculationMolecule> m_aLoss = null; ArrayList<CalculationPeak> m_aPeakListFragmented = new ArrayList<CalculationPeak>(); ArrayList<CalculationPeak> m_aPeakListProfile = new ArrayList<CalculationPeak>(); ArrayList<CalculationPeak> m_aPeakListCalculation = new ArrayList<CalculationPeak>(); boolean[] m_bIons = null; // [0] not used boolean[] m_bFragments = null; // [0] not used boolean[] m_bIonExchange = null; // [0] not used // Annotation PeakAnnotation m_objAnnotation = new PeakAnnotation(); ArrayList<String> m_aGainIDs = new ArrayList<String>(); int m_iMinResidueCount = 0; private boolean m_bLowestDeviation = false; private boolean m_bNegativeResidueMass = false; private double m_dMaxPeakMass = 0; public void setStoreOnlyLowestDeviation(boolean a_b) { this.m_bLowestDeviation = a_b; } public boolean getStoreOnlyLowestDeviation() { return this.m_bLowestDeviation; } /** * Tests the parameter set for the calculation * * @param parameter * @throws ParameterException thrown if error in parameter */ protected void testParameter() throws ParameterException { int t_iMax; Integer t_iNumber; this.m_dMassExchangeIon = this.m_objParameter.getExchangeIonMass(); this.m_dNonReducingFragmentAbzug = this.m_objParameter.getNonReducingDifference(); this.m_dErgaenzungRed = this.m_objParameter.getCompletionRed(); this.m_dErgaenzungNonRed = this.m_objParameter.getCompletionNonRed(); this.m_dMassShift = this.m_objParameter.getMassShift(); this.m_iMaxAnnotationCount = this.m_objParameter.getMaxAnnotationPerPeak(); // Derivatisation this.m_aDerivates = this.m_objParameter.getDerivatisation(); if ( this.m_aDerivates == null ) { throw new ParameterException("Modification at the reducing end must be given."); } if ( this.m_aDerivates.size() == 0 ) { throw new ParameterException("Modification at the reducing end must be given."); } // residues this.m_bNegativeResidueMass = false; CalculationMolecule t_objMolecule; ArrayList<String> t_aID = new ArrayList<String>(); ArrayList<String> t_aResidueID = new ArrayList<String>(); this.m_aResidues = new ArrayList<ResidueSpecial>(); for (Iterator<CalculationMolecule> t_iterResidue = this.m_objParameter.getResidues().iterator(); t_iterResidue.hasNext();) { t_objMolecule = t_iterResidue.next(); if ( t_objMolecule.getMin() < 0 || t_objMolecule.getMax() <= 0 ) { throw new ParameterException("Min and Max of residue " + t_objMolecule.getId() + " must be larger than 0."); } if ( t_objMolecule.getMin() > t_objMolecule.getMax() ) { throw new ParameterException("Min of residue " + t_objMolecule.getId() + " must be larger than Max."); } if ( t_aResidueID.contains(t_objMolecule.getId())) { throw new ParameterException("Duplicated residue id : " + t_objMolecule.getId() + "."); } if ( t_objMolecule.getMass() < 0 ) { this.m_bNegativeResidueMass = true; } t_aResidueID.add(t_objMolecule.getId()); ResidueSpecial t_objRes = new ResidueSpecial(t_objMolecule); t_objRes.m_iCurrent = t_objRes.getMin(); this.m_aResidues.add( t_objRes ); } if ( this.m_aResidues.size() == 0 ) { throw new ParameterException("At least one residue must be set."); } // sort residues by mass ComparatorMolecule t_objComparatorResidue = new ComparatorMolecule(); Collections.sort( this.m_aResidues, t_objComparatorResidue ); // ion CalculationIon t_objIon; t_aID.clear(); for (Iterator<CalculationIon> t_iterIon = this.m_objParameter.getIons().iterator(); t_iterIon.hasNext();) { t_objIon = t_iterIon.next(); if ( t_objIon.getCharge() < 1 ) { throw new ParameterException("Charge of ion " + t_objIon.getId() + "must be greater than 0."); } if ( t_aID.contains(t_objIon.getId())) { throw new ParameterException("Duplicated ion id : " + t_objIon.getId() + "."); } if ( t_objIon.getMass()< -1.5 ) { throw new ParameterException("Mass of ion " + t_objIon.getId() + " must be greater than -1.5."); } t_aID.add(t_objIon.getId()); } this.m_aIons = this.m_objParameter.getIons(); if ( this.m_aIons.size() == 0 ) { throw new ParameterException("At least one ion must be set."); } // ion exchange t_aID.clear(); for (Iterator<CalculationIon> t_iterIon = this.m_objParameter.getIonExchangeIon().iterator(); t_iterIon.hasNext();) { t_objIon = t_iterIon.next(); if ( t_objIon.getCharge() < 1 ) { throw new ParameterException("Charge of ion exchange ion " + t_objIon.getId() + "must be greater than 0."); } if ( t_aID.contains(t_objIon.getId())) { throw new ParameterException("Duplicated ion exchange ion id : " + t_objIon.getId() + "."); } if ( t_objIon.getMass()<= 0 ) { throw new ParameterException("Mass of ion exchange ion " + t_objIon.getId() + " must be greater than 0."); } t_aID.add(t_objIon.getId()); } this.m_aExchangeIons = this.m_objParameter.getIonExchangeIon(); // Multifragmentation if ( this.m_objParameter.getSpectraType() != SpectraType.Profile ) { t_iMax = this.m_objParameter.getMaxFragments(); this.m_iMaxFragmentCount = t_iMax; if ( t_iMax <= 0 ) { throw new ParameterException("Fragmentation level must be set (1-...)."); } this.m_bFragments = new boolean[ t_iMax + 1 ]; for (Iterator<Integer> t_iterFrags = this.m_objParameter.getMultiFragments().iterator(); t_iterFrags.hasNext();) { t_iNumber = t_iterFrags.next(); if ( t_iNumber > 0 ) { this.m_bFragments[t_iNumber] = true; } else { throw new ParameterException("Number of fragmentation must be larger than 0."); } } } // ion state t_iMax = this.m_objParameter.getMaxCharges(); if ( t_iMax <= 0 ) { throw new ParameterException("Charge state must be set (1-...)."); } this.m_iMaxChargeCount = t_iMax; this.m_bIons = new boolean[ t_iMax + 1 ]; for (Iterator<Integer> t_iterIons = this.m_objParameter.getCharges().iterator(); t_iterIons.hasNext();) { t_iNumber = t_iterIons.next(); if ( t_iNumber > 0 ) { this.m_bIons[t_iNumber] = true; } else { throw new ParameterException("Number of charges must be larger than 0."); } } // ion exchange state if ( this.m_aExchangeIons.size() != 0 ) { t_iMax = this.m_objParameter.getMaxIonExchange(); if ( t_iMax <= 0 ) { throw new ParameterException("Number of ion exchanges must be largen than 0."); } this.m_iMaxExchangeCount = t_iMax; this.m_bIonExchange = new boolean[ t_iMax + 1 ]; for (Iterator<Integer> t_iterIons = this.m_objParameter.getIonExchangeCount().iterator(); t_iterIons.hasNext();) { t_iNumber = t_iterIons.next(); if ( t_iNumber > 0 ) { this.m_bIonExchange[t_iNumber] = true; } else { throw new ParameterException("Number of ion exchanges must be larger than 0."); } } } // gain t_aID.clear(); for (Iterator<CalculationMolecule> t_iterGain = this.m_objParameter.getGainMolecules().iterator(); t_iterGain.hasNext();) { t_objMolecule = t_iterGain.next(); if ( t_objMolecule.getMin() < 0 || t_objMolecule.getMax() <= 0 ) { throw new ParameterException("Min and Max of gain molecule " + t_objMolecule.getId() + " must be larger than 0."); } if ( t_objMolecule.getMin() > t_objMolecule.getMax() ) { throw new ParameterException("Min of gain molecule " + t_objMolecule.getId() + " must be larger than Max."); } if ( t_objMolecule.getMass() <= 0 ) { throw new ParameterException("Mass of gain molecule " + t_objMolecule.getId() + " must be larger than 0."); } if ( t_aID.contains(t_objMolecule.getId())) { throw new ParameterException("Duplicated gain molecule id : " + t_objMolecule.getId() + "."); } t_aID.add(t_objMolecule.getId()); } this.m_aGain = this.m_objParameter.getGainMolecules(); // loss t_aID.clear(); for (Iterator<CalculationMolecule> t_iterLoss = this.m_objParameter.getLossMolecules().iterator(); t_iterLoss.hasNext();) { t_objMolecule = t_iterLoss.next(); if ( t_objMolecule.getMin() < 0 || t_objMolecule.getMax() <= 0 ) { throw new ParameterException("Min and Max of loss molecule " + t_objMolecule.getId() + " must be larger than 0."); } if ( t_objMolecule.getMin() > t_objMolecule.getMax() ) { throw new ParameterException("Min of loss molecule " + t_objMolecule.getId() + " must be larger than Max."); } if ( t_objMolecule.getMass() <= 0 ) { throw new ParameterException("Mass of loss molecule " + t_objMolecule.getId() + " must be larger than 0."); } if ( t_aID.contains(t_objMolecule.getId())) { throw new ParameterException("Duplicated loss molecule id : " + t_objMolecule.getId() + "."); } t_aID.add(t_objMolecule.getId()); } this.m_aLoss = this.m_objParameter.getLossMolecules(); // Nonreducing fragment if ( this.m_objParameter.getSpectraType() != SpectraType.Profile ) { CalculationFragment t_objFragment; t_aID.clear(); for (Iterator<CalculationFragment> t_iterFrag = this.m_objParameter.getFragmentsNonRed().iterator(); t_iterFrag.hasNext();) { t_objFragment = t_iterFrag.next(); if ( t_aID.contains(t_objFragment.getId())) { throw new ParameterException("Duplicated fragment id : " + t_objFragment.getId() + "."); } t_aID.add(t_objFragment.getId()); /*if ( t_objFragment.getMass() <= 0 ) { throw new ParameterException("Mass of fragment : " + t_objFragment.getId() + " must be larger than 0."); }*/ if ( t_objFragment.getResidueId() != null ) { if ( !t_aResidueID.contains( t_objFragment.getResidueId() )) { throw new ParameterException("Residue for fragment : " + t_objFragment.getId() + " is not part of the residue list."); } } } this.m_aFragmentsNonRed = this.m_objParameter.getFragmentsNonRed(); // reducing fragment t_aID.clear(); for (Iterator<CalculationFragment> t_iterFrag = this.m_objParameter.getFragmentsRed().iterator(); t_iterFrag.hasNext();) { t_objFragment = t_iterFrag.next(); if ( t_aID.contains(t_objFragment.getId())) { throw new ParameterException("Duplicated fragment id : " + t_objFragment.getId() + "."); } t_aID.add(t_objFragment.getId()); /*if ( t_objFragment.getMass() <= 0 ) { throw new ParameterException("Mass of fragment : " + t_objFragment.getId() + " must be larger than 0."); }*/ if ( t_objFragment.getResidueId() != null ) { if ( !t_aResidueID.contains( t_objFragment.getResidueId() )) { throw new ParameterException("Residue for fragment : " + t_objFragment.getId() + " is not part of the residue list."); } } } this.m_aFragmentsRed = this.m_objParameter.getFragmentsRed(); if ( this.m_aFragmentsNonRed.size() == 0 && this.m_aFragmentsRed.size() == 0 ) { throw new ParameterException("No fragments given."); } } // accuracy if ( this.m_objParameter.getAccuracy() < 0 ) { throw new ParameterException("Accuracy must be larger than 0."); } // create Peaklist this.m_aPeakListFragmented = new ArrayList<CalculationPeak>(); this.m_aPeakListProfile = new ArrayList<CalculationPeak>(); if ( this.m_objParameter.getSpectraType() == SpectraType.Profile ) { if ( this.m_objParameter.getScan().getSubScan().size() > 0 ) { throw new ParameterException("For spectrum type profile no sub scans are allowed."); } this.addScan(this.m_objParameter.getScan(),1); } else if ( this.m_objParameter.getSpectraType() == SpectraType.MS2 ) { if ( this.m_objParameter.getScan().getPrecusorMass() == null ) { throw new ParameterException("For spectrum type ms2 precursor mass has to be set."); } this.addScan(this.m_objParameter.getScan(),2); } else if ( this.m_objParameter.getSpectraType() == SpectraType.Fragmented ) { this.addScan(this.m_objParameter.getScan(),3); } else if ( this.m_objParameter.getSpectraType() == SpectraType.MSxMS ) { this.addScan(this.m_objParameter.getScan(),1); } ComparatorCalculationPeak t_objComparator = new ComparatorCalculationPeak(); Collections.sort( this.m_aPeakListFragmented , t_objComparator ); Collections.sort( this.m_aPeakListProfile , t_objComparator ); if ( this.m_aPeakListFragmented.size() == 0 && this.m_aPeakListProfile.size() == 0 ) { throw new ParameterException("At least one peak must be given."); } // calculate MinResidueMass; this.m_iMinResidueCount = 0; for (Iterator<ResidueSpecial> t_iterResidues = this.m_aResidues.iterator(); t_iterResidues.hasNext();) { ResidueSpecial t_objResidue = t_iterResidues.next(); this.m_dMinResidueMass += t_objResidue.getMin() * t_objResidue.getMass(); t_objResidue.m_iCurrent = t_objResidue.getMin(); this.m_iMinResidueCount += t_objResidue.getMin(); t_objResidue.m_iFragment = 0; } } /** * tests the scan settings * * @param a_objScan * @param a_iLevel */ private void addScan(Scan a_objScan,int a_iLevel) { if ( this.m_objParameter.getAccuracyPpm() ) { for (Iterator<CalculationPeak> t_iterPeaks = a_objScan.getPeaks().iterator(); t_iterPeaks.hasNext();) { CalculationPeak t_objPeak = t_iterPeaks.next(); t_objPeak.setAnnotation(new ArrayList<PeakAnnotation>()); t_objPeak.calculateDeviationPpm( this.m_objParameter.getAccuracy() ); if ( this.m_dMaxPeakMass < t_objPeak.maxMz() ) { this.m_dMaxPeakMass = t_objPeak.maxMz(); } if ( a_iLevel == 1 ) { this.m_aPeakListProfile.add(t_objPeak); } else { if ( a_iLevel == 2 ) { this.m_aPeakListProfile.add(t_objPeak); this.m_aPeakListFragmented.add(t_objPeak); } else { this.m_aPeakListFragmented.add(t_objPeak); } } } } else { for (Iterator<CalculationPeak> t_iterPeaks = a_objScan.getPeaks().iterator(); t_iterPeaks.hasNext();) { CalculationPeak t_objPeak = t_iterPeaks.next(); t_objPeak.setAnnotation(new ArrayList<PeakAnnotation>()); t_objPeak.calculateDeviationU( this.m_objParameter.getAccuracy() ); if ( this.m_dMaxPeakMass < t_objPeak.maxMz() ) { this.m_dMaxPeakMass = t_objPeak.maxMz(); } if ( a_iLevel == 1 ) { this.m_aPeakListProfile.add(t_objPeak); } else { if ( a_iLevel == 2 && t_objPeak.getMz() == a_objScan.getPrecusorMass() ) { this.m_aPeakListProfile.add(t_objPeak); } else { this.m_aPeakListFragmented.add(t_objPeak); } } } } if ( a_objScan.getSubScan() != null ) { for (Iterator<Scan> t_iterSubScan = a_objScan.getSubScan().iterator(); t_iterSubScan.hasNext();) { this.addScan(t_iterSubScan.next(),a_iLevel+1); } } } /** * Do calculate based on a parameter object * * @param a_objParameter * @return * @throws ParameterException */ public CalculationParameter calculate(CalculationParameter a_objParameter) throws ParameterException { // first save and test parameter values this.m_objParameter = a_objParameter; this.testParameter(); this.m_objAnnotation = new PeakAnnotation(); if ( this.m_aPeakListProfile.size() > 0 ) { this.m_aPeakListCalculation = this.m_aPeakListProfile; this.calcDericatisation( this.m_dErgaenzungRed + this.m_dErgaenzungNonRed + this.m_dMassShift ); } if ( this.m_aPeakListFragmented.size() > 0 ) { this.m_aPeakListCalculation = this.m_aPeakListFragmented; this.calcFragmentReducing(this.m_dMassShift); } // post precession of ms2 stuff if ( this.m_objParameter.getSpectraType() == SpectraType.MS2 ) { this.postProcessPreCursor( this.m_objParameter.getScan() ); } else if ( this.m_objParameter.getSpectraType() == SpectraType.MSxMS ) { for (Iterator<Scan> t_iterScans = this.m_objParameter.getScan().getSubScan().iterator(); t_iterScans.hasNext();) { this.postProcessPreCursor( t_iterScans.next() ); } } return this.m_objParameter; } /** * @param scan */ private void postProcessPreCursor(Scan a_objScan) { CalculationPeak t_objPeak; PeakAnnotation t_objAnnotation; HashMap<String,Object> t_aPreCursorAnnotation = new HashMap<String, Object>(); // find precursor for (Iterator<CalculationPeak> t_iterPeak = a_objScan.getPeaks().iterator(); t_iterPeak.hasNext();) { t_objPeak = t_iterPeak.next(); if ( t_objPeak.getMz() == a_objScan.getPrecusorMass() ) { // create list of all precursor annotations for (Iterator<PeakAnnotation> t_iterAnnotation = t_objPeak.getAnnotation().iterator(); t_iterAnnotation.hasNext();) { t_objAnnotation = t_iterAnnotation.next(); if ( t_objAnnotation.profileAnnotation() ) { t_aPreCursorAnnotation.put(this.createCompositionString(t_objAnnotation),null); } } } } ArrayList<PeakAnnotation> t_aDelete; ArrayList<PeakAnnotation> t_aOrgininal; // find all other peaks with profile annotations for (Iterator<CalculationPeak> t_iterPeak = a_objScan.getPeaks().iterator(); t_iterPeak.hasNext();) { t_objPeak = t_iterPeak.next(); t_aDelete = new ArrayList<PeakAnnotation>(); // create list of all precursor annotations for (Iterator<PeakAnnotation> t_iterAnnotation = t_objPeak.getAnnotation().iterator(); t_iterAnnotation.hasNext();) { t_objAnnotation = t_iterAnnotation.next(); if ( t_objAnnotation.profileAnnotation() ) { if ( !t_aPreCursorAnnotation.containsKey(this.createCompositionString(t_objAnnotation) ) ) { // no? ==> delete t_aDelete.add(t_objAnnotation); } } } // delete t_aOrgininal = t_objPeak.getAnnotation(); for (Iterator<PeakAnnotation> t_iterAnno = t_aDelete.iterator(); t_iterAnno.hasNext();) { t_aOrgininal.remove(t_iterAnno.next()); } } } /** * @param annotation * @return */ private String createCompositionString(PeakAnnotation a_objAnnotation) { String t_strResult = ""; AnnotationEntity t_objResidue; ArrayList<String> t_aString = new ArrayList<String>(); for (Iterator<AnnotationEntity> t_iterComposition = a_objAnnotation.getResidues().iterator(); t_iterComposition.hasNext();) { t_objResidue = t_iterComposition.next(); t_aString.add( String.format("%d%s", t_objResidue.getNumber(),t_objResidue.getId())); } Collections.sort(t_aString); for (Iterator<String> t_iterStrings = t_aString.iterator(); t_iterStrings.hasNext();) { t_strResult += t_iterStrings.next(); } return t_strResult; } /** * Adds derivatisation * * @param a_dMass mass */ private void calcDericatisation(double a_dMass) { for (Iterator<CalculationDerivatisation> t_iterDerivate = this.m_aDerivates.iterator(); t_iterDerivate.hasNext();) { CalculationDerivatisation t_objDerivate = t_iterDerivate.next(); this.m_objAnnotation.setDerivatisation(t_objDerivate.getId()); this.calcIon( a_dMass + t_objDerivate.getMass(),0,0,new ArrayList<AnnotationEntity>()); } this.m_objAnnotation.setDerivatisation(null); } /** * Adds reducing fragments * * @param a_dMass mass * @throws ParameterException */ private void calcFragmentReducing(double a_dMass) throws ParameterException { ArrayList<AnnotationEntity> t_aAnnotation = new ArrayList<AnnotationEntity>(); // without A,B,C this.calcFragmentNonReducing( a_dMass, 0 , 0, t_aAnnotation , 0); // with one A,B,C for (int t_iCounter = 0; t_iCounter < this.m_aFragmentsRed.size(); t_iCounter++) { CalculationFragment t_objSetting = this.m_aFragmentsRed.get(t_iCounter); AnnotationEntity t_objAnnotation = new AnnotationEntity(); t_objAnnotation.setId(t_objSetting.getId()); t_objAnnotation.setNumber(1); t_aAnnotation.add(t_objAnnotation); if ( t_objSetting.getResidueId() != null ) { ResidueSpecial t_objResidue = this.findResidue(t_objSetting.getResidueId()); t_objResidue.m_iCurrent++; t_objResidue.m_iFragment++; // only A,B,C this.finishFragments( a_dMass + t_objSetting.getMass(),1,0,t_aAnnotation); // with X,Y,Z this.calcFragmentNonReducing( a_dMass + t_objSetting.getMass(), 0 , 1 , t_aAnnotation ,0); t_objResidue.m_iCurrent--; t_objResidue.m_iFragment--; } else { // only A,B,C this.finishFragments( a_dMass + t_objSetting.getMass(),1,0,t_aAnnotation); // with X,Y,Z this.calcFragmentNonReducing( a_dMass + t_objSetting.getMass(), 0 , 1 , t_aAnnotation ,0); } t_aAnnotation.remove(t_objAnnotation); } } /** * adds non reducing fragments * * @param a_dMass mass * @param a_iPosition position in the list of fragments * @param a_iCount number of fragments * @param a_aAnnotion list of fragment annotations * @param a_iNonReducingCount number non reducing fragments * @throws ParameterException */ private void calcFragmentNonReducing(double a_dMass, int a_iPosition, int a_iCount, ArrayList<AnnotationEntity> a_aAnnotion, int a_iNonReducingCount) throws ParameterException { AnnotationEntity t_objAnnotation = new AnnotationEntity(); if ( a_iCount < this.m_iMaxFragmentCount && a_iPosition < this.m_aFragmentsNonRed.size() ) { double t_dMass = a_dMass; int t_iNonRedFragmentCounter = a_iNonReducingCount; CalculationFragment t_objSetting = this.m_aFragmentsNonRed.get(a_iPosition); // without current this.calcFragmentNonReducing( t_dMass, a_iPosition+1,a_iCount,a_aAnnotion,t_iNonRedFragmentCounter); // with current a_aAnnotion.add(t_objAnnotation); t_objAnnotation.setId(t_objSetting.getId()); if ( t_objSetting.getResidueId() == null ) { for ( int t_iAnzahl = a_iCount+1; t_iAnzahl <= this.m_iMaxFragmentCount; t_iAnzahl++ ) { t_dMass += t_objSetting.getMass(); t_iNonRedFragmentCounter++; t_objAnnotation.setNumber(t_iAnzahl-a_iCount); // recursion this.calcFragmentNonReducing( t_dMass, a_iPosition + 1,t_iAnzahl,a_aAnnotion,t_iNonRedFragmentCounter); // start calculation this.finishFragments(t_dMass,t_iAnzahl,t_iNonRedFragmentCounter,a_aAnnotion); } } else { ResidueSpecial t_objResidue = this.findResidue(t_objSetting.getResidueId()); int t_iStore = t_objResidue.m_iCurrent; int t_iStore2 = t_objResidue.m_iFragment; for ( int t_iAnzahl = a_iCount+1; t_iAnzahl <= this.m_iMaxFragmentCount; t_iAnzahl++ ) { t_dMass += t_objSetting.getMass(); t_iNonRedFragmentCounter++; t_objResidue.m_iCurrent++; t_objResidue.m_iFragment++; t_objAnnotation.setNumber(t_iAnzahl-a_iCount); // recursion this.calcFragmentNonReducing( t_dMass, a_iPosition + 1,t_iAnzahl,a_aAnnotion,t_iNonRedFragmentCounter); // start calculation this.finishFragments(t_dMass,t_iAnzahl,t_iNonRedFragmentCounter,a_aAnnotion); } t_objResidue.m_iCurrent = t_iStore; t_objResidue.m_iFragment = t_iStore2; } a_aAnnotion.remove(t_objAnnotation); } } /** * Finish fragment calculation * * @param a_dMass mass * @param a_iFragmentCount number of fragments * @param a_iNonReducingFragmentCount number of non reducing fragments * @param a_aFragments */ private void finishFragments(double a_dMass, int a_iFragmentCount, int a_iNonReducingFragmentCount, ArrayList<AnnotationEntity> a_aFragments) { if ( a_iFragmentCount > 0 && a_iFragmentCount <= this.m_iMaxFragmentCount ) { if ( this.m_bFragments[a_iFragmentCount] ) { double t_dMass = a_dMass; if ( a_iFragmentCount == a_iNonReducingFragmentCount ) { // only X,Y,Z t_dMass += this.m_dErgaenzungRed; } else if ( a_iNonReducingFragmentCount == 0 ) { t_dMass += this.m_dErgaenzungNonRed; } if ( a_iNonReducingFragmentCount > 0 ) { t_dMass -= (a_iNonReducingFragmentCount - 1 ) * this.m_dNonReducingFragmentAbzug; } this.m_objAnnotation.setFragments(a_aFragments); if ( a_iFragmentCount == a_iNonReducingFragmentCount ) { this.calcDericatisation(t_dMass); } else { this.calcIon(t_dMass,0,0,new ArrayList<AnnotationEntity>()); } this.m_objAnnotation.setFragments(new ArrayList<AnnotationEntity>()); } } } /** * Adds ions * * @param a_dMass mass * @param a_iPosition position in the list of ions * @param a_iCount numver of charges * @param a_aAnnotation list of ion annotations */ private void calcIon(double a_dMass , int a_iPosition , int a_iCount, ArrayList<AnnotationEntity> a_aAnnotation) { if ( a_iCount < this.m_iMaxChargeCount && a_iPosition < this.m_aIons.size() ) { double t_dMass = a_dMass; CalculationIon t_objSetting = this.m_aIons.get(a_iPosition); // without current this.calcIon( t_dMass, a_iPosition+1,a_iCount,a_aAnnotation); // with current AnnotationEntity t_objAnnotation = new AnnotationEntity(); t_objAnnotation.setId(t_objSetting.getId()); a_aAnnotation.add(t_objAnnotation); int t_iAnzahl = a_iCount; int t_iCounter = 0; while ( t_iAnzahl <= this.m_iMaxChargeCount ) { t_iCounter++; t_iAnzahl += t_objSetting.getCharge(); t_dMass += t_objSetting.getMass(); t_objAnnotation.setNumber(t_iCounter); // recursion this.calcIon( t_dMass, a_iPosition + 1,t_iAnzahl,a_aAnnotation); // start calculation this.finishIons(t_dMass,t_iAnzahl,a_aAnnotation); } a_aAnnotation.remove(t_objAnnotation); } } /** * Finish ion annotation * * @param a_dMass mass * @param a_iAnzahl number of charges * @param a_aAnnotation list of ion annotations */ private void finishIons(double a_dMass, int a_iAnzahl, ArrayList<AnnotationEntity> a_aAnnotation) { if ( a_iAnzahl > 0 && a_iAnzahl <= this.m_iMaxChargeCount ) { if ( this.m_bIons[a_iAnzahl] ) { this.m_dChargeCount = a_iAnzahl; this.m_objAnnotation.setIons(a_aAnnotation); // without ion exchange this.startCalcResidue(a_dMass + this.m_dMinResidueMass); // with gain ( + loss ) this.calcGain(a_dMass + this.m_dMinResidueMass,0,new ArrayList<AnnotationEntity>(),new ArrayList<String>()); // without gain but loss this.m_aGainIDs.clear(); this.calcLoss(a_dMass + this.m_dMinResidueMass,0, new ArrayList<AnnotationEntity>()); // with ion exchange this.calcIonExchange(a_dMass,0,0,new ArrayList<AnnotationEntity>()); } } this.m_objAnnotation.setIons(new ArrayList<AnnotationEntity>()); } /** * adds ion exchange * * @param a_dMass mass * @param a_iPosition position in the list of ion exchanges * @param a_iCount number of ion exchanges * @param a_aAnnotation list of ion exchange annotations */ private void calcIonExchange(double a_dMass, int a_iPosition, int a_iCount, ArrayList<AnnotationEntity> a_aAnnotation) { if ( a_iCount < this.m_iMaxExchangeCount && a_iPosition < this.m_aExchangeIons.size() ) { double t_dMass = a_dMass; CalculationIon t_objSetting = this.m_aExchangeIons.get(a_iPosition); // without current this.calcIonExchange( t_dMass, a_iPosition+1,a_iCount,a_aAnnotation); // with current AnnotationEntity t_objAnnotation = new AnnotationEntity(); t_objAnnotation.setId(t_objSetting.getId()); a_aAnnotation.add(t_objAnnotation); for ( int t_iAnzahl = a_iCount+1; t_iAnzahl <= this.m_iMaxExchangeCount; t_iAnzahl++ ) { t_dMass += t_objSetting.getMass(); t_objAnnotation.setNumber( t_iAnzahl - a_iCount ); // recursion this.calcIonExchange( t_dMass, a_iPosition + 1,t_iAnzahl,a_aAnnotation); // start calculation this.finishIonExchange(t_dMass,t_iAnzahl,a_aAnnotation); } a_aAnnotation.remove(t_objAnnotation); } } /** * Finish ion exchange * * @param a_dMass mass * @param a_iAnzahl number of ion exchanges * @param a_aAnnotation list of ion exchange annotations */ private void finishIonExchange(double a_dMass, int a_iAnzahl, ArrayList<AnnotationEntity> a_aAnnotation) { if ( a_iAnzahl > 0 && a_iAnzahl <= this.m_iMaxExchangeCount ) { if ( this.m_bIonExchange[a_iAnzahl] ) { this.m_objAnnotation.setIonExchange(a_aAnnotation); // without gain/loos this.startCalcResidue(a_dMass - (a_iAnzahl * this.m_dMassExchangeIon) + this.m_dMinResidueMass); // with gain this.calcGain(a_dMass - (a_iAnzahl * this.m_dMassExchangeIon) + this.m_dMinResidueMass,0,new ArrayList<AnnotationEntity>(),new ArrayList<String>()); // without gain only loss this.calcLoss(a_dMass - (a_iAnzahl * this.m_dMassExchangeIon) + this.m_dMinResidueMass,0,new ArrayList<AnnotationEntity>()); this.m_objAnnotation.setIonExchange(new ArrayList<AnnotationEntity>()); } } } /** * Adds gain of small molecules * * @param a_dMass mass * @param a_iGainLossPos position in the list of small molecules * @param a_aAnnotation list of gain annotation * @param a_aGainIDs list of the ids of gained molecules */ private void calcGain(double a_dMass, int a_iGainLossPos,ArrayList<AnnotationEntity> a_aAnnotation,ArrayList<String> a_aGainIDs) { if ( a_iGainLossPos < this.m_aGain.size() ) { double t_dMass = a_dMass; CalculationMolecule t_objMolecule = this.m_aGain.get(a_iGainLossPos); // without the current one this.calcGain(t_dMass,a_iGainLossPos+1,a_aAnnotation,a_aGainIDs); // with the current one int t_iMax = t_objMolecule.getMax() + 1; int t_iMin = t_objMolecule.getMin(); if ( t_iMin == 0 ) { t_iMin = 1; } AnnotationEntity t_objAnnotation = new AnnotationEntity(); t_objAnnotation.setId(t_objMolecule.getId()); a_aGainIDs.add(t_objMolecule.getId()); a_aAnnotation.add(t_objAnnotation); for ( int t_iAnzahl = t_iMin ; t_iAnzahl < t_iMax ; t_iAnzahl++) { t_objAnnotation.setNumber(t_iAnzahl); t_dMass = a_dMass + ( t_iAnzahl * t_objMolecule.getMass() ); this.finishGain(t_dMass,a_aAnnotation,a_aGainIDs); // recursion this.calcGain(t_dMass,a_iGainLossPos+1,a_aAnnotation,a_aGainIDs); } a_aGainIDs.remove(t_objMolecule.getId()); a_aAnnotation.remove(t_objAnnotation); } } /** * Finish gain of small molecules * * @param a_dMass mass * @param a_aGain list of gain annotations * @param a_aGainIDs list of the ids of gained molecules */ private void finishGain(double a_dMass,ArrayList<AnnotationEntity> a_aGain,ArrayList<String> a_aGainIDs) { if ( a_aGain.size() > 0 ) { this.m_objAnnotation.setGain(a_aGain); // without loss this.startCalcResidue(a_dMass); // with loss this.m_aGainIDs = a_aGainIDs; this.calcLoss(a_dMass,0,new ArrayList<AnnotationEntity>()); this.m_objAnnotation.setGain(new ArrayList<AnnotationEntity>()); this.m_aGainIDs = new ArrayList<String>(); } } /** * adds loss of small molecules * * @param a_dMass mass * @param a_iGainLossPos position in the list of lost molecules * @param a_aAnnotation list of lost annotations */ private void calcLoss(double a_dMass, int a_iGainLossPos,ArrayList<AnnotationEntity> a_aAnnotation) { if ( a_iGainLossPos < this.m_aLoss.size() ) { double t_dMass = a_dMass; CalculationMolecule t_objMolecule = this.m_aLoss.get(a_iGainLossPos); // without the current one this.calcLoss(t_dMass,a_iGainLossPos+1,a_aAnnotation); if ( !this.m_aGainIDs.contains(t_objMolecule.getId())) { // with the current one int t_iMax = t_objMolecule.getMax() + 1; int t_iMin = t_objMolecule.getMin(); if ( t_iMin == 0 ) { t_iMin = 1; } AnnotationEntity t_objAnnotation = new AnnotationEntity(); t_objAnnotation.setId(t_objMolecule.getId()); a_aAnnotation.add(t_objAnnotation); for ( int t_iAnzahl = t_iMin ; t_iAnzahl < t_iMax ; t_iAnzahl++) { t_objAnnotation.setNumber(t_iAnzahl); t_dMass = a_dMass - ( t_iAnzahl * t_objMolecule.getMass() ); this.finishLoss(t_dMass,a_aAnnotation); // recursion this.calcLoss(t_dMass,a_iGainLossPos+1,a_aAnnotation); } a_aAnnotation.remove(t_objAnnotation); } } } /** * Finish loss of small molecules * * @param a_dMass mass * @param a_aLoss list of lost molecules annotation */ private void finishLoss(double a_dMass,ArrayList<AnnotationEntity> a_aLoss) { if ( a_aLoss.size() > 0 ) { this.m_objAnnotation.setLoss(a_aLoss); this.startCalcResidue(a_dMass); this.m_objAnnotation.setLoss(new ArrayList<AnnotationEntity>()); } } /** * Start residue calculation * * @param a_dMass mass */ private void startCalcResidue(double a_dMass) { if ( this.m_iMinResidueCount > 0 ) { if ( this.m_bNegativeResidueMass ) { this.finishResultWithNegativ(a_dMass,0,-1); } else { this.finishResult(a_dMass,0); } } this.calcResidue(a_dMass, 0, 0); } /** * Adds residues * * @param a_dMass mass * @param a_iPosition position in the list of residues * @param a_iResultPos position in the peaklist */ private void calcResidue(double a_dMass, int a_iPosition, int a_iResultPos) { if ( a_iPosition < this.m_aResidues.size() ) { int t_iPos = a_iResultPos; double t_dMass = a_dMass; ResidueSpecial t_objResidue = this.m_aResidues.get(a_iPosition); int t_iMax = t_objResidue.getMax(); int t_iStore = t_objResidue.m_iCurrent; // without this residue this.calcResidue(t_dMass,a_iPosition+1,t_iPos); // with this residue for (int t_iAnzahl = t_objResidue.m_iCurrent+1; t_iAnzahl <= t_iMax;t_iAnzahl++) { t_objResidue.m_iCurrent++; t_dMass += t_objResidue.getMass(); // test if ( this.m_bNegativeResidueMass ) { t_iPos = this.finishResultWithNegativ(t_dMass,t_iPos,t_objResidue.getMass()); } else { t_iPos = this.finishResult(t_dMass,t_iPos); } if ( t_iPos == -1 ) { // abbruch t_iAnzahl = t_iMax+1; } else { // recursion this.calcResidue(t_dMass,a_iPosition+1,t_iPos); } } t_objResidue.m_iCurrent = t_iStore; } } /** * Test if calculated mass match with a peak and store annotation * * @param a_dMass calculated mass * @param a_iPos position in the peaklist to start * * @return position in the peaklist with the last peak smaller than this mass or -1 if end of list is reached */ private int finishResult(double a_dMass, int a_iPos) { double t_dMassCalculatet = a_dMass / this.m_dChargeCount; int t_iMinima = a_iPos; CalculationPeak t_objPeak; double t_dMinMass; double t_dMaxMass; int t_iPeakCount = this.m_aPeakListCalculation.size(); for (int t_iCounter = t_iMinima; t_iCounter < t_iPeakCount; t_iCounter++ ) { t_objPeak = this.m_aPeakListCalculation.get(t_iCounter); t_dMinMass = t_objPeak.minMz(); if ( t_dMinMass > t_dMassCalculatet ) { // minimal mass of the current residue is larger than the calcultated mass ==> stop criterion t_iCounter = t_iPeakCount; } else { // minimal mass of the current residue is smaller than the calculated mass t_dMaxMass = t_objPeak.maxMz(); if ( t_dMaxMass < t_dMassCalculatet ) { // no need to search for this mass again t_iMinima = t_iCounter+1; } else { // found a result ==> store it if charges match if ( t_objPeak.getCharge() != null ) { if ( t_objPeak.getCharge() == ((int)this.m_dChargeCount) ) { if ( this.m_iMaxAnnotationCount > 0 ) { if ( this.m_iMaxAnnotationCount > t_objPeak.getAnnotationCount() ) { PeakAnnotation t_objAnnotation = this.createAnnotation(t_dMassCalculatet,t_objPeak.getMz()); t_objPeak.addAnnotation(t_objAnnotation); t_objPeak.incrementAnnotationCount(); } else { if ( this.m_bLowestDeviation ) { PeakAnnotation t_objAnnotation = this.createAnnotation(t_dMassCalculatet,t_objPeak.getMz()); this.replaceAnnotation(t_objPeak,t_objAnnotation); } t_objPeak.incrementAnnotationCount(); } } else { PeakAnnotation t_objAnnotation = this.createAnnotation(t_dMassCalculatet,t_objPeak.getMz()); t_objPeak.addAnnotation(t_objAnnotation); t_objPeak.incrementAnnotationCount(); } } } else { if ( this.m_iMaxAnnotationCount > 0 ) { if ( this.m_iMaxAnnotationCount > t_objPeak.getAnnotationCount() ) { PeakAnnotation t_objAnnotation = this.createAnnotation(t_dMassCalculatet,t_objPeak.getMz()); t_objPeak.addAnnotation(t_objAnnotation); t_objPeak.incrementAnnotationCount(); } else { if ( this.m_bLowestDeviation ) { PeakAnnotation t_objAnnotation = this.createAnnotation(t_dMassCalculatet,t_objPeak.getMz()); this.replaceAnnotation(t_objPeak,t_objAnnotation); } t_objPeak.incrementAnnotationCount(); } } else { PeakAnnotation t_objAnnotation = this.createAnnotation(t_dMassCalculatet,t_objPeak.getMz()); t_objPeak.addAnnotation(t_objAnnotation); t_objPeak.incrementAnnotationCount(); } } } } } if ( t_iMinima >= t_iPeakCount ) { return -1; } return t_iMinima; } /** * Test if calculated mass match with a peak and store annotation (methode for calculation with negative mass residues) * * @param a_dMass calculated mass * @param a_iPos position in the peaklist to start * * @return position in the peaklist with the last peak smaller than this mass or -1 if end of list is reached */ private int finishResultWithNegativ(double a_dMass, int a_iPos , double a_dLastResidueMass) { double t_dMassCalculatet = a_dMass / this.m_dChargeCount; CalculationPeak t_objPeak; double t_dMinMass; double t_dMaxMass = 0; for (Iterator<CalculationPeak> t_iterPeak = this.m_aPeakListCalculation.iterator(); t_iterPeak.hasNext();) { t_objPeak = t_iterPeak.next(); t_dMinMass = t_objPeak.minMz(); if ( t_dMinMass <= t_dMassCalculatet ) { // minimal mass of the current residue is smaller than the calculated mass t_dMaxMass = t_objPeak.maxMz(); if ( t_dMaxMass >= t_dMassCalculatet ) { // found a result ==> store it if charges match if ( t_objPeak.getCharge() != null ) { if ( t_objPeak.getCharge() == ((int)this.m_dChargeCount) ) { if ( this.m_iMaxAnnotationCount > 0 ) { if ( this.m_iMaxAnnotationCount > t_objPeak.getAnnotationCount() ) { PeakAnnotation t_objAnnotation = this.createAnnotation(t_dMassCalculatet,t_objPeak.getMz()); t_objPeak.addAnnotation(t_objAnnotation); t_objPeak.incrementAnnotationCount(); } else { if ( this.m_bLowestDeviation ) { PeakAnnotation t_objAnnotation = this.createAnnotation(t_dMassCalculatet,t_objPeak.getMz()); this.replaceAnnotation(t_objPeak,t_objAnnotation); } t_objPeak.incrementAnnotationCount(); } } else { PeakAnnotation t_objAnnotation = this.createAnnotation(t_dMassCalculatet,t_objPeak.getMz()); t_objPeak.addAnnotation(t_objAnnotation); t_objPeak.incrementAnnotationCount(); } } } else { if ( this.m_iMaxAnnotationCount > 0 ) { if ( this.m_iMaxAnnotationCount > t_objPeak.getAnnotationCount() ) { PeakAnnotation t_objAnnotation = this.createAnnotation(t_dMassCalculatet,t_objPeak.getMz()); t_objPeak.addAnnotation(t_objAnnotation); t_objPeak.incrementAnnotationCount(); } else { if ( this.m_bLowestDeviation ) { PeakAnnotation t_objAnnotation = this.createAnnotation(t_dMassCalculatet,t_objPeak.getMz()); this.replaceAnnotation(t_objPeak,t_objAnnotation); } t_objPeak.incrementAnnotationCount(); } } else { PeakAnnotation t_objAnnotation = this.createAnnotation(t_dMassCalculatet,t_objPeak.getMz()); t_objPeak.addAnnotation(t_objAnnotation); t_objPeak.incrementAnnotationCount(); } } } } } if ( this.m_dMaxPeakMass < t_dMassCalculatet && a_dLastResidueMass > 0 ) { return -1; } return 0; } /** * @param peak * @param annotation */ private void replaceAnnotation(CalculationPeak a_objPeak, PeakAnnotation a_objAnnotation) { PeakAnnotation t_objMax = null; PeakAnnotation t_objCurrent = null; for (Iterator<PeakAnnotation> t_iterMax = a_objPeak.getAnnotation().iterator(); t_iterMax.hasNext();) { t_objCurrent = t_iterMax.next(); if ( t_objMax == null ) { t_objMax = t_objCurrent; } else { if ( t_objMax.getDivValue() < t_objCurrent.getDivValue() ) { t_objMax = t_objCurrent; } } } if ( t_objMax != null ) { if ( t_objMax.getDivValue() > a_objAnnotation.getDivValue() ) { a_objPeak.getAnnotation().remove(t_objMax); a_objPeak.addAnnotation(a_objAnnotation); } } } /** * Creates an annotation object * * @param a_dMass * @return */ private PeakAnnotation createAnnotation(double a_dMassCalc,double a_dMassPeak) { PeakAnnotation t_objAnnotation = new PeakAnnotation(); ArrayList<AnnotationEntity> t_aAnnotations; ResidueSpecial t_objResidue; AnnotationEntity t_objEntity; // residue t_aAnnotations = new ArrayList<AnnotationEntity>(); for (Iterator<ResidueSpecial> t_iterResidues = this.m_aResidues.iterator(); t_iterResidues.hasNext();) { t_objResidue = t_iterResidues.next(); if ( (t_objResidue.m_iCurrent - t_objResidue.m_iFragment) != 0 ) { t_objEntity = new AnnotationEntity(); t_objEntity.setId( t_objResidue.getId() ); t_objEntity.setNumber(t_objResidue.m_iCurrent - t_objResidue.m_iFragment); t_aAnnotations.add(t_objEntity); } } t_objAnnotation.setResidues(t_aAnnotations); // fragment t_aAnnotations = new ArrayList<AnnotationEntity>(); for (Iterator<AnnotationEntity> t_iterAnno = this.m_objAnnotation.getFragments().iterator(); t_iterAnno.hasNext();) { t_aAnnotations.add(t_iterAnno.next().copy()); } t_objAnnotation.setFragments(t_aAnnotations); // ions t_aAnnotations = new ArrayList<AnnotationEntity>(); for (Iterator<AnnotationEntity> t_iterAnno = this.m_objAnnotation.getIons().iterator(); t_iterAnno.hasNext();) { t_aAnnotations.add(t_iterAnno.next().copy()); } t_objAnnotation.setIons(t_aAnnotations); // ion exchange t_aAnnotations = new ArrayList<AnnotationEntity>(); for (Iterator<AnnotationEntity> t_iterAnno = this.m_objAnnotation.getIonExchange().iterator(); t_iterAnno.hasNext();) { t_aAnnotations.add(t_iterAnno.next().copy()); } t_objAnnotation.setIonExchange(t_aAnnotations); // derivatisation t_objAnnotation.setDerivatisation( this.m_objAnnotation.getDerivatisation() ); // mass t_objAnnotation.setMass(a_dMassCalc); double t_dValue = ( (a_dMassPeak - a_dMassCalc) * 1000000.0 ) / a_dMassPeak; if ( t_dValue < 0 ) { t_objAnnotation.setDivValue( t_dValue * (-1) ); } else { t_objAnnotation.setDivValue( t_dValue ); } // gain t_aAnnotations = new ArrayList<AnnotationEntity>(); for (Iterator<AnnotationEntity> t_iterAnno = this.m_objAnnotation.getGain().iterator(); t_iterAnno.hasNext();) { t_aAnnotations.add(t_iterAnno.next().copy()); } t_objAnnotation.setGain(t_aAnnotations); // loss t_aAnnotations = new ArrayList<AnnotationEntity>(); for (Iterator<AnnotationEntity> t_iterAnno = this.m_objAnnotation.getLoss().iterator(); t_iterAnno.hasNext();) { t_aAnnotations.add(t_iterAnno.next().copy()); } t_objAnnotation.setLoss(t_aAnnotations); return t_objAnnotation; } /** * Gives the residue object for an id(name) of an residue * * @param a_strResidue * @return * @throws ParameterException */ private ResidueSpecial findResidue(String a_strResidue) throws ParameterException { for (Iterator<ResidueSpecial> t_iterResidue = this.m_aResidues.iterator(); t_iterResidue.hasNext();) { ResidueSpecial t_objRes = t_iterResidue.next(); if ( t_objRes.getId().equals(a_strResidue) ) { return t_objRes; } } throw new ParameterException("Residue " + a_strResidue + " for A/X fragment is missing."); } }