JAL-3899 Update usages of uniquify and deuniquify.
[jalview.git] / src / jalview / io / packed / JalviewDataset.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.io.packed;
22
23 import jalview.analysis.SeqsetUtils.SequenceInfo;
24 import jalview.analysis.TreeModel;
25 import jalview.api.FeatureColourI;
26 import jalview.datamodel.AlignmentI;
27 import jalview.datamodel.SequenceI;
28 import jalview.io.NewickFile;
29
30 import java.util.ArrayList;
31 import java.util.HashMap;
32 import java.util.Hashtable;
33 import java.util.List;
34 import java.util.Map;
35
36 public class JalviewDataset
37 {
38   /**
39    * dataset that new data (sequences, alignments) will be added to
40    */
41   AlignmentI parentDataset;
42
43   /**
44    * @return the parentDataset
45    */
46   public AlignmentI getParentDataset()
47   {
48     return parentDataset;
49   }
50
51   /**
52    * @param parentDataset
53    *          the parentDataset to set
54    */
55   public void setParentDataset(AlignmentI parentDataset)
56   {
57     this.parentDataset = parentDataset;
58   }
59
60   /**
61    * @return the featureColours
62    */
63   public Map<String, FeatureColourI> getFeatureColours()
64   {
65     return featureColours;
66   }
67
68   /**
69    * @param featureColours
70    *          the featureColours to set
71    */
72   public void setFeatureColours(Map<String, FeatureColourI> featureColours)
73   {
74     this.featureColours = featureColours;
75   }
76
77   /**
78    * @return the seqDetails
79    */
80   public Map<String, SequenceInfo> getSeqDetails()
81   {
82     return seqDetails;
83   }
84
85   /**
86    * @param seqDetails
87    *          the seqDetails to set
88    */
89   public void setSeqDetails(Hashtable seqDetails)
90   {
91     this.seqDetails = seqDetails;
92   }
93
94   /**
95    * @return the al
96    */
97   public List<AlignmentSet> getAl()
98   {
99     return (al == null) ? new ArrayList<AlignmentSet>() : al;
100   }
101
102   /**
103    * current alignment being worked on.
104    */
105   List<AlignmentSet> al;
106
107   public class AlignmentSet
108   {
109     public AlignmentI al;
110
111     public List<jalview.io.NewickFile> trees;
112
113     AlignmentSet(AlignmentI a)
114     {
115       al = a;
116       trees = new ArrayList<jalview.io.NewickFile>();
117     }
118
119     /**
120      * deuniquify the current alignment in the context, merging any new
121      * annotation/features with the existing set
122      * 
123      * @param context
124      */
125     void deuniquifyAlignment()
126     {
127       if (seqDetails == null || seqDetails.size() == 0)
128       {
129         // nothing to do
130         return;
131       }
132       // 1. recover correct names and attributes for each sequence in alignment.
133       /*
134        * TODO: housekeeping w.r.t. recovery of dataset and annotation references
135        * for input sequences, and then dataset sequence creation for new
136        * sequences retrieved from service // finally, attempt to de-uniquify to
137        * recover input sequence identity, and try to map back onto dataset Note:
138        * this jalview.analysis.SeqsetUtils.deuniquify(SeqNames, alseqs, true);
139        * will NOT WORK - the returned alignment may contain multiple versions of
140        * the input sequence, each being a subsequence of the original.
141        * deuniquify also removes existing annotation and features added in the
142        * previous step... al.setDataset(dataset); // add in new sequences
143        * retrieved from sequence search which are not already in dataset. //
144        * trigger a 'fetchDBids' to annotate sequences with database ids...
145        */
146       // jalview.analysis.SeqsetUtils.deuniquifyAndMerge(parentDataset,
147       // seqDetails, al,true);
148
149       jalview.analysis.SeqsetUtils.deuniquify(seqDetails,
150               al.getSequencesArray(), true);
151       // 2. Update names of associated nodes in any trees
152       for (NewickFile nf : trees)
153       {
154         // the following works because all trees are already had node/SequenceI
155         // associations created.
156         TreeModel njt = new TreeModel(al.getSequencesArray(), null, nf);
157         // this just updates the displayed leaf name on the tree according to
158         // the SequenceIs.
159         njt.renameAssociatedNodes();
160       }
161
162     }
163
164     /**
165      * set modification flag. If anything modifies the alignment in the current
166      * set, this flag should be true
167      */
168     private boolean modified = false;
169
170     /**
171      * @return the modified
172      */
173     public boolean isModified()
174     {
175       return modified;
176     }
177
178     /**
179      * or the modification state with the given state
180      * 
181      * @param modifiedFromAction
182      */
183     public void updateSetModified(boolean modifiedFromAction)
184     {
185       modified |= modifiedFromAction;
186     }
187   }
188
189   /**
190    * current set of feature colours
191    */
192   Map<String, FeatureColourI> featureColours;
193
194   /**
195    * original identity of each sequence in results
196    */
197   Map<String, SequenceInfo> seqDetails;
198
199   public boolean relaxedIdMatching = false;
200
201   public JalviewDataset()
202   {
203     seqDetails = new Hashtable();
204     al = new ArrayList<AlignmentSet>();
205     parentDataset = null;
206     featureColours = new HashMap<String, FeatureColourI>();
207   }
208
209   /**
210    * context created from an existing alignment.
211    * 
212    * @param parentAlignment
213    */
214   public JalviewDataset(AlignmentI aldataset,
215           Map<String, FeatureColourI> fc, Map<String, SequenceInfo> seqDets)
216   {
217     // TODO not used - remove?
218     this(aldataset, fc, seqDets, null);
219   }
220
221   /**
222    * 
223    * @param aldataset
224    *          - parent dataset for any new alignment/sequence data (must not be
225    *          null)
226    * @param fc
227    *          (may be null) feature settings for the alignment where new feature
228    *          renderstyles are stored
229    * @param seqDets
230    *          - (may be null) anonymised sequence information created by
231    *          Sequence uniquifier
232    * @param parentAlignment
233    *          (may be null) alignment to associate new annotation and trees
234    *          with.
235    */
236   public JalviewDataset(AlignmentI aldataset,
237           Map<String, FeatureColourI> fc, Map<String, SequenceInfo> seqDets,
238           AlignmentI parentAlignment)
239   {
240     this();
241     parentDataset = aldataset;
242     if (parentAlignment != null)
243     {
244       parentDataset = parentAlignment.getDataset();
245       if (parentDataset == null)
246       {
247         parentDataset = parentAlignment;
248       }
249       else
250       {
251         addAlignment(parentAlignment);
252       }
253     }
254     if (seqDets != null)
255     {
256       seqDetails = seqDets;
257     }
258     if (fc != null)
259     {
260       featureColours = fc;
261     }
262
263   }
264
265   public boolean hasAlignments()
266   {
267     return al != null && al.size() > 0;
268   }
269
270   public AlignmentI getLastAlignment()
271   {
272     return (al == null || al.size() < 1) ? null : al.get(al.size() - 1).al;
273   }
274
275   public AlignmentSet getLastAlignmentSet()
276   {
277     return (al == null || al.size() < 1) ? null : al.get(al.size() - 1);
278   }
279
280   /**
281    * post process (deuniquify) the current alignment and its dependent data, and
282    * then add newal to the dataset.
283    * 
284    * @param newal
285    */
286   public void addAlignment(AlignmentI newal)
287   {
288     if (!hasAlignments())
289     {
290       al = new ArrayList<AlignmentSet>();
291     }
292     AlignmentSet last = getLastAlignmentSet();
293     if (last != null)
294     {
295       System.err.println("Deuniquifying last alignment set.");
296       last.deuniquifyAlignment();
297     }
298     al.add(new AlignmentSet(newal));
299   }
300
301   public void addTreeFromFile(NewickFile nf)
302   {
303     AlignmentSet lal = getLastAlignmentSet();
304     lal.trees.add(nf);
305   }
306
307   public boolean hasSequenceAssoc()
308   {
309     // TODO: discover where sequence associated data should be put.
310     return false;
311   }
312
313   public SequenceI getLastAssociatedSequence()
314   {
315     // TODO: delineate semantics for associating uniquified data with
316     // potentially de-uniquified sequence.
317     return null;
318   }
319
320   /**
321    * update the modified state flag for the current set with the given
322    * modification state
323    * 
324    * @param modified
325    *          - this will be ored with current modification state
326    */
327   public void updateSetModified(boolean modified)
328   {
329     getLastAlignmentSet().updateSetModified(modified);
330   }
331 }