JAL-3759 exclude hidden columns when processing column selection
[jalview.git] / src / jalview / analysis / Grouping.java
index 91fef84..88d3525 100644 (file)
@@ -1,30 +1,34 @@
 /*
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
- * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
  * 
  * This file is part of Jalview.
  * 
  * Jalview is free software: you can redistribute it and/or
  * modify it under the terms of the GNU General Public License 
- * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
- * 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
  * Jalview is distributed in the hope that it will be useful, but 
  * WITHOUT ANY WARRANTY; without even the implied warranty 
  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
  * PURPOSE.  See the GNU General Public License for more details.
  * 
- * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
 package jalview.analysis;
 
-import jalview.datamodel.AlignmentI;
-import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 
-import java.util.Enumeration;
-import java.util.Hashtable;
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Vector;
 
 /**
@@ -50,14 +54,14 @@ public class Grouping
           String[] selectedChars, List<SequenceGroup> list)
   {
     // TODO: determine how to get/recover input data for group generation
-    Hashtable gps = new Hashtable();
+    Map<String, List<SequenceI>> gps = new HashMap<String, List<SequenceI>>();
     int width = 0, i;
-    Hashtable pgroup = new Hashtable();
+    Map<String, SequenceGroup> pgroup = new HashMap<String, SequenceGroup>();
     if (list != null)
     {
-      for (SequenceGroup sg:list)
+      for (SequenceGroup sg : list)
       {
-        for (SequenceI sq :sg.getSequences(null))
+        for (SequenceI sq : sg.getSequences(null))
         {
           pgroup.put(sq.toString(), sg);
         }
@@ -66,32 +70,130 @@ public class Grouping
     for (i = 0; i < sequences.length; i++)
     {
       String schar = selectedChars[i];
-      SequenceGroup pgp = (SequenceGroup) pgroup
-              .get(((Object) sequences[i]).toString());
+      SequenceGroup pgp = pgroup.get(((Object) sequences[i]).toString());
       if (pgp != null)
       {
         schar = pgp.getName() + ":" + schar;
       }
-      Vector svec = (Vector) gps.get(schar);
+      List<SequenceI> svec = gps.get(schar);
       if (svec == null)
       {
-        svec = new Vector();
+        svec = new ArrayList<SequenceI>();
         gps.put(schar, svec);
       }
       if (width < sequences[i].getLength())
       {
         width = sequences[i].getLength();
       }
-      svec.addElement(sequences[i]);
+      svec.add(sequences[i]);
+    }
+    // make some groups
+    SequenceGroup[] groups = new SequenceGroup[gps.size()];
+    i = 0;
+    for (String key : gps.keySet())
+    {
+      SequenceGroup group = new SequenceGroup(gps.get(key),
+              "Subseq: " + key, null, true, true, false, 0, width - 1);
+
+      groups[i++] = group;
+    }
+    gps.clear();
+    pgroup.clear();
+    return groups;
+  }
+
+  /**
+   * Divide the given sequences based on the equivalence of characters at
+   * selected columns If exgroups is provided, existing groups will be
+   * subdivided.
+   * 
+   * @param sequences
+   * @param columnSelection
+   * @param list
+   * @param hiddenColumns
+   * @return
+   */
+  public static SequenceGroup[] makeGroupsFromCols(SequenceI[] sequences,
+          ColumnSelection cs, List<SequenceGroup> list,
+          HiddenColumns hiddenColumns)
+  {
+    // TODO: determine how to get/recover input data for group generation
+    Map<String, List<SequenceI>> gps = new HashMap<String, List<SequenceI>>();
+    Map<String, SequenceGroup> pgroup = new HashMap<String, SequenceGroup>();
+    if (list != null)
+    {
+      for (SequenceGroup sg : list)
+      {
+        for (SequenceI sq : sg.getSequences(null))
+        {
+          pgroup.put(sq.toString(), sg);
+        }
+      }
+    }
+
+    /*
+     * get selected columns (in the order they were selected);
+     * note this could include right-to-left ranges
+     */
+    int[] spos = new int[cs.getSelected().size()];
+    int width = -1;
+    int i = 0;
+    for (Integer pos : cs.getSelected())
+    {
+      if (hiddenColumns == null || hiddenColumns.isVisible(pos.intValue()))
+      {
+        spos[i++] = pos.intValue();
+      }
+    }
+    if (i < spos.length)
+    {
+      // mark end of visible column position
+      spos[i] = -1;
+    }
+    // actual number of visible columns
+    for (i = 0; i < sequences.length; i++)
+    {
+      int slen = sequences[i].getLength();
+      if (width < slen)
+      {
+        width = slen;
+      }
+
+      SequenceGroup pgp = pgroup.get(((Object) sequences[i]).toString());
+      StringBuilder schar = new StringBuilder();
+      if (pgp != null)
+      {
+        schar.append(pgp.getName() + ":");
+      }
+      for (int p : spos)
+      {
+        if (p < 0)
+        {
+          break;
+        }
+        if (p >= slen)
+        {
+          schar.append("~");
+        }
+        else
+        {
+          schar.append(sequences[i].getCharAt(p));
+        }
+      }
+      List<SequenceI> svec = gps.get(schar.toString());
+      if (svec == null)
+      {
+        svec = new ArrayList<SequenceI>();
+        gps.put(schar.toString(), svec);
+      }
+      svec.add(sequences[i]);
     }
     // make some groups
-    java.util.Enumeration sge = gps.keys();
     SequenceGroup[] groups = new SequenceGroup[gps.size()];
     i = 0;
-    while (sge.hasMoreElements())
+    for (String key : gps.keySet())
     {
-      String key = (String) sge.nextElement();
-      SequenceGroup group = new SequenceGroup((Vector) gps.get(key),
+      SequenceGroup group = new SequenceGroup(gps.get(key),
               "Subseq: " + key, null, true, true, false, 0, width - 1);
 
       groups[i++] = group;