diff --git a/CellDesigner-plugin/.classpath b/CellDesigner-plugin/.classpath index fc5f96c9feacd9cd902963cc1ed3f89769603a21..1b6e7590699faad6d494ab35ceefba4610d6cdf6 100644 --- a/CellDesigner-plugin/.classpath +++ b/CellDesigner-plugin/.classpath @@ -6,11 +6,6 @@ <attribute name="maven.pomderived" value="true"/> </attributes> </classpathentry> - <classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"> - <attributes> - <attribute name="maven.pomderived" value="true"/> - </attributes> - </classpathentry> <classpathentry kind="src" output="target/test-classes" path="src/test/java"> <attributes> <attribute name="optional" value="true"/> 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 4556ea953202ba91366e8aa50f7ad303e8b42778..61c55ec02a04a8b9928b7d7df04d7b1e92594367 100644 --- a/annotation/src/main/java/lcsb/mapviewer/annotation/services/ModelAnnotator.java +++ b/annotation/src/main/java/lcsb/mapviewer/annotation/services/ModelAnnotator.java @@ -23,6 +23,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.PdbAnnotator; import lcsb.mapviewer.annotation.services.annotators.ReconAnnotator; import lcsb.mapviewer.annotation.services.annotators.UniprotAnnotator; import lcsb.mapviewer.common.IProgressUpdater; @@ -85,6 +86,12 @@ public class ModelAnnotator { */ @Autowired private UniprotAnnotator uniprotAnnotator; + + /** + * PDB annotator. + */ + @Autowired + private PdbAnnotator pdbAnnotator; /** * Recon annotator. @@ -142,6 +149,7 @@ public class ModelAnnotator { addAnnotator(uniprotAnnotator); addAnnotator(goAnnotator); addAnnotator(hgncAnnotator); + addAnnotator(pdbAnnotator); addAnnotator(reconAnnotator); addAnnotator(entrezAnnotator); addAnnotator(ensemblAnnotator); @@ -281,7 +289,7 @@ public class ModelAnnotator { try { elementAnnotator.annotateElement(element); } catch (AnnotatorException e) { - logger.warn(elementUtils.getElementTag(element) + " " + elementAnnotator.getCommonName() + " annotation problem"); + logger.warn(elementUtils.getElementTag(element) + " " + elementAnnotator.getCommonName() + " annotation problem: " + e.getMessage()); } } counter++; diff --git a/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/ElementAnnotator.java b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/ElementAnnotator.java index 6703789f93909815b9ead7e506c659265d2b3e7e..84761857a50fbc4efc25089dc24a2445fd8e7350 100644 --- a/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/ElementAnnotator.java +++ b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/ElementAnnotator.java @@ -40,7 +40,7 @@ public abstract class ElementAnnotator extends CachableInterface { private final List<Class<? extends BioEntity>> validClasses = new ArrayList<>(); /** - * Should be this annotator used as a default annotatior. + * Should be this annotator used as a default annotator. */ private boolean isDefault = false; diff --git a/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/PdbAnnotator.java b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/PdbAnnotator.java new file mode 100644 index 0000000000000000000000000000000000000000..4d69f2e648439e4cae31bec59aeef2aaf6a5e3b6 --- /dev/null +++ b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/PdbAnnotator.java @@ -0,0 +1,295 @@ +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.Map; +import java.util.List; + +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; +import lcsb.mapviewer.model.map.species.Species; +import lcsb.mapviewer.modelutils.map.ElementUtils; +import lcsb.mapviewer.model.map.species.field.Structure; +import lcsb.mapviewer.model.map.species.field.UniprotRecord; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +/** + * This is a class that implements a backend to the EBI's PDB SIFTS REST API mapping. + * + * @author David Hoksza + * + */ +public class PdbAnnotator extends ElementAnnotator implements IExternalService { + + /** + * Default class logger. + */ + private static Logger logger = Logger.getLogger(PdbAnnotator.class); + + /** + * Class used for some simple operations on {@link BioEntity} elements. + */ + private ElementUtils elementUtils = new ElementUtils(); + + /** + * Service used for annotation of proteins using {@link MiriamType#UNIPROT + * uniprot}. + */ + @Autowired + private UniprotAnnotator uniprotAnnotator; + + /** + * Service used for annotation of proteins using {@link MiriamType#HGNC + * hgnc} (this can include lookup and loading annotation from {@link + * MiriamType#UNIPROT uniprot}. + */ + @Autowired + private HgncAnnotator hgncAnnotator; + + + /** + * Default constructor. + */ + public PdbAnnotator() { + super(PdbAnnotator.class, new Class[] { Protein.class, Rna.class, Gene.class }, false); + } + + @Override + public ExternalServiceStatus getServiceStatus() { + ExternalServiceStatus status = new ExternalServiceStatus(getCommonName(), getUrl()); + + GeneralCacheInterface cacheCopy = getCache(); + this.setCache(null); + + try { + Collection<Structure> structures = uniProtToPdb(new MiriamData(MiriamType.UNIPROT, "P29373")); + + if (structures.size() > 0){ + if (structures.iterator().next().getPdbId() != null) { //TODO - is this id? + status.setStatus(ExternalServiceStatusType.OK); + } else { + status.setStatus(ExternalServiceStatusType.CHANGED); + } + } + else { + status.setStatus(ExternalServiceStatusType.DOWN); + } + } catch (Exception e) { + logger.error(status.getName() + " is down", e); + status.setStatus(ExternalServiceStatusType.DOWN); + } + this.setCache(cacheCopy); + return status; + } + + public Set<MiriamData> getUnitProts(BioEntity bioEntity) { + HashSet<MiriamData> mds = new HashSet<>(); + for (MiriamData md : bioEntity.getMiriamData()) { + if (md.getDataType().equals(MiriamType.UNIPROT)) { + mds.add(md); + } + } + return mds; + } + + @Override + public void annotateElement(BioEntity bioEntity) throws AnnotatorException { + if (isAnnotatable(bioEntity)) { + Set<MiriamData> mds = getUnitProts(bioEntity); + + /* + if (mds == null) { + uniprotAnnotator.annotateElement(bioEntity); + mds = getUnitProts(bioEntity); + }*/ + + /*If no UniProt ID was found, try to search HGNC which then searches UNIPROT + * based on the gene name. + */ + if (mds.size() == 0) { + hgncAnnotator.annotateElement(bioEntity); + mds = getUnitProts(bioEntity); + } + + if (mds.size() == 0) { + return; + } + + for (MiriamData md : mds) { + try { + Set<Structure> structures = (Set<Structure>)uniProtToPdb(md); + if (structures.size() == 0) { + logger.warn(elementUtils.getElementTag(bioEntity) + " No PDB mapping for UniProt ID: " + md.getResource()); + } else { + //add the annotations to the set of annotation irrespective on + //which uniprot record the structures belong to (since one molecule + //can have multiple uniprot records associated, but annotations do + //do not have the concept of hierarchy or complex data types) + Set<MiriamData> annotations = new HashSet<MiriamData>(); + for (Structure s : structures) { + annotations.add(new MiriamData(MiriamType.PDB, s.getPdbId())); + } + bioEntity.addMiriamData(annotations); + + //insert the full information directly into species, .i.e. + //create new uniprot record which includes the mapped structures + //and add it to the species (bioentity) + UniprotRecord ur = new UniprotRecord(); + ur.setUniprotId(md.getResource()); + ur.setSpecies((Species)bioEntity); + for (Structure s : structures) { + s.setUniprot(ur); + } + ur.setStructures(structures); + ((Species)bioEntity).getUniprots().add(ur); + } + } catch (WrongResponseCodeIOException exception) { + logger.warn("Not found PDB mapping (wrong response code) for UniProt ID: " + md.getResource()); + } catch (IOException exception) { + throw new AnnotatorException(exception); + } + + } + } + } + + /** + * Returns url to JSON with best mapping PDB entries given the UniProt entry. + * + * @param uniprotId + * uniprot identifier + * @return url with best mapping PDB entries to the UniProt entry + */ + private String getPdbMappingUrl(String uniprotId) { + return "https://www.ebi.ac.uk/pdbe/api/mappings/best_structures/" + uniprotId; + } + + /** + * Parse UniProt-to-PDB mapping JSON file. + * {@link MiriamType#PDB} and returns them. + * + * @param pageContentJson + * JSON file with the UniProt to PDB mapping + * @return set of PDB identifiers found on the webpage + */ + private Collection<Structure> processMappingData(String pageContentJson) { + Collection<Structure> result = new HashSet<Structure>(); + Gson g = new Gson(); + java.lang.reflect.Type t = new TypeToken<Map<String, List<PdbBestMappingEntry>>>(){}.getType(); + Map<String, List<PdbBestMappingEntry>> m = g.fromJson(pageContentJson, t); + if (m != null){ + for (String key : m.keySet()){ + for(PdbBestMappingEntry e : m.get(key)) { + if (e != null){ + result.add(e.convertToStructure()); + //result.add(new MiriamData(MiriamType.PDB, e.pdb_id)); + } + } + } + } + + 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; + } + + + /** + * Tests if given input string is a valid JSON document. + * + * @param json + * Input document as a string. + * @return True or false dependent on whether the input string is a valid JSON document + */ + public static boolean isJson(String json) { + Gson gson = new Gson(); + try { + gson.fromJson(json, Object.class); + return true; + } catch (com.google.gson.JsonSyntaxException ex) { + return false; + } + } + + /** + * Transform UniProt identifier into PDB IDs. + * + * @param uniprot + * {@link MiriamData} with UniProt identifier + * @return JSON String with mapping. + * thrown when there is a problem with accessing external database + */ + public Collection<Structure> uniProtToPdb(MiriamData uniprot) throws IOException { + if (uniprot == null) { + return null; + } + + if (!MiriamType.UNIPROT.equals(uniprot.getDataType())) { + throw new InvalidArgumentException(MiriamType.UNIPROT + " expected."); + } + + String accessUrl = getPdbMappingUrl(uniprot.getResource()); + String json = getWebPageContent(accessUrl); + + return isJson(json) ? processMappingData(json) : null; + } + + @Override + public String getCommonName() { + return MiriamType.PDB.getCommonName(); + } + + @Override + public String getUrl() { + return MiriamType.PDB.getDbHomepage(); + } + + @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/PdbBestMappingEntry.java b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/PdbBestMappingEntry.java new file mode 100644 index 0000000000000000000000000000000000000000..c3cf1c9b2c2568050b2a702af2ed6cd3a2db7abe --- /dev/null +++ b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/PdbBestMappingEntry.java @@ -0,0 +1,40 @@ +package lcsb.mapviewer.annotation.services.annotators; + +import lcsb.mapviewer.model.map.species.field.Structure; + +/** + * Structure of the PDB entries returned by the PDBe REST API "Best Structures" + * + * @author David Hoksza + * + */ +public class PdbBestMappingEntry { + public String chain_id; + public String experimental_method; + public String pdb_id; + public int start; + public int end; + public int unp_end; + public double coverage; + public int unp_start; + public double resolution; + public int tax_id; + + public Structure convertToStructure() { + + Structure s = new Structure(); + + s.setPdbId(this.pdb_id); + s.setChainId(this.chain_id); + s.setCoverage(this.coverage); + s.setResolution(this.resolution); + s.setStructStart(this.start); + s.setStructEnd(this.end); + s.setUnpStart(this.unp_start); + s.setUnpEnd(this.unp_end); + s.setExperimentalMethod(this.experimental_method); + s.setTaxId(this.tax_id); + + return s; + } +} diff --git a/annotation/src/main/resources/applicationContext-annotation.xml b/annotation/src/main/resources/applicationContext-annotation.xml index 8d26b7a2b64972c73d6972a21d2f223b55c0f295..a7fb40eb35be374a23dc3648ed0f1c786b5f8d95 100644 --- a/annotation/src/main/resources/applicationContext-annotation.xml +++ b/annotation/src/main/resources/applicationContext-annotation.xml @@ -20,6 +20,7 @@ <bean id="GoAnnotator" class="lcsb.mapviewer.annotation.services.annotators.GoAnnotator"/> <bean id="HgncAnnotator" class="lcsb.mapviewer.annotation.services.annotators.HgncAnnotator"/> <bean id="ReconAnnotator" class="lcsb.mapviewer.annotation.services.annotators.ReconAnnotator"/> + <bean id="PdbAnnotator" class="lcsb.mapviewer.annotation.services.annotators.PdbAnnotator"/> <bean id="UniprotAnnotator" class="lcsb.mapviewer.annotation.services.annotators.UniprotAnnotator"/> <bean id="ChEMBLParser" class="lcsb.mapviewer.annotation.services.ChEMBLParser"/> diff --git a/annotation/src/test/java/lcsb/mapviewer/annotation/cache/WebPageDownloaderTest.java b/annotation/src/test/java/lcsb/mapviewer/annotation/cache/WebPageDownloaderTest.java index d548f06e95733454bbf64761aa45f161f0d6c95d..1a1f711b6c7c61bc370dba54a2635a7a78db1bb1 100644 --- a/annotation/src/test/java/lcsb/mapviewer/annotation/cache/WebPageDownloaderTest.java +++ b/annotation/src/test/java/lcsb/mapviewer/annotation/cache/WebPageDownloaderTest.java @@ -88,7 +88,7 @@ public class WebPageDownloaderTest { public void testInvalidHttpRequestType() { WebPageDownloader downloader = new WebPageDownloader(); try { - String result = downloader.getFromNetwork("https://www.ebi.ac.uk/pdbe/api/mappings/best_structures/", "XXX", "P29373"); + downloader.getFromNetwork("https://www.ebi.ac.uk/pdbe/api/mappings/best_structures/", "XXX", "P29373"); fail("Invalid request exception expected"); } catch (IOException e) { } 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 71dae4246b80c0f32a5ea1543bb31b73120d149d..218bd397eec6b1d0c43b14046b61f4db209aa6ed 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 @@ -13,6 +13,7 @@ import org.junit.runners.Suite.SuiteClasses; EntrezAnnotatorTest.class, // GoAnnotatorTest.class, // HgncAnnotatorTest.class, // + PdbAnnotatorTest.class, // ReconAnnotatorTest.class, // UniprotAnnotatorTest.class, // }) diff --git a/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/PdbAnnotatorTest.java b/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/PdbAnnotatorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d2fa17c6e0848b9a9fa688c9c4777369575ccfd0 --- /dev/null +++ b/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/PdbAnnotatorTest.java @@ -0,0 +1,274 @@ +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.mockito.Matchers.anyString; +import static org.mockito.Mockito.when; + +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.model.map.MiriamData; +import lcsb.mapviewer.model.map.MiriamType; +import lcsb.mapviewer.model.map.species.GenericProtein; +import lcsb.mapviewer.model.map.species.Species; +import lcsb.mapviewer.model.map.species.field.Structure; +import lcsb.mapviewer.model.map.species.field.UniprotRecord; + +public class PdbAnnotatorTest extends AnnotationTestFunctions { + + @Autowired + PdbAnnotator pdbAnnotator; + + @Autowired + UniprotAnnotator uniprotAnnotator; + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testAnnotate1() throws Exception { + try { + String uniprotId = "P29373"; + Species protein = new GenericProtein("id"); + protein.setName(uniprotId); + /* One needs to have the UniProt ID first. + * This tests simulates situation when the Uniprot annotator + * is called first. + */ + uniprotAnnotator.annotateElement(protein); + int cntAnnotations1 = protein.getMiriamData().size(); + pdbAnnotator.annotateElement(protein); + int cntAnnotations2 = protein.getMiriamData().size(); + + assertTrue(cntAnnotations2 > cntAnnotations1); + + boolean pdb = false; + + for (MiriamData md : protein.getMiriamData()) { + if (md.getDataType().equals(MiriamType.PDB)) { + pdb = true; + break; + } + } + assertTrue("No PDB annotation extracted from pdb annotator", pdb); + + Set<UniprotRecord> urs = protein.getUniprots(); + //Test whether there is a uniprot record + assertTrue(urs.size() > 0); + UniprotRecord ur = null; + for (UniprotRecord ur1 : urs) { + if (ur1.getUniprotId() == uniprotId) { + ur = ur1; + } + } + //Test whether there is a uniprot record with the uniprot ID which was stored + assertNotNull(ur); + //Test whether structures are there + Set<Structure> ss = ur.getStructures(); + assertNotNull(ss); + assertTrue(ss.size() > 0); + //Test whether uniprot is accessible from structure + assertTrue(ss.iterator().next().getUniprot() == ur); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + +// @Test +// public void testAnnotate2() throws Exception { +// try { +// Species protein = new GenericProtein("id"); +// protein.setName("P29373"); +// /* One needs to have the UniProt ID first, and Uniprot lookup +// * through HGNC is included in PDB annotator. +// * This tests simulates situation when the PDB annotator is called first. +// */ +// pdbAnnotator.annotateElement(protein); +// int cntAnnotations = protein.getMiriamData().size(); +// +// assertTrue(cntAnnotations > 0); +// +// boolean pdb = false; +// +// for (MiriamData md : protein.getMiriamData()) { +// if (md.getDataType().equals(MiriamType.PDB)) { +// pdb = true; +// break; +// } +// } +// assertTrue("No PDB annotation extracted from pdb annotator", pdb); +// +// } catch (Exception e) { +// e.printStackTrace(); +// throw e; +// } +// } + + @Test + public void testAnnotate3() throws Exception { + try { + Species protein = new GenericProtein("id"); + protein.setName("SNCA"); + /* One needs to have the UniProt ID first, but Uniprot lookup + * is included in the PDB annotator (as well as HGNC lookup). + * This tests simulates situation when the PDB annotator is called first + * and the name can be resolved by HGNC, but not UniProt. + */ + pdbAnnotator.annotateElement(protein); + int cntAnnotations = protein.getMiriamData().size(); + + assertTrue(cntAnnotations > 0); + + boolean pdb = false; + + for (MiriamData md : protein.getMiriamData()) { + if (md.getDataType().equals(MiriamType.PDB)) { + pdb = true; + break; + } + } + assertTrue("No PDB annotation extracted from pdb annotator", pdb); + + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + +// @Test +// public void testAnnotateNotUniprotAnnodated() throws Exception { +// try { +// Species protein = new GenericProtein("id"); +// protein.setName("P29373"); +// pdbAnnotator.annotateElement(protein); +// +// assertTrue("UniProt annotation in PDB annotator failed", protein.getMiriamData().size() > 0); +// +// boolean pdb = false; +// +// for (MiriamData md : protein.getMiriamData()) { +// if (md.getDataType().equals(MiriamType.PDB)) { +// pdb = true; +// break; +// } +// } +// assertTrue("No PDB annotation extracted from PDB annotator", pdb); +// +// } catch (Exception e) { +// e.printStackTrace(); +// throw e; +// } +// } + + @Test + public void testAnnotateInvalidUniprot() throws Exception { + try { + Species protein = new GenericProtein("id"); + protein.setName("bla"); + pdbAnnotator.annotateElement(protein); + + assertEquals(0, protein.getMiriamData().size()); + + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + @Test + public void testAnnotateValidUniprotNonexistingPdb() throws Exception { + try { + Species protein = new GenericProtein("id"); + protein.setName("Q88VP8"); + pdbAnnotator.annotateElement(protein); + + boolean pdb = false; + for (MiriamData md : protein.getMiriamData()) { + if (md.getDataType().equals(MiriamType.PDB)) { + pdb = true; + break; + } + } + assertTrue("PDB mapping found for structure for which no should be available", !pdb); + assertEquals(1, getWarnings().size()); + + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + @Test + public void testSimulateDownStatus() throws Exception { + WebPageDownloader downloader = pdbAnnotator.getWebPageDownloader(); + try { + WebPageDownloader mockDownloader = Mockito.mock(WebPageDownloader.class); + when(mockDownloader.getFromNetwork(anyString(), anyString(), anyString())).thenReturn(""); + pdbAnnotator.setWebPageDownloader(mockDownloader); + assertEquals(ExternalServiceStatusType.DOWN, pdbAnnotator.getServiceStatus().getStatus()); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } finally { + pdbAnnotator.setWebPageDownloader(downloader); + } + } + + @Test + public void testSimulateChangedStatus() throws Exception { + WebPageDownloader downloader = pdbAnnotator.getWebPageDownloader(); + try { + WebPageDownloader mockDownloader = Mockito.mock(WebPageDownloader.class); + when(mockDownloader.getFromNetwork(anyString(), anyString(), anyString())).thenReturn("{\"P29373\": [{\"xxx\": 140}]}"); + pdbAnnotator.setWebPageDownloader(mockDownloader); + assertEquals(ExternalServiceStatusType.CHANGED, pdbAnnotator.getServiceStatus().getStatus()); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } finally { + pdbAnnotator.setWebPageDownloader(downloader); + } + } + + @Test + public void testSimulateInvalidJson() throws Exception { + WebPageDownloader downloader = pdbAnnotator.getWebPageDownloader(); + try { + Species protein = new GenericProtein("id"); + protein.setName("Q88VP8"); + uniprotAnnotator.annotateElement(protein); + int cntAnnotations1 = protein.getMiriamData().size(); + + WebPageDownloader mockDownloader = Mockito.mock(WebPageDownloader.class); + when(mockDownloader.getFromNetwork(anyString(), anyString(), anyString())).thenReturn("\"P29373\": [{\"xxx\": 140}]}"); + pdbAnnotator.setWebPageDownloader(mockDownloader); + + pdbAnnotator.annotateElement(protein); + int cntAnnotations2 = protein.getMiriamData().size(); + assertTrue(cntAnnotations1 == cntAnnotations2); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } finally { + pdbAnnotator.setWebPageDownloader(downloader); + } + } + +} diff --git a/converter-CellDesigner/.classpath b/converter-CellDesigner/.classpath index fae1a2b37d5e3386c9651caedb78b9bd107715bd..d46faf10ed6b222a00963f1db7c75123572c051c 100644 --- a/converter-CellDesigner/.classpath +++ b/converter-CellDesigner/.classpath @@ -6,11 +6,6 @@ <attribute name="maven.pomderived" value="true"/> </attributes> </classpathentry> - <classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"> - <attributes> - <attribute name="maven.pomderived" value="true"/> - </attributes> - </classpathentry> <classpathentry kind="src" output="target/test-classes" path="src/test/java"> <attributes> <attribute name="optional" value="true"/> diff --git a/converter-graphics/.classpath b/converter-graphics/.classpath index ace82666f2f113cdb835230548bb1c0ddf6ca559..22c865221bbb05b20a9c038d748db0cbf2129ff6 100644 --- a/converter-graphics/.classpath +++ b/converter-graphics/.classpath @@ -6,11 +6,6 @@ <attribute name="maven.pomderived" value="true"/> </attributes> </classpathentry> - <classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"> - <attributes> - <attribute name="maven.pomderived" value="true"/> - </attributes> - </classpathentry> <classpathentry kind="src" output="target/test-classes" path="src/test/java"> <attributes> <attribute name="optional" value="true"/> diff --git a/frontend-js/src/main/js/map/data/BioEntity.js b/frontend-js/src/main/js/map/data/BioEntity.js index a811be4c2c0c59e935b79846b1b68aa32aa63ae4..9c5534da81e6a2f4e7bf515bf8dcc2c21ffa50e3 100644 --- a/frontend-js/src/main/js/map/data/BioEntity.js +++ b/frontend-js/src/main/js/map/data/BioEntity.js @@ -106,7 +106,7 @@ BioEntity.prototype.getType = function() { BioEntity.prototype.getOther = function(type) { if (this._other !== undefined) { - return this._other[type]; + return (type === undefined) ? this._other : this._other[type]; } }; diff --git a/model/src/main/java/lcsb/mapviewer/model/map/MiriamType.java b/model/src/main/java/lcsb/mapviewer/model/map/MiriamType.java index cd8b930f1703058b08f2138e4688354fc45bfa4a..31fa7c1338738febf5798debcde11f33fafa604a 100644 --- a/model/src/main/java/lcsb/mapviewer/model/map/MiriamType.java +++ b/model/src/main/java/lcsb/mapviewer/model/map/MiriamType.java @@ -265,6 +265,14 @@ public enum MiriamType { "http://www.pantherdb.org/", // new String[] { "urn:miriam:panther.family", "urn:miriam:panther" }, // new Class<?>[] { Protein.class, Gene.class, Rna.class }, "MIR:00000060"), // + + /** + * PDB: http://www.pdbe.org/. + */ + PDB("Protein Data Bank", // + "http://www.pdbe.org/", // + "urn:miriam:pdb", // + new Class<?>[] { Protein.class, Gene.class, Rna.class }, "MIR:00000020"), /** * Protein Family Database: http://pfam.xfam.org/. diff --git a/model/src/main/java/lcsb/mapviewer/model/map/species/Species.java b/model/src/main/java/lcsb/mapviewer/model/map/species/Species.java index 62875191ca8a99293cb0a87b49e0f4069b891554..a873e01f7d7c60a57224de620db2485e5e7923ca 100644 --- a/model/src/main/java/lcsb/mapviewer/model/map/species/Species.java +++ b/model/src/main/java/lcsb/mapviewer/model/map/species/Species.java @@ -18,6 +18,7 @@ import org.hibernate.annotations.CascadeType; import lcsb.mapviewer.model.map.reaction.ReactionNode; import lcsb.mapviewer.model.map.species.field.PositionToCompartment; +import lcsb.mapviewer.model.map.species.field.UniprotRecord; /** * Structure used for representing information about single element. @@ -121,6 +122,13 @@ public abstract class Species extends Element { * Is species hypothetical. */ private Boolean hypothetical = null; + + /** + * List of uniprot records which are associated with this species. + */ + @Cascade({ CascadeType.ALL }) + @OneToMany(fetch = FetchType.EAGER, mappedBy = "species", orphanRemoval = true) + private Set<UniprotRecord> uniprots = new HashSet<>(); /** * Constructor that set element identifier. @@ -168,6 +176,8 @@ public abstract class Species extends Element { homodimer = original.getHomodimer(); positionToCompartment = original.getPositionToCompartment(); hypothetical = original.getHypothetical(); + + uniprots = original.getUniprots(); // don't copy reaction nodes } @@ -404,6 +414,23 @@ public abstract class Species extends Element { return hypothetical; } + /** + * @param uniprots + * set of uniprot records for this species + * @see #uniprots + */ + public void setUniprots(Set<UniprotRecord> uniprots) { + this.uniprots = uniprots; + } + + /** + * @return the uniprot + * @see #uniprots + */ + public Set<UniprotRecord> getUniprots() { + return uniprots; + } + /** * @param hypothetical * the hypothetical to set diff --git a/model/src/main/java/lcsb/mapviewer/model/map/species/field/Structure.java b/model/src/main/java/lcsb/mapviewer/model/map/species/field/Structure.java new file mode 100644 index 0000000000000000000000000000000000000000..5d92fdcce29dc318a40493139f49ec71c037cd57 --- /dev/null +++ b/model/src/main/java/lcsb/mapviewer/model/map/species/field/Structure.java @@ -0,0 +1,363 @@ +package lcsb.mapviewer.model.map.species.field; + +import java.io.Serializable; +import java.util.Map; +import java.util.HashMap; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; + +import org.apache.commons.collections.map.HashedMap; + +import lcsb.mapviewer.common.exception.NotImplementedException; + +/** + * This class stores structure information as obtained from the SIFTS API + * (https://www.ebi.ac.uk/pdbe/api/doc/sifts.html best_structures), which provides + * the following fields + * pdb_id: the PDB ID which maps to the UniProt ID + * chain_id: the specific chain of the PDB which maps to the UniProt ID + * coverage: the percent coverage of the entire UniProt sequence + * resolution: the resolution of the structure + * start: the structure residue number which maps to the start of the mapped sequence + * unp_start: the sequence residue number which maps to the structure start + * end: the structure residue number which maps to the end of the mapped sequence + * unp_end: the sequence residue number which maps to the structure end + * experimental_method: type of experiment used to determine structure + * tax_id: taxonomic ID of the protein's original organism + * + * @author David Hoksza + * + */ +@Entity +@Table(name = "structure_table") +//@org.hibernate.annotations.GenericGenerator(name = "test-increment-strategy", strategy = "increment") +public class Structure implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 1L; + + + /** + * Unique identifier in the database. + */ + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "iddb", unique = true, nullable = false) + private int id; + + /** + * Uniprot record to which this structure belongs to. + */ + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name = "uniprot_id", nullable = false) + private UniprotRecord uniprot; + + /** + * the PDB ID which maps to the UniProt ID + */ + @Column(name = "pdb_id") + private String pdbId = null; + + /** + * the specific chain of the PDB which maps to the UniProt ID + */ + @Column(name = "chain_id") + private String chainId = null; + + /** + * the percent coverage of the entire UniProt sequence + */ + @Column(name = "coverage") + private Double coverage = null; + + /** + * the resolution of the structure + */ + @Column(name = "resolution") + private Double resolution = null; + + /** + * the structure residue number which maps to the start of the mapped sequence + */ + @Column(name = "struct_start") + private Integer structStart = null; + + /** + * the structure residue number which maps to the end of the mapped sequence + */ + @Column(name = "struct_end") + private Integer structEnd = null; + + /** + * the sequence residue number which maps to the structure start + */ + @Column(name = "unp_start") + private Integer unpStart = null; + + /** + * the sequence residue number which maps to the structure end + */ + @Column(name = "unp_end") + private Integer unpEnd = null; + + /** + * type of experiment used to determine structure + */ + @Column(name = "experimental_method") + private String experimentalMethod = null; + + /** + * taxonomic ID of the protein's original organism + */ + @Column(name = "tax_id") + private Integer taxId = null; + + /** + * Default constructor. + */ + public Structure() { + } + + /** + * Constructor that initialize object with the data taken from the parameter. + * + * @param s + * original object from which data is taken + */ + public Structure(Structure s) { + this.id = s.id; + this.uniprot = s.uniprot; + this.pdbId = s.pdbId; + this.chainId = s.chainId; + this.coverage = s.coverage; + this.resolution = s.resolution; + this.structStart = s.structStart; + this.structEnd = s.structEnd; + this.unpStart = s.unpStart; + this.unpEnd = s.unpEnd; + this.experimentalMethod = s.experimentalMethod; + this.taxId = s.taxId; + } + + /** + * Creates copy of the object. + * + * @return copy of the object. + */ + public Structure copy() { + if (this.getClass() == Structure.class) { + return new Structure(this); + } else { + throw new NotImplementedException("Method copy() should be overriden in class " + this.getClass()); + } + } + + /** + * @return the idModificationResidue + * @see #id + */ + public int getId() { + return id; + } + + /** + * @param id + * the id to set + * @see #id + */ + public void setId(int id) { + this.id = id; + } + + /** + * @return the uniprot + */ + public UniprotRecord getUniprot() { + return uniprot; + } + + /** + * @param uniprot the uniprot to set + */ + public void setUniprot(UniprotRecord uniprot) { + this.uniprot = uniprot; + } + + /** + * @return the pdbId + */ + public String getPdbId() { + return pdbId; + } + + /** + * @param pdbId the pdbId to set + */ + public void setPdbId(String pdbId) { + this.pdbId = pdbId; + } + + /** + * @return the chainId + */ + public String getChainId() { + return chainId; + } + + /** + * @param chainId the chainId to set + */ + public void setChainId(String chainId) { + this.chainId = chainId; + } + + /** + * @return the coverage + */ + public Double getCoverage() { + return coverage; + } + + /** + * @param coverage the coverage to set + */ + public void setCoverage(Double coverage) { + this.coverage = coverage; + } + + /** + * @return the resolution + */ + public Double getResolution() { + return resolution; + } + + /** + * @param resolution the resolution to set + */ + public void setResolution(Double resolution) { + this.resolution = resolution; + } + + /** + * @return the structStart + */ + public Integer getStructStart() { + return structStart; + } + + /** + * @param structStart the structStart to set + */ + public void setStructStart(Integer structStart) { + this.structStart = structStart; + } + + /** + * @return the structEnd + */ + public Integer getStructEnd() { + return structEnd; + } + + /** + * @param structEnd the structEnd to set + */ + public void setStructEnd(Integer structEnd) { + this.structEnd = structEnd; + } + + /** + * @return the unpStart + */ + public Integer getUnpStart() { + return unpStart; + } + + /** + * @param unpStart the unpStart to set + */ + public void setUnpStart(Integer unpStart) { + this.unpStart = unpStart; + } + + /** + * @return the unpEnd + */ + public Integer getUnpEnd() { + return unpEnd; + } + + /** + * @param unpEnd the unpEnd to set + */ + public void setUnpEnd(Integer unpEnd) { + this.unpEnd = unpEnd; + } + + /** + * @return the experimentalMethod + */ + public String getExperimentalMethod() { + return experimentalMethod; + } + + /** + * @param experimentalMethod the experimentalMethod to set + */ + public void setExperimentalMethod(String experimentalMethod) { + this.experimentalMethod = experimentalMethod; + } + + /** + * @return the taxId + */ + public Integer getTaxId() { + return taxId; + } + + /** + * @param taxId the taxId to set + */ + public void setTaxId(Integer taxId) { + this.taxId = taxId; + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "Structure [pdbId=" + pdbId + ", chainId=" + chainId + ", coverage=" + coverage + ", resolution=" + + resolution + ", structStart=" + structStart + ", structEnd=" + structEnd + ", unpStart=" + unpStart + + ", unpEnd=" + unpEnd + ", experimentalMethod=" + experimentalMethod + ", taxId=" + taxId + "]"; + } + + public Map<String, Object> toMap() { + Map<String, Object> result = new HashMap<>(); + + result.put("pdbId", this.pdbId); + result.put("chainId", this.chainId); + result.put("coverage", this.coverage); + result.put("resolution", this.resolution); + result.put("structStart", this.structStart); + result.put("structEnd", this.structEnd); + result.put("unpStart", this.unpStart); + result.put("unpEnd", this.unpEnd); + result.put("experimentalMethod", this.experimentalMethod); + result.put("taxId", this.taxId); + + return result; + } + +} diff --git a/model/src/main/java/lcsb/mapviewer/model/map/species/field/UniprotRecord.java b/model/src/main/java/lcsb/mapviewer/model/map/species/field/UniprotRecord.java new file mode 100644 index 0000000000000000000000000000000000000000..92346cb4f25c4a2e9ed39514efc40b5e7bf4a395 --- /dev/null +++ b/model/src/main/java/lcsb/mapviewer/model/map/species/field/UniprotRecord.java @@ -0,0 +1,181 @@ +package lcsb.mapviewer.model.map.species.field; + +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.Table; + +import org.hibernate.annotations.Cascade; +import org.hibernate.annotations.CascadeType; + +import lcsb.mapviewer.common.exception.NotImplementedException; +import lcsb.mapviewer.model.map.species.Species; + +/** + * This class stores basically only uniprot Id which is used as mapping between + * species and uniprot record. + * + * @author David Hoksza + * + */ + +@Entity +@Table(name = "uniprot_table") +//@org.hibernate.annotations.GenericGenerator(name = "test-increment-strategy", strategy = "increment") +public class UniprotRecord implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 1L; + + + /** + * Unique identifier in the database. + */ + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "iddb", unique = true, nullable = false) + private int id; + + + /** + * ID of the uniprot record + */ + @Column(name = "uniprot_id", nullable = false) + private String uniprotId = ""; + + /** + * Species to which this uniprot record belongs to. + */ + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name = "element_id", nullable = false) + private Species species; + + /** + * List of uniprot records which are associated with this species. + */ + @Cascade({ CascadeType.ALL }) + @OneToMany(fetch = FetchType.EAGER, mappedBy = "uniprot", orphanRemoval = true) + private Set<Structure> structures = new HashSet<>(); + + /** + * Default constructor. + */ + public UniprotRecord() { + } + + /** + * Constructor that initialize object with the data taken from the parameter. + * + * @param ur + * original object from which data is taken + */ + public UniprotRecord(UniprotRecord ur) { + this.id = ur.id; + this.uniprotId = ur.uniprotId; + this.species = ur.species; + } + + /** + * Creates copy of the object. + * + * @return copy of the object. + */ + public UniprotRecord copy() { + if (this.getClass() == UniprotRecord.class) { + return new UniprotRecord(this); + } else { + throw new NotImplementedException("Method copy() should be overriden in class " + this.getClass()); + } + } + + + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "UniprotRecord [id=" + id + ", uniprotId=" + uniprotId + ", species=" + species + ", structures=" + + structures + "]"; + } + + /** + * @return the idModificationResidue + * @see #id + */ + public int getId() { + return id; + } + + /** + * @param id + * the id to set + * @see #id + */ + public void setId(int id) { + this.id = id; + } + + /** + * @return the uniprot id + * @see #uniprotId + */ + public String getUniprotId() { + return uniprotId; + } + + /** + * @param uniprot id + * the id to set + * @see #idModificationResidue + */ + public void setUniprotId(String uniprotId) { + this.uniprotId = uniprotId; + } + + /** + * @param species + * species to which this uniprot record belongs + * @see #species + */ + public void setSpecies(Species species) { + this.species = species; + } + + /** + * @return the species + * @see #species + */ + public Species getSpecies() { + return species; + } + + /** + * @param structures + * set of structures mapped to this uniprot record + * @see #structures + */ + public void setStructures(Set<Structure> structures) { + this.structures = structures; + } + + /** + * @return the structures + * @see #structures + */ + public Set<Structure> getStructures() { + return structures; + } +} diff --git a/model/src/test/java/lcsb/mapviewer/model/map/species/field/AllFieldTests.java b/model/src/test/java/lcsb/mapviewer/model/map/species/field/AllFieldTests.java index 3cc809ba3b47cb74f06e93a74f53eb8efc6e1f70..512ff1dab965e61c18b8a36b9adea44420f8d296 100644 --- a/model/src/test/java/lcsb/mapviewer/model/map/species/field/AllFieldTests.java +++ b/model/src/test/java/lcsb/mapviewer/model/map/species/field/AllFieldTests.java @@ -11,6 +11,8 @@ import org.junit.runners.Suite.SuiteClasses; ModificationResidueTest.class, // PositionToCompartmentTest.class, // RnaRegionTest.class,// + StructureTest.class,// + UniprotRecordTest.class,// }) public class AllFieldTests { diff --git a/model/src/test/java/lcsb/mapviewer/model/map/species/field/StructureTest.java b/model/src/test/java/lcsb/mapviewer/model/map/species/field/StructureTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4e40ae40b28c4069a3f88697afc18f3aa26d2c7c --- /dev/null +++ b/model/src/test/java/lcsb/mapviewer/model/map/species/field/StructureTest.java @@ -0,0 +1,66 @@ +package lcsb.mapviewer.model.map.species.field; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import java.util.HashSet; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + +import lcsb.mapviewer.common.exception.NotImplementedException; + +public class StructureTest { + + @AfterClass + public static void tearDownAfterClass() throws Exception { + } + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testGetters() { + Structure s = new Structure(); + UniprotRecord ur = new UniprotRecord(); + ur.setId(100); + ur.setUniprotId("P29373"); + + int id = 101; + s.setUniprot(ur); + s.setId(id); + + ur.setStructures(new HashSet<Structure>() {private static final long serialVersionUID = 1L; {add(s);} }); + + assertEquals(ur, s.getUniprot()); + assertEquals(id, s.getId()); + assertEquals(s, ur.getStructures().iterator().next()); + } + + @Test + public void testCopy() { + Structure s = new Structure().copy(); + assertNotNull(s); + } + + @Test + public void testInvalidCopy() { + Structure s = Mockito.spy(Structure.class); + try { + s.copy(); + fail("Exception expected"); + } catch (NotImplementedException e) { + + } + } + +} diff --git a/model/src/test/java/lcsb/mapviewer/model/map/species/field/UniprotRecordTest.java b/model/src/test/java/lcsb/mapviewer/model/map/species/field/UniprotRecordTest.java new file mode 100644 index 0000000000000000000000000000000000000000..38460ffb23cccac9c2be4fa8c5d2d995e020e353 --- /dev/null +++ b/model/src/test/java/lcsb/mapviewer/model/map/species/field/UniprotRecordTest.java @@ -0,0 +1,61 @@ +package lcsb.mapviewer.model.map.species.field; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + +import lcsb.mapviewer.common.exception.NotImplementedException; +import lcsb.mapviewer.model.map.species.GenericProtein; +import lcsb.mapviewer.model.map.species.Species; + +public class UniprotRecordTest { + + @AfterClass + public static void tearDownAfterClass() throws Exception { + } + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testGetters() { + UniprotRecord ur = new UniprotRecord(); + Species species = new GenericProtein("id"); + int id = 94; + + ur.setSpecies(species); + ur.setId(id); + + assertEquals(species, ur.getSpecies()); + assertEquals(id, ur.getId()); + } + + @Test + public void testCopy() { + UniprotRecord ur = new UniprotRecord().copy(); + assertNotNull(ur); + } + + @Test + public void testInvalidCopy() { + UniprotRecord ur = Mockito.spy(UniprotRecord.class); + try { + ur.copy(); + fail("Exception expected"); + } catch (NotImplementedException e) { + + } + } + +} diff --git a/pathvisio/.classpath b/pathvisio/.classpath index 16c89cc13733da44a37aa705233e6704c91106ef..273e16e17b0c83eed37e90c336486772d19626b4 100644 --- a/pathvisio/.classpath +++ b/pathvisio/.classpath @@ -6,11 +6,6 @@ <attribute name="maven.pomderived" value="true"/> </attributes> </classpathentry> - <classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"> - <attributes> - <attribute name="maven.pomderived" value="true"/> - </attributes> - </classpathentry> <classpathentry kind="src" output="target/test-classes" path="src/test/java"> <attributes> <attribute name="optional" value="true"/> diff --git a/persist/src/db/11.0.1/fix_db_20170713.sql b/persist/src/db/11.0.1/fix_db_20170713.sql new file mode 100644 index 0000000000000000000000000000000000000000..c0f3e49c8e044a0962591e380b566bfca41b1e56 --- /dev/null +++ b/persist/src/db/11.0.1/fix_db_20170713.sql @@ -0,0 +1,2 @@ +DELETE FROM cache_type WHERE classname = 'lcsb.mapviewer.annotation.services.annotators.PdbAnnotator' +INSERT INTO cache_type(validity, classname) VALUES (365, 'lcsb.mapviewer.annotation.services.annotators.PdbAnnotator') \ No newline at end of file diff --git a/persist/src/db/11.0.1/fix_db_20170720.sql b/persist/src/db/11.0.1/fix_db_20170720.sql new file mode 100644 index 0000000000000000000000000000000000000000..396aaa49fa82e2d01796a3174595d577a79eba2e --- /dev/null +++ b/persist/src/db/11.0.1/fix_db_20170720.sql @@ -0,0 +1,62 @@ +CREATE SEQUENCE uniprot_table_iddb_seq + INCREMENT 1 + MINVALUE 1 + MAXVALUE 9223372036854775807 + START 1 + CACHE 1; + +-- 1:N mapping between element and its uniprot mappings, each of which is then used to map (PDB) structures to it +CREATE TABLE uniprot_table +( + iddb integer NOT NULL DEFAULT nextval('uniprot_table_iddb_seq'::regclass), + element_id integer NOT NULL, + uniprot_id character varying(255) NOT NULL, + CONSTRAINT uniprot_pkey PRIMARY KEY (iddb), + CONSTRAINT uniprot_element_fk FOREIGN KEY (element_id) + REFERENCES public.element_table (iddb) MATCH SIMPLE + ON UPDATE CASCADE ON DELETE CASCADE +); + + +CREATE SEQUENCE structure_table_iddb_seq + INCREMENT 1 + MINVALUE 1 + MAXVALUE 9223372036854775807 + START 1 + CACHE 1; + +/* +based on https://www.ebi.ac.uk/pdbe/api/doc/sifts.html best_structures API + + pdb_id: the PDB ID which maps to the UniProt ID + chain_id: the specific chain of the PDB which maps to the UniProt ID + coverage: the percent coverage of the entire UniProt sequence + resolution: the resolution of the structure + start: the structure residue number which maps to the start of the mapped sequence + end: the structure residue number which maps to the end of the mapped sequence + unp_start: the sequence residue number which maps to the structure start + unp_end: the sequence residue number which maps to the structure end + experimental_method: type of experiment used to determine structure + tax_id: taxonomic ID of the protein's original organism +*/ +CREATE TABLE structure_table +( + iddb integer NOT NULL DEFAULT nextval('structure_table_iddb_seq'::regclass), + uniprot_id integer NOT NULL, + pdb_id character varying(255) NOT NULL, --should be character(4), but to be on the safe side... + chain_id character varying(255) NOT NULL, --should be char(1), but for example 5T0C has has chains AK and BK + struct_start integer, + struct_end integer, + unp_start integer, + unp_end integer, + experimental_method character varying(255), + coverage double precision, + resolution double precision, + tax_id integer, + CONSTRAINT structure_pkey PRIMARY KEY (iddb), + CONSTRAINT structure_uniprot_fk FOREIGN KEY (uniprot_id) + REFERENCES public.uniprot_table (iddb) MATCH SIMPLE + ON UPDATE CASCADE ON DELETE CASCADE +); + + diff --git a/persist/src/main/resources/applicationContext-persist.xml b/persist/src/main/resources/applicationContext-persist.xml index b459702a7a5076281cd6cd5ca476dbb3d2bcc3cf..329bbf4c8b2cf96d197b95e0115906d4f964e3e9 100644 --- a/persist/src/main/resources/applicationContext-persist.xml +++ b/persist/src/main/resources/applicationContext-persist.xml @@ -171,6 +171,8 @@ <value>lcsb.mapviewer.model.map.species.field.AntisenseRnaRegion</value> <value>lcsb.mapviewer.model.map.species.field.ModificationResidue</value> <value>lcsb.mapviewer.model.map.species.field.RnaRegion</value> + <value>lcsb.mapviewer.model.map.species.field.UniprotRecord</value> + <value>lcsb.mapviewer.model.map.species.field.Structure</value> <value>lcsb.mapviewer.model.map.layout.graphics.Layer</value> <value>lcsb.mapviewer.model.map.layout.graphics.LayerText</value> @@ -184,7 +186,7 @@ <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop> - <!--<prop key="hibernate.show_sql">true</prop>--> + <prop key="hibernate.show_sql">false</prop> <!--<prop key="hibernate.current_session_context_class">thread</prop>--> </props> </property> diff --git a/quadTrees/.classpath b/quadTrees/.classpath index fc5f96c9feacd9cd902963cc1ed3f89769603a21..1b6e7590699faad6d494ab35ceefba4610d6cdf6 100644 --- a/quadTrees/.classpath +++ b/quadTrees/.classpath @@ -6,11 +6,6 @@ <attribute name="maven.pomderived" value="true"/> </attributes> </classpathentry> - <classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"> - <attributes> - <attribute name="maven.pomderived" value="true"/> - </attributes> - </classpathentry> <classpathentry kind="src" output="target/test-classes" path="src/test/java"> <attributes> <attribute name="optional" value="true"/> diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/bioEntities/elements/ElementsRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/bioEntities/elements/ElementsRestImpl.java index 9348dc68691f9a30029e51ad2e5a5934b8459939..4bfea6bdc2909deb7406647d799165f4a85a139c 100644 --- a/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/bioEntities/elements/ElementsRestImpl.java +++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/bioEntities/elements/ElementsRestImpl.java @@ -20,6 +20,8 @@ import lcsb.mapviewer.model.map.species.Protein; import lcsb.mapviewer.model.map.species.Rna; import lcsb.mapviewer.model.map.species.Species; import lcsb.mapviewer.model.map.species.field.ElementModification; +import lcsb.mapviewer.model.map.species.field.Structure; +import lcsb.mapviewer.model.map.species.field.UniprotRecord; import lcsb.mapviewer.services.SecurityException; import lcsb.mapviewer.services.UserAccessException; import lcsb.mapviewer.services.view.OverviewImageViewFactory; @@ -170,8 +172,9 @@ public class ElementsRestImpl extends BaseRestImpl { value = element.getSubmodel().getSubmodel().getId(); } } else if (column.equals("bounds")) { - value = createBounds(element.getX(), element.getY(), element.getWidth(), element.getHeight()); - } else { + value = createBounds(element.getX(), element.getY(), element.getWidth(), element.getHeight()); + } + else { value = "Unknown column"; } result.put(string, value); @@ -181,8 +184,9 @@ public class ElementsRestImpl extends BaseRestImpl { protected Map<String, Object> getOthersForElement(Element element) { Map<String, Object> result = new HashMap<>(); - List<Map<String, Object>> modifications = new ArrayList<>(); + List<Map<String, Object>> modifications = new ArrayList<>(); String structuralState = null; + Map<String, Object> structures = new HashMap<>(); if (element instanceof Protein) { Protein protein = ((Protein) element); modifications = getModifications(protein.getModificationResidues()); @@ -195,9 +199,13 @@ public class ElementsRestImpl extends BaseRestImpl { AntisenseRna antisenseRna = ((AntisenseRna) element); modifications = getModifications(((AntisenseRna) element).getRegions()); structuralState = antisenseRna.getState(); + } + if (element instanceof Species) { + structures = getStructures(((Species)element).getUniprots()); } result.put("modifications", modifications); result.put("structuralState", structuralState); + result.put("structures", structures); return result; } @@ -215,6 +223,18 @@ public class ElementsRestImpl extends BaseRestImpl { } return result; } + + private Map<String, Object> getStructures(Set<UniprotRecord> uniprots) { + Map<String, Object> result = new HashMap<>(); + for (UniprotRecord uniprotRec : uniprots) { + Set<Object> structs = new HashSet<>(); + for (Structure struct: uniprotRec.getStructures()) { + structs.add(struct.toMap()); + } + result.put(uniprotRec.getUniprotId(), structs); + } + return result; + } private Map<String, Object> createBounds(Double x, Double y, Double width, Double height) { Map<String, Object> result = new HashMap<>(); diff --git a/rest-api/src/test/java/lcsb/mapviewer/api/projects/models/bioEntities/elements/ElementRestImplTest.java b/rest-api/src/test/java/lcsb/mapviewer/api/projects/models/bioEntities/elements/ElementRestImplTest.java index 19cc3a66c98d2cc2f09e10d94d8709cf6831b841..5e9ac8b9f8f0e4e1e4a24acb50d8d0e0ba538c7d 100644 --- a/rest-api/src/test/java/lcsb/mapviewer/api/projects/models/bioEntities/elements/ElementRestImplTest.java +++ b/rest-api/src/test/java/lcsb/mapviewer/api/projects/models/bioEntities/elements/ElementRestImplTest.java @@ -20,10 +20,12 @@ import org.springframework.beans.factory.annotation.Autowired; import com.fasterxml.jackson.databind.ObjectMapper; +import lcsb.mapviewer.annotation.services.annotators.PdbAnnotator; import lcsb.mapviewer.api.RestTestFunctions; import lcsb.mapviewer.model.map.model.Model; import lcsb.mapviewer.model.map.species.AntisenseRna; 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.field.AntisenseRnaRegion; import lcsb.mapviewer.model.map.species.field.ModificationResidue; @@ -36,6 +38,9 @@ public class ElementRestImplTest extends RestTestFunctions { @Autowired ElementsRestImpl _elementsRestImpl; + + @Autowired + PdbAnnotator pdbAnnotator; ObjectMapper mapper = new ObjectMapper(); @@ -54,7 +59,7 @@ public class ElementRestImplTest extends RestTestFunctions { @Test public void testGetElementsProcessAllColumns() throws Exception { try { - ElementsRestImpl projectRest = createMockElementRest("testFiles/model/sample.xml"); + ElementsRestImpl projectRest = createMockElementRest("testFiles/model/sample.xml", true); List<Map<String, Object>> result = projectRest.getElements("sample", "", "", "*", token.getId(), "", "", ""); for (Map<String, Object> element : result) { for (String paramName : element.keySet()) { @@ -79,8 +84,8 @@ public class ElementRestImplTest extends RestTestFunctions { public void testGetElementsByType() throws Exception { try { String proteinType = new GenericProtein("1").getStringType(); - ElementsRestImpl elementRest = createMockElementRest("testFiles/model/sample.xml"); - List<Map<String, Object>> result = elementRest.getElements("sample", "", "", "*", token.getId(), proteinType, "", ""); + ElementsRestImpl projectRest = createMockElementRest("testFiles/model/sample.xml", false); + List<Map<String, Object>> result = projectRest.getElements("sample", "", "", "*", token.getId(), proteinType, "", ""); assertEquals(12, result.size()); } catch (Exception e) { @@ -169,13 +174,25 @@ public class ElementRestImplTest extends RestTestFunctions { throw e; } } - + private ElementsRestImpl createMockElementRest(String string) throws Exception { + return createMockElementRest(string, false); + } + + private ElementsRestImpl createMockElementRest(String string, Boolean annotate) throws Exception { Model model = super.getModelForFile(string, true); + if (annotate) { + try { + Protein protein = new GenericProtein("SNCA"); + protein.setElementId("SNCA"); + pdbAnnotator.annotateElement(protein); + model.addElement(protein); + } catch (Exception e) { + } + } IModelService mockModelService = Mockito.mock(IModelService.class); Mockito.when(mockModelService.getLastModelByProjectId(anyString(), any())).thenReturn(model); - _elementsRestImpl.setModelService(mockModelService); + _elementsRestImpl.setModelService(mockModelService); return _elementsRestImpl; } - } diff --git a/web/src/main/webapp/WEB-INF/security-context.xml b/web/src/main/webapp/WEB-INF/security-context.xml index e152ccd84870449b60082b2beddd3014c3e0c54a..f294a895dd74770d90d5065fdb99f0879e920906 100644 --- a/web/src/main/webapp/WEB-INF/security-context.xml +++ b/web/src/main/webapp/WEB-INF/security-context.xml @@ -33,6 +33,8 @@ <security:intercept-url pattern="/fonts/**" access="permitAll"/> + <security:intercept-url pattern="/plugins/**" access="permitAll"/> + <security:intercept-url pattern="/**" access="isAuthenticated()"/> <security:logout logout-url="/j_spring_security_logout" logout-success-url="/login.xhtml" invalidate-session="true"/>