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"/>