c37dfd32820a5c56ffa27bb79aac935e0e319d17
[jalview.git] / src / jalview / io / vamsas / Sequencemapping.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.4)
3  * Copyright (C) 2008 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
4  * 
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18  */
19 package jalview.io.vamsas;
20
21 import java.util.Vector;
22
23 import jalview.datamodel.AlignedCodonFrame;
24 import jalview.datamodel.Mapping;
25 import jalview.datamodel.SequenceI;
26 import jalview.io.VamsasAppDatastore;
27 import uk.ac.vamsas.client.Vobject;
28 import uk.ac.vamsas.objects.core.AlignmentSequence;
29 import uk.ac.vamsas.objects.core.DataSet;
30 import uk.ac.vamsas.objects.core.Local;
31 import uk.ac.vamsas.objects.core.RangeType;
32 import uk.ac.vamsas.objects.core.Seg;
33 import uk.ac.vamsas.objects.core.Sequence;
34 import uk.ac.vamsas.objects.core.SequenceMapping;
35 import uk.ac.vamsas.objects.core.SequenceType;
36
37 public class Sequencemapping extends Rangetype
38 {
39   public Sequencemapping(VamsasAppDatastore datastore, SequenceMapping sequenceMapping)
40   {
41     super(datastore);
42     Object mjvmapping = getvObj2jv(sequenceMapping);
43     if (mjvmapping==null)
44     {
45       add(sequenceMapping);
46     } else {
47       if (sequenceMapping.isUpdated())
48       {
49         update((jalview.util.MapList) mjvmapping, sequenceMapping);
50       }
51     }
52   }
53   /**
54    * create or update a vamsas sequence mapping corresponding to a jalview
55    * Mapping between two dataset sequences
56    * 
57    * @param datastore
58    * @param mjvmapping
59    * @param from
60    * @param ds
61    */
62   public Sequencemapping(VamsasAppDatastore datastore, jalview.datamodel.Mapping mjvmapping, uk.ac.vamsas.objects.core.SequenceType from, uk.ac.vamsas.objects.core.DataSet ds)
63   {
64     super(datastore);
65     SequenceMapping sequenceMapping = (SequenceMapping) getjv2vObj(mjvmapping);
66     if (sequenceMapping==null)
67     {
68       add(mjvmapping, from, ds);
69     } else {
70       if (from!=null && sequenceMapping.getLoc()!=from)
71       {
72         jalview.bin.Cache.log.warn("Probable IMPLEMENTATION ERROR: "+from+" doesn't match the local mapping sequence.");
73       }
74       if (ds!=null && sequenceMapping.is__stored_in_document() && sequenceMapping.getV_parent()!=ds)
75       {
76         jalview.bin.Cache.log.warn("Probable IMPLEMENTATION ERROR: "+ds+" doesn't match the parent of the bound sequence mapping object.");
77       }
78       if (sequenceMapping.isUpdated())
79       { 
80         conflict(mjvmapping, sequenceMapping);
81       } else {
82         update(mjvmapping, sequenceMapping);
83       }
84     }
85   }
86   private void conflict(Mapping mjvmapping, SequenceMapping sequenceMapping)
87   {
88     System.err.println("Conflict in update of sequenceMapping "+sequenceMapping.getVorbaId());
89   }
90   private void add(Mapping mjvmapping, uk.ac.vamsas.objects.core.SequenceType from, DataSet ds)
91   {
92     SequenceI jvto = mjvmapping.getTo();
93     while (jvto.getDatasetSequence()!=null)
94     {
95       jvto = jvto.getDatasetSequence();
96     }
97     SequenceType to = (SequenceType) getjv2vObj(jvto);
98     if (to==null)
99     {
100       jalview.bin.Cache.log.warn("NONFATAL - do a second update: Ignoring Forward Reference to seuqence not yet bound to vamsas seuqence object");
101       return;
102     } 
103     SequenceMapping sequenceMapping = new SequenceMapping();
104     sequenceMapping.setLoc(from);
105     sequenceMapping.setMap(to);
106     boolean dnaToProt=false,sense=false;
107     // ensure that we create a mapping with the correct sense
108     if (((Sequence) sequenceMapping.getLoc())
109             .getDictionary()
110             .equals(uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_NA))
111     {
112       if (((Sequence) sequenceMapping.getMap())
113               .getDictionary()
114               .equals(uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_AA))
115       {
116         dnaToProt=true;
117         sense=true;
118       } 
119     } else {
120       if (((Sequence) sequenceMapping.getMap())
121               .getDictionary()
122               .equals(uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_NA))
123       {
124         dnaToProt=true;
125         sense=false;
126       } 
127     }
128
129     if (!dnaToProt)
130     {
131       jalview.bin.Cache.log.warn("Ignoring Mapping - don't support protein to protein mapping in vamsas document yet.");
132       return;
133     }
134     if (ds==null)
135     {
136       // locate dataset for storage of SequenceMapping
137       if (sense)
138       {
139         ds = (DataSet) ((uk.ac.vamsas.client.Vobject) sequenceMapping.getLoc()).getV_parent();
140       } else {
141         ds = (DataSet) ((uk.ac.vamsas.client.Vobject) sequenceMapping.getMap()).getV_parent();
142       } 
143     }
144     if (sense)
145     {
146       this.initMapType(sequenceMapping, mjvmapping.getMap(), true);
147     } else {
148       this.initMapType(sequenceMapping, mjvmapping.getMap().getInverse(), true);
149     }
150     ds.addSequenceMapping(sequenceMapping);
151     sequenceMapping.setProvenance(this.dummyProvenance("user defined coding region translation")); // TODO:
152     // correctly
153     // construct
154     // provenance
155     // based
156     // on
157     // source
158     // of
159     // mapping
160     bindjvvobj(mjvmapping, sequenceMapping);
161
162     jalview.bin.Cache.log.debug("Successfully created mapping "+sequenceMapping.getVorbaId());
163   }
164   private void update(jalview.util.MapList mjvmapping, SequenceMapping sequenceMapping)
165   {
166     jalview.bin.Cache.log.error("Not implemented: Jalview Update Alcodon Mapping:TODO!"); 
167   }
168   private void update(jalview.datamodel.Mapping mjvmapping, SequenceMapping sequenceMapping)
169   {
170     jalview.bin.Cache.log.error("Not implemented: Jalview Update Sequence DBRef Mapping"); 
171   }
172   /**
173    * limitations: Currently, jalview only deals with mappings between dataset
174    * sequences, and even then, only between those that map from DNA to Protein.
175    * 
176    * @param sequenceMapping
177    */
178   private void add(SequenceMapping sequenceMapping)
179   {
180     Object mobj;
181     SequenceI from=null,to=null;
182     boolean dnaToProt=false,sense=false;
183     Sequence sdloc=null, sdmap=null;
184     if (sequenceMapping.getLoc() instanceof AlignmentSequence)
185     {
186       sdloc = (Sequence) ((AlignmentSequence) sequenceMapping.getLoc()).getRefid();
187     } else {
188       sdloc = ((Sequence) sequenceMapping.getLoc());
189     }
190     if (sequenceMapping.getMap() instanceof AlignmentSequence)
191     {
192       sdmap = (Sequence) ((AlignmentSequence) sequenceMapping.getMap()).getRefid();
193     } else {
194       sdmap = ((Sequence) sequenceMapping.getMap());
195     }
196     if (sdloc==null || sdmap == null)
197     {
198       jalview.bin.Cache.log.info("Ignoring non sequence-sequence mapping");
199       return;
200     }
201     mobj = this.getvObj2jv((Vobject) sdloc);
202     if (mobj instanceof SequenceI)
203     {
204       from = (SequenceI) mobj;
205     }
206     mobj = this.getvObj2jv((Vobject) sdmap);
207     if (mobj instanceof SequenceI)
208     {
209       to = (SequenceI) mobj;
210     }
211     if (from == null || to == null)
212     {
213
214       jalview.bin.Cache.log.error("Probable Vamsas implementation error : unbound dataset sequences involved in a mapping are being parsed!");
215       return;
216     } 
217
218     if (sdloc.getDictionary()
219             .equals(uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_NA))
220     {
221       if (sdmap.getDictionary()
222               .equals(uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_AA))
223       {
224         dnaToProt=true;
225         sense=true;
226       } 
227       // else {
228
229       // }
230     } else {
231       if (sdmap.getDictionary()
232               .equals(uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_NA))
233       {
234         dnaToProt=true;
235         sense=false;
236       } 
237     }
238     // create mapping storage object and make each dataset alignment reference
239     // it.
240     jalview.datamodel.AlignmentI dsLoc = (jalview.datamodel.AlignmentI) getvObj2jv(sdloc.getV_parent());
241     jalview.datamodel.AlignmentI dsMap = (jalview.datamodel.AlignmentI) getvObj2jv(sdmap.getV_parent());
242     AlignedCodonFrame afc = new AlignedCodonFrame(0);
243
244     if (dsLoc!=null && dsLoc!=dsMap)
245     {
246       dsLoc.addCodonFrame(afc);
247     }
248     if (dsMap!=null)
249     {
250       dsMap.addCodonFrame(afc);
251     }
252     // create and add the new mapping to (each) dataset's codonFrame
253
254     jalview.util.MapList mapping = null; 
255     if (!sense)
256     {
257       mapping = this.parsemapType(sequenceMapping, 1, 3); // invert sense
258       mapping = new jalview.util.MapList(mapping.getToRanges(), mapping.getFromRanges(), mapping.getToRatio(), mapping.getFromRatio());
259       afc.addMap(to, from, mapping);
260     } else {
261       mapping = this.parsemapType(sequenceMapping, 3, 1); // correct sense
262       afc.addMap(from, to, mapping);
263     }
264     bindjvvobj(mapping, sequenceMapping);
265     jalview.structure.StructureSelectionManager.getStructureSelectionManager().addMappings(new AlignedCodonFrame[] { afc });
266     // Try to link up any conjugate database references in the two sequences
267     // matchConjugateDBRefs(from, to,  mapping);
268     // Try to propagate any dbrefs across this mapping.
269
270   }
271   /**
272    * Complete any 'to' references in jalview.datamodel.Mapping objects associated with conjugate DBRefEntry under given mapping  
273    * @param from sequence corresponding to from reference for sequence mapping
274    * @param to sequence correspondeing to to reference for sequence mapping
275    * @param smap maplist parsed in same sense as from and to
276    */
277   private void matchConjugateDBRefs(SequenceI from, SequenceI to,
278           jalview.util.MapList smap)
279   {
280     if (from.getDBRef()==null && to.getDBRef()==null)
281     {
282       if (jalview.bin.Cache.log.isDebugEnabled())
283       {
284         jalview.bin.Cache.log.debug("Not matching conjugate refs for "+from.getName()+" and "+to.getName());
285       }
286       return; 
287     }
288     if (jalview.bin.Cache.log.isDebugEnabled())
289     {
290       jalview.bin.Cache.log.debug("Matching conjugate refs for "+from.getName()+" and "+to.getName());
291     }
292     jalview.datamodel.DBRefEntry[] fdb = from.getDBRef();
293     jalview.datamodel.DBRefEntry[] tdb = new jalview.datamodel.DBRefEntry[to.getDBRef().length];
294     int tdblen = to.getDBRef().length;
295     System.arraycopy(to.getDBRef(), 0, tdb, 0, tdblen);
296     Vector matched = new Vector();
297     jalview.util.MapList smapI = smap.getInverse();
298     for (int f=0;f<fdb.length; f++)
299     {
300       jalview.datamodel.DBRefEntry fe = fdb[f];
301       jalview.datamodel.Mapping fmp = fe.getMap();
302       boolean fmpnnl = fmp!=null;
303       // if (fmpnnl && fmp.getTo()!=null)
304       //{
305       //  jalview.bin.Cache.log.debug("Not overwriting existing To reference in "+fe);
306       //  continue;
307       //}
308       // smap from maps from fe.local to fe.map
309       boolean smapfromlocal2fe = (fmpnnl) ? smap.equals(fmp.getMap()) : false;
310       // smap from maps from fe.map to fe.local.
311       boolean smapfromfemap2local = (fmpnnl) ? smapI.equals(fmp.getMap()) : false;
312       for (int t=0; t<tdblen; t++)
313       {
314         jalview.datamodel.DBRefEntry te = tdb[t];
315         if (te!=null)
316         {
317           if (fe.getSource().equals(te.getSource())
318               && fe.getAccessionId().equals(te.getAccessionId()))
319           {
320             jalview.datamodel.Mapping tmp = te.getMap();
321             boolean tmpnnl = tmp!=null;
322             if (tmpnnl && tmp.getTo()!=null)
323             {
324               
325             }
326             // smap to maps from te.local to te.map
327             boolean smaptolocal2tm = (tmpnnl) ? smap.equals(tmp.getMap()) : false;
328             // smap to maps from te.map to te.local
329             boolean smaptotemap2local = (tmpnnl) ? smapI.equals(fmp.getMap()) : false;
330             if (smapfromlocal2fe && smaptotemap2local)
331             {
332               // smap implies mapping from to to from
333               fmp.setTo(to);
334               tmp.setTo(from);
335             } else 
336               if (smapfromfemap2local && smaptolocal2tm) {
337                 fmp.setTo(to);
338               }
339             }
340             
341         }
342       }
343     }
344     }
345 }