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