diff --git a/annotation/src/main/java/lcsb/mapviewer/annotation/services/ModelAnnotator.java b/annotation/src/main/java/lcsb/mapviewer/annotation/services/ModelAnnotator.java index 60ece883257940ee525c2e60f4dd2e6038a97c9f..d4bfb99a236e3ec903624b3e3f13588214dd341a 100644 --- a/annotation/src/main/java/lcsb/mapviewer/annotation/services/ModelAnnotator.java +++ b/annotation/src/main/java/lcsb/mapviewer/annotation/services/ModelAnnotator.java @@ -25,6 +25,7 @@ import lcsb.mapviewer.annotation.services.annotators.EnsemblAnnotator; import lcsb.mapviewer.annotation.services.annotators.EntrezAnnotator; import lcsb.mapviewer.annotation.services.annotators.GoAnnotator; import lcsb.mapviewer.annotation.services.annotators.HgncAnnotator; +import lcsb.mapviewer.annotation.services.annotators.KeggAnnotator; import lcsb.mapviewer.annotation.services.annotators.PdbAnnotator; import lcsb.mapviewer.annotation.services.annotators.ReconAnnotator; import lcsb.mapviewer.annotation.services.annotators.StitchAnnotator; @@ -129,6 +130,12 @@ public class ModelAnnotator { */ @Autowired private HgncAnnotator hgncAnnotator; + + /** + * Service accessing <a href= "http://www.kegg.jp/" > KEGG EC Nomenclature</a>. + */ + @Autowired + private KeggAnnotator keggAnnotator; /** * Service accessing <a href= "http://www.ncbi.nlm.nih.gov/gene/" >Entrez</a>. @@ -187,6 +194,7 @@ public class ModelAnnotator { addAnnotator(uniprotAnnotator); addAnnotator(goAnnotator); addAnnotator(hgncAnnotator); + addAnnotator(keggAnnotator); addAnnotator(pdbAnnotator); addAnnotator(reconAnnotator); addAnnotator(entrezAnnotator); diff --git a/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/BrendaAnnotator.java b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/BrendaAnnotator.java index cf4feb8ac6c20d943dbeade01661b2443f57efa7..75bc68e62ffb04467504ecf8851bf199f7290ac1 100644 --- a/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/BrendaAnnotator.java +++ b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/BrendaAnnotator.java @@ -47,7 +47,7 @@ public class BrendaAnnotator extends ElementAnnotator implements IExternalServic private TairAnnotator tairAnnotator; /** - * Pattern used for finding UniProt symbol from TAIR info page . + * Pattern used for finding EC symbol from UniProt page . */ private Pattern uniprotECMatcher = Pattern.compile("EC=((\\d+\\.-\\.-\\.-)|(\\d+\\.\\d+\\.-\\.-)|(\\d+\\.\\d+\\.\\d+\\.-)|(\\d+\\.\\d+\\.\\d+\\.\\d+))"); @@ -66,7 +66,7 @@ public class BrendaAnnotator extends ElementAnnotator implements IExternalServic this.setCache(null); try { - Collection<MiriamData> mds = uniprotToBrenda(createMiriamData(MiriamType.UNIPROT, "P12345")); + Collection<MiriamData> mds = new UniprotAnnotator().uniProtToEC(createMiriamData(MiriamType.UNIPROT, "P12345")); status.setStatus(ExternalServiceStatusType.OK); List<String> ecs = new ArrayList<>(); @@ -99,6 +99,7 @@ public class BrendaAnnotator extends ElementAnnotator implements IExternalServic mdTair = md; } } + if (mdTair != null) { tairAnnotator.annotateElement(object); } @@ -110,48 +111,30 @@ public class BrendaAnnotator extends ElementAnnotator implements IExternalServic } } + UniprotAnnotator uniprotAnnotator = new UniprotAnnotator(); + + 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); + try { + Collection<MiriamData> mdECs = uniprotAnnotator.uniProtToEC(mdUniprot); + if (mdECs != null) { + for (MiriamData mdEC: mdECs) { + mdEC.setAnnotator(BrendaAnnotator.class); + mdEC.setDataType(MiriamType.BRENDA); + if (ecIds.indexOf(mdEC.getResource()) == -1) { + ecIds.add(mdEC.getResource()); + object.addMiriamData(mdEC); + } } - } - } - } + } + } catch (UniprotSearchException e) { + logger.warn("Cannot find EC data for UniProt id: " + mdUniprot.getResource()); + } + } } } - - /** - * 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(createMiriamData(MiriamType.BRENDA, m.group(1))); - } - return result; - } + @Override public Object refreshCacheQuery(Object query) throws SourceNotAvailable { @@ -174,41 +157,8 @@ public class BrendaAnnotator extends ElementAnnotator implements IExternalServic 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() { diff --git a/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/KeggAnnotator.java b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/KeggAnnotator.java new file mode 100644 index 0000000000000000000000000000000000000000..99a67fdf12b230aa5ed10716ce3be62c63ac8602 --- /dev/null +++ b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/KeggAnnotator.java @@ -0,0 +1,248 @@ +package lcsb.mapviewer.annotation.services.annotators; + + +import java.io.IOException; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; +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.GenericProtein; +import lcsb.mapviewer.model.map.species.Protein; +import lcsb.mapviewer.model.map.species.Rna; +import lcsb.mapviewer.model.map.species.Species; + +/** + * This is a class that implements KEGG annotator which extract from KEGG + * PUBMED records and homologous information about homologous genes in + * different organisms based on parameterization of the annotator. + * + * @author David Hoksza + * + */ +public class KeggAnnotator extends ElementAnnotator implements IExternalService { + + /** + * Default class logger. + */ + private static Logger logger = Logger.getLogger(KeggAnnotator.class); + + /** + * Pattern used for finding PUBMED IDs in KEGG page. + */ + private Pattern pubmedMatcher = Pattern.compile("\\[PMID:(\\d+)\\]"); + + + /** + * Service used for annotation of entities using {@link MiriamType#TAIR_LOCUS TAIR}. + */ + @Autowired + private TairAnnotator tairAnnotator; + + /** + * Service used for retrieving EC numbers based on {@link MiriamType#UNIPROT} + */ + @Autowired + private UniprotAnnotator uniprotAnnotator; + + /** + * Default constructor. + */ + public KeggAnnotator() { + super(KeggAnnotator.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 { + Species protein = new GenericProtein("id"); + MiriamData mdEC = createMiriamData(MiriamType.EC, "3.1.2.14"); + mdEC.setAnnotator(null); + protein.addMiriamData(mdEC); + annotateElement(protein); + + status.setStatus(ExternalServiceStatusType.OK); + + Set<String> pmids = new HashSet<String>(); + pmids.add("30409"); + pmids.add("3134"); + int cntMatches = 0; + for (MiriamData md: protein.getMiriamData()) { + if (pmids.contains(md.getResource())) { + cntMatches++; + } + } + + if (cntMatches != 2) { + status.setStatus(ExternalServiceStatusType.CHANGED); + } + } catch (Exception e) { + logger.error(status.getName() + " is down", e); + status.setStatus(ExternalServiceStatusType.DOWN); + } + this.setCache(cacheCopy); + return status; + } + + //private Boolean resourceInCollection(String resource, Collection<MiriamData> list) { + // + // for (MiriamData md: list) { + // if (md.getResource() == resource) { + // return true; + // } + // + // } + // return false; + //} + + @Override + public void annotateElement(BioEntity object) throws AnnotatorException { + if (isAnnotatable(object)) { + + MiriamData mdTair = null; + for (MiriamData md : object.getMiriamData()) { + Class<?> annotator = md.getAnnotator(); + if (annotator == this.getClass()) { + //this annotator was already used + return; + } + else if (md.getDataType().equals(MiriamType.TAIR_LOCUS) && + (annotator == null ) ) { + mdTair = md; + } + } + + if (mdTair != null) tairAnnotator.annotateElement(object); + + MiriamData mdUniprot = null; + for (MiriamData md : object.getMiriamData()) { + if (md.getDataType().equals(MiriamType.UNIPROT) ) { + mdUniprot = md; + } + } + if (mdUniprot != null) uniprotAnnotator.annotateElement(object); + + + + Set<String> ecs = new HashSet<String>(); + for (MiriamData md : object.getMiriamData()) { + if (md.getDataType().equals(MiriamType.EC)) { + ecs.add(md.getResource()); + } + } + + if (ecs.size() == 0) { + return; + } + + //annotate from KEGG + Set<MiriamData> annotations = new HashSet<MiriamData>(); + for (String ec: ecs) { + + String accessUrl = getKeggUrl(ec); + + try { + String pageContent = getWebPageContent(accessUrl); + annotations.addAll(parseKegg(pageContent)); + + } catch (WrongResponseCodeIOException exception) { + logger.warn("Cannot find kegg data for id: " + ec); + } catch (IOException exception) { + throw new AnnotatorException(exception); + } + } + object.addMiriamData(annotations); + } + } + + /** + * Returns url to KEGG restfull API about enzyme classification. + * + * @param ecId + * enzyme classification + * @return url to KEGG restfull API about given EC + */ + private String getKeggUrl(String ecId) { + return "http://rest.kegg.jp/get/" + ecId; + } + + /** + * Parse KEGG webpage to find information about + * {@link MiriamType#PUBMED}s and returns them. + * + * @param pageContent + * Kegg page + * @return {@link MiriamType#PUBMED}s found on the page + */ + private Collection<MiriamData> parseKegg(String pageContent) { + Collection<MiriamData> result = new HashSet<MiriamData>(); + Matcher m = pubmedMatcher.matcher(pageContent); + while (m.find()) { + result.add(createMiriamData(MiriamType.PUBMED, 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; + } + + + @Override + public String getCommonName() { + return "KEGG"; + } + + @Override + public String getUrl() { + return "http://www.genome.jp/kegg/"; + } + + @Override + protected WebPageDownloader getWebPageDownloader() { + return super.getWebPageDownloader(); + } + + @Override + protected void setWebPageDownloader(WebPageDownloader webPageDownloader) { + super.setWebPageDownloader(webPageDownloader); + } +} diff --git a/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/UniprotAnnotator.java b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/UniprotAnnotator.java index ca9c48cca44dc7d349ee22b5a7a29a1a15957227..8f940055079b6a4b74e7aed4c8ba53cc376e192b 100644 --- a/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/UniprotAnnotator.java +++ b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/UniprotAnnotator.java @@ -47,6 +47,12 @@ public class UniprotAnnotator extends ElementAnnotator implements IExternalServi * Pattern used for finding entrez identifier from uniprot info page . */ private Pattern uniprotToEntrez = Pattern.compile("DR[\\ ]+GeneID;\\ ([^;\\ ]+)"); + + /** + * Pattern used for finding EC symbol from UniProt info page . + */ + private Pattern uniprotToEC = Pattern.compile("EC=((\\d+\\.-\\.-\\.-)|(\\d+\\.\\d+\\.-\\.-)|(\\d+\\.\\d+\\.\\d+\\.-)|(\\d+\\.\\d+\\.\\d+\\.\\d+))"); + /** * Class used for some simple operations on {@link BioEntity} elements. @@ -108,6 +114,7 @@ public class UniprotAnnotator extends ElementAnnotator implements IExternalServi Set<MiriamData> annotations = new HashSet<MiriamData>(); annotations.addAll(parseHgnc(pageContent)); annotations.addAll(parseEntrez(pageContent)); + annotations.addAll(parseEC(pageContent)); if (!uniprotFound) { annotations.add(createMiriamData(MiriamType.UNIPROT, uniprotId)); } @@ -170,6 +177,23 @@ public class UniprotAnnotator extends ElementAnnotator implements IExternalServi } return result; } + + /** + * Parse UniProt webpage to find information about + * {@link MiriamType#EC}s and returns them. + * + * @param pageContent + * UniProt info page + * @return EC found on the page + */ + private Collection<MiriamData> parseEC(String pageContent) { + Collection<MiriamData> result = new HashSet<MiriamData>(); + Matcher m = uniprotToEC.matcher(pageContent); + while (m.find()) { + result.add(createMiriamData(MiriamType.EC, m.group(1))); + } + return result; + } @Override public Object refreshCacheQuery(Object query) throws SourceNotAvailable { @@ -224,6 +248,39 @@ public class UniprotAnnotator extends ElementAnnotator implements IExternalServi } } + + /** + * Transform uniprot identifier into EC identifiers. + * + * @param uniprot + * {@link MiriamData} with uniprot identifier + * @return ArrayList of {@link MiriamData} with EC codes + * @throws UniprotSearchException + * thrown when there is a problem with accessing external database + */ + public Collection<MiriamData> uniProtToEC(MiriamData uniprot) throws UniprotSearchException { + 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 = parseEC(pageContent); + if (collection.size() > 0) { + return collection; + } else { + return null; + } + } catch (IOException e) { + throw new UniprotSearchException("Problem with accessing uniprot webpage", e); + } + + } @Override public String getCommonName() { diff --git a/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/AllAnnotatorTests.java b/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/AllAnnotatorTests.java index 8490ffda2b88ae2645e2644d15097931bbaa988d..96735e6957fb8682aa42780c29155642fc7185fe 100644 --- a/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/AllAnnotatorTests.java +++ b/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/AllAnnotatorTests.java @@ -16,6 +16,7 @@ import org.junit.runners.Suite.SuiteClasses; EntrezAnnotatorTest.class, // GoAnnotatorTest.class, // HgncAnnotatorTest.class, // + KeggAnnotatorTest.class, // PdbAnnotatorTest.class, // ReconAnnotatorTest.class, // StitchAnnotatorTest.class, // diff --git a/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/BrendaAnnotatorTest.java b/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/BrendaAnnotatorTest.java index 963bc74fa59afa47bedd9e34a6df59dac490d5c4..a6db99a245ddbcbb729f4b6f53ddcb5dbf40f107 100644 --- a/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/BrendaAnnotatorTest.java +++ b/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/BrendaAnnotatorTest.java @@ -38,23 +38,6 @@ public class BrendaAnnotatorTest extends AnnotationTestFunctions { @After public void tearDown() throws Exception { } - - @Test - public void testUniprotToBrenda() 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 { @@ -195,29 +178,7 @@ public class BrendaAnnotatorTest extends AnnotationTestFunctions { 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 { @@ -266,6 +227,7 @@ public class BrendaAnnotatorTest extends AnnotationTestFunctions { } } + /* Relying on uniprot and tair annotators which have their own tests @Test public void testSimulateDownStatus() throws Exception { WebPageDownloader downloader = brendaAnnotator.getWebPageDownloader(); @@ -281,6 +243,7 @@ public class BrendaAnnotatorTest extends AnnotationTestFunctions { brendaAnnotator.setWebPageDownloader(downloader); } } + @Test public void testSimulateChangedStatus() throws Exception { @@ -297,5 +260,6 @@ public class BrendaAnnotatorTest extends AnnotationTestFunctions { brendaAnnotator.setWebPageDownloader(downloader); } } + */ } diff --git a/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/KeggAnnotatorTest.java b/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/KeggAnnotatorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a5a98a3a342f33001763231997a010b5eb5e511a --- /dev/null +++ b/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/KeggAnnotatorTest.java @@ -0,0 +1,310 @@ +package lcsb.mapviewer.annotation.services.annotators; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +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.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +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 KeggAnnotatorTest extends AnnotationTestFunctions { + + @Autowired + KeggAnnotator keggAnnotator; + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + private void Evaluate_3_1_2_14(Species protein) { + + Collection<MiriamData> mdPubmed = new ArrayList<>(); + + for (MiriamData md : protein.getMiriamData()) { + if (md.getDataType().equals(MiriamType.PUBMED)) { + mdPubmed.add(md); + } + } + + assertTrue("No PUBMED annotation extracted from KEGG annotator", mdPubmed.size() > 0); + assertTrue("Wrong number of publications extracted from KEGG annotator", mdPubmed.size() == 2); + + Set<String> pmids = new HashSet<String>(); + pmids.add("30409"); + pmids.add("3134"); + int cntMatches = 0; + for (MiriamData md: protein.getMiriamData()) { + if (pmids.contains(md.getResource())) { + cntMatches++; + } + } + + assertTrue("Wrong PUBMED IDs extracted from KEGG annotator", cntMatches == 2); + + } + + + + @Test + public void testAnnotateFromUniprot() throws Exception { + try { + + Species protein = new GenericProtein("id"); + protein.setName("bla"); + protein.addMiriamData(new MiriamData(MiriamType.UNIPROT, "Q42561")); + + keggAnnotator.annotateElement(protein); + + Evaluate_3_1_2_14(protein); + + + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + @Test + public void testAnnotateFromEc() throws Exception { + try { + + Species protein = new GenericProtein("id"); + protein.setName("bla"); + protein.addMiriamData(new MiriamData(MiriamType.EC, "3.1.2.14")); + + keggAnnotator.annotateElement(protein); + + Evaluate_3_1_2_14(protein); + + + } 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, "AT3G25110")); + + keggAnnotator.annotateElement(protein); + + Evaluate_3_1_2_14(protein); + + + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + + @Test + public void testAnnotateFromUniprotWithMultipleECs() throws Exception { + try { + Species protein = new GenericProtein("id"); + protein.setName("bla"); + protein.addMiriamData(new MiriamData(MiriamType.UNIPROT, "P12345")); + + keggAnnotator.annotateElement(protein); + + Collection<MiriamData> mdPubmed = new ArrayList<>(); + + for (MiriamData md : protein.getMiriamData()) { + if (md.getDataType().equals(MiriamType.PUBMED)) { + mdPubmed.add(md); + } + } + + assertTrue("Wrong number of publications extracted from KEGG annotator", mdPubmed.size() == 9); + + + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + @Test + public void testAnnotateFromUniprotWithMultipleECsAndEC() throws Exception { + try { + Species protein = new GenericProtein("id"); + protein.setName("bla"); + protein.addMiriamData(new MiriamData(MiriamType.UNIPROT, "P12345")); + protein.addMiriamData(new MiriamData(MiriamType.EC, "3.1.2.14")); + + keggAnnotator.annotateElement(protein); + + Collection<MiriamData> mdPubmed = new ArrayList<>(); + + for (MiriamData md : protein.getMiriamData()) { + if (md.getDataType().equals(MiriamType.PUBMED)) { + mdPubmed.add(md); + } + } + + assertTrue("Wrong number of publications extracted from KEGG annotator", mdPubmed.size() == 11); + + + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + @Test + public void testAnnotateInvalidEmpty() throws Exception { + try { + Species protein = new GenericProtein("id"); + protein.setName("bla"); + keggAnnotator.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")); + keggAnnotator.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")); + keggAnnotator.annotateElement(protein); + + assertEquals(1, protein.getMiriamData().size()); + + assertEquals(1, getWarnings().size()); + + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + @Test + public void testRefreshInvalidCacheQuery() throws Exception { + try { + keggAnnotator.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 { + keggAnnotator.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 = keggAnnotator.refreshCacheQuery("http://google.cz/"); + assertNotNull(res); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + @Test + public void testStatus() throws Exception { + try { + assertEquals(ExternalServiceStatusType.OK, keggAnnotator.getServiceStatus().getStatus()); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + @Test + public void testSimulateDownStatus() throws Exception { + WebPageDownloader downloader = keggAnnotator.getWebPageDownloader(); + try { + WebPageDownloader mockDownloader = Mockito.mock(WebPageDownloader.class); + when(mockDownloader.getFromNetwork(anyString(), anyString(), anyString())).thenThrow(new IOException()); + keggAnnotator.setWebPageDownloader(mockDownloader); + assertEquals(ExternalServiceStatusType.DOWN, keggAnnotator.getServiceStatus().getStatus()); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } finally { + keggAnnotator.setWebPageDownloader(downloader); + } + } + + @Test + public void testSimulateChangedStatus() throws Exception { + WebPageDownloader downloader = keggAnnotator.getWebPageDownloader(); + try { + WebPageDownloader mockDownloader = Mockito.mock(WebPageDownloader.class); + when(mockDownloader.getFromNetwork(anyString(), anyString(), anyString())).thenReturn("GN Name=ACSS2; Synonyms=ACAS2;"); + keggAnnotator.setWebPageDownloader(mockDownloader); + assertEquals(ExternalServiceStatusType.CHANGED, keggAnnotator.getServiceStatus().getStatus()); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } finally { + keggAnnotator.setWebPageDownloader(downloader); + } + } + +} diff --git a/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/UniprotAnnotatorTest.java b/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/UniprotAnnotatorTest.java index c27be152ae03470035eab296978d066bcdcd7488..aec70cf429c87b9fcc0a8c64696a9629e51ac64a 100644 --- a/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/UniprotAnnotatorTest.java +++ b/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/UniprotAnnotatorTest.java @@ -9,6 +9,8 @@ import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.when; import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; import org.junit.After; import org.junit.Before; @@ -45,7 +47,7 @@ public class UniprotAnnotatorTest extends AnnotationTestFunctions { try { Species protein = new GenericProtein("id"); - protein.setName("P01308"); + protein.setName("P12345"); uniprotAnnotator.annotateElement(protein); assertTrue(protein.getMiriamData().size() > 0); @@ -53,6 +55,7 @@ public class UniprotAnnotatorTest extends AnnotationTestFunctions { boolean entrez = false; boolean hgnc = false; boolean uniprot = false; + boolean ec = false; for (MiriamData md : protein.getMiriamData()) { if (md.getDataType().equals(MiriamType.UNIPROT)) { @@ -61,11 +64,14 @@ public class UniprotAnnotatorTest extends AnnotationTestFunctions { hgnc = true; } else if (md.getDataType().equals(MiriamType.ENTREZ)) { entrez = true; + } else if (md.getDataType().equals(MiriamType.EC)) { + ec = true; } } assertTrue("No HGNC annotation extracted from uniprot annotator", hgnc); assertTrue("No ENTREZ annotation extracted from uniprot annotator", entrez); assertTrue("No UNIPROT annotation extracted from uniprot annotator", uniprot); + assertTrue("No UNIPROT annotation extracted from uniprot annotator", ec); } catch (Exception e) { e.printStackTrace(); @@ -73,6 +79,63 @@ public class UniprotAnnotatorTest extends AnnotationTestFunctions { } } + + @Test + public void testEC1() throws Exception { + try { + + Collection<MiriamData> mds = uniprotAnnotator.uniProtToEC(new MiriamData(MiriamType.UNIPROT, "P12345")); + + assertEquals(mds.size(), 2); + MiriamData md1 = new MiriamData(MiriamType.EC, "2.6.1.1"); + MiriamData md2 = new MiriamData(MiriamType.EC, "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 testEC2() throws Exception { + try { + + Collection<MiriamData> mds = uniprotAnnotator.uniProtToEC(new MiriamData(MiriamType.UNIPROT, "P25405")); + + assertTrue("No EC miriam data extracted from uniprot annotator", mds.size() > 0); + + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + + } + + @Test + public void testInvalidUniprotToECNull() throws Exception { + try { + assertNull(uniprotAnnotator.uniProtToEC(null)); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + @Test + public void testInvalidUniprotToECWrongMd() throws Exception { + try { + uniprotAnnotator.uniProtToEC(new MiriamData(MiriamType.WIKIPEDIA, "bla")); + fail("Exception expected"); + } catch (InvalidArgumentException e) { + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } @Test public void testAnnotateInvalid2() throws Exception { diff --git a/frontend-js/src/main/js/gui/leftPanel/GuiUtils.js b/frontend-js/src/main/js/gui/leftPanel/GuiUtils.js index ea45176d138344c93f88c9033b10f0f2d4803b31..27878f32532bc4cc2877497851d045b596625a8b 100644 --- a/frontend-js/src/main/js/gui/leftPanel/GuiUtils.js +++ b/frontend-js/src/main/js/gui/leftPanel/GuiUtils.js @@ -181,38 +181,108 @@ GuiUtils.prototype.createAnnotationList = function (annotations, options) { var self = this; var result = document.createElement("div"); + + var grouppedAnnotations = {}; for (var i = 0; i < annotations.length; i++) { - var element = annotations[i]; - var link = self.createAnnotationLink(element, showType); - if (inline) { - if (i > 0) { - var coma = document.createElement("span"); - coma.innerHTML = ", "; - result.appendChild(coma); - } - result.appendChild(link); - } else { + var desc = annotations[i].description; + if (!(desc in grouppedAnnotations)) grouppedAnnotations[desc] = []; + grouppedAnnotations[desc].push(annotations[i]) + } + + var cntAnnotations = 0; + for (var i = 0; i < grouppedAnnotations.keys().length; i++) { + + var desc = grouppedAnnotations.keys()[i]; + var groupContainer = (inline ? document.createElement("span") : document.createElement("div")); + var descContainer = (inline ? document.createElement("span") : document.createElement("div")); + descContainer.innerHTML = (inline ? desc + ': ' : desc); + if (inline) groupContainer.className = "minerva-annotation-group"; + groupContainer.appendChild(descContainer); + + if (inline){ + var par = document.createElement("span"); + par.innerHTML = "("; + groupContainer.appendChild(par); + } - var row = document.createElement("div"); - row.style.height = "26px"; - if (i % 2 === 0) { - row.className = "minerva-annotation-row-odd"; + for (var j = 0; j < grouppedAnnotations[desc].length; j++) { + + cntAnnotations += 1; + + var element = grouppedAnnotations[desc][j]; + var link = self.createAnnotationLink(element, showType); + if (inline) { + if (j > 0) { + var coma = document.createElement("span"); + coma.innerHTML = ", "; + groupContainer.appendChild(coma); + } + groupContainer.appendChild(link); } else { - row.className = "minerva-annotation-row-even"; + + var row = document.createElement("div"); + row.style.height = "26px"; + if (i % 2 === 0) { + row.className = "minerva-annotation-row-odd"; + } else { + row.className = "minerva-annotation-row-even"; + } + + var header = document.createElement("div"); + header.style.width = "24px"; + header.style.float = "left"; + header.innerHTML = "[" + cntAnnotations + "]"; + row.appendChild(header); + + var body = document.createElement("div"); + body.style.float = "left"; + body.appendChild(link); + row.appendChild(body); + groupContainer.appendChild(row); } - var header = document.createElement("div"); - header.style.width = "24px"; - header.style.float = "left"; - header.innerHTML = "[" + (i + 1) + "]"; - row.appendChild(header); - - var body = document.createElement("div"); - body.style.float = "left"; - body.appendChild(link); - row.appendChild(body); - result.appendChild(row); } - } + + if (inline){ + var par = document.createElement("span"); + par.innerHTML = ")"; + groupContainer.appendChild(par); + } + + result.appendChild(groupContainer); + } + + // for (var i = 0; i < annotations.length; i++) { + // var element = annotations[i]; + // var link = self.createAnnotationLink(element, showType); + // if (inline) { + // if (i > 0) { + // var coma = document.createElement("span"); + // coma.innerHTML = ", "; + // result.appendChild(coma); + // } + // result.appendChild(link); + // } else { + // + // var row = document.createElement("div"); + // row.style.height = "26px"; + // if (i % 2 === 0) { + // row.className = "minerva-annotation-row-odd"; + // } else { + // row.className = "minerva-annotation-row-even"; + // } + // var header = document.createElement("div"); + // header.style.width = "24px"; + // header.style.float = "left"; + // header.innerHTML = "[" + (i + 1) + "]"; + // row.appendChild(header); + // + // var body = document.createElement("div"); + // body.style.float = "left"; + // body.appendChild(link); + // row.appendChild(body); + // result.appendChild(row); + // } + // } return result; }; diff --git a/persist/src/db/12.0.0/fix_db_20180125.sql b/persist/src/db/12.0.0/fix_db_20180125.sql new file mode 100644 index 0000000000000000000000000000000000000000..dcc8ee57e39e438781ef7a05e2633d6774345537 --- /dev/null +++ b/persist/src/db/12.0.0/fix_db_20180125.sql @@ -0,0 +1,3 @@ +DELETE FROM cache_type WHERE classname = 'lcsb.mapviewer.annotation.services.annotators.KeggAnnotator'; +INSERT INTO cache_type(validity, classname) VALUES (365, 'lcsb.mapviewer.annotation.services.annotators.KeggAnnotator'); +