1 /* ===========================================================================
2 *
3 * PUBLIC DOMAIN NOTICE
4 * National Center for Biotechnology Information
5 *
6 * This software/database is a "United States Government Work" under the
7 * terms of the United States Copyright Act. It was written as part of
8 * the author's official duties as a United States Government employee and
9 * thus cannot be copyrighted. This software/database is freely available
10 * to the public for use. The National Library of Medicine and the U.S.
11 * Government have not placed any restriction on its use or reproduction.
12 *
13 * Although all reasonable efforts have been taken to ensure the accuracy
14 * and reliability of the software and data, the NLM and the U.S.
15 * Government do not and cannot warrant the performance or results that
16 * may be obtained by using this software or data. The NLM and the U.S.
17 * Government disclaim all warranties, express or implied, including
18 * warranties of performance, merchantability or fitness for any particular
19 * purpose.
20 *
21 * Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================*/
24
25 /*****************************************************************************
26
27 File name: dotmatrx.c
28
29 Author: Tom Madden
30
31 *****************************************************************************/
32 #include <dotmatrx.h>
33 #include <objmgr.h>
34 #include <dlogutil.h>
35 #include <vibrant.h>
36 #include <picture.h>
37 #include <viewer.h>
38 #include <objseq.h>
39 #include <objsset.h>
40 #include <salsap.h>
41 #include <blast.h>
42 #include <salpedit.h>
43
44 typedef struct dotmatrixform {
45 FEATURE_FORM_BLOCK
46 PopuP scale;
47 GrouP showLabels;
48 VieweR vwr;
49 SegmenT pict;
50 DotMatrixAlignmentPtr dmap;
51 int (LIBCALLBACK *user_callback)PROTO((SeqAlignPtr seqalign));
52 Boolean scaleNotCalculated;
53 } DotMatForm, PNTR DotMatFormPtr;
54
55 #define MAXZOOMSCALEVAL 22
56
57 static Int4 zoomScaleVal [MAXZOOMSCALEVAL] = {
58 1L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 20L,
59 30L, 40L, 50L, 60L, 70L, 80L, 90L, 100L, 200L, 500L
60 };
61
62
DeselectSegment(SegmenT seg,PrimitivE prim,Uint2 segID,Uint2 primID,Uint2 primCt,VoidPtr userdata)63 static Boolean DeselectSegment (SegmenT seg, PrimitivE prim, Uint2 segID,
64 Uint2 primID, Uint2 primCt, VoidPtr userdata)
65
66 {
67 DotMatFormPtr dfp;
68
69 dfp = (DotMatFormPtr) userdata;
70 if (dfp == NULL)
71 return FALSE;
72 HighlightSegment (dfp->vwr, seg, PLAIN_SEGMENT);
73 return TRUE;
74 }
75
FindSeqAlign(DotMatFormPtr dfp,Int4 segID)76 static SeqAlignPtr FindSeqAlign(DotMatFormPtr dfp, Int4 segID)
77
78 {
79 DenseDiagPtr ddp, ddp_new;
80 DotMatrixAlignmentPtr dmap;
81 SeqAlignPtr seqalign, new_seqalign=NULL;
82 Int4 index=0;
83
84 dmap = dfp->dmap;
85 while (dmap)
86 {
87 if (dmap->sap->segtype == 2)
88 {
89 seqalign = dmap->sap;
90 }
91 else
92 { /* discontinuous */
93 seqalign = dmap->sap->segs;
94 }
95
96 while (seqalign != NULL)
97 {
98 index++;
99 if (index == segID)
100 {
101 break;
102 }
103 seqalign = seqalign->next;
104 }
105
106 if (seqalign)
107 {
108 if (seqalign->segtype == 1)
109 {
110 new_seqalign = SeqAlignNew();
111 new_seqalign->type = 2;
112 new_seqalign->segtype = 1;
113 ddp = seqalign->segs;
114 new_seqalign->segs = ddp_new = DenseDiagDup(ddp);
115 while (ddp->next)
116 {
117 ddp_new->next = DenseDiagDup(ddp->next);
118 ddp = ddp->next;
119 ddp_new = ddp_new->next;
120 }
121 }
122 else if (seqalign->segtype == 2)
123 {
124 new_seqalign = SeqAlignDup(seqalign);
125 }
126 }
127 dmap = dmap->next;
128 }
129
130 return new_seqalign;
131 }
132
ClickDotMatrix(VieweR vwr,SegmenT seg,PoinT pt)133 static void ClickDotMatrix (VieweR vwr, SegmenT seg, PoinT pt)
134
135 {
136 DotMatFormPtr dfp;
137 Int1 highlight;
138 SegmenT new_seg;
139 PrimitivE prim;
140 SeqAlignPtr seqalign;
141 Uint2 primCT;
142 Uint2 primID;
143 Uint2 segID;
144
145 dfp = (DotMatFormPtr) GetObjectExtra (vwr);
146 new_seg = FindSegment (vwr, pt, &segID, &primID, &primCT);
147 if (new_seg == NULL)
148 {
149 ExploreSegment(seg, (Pointer) dfp, DeselectSegment);
150 }
151 else
152 {
153 prim = GetPrimitive (new_seg, primCT);
154 GetPrimDrawAttribute (prim, NULL, NULL, NULL, NULL, NULL, &highlight);
155 if (highlight != PLAIN_SEGMENT)
156 {
157 HighlightSegment (vwr, new_seg, PLAIN_SEGMENT);
158 }
159 else
160 {
161 HighlightSegment (vwr, new_seg, FILL_CONTENTS);
162 seqalign = FindSeqAlign(dfp, segID);
163 if (dblClick && dfp->user_callback)
164 dfp->user_callback(seqalign);
165 }
166 }
167 }
168 static SegmenT
CreateDotMatrixPic(DotMatrixAlignmentPtr dmap,Boolean showLabels)169 CreateDotMatrixPic (DotMatrixAlignmentPtr dmap, Boolean showLabels)
170
171 {
172 Char buffer [50];
173 DenseDiagPtr ddp;
174 DenseSegPtr dsp;
175 SeqAlignPtr sap;
176 Int4 index, index1;
177 SegmenT seg;
178 Int4 x;
179 Int4 y;
180 SegmenT pict;
181
182 if (dmap == NULL || dmap->sap == NULL)
183 return NULL;
184 pict = CreatePicture ();
185
186 while (dmap)
187 {
188 sap = dmap->sap;
189 if (sap == NULL)
190 break;
191 if (sap->segtype != 2)
192 { /* discontinuous */
193 sap = sap->segs;
194 }
195 index = 0;
196 while (sap != NULL)
197 {
198 seg = CreateSegment (pict, index + 1, 0);
199
200 AddAttribute (seg, COLOR_ATT, dmap->color, 0, 0, 0, 0);
201
202 if (sap->segtype == 1)
203 {
204 ddp = sap->segs;
205 while (ddp != NULL)
206 {
207 AddLine (seg, ddp->starts [0], ddp->starts [1], ddp->starts [0] + ddp->len, ddp->starts [1] + ddp->len, FALSE, 0);
208
209 if (showLabels)
210 {
211 x = ddp->starts [0];
212 y = ddp->starts [1];
213 sprintf (buffer, "(%ld, %ld)", (long) x + 1, (long) y + 1);
214 AddLabel (seg, x, y, buffer, SMALL_TEXT, 0, LOWER_RIGHT, 0);
215
216 x = ddp->starts [0] + ddp->len;
217 y = ddp->starts [1] + ddp->len;
218 sprintf (buffer, "(%ld, %ld)", (long) x, (long) y);
219 AddLabel (seg, x, y, buffer, SMALL_TEXT, 0, UPPER_RIGHT, 0);
220 }
221
222 ddp = ddp->next;
223 }
224 }
225 else if (sap->segtype == 2)
226 {
227 dsp = sap->segs;
228 for (index1=0; index1<dsp->numseg; index1++)
229 {
230 if (dsp->starts[2*index1] != -1 && dsp->starts[2*index1+1] != -1)
231 {
232 AddLine (seg, dsp->starts[2*index1], dsp->starts[2*index1+1], dsp->starts[2*index1] + dsp->lens[index1], dsp->starts[2*index1+1] + dsp->lens[index1], FALSE, 0);
233 if (showLabels)
234 {
235 x = dsp->starts[2*index1];
236 y = dsp->starts[2*index1+1];
237 sprintf (buffer, "(%ld, %ld)", (long) x + 1, (long) y + 1);
238 AddLabel (seg, x, y, buffer, SMALL_TEXT, 0, LOWER_RIGHT, 0);
239 x = dsp->starts[2*index1] + dsp->lens[index1];
240 y = dsp->starts[2*index1+1] + dsp->lens[index1];
241 sprintf (buffer, "(%ld, %ld)", (long) x + 1, (long) y + 1);
242 AddLabel (seg, x, y, buffer, SMALL_TEXT, 0, UPPER_RIGHT, 0);
243 }
244 }
245 }
246 }
247 index++;
248 sap = sap->next;
249 }
250 dmap = dmap->next;
251 }
252 return pict;
253 }
254
MakeDotMatrixPicture(DotMatFormPtr dfp)255 static void MakeDotMatrixPicture (DotMatFormPtr dfp)
256
257 {
258 Boolean showLabels;
259
260 if (dfp == NULL || dfp->dmap == NULL)
261 return;
262
263 showLabels = (Boolean) (GetValue (dfp->showLabels) == 1);
264 dfp->pict = CreateDotMatrixPic (dfp->dmap, showLabels);
265
266 }
RepopulateDotMatrixViewer(DotMatFormPtr dfp)267 static void RepopulateDotMatrixViewer (DotMatFormPtr dfp)
268
269 {
270 Int2 index;
271 Int4 scaleX;
272 Int4 scaleY;
273 Char str [16];
274
275 if (dfp == NULL)
276 return;
277
278 Reset (dfp->vwr);
279 dfp->pict = DeletePicture (dfp->pict);
280 Update ();
281 MakeDotMatrixPicture (dfp);
282 if (dfp->scaleNotCalculated)
283 {
284 SafeHide (dfp->scale);
285 Reset (dfp->scale);
286 for (index=1; index<=20; index++)
287 {
288 sprintf (str, "%ld", (long) (zoomScaleVal [index]));
289 PopupItem (dfp->scale, str);
290 }
291 SetValue (dfp->scale, 5);
292 dfp->scaleNotCalculated = FALSE;
293 }
294 SafeShow (dfp->scale);
295 index = GetValue (dfp->scale);
296 if (index < MAXZOOMSCALEVAL && index > 0)
297 {
298 scaleX = zoomScaleVal [index];
299 }
300 else
301 {
302 scaleX = 1;
303 }
304 scaleY = scaleX;
305 AttachPicture (dfp->vwr, dfp->pict, INT4_MIN, INT4_MAX, UPPER_LEFT, scaleX, scaleY, NULL);
306 SetViewerProcs (dfp->vwr, ClickDotMatrix, NULL, NULL, NULL);
307 Update ();
308 }
309
ChangeScale(PopuP p)310 static void ChangeScale (PopuP p)
311
312 {
313 DotMatFormPtr dfp;
314
315 dfp = (DotMatFormPtr) GetObjectExtra (p);
316 if (dfp != NULL)
317 {
318 RepopulateDotMatrixViewer (dfp);
319 }
320 }
321
ChangeLabels(GrouP g)322 static void ChangeLabels (GrouP g)
323
324 {
325 DotMatFormPtr dfp;
326
327 dfp = (DotMatFormPtr) GetObjectExtra (g);
328 if (dfp != NULL)
329 {
330 RepopulateDotMatrixViewer (dfp);
331 }
332 }
333
ResizeDotMatrixForm(WindoW w)334 static void ResizeDotMatrixForm (WindoW w)
335
336 {
337 DotMatFormPtr dfp;
338 Int2 height;
339 RecT r;
340 RecT s;
341 Int2 width;
342
343 dfp = (DotMatFormPtr) GetObjectExtra (w);
344 if (dfp != NULL)
345 {
346 ObjectRect (w, &r);
347 width = r.right - r.left;
348 height = r.bottom - r.top;
349 if (dfp->vwr != NULL)
350 {
351 GetPosition (dfp->vwr, &s);
352 s.right = width - s.left;
353 s.bottom = height - s.left;
354 SetPosition (dfp->vwr, &s);
355 AdjustPrnt (dfp->vwr, &s, FALSE);
356 if (Visible (dfp->vwr) && AllParentsVisible (dfp->vwr))
357 {
358 ViewerWasResized (dfp->vwr);
359 }
360 }
361 Update ();
362 }
363 }
364
CleanupDotMatrixForm(GraphiC g,VoidPtr data)365 static void CleanupDotMatrixForm (GraphiC g, VoidPtr data)
366
367 {
368 DotMatFormPtr dfp;
369 DotMatrixAlignmentPtr dmap;
370
371 dfp = (DotMatFormPtr) data;
372 if (dfp != NULL)
373 {
374 dfp->pict = DeletePicture (dfp->pict);
375 dmap = dfp->dmap;
376 while (dmap)
377 {
378 dmap->sap = SeqAlignFree (dmap->sap);
379 dmap = dmap->next;
380 }
381 }
382 StdCleanupFormProc (g, data);
383 }
384
HideDotMatrix(ButtoN i)385 static void HideDotMatrix (ButtoN i)
386
387 {
388 WindoW w;
389
390 w = (WindoW)ParentWindow (i);
391 Remove(w);
392
393 }
394
395 DotMatrixAlignmentPtr LIBCALL
DotMatrixAlignmentNew(SeqAlignPtr sap,Uint1Ptr color,DotMatrixAlignmentPtr PNTR oldp)396 DotMatrixAlignmentNew (SeqAlignPtr sap, Uint1Ptr color, DotMatrixAlignmentPtr PNTR oldp)
397
398 {
399 DotMatrixAlignmentPtr new, old;
400
401 new = MemNew(sizeof(DotMatrixAlignment));
402
403 if (new == NULL || oldp == NULL)
404 return NULL;
405
406 new->sap = sap;
407 new->color = color;
408
409 if (*oldp)
410 {
411 old = *oldp;
412 while (old->next)
413 old = old->next;
414
415 old->next = new;
416 }
417 else
418 {
419 *oldp = new;
420 }
421 return new;
422 }
423
424 #define BLAST_DOTMATRIX_EXTENT 600 /* Size of screen. */
425
CreateDotMatrixForm(SeqAlignPtr sap,int (LIBCALLBACK * callback)PROTO ((SeqAlignPtr seqalign)))426 ForM LIBCALL CreateDotMatrixForm (SeqAlignPtr sap, int (LIBCALLBACK *callback)PROTO((SeqAlignPtr seqalign)))
427
428 {
429 DotMatrixAlignmentPtr dmap, tmp;
430
431 tmp = NULL;
432 dmap = DotMatrixAlignmentNew(sap, NULL, &tmp);
433 return CreateDotMatrixFormEx(dmap, callback);
434 }
435
CreateDotMatrixFormEx(DotMatrixAlignmentPtr dmap,int (LIBCALLBACK * callback)PROTO ((SeqAlignPtr seqalign)))436 ForM LIBCALL CreateDotMatrixFormEx (DotMatrixAlignmentPtr dmap, int (LIBCALLBACK *callback)PROTO((SeqAlignPtr seqalign)))
437
438 {
439 DotMatFormPtr dfp;
440 GrouP g;
441 PrompT p1;
442 PrompT p2;
443 GrouP s, x;
444 WindoW w;
445
446 w = NULL;
447 dfp = (DotMatFormPtr) MemNew (sizeof (DotMatForm));
448 if (dfp != NULL)
449 {
450 dfp->dmap = dmap;
451 dfp->user_callback = callback;
452
453 w = DocumentWindow (-40, -33, -10, -10, "Dot Matrix Display",
454 StdCloseWindowProc, ResizeDotMatrixForm);
455 SetObjectExtra (w, dfp, CleanupDotMatrixForm);
456 dfp->form = (ForM) w;
457
458 x = HiddenGroup (w, 0, 1, NULL);
459 StaticPrompt (x, "Dot Matrix showing the BLAST hits between 2 sequences", 0, 0, programFont, 'l');
460
461 s = HiddenGroup (w, 5, 0, NULL);
462 SetGroupSpacing (s, 7, 2);
463
464 p1 = StaticPrompt (s, "Labels", 0, 0, programFont, 'l');
465 dfp->showLabels = HiddenGroup (s, 3, 0, ChangeLabels);
466 SetObjectExtra (dfp->showLabels, dfp, NULL);
467 RadioButton (dfp->showLabels, "Show");
468 RadioButton (dfp->showLabels, "Hide");
469 SetValue (dfp->showLabels, TRUE);
470
471 p2 = StaticPrompt (s, "Scale", 0, popupMenuHeight, programFont, 'l');
472 dfp->scale = PopupList (s, TRUE, ChangeScale);
473 SetObjectExtra (dfp->scale, dfp, NULL);
474
475 AlignObjects (ALIGN_MIDDLE, (HANDLE) p1, (HANDLE) dfp->showLabels, (HANDLE) p2, (HANDLE) dfp->scale, NULL);
476
477 x = HiddenGroup (w, 0, 2, NULL);
478 StaticPrompt (x, "Decrease scale to zoom in", 0, 0, programFont, 'l');
479 StaticPrompt (x, "Click on diagonals to launch the alignment editor", 0, 0, programFont, 'l');
480
481 g = HiddenGroup (w, 2, 0, NULL);
482 dfp->vwr = CreateViewer (g, BLAST_DOTMATRIX_EXTENT, BLAST_DOTMATRIX_EXTENT, TRUE, TRUE);
483 SetObjectExtra (dfp->vwr, dfp, NULL);
484 dfp->pict = NULL;
485 dfp->scaleNotCalculated = TRUE;
486
487 PushButton (w, "Dismiss", HideDotMatrix );
488
489 RealizeWindow (w);
490 RepopulateDotMatrixViewer (dfp);
491 }
492 return (ForM) w;
493 }
494
DotMatrixSearch(SeqIdPtr sip1,SeqIdPtr sip2,int (LIBCALLBACK * callback)PROTO ((SeqAlignPtr seqalign)))495 Int2 LIBCALL DotMatrixSearch(SeqIdPtr sip1, SeqIdPtr sip2, int (LIBCALLBACK *callback)PROTO((SeqAlignPtr seqalign)))
496
497 {
498 BioseqPtr query_bsp, subject_bsp;
499 BLAST_OptionsBlkPtr options;
500 Boolean is_na;
501 SeqAlignPtr seqalign;
502 WindoW window;
503
504
505 query_bsp = BioseqLockById(sip1);
506 subject_bsp = BioseqLockById(sip2);
507 if (query_bsp == NULL || subject_bsp == NULL)
508 {
509 ErrPostEx(SEV_WARNING, 0, 0, "Unable to obtain sequences");
510 return 1;
511 }
512
513 if (ISA_na(query_bsp->mol) != ISA_na(subject_bsp->mol))
514 {
515 ErrPostEx(SEV_WARNING, 0, 0, "Sequences are of different types");
516 return 1;
517 }
518
519 is_na = ISA_na(query_bsp->mol);
520
521 options = BLASTOptionNew((is_na == TRUE) ? "blastn":"blastp", TRUE);
522
523 seqalign = BlastTwoSequences(query_bsp, subject_bsp, NULL, options);
524
525 if (seqalign == NULL)
526 {
527 ErrPostEx(SEV_WARNING, 0, 0, "No hits found");
528 return 0;
529 }
530
531 window = (WindoW) CreateDotMatrixForm(seqalign, callback);
532
533 Show(window);
534
535 BioseqUnlockById(sip1);
536 BioseqUnlockById(sip2);
537
538 return 0;
539 }
540
DotMatrixGenFunc(Pointer data)541 Int2 LIBCALLBACK DotMatrixGenFunc (Pointer data)
542
543 {
544 OMProcControlPtr ompcp;
545 SeqAlignPtr sap;
546 WindoW w;
547
548 ompcp = (OMProcControlPtr) data;
549 if (ompcp == NULL || ompcp->proc == NULL)
550 return OM_MSG_RET_ERROR;
551
552 sap = NULL;
553 switch (ompcp->input_itemtype)
554 {
555 case OBJ_SEQALIGN :
556 sap = (SeqAlignPtr) ompcp->input_data;
557 break;
558 case 0 :
559 return OM_MSG_RET_ERROR;
560 default :
561 return OM_MSG_RET_ERROR;
562 }
563 w = (WindoW) CreateDotMatrixForm (sap, NULL);
564 Show (w);
565 Select (w);
566 return OM_MSG_RET_DONE;
567 }
568