JAL-3860 prototype for highlight species/assembly/chromosome/position
authorJim Procter <j.procter@dundee.ac.uk>
Wed, 30 Mar 2022 13:14:23 +0000 (14:14 +0100)
committerJim Procter <j.procter@dundee.ac.uk>
Wed, 30 Mar 2022 13:14:23 +0000 (14:14 +0100)
src/jalview/datamodel/GenomicAssemblies.java
src/jalview/rest/API.java
src/jalview/rest/HighlightGenomicRangeEndpoint.java [new file with mode: 0644]

index 13d9a61..b65dcba 100644 (file)
@@ -173,7 +173,7 @@ public class GenomicAssemblies
    * assemblies<br>
    * <em>will most likely fail for species other than human</em>
    */
-  public static MapList mapAssemblyFor(String seqRef, String species,
+  public static MapList mapAssemblyFor(String localAssembly, String species,
           MapList map, String chromosome, String vcfAssembly)
   {
     List<int[]> toVcfRanges = new ArrayList<>();
@@ -188,12 +188,12 @@ public class GenomicAssemblies
         continue;
       }
 
-      int[] newRange = mapReferenceRange(range, chromosome, species, seqRef,
+      int[] newRange = mapReferenceRange(range, chromosome, species, localAssembly,
               vcfAssembly);
       if (newRange == null)
       {
         Console.error(String.format("Failed to map %s:%s:%s:%d:%d to %s",
-                species, chromosome, seqRef, range[0], range[1],
+                species, chromosome, localAssembly, range[0], range[1],
                 vcfAssembly));
         continue;
       }
@@ -207,4 +207,15 @@ public class GenomicAssemblies
     return new MapList(fromSequenceRanges, toVcfRanges, 1, 1);
   }
 
+  /**
+   * get a maplist for positions in the given assembly for the given locus
+   * @param locus
+   * @param assembly
+   * @return
+   */
+  public static MapList mapAssemblyFor(GeneLociI locus, String assembly)
+  {
+    return mapAssemblyFor(assembly,locus.getSpeciesId(),locus.getMapping(),locus.getChromosomeId(),locus.getAssemblyId());
+  }
+
 }
index 93e7622..2455914 100644 (file)
@@ -50,6 +50,7 @@ public class API extends RestHandler
     addEndpoint(new HighlightSequenceEndpoint(this));
     addEndpoint(new SelectSequencesEndpoint(this));
     addEndpoint(new GetCrossReferencesEndpoint(this));
+    addEndpoint(new HighlightGenomicRangeEndpoint(this));
 
     setPath(MY_PATH);
     this.registerHandler();
diff --git a/src/jalview/rest/HighlightGenomicRangeEndpoint.java b/src/jalview/rest/HighlightGenomicRangeEndpoint.java
new file mode 100644 (file)
index 0000000..b0aa435
--- /dev/null
@@ -0,0 +1,126 @@
+package jalview.rest;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import jalview.api.AlignmentViewPanel;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.DBRefEntry;
+import jalview.datamodel.GeneLociI;
+import jalview.datamodel.GeneLocus;
+import jalview.datamodel.GenomicAssemblies;
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignFrame;
+import jalview.structure.StructureSelectionManager;
+import jalview.util.MapList;
+
+public class HighlightGenomicRangeEndpoint extends AbstractEndpoint
+{
+  public HighlightGenomicRangeEndpoint(API api)
+  {
+    super(api, path, name, parameters, description);
+  }
+
+  protected static final String path = "highlightgenome";
+
+  private static final String name = "Highlight sequence positions for genomic regions";
+
+  private static final String parameters = "species/assembly/chromosome/<position>";
+
+  private static final String description = "Highlight positions in sequences mapped to a particular location in a species' genome. assembly can be just the species name if it is not known.";
+
+  public void processEndpoint(HttpServletRequest request,
+          HttpServletResponse response)
+  {
+    if (!checkParameters(request, response, 4))
+    {
+      return;
+    }
+    String[] parameters = getEndpointPathParameters(request);
+
+    String species=parameters[0], assembly=parameters[1],chromid=parameters[2],posString=parameters[3];
+    
+    int pos = -1;
+    try
+    {
+      pos = Integer.parseInt(posString);
+    } catch (NumberFormatException e)
+    {
+      returnError(request, response,
+              "Could not parse postition integer " + posString);
+    }
+
+    AlignFrame[] alignFrames = getAlignFrames(request, true);
+    if (alignFrames == null)
+    {
+      returnError(request, response, "could not find results");
+      return;
+    }
+
+    Map<SequenceI, StructureSelectionManager> ssmMap = new HashMap<>();
+
+    for (int i = 0; i < alignFrames.length; i++)
+    {
+      AlignFrame af = alignFrames[i];
+      List<AlignmentViewPanel> aps = (List<AlignmentViewPanel>) af
+              .getAlignPanels();
+
+      for (AlignmentViewPanel ap : aps)
+      {
+        StructureSelectionManager ssm = ap.getStructureSelectionManager();
+        AlignmentI al = ap.getAlignment();
+        List<SequenceI> seqs = (List<SequenceI>) al.getSequences();
+        for (SequenceI seq : seqs)
+        {
+          GeneLociI locus = seq.getGeneLoci();
+          if (locus!=null && locus.getSpeciesId().equalsIgnoreCase(species))
+          {
+            if (locus.getAssemblyId() == null || assembly.equals(species)
+                    || locus.getAssemblyId().equals(assembly))
+            {
+              if (locus.getChromosomeId() != null
+                      && locus.getChromosomeId().equalsIgnoreCase(chromid))
+              {
+                MapList mp = locus.getMapping();
+                // TODO: find a better way to determine which is the sequence corresponding to the reference locus (ie the ENSG sequence)
+                if ((mp.getFromHighest()-mp.getFromLowest())==(mp.getToHighest()-mp.getToLowest()))
+                {
+                  // genomic locus (we hope)
+                  ssmMap.put(seq, ssm);
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+    // highlight
+    for (SequenceI seq : ssmMap.keySet())
+    {
+      StructureSelectionManager ssm = ssmMap.get(seq);
+      if (ssm == null)
+      {
+        continue;
+      }
+      GeneLociI locus = seq.getGeneLoci();
+      MapList assmap=locus.getMapping();
+      
+      if (assembly!=null && !assembly.equalsIgnoreCase(species) && locus.getAssemblyId()!=null && !locus.getAssemblyId().equalsIgnoreCase(assembly))
+      {
+        assmap = GenomicAssemblies.mapAssemblyFor(locus, assembly);
+      }
+      // locate local position(s) mapping to species:assembly:chromosome:pos 
+      int[] mappedPos = assmap.locateInFrom(pos, pos);
+      if (mappedPos!=null && mappedPos.length>0)
+      {
+        // use vamsas sequence so the position in the reference locus is added to the region being highlighted, as well as the mapped sequence
+        ssm.mouseOverVamsasSequence(seq.getDatasetSequence(), mappedPos[0], null);
+      }
+    }
+
+  }
+}
\ No newline at end of file