Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
Sequencemapping | 53 | 135 | 65 |
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.vamsas; | |
22 | ||
23 | import jalview.bin.Console; | |
24 | import jalview.datamodel.AlignedCodonFrame; | |
25 | import jalview.datamodel.AlignmentI; | |
26 | import jalview.datamodel.DBRefEntry; | |
27 | import jalview.datamodel.Mapping; | |
28 | import jalview.datamodel.SequenceI; | |
29 | import jalview.gui.Desktop; | |
30 | import jalview.io.VamsasAppDatastore; | |
31 | ||
32 | import java.util.ArrayList; | |
33 | import java.util.List; | |
34 | import java.util.Vector; | |
35 | ||
36 | import uk.ac.vamsas.objects.core.AlignmentSequence; | |
37 | import uk.ac.vamsas.objects.core.DataSet; | |
38 | import uk.ac.vamsas.objects.core.Sequence; | |
39 | import uk.ac.vamsas.objects.core.SequenceMapping; | |
40 | import uk.ac.vamsas.objects.core.SequenceType; | |
41 | ||
42 | /** | |
43 | * binds a vamsas sequence mapping object from the vamsas document to a maplist | |
44 | * object associated with a mapping in the Jalview model. We use the maplist | |
45 | * object because these are referred to both in the Mapping object associated | |
46 | * with a jalview.datamodel.DBRefEntry and in the array of | |
47 | * jalview.datamodel.AlCodonFrame objects that Jalview uses to propagate | |
48 | * sequence mapping position highlighting across the views. | |
49 | * | |
50 | * @author JimP | |
51 | * | |
52 | */ | |
53 | public class Sequencemapping extends Rangetype | |
54 | { | |
55 | 0 | public Sequencemapping(VamsasAppDatastore datastore, |
56 | SequenceMapping sequenceMapping) | |
57 | { | |
58 | 0 | super(datastore, sequenceMapping, jalview.util.MapList.class); |
59 | 0 | doJvUpdate(); |
60 | } | |
61 | ||
62 | private SequenceType from; | |
63 | ||
64 | private DataSet ds; | |
65 | ||
66 | private Mapping mjvmapping; | |
67 | ||
68 | /** | |
69 | * create or update a vamsas sequence mapping corresponding to a jalview | |
70 | * Mapping between two dataset sequences | |
71 | * | |
72 | * @param datastore | |
73 | * @param mjvmapping | |
74 | * @param from | |
75 | * @param ds | |
76 | */ | |
77 | 0 | public Sequencemapping(VamsasAppDatastore datastore, |
78 | jalview.datamodel.Mapping mjvmapping, | |
79 | uk.ac.vamsas.objects.core.SequenceType from, | |
80 | uk.ac.vamsas.objects.core.DataSet ds) | |
81 | { | |
82 | 0 | super(datastore, mjvmapping.getMap(), SequenceMapping.class); |
83 | 0 | this.from = from; |
84 | 0 | this.ds = ds; |
85 | 0 | this.mjvmapping = mjvmapping; |
86 | 0 | validate(); |
87 | 0 | doSync(); |
88 | } | |
89 | ||
90 | /** | |
91 | * local check that extant mapping context is valid | |
92 | */ | |
93 | 0 | public void validate() |
94 | { | |
95 | ||
96 | 0 | SequenceMapping sequenceMapping = (SequenceMapping) vobj; |
97 | 0 | if (sequenceMapping == null) |
98 | { | |
99 | 0 | return; |
100 | } | |
101 | 0 | if (from != null && sequenceMapping.getLoc() != from) |
102 | { | |
103 | 0 | Console.warn("Probable IMPLEMENTATION ERROR: " + from |
104 | + " doesn't match the local mapping sequence."); | |
105 | } | |
106 | 0 | if (ds != null && sequenceMapping.is__stored_in_document() |
107 | && sequenceMapping.getV_parent() != ds) | |
108 | { | |
109 | 0 | Console.warn("Probable IMPLEMENTATION ERROR: " + ds |
110 | + " doesn't match the parent of the bound sequence mapping object."); | |
111 | } | |
112 | } | |
113 | ||
114 | 0 | public void addToDocument() |
115 | { | |
116 | 0 | add(mjvmapping, from, ds); |
117 | } | |
118 | ||
119 | 0 | public void addFromDocument() |
120 | { | |
121 | 0 | add((SequenceMapping) vobj); |
122 | } | |
123 | ||
124 | 0 | public void conflict() |
125 | { | |
126 | 0 | conflict(mjvmapping, (SequenceMapping) vobj); |
127 | ||
128 | } | |
129 | ||
130 | 0 | public void updateToDoc() |
131 | { | |
132 | 0 | update(mjvmapping, (SequenceMapping) vobj); |
133 | } | |
134 | ||
135 | 0 | public void updateFromDoc() |
136 | { | |
137 | 0 | update((SequenceMapping) vobj, (jalview.datamodel.Mapping) jvobj); |
138 | } | |
139 | ||
140 | 0 | private void conflict(Mapping mjvmapping, SequenceMapping sequenceMapping) |
141 | { | |
142 | 0 | jalview.bin.Console.errPrintln("Conflict in update of sequenceMapping " |
143 | + sequenceMapping.getVorbaId()); | |
144 | } | |
145 | ||
146 | 0 | private void add(Mapping mjvmapping, |
147 | uk.ac.vamsas.objects.core.SequenceType from, DataSet ds) | |
148 | { | |
149 | 0 | SequenceI jvto = mjvmapping.getTo(); |
150 | 0 | while (jvto.getDatasetSequence() != null) |
151 | { | |
152 | 0 | jvto = jvto.getDatasetSequence(); |
153 | } | |
154 | 0 | SequenceType to = (SequenceType) getjv2vObj(jvto); |
155 | 0 | if (to == null) |
156 | { | |
157 | 0 | Console.warn( |
158 | "FIXME NONFATAL - do a second update: Ignoring Forward Reference to seuqence not yet bound to vamsas seuqence object"); | |
159 | 0 | return; |
160 | } | |
161 | 0 | SequenceMapping sequenceMapping = new SequenceMapping(); |
162 | 0 | sequenceMapping.setLoc(from); |
163 | 0 | sequenceMapping.setMap(to); |
164 | 0 | boolean dnaToProt = false, sense = false; |
165 | // ensure that we create a mapping with the correct sense | |
166 | 0 | if (((Sequence) sequenceMapping.getLoc()).getDictionary().equals( |
167 | uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_NA)) | |
168 | { | |
169 | 0 | if (((Sequence) sequenceMapping.getMap()).getDictionary().equals( |
170 | uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_AA)) | |
171 | { | |
172 | 0 | dnaToProt = true; |
173 | 0 | sense = true; |
174 | } | |
175 | } | |
176 | else | |
177 | { | |
178 | 0 | if (((Sequence) sequenceMapping.getMap()).getDictionary().equals( |
179 | uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_NA)) | |
180 | { | |
181 | 0 | dnaToProt = true; |
182 | 0 | sense = false; |
183 | } | |
184 | } | |
185 | ||
186 | 0 | if (!dnaToProt) |
187 | { | |
188 | 0 | Console.warn( |
189 | "Ignoring Mapping - don't support protein to protein mapping in vamsas document yet."); | |
190 | 0 | return; |
191 | } | |
192 | 0 | if (ds == null) |
193 | { | |
194 | // locate dataset for storage of SequenceMapping | |
195 | 0 | if (sense) |
196 | { | |
197 | 0 | ds = (DataSet) ((uk.ac.vamsas.client.Vobject) sequenceMapping |
198 | .getLoc()).getV_parent(); | |
199 | } | |
200 | else | |
201 | { | |
202 | 0 | ds = (DataSet) ((uk.ac.vamsas.client.Vobject) sequenceMapping |
203 | .getMap()).getV_parent(); | |
204 | } | |
205 | } | |
206 | 0 | if (sense) |
207 | { | |
208 | 0 | this.initMapType(sequenceMapping, mjvmapping.getMap(), true); |
209 | } | |
210 | else | |
211 | { | |
212 | 0 | this.initMapType(sequenceMapping, mjvmapping.getMap().getInverse(), |
213 | true); | |
214 | } | |
215 | 0 | ds.addSequenceMapping(sequenceMapping); |
216 | 0 | sequenceMapping.setProvenance( |
217 | this.dummyProvenance("user defined coding region translation")); // TODO: | |
218 | // correctly | |
219 | // construct | |
220 | // provenance | |
221 | // based | |
222 | // on | |
223 | // source | |
224 | // of | |
225 | // mapping | |
226 | 0 | bindjvvobj(mjvmapping.getMap(), sequenceMapping); |
227 | ||
228 | 0 | Console.debug( |
229 | "Successfully created mapping " + sequenceMapping.getVorbaId()); | |
230 | } | |
231 | ||
232 | // private void update(jalview.util.MapList mjvmapping, | |
233 | // SequenceMapping sequenceMapping) | |
234 | 0 | { |
235 | 0 | Console.error("Not implemented: Jalview Update Alcodon Mapping:TODO!"); |
236 | } | |
237 | ||
238 | 0 | private void update(SequenceMapping sequenceMapping, |
239 | jalview.datamodel.Mapping mjvmapping) | |
240 | { | |
241 | 0 | Console.error("Not implemented: Update DBRef Mapping from Jalview"); |
242 | } | |
243 | ||
244 | 0 | private void update(jalview.datamodel.Mapping mjvmapping, |
245 | SequenceMapping sequenceMapping) | |
246 | { | |
247 | 0 | Console.error("Not implemented: Jalview Update Sequence DBRef Mapping"); |
248 | } | |
249 | ||
250 | /** | |
251 | * bind a SequenceMapping to a live AlCodonFrame element limitations: | |
252 | * Currently, jalview only deals with mappings between dataset sequences, and | |
253 | * even then, only between those that map from DNA to Protein. | |
254 | * | |
255 | * @param sequenceMapping | |
256 | */ | |
257 | 0 | private void add(SequenceMapping sequenceMapping) |
258 | { | |
259 | 0 | Object mobj; |
260 | 0 | SequenceI from = null, to = null; |
261 | 0 | boolean dnaToProt = false, sense = false; |
262 | 0 | Sequence sdloc = null, sdmap = null; |
263 | 0 | if (sequenceMapping.getLoc() instanceof AlignmentSequence) |
264 | { | |
265 | 0 | sdloc = (Sequence) ((AlignmentSequence) sequenceMapping.getLoc()) |
266 | .getRefid(); | |
267 | } | |
268 | else | |
269 | { | |
270 | 0 | sdloc = ((Sequence) sequenceMapping.getLoc()); |
271 | } | |
272 | 0 | if (sequenceMapping.getMap() instanceof AlignmentSequence) |
273 | { | |
274 | 0 | sdmap = (Sequence) ((AlignmentSequence) sequenceMapping.getMap()) |
275 | .getRefid(); | |
276 | } | |
277 | else | |
278 | { | |
279 | 0 | sdmap = ((Sequence) sequenceMapping.getMap()); |
280 | } | |
281 | 0 | if (sdloc == null || sdmap == null) |
282 | { | |
283 | 0 | Console.info("Ignoring non sequence-sequence mapping"); |
284 | 0 | return; |
285 | } | |
286 | 0 | mobj = this.getvObj2jv(sdloc); |
287 | 0 | if (mobj instanceof SequenceI) |
288 | { | |
289 | 0 | from = (SequenceI) mobj; |
290 | } | |
291 | 0 | mobj = this.getvObj2jv(sdmap); |
292 | 0 | if (mobj instanceof SequenceI) |
293 | { | |
294 | 0 | to = (SequenceI) mobj; |
295 | } | |
296 | 0 | if (from == null || to == null) |
297 | { | |
298 | ||
299 | 0 | Console.error( |
300 | "Probable Vamsas implementation error : unbound dataset sequences involved in a mapping are being parsed!"); | |
301 | 0 | return; |
302 | } | |
303 | ||
304 | 0 | if (sdloc.getDictionary().equals( |
305 | uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_NA)) | |
306 | { | |
307 | 0 | if (sdmap.getDictionary().equals( |
308 | uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_AA)) | |
309 | { | |
310 | 0 | dnaToProt = true; |
311 | 0 | sense = true; |
312 | } | |
313 | // else { | |
314 | ||
315 | // } | |
316 | } | |
317 | else | |
318 | { | |
319 | 0 | if (sdmap.getDictionary().equals( |
320 | uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_NA)) | |
321 | { | |
322 | 0 | dnaToProt = true; |
323 | 0 | sense = false; |
324 | } | |
325 | } | |
326 | // create mapping storage object and make each dataset alignment reference | |
327 | // it. | |
328 | 0 | AlignmentI dsLoc = (AlignmentI) getvObj2jv(sdloc.getV_parent()); |
329 | 0 | AlignmentI dsMap = (AlignmentI) getvObj2jv(sdmap.getV_parent()); |
330 | 0 | AlignedCodonFrame acf = new AlignedCodonFrame(); |
331 | ||
332 | 0 | if (dsLoc != null && dsLoc != dsMap) |
333 | { | |
334 | 0 | dsLoc.addCodonFrame(acf); |
335 | } | |
336 | 0 | if (dsMap != null) |
337 | { | |
338 | 0 | dsMap.addCodonFrame(acf); |
339 | } | |
340 | // create and add the new mapping to (each) dataset's codonFrame | |
341 | ||
342 | 0 | jalview.util.MapList mapping = null; |
343 | 0 | if (dnaToProt) |
344 | { | |
345 | 0 | if (!sense) |
346 | { | |
347 | 0 | mapping = this.parsemapType(sequenceMapping, 1, 3); // invert sense |
348 | 0 | mapping = new jalview.util.MapList(mapping.getToRanges(), |
349 | mapping.getFromRanges(), mapping.getToRatio(), | |
350 | mapping.getFromRatio()); | |
351 | 0 | acf.addMap(to, from, mapping); |
352 | } | |
353 | else | |
354 | { | |
355 | 0 | mapping = this.parsemapType(sequenceMapping, 3, 1); // correct sense |
356 | 0 | acf.addMap(from, to, mapping); |
357 | } | |
358 | } | |
359 | else | |
360 | { | |
361 | 0 | mapping = this.parsemapType(sequenceMapping, 1, 1); // correct sense |
362 | 0 | acf.addMap(from, to, mapping); |
363 | } | |
364 | 0 | bindjvvobj(mapping, sequenceMapping); |
365 | 0 | jalview.structure.StructureSelectionManager |
366 | .getStructureSelectionManager(Desktop.instance) | |
367 | .registerMapping(acf); | |
368 | // Try to link up any conjugate database references in the two sequences | |
369 | // matchConjugateDBRefs(from, to, mapping); | |
370 | // Try to propagate any dbrefs across this mapping. | |
371 | ||
372 | } | |
373 | ||
374 | /** | |
375 | * Complete any 'to' references in jalview.datamodel.Mapping objects | |
376 | * associated with conjugate DBRefEntry under given mapping | |
377 | * | |
378 | * @param from | |
379 | * sequence corresponding to from reference for sequence mapping | |
380 | * @param to | |
381 | * sequence correspondeing to to reference for sequence mapping | |
382 | * @param smap | |
383 | * maplist parsed in same sense as from and to | |
384 | */ | |
385 | 0 | private void matchConjugateDBRefs(SequenceI from, SequenceI to, |
386 | jalview.util.MapList smap) | |
387 | { | |
388 | 0 | if (from.getDBRefs() == null && to.getDBRefs() == null) |
389 | { | |
390 | 0 | if (Console.isDebugEnabled()) |
391 | { | |
392 | 0 | Console.debug("Not matching conjugate refs for " + from.getName() |
393 | + " and " + to.getName()); | |
394 | } | |
395 | 0 | return; |
396 | } | |
397 | 0 | if (Console.isDebugEnabled()) |
398 | { | |
399 | 0 | Console.debug("Matching conjugate refs for " + from.getName() |
400 | + " and " + to.getName()); | |
401 | } | |
402 | 0 | List<DBRefEntry> fdb = from.getDBRefs(); |
403 | 0 | List<DBRefEntry> tdb = new ArrayList<DBRefEntry>(to.getDBRefs()); |
404 | 0 | int tdblen = to.getDBRefs().size(); |
405 | // | |
406 | // | |
407 | // YOWSER | |
408 | // | |
409 | // System.arraycopy(to.getDBRefs(), 0, tdb, 0, tdblen); | |
410 | // | |
411 | // | |
412 | // | |
413 | // | |
414 | 0 | Vector matched = new Vector(); |
415 | 0 | jalview.util.MapList smapI = smap.getInverse(); |
416 | 0 | for (int f = 0, fn = fdb.size(); f < fn; f++) |
417 | { | |
418 | 0 | jalview.datamodel.DBRefEntry fe = fdb.get(f); |
419 | 0 | jalview.datamodel.Mapping fmp = fe.getMap(); |
420 | 0 | boolean fmpnnl = (fmp != null); |
421 | // if (fmpnnl && fmp.getTo()!=null) | |
422 | // { | |
423 | // Cache.debug("Not overwriting existing To reference in | |
424 | // "+fe); | |
425 | // continue; | |
426 | // } | |
427 | // smap from maps from fe.local to fe.map | |
428 | 0 | boolean smapfromlocal2fe = (fmpnnl) ? smap.equals(fmp.getMap()) |
429 | : false; | |
430 | // smap from maps from fe.map to fe.local. | |
431 | 0 | boolean smapfromfemap2local = (fmpnnl) ? smapI.equals(fmp.getMap()) |
432 | : false; | |
433 | 0 | for (int t = 0; t < tdblen; t++) |
434 | { | |
435 | 0 | jalview.datamodel.DBRefEntry te = tdb.get(t); |
436 | 0 | if (te != null) |
437 | { | |
438 | 0 | if (fe.getSource().equals(te.getSource()) |
439 | && fe.getAccessionId().equals(te.getAccessionId())) | |
440 | { | |
441 | 0 | jalview.datamodel.Mapping tmp = te.getMap(); |
442 | 0 | boolean tmpnnl = tmp != null; |
443 | 0 | if (tmpnnl && tmp.getTo() != null) |
444 | { | |
445 | ||
446 | } | |
447 | // smap to maps from te.local to te.map | |
448 | 0 | boolean smaptolocal2tm = (tmpnnl) ? smap.equals(tmp.getMap()) |
449 | : false; | |
450 | // smap to maps from te.map to te.local | |
451 | 0 | boolean smaptotemap2local = (tmpnnl) |
452 | ? smapI.equals(fmp.getMap()) | |
453 | : false; | |
454 | 0 | if (smapfromlocal2fe && smaptotemap2local) |
455 | { | |
456 | // smap implies mapping from to to from | |
457 | 0 | fmp.setTo(to); |
458 | 0 | tmp.setTo(from); |
459 | } | |
460 | 0 | else if (smapfromfemap2local && smaptolocal2tm) |
461 | { | |
462 | 0 | fmp.setTo(to); |
463 | } | |
464 | } | |
465 | ||
466 | } | |
467 | } | |
468 | } | |
469 | } | |
470 | } |