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