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 index 3995f04896ec4b9c783553e01fa4d94d80c87241..fc3b02a9bf5ce04ce88fde8157feab4862d33890 100644 --- a/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/PdbAnnotator.java +++ b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/PdbAnnotator.java @@ -24,7 +24,10 @@ 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; @@ -82,10 +85,10 @@ public class PdbAnnotator extends ElementAnnotator implements IExternalService { this.setCache(null); try { - Collection<MiriamData> pdbMiriamData = uniProtToPdb(new MiriamData(MiriamType.UNIPROT, "P29373")); + Collection<Structure> structures = uniProtToPdb(new MiriamData(MiriamType.UNIPROT, "P29373")); - if (pdbMiriamData.size() > 0){ - if (pdbMiriamData.iterator().next().getResource() != null) { //TODO - is this id? + if (structures.size() > 0){ + if (structures.iterator().next().getPdbId() != null) { //TODO - is this id? status.setStatus(ExternalServiceStatusType.OK); } else { status.setStatus(ExternalServiceStatusType.CHANGED); @@ -102,48 +105,72 @@ public class PdbAnnotator extends ElementAnnotator implements IExternalService { return status; } - public MiriamData getUnitProt(BioEntity bioEntity) { + public Set<MiriamData> getUnitProts(BioEntity bioEntity) { + HashSet<MiriamData> mds = new HashSet<MiriamData>(); for (MiriamData md : bioEntity.getMiriamData()) { if (md.getDataType().equals(MiriamType.UNIPROT)) { - return md; + mds.add(md); } } - return null; + return mds.size() > 0 ? mds : null; } @Override public void annotateElement(BioEntity bioEntity) throws AnnotatorException { if (isAnnotatable(bioEntity)) { - MiriamData md = getUnitProt(bioEntity); - if (md == null) { + Set<MiriamData> mds = getUnitProts(bioEntity); + if (mds == null) { uniprotAnnotator.annotateElement(bioEntity); - md = getUnitProt(bioEntity); + mds = getUnitProts(bioEntity); } /*If no UniProt ID was found, try to search HGNC which then searches UNIPROT * based on the gene name. */ - if (md == null) { + if (mds == null) { hgncAnnotator.annotateElement(bioEntity); - md = getUnitProt(bioEntity); + mds = getUnitProts(bioEntity); } - if (md == null) { + if (mds == null) { return; } - try { - Set<MiriamData> annotations = (Set<MiriamData>)uniProtToPdb(md); - if (annotations.size() == 0) { - logger.warn(elementUtils.getElementTag(bioEntity) + " No PDB mapping for UniProt ID: " + md.getResource()); - } else { - bioEntity.addMiriamData(annotations); - } - } catch (WrongResponseCodeIOException exception) { - logger.warn("Response error when trying to find PDB mapping for UniProt ID: " + md.getResource()); - } catch (IOException exception) { - throw new AnnotatorException(exception); + 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 annotations do + //not include 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("Response error when trying to find PDB mapping for UniProt ID: " + md.getResource()); + } catch (IOException exception) { + throw new AnnotatorException(exception); + } + } + } } @@ -166,8 +193,8 @@ public class PdbAnnotator extends ElementAnnotator implements IExternalService { * JSON file with the UniProt to PDB mapping * @return set of PDB identifiers found on the webpage */ - private Collection<MiriamData> processMappingData(String pageContentJson) { - Collection<MiriamData> result = new HashSet<MiriamData>(); + 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); @@ -175,7 +202,8 @@ public class PdbAnnotator extends ElementAnnotator implements IExternalService { for (String key : m.keySet()){ for(PdbBestMappingEntry e : m.get(key)) { if (e != null){ - result.add(new MiriamData(MiriamType.PDB, e.pdb_id)); + result.add(e.convertToStructure()); + //result.add(new MiriamData(MiriamType.PDB, e.pdb_id)); } } } @@ -231,7 +259,7 @@ public class PdbAnnotator extends ElementAnnotator implements IExternalService { * @return JSON String with mapping. * thrown when there is a problem with accessing external database */ - public Collection<MiriamData> uniProtToPdb(MiriamData uniprot) throws IOException /*throws UniprotSearchException*/ { + public Collection<Structure> uniProtToPdb(MiriamData uniprot) throws IOException { if (uniprot == null) { return null; } @@ -241,18 +269,9 @@ public class PdbAnnotator extends ElementAnnotator implements IExternalService { } String accessUrl = getPdbMappingUrl(uniprot.getResource()); -// try { - String json = getWebPageContent(accessUrl); - if (!isJson(json)) { - return null; - } else { - return processMappingData(json); - } - -// } catch (IOException e) { -// throw new UniprotSearchException("Problem with accessing mapping data: ", e); //TODO -// } - + String json = getWebPageContent(accessUrl); + + return isJson(json) ? processMappingData(json) : null; } @Override 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 index 00f63e8ddd84ed391415351cf9cbd8126ee9b691..c3cf1c9b2c2568050b2a702af2ed6cd3a2db7abe 100644 --- a/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/PdbBestMappingEntry.java +++ b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/PdbBestMappingEntry.java @@ -1,21 +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 end; +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/test/java/lcsb/mapviewer/annotation/services/annotators/PdbAnnotatorTest.java b/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/PdbAnnotatorTest.java index c417885b45e2ffee7355fa46d6a6c1638808ec21..a5af588359ec3bffbbb354fa4c328f38054a6041 100644 --- a/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/PdbAnnotatorTest.java +++ b/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/PdbAnnotatorTest.java @@ -1,10 +1,13 @@ 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; @@ -18,6 +21,8 @@ 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 { @@ -38,8 +43,9 @@ public class PdbAnnotatorTest extends AnnotationTestFunctions { @Test public void testAnnotate1() throws Exception { try { + String uniprotId = "P29373"; Species protein = new GenericProtein("id"); - protein.setName("P29373"); + protein.setName(uniprotId); /* One needs to have the UniProt ID first. * This tests simulates situation when the Uniprot annotator * is called first. @@ -60,7 +66,20 @@ public class PdbAnnotatorTest extends AnnotationTestFunctions { } } assertTrue("No PDB annotation extracted from pdb annotator", pdb); - + + Set<UniprotRecord> urs = protein.getUniprots(); + assertTrue(urs.size() > 0); + UniprotRecord ur = null; + for (UniprotRecord ur1 : urs) { + if (ur1.getUniprotId() == uniprotId) { + ur = ur1; + } + } + assertNotNull(ur); + Set<Structure> ss = ur.getStructures(); + assertNotNull(ss); + assertTrue(ss.size() > 0); + assertTrue(ss.iterator().next().getUniprot() == ur); } catch (Exception e) { e.printStackTrace(); throw e; @@ -197,7 +216,7 @@ public class PdbAnnotatorTest extends AnnotationTestFunctions { WebPageDownloader downloader = pdbAnnotator.getWebPageDownloader(); try { WebPageDownloader mockDownloader = Mockito.mock(WebPageDownloader.class); - when(mockDownloader.getFromNetwork(anyString())).thenReturn(""); + when(mockDownloader.getFromNetwork(anyString(), anyString(), anyString())).thenReturn(""); pdbAnnotator.setWebPageDownloader(mockDownloader); assertEquals(ExternalServiceStatusType.DOWN, pdbAnnotator.getServiceStatus().getStatus()); } catch (Exception e) { @@ -213,7 +232,7 @@ public class PdbAnnotatorTest extends AnnotationTestFunctions { WebPageDownloader downloader = pdbAnnotator.getWebPageDownloader(); try { WebPageDownloader mockDownloader = Mockito.mock(WebPageDownloader.class); - when(mockDownloader.getFromNetwork(anyString())).thenReturn("{\"P29373\": [{\"xxx\": 140}]}"); + when(mockDownloader.getFromNetwork(anyString(), anyString(), anyString())).thenReturn("{\"P29373\": [{\"xxx\": 140}]}"); pdbAnnotator.setWebPageDownloader(mockDownloader); assertEquals(ExternalServiceStatusType.CHANGED, pdbAnnotator.getServiceStatus().getStatus()); } catch (Exception e) { @@ -234,7 +253,7 @@ public class PdbAnnotatorTest extends AnnotationTestFunctions { int cntAnnotations1 = protein.getMiriamData().size(); WebPageDownloader mockDownloader = Mockito.mock(WebPageDownloader.class); - when(mockDownloader.getFromNetwork(anyString())).thenReturn("\"P29373\": [{\"xxx\": 140}]}"); + when(mockDownloader.getFromNetwork(anyString(), anyString(), anyString())).thenReturn("\"P29373\": [{\"xxx\": 140}]}"); pdbAnnotator.setWebPageDownloader(mockDownloader); pdbAnnotator.annotateElement(protein); 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..5dbe0b9053b6dfb40b3dd86edd27ba9a24be444a --- /dev/null +++ b/model/src/main/java/lcsb/mapviewer/model/map/species/field/Structure.java @@ -0,0 +1,344 @@ +package lcsb.mapviewer.model.map.species.field; + +import java.io.Serializable; + +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 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 + * 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 + * + * @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 + "]"; + } + + + +} 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..ddcce641700e7967a43fdf4da7fa80dc625ecdce --- /dev/null +++ b/model/src/test/java/lcsb/mapviewer/model/map/species/field/StructureTest.java @@ -0,0 +1,68 @@ +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; +import lcsb.mapviewer.model.map.species.GenericProtein; +import lcsb.mapviewer.model.map.species.Species; + +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/persist/src/db/11.0.1/fix_db_20171307.sql b/persist/src/db/11.0.1/fix_db_20170713.sql similarity index 99% rename from persist/src/db/11.0.1/fix_db_20171307.sql rename to persist/src/db/11.0.1/fix_db_20170713.sql index 94523a2c4d08e87d3b5af2767a02ebd675043bea..c0f3e49c8e044a0962591e380b566bfca41b1e56 100644 --- a/persist/src/db/11.0.1/fix_db_20171307.sql +++ b/persist/src/db/11.0.1/fix_db_20170713.sql @@ -1,2 +1,2 @@ -DELETE FROM cache_type WHERE classname = 'lcsb.mapviewer.annotation.services.annotators.PdbAnnotator' +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..71cf63626c3ad465f1682894f40f7fd5a24d6361 --- /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(1)NOT NULL, + 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 896e204ca1ca0b1a64eb6b4ba1dc01905591c689..896a8cafaf6bdb15ae8467358047a8a7ea58dede 100644 --- a/persist/src/main/resources/applicationContext-persist.xml +++ b/persist/src/main/resources/applicationContext-persist.xml @@ -185,6 +185,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>