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