/*
* 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: 1930 $ by $Author: david@nixbioinf.org $ on $Date:: 2010-07-29 #$
*/
package org.eurocarbdb.application.glycanbuilder;
import java.util.*;
/**
* This utility class is used to generate all possible fragments of a glycan
* molecule.
*
* @author Alessio Ceroni (a.ceroni@imperial.ac.uk)
*/
public class Fragmenter {
protected boolean afragments = true;
protected boolean bfragments = true;
protected boolean cfragments = true;
protected boolean xfragments = true;
protected boolean yfragments = true;
protected boolean zfragments = true;
protected boolean internal_fragments = true;
protected int max_no_cleavages = 2;
protected int max_no_crossrings = 1;
protected boolean small_ring_fragments = true;
/**
* Initialize the fragmenter using the default options.
*/
public Fragmenter() {
}
/**
* Initialize the fragmenter using the given options.
*/
public Fragmenter(FragmentOptions opt) {
if (opt != null) {
afragments = opt.ADD_AFRAGMENTS;
bfragments = opt.ADD_BFRAGMENTS;
cfragments = opt.ADD_CFRAGMENTS;
xfragments = opt.ADD_XFRAGMENTS;
yfragments = opt.ADD_YFRAGMENTS;
zfragments = opt.ADD_ZFRAGMENTS;
internal_fragments = opt.INTERNAL_FRAGMENTS;
max_no_cleavages = opt.MAX_NO_CLEAVAGES;
max_no_crossrings = opt.MAX_NO_CROSSRINGS;
}
}
/**
* Return the compute A-type fragments flag.
*/
public boolean getComputeAFragments() {
return afragments;
}
/**
* Set the compute A-type fragments flag.
*/
public void setComputeAFragments(boolean f) {
afragments = f;
}
/**
* Return the compute B-type fragments flag.
*/
public boolean getComputeBFragments() {
return afragments;
}
/**
* Set the compute B-type fragments flag.
*/
public void setComputeBFragments(boolean f) {
bfragments = f;
}
/**
* Return the compute C-type fragments flag.
*/
public boolean getComputeCFragments() {
return afragments;
}
/**
* Set the compute C-type fragments flag.
*/
public void setComputeCFragments(boolean f) {
cfragments = f;
}
/**
* Return the compute X-type fragments flag.
*/
public boolean getComputeXFragments() {
return afragments;
}
/**
* Set the compute X-type fragments flag.
*/
public void setComputeXFragments(boolean f) {
xfragments = f;
}
/**
* Return the compute Y-type fragments flag.
*/
public boolean getComputeYFragments() {
return yfragments;
}
/**
* Set the compute Y-type fragments flag.
*/
public void setComputeYFragments(boolean f) {
yfragments = f;
}
/**
* Return the compute Z-type fragments flag.
*/
public boolean getComputeZFragments() {
return zfragments;
}
/**
* Set the compute Z-type fragments flag.
*/
public void setComputeZFragments(boolean f) {
zfragments = f;
}
/**
* Return the compute internal fragments flag.
*/
public boolean getComputeInternalFragments() {
return internal_fragments;
}
/**
* Set the compute internal fragments flag.
*/
public void setComputeInternalFragments(boolean f) {
internal_fragments = f;
}
/**
* Return the maximum number of cleavages that this fragmenter will compute
* for each structure
*/
public int getMaxNoCleavages() {
return max_no_cleavages;
}
/**
* Set the maximum number of cleavages that this fragmenter will compute for
* each structure
*/
public void setMaxNoCleavages(int i) {
max_no_cleavages = i;
}
/**
* Return the maximum number of cross-ring fragments that this fragmenter
* will compute for each structure
*/
public int getMaxNoCrossRings() {
return max_no_crossrings;
}
/**
* set the maximum number of cross-ring fragments that this fragmenter will
* compute for each structure
*/
public void setMaxNoCrossRings(int i) {
max_no_crossrings = i;
}
/**
* Return <code>true</code> if this fragmenter will create fragments
* containing no intact saccharides.
*/
public boolean getComputeSmallRingFragments() {
return small_ring_fragments;
}
/**
* Set to <code>true</code> if this fragmenter should create fragments
* containing no intact saccharides.
*/
public void setComputeSmallRingFragments(boolean f) {
small_ring_fragments = f;
}
// profiling
/**
* Generate all possible configuration of labile residues given a set of
* structures.
*
* @see Glycan#detachLabileResidues
* @see Glycan#getAllLabilesConfigurations
*/
static public FragmentDocument generateLabilesConfigurations(
Collection<Glycan> structures) {
FragmentDocument ret = new FragmentDocument();
for (Glycan s : structures) {
FragmentCollection fc = new FragmentCollection();
// prepare labiles
Glycan parent = s.detachLabileResidues().removeDetachedLabiles();
TypePattern labiles = parent.getLabilePositionsPattern();
// remove exchanges from parent mass options
MassOptions mass_opt = s.getMassOptions().removeExchanges();
parent.setMassOptions(mass_opt);
// compute fragments
for (Glycan conf : parent.getAllLabilesConfigurations(labiles))
fc.addFragment(conf, getFragmentType(conf));
// add to document
ret.addFragments(parent, fc);
}
return ret;
}
// ----------------
// Fragments
/**
* Compute all fragments of a given structure resulting from cleaveages at
* the specified residue. Fuzzy structures and structure with repeating
* units cannot be fragmented.
*/
public FragmentCollection computeFragments(Glycan structure, Residue current) {
FragmentCollection fragments = new FragmentCollection();
computeFragments(fragments, structure, current);
return fragments;
}
/**
* Compute all fragments of a given structure resulting from cleavages at
* the specified residue. Fuzzy structures and structure with repeating
* units cannot be fragmented. Return the results in <code>fragments</code>
*/
public void computeFragments(FragmentCollection fragments,
Glycan structure, Residue current) {
if (structure != null && structure.contains(current)
&& !structure.isFuzzy(true) && !structure.hasRepetition()) {
MassOptions mass_opt = structure.getMassOptions().removeExchanges();
// glycosidic cleavages
if (canDoCleavage(current)) {
if (bfragments) {
Glycan b_frag = getBFragment(current, mass_opt);
fragments.addFragment(b_frag, getFragmentType(b_frag));
}
if (cfragments) {
Glycan c_frag = getCFragment(current, mass_opt);
fragments.addFragment(c_frag, getFragmentType(c_frag));
}
if (yfragments) {
Glycan y_frag = getYFragment(current, mass_opt);
fragments.addFragment(y_frag, getFragmentType(y_frag));
}
if (zfragments) {
Glycan z_frag = getZFragment(current, mass_opt);
fragments.addFragment(z_frag, getFragmentType(z_frag));
}
}
// cross ring fragments
if (canDoRingFragment(current)) {
if (afragments) {
for (CrossRingFragmentType crt : CrossRingFragmentDictionary
.getCrossRingFragmentTypesA(current)) {
Glycan a_frag = getAFragment(current, crt, false,
mass_opt);
fragments.addFragment(a_frag, getFragmentType(a_frag));
}
}
if (xfragments) {
for (CrossRingFragmentType crt : CrossRingFragmentDictionary
.getCrossRingFragmentTypesX(current)) {
Glycan x_frag = getXFragment(current, crt, false,
mass_opt);
fragments.addFragment(x_frag, getFragmentType(x_frag));
}
}
}
}
}
/**
* Compute all fragments of a given structure.
*/
public FragmentCollection computeAllFragments(Glycan structure) {
FragmentCollection fragments = new FragmentCollection();
computeAllFragments(fragments, structure);
return fragments;
}
/**
* Compute all fragments of a given structure. Return the results in
* <code>fragments</code>.
*/
public void computeAllFragments(FragmentCollection fragments,
Glycan structure) {
if (structure != null && !structure.isFuzzy(true)
&& !structure.hasRepetition()) {
// remove exchanges from parent mass options
MassOptions mass_opt = structure.getMassOptions().removeExchanges();
Glycan parent = structure.clone();
parent.setMassOptions(mass_opt);
// compute fragments
if (parent.hasLabileResidues()) {
computeAllFragmentsWithLabiles(fragments, parent,
max_no_cleavages, Math.min(max_no_cleavages,
max_no_crossrings), mass_opt);
for (Glycan conf : parent.getAllLabilesConfigurations())
fragments.addFragment(conf, getFragmentType(conf));
} else {
computeAllFragments(fragments, parent.getRoot(),
max_no_cleavages, Math.min(max_no_cleavages,
max_no_crossrings), mass_opt);
fragments.addFragment(parent, getFragmentType(parent));
}
}
}
protected void computeAllFragments(FragmentCollection fragments,
Residue current, int cur_max_no_cleavages,
int cur_max_no_crossrings, MassOptions mass_opt) {
if (cur_max_no_cleavages == 0)
return;
// glycosidic cleavages
if (canDoCleavage(current)) {
if (bfragments) {
Glycan b_frag = getBFragment(current, mass_opt);
if (fragments.addFragment(b_frag, getFragmentType(b_frag)))
computeAllFragments(fragments, b_frag.getRoot(),
cur_max_no_cleavages - 1, cur_max_no_crossrings,
mass_opt);
}
if (cfragments) {
Glycan c_frag = getCFragment(current, mass_opt);
if (fragments.addFragment(c_frag, getFragmentType(c_frag)))
computeAllFragments(fragments, c_frag.getRoot(),
cur_max_no_cleavages - 1, cur_max_no_crossrings,
mass_opt);
}
if (yfragments) {
Glycan y_frag = getYFragment(current, mass_opt);
if (fragments.addFragment(y_frag, getFragmentType(y_frag)))
computeAllFragments(fragments, y_frag.getRoot(),
cur_max_no_cleavages - 1, cur_max_no_crossrings,
mass_opt);
}
if (zfragments) {
Glycan z_frag = getZFragment(current, mass_opt);
if (fragments.addFragment(z_frag, getFragmentType(z_frag)))
computeAllFragments(fragments, z_frag.getRoot(),
cur_max_no_cleavages - 1, cur_max_no_crossrings,
mass_opt);
}
}
// cross ring cleavages
if (cur_max_no_crossrings > 0 && canDoRingFragment(current)) {
if (afragments) {
for (CrossRingFragmentType crt : CrossRingFragmentDictionary
.getCrossRingFragmentTypesA(current)) {
Glycan a_frag = getAFragment(current, crt, false, mass_opt);
if (fragments.addFragment(a_frag, getFragmentType(a_frag)))
computeAllFragments(fragments, a_frag.getRoot(),
cur_max_no_cleavages - 1,
cur_max_no_crossrings - 1, mass_opt);
}
}
if (xfragments) {
for (CrossRingFragmentType crt : CrossRingFragmentDictionary
.getCrossRingFragmentTypesX(current)) {
Glycan x_frag = getXFragment(current, crt, false, mass_opt);
if (fragments.addFragment(x_frag, getFragmentType(x_frag)))
computeAllFragments(fragments, x_frag.getRoot(),
cur_max_no_cleavages - 1,
cur_max_no_crossrings - 1, mass_opt);
}
}
}
// recursion
for (Linkage l : current.getChildrenLinkages())
computeAllFragments(fragments, l.getChildResidue(),
cur_max_no_cleavages, cur_max_no_crossrings, mass_opt);
}
protected void computeAllFragmentsWithLabiles(FragmentCollection fragments,
Glycan structure, int cur_max_no_cleavages,
int cur_max_no_crossrings, MassOptions mass_opt) {
if (cur_max_no_cleavages == 0)
return;
structure = structure.detachLabileResidues();
TypePattern avail_labiles = structure.getDetachedLabilesPattern();
computeAllFragmentsWithLabiles(fragments, structure.getRoot(),
avail_labiles, cur_max_no_cleavages, cur_max_no_crossrings,
mass_opt);
}
protected void computeAllFragmentsWithLabiles(FragmentCollection fragments,
Residue current, TypePattern avail_labiles,
int cur_max_no_cleavages, int cur_max_no_crossrings,
MassOptions mass_opt) {
if (cur_max_no_cleavages == 0)
return;
// glycosidic cleavages
if (canDoCleavage(current)) {
if (bfragments) {
for (Glycan b_frag : Glycan.getAllLabilesConfigurations(
getBFragment(current, mass_opt), avail_labiles)) {
if (fragments.addFragment(b_frag, getFragmentType(b_frag)))
computeAllFragmentsWithLabiles(fragments, b_frag,
cur_max_no_cleavages - 1,
cur_max_no_crossrings, mass_opt);
}
}
if (cfragments) {
for (Glycan c_frag : Glycan.getAllLabilesConfigurations(
getCFragment(current, mass_opt), avail_labiles)) {
if (fragments.addFragment(c_frag, getFragmentType(c_frag)))
computeAllFragmentsWithLabiles(fragments, c_frag,
cur_max_no_cleavages - 1,
cur_max_no_crossrings, mass_opt);
}
}
if (yfragments) {
for (Glycan y_frag : Glycan.getAllLabilesConfigurations(
getYFragment(current, mass_opt), avail_labiles)) {
if (fragments.addFragment(y_frag, getFragmentType(y_frag)))
computeAllFragmentsWithLabiles(fragments, y_frag,
cur_max_no_cleavages - 1,
cur_max_no_crossrings, mass_opt);
}
}
if (zfragments) {
for (Glycan z_frag : Glycan.getAllLabilesConfigurations(
getZFragment(current, mass_opt), avail_labiles)) {
if (fragments.addFragment(z_frag, getFragmentType(z_frag)))
computeAllFragmentsWithLabiles(fragments, z_frag,
cur_max_no_cleavages - 1,
cur_max_no_crossrings, mass_opt);
}
}
}
// cross ring cleavages
if (cur_max_no_crossrings > 0 && canDoRingFragment(current)) {
if (afragments) {
for (CrossRingFragmentType crt : CrossRingFragmentDictionary
.getCrossRingFragmentTypesA(current)) {
for (Glycan a_frag : Glycan.getAllLabilesConfigurations(
getAFragment(current, crt, true, mass_opt),
avail_labiles)) {
if ((!a_frag.isSmallRingFragment() || a_frag
.countCharges() > 0)
&& fragments.addFragment(a_frag,
getFragmentType(a_frag)))
computeAllFragmentsWithLabiles(fragments, a_frag,
cur_max_no_cleavages - 1,
cur_max_no_crossrings - 1, mass_opt);
}
}
}
if (xfragments) {
for (CrossRingFragmentType crt : CrossRingFragmentDictionary
.getCrossRingFragmentTypesX(current)) {
for (Glycan x_frag : Glycan.getAllLabilesConfigurations(
getXFragment(current, crt, true, mass_opt),
avail_labiles)) {
if ((!x_frag.isSmallRingFragment() || x_frag
.countCharges() > 0)
&& fragments.addFragment(x_frag,
getFragmentType(x_frag)))
computeAllFragmentsWithLabiles(fragments, x_frag,
cur_max_no_cleavages - 1,
cur_max_no_crossrings - 1, mass_opt);
}
}
}
}
// recursion
for (Linkage l : current.getChildrenLinkages())
computeAllFragmentsWithLabiles(fragments, l.getChildResidue(),
avail_labiles, cur_max_no_cleavages, cur_max_no_crossrings,
mass_opt);
}
/**
* Return <code>true</code> if the structure can be cleaved at the specified
* residue with a glycosidic cleavage. Fuzzy structures and structure with
* repeating unit cannot be fragmented. If <code>tolerate_labiles</code> is
* <code>true</code> the fragments could be computed even if some labile
* residues have unspeficied connectivity.
*
* @see Glycan#isFuzzy(boolean)
* @see #canDoCleavage(Residue)
*/
static public boolean canDoCleavage(Glycan structure, Residue current,
boolean tolerate_labiles) {
return (structure != null && !structure.isFuzzy(tolerate_labiles)
&& !structure.hasRepetition() && canDoCleavage(current));
}
/**
* Return <code>true</code> if the structure can be cleaved at the specified
* residue with a glycosidic cleavage. Fuzzy structures and structure with
* repeating unit cannot be fragmented.
*
* @see Glycan#isFuzzy
* @see #canDoCleavage(Residue)
*/
static public boolean canDoCleavage(Glycan structure, Residue current) {
return (structure != null && !structure.isFuzzy()
&& !structure.hasRepetition() && canDoCleavage(current));
}
/**
* Return <code>true</code> if a glycosidic-cleavage can be computed at the
* specified residue.
*
* @see Residue#isCleavable
*/
static public boolean canDoCleavage(Residue current) {
return (current != null && current.isCleavable()
&& current.getParent() != null && current.getParent()
.isCleavable());
}
/**
* Return <code>true</code> if the structure can be cleaved at the specified
* residue with a ring cleavage. Fuzzy structures and structure with
* repeating units cannot be fragmented. If <code>tolerate_labiles</code> is
* <code>true</code> the fragments could be computed even if some labile
* residues have unspeficied connectivity.
*
* @see Glycan#isFuzzy(boolean)
* @see #canDoCleavage(Residue)
*/
static public boolean canDoRingFragment(Glycan structure, Residue current,
boolean tolerate_labiles) {
return (structure != null && !structure.isFuzzy(tolerate_labiles)
&& !structure.hasRepetition() && canDoRingFragment(current));
}
/**
* Return <code>true</code> if the structure can be cleaved at the specified
* residue with a ring cleavage. Fuzzy structures and structure with
* repeating units cannot be fragmented.
*
* @see Glycan#isFuzzy
* @see #canDoCleavage(Residue)
*/
static public boolean canDoRingFragment(Glycan structure, Residue current) {
return (structure != null && !structure.isFuzzy()
&& !structure.hasRepetition() && canDoRingFragment(current));
}
/**
* Return <code>true</code> if a ring-cleavage can be computed at the
* specified residue. All linkages with the residue must be valid and fully
* specified.
*
* @see Residue#checkLinkages
*/
static public boolean canDoRingFragment(Residue current) {
return (current != null && current.isSaccharide() && current
.checkLinkages());
}
/**
* Return all possible configurations of labile residues for the A-type
* fragment resulting from the cleavage of the given structure at the
* specified residue.
*
* @param type
* the type of A fragment to be computed
* @see CrossRingFragmentDictionary#getCrossRingFragmentTypesA(Residue)
* @see Glycan getAllLabilesConfigurations
*/
public Collection<Glycan> getAllAFragmentsWithLabiles(Glycan structure,
Residue current, CrossRingFragmentType type) {
if (!canDoRingFragment(structure, current, true))
return new Vector<Glycan>();
structure = structure.detachLabileResidues();
TypePattern avail_labiles = structure.getDetachedLabilesPattern();
Glycan fragment = getAFragment(current, type, false, structure
.getMassOptions().removeExchanges());
if (fragment == null)
return new Vector<Glycan>();
return Glycan.getAllLabilesConfigurations(fragment
.detachLabileResidues(), avail_labiles);
}
/**
* Return all possible configurations of labile residues for the B-type
* fragment resulting from the cleavage of the given structure at the
* specified residue.
*
* @see Glycan getAllLabilesConfigurations
*/
public Collection<Glycan> getAllBFragmentsWithLabiles(Glycan structure,
Residue current) {
if (!canDoCleavage(structure, current, true))
return new Vector<Glycan>();
structure = structure.detachLabileResidues();
TypePattern avail_labiles = structure.getDetachedLabilesPattern();
Glycan fragment = getBFragment(current, structure.getMassOptions()
.removeExchanges());
if (fragment == null)
return new Vector<Glycan>();
return Glycan.getAllLabilesConfigurations(fragment
.detachLabileResidues(), avail_labiles);
}
/**
* Return all possible configurations of labile residues for the C-type
* fragment resulting from the cleavage of the given structure at the
* specified residue.
*
* @see Glycan getAllLabilesConfigurations
*/
public Collection<Glycan> getAllCFragmentsWithLabiles(Glycan structure,
Residue current) {
if (!canDoCleavage(structure, current, true))
return new Vector<Glycan>();
structure = structure.detachLabileResidues();
TypePattern avail_labiles = structure.getDetachedLabilesPattern();
Glycan fragment = getCFragment(current, structure.getMassOptions()
.removeExchanges());
if (fragment == null)
return new Vector<Glycan>();
return Glycan.getAllLabilesConfigurations(fragment
.detachLabileResidues(), avail_labiles);
}
/**
* Return all possible configurations of labile residues for the X-type
* fragment resulting from the cleavage of the given structure at the
* specified residue.
*
* @param type
* the type of X fragment to be computed
* @see CrossRingFragmentDictionary#getCrossRingFragmentTypesX(Residue)
* @see Glycan getAllLabilesConfigurations
*/
public Collection<Glycan> getAllXFragmentsWithLabiles(Glycan structure,
Residue current, CrossRingFragmentType type) {
if (!canDoRingFragment(structure, current, true))
return new Vector<Glycan>();
structure = structure.detachLabileResidues();
TypePattern avail_labiles = structure.getDetachedLabilesPattern();
Glycan fragment = getXFragment(current, type, false, structure
.getMassOptions().removeExchanges());
if (fragment == null)
return new Vector<Glycan>();
return Glycan.getAllLabilesConfigurations(fragment
.detachLabileResidues(), avail_labiles);
}
/**
* Return all possible configurations of labile residues for the Y-type
* fragment resulting from the cleavage of the given structure at the
* specified residue.
*
* @see Glycan getAllLabilesConfigurations
*/
public Collection<Glycan> getAllYFragmentsWithLabiles(Glycan structure,
Residue current) {
if (!canDoCleavage(structure, current, true))
return new Vector<Glycan>();
structure = structure.detachLabileResidues();
TypePattern avail_labiles = structure.getDetachedLabilesPattern();
Glycan fragment = getYFragment(current, structure.getMassOptions()
.removeExchanges());
if (fragment == null)
return new Vector<Glycan>();
return Glycan.getAllLabilesConfigurations(fragment
.detachLabileResidues(), avail_labiles);
}
/**
* Return all possible configurations of labile residues for the Z-type
* fragment resulting from the cleavage of the given structure at the
* specified residue.
*
* @see Glycan getAllLabilesConfigurations
*/
public Collection<Glycan> getAllZFragmentsWithLabiles(Glycan structure,
Residue current) {
if (!canDoCleavage(structure, current, true))
return new Vector<Glycan>();
structure = structure.detachLabileResidues();
TypePattern avail_labiles = structure.getDetachedLabilesPattern();
Glycan fragment = getZFragment(current, structure.getMassOptions()
.removeExchanges());
if (fragment == null)
return new Vector<Glycan>();
return Glycan.getAllLabilesConfigurations(fragment
.detachLabileResidues(), avail_labiles);
}
/**
* Return the A-type fragment resulting from the cleavage of the given
* structure at the specified residue.
*
* @param type
* the type of A fragment to be computed
* @see CrossRingFragmentDictionary#getCrossRingFragmentTypesA(Residue)
*/
public Glycan getAFragment(Glycan structure, Residue current,
CrossRingFragmentType type) {
if (!canDoRingFragment(structure, current))
return null;
return getAFragment(current, type, false, structure.getMassOptions()
.removeExchanges());
}
protected Glycan getAFragment(Residue current, CrossRingFragmentType type,
boolean allow_virtual_charges, MassOptions mass_opt) {
Residue a_root = new Residue(type);
a_root.setCleavedResidue(current.cloneResidue());
// an A fragment must contain no bonds to its parent
if (!internal_fragments
&& type.anyValidPosition(current.getParentLinkage()
.getChildPositions()))
return null;
// check which children are in
for (Linkage l : current.getChildrenLinkages()) {
if (type.areValidPositions(l.getParentPositions()))
a_root.addChild(l.getChildResidue().cloneSubtree(), l
.getBonds());
}
// no ring fragment next to a glycosidic cleavage
if (!internal_fragments && a_root.hasGlycosidicCleavages())
return null;
// a glycan must contain at least one saccharide or a charge (in
// negative mode)
Glycan a_frag = new Glycan(a_root, false, mass_opt);
if ((!a_frag.isSmallRingFragment() && !a_root.hasRingFragments())
|| (small_ring_fragments == true && a_frag
.countCharges(allow_virtual_charges) > 0))
return a_frag;
return null;
}
/**
* Return the B-type fragment resulting from the cleavage of the given
* structure at the specified residue.
*/
public Glycan getBFragment(Glycan structure, Residue current) {
if (!canDoCleavage(structure, current))
return null;
return getBFragment(current, structure.getMassOptions()
.removeExchanges());
}
protected Glycan getBFragment(Residue current, MassOptions mass_opt) {
Residue b_frag = current.cloneSubtree();
Residue b_root = ResidueDictionary.createBCleavage();
b_root.setCleavedResidue(current.getParent().cloneResidue());
b_root.addChild(b_frag, current.getParentLinkage().getBonds());
// a glycan must contain at least one saccharide
if (!b_root.hasSaccharideChildren())
return null;
return new Glycan(b_root, false, mass_opt);
}
/**
* Return the C-type fragment resulting from the cleavage of the given
* structure at the specified residue.
*/
public Glycan getCFragment(Glycan structure, Residue current) {
if (!canDoCleavage(structure, current))
return null;
return getCFragment(current, structure.getMassOptions()
.removeExchanges());
}
protected Glycan getCFragment(Residue current, MassOptions mass_opt) {
Residue c_frag = current.cloneSubtree();
Residue c_root = ResidueDictionary.createCCleavage();
c_root.setCleavedResidue(current.getParent().cloneResidue());
c_root.addChild(c_frag, current.getParentLinkage().getBonds());
// a glycan must contain at least one saccharide
if (!c_root.hasSaccharideChildren())
return null;
return new Glycan(c_root, false, mass_opt);
}
/**
* Return the X-type fragment resulting from the cleavage of the given
* structure at the specified residue.
*
* @param type
* the type of X fragment to be computed
* @see CrossRingFragmentDictionary#getCrossRingFragmentTypesX(Residue)
*/
public Glycan getXFragment(Glycan structure, Residue current,
CrossRingFragmentType type) {
if (!canDoRingFragment(structure, current))
return null;
return getXFragment(current, type, false, structure.getMassOptions()
.removeExchanges());
}
public Glycan getXFragment(Residue current, CrossRingFragmentType type,
boolean allow_virtual_charges, MassOptions mass_opt) {
//
Residue x_leaf = new Residue(type);
x_leaf.setCleavedResidue(current.cloneResidue());
// a X fragment must contain all the bonds to its parent
if (!type.areValidPositions(current.getParentLinkage()
.getChildPositions()))
return null;
// check which children are in
for (Linkage l : current.getChildrenLinkages()) {
if (type.areValidPositions(l.getParentPositions()))
x_leaf.addChild(l.getChildResidue().cloneSubtree(), l
.getBonds());
}
// an X fragment cannot have children (no internal fragments)
if (!internal_fragments && x_leaf.hasSaccharideChildren())
return null;
// create tree structure
Glycan x_frag = new Glycan(current.getTreeRoot().cloneSubtree(current,
x_leaf), false, mass_opt);
// no ring fragment next to a glycosidic cleavage
if (!internal_fragments && x_leaf.hasGlycosidicCleavages())
return null;
// a glycan must contain at least one saccharide or a charge (in
// negative mode)
if ((!x_frag.isSmallRingFragment() && !x_leaf.hasRingFragments())
|| (small_ring_fragments == true && x_frag
.countCharges(allow_virtual_charges) > 0))
return x_frag;
return null;
}
/**
* Return the Y-type fragment resulting from the cleavage of the given
* structure at the specified residue.
*/
public Glycan getYFragment(Glycan structure, Residue current) {
if (!canDoCleavage(structure, current))
return null;
return getYFragment(current, structure.getMassOptions()
.removeExchanges());
}
protected Glycan getYFragment(Residue current, MassOptions mass_opt) {
Residue y_leaf = ResidueDictionary.createYCleavage();
y_leaf.setCleavedResidue(current.cloneResidue());
Glycan ret = new Glycan(current.getTreeRoot().cloneSubtree(current,
y_leaf), false, mass_opt);
// a glycan must contain at least one saccharide
if (!y_leaf.getParent().isSaccharide())
return null;
return ret;
}
/**
* Return the Z-type fragment resulting from the cleavage of the given
* structure at the specified residue.
*/
public Glycan getZFragment(Glycan structure, Residue current) {
if (!canDoCleavage(structure, current))
return null;
return getZFragment(current, structure.getMassOptions()
.removeExchanges());
}
protected Glycan getZFragment(Residue current, MassOptions mass_opt) {
Residue z_leaf = ResidueDictionary.createZCleavage();
z_leaf.setCleavedResidue(current.cloneResidue());
Glycan ret = new Glycan(current.getTreeRoot().cloneSubtree(current,
z_leaf), false, mass_opt);
// a glycan must contain at least one saccharide
if (!z_leaf.getParent().isSaccharide())
return null;
return ret;
}
/**
* Return the fragment resulting from the cleavage of the labile residue
* <code>current</code> from the given structure.
*/
public Glycan getLFragment(Glycan structure, Residue current) {
if (!canDoCleavage(structure, current))
return null;
return getLFragment(current, structure.getMassOptions()
.removeExchanges());
}
protected Glycan getLFragment(Residue current, MassOptions mass_opt) {
Residue l_leaf = ResidueDictionary.createLCleavage();
l_leaf.setCleavedResidue(current.cloneResidue());
Glycan ret = new Glycan(current.getTreeRoot().cloneSubtree(current,
l_leaf), false, mass_opt);
// a glycan must contain at least one saccharide
if (!l_leaf.getParent().isSaccharide())
return null;
return ret;
}
/**
* Return a representation of the type of fragment represented by this
* structure as a string formed by the cleavage types. Return the empty
* string if no cleavages are present
*
* @see Residue#getCleavageType
*/
static public String getFragmentType(Glycan structure) {
if (structure == null)
return "";
return getFragmentType(structure.getRoot());
}
static protected String getFragmentType(Residue node) {
if (node == null)
return "";
String type = "";
if (node.isCleavage() && !node.isLCleavage()) {
type += node.getCleavageType();
if (node.isRingFragment())
type += "_{" + node.getCleavedResidue().getTypeName() + "}";
}
for (Linkage l : node.getChildrenLinkages())
type += getFragmentType(l.getChildResidue());
return type;
}
}