Skip to content
Snippets Groups Projects
Commit 0bc06347 authored by David Hoksza's avatar David Hoksza
Browse files

BRENDA annotator including unit tests.

parent c24ecf7c
No related branches found
No related tags found
1 merge request!201Cellwall annotations
Pipeline #
Showing
with 556 additions and 5 deletions
......@@ -16,6 +16,7 @@ import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import lcsb.mapviewer.annotation.services.annotators.AnnotatorException;
import lcsb.mapviewer.annotation.services.annotators.BrendaAnnotator;
import lcsb.mapviewer.annotation.services.annotators.BiocompendiumAnnotator;
import lcsb.mapviewer.annotation.services.annotators.CazyAnnotator;
import lcsb.mapviewer.annotation.services.annotators.ChebiAnnotator;
......@@ -69,6 +70,12 @@ public class ModelAnnotator {
* Default class logger.
*/
private static Logger logger = Logger.getLogger(ModelAnnotator.class);
/**
* BRENDA annotator.
*/
@Autowired
private BrendaAnnotator brendaAnnotator;
/**
* Service accessing <a href= "http://biocompendium.embl.de/" >internal
......@@ -159,6 +166,7 @@ public class ModelAnnotator {
availableAnnotators = new ArrayList<>();
defaultAnnotators = new ArrayList<>();
addAnnotator(brendaAnnotator);
addAnnotator(biocompendiumAnnotator);
addAnnotator(cazyAnnotator);
addAnnotator(chebiBackend);
......
package lcsb.mapviewer.annotation.services.annotators;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import lcsb.mapviewer.annotation.cache.GeneralCacheInterface;
import lcsb.mapviewer.annotation.cache.SourceNotAvailable;
import lcsb.mapviewer.annotation.cache.WebPageDownloader;
import lcsb.mapviewer.annotation.services.ExternalServiceStatus;
import lcsb.mapviewer.annotation.services.ExternalServiceStatusType;
import lcsb.mapviewer.annotation.services.IExternalService;
import lcsb.mapviewer.annotation.services.WrongResponseCodeIOException;
import lcsb.mapviewer.common.exception.InvalidArgumentException;
import lcsb.mapviewer.model.map.BioEntity;
import lcsb.mapviewer.model.map.MiriamData;
import lcsb.mapviewer.model.map.MiriamType;
import lcsb.mapviewer.model.map.species.Gene;
import lcsb.mapviewer.model.map.species.Protein;
import lcsb.mapviewer.model.map.species.Rna;
/**
* This is a class that implements a backend to Brenda enzyme database.
*
* @author David Hoksza
*
*/
public class BrendaAnnotator extends ElementAnnotator implements IExternalService {
/**
* Default class logger.
*/
private static Logger logger = Logger.getLogger(BrendaAnnotator.class);
/**
* Service used for annotation of entities using {@link MiriamType#TAIR_LOCUS
* TAIR}.
*/
@Autowired
private TairAnnotator tairAnnotator;
/**
* Pattern used for finding UniProt symbol from TAIR info page .
*/
private Pattern uniprotECMatcher = Pattern.compile("EC=((\\d+\\.-\\.-\\.-)|(\\d+\\.\\d+\\.-\\.-)|(\\d+\\.\\d+\\.\\d+\\.-)|(\\d+\\.\\d+\\.\\d+\\.\\d+))");
/**
* Default constructor.
*/
public BrendaAnnotator() {
super(BrendaAnnotator.class, new Class[] { Protein.class, Gene.class, Rna.class }, false);
}
@Override
public ExternalServiceStatus getServiceStatus() {
ExternalServiceStatus status = new ExternalServiceStatus(getCommonName(), getUrl());
GeneralCacheInterface cacheCopy = getCache();
this.setCache(null);
try {
Collection<MiriamData> mds = uniprotToBrenda(new MiriamData(MiriamType.UNIPROT, "P12345"));
status.setStatus(ExternalServiceStatusType.OK);
List<String> ecs = new ArrayList<>();
if (mds != null) {
for (MiriamData md: mds) {
ecs.add(md.getResource());
}
}
if (mds == null || mds.size() != 2 || ecs.indexOf("2.6.1.1") < 0 || ecs.indexOf("2.6.1.7") < 0) {
status.setStatus(ExternalServiceStatusType.CHANGED);
}
} catch (Exception e) {
logger.error(status.getName() + " is down", e);
status.setStatus(ExternalServiceStatusType.DOWN);
}
this.setCache(cacheCopy);
return status;
}
@Override
public void annotateElement(BioEntity object) throws AnnotatorException {
if (isAnnotatable(object)) {
MiriamData mdTair = null;
for (MiriamData md : object.getMiriamData()) {
if (md.getDataType().equals(MiriamType.BRENDA)) {
return;
}
else if (md.getDataType().equals(MiriamType.TAIR_LOCUS)) {
mdTair = md;
}
}
if (mdTair != null) {
tairAnnotator.annotateElement(object);
}
List<MiriamData> mdUniprots = new ArrayList<MiriamData>();
for (MiriamData md : object.getMiriamData()) {
if (md.getDataType().equals(MiriamType.UNIPROT)) {
mdUniprots.add(md);
}
}
List<String> ecIds = new ArrayList<String>();
for (MiriamData mdUniprot: mdUniprots) {
Collection<MiriamData> mdBrendas = uniprotToBrenda(mdUniprot);
if (mdBrendas != null) {
for (MiriamData mdBrenda: mdBrendas) {
if (ecIds.indexOf(mdBrenda.getResource()) == -1) {
ecIds.add(mdBrenda.getResource());
object.addMiriamData(mdBrenda);
}
}
}
}
}
}
/**
* Returns URL to UniProt restfull API about UniProt entry.
*
* @param uniprotId
* UniProt identifier
* @return URL to UniProt restfull API about UniProt entry
*/
private String getUniprotUrl(String uniprotId) {
return "http://www.uniprot.org/uniprot/" + uniprotId + ".txt";
}
/**
* Parse UniProt webpage to find information about
* {@link MiriamType#BRENDA}, i.e. EC, and returns them.
*
* @param pageContent
* UniProt info page
* @return BRENDA family identifier, i.e. EC, found on the page
*/
private Collection<MiriamData> parseUniprot(String pageContent) {
Collection<MiriamData> result = new HashSet<MiriamData>();
Matcher m = uniprotECMatcher.matcher(pageContent);
while (m.find()) {
result.add(new MiriamData(MiriamType.BRENDA, m.group(1)));
}
return result;
}
@Override
public Object refreshCacheQuery(Object query) throws SourceNotAvailable {
String name;
String result = null;
if (query instanceof String) {
name = (String) query;
if (name.startsWith("http")) {
try {
result = getWebPageContent(name);
} catch (IOException e) {
throw new SourceNotAvailable(e);
}
} else {
throw new InvalidArgumentException("Don't know what to do with query: " + query);
}
} else {
throw new InvalidArgumentException("Don't know what to do with class: " + query.getClass());
}
return result;
}
/**
* Transform UniProt identifier to CAZy identifier.
*
* @param UniProt
* {@link MiriamData} with UniProt identifier
* @return Collection of {@link MiriamData} with BRENDA identifier
* @throws AnnotatorException
* thrown when there is a problem with accessing external database
*/
public Collection<MiriamData> uniprotToBrenda(MiriamData uniprot) throws AnnotatorException {
if (uniprot == null) {
return null;
}
if (!MiriamType.UNIPROT.equals(uniprot.getDataType())) {
throw new InvalidArgumentException(MiriamType.UNIPROT + " expected.");
}
String accessUrl = getUniprotUrl(uniprot.getResource());
try {
String pageContent = getWebPageContent(accessUrl);
Collection<MiriamData> collection = parseUniprot(pageContent);
if (collection.size() > 0) {
return collection;
} else {
logger.warn("Cannot find EC data for UniProt id: " + uniprot.getResource());
return null;
}
} catch (WrongResponseCodeIOException exception) {
logger.warn("Wrong response code when retrieving EC data for UniProt id: " + uniprot.getResource());
return null;
} catch (IOException exception) {
throw new AnnotatorException(exception);
}
}
@Override
public String getCommonName() {
return MiriamType.BRENDA.getCommonName();
}
@Override
public String getUrl() {
return MiriamType.BRENDA.getDbHomepage();
}
@Override
protected WebPageDownloader getWebPageDownloader() {
return super.getWebPageDownloader();
}
@Override
protected void setWebPageDownloader(WebPageDownloader webPageDownloader) {
super.setWebPageDownloader(webPageDownloader);
}
}
......@@ -59,7 +59,7 @@ public class CazyAnnotator extends ElementAnnotator implements IExternalService
}
@Override
public ExternalServiceStatus getServiceStatus() { //TODO
public ExternalServiceStatus getServiceStatus() {
ExternalServiceStatus status = new ExternalServiceStatus(getCommonName(), getUrl());
GeneralCacheInterface cacheCopy = getCache();
......
......@@ -13,6 +13,7 @@
<!-- Annotation services -->
<!-- Annotators -->
<bean id="BrendaAnnotator" class="lcsb.mapviewer.annotation.services.annotators.BrendaAnnotator"/>
<bean id="BiocompendiumAnnotator" class="lcsb.mapviewer.annotation.services.annotators.BiocompendiumAnnotator"/>
<bean id="CazyAnnotator" class="lcsb.mapviewer.annotation.services.annotators.CazyAnnotator"/>
<bean id="ChebiAnnotator" class="lcsb.mapviewer.annotation.services.annotators.ChebiAnnotator"/>
......
......@@ -6,6 +6,7 @@ import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@SuiteClasses({ AnnotatorExceptionTest.class, //
BrendaAnnotatorTest.class, //
BiocompendiumAnnotatorTest.class, //
CazyAnnotatorTest.class, //
ChebiAnnotatorTest.class, //
......
package lcsb.mapviewer.annotation.services.annotators;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.when;
import java.util.Collection;
import java.io.IOException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import lcsb.mapviewer.annotation.AnnotationTestFunctions;
import lcsb.mapviewer.annotation.cache.WebPageDownloader;
import lcsb.mapviewer.annotation.services.ExternalServiceStatusType;
import lcsb.mapviewer.common.exception.InvalidArgumentException;
import lcsb.mapviewer.model.map.MiriamData;
import lcsb.mapviewer.model.map.MiriamType;
import lcsb.mapviewer.model.map.species.GenericProtein;
import lcsb.mapviewer.model.map.species.Species;
public class BrendaAnnotatorTest extends AnnotationTestFunctions {
@Autowired
BrendaAnnotator brendaAnnotator;
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
@Test
public void testUniprotToCazy() throws Exception {
try {
Collection<MiriamData> mds = brendaAnnotator.uniprotToBrenda(new MiriamData(MiriamType.UNIPROT, "P12345"));
assertEquals(mds.size(), 2);
MiriamData md1 = new MiriamData(MiriamType.BRENDA, "2.6.1.1");
MiriamData md2 = new MiriamData(MiriamType.BRENDA, "2.6.1.7");
for (MiriamData md: mds) {
assertTrue(md.compareTo(md1) == 0 || md.compareTo(md2) == 0);
}
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Test
public void testAnnotateFromUniprot() throws Exception {
try {
Species protein = new GenericProtein("id");
protein.addMiriamData(new MiriamData(MiriamType.UNIPROT, "P12345"));
brendaAnnotator.annotateElement(protein);
int cntMds = 0;
for (MiriamData md : protein.getMiriamData()) {
if (md.getDataType().equals(MiriamType.BRENDA)) {
cntMds++;
assertTrue("Invalid BRENDA annotation extracted from BRENDA annotator",
md.getResource().equals("2.6.1.1") || md.getResource().equals("2.6.1.7") );
}
}
assertTrue("Incorrect BRENDA annotations extracted from BRENDA annotator", cntMds == 2);
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Test
public void testAnnotateFromTair() throws Exception {
try {
Species protein = new GenericProtein("id");
protein.setName("bla");
protein.addMiriamData(new MiriamData(MiriamType.TAIR_LOCUS, "AT5G48930"));
brendaAnnotator.annotateElement(protein);
MiriamData mdBrenda = null;
for (MiriamData md : protein.getMiriamData()) {
if (md.getDataType().equals(MiriamType.BRENDA)) {
mdBrenda = md; //there should be only one EC number for that TAIR<->UNIPROT record
}
}
assertTrue("No BRENDA annotation extracted from BRENDA annotator", mdBrenda != null);
assertTrue("Invalid BRENDA annotation extracted from BRENDA annotator based on TAIR", mdBrenda.getResource().equals("2.3.1.133") );
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Test
public void testAnnotateMultipleUniprots() throws Exception {
try {
Species protein = new GenericProtein("id");
protein.setName("bla");
protein.addMiriamData(new MiriamData(MiriamType.UNIPROT, "Q9SG95"));
protein.addMiriamData(new MiriamData(MiriamType.UNIPROT, "Q12540"));
brendaAnnotator.annotateElement(protein);
assertTrue("Wrong number of BRENDA identifiers extracted from BRENDA annotator", protein.getMiriamData().size() == 4 );
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Test
public void testAnnotateMultipleUniprotsWithIdenticalEC() throws Exception {
try {
Species protein = new GenericProtein("id");
protein.setName("bla");
protein.addMiriamData(new MiriamData(MiriamType.UNIPROT, "Q9SG95"));
protein.addMiriamData(new MiriamData(MiriamType.UNIPROT, "Q8L5J1"));
brendaAnnotator.annotateElement(protein);
assertTrue("Wrong number of BRENDA identifiers extracted from BRENDA annotator", protein.getMiriamData().size() == 3 );
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Test
public void testAnnotateInvalidEmpty() throws Exception {
try {
Species protein = new GenericProtein("id");
protein.setName("bla");
brendaAnnotator.annotateElement(protein);
assertEquals(0, protein.getMiriamData().size());
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Test
public void testAnnotateInvalidUniprot() throws Exception {
try {
Species protein = new GenericProtein("id");
protein.addMiriamData(new MiriamData(MiriamType.UNIPROT, "bla"));
brendaAnnotator.annotateElement(protein);
assertEquals(1, protein.getMiriamData().size());
assertEquals(1, getWarnings().size());
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Test
public void testAnnotateInvalidTair() throws Exception {
try {
Species protein = new GenericProtein("id");
protein.addMiriamData(new MiriamData(MiriamType.TAIR_LOCUS, "bla"));
brendaAnnotator.annotateElement(protein);
assertEquals(1, protein.getMiriamData().size());
assertEquals(1, getWarnings().size());
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Test
public void testInvalidUniprotToCazyNull() throws Exception {
try {
assertNull(brendaAnnotator.uniprotToBrenda(null));
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Test
public void testInvalidUniprotToCazyWrongMd() throws Exception {
try {
brendaAnnotator.uniprotToBrenda(new MiriamData(MiriamType.WIKIPEDIA, "bla"));
fail("Exception expected");
} catch (InvalidArgumentException e) {
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Test
public void testRefreshInvalidCacheQuery() throws Exception {
try {
brendaAnnotator.refreshCacheQuery("invalid_query");
fail("Exception expected");
} catch (InvalidArgumentException e) {
assertTrue(e.getMessage().contains("Don't know what to do"));
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Test
public void testRefreshInvalidCacheQuery2() throws Exception {
try {
brendaAnnotator.refreshCacheQuery(new Object());
fail("Exception expected");
} catch (InvalidArgumentException e) {
assertTrue(e.getMessage().contains("Don't know what to do"));
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Test
public void testRefreshCacheQuery() throws Exception {
try {
Object res = brendaAnnotator.refreshCacheQuery("http://google.cz/");
assertNotNull(res);
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Test
public void testStatus() throws Exception {
try {
assertEquals(ExternalServiceStatusType.OK, brendaAnnotator.getServiceStatus().getStatus());
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Test
public void testSimulateDownStatus() throws Exception {
WebPageDownloader downloader = brendaAnnotator.getWebPageDownloader();
try {
WebPageDownloader mockDownloader = Mockito.mock(WebPageDownloader.class);
when(mockDownloader.getFromNetwork(anyString(), anyString(), anyString())).thenThrow(new IOException());
brendaAnnotator.setWebPageDownloader(mockDownloader);
assertEquals(ExternalServiceStatusType.DOWN, brendaAnnotator.getServiceStatus().getStatus());
} catch (Exception e) {
e.printStackTrace();
throw e;
} finally {
brendaAnnotator.setWebPageDownloader(downloader);
}
}
@Test
public void testSimulateChangedStatus() throws Exception {
WebPageDownloader downloader = brendaAnnotator.getWebPageDownloader();
try {
WebPageDownloader mockDownloader = Mockito.mock(WebPageDownloader.class);
when(mockDownloader.getFromNetwork(anyString(), anyString(), anyString())).thenReturn("GN Name=ACSS2; Synonyms=ACAS2;");
brendaAnnotator.setWebPageDownloader(mockDownloader);
assertEquals(ExternalServiceStatusType.CHANGED, brendaAnnotator.getServiceStatus().getStatus());
} catch (Exception e) {
e.printStackTrace();
throw e;
} finally {
brendaAnnotator.setWebPageDownloader(downloader);
}
}
}
......@@ -10,17 +10,13 @@ import static org.mockito.Mockito.when;
import java.io.IOException;
import org.apache.http.client.HttpResponseException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import javassist.NotFoundException;
import lcsb.mapviewer.annotation.AnnotationTestFunctions;
import lcsb.mapviewer.annotation.cache.GeneralCacheInterface;
import lcsb.mapviewer.annotation.cache.GeneralCacheWithExclusion;
import lcsb.mapviewer.annotation.cache.WebPageDownloader;
import lcsb.mapviewer.annotation.services.ExternalServiceStatusType;
import lcsb.mapviewer.common.exception.InvalidArgumentException;
......
......@@ -22,6 +22,14 @@ import lcsb.mapviewer.model.map.species.Rna;
*/
@SuppressWarnings("unchecked")
public enum MiriamType {
/**
* Brenda enzyme database: http://www.brenda-enzymes.org.
*/
BRENDA("BRENDA", //
"http://www.brenda-enzymes.org", //
new String[] { "urn:miriam:brenda" }, //
new Class<?>[] {}, "MIR:00100101"), //
/**
* Chemical Abstracts Service database: http://commonchemistry.org.
*/
......
......@@ -3,3 +3,6 @@ INSERT INTO cache_type(validity, classname) VALUES (365, 'lcsb.mapviewer.annotat
DELETE FROM cache_type WHERE classname = 'lcsb.mapviewer.annotation.services.annotators.CazyAnnotator';
INSERT INTO cache_type(validity, classname) VALUES (365, 'lcsb.mapviewer.annotation.services.annotators.CazyAnnotator');
DELETE FROM cache_type WHERE classname = 'lcsb.mapviewer.annotation.services.annotators.BrendaAnnotator';
INSERT INTO cache_type(validity, classname) VALUES (365, 'lcsb.mapviewer.annotation.services.annotators.BrendaAnnotator');
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment