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