2
* Author: Jean Thierry-Mieg (mieg@mrc-lmb.cam.ac.uk)
3
* Copyright (C) J Thierry-Mieg and R Durbin, 1992
4
* -------------------------------------------------------------------
5
* Acedb 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.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
* or see the on-line version at http://www.gnu.org/copyleft/gpl.txt
19
* -------------------------------------------------------------------
20
* This file is part of the ACEDB genome database package, written by
21
* Richard Durbin (MRC LMB, UK) rd@mrc-lmb.cam.ac.uk, and
22
* Jean Thierry-Mieg (CRBM du CNRS, France) mieg@kaa.cnrs-mop.fr
25
** The aim of this tool is to display on a unique graph as many
26
** system of maps as control by sprdctrl.c
29
* Last edited: May 6 10:22 2003 (edgrif)
30
* * Feb 8 16:45 1999 (edgrif): Remove use of graph internals in myMapPrint()
31
* * Oct 15 16:44 1998 (edgrif): Change names of MAP2GRAPH & GRAPH2MAP
32
* as they clash with the graph headers versions.
33
* Created: Wed May 27 11:40:21 1992 (mieg)
34
* CVS info: $Id: multimapdisp.c,v 1.11 2003/05/06 13:13:12 edgrif Exp $
35
*-------------------------------------------------------------------
46
#include <wh/spread.h>
47
#include <whooks/sysclass.h>
48
#include <whooks/classes.h>
49
#include <whooks/tags.h>
50
#include <whooks/systags.h>
51
#include <wh/display.h>
52
#include <wh/tabledisp.h>
54
BITSET_MAKE_BITFIELD /* define bitField for bitset.h ops */
56
/************************************************************/
58
typedef struct MapColumnStruct MapColumn;
59
typedef struct SegStruct SEG;
61
struct MapColumnStruct {
65
float mag, centre, min, max;
67
Array segs , segps ; /* segps are used to reorder the segs without loosing the friend info */
77
int x, xs ; float y, ys ;
79
SEG *friends ; /* Loop of related segs */
81
KEY parent, grandParent ;
85
SEG* seg ; /* pointer OK: segs fixed when drawing */
92
static magic_t MultiMap_MAGIC = "MultiMap";
94
typedef struct MultiMapStruct {
97
Graph graph, parentGraph;
102
Array mapColumns; /* of type MapColumn */
103
MapColumn *activeMapColumn ;
106
int cursorBox , chromoBox , allButton ;
110
static int nx, ny ; /* window dimensions */
111
static float yCentre ; /* ny/2 */
112
static float yLength ; /* length of picture */
113
static float topMargin = 6 ; /* space at top for buttons etc */
114
static float bottomMargin = 1 ; /* space at bottom */
115
static float xCursor = 5 ; /* midline of mini-chromosome */
116
static float xScale = 10 ; /* scale bar text LHS */
118
static float symbolSize_L = 3.0 ; /* size of little squares */
120
static BOOL isPapDisp = FALSE ;
122
#define SPRDMAP2GRAPH(mcol, x) \
123
(yCentre + mcol->mag * ((float)(x) - mcol->centre))
124
#define SPRDGRAPH2MAP(c,x) \
125
(((x) - yCentre) / mcol->mag + c->centre)
127
#define MAP2CHROM(x) \
128
(topMargin + yLength * (x - mcol->min) / (mcol->max != mcol->min ? mcol->max - mcol->min : 1 ))
130
#define FLAG_HIGHLIGHT 1 /* not implemented yet */
131
#define FLAG_INSITU 2
134
/************************************************************/
136
/* p1, p2 are used for contigs: multiMap <-> pmap
137
for in_situ data for in_situ clones
141
static void multiMapDisplayDestroy (void);
142
static void multiMapDraw (MultiMap mmdisp);
143
static MultiMap currentMultiMap (char *caller);
145
static void multiMapPick (int box, double x , double y, int modifier_unused) ;
146
static void multiMapDragCursor (float *x, float *y, BOOL isDone) ;
147
static void multiMapMiddleDown (double x, double y) ;
148
static void multiMapMiddleDrag (double x, double y) ;
149
static void multiMapMiddleUp (double x, double y) ;
150
static void multiMapConvert (MultiMap mmdisp) ;
151
static void multiMapDrawKey (MultiMap mmdisp, KEY key) ;
152
static void multiMapResize (void) ;
153
static void multiMapSelect (MultiMap mmdisp, int box) ;
154
static void multiMapFollow (MultiMap mmdisp, double x, double y) ;
155
static void multiMapChangeSymbolSize (void) ;
156
static void drawChromosomeBox (MultiMap mmdisp) ;
158
static void multiMapWhole (void) ;
159
static void multiMapZoomIn (void);
160
static void multiMapZoomOut (void);
161
static void multiMapZoomAll (void);
162
static void multiMapFlip (void);
163
static void multiMapClear (void);
165
static void myMapPrint(void) ;
167
static Array multiMapFindLimits(TABLE *table, Array isFlipMapArray);
169
/************************************************************/
171
static MENUOPT multiMapMenu[] = {
172
{graphDestroy, "Quit"},
174
{graphPrint, "Print Screen"},
175
{myMapPrint, "Print Whole Map"},
177
{displayPreserve, "Preserve"},
178
{multiMapChangeSymbolSize, "Symbol size"},
182
static MENUOPT buttonOpts[] = {
183
{multiMapWhole, "Whole"},
184
{multiMapZoomIn, "Zoom In"},
185
{multiMapZoomOut, "Zoom Out"},
186
{multiMapClear, "Clear"},
187
{multiMapFlip, "Flip"},
191
/************************************************************/
194
* DisplayFunc for _VMultiMap objects
196
BOOL multiMapDisplay (KEY key, KEY from, BOOL isOldGraph, void *unused)
198
KEY map, anchor = 0 , anchor_group;
199
int n = 0 , cl, minMap = 2 ;
204
if (key == KEY_UNDEFINED || class(key) != _VMultiMap || !(obj = bsCreate(key)))
211
bsGetData(obj, _Min, _Int, &minMap) ;
212
if (minMap <1) minMap = 1 ;
213
if (bsGetKey(obj, _Map, &map))
215
keySet(ks, n++) = map ;
216
} while (bsGetKey(obj, _bsDown, &map)) ;
219
if (bsGetData (obj, _Anchor, _Text, &cp) &&
220
(cl = pickWord2Class (cp)) &&
221
bsGetData (obj, _bsRight, _Text, &cp) &&
222
lexword2key (cp, &anchor_group, _VSystem) &&
223
bsGetData (obj, _bsRight, _Text, &cp) &&
224
lexword2key (cp, &anchor, _VSystem)) ;
226
{ cl = 0 ; anchor = 0 ; anchor_group = 0 ; }
229
isSuccess = multiMapDisplayKeySet (name(key), ks, cl, anchor_group, anchor, minMap);
231
keySetDestroy (ks); /* is this correct here ? */
234
} /* multiMapDisplay */
236
/************************************************************/
238
BOOL multiMapDisplayKeySet (char *title, KEYSET ks, int cl,
239
KEY anchor_group, KEY anchor, int minMap)
240
/* also called from keySetDisplay */
243
KEYSET loci = 0 , loci1 = 0 ;
251
aa = arrayCreate(100, BSunit) ;
252
loci = keySetCreate() ; n = 0 ;
253
flipped = arrayCreate(12, BOOL) ;
255
/* this may take very long,
256
* but when it does the user has probably chosen the wrong keyset */
257
messStatus ("Multimap, F4 to interrupt...");
259
for (i = 0; i < keySetMax(ks); i++)
261
if (messIsInterruptCalled())
263
messout("Multimap interrupted...\n"
264
"Processed %d out of %d possible objects",
268
if ((obj = bsCreate(keySet(ks, i))))
271
if (bsFindTag(obj, _Contains) &&
272
bsFlatten(obj, 2, aa))
273
for (j = 1 ; j < arrayMax(aa); j += 2)
274
keySet(loci, n++) = arr(aa, j, BSunit).k ;
275
if (bsFindTag(obj, _Flipped))
276
array(flipped,i,BOOL) = TRUE ;
281
if (keySetMax(loci) == 0)
283
messout("Objects do not contain loci\n"
284
"Unable to make a multi-map !");
289
keySetCompress(loci) ;
291
s = stackCreate(100) ;
294
/*************** Multi-map ***************/
296
loci = query(loci1, "COUNT Map >= 1") ;
300
pushText(s,"Title \"") ;
301
catText(s, "Multi-map") ;
307
catText (s, "\"\n\n") ;
308
catText(s,"Colonne 1\n"
310
"Width 12\nVisible\nClass Locus\n");
311
catText(s,messprintf("Condition COUNT Map >= %d\n\n", minMap)) ;
313
for (i = 0; i < keySetMax(ks) ; i++)
314
{ catText(s, "Colonne ") ;
315
catText(s, messprintf("%d\n", i + 2)) ;
316
catText(s, messprintf("Subtitle %s\n", name(keySet(ks,i)))) ;
317
catText(s, "Float\nFrom 1\nTag Map = \"") ;
318
catText(s, name(keySet(ks,i))) ;
320
catText(s," # Position") ;
321
catText(s," \nVisible \nOptional") ;
322
if (array(flipped,i,BOOL))
323
catText(s,"\nFlipMap") ;
330
/***************** Homology-map ****************/
332
loci = query(loci1, messprintf(">%s", name(anchor_group))) ;
336
pushText(s,"Title \"") ;
337
catText(s, "Homology-map") ;
343
catText (s, "\"\n\n") ;
344
catText(s,"Colonne 1\n"
346
catText (s, pickClass2Word (cl)) ;
348
"Width 12 \nVisible \nClass ") ;
349
catText (s, pickClass2Word (cl)) ;
352
for (i = 0; i < keySetMax(ks) ; i++)
353
{ catText(s, "Colonne ") ;
354
catText(s, messprintf("%d\n", 2*i + 2)) ;
355
catText(s, messprintf("Subtitle Locus on %s\n", name(keySet(ks,i)))) ;
356
catText(s,"Class ") ;
357
catText (s, pickClass2Word (cl)) ;
358
catText (s, " \nFrom 1 \nTag ") ;
359
catText (s, freeprotect(name (anchor))) ;
361
catText(s,"Condition Map = ") ;
362
catText(s, freeprotect(name(keySet(ks,i)))) ;
364
catText(s," \nVisible \nOptional") ;
367
catText(s, "Colonne ") ;
368
catText(s, messprintf("%d\n", 2*i + 3)) ;
369
catText(s, messprintf("Subtitle %s\n", name(keySet(ks,i)))) ;
370
catText(s,messprintf("Float\n From %d \n Tag Map = ", 2*i + 2)) ;
371
catText(s,freeprotect(name(keySet(ks,i)))) ;
372
catText(s," # Position \n") ;
373
catText(s,"Visible \nOptional") ;
374
if (array(flipped,i,BOOL))
375
catText(s,"\nFlipMap") ;
381
/********** display data and multi-map for these definitions ********/
383
/* parse definition Stack */
384
spread = spreadCreateFromStack (s, NULL);
386
table = spreadCalculateOverKeySet (spread, loci, NULL);
387
tableTitle = spreadGetTitle (spread);
389
/* display results */
390
tableDisplayCreate (table, tableTitle, flipped, 0) ;
391
multiMapDisplayCreate (table, tableTitle, flipped) ;
393
/******** clean up ********/
395
spreadDestroy (spread);
398
keySetDestroy(loci) ;
399
if (keySetExists(loci1))
400
keySetDestroy(loci1) ;
403
arrayDestroy (flipped);
406
/* NOTE, do -NOT- destroy ks, it belongs to caller
407
* (e.g. keysetdisplay) */
410
} /* multiMapDisplayKeySet */
412
/************************************************************/
414
Graph multiMapDisplayCreate (TABLE *table, char *title, Array isFlipMapArray)
418
Graph oldGraph = graphActive();
420
mapColumns = multiMapFindLimits(table, isFlipMapArray);
424
messout("No visible numerical column in this spread sheet") ;
428
mmdisp = (MultiMap)messalloc(sizeof(struct MultiMapStruct));
429
mmdisp->magic = &MultiMap_MAGIC;
430
mmdisp->graph = displayCreate("DtMULTIMAP");
431
mmdisp->table = tableCopy(table, 0);
432
mmdisp->title = strnew(title, 0);
434
mmdisp->mapColumns = mapColumns;
435
mmdisp->parentGraph = oldGraph;
436
mmdisp->zoomAll = TRUE ;
438
/* default for help, if undef in displays.wrm */
439
if (graphHelp(0) == NULL)
440
graphHelp("Multi_Map");
443
graphMenu (multiMapMenu) ;
445
graphAssociate (&MultiMap_MAGIC, mmdisp) ;
447
graphRegister (DESTROY, multiMapDisplayDestroy);
448
graphRegister (RESIZE, multiMapResize) ;
449
graphRegister (PICK, multiMapPick) ;
450
graphRegister (MIDDLE_DOWN, multiMapMiddleDown) ;
451
graphRegister (MIDDLE_DRAG, multiMapMiddleDrag) ;
452
graphRegister (MIDDLE_UP, multiMapMiddleUp) ;
455
multiMapDraw (mmdisp);
457
return mmdisp->graph;
458
} /* multiMapDisplayCreate */
462
void multiMapDisplayReCreate (TABLE *table, char *title, Array isFlipMapArray)
464
MultiMap mmdisp = currentMultiMap("multiMapDisplayReCreate");
467
mapColumns = multiMapFindLimits(table, isFlipMapArray);
471
messout("No visible numerical column in this spread sheet") ;
475
messfree(mmdisp->title);
476
mmdisp->title = strnew(title, 0);
478
tableDestroy(mmdisp->table);
479
mmdisp->table = tableCopy(table, 0);
481
mmdisp->mapColumns = mapColumns;
484
multiMapDraw (mmdisp);
487
} /* multiMapDisplayReCreate */
489
/*****************************************/
491
static MultiMap currentMultiMap (char *caller)
493
/* find and verify MultiMap struct on active graph */
494
MultiMap mmdisp = 0 ;
496
if (!(graphAssFind(&MultiMap_MAGIC, &mmdisp)))
497
messcrash("%s() could not find MultiMapStruct on graph", caller);
499
messcrash("%s() received NULL MultiMapStruct pointer", caller);
500
if (mmdisp->magic != &MultiMap_MAGIC)
501
messcrash("%s() received non-magic MultiMapStruct pointer", caller);
504
} /* currentMultiMap */
506
/************************************************************/
508
static void multiMapDisplayDestroy (void)
510
MultiMap mmdisp = currentMultiMap("multiMapDisplayDestroy");
514
tableDestroy(mmdisp->table);
515
messfree(mmdisp->title);
517
for (colNum = 0; colNum < arrayMax(mmdisp->mapColumns); colNum++)
519
mcol = arrp(mmdisp->mapColumns, colNum, MapColumn) ;
520
bumpDestroy(mcol->bump);
521
arrayDestroy(mcol->segs);
522
arrayDestroy(mcol->segps);
524
arrayDestroy(mmdisp->mapColumns);
530
} /* multiMapDisplayDestroy */
532
static void multiMapDraw (MultiMap mmdisp)
536
if (!graphActivate(mmdisp->graph))
539
windowTitle = displayGetTitle("DtMULTIMAP");
540
if (strcmp(windowTitle, "DtMULTIMAP") == 0)
541
windowTitle = "Multi Map"; /* if unchanged in displays.wrm */
543
if (strlen(mmdisp->title) > 0)
544
graphRetitle(messprintf("%s : %s",
545
windowTitle, mmdisp->title));
547
graphRetitle(messprintf("%s : untitled", windowTitle));
553
multiMapConvert(mmdisp) ;
554
multiMapWhole () ; /* sets ->centre, ->mag and calls Draw() */
560
static void multiMapResize (void)
562
MultiMap mmdisp = currentMultiMap("multiMapResize") ;
564
multiMapDrawKey (mmdisp, 0) ;
567
/***********************************/
569
static void multiMapPick (int box, double x, double y, int modifier_unused)
573
MultiMap mmdisp = currentMultiMap("multiMapPick") ;
578
if (box == mmdisp->cursorBox)
579
graphBoxDrag (mmdisp->cursorBox, multiMapDragCursor) ;
582
for (i = 0; i < arrayMax(mmdisp->mapColumns); i++)
584
mcol = arrp(mmdisp->mapColumns, i, MapColumn) ;
586
if (box == mcol->subTitleBox ||
587
box == mcol->mapColBox)
589
if (mcol != mmdisp->activeMapColumn)
591
if (mmdisp->activeMapColumn &&
592
mmdisp->activeMapColumn->subTitleBox)
593
graphBoxDraw(mmdisp->activeMapColumn->subTitleBox, BLACK, WHITE) ;
594
mmdisp->activeMapColumn = mcol ;
595
if (mmdisp->activeMapColumn->subTitleBox)
596
graphBoxDraw(mmdisp->activeMapColumn->subTitleBox, BLACK, LIGHTGREEN) ;
597
drawChromosomeBox(mmdisp) ;
604
if (box == mmdisp->activeColBox)
605
multiMapFollow (mmdisp, x, y) ;
607
multiMapSelect (mmdisp, box) ;
612
/*********************/
614
static void multiMapClear (void)
617
MultiMap mmdisp = currentMultiMap("multiMapClear") ;
619
if (mmdisp->activeColBox && arrp(mmdisp->mapBoxes, mmdisp->activeColBox,BOX)->seg)
620
curr = arrp(mmdisp->mapBoxes,mmdisp->activeColBox,BOX)->seg->key ;
624
multiMapDrawKey (mmdisp, curr) ;
627
} /* multiMapClear */
630
static void multiMapSelect (MultiMap mmdisp, int box)
635
if (mmdisp->activeColBox)
637
graphBoxDraw (mmdisp->activeColBox, BLACK, LIGHTBLUE) ;
638
seg = friend = arrp(mmdisp->mapBoxes, mmdisp->activeColBox, BOX)->seg ;
639
while (friend = friend->friends, friend != seg)
641
graphBoxDraw (friend->ibox, BLACK, LIGHTBLUE) ;
644
if ((seg = arrp(mmdisp->mapBoxes, box, BOX)->seg))
646
mmdisp->activeColBox = box ;
647
graphBoxDraw (mmdisp->activeColBox, BLACK, RED) ;
648
seg = friend = arrp(mmdisp->mapBoxes, mmdisp->activeColBox, BOX)->seg ;
649
while (friend = friend->friends, friend != seg)
651
graphBoxDraw (friend->ibox, BLACK, LIGHTRED) ;
654
if (mcol != mmdisp->activeMapColumn)
656
if (mmdisp->activeMapColumn && /* check if we had no
657
* previously selected column */
658
mmdisp->activeMapColumn->subTitleBox)
659
graphBoxDraw(mmdisp->activeMapColumn->subTitleBox, BLACK, WHITE) ;
660
mmdisp->activeMapColumn = mcol ;
661
if (mmdisp->activeMapColumn->subTitleBox)
662
graphBoxDraw(mmdisp->activeMapColumn->subTitleBox, BLACK, LIGHTGREEN) ;
663
drawChromosomeBox(mmdisp) ;
666
graphActivate(spread->dataGraph) ;
667
spreadSelectFromMap(spread, seg->line, c->colonne) ;
668
graphActivate(spread->mapGraph) ;
672
mmdisp->activeColBox = 0 ;
675
} /* multiMapSelect */
678
static void multiMapFollow (MultiMap mmdisp, double x, double y)
682
seg = arrp(mmdisp->mapBoxes, mmdisp->activeColBox, BOX)->seg ;
683
if (seg && seg->parent)
685
if (seg->grandParent)
687
if (display (seg->parent, seg->grandParent, 0))
688
displayPreserve() ; /* automatically preserve the called map */
691
display (seg->parent, 0, "TREE") ;
694
} /* multiMapFollow */
696
/*****************************************/
698
/**************************************************/
699
/**************** drawing info ********************/
701
static int segpOrder(void *a, void *b)
703
SEG *seg1 = *(SEG**)a;
704
SEG *seg2 = *(SEG**)b;
708
if (seg1->mcol && seg2->mcol)
709
return ya > yb ? 1 : ( ya == yb ? 0 : -1 ) ;
710
if (seg1->mcol) /* !seg2-> implied */
714
return seg1 < seg2 ? -1 : 1 ;
717
/***********************************************/
719
/********* start off with some utility routines ********/
721
static void getNxNy(void)
723
graphFitBounds (&nx, &ny) ;
724
yLength = (ny - topMargin - bottomMargin) ;
725
yCentre = topMargin + 0.5*yLength ;
728
/***************************************/
730
static void multiMapWhole (void)
735
MultiMap mmdisp = currentMultiMap("multiMapWhole") ;
738
if (!mmdisp->activeMapColumn || mmdisp->zoomAll)
740
maxCol = arrayMax(mmdisp->mapColumns) ;
741
for(j = 0 ; j < maxCol ; j++)
743
mcol = arrp(mmdisp->mapColumns, j, MapColumn) ;
744
if (!j || mcol->isMappable)
746
l = mcol->max - mcol->min ;
747
mcol->centre = mcol->min + 0.5 * l ;
750
mcol->mag = .9 * yLength / l ;
751
mmdisp->activeMapColumn = mcol ;
757
mcol = mmdisp->activeMapColumn;
758
if (mcol && mcol->mag) /* will work on name collone */
760
l = mcol->max - mcol->min ;
763
mcol->centre = mcol->min + 0.5 * l ;
764
mcol->mag = .9 * yLength / l ;
768
multiMapDrawKey (mmdisp, 0) ;
771
} /* multiMapWhole */
773
static void multiMapZoomIn (void)
777
MultiMap mmdisp = currentMultiMap("multiMapZoomIn") ;
781
maxCol = arrayMax(mmdisp->mapColumns) ;
782
for(j = 0 ; j < maxCol ; j++)
784
mcol = arrp(mmdisp->mapColumns, j, MapColumn) ;
785
if (!j || mcol->isMappable)
790
if (mmdisp->activeMapColumn)
792
mcol = mmdisp->activeMapColumn;
797
multiMapDrawKey (mmdisp, 0) ;
800
} /* multiMapZoomIn */
803
static void multiMapZoomOut (void)
807
MultiMap mmdisp = currentMultiMap("multiMapZoomIn") ;
811
maxCol = arrayMax(mmdisp->mapColumns) ;
812
for(j = 0 ; j < maxCol ; j++)
814
mcol = arrp(mmdisp->mapColumns, j, MapColumn) ;
815
if (!j || mcol->isMappable)
820
if (mmdisp->activeMapColumn)
822
mcol = mmdisp->activeMapColumn;
827
multiMapDrawKey (mmdisp, 0) ;
830
} /* multiMapZoomOut */
833
static void multiMapZoomAll (void)
835
MultiMap mmdisp = currentMultiMap("multiMapZoomAll") ;
837
mmdisp->zoomAll = TRUE ;
838
graphBoxDraw(mmdisp->allButton, BLACK, LIGHTBLUE) ;
839
graphBoxDraw(mmdisp->allButton + 1, BLACK, WHITE) ;
842
} /* multiMapZoomAll */
845
static void multiMapZoomActive (void)
847
MultiMap mmdisp = currentMultiMap("multiMapZoomActive") ;
849
mmdisp->zoomAll = FALSE ;
850
graphBoxDraw(mmdisp->allButton + 1, BLACK, LIGHTBLUE) ;
851
graphBoxDraw(mmdisp->allButton, BLACK, WHITE) ;
854
} /* multiMapZoomActive */
857
static void multiMapChangeSymbolSize (void)
861
size_in = messPrompt ("Change size of little square symbols to",
862
messprintf ("%f", symbolSize_L), "fz", 0);
865
aceInFloat (size_in, &symbolSize_L) ;
866
aceInDestroy (size_in);
870
} /* multiMapChangeSymbolSize */
873
static void multiMapFlip (void)
879
MultiMap mmdisp = currentMultiMap("multiMapFlip") ;
881
mcol = mmdisp->activeMapColumn ;
885
mcol->isFlipMap = ! mcol->isFlipMap ;
887
i = arrayMax(mcol->segs) ;
888
seg = arrp(mcol->segs, 0, SEG) - 1 ;
890
if (seg->mcol == mcol)
893
mcol->min = - mcol->max ; mcol->max = - tmp ;
894
mcol->centre = - mcol->centre ;
896
multiMapDrawKey (mmdisp, 0) ;
901
/**************************************************************/
902
/***************** dragging code - middle button **************/
904
static double oldy, oldDy, oldx;
905
static BOOL dragFast ;
906
#define DRAGFASTLIMIT xScale
908
static void multiMapMiddleDrag (double x, double y)
912
graphXorLine (0, oldy - oldDy, DRAGFASTLIMIT, oldy - oldDy) ;
913
graphXorLine (0, oldy + oldDy, DRAGFASTLIMIT, oldy + oldDy) ;
916
graphXorLine (DRAGFASTLIMIT, oldy, nx, oldy) ;
922
oldDy *= exp ((x - oldx) / 25.) ;
924
graphXorLine (0, y - oldDy, DRAGFASTLIMIT, y - oldDy) ;
925
graphXorLine (0, y + oldDy, DRAGFASTLIMIT, y + oldDy) ;
928
graphXorLine (DRAGFASTLIMIT, y, nx, y) ;
931
} /* multiMapMiddleDrag */
934
static void multiMapMiddleUp (double x, double y)
939
MultiMap mmdisp = currentMultiMap("multiMapMiddleUp") ;
943
maxCol = arrayMax(mmdisp->mapColumns) ;
944
for(j = 0 ; j < maxCol ; j++)
946
mcol = arrp(mmdisp->mapColumns,j, MapColumn) ;
947
if (!j || mcol->isMappable)
951
graphBoxDim (mmdisp->cursorBox, &x1, &y1, &x2, &y2) ;
952
mcol->mag *= (y2 - y1) / (2. * oldDy) ;
953
mcol->centre = mcol->min +
954
(mcol->max - mcol->min) * (y - topMargin) / yLength ;
957
mcol->centre += (y - 0.5 - yCentre) / mcol->mag ;
962
if (mmdisp->activeMapColumn)
964
mcol = mmdisp->activeMapColumn ;
967
graphBoxDim (mmdisp->cursorBox, &x1, &y1, &x2, &y2) ;
968
mcol->mag *= (y2 - y1) / (2. * oldDy) ;
969
mcol->centre = mcol->min +
970
(mcol->max - mcol->min) * (y - topMargin) / yLength ;
973
mcol->centre += (y - 0.5 - yCentre) / mcol->mag ;
976
multiMapDrawKey (mmdisp, 0) ;
979
} /* multiMapMiddleUp */
981
static void multiMapMiddleDown (double x, double y)
984
MultiMap mmdisp = currentMultiMap("multiMapMiddleDown") ;
988
graphBoxDim (mmdisp->cursorBox, &x1, &y1, &x2, &y2) ;
989
oldDy = (y2 - y1) / 2. ;
991
dragFast = (x < DRAGFASTLIMIT) ? TRUE : FALSE ;
995
graphXorLine (0, y - oldDy, DRAGFASTLIMIT, y - oldDy) ;
996
graphXorLine (0, y + oldDy, DRAGFASTLIMIT, y + oldDy) ;
999
graphXorLine (DRAGFASTLIMIT, y, nx, y) ;
1003
graphRegister (MIDDLE_DRAG, multiMapMiddleDrag) ;
1004
graphRegister (MIDDLE_UP, multiMapMiddleUp) ;
1007
} /* multiMapMiddleDown */
1009
static void multiMapDragCursor (float *x, float *y, BOOL isDone)
1016
MultiMap mmdisp = currentMultiMap("multiMapDragCursor") ;
1019
graphBoxDim (mmdisp->cursorBox, &x1, &y1, &x2, &y2) ;
1020
if (mmdisp->zoomAll)
1022
maxCol = arrayMax(mmdisp->mapColumns) ;
1023
for(j = 0 ; j < maxCol ; j++)
1025
mcol = arrp(mmdisp->mapColumns,j, MapColumn) ;
1026
if (!j || mcol->isMappable)
1027
mcol->centre = mcol->min + (mcol->max - mcol->min) *
1028
((*y + 0.5*(y2-y1)) - topMargin) / yLength ;
1032
if (mmdisp->activeMapColumn)
1034
mcol = mmdisp->activeMapColumn ;
1035
mcol->centre = mcol->min + (mcol->max - mcol->min) *
1036
((*y + 0.5*(y2-y1)) - topMargin) / yLength ;
1039
multiMapDrawKey (mmdisp, 0) ;
1042
*x = xCursor - 0.5 ;
1045
} /* multiMapDragCursor */
1047
/**************************************************/
1048
/**************************************************/
1050
static void drawScale (MapColumn *mcol, int xScale1)
1052
float cutoff = 5 / mcol->mag ;
1054
float subunit = 0.001 ;
1055
float x, xx, y, start, end ;
1057
while (unit < cutoff)
1070
start = SPRDGRAPH2MAP(mcol, topMargin) ;
1071
if (start < mcol->min)
1073
end = SPRDGRAPH2MAP(mcol, ny-bottomMargin) ;
1074
if (end > mcol->max)
1077
x = unit * (((start > mcol->min) ? 1 : 0) + (int)(start/unit)) ;
1080
y = SPRDMAP2GRAPH(mcol, x) ;
1082
xx = mcol->isFlipMap ? -x : x ;
1083
graphLine (xScale1-1.5,y,xScale1-0.5,y) ;
1085
graphText (messprintf ("%-4.0f",xx),xScale1,y-.5) ;
1087
graphText (messprintf ("%-4.1f",xx),xScale1,y-.5) ;
1088
else if(unit >= .01)
1089
graphText (messprintf ("%-4.2f",xx),xScale1,y-.5) ;
1090
else if(unit >= .001)
1091
graphText (messprintf ("%-4.3f",xx),xScale1,y-.5) ;
1096
x = subunit * (((start >= mcol->min)? 1 : 0) + (int)(start/subunit)) ;
1099
y = SPRDMAP2GRAPH(mcol, x) ;
1100
graphLine (xScale1-1.0,y,xScale1-0.5,y) ;
1104
graphLine (xScale1-0.5, SPRDMAP2GRAPH(mcol,start),
1105
xScale1-0.5, SPRDMAP2GRAPH(mcol,end)) ;
1112
static void drawChromosomeBox (MultiMap mmdisp)
1114
MapColumn *mcol = mmdisp->activeMapColumn ;
1119
if (mmdisp->chromoBox)
1120
graphBoxClear(mmdisp->chromoBox) ;
1122
mmdisp->chromoBox = graphBoxStart() ;
1123
graphFillRectangle (xCursor - 0.25, topMargin,
1124
xCursor + 0.25, ny - bottomMargin) ;
1125
mmdisp->cursorBox = graphBoxStart() ;
1127
arrayp(mmdisp->mapBoxes, mmdisp->cursorBox, BOX)->seg = 0 ;
1129
if (mcol->max != mcol->min)
1130
graphRectangle (xCursor - 0.5,
1131
MAP2CHROM(SPRDGRAPH2MAP(mcol, topMargin)),
1133
MAP2CHROM(SPRDGRAPH2MAP(mcol, ny - bottomMargin))) ;
1136
graphBoxDraw (mmdisp->chromoBox,BLACK, WHITE) ;
1137
graphBoxDraw (mmdisp->cursorBox,DARKGREEN,GREEN) ;
1140
} /* drawChromosomeBox */
1144
static void drawChromosomeLine (MultiMap mmdisp)
1148
mmdisp->chromoBox = 0 ;
1151
graphColor (DARKGRAY) ;
1152
graphLine (xCursor, MAP2CHROM(SPRDGRAPH2MAP(c,topMargin)),
1153
xScale-0.5, topMargin ) ;
1154
graphLine (xCursor, MAP2CHROM(SPRDGRAPH2MAP(c,ny - bottomMargin)),
1155
xScale-0.5, ny - bottomMargin) ;
1156
graphColor (BLACK) ;
1159
graphTextHeight (0.75) ;
1160
for (i = 0 ; i <= 10 ; ++i)
1161
graphText (messprintf ("%3d%%",10*i),
1162
1, topMargin + yLength * i / 10.0 - 0.25) ;
1163
graphTextHeight (0) ;
1167
} /* drawChromosomeLine */
1169
/***********************************************/
1171
static void multiMapBoxEnd (int ibox, BOX *box)
1174
if (box->seg && box->seg->flag & FLAG_HIGHLIGHT)
1175
graphBoxDraw (ibox, BLACK, MAGENTA) ;
1177
graphBoxDraw (ibox, BLACK, box->color) ;
1180
} /* multiMapBoxEnd */
1182
/***********************************************/
1184
static Array multiMapFindLimits(TABLE *table, Array isFlipMapArray)
1186
int rowNum, colNum, colNum1 ;
1187
BOOL isSuccess = FALSE ;
1191
Array mapColumns = arrayCreate(table->ncol, MapColumn);
1193
if (table->ncol == 0)
1194
messcrash("multiMapFindLimits() - received table without columns");
1196
for(colNum = 0 ; colNum < table->ncol ; colNum++)
1198
mcol = arrayp(mapColumns, colNum, MapColumn);
1200
mcol->type = table->type[colNum];
1202
if (isFlipMapArray && array(isFlipMapArray, colNum, BOOL))
1203
mcol->isFlipMap = TRUE;
1205
mcol->isFlipMap = FALSE;
1207
if ((mcol->type == 'i' || mcol->type == 'f') /*&& !mcol->isHidden*/)
1208
mcol->isMappable = TRUE;
1211
mcol->isMappable = FALSE;
1216
for (rowNum = 0 ; rowNum < tabMax(table, colNum) ; rowNum++)
1220
if (!tabEmpty(table, rowNum, colNum))
1221
switch (table->type[colNum])
1225
y = (float)tabInt(table, rowNum, colNum) ;
1229
y = tabFloat(table, rowNum, colNum) ;
1235
y = mcol->isFlipMap ? -y : y ;
1251
for(colNum = 0 ; colNum < table->ncol ; colNum++)
1253
mcol = arrp(mapColumns, colNum, MapColumn);
1254
if (!mcol->isMappable /*&& !mcol->isHidden*/)
1256
for(colNum1 = table->ncol-1 ; colNum1 >= 0 ; colNum1--)
1259
mcol1 = arrp(mapColumns,colNum1, MapColumn) ;
1261
if(mcol1->isMappable)
1263
mcol->min = mcol1->min ;
1264
mcol->max = mcol1->max ;
1272
arrayDestroy(mapColumns);
1277
} /* multiMapFindLimits */
1279
/************************************************************/
1281
static void multiMapConvert (MultiMap mmdisp)
1284
int rowNum, rowMax, colNum, colMax ;
1288
colMax = mmdisp->table->ncol ;
1289
rowMax = tableMax(mmdisp->table);
1291
for (colNum = 0 ; colNum < colMax ; colNum++)
1293
mcol = arrp(mmdisp->mapColumns, colNum, MapColumn);
1295
if (colNum == 0 || mcol->isMappable)
1296
mcol->segs = arrayReCreate (mcol->segs, rowMax, SEG) ;
1298
arrayDestroy(mcol->segs) ;
1301
for(rowNum = 0 ; rowNum < rowMax ; rowNum++)
1305
for(colNum = 0 ; colNum < colMax ; colNum++)
1307
mcol = arrp(mmdisp->mapColumns, colNum, MapColumn);
1309
if (!mcol->isMappable)
1312
if (tabEmpty(mmdisp->table, rowNum, colNum))
1315
seg = arrayp(mcol->segs, rowNum, SEG) ;
1316
seg->line = rowNum ;
1320
seg->friends = oldSeg->friends ;
1321
oldSeg->friends = seg ;
1325
seg->friends = seg ; /* loop ! */
1332
y = (float)tabInt(mmdisp->table, rowNum, colNum) ;
1335
y = tabFloat(mmdisp->table, rowNum, colNum) ;
1338
seg->y = mcol->isFlipMap ? -y : y ;
1339
seg->parent = tabParent(mmdisp->table, rowNum, colNum) ;
1340
seg->grandParent = tabGrandParent(mmdisp->table, rowNum, colNum) ;
1343
/* Now the names - they are the keys in the master-column No 0 */
1344
mcol = arrp(mmdisp->mapColumns, 0, MapColumn);
1345
seg = arrayp(mcol->segs, rowNum, SEG) ;
1347
seg->key = tabKey(mmdisp->table, rowNum, 0);
1348
seg->parent = tabKey(mmdisp->table, rowNum, 0);
1349
seg->grandParent = 0 ;
1351
seg->line = rowNum ;
1352
seg->flag = FLAG_NAME ;
1356
seg->friends = oldSeg->friends ;
1357
oldSeg->friends = seg ;
1358
seg->y = seg->friends->y ;
1361
seg->friends = seg ; /* loop ! */
1365
for(colNum = 0 ; colNum < colMax ; colNum++)
1367
mcol = arrp(mmdisp->mapColumns, colNum, MapColumn);
1371
mcol->segps = arrayReCreate (mcol->segps, rowMax, SEG*) ;
1373
zsp = arrayp(mcol->segps, rowNum - 1, SEG*) ;
1374
zs = arrp(mcol->segs, rowNum - 1, SEG) ;
1381
} /* multiMapConvert */
1385
static void multiMapDrawKeyC(MapColumn *mcol, Array mapBoxes, float x)
1387
int i = arrayMax(mcol->segs), ibox, oldFormat ;
1388
SEG *seg = arrp(mcol->segs, 0, SEG) - 1 ;
1390
int screenMin = topMargin, screenMax = ny - bottomMargin ;
1397
if (seg->ys > screenMin && seg->ys < screenMax + 30)
1399
ibox = graphBoxStart() ;
1400
box = arrayp(mapBoxes, ibox, BOX) ;
1403
box->color = YELLOW ;
1405
if (seg->flag & FLAG_NAME)
1407
box->color = WHITE ;
1408
if (iskey(seg->key) == 2)
1409
oldFormat = graphTextFormat(BOLD) ;
1410
graphText (name(seg->key), x + seg->xs, seg->ys) ;
1411
if (iskey(seg->key) == 2)
1412
graphTextFormat(oldFormat) ;
1413
seg->x = x + seg->xs ;
1417
graphLine(x , seg->ys, x + symbolSize_L, seg->ys ) ;
1418
graphLine(x , seg->ys , x , seg->ys + .5) ;
1420
seg->x = x + seg->xs ;
1422
multiMapBoxEnd(ibox, box) ;
1425
{ seg->x = x ; /* needed to draw lines */
1429
} /* multiMapDrawKeyC */
1433
static void multiMapDrawKeyLines(Array segs)
1436
int i = arrayMax(segs) ;
1437
int screenMin = topMargin, screenMax = ny - bottomMargin ;
1438
SEG *friend, *seg = arrp(segs, 0, SEG) - 1 ;
1443
x = seg->x ; y = seg->ys ;
1444
if (seg->mcol) /* may be zero if line is hidden */
1445
while (friend = friend->friends, friend != seg)
1447
if ((y > screenMin && y < screenMax) ||
1448
(friend->ys > screenMin && friend->ys < screenMax))
1449
if (x - friend->x < 26) /* I hope nearest neighbours */
1450
graphLine(x, y, friend->x + symbolSize_L, friend->ys) ;
1451
x = friend->x ; y = friend->ys ;
1456
} /* multiMapDrawKeyLines */
1460
static void multiMapBump (MapColumn *mcol)
1462
int i = arrayMax(mcol->segs) ;
1464
int screenMin = topMargin ;
1465
float h = freelower(mcol->type) == 'k' ? 1 : .01 ;
1466
segp = arrp(mcol->segps, 0, SEG*) ;
1475
if ((seg->flag & FLAG_NAME)
1477
seg->ys = SPRDMAP2GRAPH (seg->friends->mcol, seg->y) ;
1479
seg->ys = SPRDMAP2GRAPH (seg->mcol, seg->y) ;
1482
i = arrayMax(mcol->segs) ;
1483
arraySort(mcol->segps, segpOrder) ;
1485
mcol->bump = bumpReCreate(mcol->bump, 1, ny) ;
1487
segp = arrp(mcol->segps, 0, SEG*) ;
1491
if (!(seg->flag & FLAG_NAME) || seg->ys >= screenMin)
1492
bumpItem(mcol->bump, 1, h, &seg->xs, &seg->ys) ;
1498
static void multiMapDrawKey (MultiMap mmdisp, KEY curr)
1501
MapColumn *mcol, *lastmcol ;
1503
mmdisp->mapBoxes = arrayReCreate (mmdisp->mapBoxes, 64, BOX) ;
1504
mmdisp->activeColBox = 0 ;
1505
if (mmdisp->activeMapColumn && !mmdisp->activeMapColumn->isMappable)
1506
mmdisp->activeMapColumn = 0 ;
1512
graphColor (BLACK) ;
1514
{ messout ("Sorry, this window is too small for a multi map") ;
1517
drawChromosomeLine (mmdisp) ;
1520
maxCol = arrayMax(mmdisp->mapColumns) ;
1522
if (strlen(mmdisp->title) > 0)
1523
graphText(mmdisp->title, 32, 1.5) ;
1526
for(j = 0 ; j < maxCol ; j++)
1528
mcol = arrp(mmdisp->mapColumns, j, MapColumn) ;
1530
if (mcol->isMappable)
1532
drawScale(mcol, x) ;
1535
multiMapBump(mcol) ;
1537
mcol->mapColBox = graphBoxStart() ;
1539
multiMapDrawKeyC(mcol, mmdisp->mapBoxes, x) ;
1540
if (strlen(tableGetColumnName(mmdisp->table, j)) > 0)
1542
mcol->subTitleBox = graphBoxStart() ;
1543
graphText(tableGetColumnName(mmdisp->table, j), x, 5) ;
1547
mcol->subTitleBox = 0;
1549
graphBoxEnd() ; /* mapColBox */
1551
x += 3 * symbolSize_L + 2 ;
1553
if (!mmdisp->activeMapColumn)
1554
mmdisp->activeMapColumn = mcol ;
1557
drawChromosomeBox (mmdisp) ;
1559
arrp(mmdisp->mapColumns, 0, MapColumn)->mag = mcol->mag ;
1560
arrp(mmdisp->mapColumns, 0, MapColumn)->centre = mcol->centre ;
1561
arrp(mmdisp->mapColumns, 0, MapColumn)->min = mcol->min ;
1562
arrp(mmdisp->mapColumns, 0, MapColumn)->max = (mcol->max > mcol->min ? mcol->max : mcol->max + 1) ;
1563
mcol = arrp(mmdisp->mapColumns, 0, MapColumn) ;
1565
multiMapBump(mcol) ;
1566
multiMapDrawKeyC(mcol, mmdisp->mapBoxes, x) ;
1567
multiMapDrawKeyLines(mcol->segs) ;
1569
mmdisp->allButton = graphButton ("Zoom All", multiMapZoomAll, 5, 0.5) ;
1570
graphButton ("Zoom Active", multiMapZoomActive, 15, 0.5) ; /* has to be the box right after the "Zoom All" button */
1572
if (mmdisp->zoomAll)
1574
graphBoxDraw(mmdisp->allButton, BLACK, LIGHTBLUE) ;
1575
graphBoxDraw(mmdisp->allButton + 1, BLACK, WHITE) ;
1579
graphBoxDraw(mmdisp->allButton + 1, BLACK, LIGHTBLUE) ;
1580
graphBoxDraw(mmdisp->allButton, BLACK, WHITE) ;
1582
graphButtons (buttonOpts, 5, 2.5, nx) ;
1584
mmdisp->activeMapColumn = 0 ; /* ? ? ? */
1585
if (mmdisp->activeMapColumn && mmdisp->activeMapColumn->subTitleBox)
1586
graphBoxDraw(mmdisp->activeMapColumn->subTitleBox, BLACK, LIGHTGREEN) ;
1591
} /* multiMapDrawKey */
1593
/*********************************************************/
1594
/* This routine is a bit artificial in that it used to dig in
1595
* the internals of graph but this has been changed so that it uses
1596
* some calls provided by graph just to support it.
1598
static void myMapPrint(void)
1604
float olduh, newuh ;
1607
MultiMap mmdisp = currentMultiMap("myMapPrintWhole") ;
1610
mcol = mmdisp->activeMapColumn ;
1613
messerror ("No active column");
1617
min = mcol->min ; max = mcol->max ;
1618
zone_in = messPrompt("Please state the zone you wish to print",
1619
messprintf("%g %g", min, max), "ff", 0);
1623
aceInFloat(zone_in, &min) ; aceInFloat(zone_in, &max) ;
1624
aceInDestroy (zone_in);
1628
if (min < mcol->min)
1630
if (max > mcol->max)
1633
oldcentre = mcol->centre ;
1634
mcol->centre = (max + min) / 2 ;
1636
/* Record current settings of active graph height etc. */
1637
graphGetSprdmapData(&oldh, &olduh, &oldtype, &yfac) ;
1639
/* Set a new height and draw the map. */
1640
newuh = 1.05 * (max - min) * mcol->mag + topMargin + 5 ;
1641
newh = newuh * yfac ;
1642
graphSetSprdmapCoords(newh, newuh) ;
1643
multiMapDrawKey (mmdisp, 0) ;
1645
/* OK, now it's drawn we can print it. */
1646
graphSetSprdmapType(TEXT_SCROLL) ;
1648
graphSetSprdmapType(oldtype) ;
1650
/* Restore the old graph height settings and redraw the map. */
1651
graphSetSprdmapCoords(oldh, olduh) ;
1652
mcol->centre = oldcentre ;
1653
multiMapDrawKey (mmdisp, 0) ;
1658
/*************************** eof ****************************/