/*
* 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: 1273 $ by $Author: glycoslave $ on $Date:: 2009-06-26 #$
*/
package test.eurocarbdb.sugar;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;
import org.testng.annotations.*;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.ArrayListMultimap;
import org.eurocarbdb.util.BitSet;
import org.eurocarbdb.sugar.Basetype;
import org.eurocarbdb.sugar.CommonBasetype;
import org.eurocarbdb.sugar.CustomBasetype;
import org.eurocarbdb.sugar.Substituent;
import org.eurocarbdb.sugar.CommonSubstituent;
import test.eurocarbdb.dataaccess.CoreApplicationTest;
import static java.lang.System.out;
import static org.eurocarbdb.sugar.CommonSubstituent.*;
import static org.eurocarbdb.sugar.CommonBasetype.*;
import static org.eurocarbdb.sugar.StereoConfig.*;
import static org.eurocarbdb.sugar.Superclass.*;
import static org.eurocarbdb.util.StringUtils.join;
import static org.eurocarbdb.sugar.Basetypes.describe;
import static org.eurocarbdb.sugar.Basetypes.getBasetype;
import static org.eurocarbdb.sugar.Basetypes.getInvertedBasetype;
import static org.eurocarbdb.sugar.Basetypes.getNormalisedBasetype;
import static org.eurocarbdb.sugar.Basetypes.getStereochemicalId;
import static org.eurocarbdb.sugar.Basetypes.getBasetypeId;
// @Test( groups={"sugar.lib.basetype"}, dependsOnGroups={"util.bitset"} )
@Test( groups={"sugar.lib"} )
public class BasetypeTest extends CoreApplicationTest
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TESTS ~~~~~~~~~~~~~~~~~~~~~~~~~~//
/**
* Dumps the list of {@link CommonBasetype}s.
*/
@Test
public void basetypeInit()
{
out.println("sanity checking all common basetypes");
for ( Basetype b : CommonBasetype.values() )
{
if ( ! b.isDefinite() )
continue;
report( b );
}
}
/**
* Tests creation of {@link Basetype}s using {@link Basetypes#getBasetype}.
*/
@Test( dependsOnMethods={"basetypeInit", "basetypeId", "basetypeStereochemId"} )
public void basetypeCreateComplex()
{
report( getBasetype( L, Glc ) );
report( getBasetype( D, Gly, D, Gal ) );
report( getBasetype( D, Gly, L, Gal ) );
// Basetype b2 = getBasetype( D, Gly, D, Gal, Octose );
// Basetype b3 = getBasetype("d-glc");
}
/**
* Tests complex manipulation of {@link CustomBasetype}s using
* {@link CustomBasetype#setFunctionalGroup}.
*/
@Test( dependsOnMethods={"basetypeCreateComplex", "basetypeId", "basetypeStereochemId"} )
public void basetypeManipulateComplex()
{
CustomBasetype b1 = (CustomBasetype) getBasetype( L, All );
out.println("at start: ");
report( b1 );
assert b1.getSuperclass() == Hexose;
out.println("add 2-deoxy, preserve basetype: ");
b1.setFunctionalGroup( Deoxy, 2, false );
report( b1 );
assert b1.getSuperclass() == Heptose;
out.println("add 4-deoxy, preserve basetype: ");
b1.setFunctionalGroup( Deoxy, 4, false );
report( b1 );
assert b1.getSuperclass() == Octose;
// looking up basetype after changing isn't done yet
/*
CustomBasetype b2 = (CustomBasetype) getBasetype( L, Glc );
out.println("at start: ");
report( b2 );
assert b2.getSuperclass() == Hexose;
out.println("add 2-deoxy, don't preserve basetype: ");
b2.setFunctionalGroup( Deoxy, 2 );
report( b2 );
assert b2.getSuperclass() == Hexose;
out.println("add 4-deoxy, don't preserve basetype: ");
b2.setFunctionalGroup( Deoxy, 4 );
report( b2 );
assert b2.getSuperclass() == Hexose;
*/
}
static final String[] bts = new String[] {
"d-Glc",
"D-Glc",
"l-Glc",
"L-Glc",
"d-glc-l-glc",
"l-ery-l-gal",
"d-ery-l-gal",
"l-ery-d-gal",
"l-all-l-all",
"d-all-l-all",
"l-all-d-all",
"l-glc;2-deoxy",
// "D-Glc,2-NAc",
// "d-Gly-l-Glc|2-deoxy-2-keto",
};
static final String[] incorrect_bts = new String[] {
"d-Glcc",
"l-Glc-d"
};
/** Is going to be moved */
@Test( enabled=false )
public void basetypeParse()
{
for ( String name : bts )
{
out.println();
out.println("attempting to parse name '" + name + "':" );
report( getBasetype( name ) );
}
}
/** Is going to be moved */
@Test( enabled=false )
public void basetypeParse2()
{
for ( String name : incorrect_bts )
{
try
{
out.println();
out.println("attempting to parse (incorrect) name '" + name + "':" );
Basetype b = getBasetype( name );
assert false : "Expected exception, but parsed OK";
}
catch ( Exception ex )
{
out.println("name correctly threw " + ex );
}
}
}
/**
* Tests/Lists IDs for basetypes that are dependent on basetype
* stereochemistry *and* the positions of chiral centres, but not dependent
* on functiional groups.
*/
@Test( dependsOnMethods={"basetypeInit"} )
public void basetypeId()
{
out.println("calculating basetype IDs (stereochem + chiral positions + superclass)" );
out.println();
// Map<Integer,Basetype> bts = new HashMap<Integer,Basetype>();
ListMultimap<Integer,Basetype> bts = ArrayListMultimap.create();
for ( CommonBasetype b : CommonBasetype.values() )
{
if ( b.getStereochemistry() == null )
continue;
int id = getBasetypeId( b );
addToMap( bts, id, b );
// skip unknown basetype
if ( id == 0 )
continue;
Basetype inverted = getInvertedBasetype( b );
id = getBasetypeId( inverted );
addToMap( bts, id, inverted );
}
List<Integer> ids = new ArrayList<Integer>( bts.keySet() );
java.util.Collections.sort( ids );
for ( Integer id : ids )
{
// Basetype b = bts.get( id );
List<Basetype> list = bts.get( id );
// out.println( "name=" + b + ", id=" + id );
out.println( "id=" + id + ", basetypes=" + list );
}
}
/**
* Tests/Lists IDs for basetypes that are dependent solely on basetype
* stereochemistry independent of *where* those stereochemical positions
* are, and what functional groups are involved.
*/
@Test( dependsOnMethods={"basetypeInit"} )
public void basetypeStereochemId()
{
out.println("calculating basetype stereochem IDs (stereochem only)" );
out.println();
// Map<Integer,Basetype> bts = new HashMap<Integer,Basetype>();
ListMultimap<Integer,Basetype> bts = ArrayListMultimap.create();
for ( CommonBasetype b : CommonBasetype.values() )
{
if ( b.getStereochemistry() == null )
continue;
// out.println("processing: " + b );
int id = getStereochemicalId( b );
addToMap( bts, id, b );
// skip unknown basetype
if ( id == 0 )
continue;
Basetype inverted = getInvertedBasetype( b );
id = getStereochemicalId( inverted );
addToMap( bts, id, inverted );
}
List<Integer> ids = new ArrayList<Integer>( bts.keySet() );
java.util.Collections.sort( ids );
for ( Integer id : ids )
{
// Basetype b = bts.get( id );
List<Basetype> list = bts.get( id );
// out.println( "name=" + b + ", id=" + id );
out.println( "id=" + id + ", basetypes=" + list );
}
}
/**
* Tests {@link Basetypes#getNormalisedBasetype}: checks that
* basetypes + substituents that cause loss or gain of stereogenic
* positions are handled correctly, in this case, by preserving basetype
* stereochemistry and changing the {@link Superclass}.
*/
@Test( dependsOnMethods={"basetypeManipulateComplex"} )
public void basetypeNormalise_checkSuperclassNormalisation()
{
Basetype basetype;
List<CommonSubstituent> substits;
// 1-Deoxy-Glc
out.println("::::::::: test 1 :::::::::");
substits = Arrays.asList( Deoxy, null, null, null, null, null );
basetype = normaliseAndReport( Glc, substits );
assert basetype == Glc;
// 2-Deoxy-Glc
out.println("::::::::: test 2 :::::::::");
substits = Arrays.asList( null, Deoxy, null, null, null, null );
basetype = normaliseAndReport( Glc, substits );
assert basetype != Glc;
assert basetype.getSuperclass() == Heptose;
// 6-Deoxy-Glc
out.println("::::::::: test 3 :::::::::");
substits = Arrays.asList( null, null, null, null, null, Deoxy );
basetype = normaliseAndReport( Glc, substits );
assert basetype == Glc;
// 6x Deoxy to Glc
out.println("::::::::: test 4 :::::::::");
substits = Arrays.asList( Deoxy, Deoxy, Deoxy, Deoxy, Deoxy, Deoxy );
basetype = normaliseAndReport( Glc, substits );
assert basetype != Glc;
assert basetype.getSuperclass() == Undecose;
// 2-Deoxy-Fru
out.println("::::::::: test 5 :::::::::");
substits = Arrays.asList( null, Deoxy, null, null, null, null );
basetype = normaliseAndReport( Fru, substits );
// 2-keto-Glc
out.println("::::::::: test 6 :::::::::");
substits = Arrays.asList( null, Carbonyl, null, null, null, null );
basetype = normaliseAndReport( Glc, substits );
assert basetype != Glc;
assert basetype.getSuperclass() == Heptose;
// 1-deoxy-2-keto-Glc
out.println("::::::::: test 7 :::::::::");
substits = Arrays.asList( Deoxy, Carbonyl, null, null, null, null );
basetype = normaliseAndReport( Glc, substits );
assert basetype != Glc;
assert basetype.getSuperclass() == Heptose;
}
/**
* Tests {@link Basetypes#getNormalisedBasetype}: checks that
* basetypes + substituents that match a pre-defined {@link CommonBasetype}
* will return that CommonBasetype.
*/
@Test( dependsOnMethods={"basetypeManipulateComplex"} )
public void basetypeNormalise_checkNormalisationToCommonBasetypes()
{
Basetype basetype;
List<CommonSubstituent> substits;
// Glc -> GlcNAc
out.println("::::::::: test 1 :::::::::");
substits = Arrays.asList( null, NAc, null, null, null, null );
basetype = normaliseAndReport( Glc, substits );
assert basetype == GlcNAc;
// Glc -> GlcN
out.println("::::::::: test 2 :::::::::");
substits = Arrays.asList( null, NH2, null, null, null, null );
basetype = normaliseAndReport( Glc, substits );
assert basetype == GlcN;
// Gal -> GalNAc
out.println("::::::::: test 3 :::::::::");
substits = Arrays.asList( null, NAc, null, null, null, null );
basetype = normaliseAndReport( Gal, substits );
assert basetype == GalNAc;
// NeuAc-related tests
Basetype neuac = getBasetype( D, Gly, D, Gal );
// not quite NeuAc
out.println("::::::::: test 4 :::::::::");
substits = Arrays.asList( Carboxyl, Carbonyl, Deoxy, null, null, null );
basetype = normaliseAndReport( neuac, substits );
assert basetype != NeuAc;
// really NeuAc
out.println("::::::::: test 5 :::::::::");
substits = Arrays.asList( Carboxyl, Carbonyl, Deoxy, null, NAc, null );
basetype = normaliseAndReport( neuac, substits );
assert basetype == NeuAc;
// Man -> Rha
out.println("::::::::: test 6 :::::::::");
substits = Arrays.asList( null, null, null, null, null, Deoxy );
basetype = normaliseAndReport( Man, substits );
assert basetype == Rha;
// Gal -> Fuc
out.println("::::::::: test 6 :::::::::");
substits = Arrays.asList( null, null, null, null, null, Deoxy );
basetype = normaliseAndReport( getInvertedBasetype( Gal ), substits );
assert basetype == Fuc;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~ PRIVATE METHODS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
final Basetype normaliseAndReport( Basetype basetype, List<CommonSubstituent> substits )
{
out.print( "basetype before normalisation: " );
report( basetype );
out.print( "substits to consider: " );
out.println( substits );
out.println();
Basetype normalised = getNormalisedBasetype(
basetype, new ArrayList<Substituent>( substits ) );
out.println();
out.print( "basetype after normalisation: " );
report( normalised );
out.print( "substits remaining: " );
out.println( substits );
out.println();
return normalised;
}
final void addToMap( ListMultimap<Integer,Basetype> bts, int id, Basetype b )
{
bts.put( id, b );
}
final void report( Basetype b )
{
out.println( describe( b ) );
}
}