Commit 54a99a17 authored by David Hoksza's avatar David Hoksza
Browse files

Passing annotator parameters from client to server

parent dd7c78a0
......@@ -363,9 +363,7 @@ public class ModelAnnotator {
for (ElementAnnotator elementAnnotator : list) {
try {
List<UserAnnotatorsParam> params = annotatorsParams.get(elementAnnotator.getClass());
logger.debug("params");
logger.debug(params);
List<UserAnnotatorsParam> params = annotatorsParams.get(elementAnnotator.getClass());
if (params != null) {
elementAnnotator.annotateElement(element, params);
} else {
......
......@@ -4,6 +4,7 @@ package lcsb.mapviewer.annotation.services.annotators;
import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
......@@ -27,6 +28,7 @@ import lcsb.mapviewer.model.map.species.GenericProtein;
import lcsb.mapviewer.model.map.species.Protein;
import lcsb.mapviewer.model.map.species.Rna;
import lcsb.mapviewer.model.map.species.Species;
import lcsb.mapviewer.model.user.UserAnnotatorsParam;
/**
* This is a class that implements KEGG annotator which extract from KEGG
......@@ -48,6 +50,11 @@ public class KeggAnnotator extends ElementAnnotator implements IExternalService
*/
private Pattern pubmedMatcher = Pattern.compile("\\[PMID:(\\d+)\\]");
/**
* Pattern used for finding ATH orghologs in KEGG GENE sectionpage.
*/
private Pattern athOrthologMatcher = Pattern.compile(" *ATH: (.*)");
/**
* Service used for annotation of entities using {@link MiriamType#TAIR_LOCUS TAIR}.
......@@ -73,14 +80,6 @@ public class KeggAnnotator extends ElementAnnotator implements IExternalService
+ " (GENE section in the KEGG enzyme record) should be imported."
+ " Currently ATH (Arabidopsis Thaliana) is supported.");
this.addParameterDefinition(paramDef);
this.addParameterDefinition(new AnnotatorParamDefinition("test string1", String.class, "test string1 comment"));
this.addParameterDefinition(new AnnotatorParamDefinition("test int1", Integer.class, "int1 comment"));
this.addParameterDefinition(new AnnotatorParamDefinition("test bool1", Boolean.class, "boolean comment"));
this.addParameterDefinition(new AnnotatorParamDefinition("test bool2", Boolean.class, "boolean comment 2"));
this.addParameterDefinition(new AnnotatorParamDefinition("test int2", Integer.class, "int2 comment"));
this.addParameterDefinition(new AnnotatorParamDefinition("test int3", Integer.class, "int3 comment"));
this.addParameterDefinition(new AnnotatorParamDefinition("test string2", String.class, "test string2 comment"));
}
@Override
......@@ -122,61 +121,66 @@ public class KeggAnnotator extends ElementAnnotator implements IExternalService
@Override
public void annotateElement(BioEntity object) throws AnnotatorException {
if (isAnnotatable(object)) {
public void annotateElement(BioEntity object, List<UserAnnotatorsParam> params) throws AnnotatorException {
if (!isAnnotatable(object)) { return; }
MiriamData mdTair = null;
for (MiriamData md : object.getMiriamData()) {
Class<?> annotator = md.getAnnotator();
if (annotator == this.getClass()) {
//this annotator was already used
return;
}
else if (md.getDataType().equals(MiriamType.TAIR_LOCUS) &&
(annotator == null ) ) {
mdTair = md;
}
MiriamData mdTair = null;
for (MiriamData md : object.getMiriamData()) {
Class<?> annotator = md.getAnnotator();
if (annotator == this.getClass()) {
//this annotator was already used
return;
}
if (mdTair != null) tairAnnotator.annotateElement(object);
MiriamData mdUniprot = null;
for (MiriamData md : object.getMiriamData()) {
if (md.getDataType().equals(MiriamType.UNIPROT) ) {
mdUniprot = md;
}
else if (md.getDataType().equals(MiriamType.TAIR_LOCUS) &&
(annotator == null ) ) {
mdTair = md;
}
}
if (mdTair != null) tairAnnotator.annotateElement(object);
MiriamData mdUniprot = null;
for (MiriamData md : object.getMiriamData()) {
if (md.getDataType().equals(MiriamType.UNIPROT) ) {
mdUniprot = md;
}
if (mdUniprot != null) uniprotAnnotator.annotateElement(object);
Set<String> ecs = new HashSet<String>();
for (MiriamData md : object.getMiriamData()) {
if (md.getDataType().equals(MiriamType.EC)) {
ecs.add(md.getResource());
}
}
if (mdUniprot != null) uniprotAnnotator.annotateElement(object);
Set<String> ecs = new HashSet<String>();
for (MiriamData md : object.getMiriamData()) {
if (md.getDataType().equals(MiriamType.EC)) {
ecs.add(md.getResource());
}
}
if (ecs.size() == 0) {
return;
}
//annotate from KEGG
Set<MiriamData> annotations = new HashSet<MiriamData>();
for (String ec: ecs) {
if (ecs.size() == 0) {
return;
}
//annotate from KEGG
Set<MiriamData> annotations = new HashSet<MiriamData>();
for (String ec: ecs) {
String accessUrl = getKeggUrl(ec);
try {
String pageContent = getWebPageContent(accessUrl);
annotations.addAll(parseKegg(pageContent));
} catch (WrongResponseCodeIOException exception) {
logger.warn("Cannot find kegg data for id: " + ec);
} catch (IOException exception) {
throw new AnnotatorException(exception);
}
String accessUrl = getKeggUrl(ec);
try {
String pageContent = getWebPageContent(accessUrl);
annotations.addAll(parseKegg(pageContent, params));
} catch (WrongResponseCodeIOException exception) {
logger.warn("Cannot find kegg data for id: " + ec);
} catch (IOException exception) {
throw new AnnotatorException(exception);
}
object.addMiriamData(annotations);
}
}
object.addMiriamData(annotations);
}
@Override
public void annotateElement(BioEntity object) throws AnnotatorException {
this.annotateElement(object, null);
}
/**
......@@ -196,9 +200,16 @@ public class KeggAnnotator extends ElementAnnotator implements IExternalService
*
* @param pageContent
* Kegg page
* @return {@link MiriamType#PUBMED}s found on the page
* @param params
* List of {@link UserAnnotatorsParam} to be used
* for parameterization. Should contain only at most
* one record with space separated KEGG organisms names.
* If the value has not been set by the user,
* null will be passed.
* @return
* {@link MiriamType#PUBMED}s found on the page
*/
private Collection<MiriamData> parseKegg(String pageContent) {
private Collection<MiriamData> parseKegg(String pageContent, List<UserAnnotatorsParam> params) {
//Retrieve Pubmeds
Collection<MiriamData> result = new HashSet<MiriamData>();
......@@ -208,6 +219,23 @@ public class KeggAnnotator extends ElementAnnotator implements IExternalService
}
//Retrieve homologous organisms based on parameterization
if (params != null) {
String[] keggOrgnismCodes = params.get(0).getParamValue().trim().split(" +");
for (String code: keggOrgnismCodes) {
if (code.toUpperCase() != "ATH") {
logger.warn("KEGG annotator currently supports only ATH");
} else {
m = athOrthologMatcher.matcher(pageContent);
if (m.find()) {
String[] tairCodes = m.group(1).trim().split(" ");
for (String tairCode: tairCodes) {
tairCode = tairCode.split("\\(")[0]; //some codes are in the form AT1G08510(FATB)
result.add(createMiriamData(MiriamType.TAIR_LOCUS, tairCode));
}
}
}
}
}
return result;
}
......
......@@ -2,23 +2,15 @@ package lcsb.mapviewer.annotation.services.annotators;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.when;
import java.util.Collection;
import java.io.IOException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import lcsb.mapviewer.annotation.AnnotationTestFunctions;
import lcsb.mapviewer.annotation.cache.WebPageDownloader;
import lcsb.mapviewer.annotation.services.ExternalServiceStatusType;
import lcsb.mapviewer.common.exception.InvalidArgumentException;
import lcsb.mapviewer.model.map.MiriamData;
......
......@@ -11,6 +11,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.junit.After;
......@@ -27,6 +28,7 @@ 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.user.UserAnnotatorsParam;
public class KeggAnnotatorTest extends AnnotationTestFunctions {
......@@ -71,7 +73,7 @@ public class KeggAnnotatorTest extends AnnotationTestFunctions {
@Test
public void testAnnotateFromUniprot() throws Exception {
public void testAnnotateFromUniprotWithoutParams() throws Exception {
try {
Species protein = new GenericProtein("id");
......@@ -89,6 +91,82 @@ public class KeggAnnotatorTest extends AnnotationTestFunctions {
}
}
@Test
public void testAnnotateFromUniprotWithParams() throws Exception {
try {
Species protein = new GenericProtein("id");
protein.setName("bla");
protein.addMiriamData(new MiriamData(MiriamType.UNIPROT, "Q42561"));
UserAnnotatorsParam ap = new UserAnnotatorsParam(String.class, "KEGG organism identifier", "ATH");
List<UserAnnotatorsParam> aps = new ArrayList<>();
aps.add(ap);
keggAnnotator.annotateElement(protein, aps);
int cntTairs = 0;
for (MiriamData md : protein.getMiriamData()) {
if (md.getDataType().equals(MiriamType.TAIR_LOCUS)) {
cntTairs++;
}
}
assertTrue("Invalid number of TAIR annotators from KEGG", cntTairs == 3);
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Test
public void testAnnotateFromUniprotWithWrongParams1() throws Exception {
try {
Species protein = new GenericProtein("id");
protein.setName("bla");
protein.addMiriamData(new MiriamData(MiriamType.UNIPROT, "Q42561"));
UserAnnotatorsParam ap = new UserAnnotatorsParam(String.class, "XXX", "XXX");
List<UserAnnotatorsParam> aps = new ArrayList<>();
aps.add(ap);
keggAnnotator.annotateElement(protein, aps);
assertEquals("There should be warning about unsupported parameter", 1, getWarnings().size());
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Test
public void testAnnotateFromUniprotWithWrongParams2() throws Exception {
try {
Species protein = new GenericProtein("id");
protein.setName("bla");
protein.addMiriamData(new MiriamData(MiriamType.UNIPROT, "Q42561"));
List<UserAnnotatorsParam> aps = new ArrayList<>();
aps.add(new UserAnnotatorsParam(String.class, "KEGG organism identifier", "ATH XXX"));
keggAnnotator.annotateElement(protein, aps);
int cntTairs = 0;
for (MiriamData md : protein.getMiriamData()) {
if (md.getDataType().equals(MiriamType.TAIR_LOCUS)) {
cntTairs++;
}
}
assertTrue("Invalid number of TAIR annotators from KEGG", cntTairs == 3);
assertEquals("There should be warning about unsupported parameter", 1, getWarnings().size());
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Test
public void testAnnotateFromEc() throws Exception {
try {
......@@ -101,7 +179,6 @@ public class KeggAnnotatorTest extends AnnotationTestFunctions {
Evaluate_3_1_2_14(protein);
} catch (Exception e) {
e.printStackTrace();
throw e;
......
......@@ -65,7 +65,8 @@ function onChangeParameterValue(element, user){
var annotatorsParams = {};
annotatorsParams[annotatorClassName] = {};
annotatorsParams[annotatorClassName][name] = element.value;
if (element.type == 'checkbox') annotatorsParams[annotatorClassName][name] = element.checked.toString();
else annotatorsParams[annotatorClassName][name] = element.value;
data.setAnnotatorsParameters(annotatorsParams);
return ServerConnector.updateUserPreferences({user: user, preferences: data}).then(null, GuiConnector.alert);
......@@ -95,6 +96,7 @@ ChooseAnnotatorsDialog.prototype.setElementType = function (elementType) {
var selectedAnnotators = user.getPreferences().getElementAnnotators(elementType.className);
var existingAnnotatorsParameters = user.getPreferences().getAnnotatorsParameters();
for (var i = 0; i < annotators.length; i++) {
var annotator = annotators[i];
var selected = false;
......@@ -157,12 +159,14 @@ ChooseAnnotatorsDialog.prototype.setElementType = function (elementType) {
inputType: "number",
onchange: function(){return onChangeParameterValue(this, user);}
});
if (existingParamValue) paramValue.value = existingParamValue;
} else if (param.type.indexOf("Boolean") >= 0) {
paramValue = Functions.createElement({
type: "input",
inputType: "checkbox",
onchange: function(){return onChangeParameterValue(this, user);}
});
paramValue.checked = (existingParamValue && existingParamValue === 'true');
} else {
throw new InvalidAlgorithmError("Unknown annotator parameter type");
}
......
......@@ -248,17 +248,12 @@ public class UserAnnotationSchema implements Serializable {
if (params.getAnnotatorClassName().equals(ap.getAnnotatorClassName()) &&
params.getParamName().equals(ap.getParamName())) {
this.annotatorsParams.get(i).setParamValue(ap.getParamValue());
} else {
ap.setAnnotationSchema(this);
this.annotatorsParams.add(ap);
return;
}
}
if (this.annotatorsParams.size() == 0) {
ap.setAnnotationSchema(this);
this.annotatorsParams.add(ap);
}
ap.setAnnotationSchema(this);
this.annotatorsParams.add(ap);
}
/**
......
......@@ -1469,7 +1469,16 @@ public class ProjectService implements IProjectService {
dbUser.setAnnotationSchema(annotationSchema);
}
return annotationSchema.getAnnotatorsParams();
/*
* Hibernate lazy loads collections so each element needs to be accessed
* to be loaded now or otherwise the data might not be available
* when accessed because the session might not be available at that time.
*/
List<UserAnnotatorsParam> aps = new ArrayList<>();
for (UserAnnotatorsParam ap: annotationSchema.getAnnotatorsParams()){
aps.add(ap);
}
return aps;
}
/**
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment