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