~ubuntu-branches/ubuntu/precise/acedb/precise

« back to all changes in this revision

Viewing changes to w6/multimapdisp.c

  • Committer: Bazaar Package Importer
  • Author(s): Steffen Moeller
  • Date: 2010-07-11 06:27:12 UTC
  • Revision ID: james.westby@ubuntu.com-20100711062712-f1mtli96gavo7mk4
Tags: upstream-4.9.39
ImportĀ upstreamĀ versionĀ 4.9.39

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  File: sprdmap.c
 
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.
 
9
 * 
 
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.
 
14
 * 
 
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
 
23
 *
 
24
 * Description:
 
25
 **  The aim of this tool is to display on a unique graph as many
 
26
 **  system of maps as control by sprdctrl.c
 
27
 * Exported functions:
 
28
 * HISTORY:
 
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
 *-------------------------------------------------------------------
 
36
 */
 
37
 
 
38
#include <wh/acedb.h>
 
39
#include <wh/aceio.h>
 
40
#include <wh/bs.h>
 
41
#include <wh/bump.h>
 
42
#include <wh/table.h>
 
43
#include <wh/lex.h>
 
44
#include <wh/pick.h>
 
45
#include <wh/query.h>
 
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>
 
53
 
 
54
BITSET_MAKE_BITFIELD      /* define bitField for bitset.h ops */
 
55
 
 
56
/************************************************************/
 
57
 
 
58
typedef struct MapColumnStruct MapColumn;
 
59
typedef struct SegStruct SEG;
 
60
 
 
61
struct MapColumnStruct {
 
62
  char type;
 
63
  BOOL isMappable;
 
64
  BOOL isFlipMap;
 
65
  float mag, centre, min, max;
 
66
 
 
67
  Array segs , segps ;  /* segps are used to reorder the segs without loosing the friend info */
 
68
  int subTitleBox;
 
69
  int mapColBox;
 
70
  BUMP bump ; 
 
71
} ;
 
72
 
 
73
struct SegStruct {
 
74
  KEY key ;
 
75
  int line ;
 
76
  MapColumn *mcol;
 
77
  int x, xs ; float y, ys ;    
 
78
  int flag ;
 
79
  SEG *friends ;  /* Loop of related segs */
 
80
  int ibox ;
 
81
  KEY parent, grandParent ;
 
82
} ;
 
83
 
 
84
typedef struct {
 
85
  SEG* seg ;            /* pointer OK: segs fixed when drawing */
 
86
  int  color ;
 
87
  float xs, ys ;
 
88
} BOX ;
 
89
 
 
90
 
 
91
 
 
92
static magic_t MultiMap_MAGIC = "MultiMap";
 
93
 
 
94
typedef struct MultiMapStruct {
 
95
  magic_t *magic;
 
96
 
 
97
  Graph graph, parentGraph;
 
98
 
 
99
  TABLE *table;
 
100
  char *title;
 
101
  BOOL zoomAll ;
 
102
  Array mapColumns;             /* of type MapColumn */
 
103
  MapColumn *activeMapColumn ;
 
104
  int activeColBox ;
 
105
  Array mapBoxes ;
 
106
  int  cursorBox , chromoBox , allButton ;
 
107
} *MultiMap;
 
108
 
 
109
 
 
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 */
 
117
 
 
118
static float    symbolSize_L = 3.0 ; /* size of little squares */
 
119
 
 
120
static BOOL isPapDisp = FALSE ;
 
121
 
 
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)
 
126
 
 
127
#define MAP2CHROM(x) \
 
128
  (topMargin + yLength * (x - mcol->min) / (mcol->max != mcol->min ? mcol->max - mcol->min : 1 ))
 
129
 
 
130
#define FLAG_HIGHLIGHT 1        /* not implemented yet */
 
131
#define FLAG_INSITU 2
 
132
#define FLAG_NAME 4
 
133
 
 
134
/************************************************************/
 
135
 
 
136
/* p1, p2 are used for contigs: multiMap <-> pmap
 
137
                   for in_situ data for in_situ clones
 
138
*/
 
139
 
 
140
 
 
141
static void multiMapDisplayDestroy (void);
 
142
static void multiMapDraw (MultiMap mmdisp);
 
143
static MultiMap currentMultiMap (char *caller);
 
144
 
 
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) ;
 
157
 
 
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);
 
164
 
 
165
static void myMapPrint(void) ;
 
166
 
 
167
static Array multiMapFindLimits(TABLE *table, Array isFlipMapArray);
 
168
 
 
169
/************************************************************/
 
170
 
 
171
static MENUOPT multiMapMenu[] = { 
 
172
  {graphDestroy,              "Quit"},
 
173
  {help,                      "Help"},
 
174
  {graphPrint,                "Print Screen"},
 
175
  {myMapPrint,                "Print Whole Map"},
 
176
  {menuSpacer,                ""},
 
177
  {displayPreserve,           "Preserve"},
 
178
  {multiMapChangeSymbolSize, "Symbol size"},
 
179
  {0, 0}
 
180
} ;
 
181
 
 
182
static MENUOPT buttonOpts[] = {
 
183
  {multiMapWhole,   "Whole"}, 
 
184
  {multiMapZoomIn,  "Zoom In"},
 
185
  {multiMapZoomOut, "Zoom Out"},
 
186
  {multiMapClear,   "Clear"},
 
187
  {multiMapFlip,    "Flip"},
 
188
  {0, 0}
 
189
} ;
 
190
 
 
191
/************************************************************/
 
192
 
 
193
/*
 
194
 * DisplayFunc for _VMultiMap objects
 
195
 */
 
196
BOOL multiMapDisplay (KEY key, KEY from, BOOL isOldGraph, void *unused) 
 
197
{ OBJ obj ;
 
198
  KEY map, anchor = 0 , anchor_group;
 
199
  int n = 0 , cl, minMap = 2 ;
 
200
  KEYSET ks ;
 
201
  char *cp ;
 
202
  BOOL isSuccess;
 
203
 
 
204
  if (key == KEY_UNDEFINED || class(key) != _VMultiMap || !(obj = bsCreate(key)))
 
205
    {
 
206
      return FALSE ;
 
207
    }
 
208
 
 
209
  ks = keySetCreate();
 
210
 
 
211
  bsGetData(obj, _Min, _Int, &minMap) ;
 
212
  if (minMap <1) minMap = 1 ;
 
213
  if (bsGetKey(obj, _Map, &map))
 
214
    do {          
 
215
         keySet(ks, n++) = map ;
 
216
       } while (bsGetKey(obj, _bsDown, &map)) ;
 
217
  if (minMap >n)
 
218
    minMap = n ;
 
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)) ;
 
225
  else
 
226
    { cl = 0 ; anchor = 0 ; anchor_group = 0 ; }
 
227
  bsDestroy(obj) ;
 
228
 
 
229
  isSuccess = multiMapDisplayKeySet (name(key), ks, cl, anchor_group, anchor, minMap);
 
230
 
 
231
  keySetDestroy (ks);           /* is this correct here ? */
 
232
 
 
233
 return isSuccess;
 
234
} /* multiMapDisplay */
 
235
 
 
236
/************************************************************/
 
237
 
 
238
BOOL multiMapDisplayKeySet (char *title, KEYSET ks, int cl, 
 
239
                            KEY anchor_group, KEY anchor, int minMap)
 
240
     /* also called from keySetDisplay */
 
241
{ OBJ obj ;
 
242
  Stack s = 0 ;
 
243
  KEYSET loci = 0 , loci1 = 0 ; 
 
244
  Array aa = 0;
 
245
  Array flipped ;
 
246
  int i, j, n = 0 ;
 
247
  SPREAD spread;
 
248
  TABLE *table;
 
249
  char *tableTitle;
 
250
 
 
251
  aa = arrayCreate(100, BSunit) ;
 
252
  loci = keySetCreate() ; n = 0 ;
 
253
  flipped = arrayCreate(12, BOOL) ;
 
254
 
 
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...");
 
258
 
 
259
  for (i = 0; i < keySetMax(ks); i++)
 
260
    {
 
261
      if (messIsInterruptCalled())
 
262
        {
 
263
          messout("Multimap interrupted...\n"
 
264
                  "Processed %d out of %d possible objects",
 
265
                  i, keySetMax(ks));
 
266
          break;
 
267
        }
 
268
      if ((obj = bsCreate(keySet(ks, i))))
 
269
        {
 
270
          arrayMax(aa) = 0 ;
 
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 ;
 
277
          bsDestroy(obj) ;
 
278
        }
 
279
    }
 
280
 
 
281
  if (keySetMax(loci) == 0)
 
282
    {
 
283
      messout("Objects do not contain loci\n"
 
284
              "Unable to make a multi-map !");
 
285
      return FALSE;
 
286
    }
 
287
 
 
288
  keySetSort(loci) ;
 
289
  keySetCompress(loci) ;
 
290
 
 
291
  s = stackCreate(100) ;
 
292
  if (!anchor)
 
293
    { 
 
294
      /*************** Multi-map ***************/
 
295
      loci1 = loci ;
 
296
      loci = query(loci1, "COUNT Map >= 1") ;  
 
297
      
 
298
      if (ks)
 
299
        {
 
300
          pushText(s,"Title \"") ;
 
301
          catText(s, "Multi-map") ;
 
302
          if (title)
 
303
            {
 
304
              catText (s, " ") ;
 
305
              catText (s, title) ;
 
306
            }
 
307
          catText (s, "\"\n\n") ;
 
308
          catText(s,"Colonne 1\n"
 
309
                  "Subtitle Locus\n"
 
310
                  "Width 12\nVisible\nClass Locus\n");
 
311
          catText(s,messprintf("Condition COUNT Map >= %d\n\n", minMap)) ;
 
312
          
 
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))) ;
 
319
              catText(s, "\"") ;
 
320
              catText(s," # Position") ;
 
321
              catText(s," \nVisible \nOptional") ;
 
322
              if (array(flipped,i,BOOL))
 
323
                catText(s,"\nFlipMap") ;
 
324
              catText(s, "\n\n") ;
 
325
            }
 
326
        }
 
327
    }
 
328
  else
 
329
    {
 
330
      /***************** Homology-map ****************/
 
331
      loci1 = loci ;
 
332
      loci = query(loci1, messprintf(">%s", name(anchor_group))) ;
 
333
      
 
334
      if (ks)
 
335
        {
 
336
          pushText(s,"Title \"") ;
 
337
          catText(s, "Homology-map") ;
 
338
          if (title)
 
339
            {
 
340
              catText (s, " ") ;
 
341
              catText (s, title) ;
 
342
            }
 
343
          catText (s, "\"\n\n") ;
 
344
          catText(s,"Colonne 1\n"
 
345
                  "Subtitle ");
 
346
          catText (s, pickClass2Word (cl)) ;
 
347
          catText(s, "\n"
 
348
                  "Width 12 \nVisible \nClass ") ;
 
349
          catText (s, pickClass2Word (cl)) ;
 
350
          catText (s, "\n") ;
 
351
          
 
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))) ;
 
360
              catText (s, "\n ") ;
 
361
              catText(s,"Condition Map = ") ;
 
362
              catText(s, freeprotect(name(keySet(ks,i)))) ;
 
363
              catText(s,"\n") ;
 
364
              catText(s," \nVisible \nOptional") ;
 
365
              catText(s, "\n\n") ;
 
366
 
 
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") ;
 
376
              catText(s, "\n\n") ;
 
377
            }
 
378
        }
 
379
    }
 
380
 
 
381
  /********** display data and multi-map for these definitions ********/
 
382
 
 
383
  /* parse definition Stack */
 
384
  spread = spreadCreateFromStack (s, NULL);
 
385
            
 
386
  table = spreadCalculateOverKeySet (spread, loci, NULL);
 
387
  tableTitle = spreadGetTitle (spread);
 
388
 
 
389
  /* display results */
 
390
  tableDisplayCreate (table, tableTitle, flipped, 0) ;
 
391
  multiMapDisplayCreate (table, tableTitle, flipped) ;
 
392
 
 
393
  /******** clean up ********/
 
394
 
 
395
  spreadDestroy (spread);
 
396
 
 
397
 
 
398
  keySetDestroy(loci) ;
 
399
  if (keySetExists(loci1))
 
400
    keySetDestroy(loci1) ;
 
401
 
 
402
  arrayDestroy(aa) ;
 
403
  arrayDestroy (flipped);
 
404
  stackDestroy(s) ;
 
405
 
 
406
  /* NOTE, do -NOT- destroy ks, it belongs to caller 
 
407
   * (e.g. keysetdisplay) */
 
408
 
 
409
  return TRUE ;
 
410
} /* multiMapDisplayKeySet */
 
411
 
 
412
/************************************************************/
 
413
 
 
414
Graph multiMapDisplayCreate (TABLE *table, char *title, Array isFlipMapArray)
 
415
{
 
416
  MultiMap mmdisp;
 
417
  Array mapColumns;
 
418
  Graph oldGraph = graphActive();
 
419
 
 
420
  mapColumns = multiMapFindLimits(table, isFlipMapArray);
 
421
 
 
422
  if (!mapColumns)
 
423
    { 
 
424
      messout("No visible numerical column in this spread sheet") ;
 
425
      return -1 ;
 
426
    }
 
427
  
 
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);
 
433
 
 
434
  mmdisp->mapColumns = mapColumns;
 
435
  mmdisp->parentGraph = oldGraph;
 
436
  mmdisp->zoomAll =  TRUE ;
 
437
 
 
438
  /* default for help, if undef in displays.wrm */
 
439
  if (graphHelp(0) == NULL)
 
440
    graphHelp("Multi_Map");
 
441
 
 
442
 
 
443
  graphMenu (multiMapMenu) ;
 
444
 
 
445
  graphAssociate (&MultiMap_MAGIC, mmdisp) ;
 
446
 
 
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) ;
 
453
 
 
454
 
 
455
  multiMapDraw (mmdisp);
 
456
 
 
457
  return mmdisp->graph;
 
458
} /* multiMapDisplayCreate */
 
459
 
 
460
 
 
461
 
 
462
void multiMapDisplayReCreate (TABLE *table, char *title, Array isFlipMapArray)
 
463
{
 
464
  MultiMap mmdisp = currentMultiMap("multiMapDisplayReCreate");
 
465
  Array mapColumns;
 
466
 
 
467
  mapColumns = multiMapFindLimits(table, isFlipMapArray);
 
468
 
 
469
  if (!mapColumns)
 
470
    { 
 
471
      messout("No visible numerical column in this spread sheet") ;
 
472
      return ;
 
473
    }
 
474
 
 
475
  messfree(mmdisp->title);
 
476
  mmdisp->title = strnew(title, 0);
 
477
 
 
478
  tableDestroy(mmdisp->table);
 
479
  mmdisp->table = tableCopy(table, 0);
 
480
 
 
481
  mmdisp->mapColumns = mapColumns;
 
482
 
 
483
  
 
484
  multiMapDraw (mmdisp);
 
485
 
 
486
  return;
 
487
} /* multiMapDisplayReCreate */
 
488
 
 
489
/*****************************************/
 
490
 
 
491
static MultiMap currentMultiMap (char *caller)
 
492
{
 
493
  /* find and verify MultiMap struct on active graph */
 
494
  MultiMap mmdisp = 0 ;
 
495
 
 
496
  if (!(graphAssFind(&MultiMap_MAGIC, &mmdisp)))
 
497
    messcrash("%s() could not find MultiMapStruct on graph", caller);
 
498
  if (!mmdisp)
 
499
    messcrash("%s() received NULL MultiMapStruct pointer", caller);
 
500
  if (mmdisp->magic != &MultiMap_MAGIC)
 
501
    messcrash("%s() received non-magic MultiMapStruct pointer", caller);
 
502
 
 
503
  return mmdisp; 
 
504
} /* currentMultiMap */
 
505
 
 
506
/************************************************************/
 
507
 
 
508
static void multiMapDisplayDestroy (void)
 
509
{
 
510
  MultiMap mmdisp = currentMultiMap("multiMapDisplayDestroy");
 
511
  int colNum;
 
512
  MapColumn *mcol;
 
513
 
 
514
  tableDestroy(mmdisp->table);
 
515
  messfree(mmdisp->title);
 
516
 
 
517
  for (colNum = 0; colNum < arrayMax(mmdisp->mapColumns); colNum++)
 
518
    { 
 
519
      mcol = arrp(mmdisp->mapColumns, colNum, MapColumn) ;
 
520
      bumpDestroy(mcol->bump);
 
521
      arrayDestroy(mcol->segs);
 
522
      arrayDestroy(mcol->segps);
 
523
    }
 
524
  arrayDestroy(mmdisp->mapColumns);
 
525
 
 
526
  mmdisp->magic = 0;
 
527
  messfree(mmdisp);
 
528
 
 
529
  return;
 
530
} /* multiMapDisplayDestroy */
 
531
 
 
532
static void multiMapDraw (MultiMap mmdisp)
 
533
{
 
534
  char *windowTitle;
 
535
 
 
536
  if (!graphActivate(mmdisp->graph))
 
537
    return;
 
538
 
 
539
  windowTitle = displayGetTitle("DtMULTIMAP");
 
540
  if (strcmp(windowTitle, "DtMULTIMAP") == 0)
 
541
    windowTitle = "Multi Map";  /* if unchanged in displays.wrm */
 
542
 
 
543
  if (strlen(mmdisp->title) > 0)
 
544
    graphRetitle(messprintf("%s : %s",
 
545
                            windowTitle, mmdisp->title));
 
546
  else
 
547
    graphRetitle(messprintf("%s : untitled", windowTitle));
 
548
 
 
549
  /*****************/
 
550
 
 
551
  graphClear();
 
552
 
 
553
  multiMapConvert(mmdisp) ;
 
554
  multiMapWhole () ;    /* sets ->centre, ->mag and calls Draw() */
 
555
 
 
556
  return;
 
557
} /* multiMapDraw */
 
558
 
 
559
 
 
560
static void multiMapResize (void)
 
561
{
 
562
  MultiMap mmdisp = currentMultiMap("multiMapResize") ;
 
563
 
 
564
  multiMapDrawKey (mmdisp, 0) ;
 
565
}
 
566
 
 
567
/***********************************/
 
568
 
 
569
static void multiMapPick (int box, double x, double y, int modifier_unused) 
 
570
{
 
571
  int i ;
 
572
  MapColumn *mcol ;
 
573
  MultiMap mmdisp = currentMultiMap("multiMapPick") ;
 
574
 
 
575
  if (!box)
 
576
    return ;
 
577
 
 
578
  if (box == mmdisp->cursorBox)
 
579
    graphBoxDrag (mmdisp->cursorBox, multiMapDragCursor) ;
 
580
 
 
581
  
 
582
  for (i = 0; i < arrayMax(mmdisp->mapColumns); i++)
 
583
    { 
 
584
      mcol = arrp(mmdisp->mapColumns, i, MapColumn) ;
 
585
 
 
586
      if (box == mcol->subTitleBox ||
 
587
          box == mcol->mapColBox)
 
588
        {
 
589
          if (mcol != mmdisp->activeMapColumn)
 
590
            {
 
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) ;
 
598
            }
 
599
          return ;
 
600
        }
 
601
    }
 
602
                                
 
603
  
 
604
  if (box == mmdisp->activeColBox)
 
605
    multiMapFollow (mmdisp, x, y) ;
 
606
  else
 
607
    multiMapSelect (mmdisp, box) ;
 
608
 
 
609
  return;
 
610
} /* multiMapPick */
 
611
 
 
612
/*********************/
 
613
 
 
614
static void multiMapClear (void)
 
615
{
 
616
  KEY curr ;
 
617
  MultiMap mmdisp = currentMultiMap("multiMapClear") ;
 
618
  
 
619
  if (mmdisp->activeColBox && arrp(mmdisp->mapBoxes, mmdisp->activeColBox,BOX)->seg)
 
620
    curr = arrp(mmdisp->mapBoxes,mmdisp->activeColBox,BOX)->seg->key ;
 
621
  else 
 
622
    curr = 0 ;
 
623
  
 
624
  multiMapDrawKey (mmdisp, curr) ;
 
625
  
 
626
  return;
 
627
} /* multiMapClear */
 
628
 
 
629
 
 
630
static void multiMapSelect (MultiMap mmdisp, int box) 
 
631
{
 
632
  MapColumn *mcol ;
 
633
  SEG *seg, *friend ;
 
634
  
 
635
  if (mmdisp->activeColBox)
 
636
    { 
 
637
      graphBoxDraw (mmdisp->activeColBox, BLACK, LIGHTBLUE) ;
 
638
      seg = friend = arrp(mmdisp->mapBoxes, mmdisp->activeColBox, BOX)->seg ;
 
639
      while (friend = friend->friends, friend != seg)
 
640
        if (friend->ibox)
 
641
          graphBoxDraw (friend->ibox, BLACK, LIGHTBLUE) ;
 
642
    }
 
643
 
 
644
  if ((seg = arrp(mmdisp->mapBoxes, box, BOX)->seg))
 
645
    {
 
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)
 
650
        if (friend->ibox)
 
651
          graphBoxDraw (friend->ibox, BLACK, LIGHTRED) ;
 
652
 
 
653
      mcol = seg->mcol ;
 
654
      if (mcol != mmdisp->activeMapColumn)
 
655
        { 
 
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) ;
 
664
        }
 
665
      /*    
 
666
      graphActivate(spread->dataGraph) ;
 
667
      spreadSelectFromMap(spread, seg->line, c->colonne) ;
 
668
      graphActivate(spread->mapGraph) ;
 
669
      */
 
670
    }
 
671
  else
 
672
    mmdisp->activeColBox = 0 ;
 
673
 
 
674
  return;
 
675
} /* multiMapSelect */
 
676
 
 
677
 
 
678
static void multiMapFollow (MultiMap mmdisp, double x, double y)
 
679
{
 
680
  SEG *seg ;
 
681
 
 
682
  seg = arrp(mmdisp->mapBoxes, mmdisp->activeColBox, BOX)->seg ;
 
683
  if (seg && seg->parent)
 
684
    {
 
685
      if (seg->grandParent)
 
686
        {
 
687
          if (display (seg->parent, seg->grandParent, 0))
 
688
            displayPreserve() ;   /* automatically preserve the called map */
 
689
        }
 
690
      else
 
691
        display (seg->parent, 0, "TREE") ;
 
692
    }
 
693
  return;
 
694
} /* multiMapFollow */
 
695
 
 
696
/*****************************************/
 
697
 
 
698
/**************************************************/
 
699
/**************** drawing info ********************/
 
700
 
 
701
static int segpOrder(void *a, void *b)
 
702
 
703
  SEG *seg1 = *(SEG**)a;
 
704
  SEG *seg2 = *(SEG**)b;
 
705
  float ya = seg1->ys;
 
706
  float yb = seg2->ys;
 
707
  
 
708
  if (seg1->mcol && seg2->mcol)
 
709
    return ya > yb ? 1 : ( ya == yb ? 0 : -1 ) ;
 
710
  if (seg1->mcol) /* !seg2-> implied */
 
711
    return -1 ; 
 
712
  if (seg2->mcol)
 
713
    return 1 ;
 
714
  return seg1 < seg2 ? -1 : 1 ;
 
715
} /* segpOrder */
 
716
 
 
717
/***********************************************/
 
718
 
 
719
/********* start off with some utility routines ********/
 
720
 
 
721
static void getNxNy(void)
 
722
{
 
723
  graphFitBounds (&nx, &ny) ;
 
724
  yLength = (ny - topMargin - bottomMargin) ;
 
725
  yCentre = topMargin + 0.5*yLength ;
 
726
}
 
727
 
 
728
/***************************************/
 
729
 
 
730
static void multiMapWhole (void)
 
731
 
732
  float  l ;
 
733
  MapColumn *mcol ;
 
734
  int j, maxCol ;
 
735
  MultiMap mmdisp = currentMultiMap("multiMapWhole") ; 
 
736
 
 
737
  getNxNy() ;
 
738
  if (!mmdisp->activeMapColumn || mmdisp->zoomAll)
 
739
    { 
 
740
      maxCol = arrayMax(mmdisp->mapColumns) ;
 
741
      for(j = 0 ; j < maxCol ; j++)
 
742
        { 
 
743
          mcol = arrp(mmdisp->mapColumns, j, MapColumn) ;
 
744
          if (!j || mcol->isMappable)
 
745
            { 
 
746
              l = mcol->max - mcol->min ;
 
747
              mcol->centre = mcol->min + 0.5 * l ;
 
748
              if (l == 0)
 
749
                l = 1 ;
 
750
              mcol->mag = .9 * yLength / l ;
 
751
              mmdisp->activeMapColumn = mcol ;
 
752
            }
 
753
        }
 
754
    }
 
755
  else
 
756
    {
 
757
      mcol = mmdisp->activeMapColumn;
 
758
      if (mcol && mcol->mag)  /* will work on name collone */
 
759
        { 
 
760
          l = mcol->max - mcol->min ;
 
761
          if (l == 0) 
 
762
            l = 1 ;
 
763
          mcol->centre = mcol->min + 0.5 * l ;
 
764
          mcol->mag = .9 * yLength / l ;
 
765
        }
 
766
    }
 
767
 
 
768
  multiMapDrawKey (mmdisp, 0) ;
 
769
 
 
770
  return;
 
771
} /* multiMapWhole */
 
772
 
 
773
static void multiMapZoomIn (void)
 
774
{
 
775
  MapColumn *mcol;
 
776
  int j, maxCol;
 
777
  MultiMap mmdisp = currentMultiMap("multiMapZoomIn") ; 
 
778
 
 
779
  if (mmdisp->zoomAll)
 
780
    {
 
781
      maxCol = arrayMax(mmdisp->mapColumns) ;
 
782
      for(j = 0 ; j < maxCol ; j++)
 
783
        {
 
784
          mcol = arrp(mmdisp->mapColumns, j, MapColumn) ;
 
785
          if (!j || mcol->isMappable)
 
786
            mcol->mag *= 2 ; 
 
787
        }
 
788
    }
 
789
  else 
 
790
    if (mmdisp->activeMapColumn)
 
791
      {
 
792
        mcol = mmdisp->activeMapColumn;
 
793
        if (mcol->mag)
 
794
          mcol->mag *= 2 ; 
 
795
      }
 
796
 
 
797
  multiMapDrawKey (mmdisp, 0) ;
 
798
 
 
799
  return;
 
800
} /* multiMapZoomIn */
 
801
 
 
802
 
 
803
static void multiMapZoomOut (void)
 
804
{
 
805
  MapColumn *mcol ;
 
806
  int j , maxCol ;
 
807
  MultiMap mmdisp = currentMultiMap("multiMapZoomIn") ; 
 
808
 
 
809
  if (mmdisp->zoomAll)
 
810
    { 
 
811
      maxCol = arrayMax(mmdisp->mapColumns) ;
 
812
      for(j = 0 ; j < maxCol ; j++)
 
813
        {
 
814
          mcol = arrp(mmdisp->mapColumns, j, MapColumn) ;
 
815
          if (!j || mcol->isMappable)
 
816
            mcol->mag /= 2 ; 
 
817
        }
 
818
    }
 
819
  else
 
820
    if (mmdisp->activeMapColumn)
 
821
      { 
 
822
        mcol = mmdisp->activeMapColumn;
 
823
        if (mcol->mag)
 
824
          mcol->mag /= 2 ; 
 
825
      }
 
826
 
 
827
  multiMapDrawKey (mmdisp, 0) ;
 
828
 
 
829
  return;
 
830
} /* multiMapZoomOut */
 
831
 
 
832
 
 
833
static void multiMapZoomAll (void)
 
834
 
835
  MultiMap mmdisp = currentMultiMap("multiMapZoomAll") ; 
 
836
 
 
837
  mmdisp->zoomAll =  TRUE ;
 
838
  graphBoxDraw(mmdisp->allButton, BLACK, LIGHTBLUE) ;
 
839
  graphBoxDraw(mmdisp->allButton + 1, BLACK, WHITE) ;
 
840
 
 
841
  return;
 
842
} /* multiMapZoomAll */
 
843
 
 
844
 
 
845
static void multiMapZoomActive (void)
 
846
 
847
  MultiMap mmdisp = currentMultiMap("multiMapZoomActive") ; 
 
848
 
 
849
  mmdisp->zoomAll = FALSE ;
 
850
  graphBoxDraw(mmdisp->allButton + 1, BLACK, LIGHTBLUE) ;
 
851
  graphBoxDraw(mmdisp->allButton, BLACK, WHITE) ;
 
852
 
 
853
  return;
 
854
} /* multiMapZoomActive */
 
855
 
 
856
 
 
857
static void multiMapChangeSymbolSize (void)
 
858
{
 
859
  ACEIN size_in;
 
860
 
 
861
  size_in = messPrompt ("Change size of little square symbols to",
 
862
                        messprintf ("%f", symbolSize_L), "fz", 0);
 
863
  if (size_in)
 
864
    {
 
865
      aceInFloat (size_in, &symbolSize_L) ;
 
866
      aceInDestroy (size_in);
 
867
    }
 
868
 
 
869
  return;
 
870
} /* multiMapChangeSymbolSize */
 
871
 
 
872
 
 
873
static void multiMapFlip (void)
 
874
 
875
  MapColumn *mcol ;
 
876
  SEG *seg ;
 
877
  int i ;
 
878
  float tmp ;
 
879
  MultiMap mmdisp = currentMultiMap("multiMapFlip") ; 
 
880
 
 
881
  mcol = mmdisp->activeMapColumn ;
 
882
  if (!mcol)
 
883
    return ;
 
884
  
 
885
  mcol->isFlipMap = ! mcol->isFlipMap ;
 
886
 
 
887
  i = arrayMax(mcol->segs) ;
 
888
  seg = arrp(mcol->segs, 0, SEG) - 1 ;
 
889
  while(seg++, i--)
 
890
    if (seg->mcol == mcol)
 
891
      seg->y = - seg->y ;
 
892
  tmp = mcol->min ;
 
893
  mcol->min = - mcol->max ; mcol->max = - tmp ;
 
894
  mcol->centre = - mcol->centre ;
 
895
 
 
896
  multiMapDrawKey (mmdisp, 0) ;
 
897
 
 
898
  return;
 
899
} /* multiMapFlip */
 
900
 
 
901
/**************************************************************/
 
902
/***************** dragging code - middle button **************/
 
903
 
 
904
static double   oldy, oldDy, oldx;
 
905
static BOOL     dragFast ;
 
906
#define DRAGFASTLIMIT xScale
 
907
 
 
908
static void multiMapMiddleDrag (double x, double y) 
 
909
{
 
910
  if (dragFast)
 
911
    {
 
912
      graphXorLine (0, oldy - oldDy, DRAGFASTLIMIT, oldy - oldDy) ;
 
913
      graphXorLine (0, oldy + oldDy, DRAGFASTLIMIT, oldy + oldDy) ;
 
914
    }
 
915
  else
 
916
    graphXorLine (DRAGFASTLIMIT, oldy, nx, oldy) ;
 
917
 
 
918
  oldy = y ;
 
919
 
 
920
  if (dragFast)
 
921
    {
 
922
      oldDy *= exp ((x - oldx) / 25.) ;
 
923
      oldx = x ;
 
924
      graphXorLine (0, y - oldDy, DRAGFASTLIMIT, y - oldDy) ;
 
925
      graphXorLine (0, y + oldDy, DRAGFASTLIMIT, y + oldDy) ;
 
926
    }
 
927
  else
 
928
    graphXorLine (DRAGFASTLIMIT, y, nx, y) ;
 
929
 
 
930
  return;
 
931
} /* multiMapMiddleDrag */
 
932
 
 
933
 
 
934
static void multiMapMiddleUp (double x, double y) 
 
935
{
 
936
  MapColumn *mcol ;
 
937
  float x1,x2,y1,y2 ;
 
938
  int j, maxCol ;
 
939
  MultiMap mmdisp = currentMultiMap("multiMapMiddleUp") ;
 
940
 
 
941
  if (mmdisp->zoomAll)
 
942
    { 
 
943
      maxCol = arrayMax(mmdisp->mapColumns) ;
 
944
      for(j = 0 ; j < maxCol ; j++)
 
945
        {
 
946
          mcol = arrp(mmdisp->mapColumns,j, MapColumn) ;
 
947
          if (!j || mcol->isMappable)
 
948
            {
 
949
              if (dragFast)
 
950
                {
 
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 ;
 
955
                }
 
956
              else
 
957
                mcol->centre +=  (y - 0.5 - yCentre) / mcol->mag ;
 
958
            }
 
959
        }
 
960
    }
 
961
  else
 
962
    if (mmdisp->activeMapColumn)
 
963
      { 
 
964
        mcol = mmdisp->activeMapColumn ;
 
965
        if (dragFast)
 
966
          { 
 
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 ;
 
971
          }
 
972
        else
 
973
          mcol->centre +=  (y - 0.5 - yCentre) / mcol->mag ;
 
974
      }
 
975
  
 
976
  multiMapDrawKey (mmdisp, 0) ;
 
977
 
 
978
  return;
 
979
} /* multiMapMiddleUp */
 
980
 
 
981
static void multiMapMiddleDown (double x, double y) 
 
982
{  
 
983
  float x1,x2,y1,y2 ;
 
984
  MultiMap mmdisp = currentMultiMap("multiMapMiddleDown") ;
 
985
 
 
986
  getNxNy () ; 
 
987
 
 
988
  graphBoxDim (mmdisp->cursorBox, &x1, &y1, &x2, &y2) ;
 
989
  oldDy = (y2 - y1) / 2. ;
 
990
 
 
991
  dragFast = (x < DRAGFASTLIMIT) ? TRUE : FALSE ;
 
992
 
 
993
  if(dragFast)
 
994
    {
 
995
      graphXorLine (0, y - oldDy, DRAGFASTLIMIT, y - oldDy) ;
 
996
      graphXorLine (0, y + oldDy, DRAGFASTLIMIT, y + oldDy) ;
 
997
    }
 
998
  else
 
999
    graphXorLine (DRAGFASTLIMIT, y, nx, y) ;
 
1000
   
 
1001
  oldx = x ;
 
1002
  oldy = y ;
 
1003
  graphRegister (MIDDLE_DRAG,  multiMapMiddleDrag) ;
 
1004
  graphRegister (MIDDLE_UP,  multiMapMiddleUp) ;
 
1005
 
 
1006
  return;
 
1007
} /* multiMapMiddleDown */
 
1008
 
 
1009
static void multiMapDragCursor (float *x, float *y, BOOL isDone)
 
1010
{
 
1011
  if (isDone)
 
1012
    {
 
1013
      float x1,y1,x2,y2 ;
 
1014
      MapColumn *mcol ;
 
1015
      int j, maxCol ;
 
1016
      MultiMap mmdisp = currentMultiMap("multiMapDragCursor") ;
 
1017
 
 
1018
      getNxNy() ;
 
1019
      graphBoxDim (mmdisp->cursorBox, &x1, &y1, &x2, &y2) ;
 
1020
      if (mmdisp->zoomAll)
 
1021
        { 
 
1022
          maxCol = arrayMax(mmdisp->mapColumns) ;
 
1023
          for(j = 0 ; j < maxCol ; j++)
 
1024
            {
 
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 ;
 
1029
            }
 
1030
        }
 
1031
      else
 
1032
        if (mmdisp->activeMapColumn)
 
1033
          {
 
1034
            mcol = mmdisp->activeMapColumn ;
 
1035
            mcol->centre = mcol->min + (mcol->max - mcol->min) * 
 
1036
              ((*y + 0.5*(y2-y1)) - topMargin) / yLength ;
 
1037
          }
 
1038
 
 
1039
      multiMapDrawKey (mmdisp, 0) ;
 
1040
    }
 
1041
  else
 
1042
    *x = xCursor - 0.5 ;
 
1043
 
 
1044
  return;
 
1045
} /* multiMapDragCursor */
 
1046
 
 
1047
/**************************************************/
 
1048
/**************************************************/
 
1049
 
 
1050
static void drawScale (MapColumn *mcol, int xScale1)
 
1051
{
 
1052
  float cutoff = 5 / mcol->mag ;
 
1053
  float unit = 0.01 ;
 
1054
  float subunit = 0.001 ;
 
1055
  float x, xx, y, start, end ;
 
1056
 
 
1057
  while (unit < cutoff)
 
1058
    {
 
1059
      unit *= 2 ;
 
1060
      subunit *= 5 ;
 
1061
      if (unit >= cutoff)
 
1062
        break ;
 
1063
      unit *= 2.5 ;
 
1064
      if (unit >= cutoff)
 
1065
        break ;
 
1066
      unit *= 2 ;
 
1067
      subunit *= 2 ;
 
1068
    }
 
1069
 
 
1070
  start = SPRDGRAPH2MAP(mcol, topMargin) ;
 
1071
  if (start < mcol->min)
 
1072
    start = mcol->min ;
 
1073
  end = SPRDGRAPH2MAP(mcol, ny-bottomMargin) ;
 
1074
  if (end > mcol->max)
 
1075
    end = mcol->max ;
 
1076
      
 
1077
  x = unit * (((start > mcol->min) ? 1 : 0) + (int)(start/unit)) ;
 
1078
  while (x <= end)
 
1079
    {
 
1080
      y = SPRDMAP2GRAPH(mcol, x) ;
 
1081
        
 
1082
      xx = mcol->isFlipMap ?  -x :  x ;
 
1083
      graphLine (xScale1-1.5,y,xScale1-0.5,y) ;
 
1084
      if(unit >= 1)
 
1085
        graphText (messprintf ("%-4.0f",xx),xScale1,y-.5) ;
 
1086
      else if(unit >= .1)
 
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) ;
 
1092
    
 
1093
      x += unit ;
 
1094
    }
 
1095
  
 
1096
  x = subunit * (((start >= mcol->min)? 1 : 0) + (int)(start/subunit)) ;
 
1097
  while (x <= end)
 
1098
    {
 
1099
      y = SPRDMAP2GRAPH(mcol, x) ;
 
1100
      graphLine (xScale1-1.0,y,xScale1-0.5,y) ;
 
1101
      x += subunit ;
 
1102
    }
 
1103
 
 
1104
  graphLine (xScale1-0.5, SPRDMAP2GRAPH(mcol,start), 
 
1105
             xScale1-0.5, SPRDMAP2GRAPH(mcol,end)) ;
 
1106
 
 
1107
  return;
 
1108
} /* drawScale */
 
1109
 
 
1110
 
 
1111
 
 
1112
static void drawChromosomeBox (MultiMap mmdisp)
 
1113
 
1114
  MapColumn *mcol = mmdisp->activeMapColumn ;
 
1115
 
 
1116
  if (!mcol)
 
1117
    return ;
 
1118
 
 
1119
  if (mmdisp->chromoBox)
 
1120
    graphBoxClear(mmdisp->chromoBox) ;
 
1121
 
 
1122
  mmdisp->chromoBox = graphBoxStart() ;
 
1123
  graphFillRectangle (xCursor - 0.25, topMargin, 
 
1124
                      xCursor + 0.25, ny - bottomMargin) ;
 
1125
  mmdisp->cursorBox = graphBoxStart() ;
 
1126
 
 
1127
  arrayp(mmdisp->mapBoxes, mmdisp->cursorBox, BOX)->seg = 0 ;
 
1128
 
 
1129
  if (mcol->max != mcol->min)
 
1130
    graphRectangle (xCursor - 0.5, 
 
1131
                    MAP2CHROM(SPRDGRAPH2MAP(mcol, topMargin)), 
 
1132
                    xCursor + 0.5, 
 
1133
                    MAP2CHROM(SPRDGRAPH2MAP(mcol, ny - bottomMargin))) ;
 
1134
  graphBoxEnd () ;
 
1135
  graphBoxEnd () ;
 
1136
  graphBoxDraw (mmdisp->chromoBox,BLACK, WHITE) ;
 
1137
  graphBoxDraw (mmdisp->cursorBox,DARKGREEN,GREEN) ;
 
1138
 
 
1139
  return;
 
1140
} /* drawChromosomeBox */
 
1141
 
 
1142
 
 
1143
 
 
1144
static void drawChromosomeLine (MultiMap mmdisp)
 
1145
{
 
1146
  int i ;
 
1147
 
 
1148
  mmdisp->chromoBox = 0 ;
 
1149
 
 
1150
/*
 
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) ;
 
1157
*/
 
1158
  graphBoxStart() ;
 
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) ;
 
1164
  graphBoxEnd() ;
 
1165
 
 
1166
  return;
 
1167
} /* drawChromosomeLine */
 
1168
 
 
1169
/***********************************************/
 
1170
 
 
1171
static void multiMapBoxEnd (int ibox, BOX *box)
 
1172
{
 
1173
  graphBoxEnd () ;
 
1174
  if (box->seg && box->seg->flag & FLAG_HIGHLIGHT)
 
1175
    graphBoxDraw (ibox, BLACK, MAGENTA) ;
 
1176
  else
 
1177
    graphBoxDraw (ibox, BLACK, box->color) ;
 
1178
 
 
1179
  return;
 
1180
} /* multiMapBoxEnd */
 
1181
 
 
1182
/***********************************************/
 
1183
 
 
1184
static Array multiMapFindLimits(TABLE *table, Array isFlipMapArray)
 
1185
{
 
1186
  int rowNum, colNum, colNum1 ;
 
1187
  BOOL isSuccess = FALSE ;
 
1188
  float y ;
 
1189
  BOOL first, found ;
 
1190
  MapColumn *mcol;
 
1191
  Array mapColumns = arrayCreate(table->ncol, MapColumn);
 
1192
  
 
1193
  if (table->ncol == 0)
 
1194
    messcrash("multiMapFindLimits() - received table without columns");
 
1195
  
 
1196
  for(colNum = 0 ; colNum < table->ncol ; colNum++)
 
1197
    {
 
1198
      mcol = arrayp(mapColumns, colNum, MapColumn);
 
1199
      
 
1200
      mcol->type = table->type[colNum];
 
1201
 
 
1202
      if (isFlipMapArray && array(isFlipMapArray, colNum, BOOL))
 
1203
        mcol->isFlipMap = TRUE;
 
1204
      else
 
1205
        mcol->isFlipMap = FALSE;
 
1206
 
 
1207
      if ((mcol->type == 'i' || mcol->type == 'f') /*&& !mcol->isHidden*/)
 
1208
        mcol->isMappable = TRUE;
 
1209
      else
 
1210
        {
 
1211
          mcol->isMappable = FALSE;
 
1212
          continue;
 
1213
        }
 
1214
      
 
1215
      first = TRUE;
 
1216
      for (rowNum = 0 ; rowNum < tabMax(table, colNum) ; rowNum++)
 
1217
        {
 
1218
          y = 0.0 ;
 
1219
          found = FALSE ;
 
1220
          if (!tabEmpty(table, rowNum, colNum))
 
1221
            switch (table->type[colNum])
 
1222
              {
 
1223
              case 'i':
 
1224
                found = TRUE ;
 
1225
                y = (float)tabInt(table, rowNum, colNum) ;
 
1226
                break ;
 
1227
              case 'f':
 
1228
                found = TRUE ;
 
1229
                y = tabFloat(table, rowNum, colNum) ;
 
1230
                break ;
 
1231
              }
 
1232
 
 
1233
          if (found)
 
1234
            {
 
1235
              y = mcol->isFlipMap ? -y : y ;
 
1236
              if (first)
 
1237
                { 
 
1238
                  isSuccess = TRUE ;
 
1239
                  first = FALSE ;
 
1240
                  mcol->min = y ;
 
1241
                  mcol->max = y ;
 
1242
                }
 
1243
              if (y < mcol->min)
 
1244
                mcol->min = y ;
 
1245
              if (y > mcol->max)
 
1246
                mcol->max = y ;
 
1247
            }
 
1248
        }
 
1249
    }
 
1250
 
 
1251
  for(colNum = 0 ; colNum < table->ncol ; colNum++)
 
1252
    {
 
1253
      mcol = arrp(mapColumns, colNum, MapColumn);
 
1254
      if (!mcol->isMappable /*&& !mcol->isHidden*/)
 
1255
        {
 
1256
          for(colNum1 = table->ncol-1 ; colNum1 >= 0 ; colNum1--)
 
1257
            {
 
1258
              MapColumn *mcol1;
 
1259
              mcol1 = arrp(mapColumns,colNum1, MapColumn) ;
 
1260
 
 
1261
              if(mcol1->isMappable)
 
1262
                {
 
1263
                  mcol->min = mcol1->min ;
 
1264
                  mcol->max = mcol1->max ;
 
1265
                  break ;
 
1266
                }
 
1267
            }
 
1268
        }
 
1269
    }
 
1270
  if (!isSuccess)
 
1271
    {
 
1272
      arrayDestroy(mapColumns);
 
1273
      mapColumns = NULL;
 
1274
    }
 
1275
 
 
1276
  return mapColumns ;
 
1277
} /* multiMapFindLimits */
 
1278
 
 
1279
  /************************************************************/
 
1280
 
 
1281
static void multiMapConvert (MultiMap mmdisp)
 
1282
 
1283
  SEG *seg, *oldSeg ;
 
1284
  int rowNum, rowMax, colNum, colMax ;
 
1285
  float y ;
 
1286
  MapColumn *mcol;
 
1287
 
 
1288
  colMax = mmdisp->table->ncol ;
 
1289
  rowMax = tableMax(mmdisp->table);
 
1290
 
 
1291
  for (colNum = 0 ; colNum < colMax ; colNum++)
 
1292
    { 
 
1293
      mcol = arrp(mmdisp->mapColumns, colNum, MapColumn);
 
1294
 
 
1295
      if (colNum == 0 || mcol->isMappable)
 
1296
        mcol->segs = arrayReCreate (mcol->segs, rowMax, SEG) ;
 
1297
      else
 
1298
        arrayDestroy(mcol->segs) ;
 
1299
    }
 
1300
   
 
1301
  for(rowNum = 0 ; rowNum < rowMax ; rowNum++)
 
1302
    {
 
1303
      oldSeg = 0 ;
 
1304
 
 
1305
      for(colNum = 0 ; colNum < colMax ; colNum++)
 
1306
        {
 
1307
          mcol = arrp(mmdisp->mapColumns, colNum, MapColumn);
 
1308
              
 
1309
          if (!mcol->isMappable)
 
1310
            continue ;
 
1311
 
 
1312
          if (tabEmpty(mmdisp->table, rowNum, colNum))
 
1313
            continue;
 
1314
 
 
1315
          seg = arrayp(mcol->segs, rowNum, SEG) ;
 
1316
          seg->line = rowNum ;
 
1317
          seg->mcol = mcol ;
 
1318
          if (oldSeg)
 
1319
            {
 
1320
              seg->friends = oldSeg->friends ;
 
1321
              oldSeg->friends = seg ;
 
1322
            }
 
1323
          else
 
1324
            {
 
1325
              seg->friends = seg ;    /* loop ! */
 
1326
              oldSeg = seg ;
 
1327
            }
 
1328
 
 
1329
          switch (mcol->type)
 
1330
            {
 
1331
            case 'i':
 
1332
              y = (float)tabInt(mmdisp->table, rowNum, colNum) ;
 
1333
              break ;
 
1334
            case 'f':
 
1335
              y = tabFloat(mmdisp->table, rowNum, colNum) ;
 
1336
              break ;
 
1337
            }
 
1338
          seg->y = mcol->isFlipMap ? -y : y ;
 
1339
          seg->parent = tabParent(mmdisp->table, rowNum, colNum) ;
 
1340
          seg->grandParent = tabGrandParent(mmdisp->table, rowNum, colNum) ;
 
1341
        }
 
1342
 
 
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) ;
 
1346
          
 
1347
      seg->key = tabKey(mmdisp->table, rowNum, 0);
 
1348
      seg->parent = tabKey(mmdisp->table, rowNum, 0);
 
1349
      seg->grandParent = 0 ;
 
1350
 
 
1351
      seg->line = rowNum ;
 
1352
      seg->flag = FLAG_NAME ;
 
1353
      seg->mcol = mcol ;
 
1354
      if (oldSeg)
 
1355
        { 
 
1356
          seg->friends = oldSeg->friends ;
 
1357
          oldSeg->friends = seg ;
 
1358
          seg->y = seg->friends->y ;
 
1359
        }
 
1360
      else
 
1361
        seg->friends = seg ;    /* loop ! */
 
1362
    }
 
1363
 
 
1364
 
 
1365
  for(colNum = 0 ; colNum < colMax ; colNum++)
 
1366
    {
 
1367
      mcol = arrp(mmdisp->mapColumns, colNum, MapColumn);
 
1368
      if (mcol->segs)
 
1369
        { 
 
1370
          SEG *zs, **zsp ;
 
1371
          mcol->segps = arrayReCreate (mcol->segps, rowMax, SEG*) ;
 
1372
          rowNum = rowMax ;
 
1373
          zsp = arrayp(mcol->segps, rowNum - 1, SEG*) ;
 
1374
          zs = arrp(mcol->segs, rowNum - 1, SEG) ;
 
1375
          while (rowNum--)
 
1376
            *zsp-- = zs-- ;
 
1377
        }
 
1378
    }
 
1379
 
 
1380
  return;
 
1381
} /* multiMapConvert */
 
1382
 
 
1383
/**********/
 
1384
 
 
1385
static void multiMapDrawKeyC(MapColumn *mcol, Array mapBoxes, float x)
 
1386
{
 
1387
  int i = arrayMax(mcol->segs), ibox, oldFormat ;
 
1388
  SEG *seg = arrp(mcol->segs, 0, SEG) - 1 ;
 
1389
  BOX *box ;
 
1390
  int screenMin = topMargin, screenMax = ny - bottomMargin ;
 
1391
        
 
1392
  while(seg++, i--)
 
1393
    { 
 
1394
      if (!seg->mcol) 
 
1395
        continue ;
 
1396
      
 
1397
      if (seg->ys > screenMin && seg->ys < screenMax + 30)
 
1398
        {
 
1399
          ibox = graphBoxStart() ;
 
1400
          box = arrayp(mapBoxes, ibox, BOX) ;
 
1401
          box->seg = seg ;
 
1402
          seg->ibox = ibox ;
 
1403
          box->color = YELLOW ;
 
1404
          
 
1405
          if (seg->flag & FLAG_NAME)
 
1406
            {
 
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 ;
 
1414
            }
 
1415
          else
 
1416
            {
 
1417
              graphLine(x , seg->ys, x + symbolSize_L, seg->ys ) ;
 
1418
              graphLine(x , seg->ys , x , seg->ys + .5) ;
 
1419
              
 
1420
              seg->x = x + seg->xs ;
 
1421
            }
 
1422
          multiMapBoxEnd(ibox, box) ;
 
1423
        }
 
1424
      else
 
1425
        { seg->x = x ;  /* needed to draw lines */
 
1426
          seg->ibox = 0 ;
 
1427
        }
 
1428
    }
 
1429
} /* multiMapDrawKeyC */
 
1430
 
 
1431
/**********/
 
1432
 
 
1433
static void multiMapDrawKeyLines(Array segs)
 
1434
{
 
1435
  float x, y ;
 
1436
  int i = arrayMax(segs) ;
 
1437
  int screenMin = topMargin, screenMax = ny - bottomMargin ;
 
1438
  SEG *friend, *seg = arrp(segs, 0, SEG) - 1 ;
 
1439
  
 
1440
  while (seg++, i--)
 
1441
    { 
 
1442
      friend = seg ;
 
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)
 
1446
          {
 
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 ;
 
1452
          }
 
1453
    }
 
1454
 
 
1455
  return;
 
1456
} /* multiMapDrawKeyLines */
 
1457
 
 
1458
/**********/
 
1459
 
 
1460
static void multiMapBump (MapColumn *mcol)
 
1461
{
 
1462
  int i = arrayMax(mcol->segs) ;
 
1463
  SEG **segp, *seg ;
 
1464
  int screenMin = topMargin ; 
 
1465
  float h = freelower(mcol->type) == 'k' ? 1 : .01 ;
 
1466
  segp = arrp(mcol->segps, 0, SEG*) ;
 
1467
 
 
1468
 
 
1469
  while (i--)
 
1470
    { 
 
1471
      seg = *segp++ ;
 
1472
      if (seg->mcol)
 
1473
        { 
 
1474
          seg->xs = 0 ;
 
1475
          if ((seg->flag & FLAG_NAME)
 
1476
              && seg->friends)
 
1477
            seg->ys = SPRDMAP2GRAPH (seg->friends->mcol, seg->y) ;
 
1478
          else
 
1479
            seg->ys = SPRDMAP2GRAPH (seg->mcol, seg->y) ;
 
1480
        }
 
1481
    }
 
1482
  i = arrayMax(mcol->segs) ;
 
1483
  arraySort(mcol->segps, segpOrder) ;
 
1484
  
 
1485
  mcol->bump = bumpReCreate(mcol->bump, 1, ny) ; 
 
1486
 
 
1487
  segp = arrp(mcol->segps, 0, SEG*) ;
 
1488
  while(i--)
 
1489
    {
 
1490
      seg = *segp++ ;
 
1491
      if (!(seg->flag & FLAG_NAME) || seg->ys >= screenMin)
 
1492
        bumpItem(mcol->bump, 1, h, &seg->xs, &seg->ys) ;
 
1493
    }
 
1494
}
 
1495
 
 
1496
/**********/
 
1497
 
 
1498
static void multiMapDrawKey (MultiMap mmdisp, KEY curr)
 
1499
{
 
1500
  int x, j, maxCol;
 
1501
  MapColumn *mcol, *lastmcol ;
 
1502
 
 
1503
  mmdisp->mapBoxes = arrayReCreate (mmdisp->mapBoxes, 64, BOX) ;
 
1504
  mmdisp->activeColBox = 0 ;
 
1505
  if (mmdisp->activeMapColumn && !mmdisp->activeMapColumn->isMappable)
 
1506
     mmdisp->activeMapColumn = 0 ;
 
1507
 
 
1508
  getNxNy () ;
 
1509
  if (!isPapDisp)
 
1510
    { 
 
1511
      graphClear () ;
 
1512
      graphColor (BLACK) ;
 
1513
      if (yLength < 6)
 
1514
        { messout ("Sorry, this window is too small for a multi map") ;
 
1515
          return ;
 
1516
        }
 
1517
       drawChromosomeLine (mmdisp) ;
 
1518
    }
 
1519
  
 
1520
  maxCol = arrayMax(mmdisp->mapColumns) ;
 
1521
  
 
1522
  if (strlen(mmdisp->title) > 0)
 
1523
    graphText(mmdisp->title, 32, 1.5) ;
 
1524
 
 
1525
  x = xScale;
 
1526
  for(j = 0 ; j < maxCol ; j++)
 
1527
    {
 
1528
      mcol = arrp(mmdisp->mapColumns, j, MapColumn) ;
 
1529
 
 
1530
      if (mcol->isMappable)
 
1531
        { 
 
1532
          drawScale(mcol, x) ;
 
1533
          lastmcol = mcol ;
 
1534
          x += 8 ;
 
1535
          multiMapBump(mcol) ;
 
1536
 
 
1537
          mcol->mapColBox = graphBoxStart() ;
 
1538
 
 
1539
          multiMapDrawKeyC(mcol, mmdisp->mapBoxes, x) ;
 
1540
          if (strlen(tableGetColumnName(mmdisp->table, j)) > 0)
 
1541
            {
 
1542
              mcol->subTitleBox = graphBoxStart() ;
 
1543
              graphText(tableGetColumnName(mmdisp->table, j), x, 5) ;
 
1544
              graphBoxEnd() ;
 
1545
            }
 
1546
          else
 
1547
            mcol->subTitleBox = 0;
 
1548
 
 
1549
          graphBoxEnd() ;       /* mapColBox */
 
1550
 
 
1551
          x += 3 * symbolSize_L + 2 ;
 
1552
        }
 
1553
      if (!mmdisp->activeMapColumn)
 
1554
        mmdisp->activeMapColumn = mcol ;
 
1555
    }
 
1556
 
 
1557
  drawChromosomeBox (mmdisp) ;
 
1558
  mcol = lastmcol ;
 
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) ;
 
1564
  x += 4 ;
 
1565
  multiMapBump(mcol) ; 
 
1566
  multiMapDrawKeyC(mcol, mmdisp->mapBoxes, x) ;
 
1567
  multiMapDrawKeyLines(mcol->segs) ;
 
1568
 
 
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 */
 
1571
 
 
1572
  if (mmdisp->zoomAll)
 
1573
    {
 
1574
      graphBoxDraw(mmdisp->allButton, BLACK, LIGHTBLUE) ;
 
1575
      graphBoxDraw(mmdisp->allButton + 1, BLACK, WHITE) ;
 
1576
    }
 
1577
  else
 
1578
    { 
 
1579
      graphBoxDraw(mmdisp->allButton + 1, BLACK, LIGHTBLUE) ;
 
1580
      graphBoxDraw(mmdisp->allButton, BLACK, WHITE) ;
 
1581
    }
 
1582
  graphButtons (buttonOpts, 5, 2.5, nx) ; 
 
1583
 
 
1584
  mmdisp->activeMapColumn = 0 ; /* ? ? ? */
 
1585
  if (mmdisp->activeMapColumn && mmdisp->activeMapColumn->subTitleBox)
 
1586
    graphBoxDraw(mmdisp->activeMapColumn->subTitleBox, BLACK, LIGHTGREEN) ;
 
1587
 
 
1588
  graphRedraw () ;
 
1589
 
 
1590
  return;
 
1591
} /* multiMapDrawKey */
 
1592
 
 
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.
 
1597
 */
 
1598
static void myMapPrint(void)
 
1599
{
 
1600
  float min, max ;
 
1601
  float oldcentre ;
 
1602
  int   oldh, newh ;
 
1603
  int   oldtype ;
 
1604
  float olduh, newuh ;
 
1605
  float yfac ;
 
1606
  MapColumn *mcol ;
 
1607
  MultiMap mmdisp = currentMultiMap("myMapPrintWhole") ; 
 
1608
  ACEIN zone_in;
 
1609
 
 
1610
  mcol = mmdisp->activeMapColumn ;
 
1611
  if (!mcol)
 
1612
    {
 
1613
      messerror ("No active column");
 
1614
      return;
 
1615
    }
 
1616
  
 
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);
 
1620
  if (!zone_in)
 
1621
    return ;
 
1622
 
 
1623
  aceInFloat(zone_in, &min) ; aceInFloat(zone_in, &max) ;
 
1624
  aceInDestroy (zone_in);
 
1625
 
 
1626
  if (min >= max)
 
1627
    return ;
 
1628
  if (min < mcol->min)
 
1629
    min = mcol->min ;
 
1630
  if (max > mcol->max)
 
1631
    max = mcol->max ;
 
1632
 
 
1633
  oldcentre = mcol->centre ;
 
1634
  mcol->centre = (max + min) / 2 ;  
 
1635
 
 
1636
  /* Record current settings of active graph height etc.   */
 
1637
  graphGetSprdmapData(&oldh, &olduh, &oldtype, &yfac) ;
 
1638
 
 
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) ;
 
1644
 
 
1645
  /* OK, now it's drawn we can print it.                   */
 
1646
  graphSetSprdmapType(TEXT_SCROLL) ;
 
1647
  graphPrint() ;
 
1648
  graphSetSprdmapType(oldtype) ;
 
1649
 
 
1650
  /* Restore the old graph height settings and redraw the map. */
 
1651
  graphSetSprdmapCoords(oldh, olduh) ;
 
1652
  mcol->centre = oldcentre ;
 
1653
  multiMapDrawKey (mmdisp, 0) ;
 
1654
 
 
1655
  return;
 
1656
} /* myMapPrint */
 
1657
 
 
1658
/*************************** eof ****************************/