package org.nextprot.api.core.utils.annot; import org.junit.Assert; import org.junit.Test; import org.nextprot.api.commons.constants.AnnotationCategory; import org.nextprot.api.commons.constants.PropertyApiModel; import org.nextprot.api.core.domain.BioObject; import org.nextprot.api.core.domain.Entry; import org.nextprot.api.core.domain.Isoform; import org.nextprot.api.core.domain.annotation.Annotation; import org.nextprot.api.core.domain.annotation.AnnotationEvidence; import org.nextprot.api.core.domain.annotation.AnnotationIsoformSpecificity; import org.nextprot.api.core.domain.annotation.AnnotationProperty; import org.nextprot.api.core.service.AnnotationService; import org.nextprot.api.core.service.EntryBuilderService; import org.nextprot.api.core.service.fluent.EntryConfig; import org.nextprot.api.core.test.base.CoreUnitBaseTest; import org.nextprot.api.core.utils.IsoformUtils; import org.nextprot.api.core.utils.seqmap.IsoformSequencePositionMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ActiveProfiles; import java.io.FileNotFoundException; import java.io.PrintWriter; import java.util.*; import java.util.stream.Collectors; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @ActiveProfiles({ "dev"}) public class AnnotationUtilsTest extends CoreUnitBaseTest { @Autowired private EntryBuilderService entryBuilderService; @Autowired private AnnotationService annotationService; @Test public void shouldTurnSequenceCautionRelativeEvidenceIntoDifferingSequenceProperty() { long annotId=1234; // create evidence (type=3) AnnotationEvidence ev3 = new AnnotationEvidence(); ev3.setAnnotationId(annotId); ev3.setAssignedBy(null); ev3.setAssignmentMethod(null); ev3.setEvidenceCodeAC("ECO-000003"); ev3.setEvidenceId(3000); ev3.setNegativeEvidence(false); ev3.setQualityQualifier("GOLD"); ev3.setResourceAccession("AC-0003"); ev3.setResourceAssociationType("evidence"); ev3.setResourceDb("DB-0003"); ev3.setResourceDescription("Resource descr 3"); ev3.setResourceId(3333); ev3.setResourceType("database"); // create relative info (type=2) AnnotationEvidence ev2 = new AnnotationEvidence(); ev2.setAnnotationId(annotId); ev2.setAssignedBy(null); ev2.setAssignmentMethod(null); ev2.setEvidenceCodeAC(null); ev2.setEvidenceId(2000); ev2.setNegativeEvidence(false); ev2.setQualityQualifier("SILVER"); ev2.setResourceAccession("AC-0002"); ev2.setResourceAssociationType("relative"); ev2.setResourceDb("DB-0002"); ev2.setResourceDescription("Resource descr 2"); ev2.setResourceId(2222); ev2.setResourceType("database"); List<AnnotationEvidence> evidences = new ArrayList<>(); evidences.add(ev2); evidences.add(ev3); // create an annotation Annotation annot = new Annotation(); annot.setAnnotationId(annotId); annot.setUniqueName("some_sequence_caution_annotation"); annot.setCategory(AnnotationCategory.SEQUENCE_CAUTION.getDbAnnotationTypeName()); annot.setQualityQualifier("GOLD"); annot.setEvidences(evidences); annot.setDescription(""); // will be modified by convertType2EvidencesToProperties() List<Annotation> annotations = new ArrayList<>(); annotations.add(annot); AnnotationUtils.convertRelativeEvidencesToProperties(annotations); Assert.assertEquals(1, annotations.get(0).getEvidences().size()); // evidence type 2 should removed Assert.assertEquals(1, annotations.get(0).getProperties().size()); // property should be created (replaces evidence removed) assertContainsExpectedProperties(annotations.get(0).getProperties(), newAnnotationProperty(1234, "AC-0002", PropertyApiModel.NAME_DIFFERING_SEQUENCE, String.valueOf(ev2.getResourceId()), PropertyApiModel.VALUE_TYPE_RIF)); } @Test public void shouldTurnDiseaseRelativeEvidenceIntoAlternativeDiseaseTermProperty() { long annotId=1234; // create evidence (type=3) AnnotationEvidence ev3 = new AnnotationEvidence(); ev3.setAnnotationId(annotId); ev3.setAssignedBy(null); ev3.setAssignmentMethod(null); ev3.setEvidenceCodeAC("ECO-000003"); ev3.setEvidenceId(3000); ev3.setNegativeEvidence(false); ev3.setQualityQualifier("GOLD"); ev3.setResourceAccession("AC-0003"); ev3.setResourceAssociationType("evidence"); ev3.setResourceDb("DB-0003"); ev3.setResourceDescription("Resource descr 3"); ev3.setResourceId(3333); ev3.setResourceType("database"); // create relative info (type=2) AnnotationEvidence ev2 = new AnnotationEvidence(); ev2.setAnnotationId(annotId); ev2.setAssignedBy(null); ev2.setAssignmentMethod(null); ev2.setEvidenceCodeAC(null); ev2.setEvidenceId(2000); ev2.setNegativeEvidence(false); ev2.setQualityQualifier("SILVER"); ev2.setResourceAccession("AC-0002"); ev2.setResourceAssociationType("relative"); ev2.setResourceDb("DB-0002"); ev2.setResourceDescription("Resource descr 2"); ev2.setResourceId(2222); ev2.setResourceType("database"); List<AnnotationEvidence> evidences = new ArrayList<AnnotationEvidence>(); evidences.add(ev2); evidences.add(ev3); // create an annotation Annotation annot = new Annotation(); annot.setAnnotationId(annotId); annot.setUniqueName("some_disease_annotation"); annot.setCategory(AnnotationCategory.DISEASE.getDbAnnotationTypeName()); annot.setQualityQualifier("GOLD"); annot.setEvidences(evidences); annot.setDescription(""); // will be modified by convertType2EvidencesToProperties() List<Annotation> annotations = new ArrayList<Annotation>(); annotations.add(annot); AnnotationUtils.convertRelativeEvidencesToProperties(annotations); Assert.assertEquals(1, annotations.get(0).getEvidences().size()); // evidence type 2 should removed Assert.assertEquals(1, annotations.get(0).getProperties().size()); // property should be created (replaces evidence removed) assertContainsExpectedProperties(annotations.get(0).getProperties(), newAnnotationProperty(1234, "AC-0002", PropertyApiModel.NAME_ALTERNATIVE_DISEASE_TERM, String.valueOf(ev2.getResourceId()), PropertyApiModel.VALUE_TYPE_RIF)); } @Test public void shouldReturnAnnotationIfContainedInTheRange() { String isoName = "iso-1"; Annotation a1 = mock(Annotation.class); when(a1.isAnnotationPositionalForIsoform(isoName)).thenReturn(true); when(a1.getStartPositionForIsoform(isoName)).thenReturn(10); when(a1.getEndPositionForIsoform(isoName)).thenReturn(12); List<Annotation> filteredAnnots = AnnotationUtils.filterAnnotationsBetweenPositions(10, 20, Arrays.asList(a1), isoName); assertEquals(filteredAnnots.size(), 1); } @Test public void shouldNotReturnAnnotationIfOverlapsALittleBit() { //This is used on the pepX logic, if you want to change the logic be careful (add a flag or change the method name for example), but keep the same logic for pepX String isoName = "iso-1"; Annotation a1 = mock(Annotation.class); when(a1.isAnnotationPositionalForIsoform(isoName)).thenReturn(true); when(a1.getStartPositionForIsoform(isoName)).thenReturn(5); when(a1.getEndPositionForIsoform(isoName)).thenReturn(10); assertTrue(AnnotationUtils.filterAnnotationsBetweenPositions(10, 20, Arrays.asList(a1), isoName).isEmpty()); } @Test public void shouldNotReturnAnnotationIfOusideTheRange() { String isoName = "iso-1"; Annotation a1 = mock(Annotation.class); when(a1.isAnnotationPositionalForIsoform(isoName)).thenReturn(true); when(a1.getStartPositionForIsoform(isoName)).thenReturn(5); when(a1.getEndPositionForIsoform(isoName)).thenReturn(9); assertTrue(AnnotationUtils.filterAnnotationsBetweenPositions(10, 20, Arrays.asList(a1), isoName).isEmpty()); } @Test public void shouldcomputeIsoformsDisplayedAsSpecificForBinaryInteractionCase1() { // BinaryInteraction with 2 isoforms, 1 specific flag => should return 1 isoformDiplayed as specific int isoCount=2; Map<String, AnnotationIsoformSpecificity> targetIsoformMap = new HashMap<>(); AnnotationIsoformSpecificity spec1=new AnnotationIsoformSpecificity(); spec1.setIsoformAccession("iso1"); spec1.setSpecificity("SPECIFIC"); targetIsoformMap.put("iso1", spec1); AnnotationIsoformSpecificity spec2=new AnnotationIsoformSpecificity(); spec2.setIsoformAccession("iso2"); spec2.setSpecificity("BY DEFAULT"); targetIsoformMap.put("iso2", spec2); Annotation annot = mock(Annotation.class); when(annot.getAPICategory()).thenReturn(AnnotationCategory.BINARY_INTERACTION); when(annot.getTargetingIsoformsMap()).thenReturn(targetIsoformMap); List<String> result = AnnotationUtils.computeIsoformsDisplayedAsSpecific(annot,isoCount); assertEquals(1, result.size()); assertEquals("iso1", result.get(0)); } @Test public void shouldcomputeIsoformsDisplayedAsSpecificForBinaryInteractionCase2() { // BinaryInteraction with 2 isoforms, 2 specific flag => should return 0 isoformDiplayed as specific int isoCount=2; Map<String, AnnotationIsoformSpecificity> targetIsoformMap = new HashMap<>(); AnnotationIsoformSpecificity spec1=new AnnotationIsoformSpecificity(); spec1.setIsoformAccession("iso1"); spec1.setSpecificity("SPECIFIC"); targetIsoformMap.put("iso1", spec1); AnnotationIsoformSpecificity spec2=new AnnotationIsoformSpecificity(); spec2.setIsoformAccession("iso2"); spec2.setSpecificity("SPECIFIC"); targetIsoformMap.put("iso2", spec2); Annotation annot = mock(Annotation.class); when(annot.getAPICategory()).thenReturn(AnnotationCategory.BINARY_INTERACTION); when(annot.getTargetingIsoformsMap()).thenReturn(targetIsoformMap); List<String> result = AnnotationUtils.computeIsoformsDisplayedAsSpecific(annot,isoCount); assertEquals(0, result.size()); } @Test public void shouldcomputeIsoformsDisplayedAsSpecificForBinaryInteractionCase3() { // BinaryInteraction with 1 isoform, 1 specific flag => 0 isoformDiplayed as specific int isoCount=1; Map<String, AnnotationIsoformSpecificity> targetIsoformMap = new HashMap<>(); AnnotationIsoformSpecificity spec1=new AnnotationIsoformSpecificity(); spec1.setIsoformAccession("iso1"); spec1.setSpecificity("SPECIFIC"); targetIsoformMap.put("iso1", spec1); Annotation annot = mock(Annotation.class); when(annot.getAPICategory()).thenReturn(AnnotationCategory.BINARY_INTERACTION); when(annot.getTargetingIsoformsMap()).thenReturn(targetIsoformMap); List<String> result = AnnotationUtils.computeIsoformsDisplayedAsSpecific(annot,isoCount); assertEquals(0, result.size()); } @Test public void shouldcomputeIsoformsDisplayedAsSpecificForBinaryInteractionCase4() { // BinaryInteraction with 1 isoform, 0 specific flag => 0 isoformDiplayed as specific int isoCount=1; Map<String, AnnotationIsoformSpecificity> targetIsoformMap = new HashMap<>(); AnnotationIsoformSpecificity spec1=new AnnotationIsoformSpecificity(); spec1.setIsoformAccession("iso1"); spec1.setSpecificity("BY DEFAULT"); targetIsoformMap.put("iso1", spec1); Annotation annot = mock(Annotation.class); when(annot.getAPICategory()).thenReturn(AnnotationCategory.BINARY_INTERACTION); when(annot.getTargetingIsoformsMap()).thenReturn(targetIsoformMap); List<String> result = AnnotationUtils.computeIsoformsDisplayedAsSpecific(annot,isoCount); assertEquals(0, result.size()); } // -------------------------------- @Test public void shouldcomputeIsoformsDisplayedAsSpecificForNonBinaryInteractionCase1() { // Non BinaryInteraction with 2 isoforms, 2 targetingIsoform records => should return 0 isoformDiplayed as specific int isoCount=2; Map<String, AnnotationIsoformSpecificity> targetIsoformMap = new HashMap<>(); AnnotationIsoformSpecificity spec1=new AnnotationIsoformSpecificity(); spec1.setIsoformAccession("iso1"); spec1.setSpecificity("SPECIFIC"); targetIsoformMap.put("iso1", spec1); AnnotationIsoformSpecificity spec2=new AnnotationIsoformSpecificity(); spec2.setIsoformAccession("iso2"); spec2.setSpecificity("BY DEFAULT"); targetIsoformMap.put("iso2", spec2); Annotation annot = mock(Annotation.class); when(annot.getAPICategory()).thenReturn(AnnotationCategory.GO_MOLECULAR_FUNCTION); when(annot.getTargetingIsoformsMap()).thenReturn(targetIsoformMap); List<String> result = AnnotationUtils.computeIsoformsDisplayedAsSpecific(annot, isoCount); assertEquals(0, result.size()); } @Test public void shouldcomputeIsoformsDisplayedAsSpecificForNonBinaryInteractionCase2() { // Non BinaryInteraction with 2 isoforms, 2 targetingIsoform records => should return 0 isoformDiplayed as specific int isoCount=2; Map<String, AnnotationIsoformSpecificity> targetIsoformMap = new HashMap<>(); AnnotationIsoformSpecificity spec1=new AnnotationIsoformSpecificity(); spec1.setIsoformAccession("iso1"); spec1.setSpecificity("SPECIFIC"); targetIsoformMap.put("iso1", spec1); AnnotationIsoformSpecificity spec2=new AnnotationIsoformSpecificity(); spec2.setIsoformAccession("iso2"); spec2.setSpecificity("SPECIFIC"); targetIsoformMap.put("iso2", spec2); Annotation annot = mock(Annotation.class); when(annot.getAPICategory()).thenReturn(AnnotationCategory.GO_MOLECULAR_FUNCTION); when(annot.getTargetingIsoformsMap()).thenReturn(targetIsoformMap); List<String> result = AnnotationUtils.computeIsoformsDisplayedAsSpecific(annot,isoCount); assertEquals(0, result.size()); } @Test public void shouldcomputeIsoformsDisplayedAsSpecificForNonBinaryInteractionCase3() { // BinaryInteraction with 1 isoform, 1 targetingIsoform record => should return 0 isoformDiplayed as specific int isoCount=1; Map<String, AnnotationIsoformSpecificity> targetIsoformMap = new HashMap<>(); AnnotationIsoformSpecificity spec1=new AnnotationIsoformSpecificity(); spec1.setIsoformAccession("iso1"); spec1.setSpecificity("SPECIFIC"); targetIsoformMap.put("iso1", spec1); Annotation annot = mock(Annotation.class); when(annot.getAPICategory()).thenReturn(AnnotationCategory.GO_MOLECULAR_FUNCTION); when(annot.getTargetingIsoformsMap()).thenReturn(targetIsoformMap); List<String> result = AnnotationUtils.computeIsoformsDisplayedAsSpecific(annot,isoCount); assertEquals(0, result.size()); } @Test public void shouldcomputeIsoformsDisplayedAsSpecificForNonBinaryInteractionCase4() { // BinaryInteraction with 2 isoforms, 1 targetingIsoform record => 1 isoformDiplayed as specific int isoCount=2; Map<String, AnnotationIsoformSpecificity> targetIsoformMap = new HashMap<>(); AnnotationIsoformSpecificity spec1=new AnnotationIsoformSpecificity(); spec1.setIsoformAccession("iso1"); spec1.setSpecificity("BY DEFAULT"); targetIsoformMap.put("iso1", spec1); Annotation annot = mock(Annotation.class); when(annot.getAPICategory()).thenReturn(AnnotationCategory.GO_MOLECULAR_FUNCTION); when(annot.getTargetingIsoformsMap()).thenReturn(targetIsoformMap); List<String> result = AnnotationUtils.computeIsoformsDisplayedAsSpecific(annot,isoCount); assertEquals(1, result.size()); assertEquals("iso1", result.get(0)); } // ---------------------------------- @Test public void testConvertEvidenceToExternalBioObject() { AnnotationEvidence ev = new AnnotationEvidence(); ev.setResourceAccession("CHEBI:38290"); ev.setResourceAssociationType("relative"); ev.setResourceDb("ChEBI"); ev.setResourceId(39334228); BioObject bo = AnnotationUtils.newExternalChemicalBioObject(ev); Assert.assertEquals("CHEBI:38290", bo.getAccession()); Assert.assertEquals("ChEBI", bo.getDatabase()); Assert.assertEquals(39334228, bo.getId()); Assert.assertEquals(BioObject.BioType.CHEMICAL, bo.getBioType()); } //@Test public void exportMergedAnnotationsForBrca1AndScn9A() throws FileNotFoundException { List<String> accessions = Arrays.asList("NX_Q15858", "NX_P38398"); List<String> headers = Arrays.asList("accession", "uniqueName", "category", "annotationName", "annotationHash", "masterPosition"); PrintWriter pw = new PrintWriter("mergedBrca1AndScn9AVariants.tsv"); // write header line pw.append(headers.stream().collect(Collectors.joining("\t"))).append("\n"); for (String accession : accessions) { Entry entry = entryBuilderService.build(EntryConfig.newConfig(accession).withAnnotations()); List<Annotation> mergedAnnotations = entry.getAnnotations().stream() .filter(a -> a.getAnnotationHash() != null) .filter(a -> a.getUniqueName().startsWith("AN")) .filter(a -> a.getAPICategory() == AnnotationCategory.VARIANT || a.getAPICategory() == AnnotationCategory.MUTAGENESIS) .collect(Collectors.toList()); pw.append(exportAnnotationsAsTsvString(entry, mergedAnnotations)); } pw.close(); } @Test public void shouldFilterBindingTypeDescendantAnnotations() { List<Annotation> annotations = entryBuilderService.build(EntryConfig.newConfig("NX_P01308") .with("go-molecular-function")).getAnnotations(); Assert.assertEquals(6, annotations.size()); List<Annotation> filtered = annotations.stream() .filter(annotationService.buildCvTermAncestorPredicate("GO:0005102")) .collect(Collectors.toList()); Assert.assertEquals(3, filtered.size()); Set<String> terms = filtered.stream().map(Annotation::getCvTermAccessionCode).collect(Collectors.toSet()); Assert.assertTrue(terms.contains("GO:0005158")); Assert.assertTrue(terms.contains("GO:0005159")); Assert.assertTrue(terms.contains("GO:0005179")); } @Test public void shouldFilterByPropertyTopologyExistence() { List<Annotation> annotations = entryBuilderService.build(EntryConfig.newConfig("NX_P04083") .with("subcellular-location")).getAnnotations(); Assert.assertEquals(21, annotations.size()); List<Annotation> filtered = annotations.stream() .filter(annotationService.buildPropertyPredicate("topology", null)) .collect(Collectors.toList()); Assert.assertEquals(4, filtered.size()); for (Annotation annot : filtered) { Assert.assertNotNull(annot.getPropertiesByKey("topology")); } } @Test public void shouldNotFilterByPropertyTopologyExistence() { List<Annotation> annotations = entryBuilderService.build(EntryConfig.newConfig("NX_P04083") .with("subcellular-location")).getAnnotations(); Assert.assertEquals(21, annotations.size()); List<Annotation> filtered = annotations.stream() .filter(annotationService.buildPropertyPredicate("tOpology", null)) .collect(Collectors.toList()); Assert.assertTrue(filtered.isEmpty()); } @Test public void shouldFilterByPropertyTopologyValue() { List<Annotation> annotations = entryBuilderService.build(EntryConfig.newConfig("NX_P04083") .with("subcellular-location")).getAnnotations(); List<Annotation> filtered = annotations.stream() .filter(annotationService.buildPropertyPredicate("topology", "Peripheral membrane protein")) .collect(Collectors.toList()); for (Annotation annot : filtered) { for (AnnotationProperty property : annot.getPropertiesByKey("topology")) { Assert.assertEquals("Peripheral membrane protein", property.getValue()); } } } @Test public void shouldNotFilterByPropertyTopologyValue() { List<Annotation> annotations = entryBuilderService.build(EntryConfig.newConfig("NX_P04083") .with("subcellular-location")).getAnnotations(); List<Annotation> filtered = annotations.stream() .filter(annotationService.buildPropertyPredicate("topology", "Peripheral mEMbrane protein")) .collect(Collectors.toList()); Assert.assertTrue(filtered.isEmpty()); } @Test public void shouldFilterByPropertyTopologyAccession() { List<Annotation> annotations = entryBuilderService.build(EntryConfig.newConfig("NX_P04083") .with("subcellular-location")).getAnnotations(); List<Annotation> filtered = annotations.stream() .filter(annotationService.buildPropertyPredicate("topology", "SL-9903")) .collect(Collectors.toList()); Assert.assertTrue(!filtered.isEmpty()); for (Annotation annot : filtered) { for (AnnotationProperty property : annot.getPropertiesByKey("topology")) { Assert.assertEquals("Peripheral membrane protein", property.getValue()); } } } private String exportAnnotationsAsTsvString(Entry entry, List<Annotation> mergedAnnotations) { Isoform canonical = IsoformUtils.getCanonicalIsoform(entry); StringBuilder sb = new StringBuilder(); for (Annotation annotation : mergedAnnotations) { List<String> row = Arrays.asList( entry.getUniqueName(), annotation.getUniqueName(), annotation.getAPICategory().getApiTypeName(), annotation.getAnnotationName(), annotation.getAnnotationHash(), String.valueOf(computeMasterPos(canonical, annotation.getTargetingIsoformsMap().get(canonical.getIsoformAccession()).getFirstPosition())) ); // write annotation line sb.append(row.stream().collect(Collectors.joining("\t"))).append("\n"); } return sb.toString(); } private int computeMasterPos(Isoform canonical, Integer integer) { return IsoformSequencePositionMapper.getCodonPositionsOnMaster(integer, canonical).getNucleotidePosition(0); } public static void assertContainsExpectedProperties(Collection<AnnotationProperty> properties, AnnotationProperty... expectedProperties) { for (AnnotationProperty property : expectedProperties) { Assert.assertTrue(properties.contains(property)); } } public static AnnotationProperty newAnnotationProperty(long annotationId, String accession, String name, String value, String valueType) { AnnotationProperty property = new AnnotationProperty(); property.setAnnotationId(annotationId); property.setAccession(accession); property.setName(name); property.setValue(value); property.setValueType(valueType); return property; } }