2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team.
6 * Copyright (c) 2013,2014, by the GROMACS development team, led by
7 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8 * and including many others, as listed in the AUTHORS file in the
9 * top-level source directory and at http://www.gromacs.org.
11 * GROMACS is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation; either version 2.1
14 * of the License, or (at your option) any later version.
16 * GROMACS is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with GROMACS; if not, see
23 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * If you want to redistribute modifications to GROMACS, please
27 * consider that scientific software is very special. Version
28 * control is crucial - bugs must be traceable. We will be happy to
29 * consider code for inclusion in the official distribution, but
30 * derived work must not be called official GROMACS. Details are found
31 * in the README & COPYING files - if they are missing, get the
32 * official version at http://www.gromacs.org.
34 * To help us fund GROMACS development, we humbly ask that you cite
35 * the research papers on the package. Check out http://www.gromacs.org.
46 #include "gromacs/utility/fatalerror.h"
47 #include "gromacs/utility/smalloc.h"
51 #include "gromacs/commandline/pargs.h"
52 #include "gromacs/utility/futil.h"
53 #include "gromacs/fileio/matio.h"
54 #include "gromacs/fileio/trxio.h"
55 #include "gromacs/fileio/writeps.h"
72 char tickfont
[STRLEN
];
87 char leglabel
[STRLEN
];
88 char leg2label
[STRLEN
];
98 /* MUST correspond to char *legend[] in main() */
100 elSel
, elBoth
, elFirst
, elSecond
, elNone
, elNR
103 /* MUST correspond to char *combine[] in main() */
105 ecSel
, ecHalves
, ecAdd
, ecSub
, ecMult
, ecDiv
, ecNR
108 void get_params(const char *mpin
, const char *mpout
, t_psrec
*psr
)
110 static const char *gmx_bools
[BOOL_NR
+1] = { "no", "yes", NULL
};
111 /* this must correspond to t_rgb *linecolors[] below */
112 static const char *colors
[] = { "none", "black", "white", NULL
};
118 wi
= init_warning(FALSE
, 0);
122 inp
= read_inpfile(mpin
, &ninp
, wi
);
128 ETYPE("black&white", psr
->bw
, gmx_bools
);
129 RTYPE("linewidth", psr
->linewidth
, 1.0);
130 STYPE("titlefont", psr
->titfont
, "Helvetica");
131 RTYPE("titlefontsize", psr
->titfontsize
, 20.0);
132 ETYPE("legend", psr
->legend
, gmx_bools
);
133 STYPE("legendfont", psr
->legfont
, psr
->titfont
);
134 STYPE("legendlabel", psr
->leglabel
, "");
135 STYPE("legend2label", psr
->leg2label
, psr
->leglabel
);
136 RTYPE("legendfontsize", psr
->legfontsize
, 14.0);
137 RTYPE("xbox", psr
->xboxsize
, 0.0);
138 RTYPE("ybox", psr
->yboxsize
, 0.0);
139 RTYPE("matrixspacing", psr
->boxspacing
, 20.0);
140 RTYPE("xoffset", psr
->xoffs
, 0.0);
141 RTYPE("yoffset", psr
->yoffs
, psr
->xoffs
);
142 RTYPE("boxlinewidth", psr
->boxlinewidth
, psr
->linewidth
);
143 RTYPE("ticklinewidth", psr
->ticklinewidth
, psr
->linewidth
);
144 RTYPE("zerolinewidth", psr
->zerolinewidth
, psr
->ticklinewidth
);
145 ETYPE("x-lineat0value", psr
->X
.lineatzero
, colors
);
146 RTYPE("x-major", psr
->X
.major
, NOTSET
);
147 RTYPE("x-minor", psr
->X
.minor
, NOTSET
);
148 RTYPE("x-firstmajor", psr
->X
.offset
, 0.0);
149 ETYPE("x-majorat0", psr
->X
.first
, gmx_bools
);
150 RTYPE("x-majorticklen", psr
->X
.majorticklen
, 8.0);
151 RTYPE("x-minorticklen", psr
->X
.minorticklen
, 4.0);
152 STYPE("x-label", psr
->X
.label
, "");
153 RTYPE("x-fontsize", psr
->X
.fontsize
, 16.0);
154 STYPE("x-font", psr
->X
.font
, psr
->titfont
);
155 RTYPE("x-tickfontsize", psr
->X
.tickfontsize
, 10.0);
156 STYPE("x-tickfont", psr
->X
.tickfont
, psr
->X
.font
);
157 ETYPE("y-lineat0value", psr
->Y
.lineatzero
, colors
);
158 RTYPE("y-major", psr
->Y
.major
, psr
->X
.major
);
159 RTYPE("y-minor", psr
->Y
.minor
, psr
->X
.minor
);
160 RTYPE("y-firstmajor", psr
->Y
.offset
, psr
->X
.offset
);
161 ETYPE("y-majorat0", psr
->Y
.first
, gmx_bools
);
162 RTYPE("y-majorticklen", psr
->Y
.majorticklen
, psr
->X
.majorticklen
);
163 RTYPE("y-minorticklen", psr
->Y
.minorticklen
, psr
->X
.minorticklen
);
164 STYPE("y-label", psr
->Y
.label
, psr
->X
.label
);
165 RTYPE("y-fontsize", psr
->Y
.fontsize
, psr
->X
.fontsize
);
166 STYPE("y-font", psr
->Y
.font
, psr
->X
.font
);
167 RTYPE("y-tickfontsize", psr
->Y
.tickfontsize
, psr
->X
.tickfontsize
);
168 STYPE("y-tickfont", psr
->Y
.tickfont
, psr
->Y
.font
);
172 write_inpfile(mpout
, ninp
, inp
, TRUE
, wi
);
175 done_warning(wi
, FARGS
);
178 t_rgb black
= { 0, 0, 0 };
179 t_rgb white
= { 1, 1, 1 };
180 t_rgb red
= { 1, 0, 0 };
181 t_rgb blue
= { 0, 0, 1 };
182 #define BLACK (&black)
183 /* this must correspond to *colors[] in get_params */
184 t_rgb
*linecolors
[] = { NULL
, &black
, &white
, NULL
};
186 gmx_bool
diff_maps(int nmap1
, t_mapping
*map1
, int nmap2
, t_mapping
*map2
)
189 gmx_bool bDiff
, bColDiff
= FALSE
;
198 for (i
= 0; i
< nmap1
; i
++)
200 if (!matelmt_cmp(map1
[i
].code
, map2
[i
].code
))
204 if (strcmp(map1
[i
].desc
, map2
[i
].desc
) != 0)
208 if ((map1
[i
].rgb
.r
!= map2
[i
].rgb
.r
) ||
209 (map1
[i
].rgb
.g
!= map2
[i
].rgb
.g
) ||
210 (map1
[i
].rgb
.b
!= map2
[i
].rgb
.b
))
215 if (!bDiff
&& bColDiff
)
217 fprintf(stderr
, "Warning: two colormaps differ only in RGB value, using one colormap.\n");
224 void leg_discrete(t_psdata ps
, real x0
, real y0
, char *label
,
225 real fontsize
, char *font
, int nmap
, t_mapping map
[])
231 boxhh
= fontsize
+DDD
;
234 ps_strfont(ps
, font
, fontsize
);
235 yhh
= y0
+fontsize
+3*DDD
;
236 if ((int)strlen(label
) > 0)
238 ps_ctext(ps
, x0
, yhh
, label
, eXLeft
);
240 ps_moveto(ps
, x0
, y0
);
241 for (i
= 0; (i
< nmap
); i
++)
244 ps_rgb(ps
, &(map
[i
].rgb
));
245 ps_fillbox(ps
, DDD
, DDD
, DDD
+fontsize
, boxhh
-DDD
);
247 ps_box(ps
, DDD
, DDD
, DDD
+fontsize
, boxhh
-DDD
);
248 ps_ctext(ps
, boxhh
+2*DDD
, fontsize
/3, map
[i
].desc
, eXLeft
);
250 ps_moverel(ps
, DDD
, -fontsize
/3);
254 void leg_continuous(t_psdata ps
, real x0
, real x
, real y0
, char *label
,
255 real fontsize
, char *font
,
256 int nmap
, t_mapping map
[],
261 real yhh
, boxxh
, boxyh
;
268 boxxh
= (real
)x
/(real
)(nmap
-mapoffset
);
269 if (boxxh
> fontsize
)
275 xx0
= x0
-((nmap
-mapoffset
)*boxxh
)/2.0;
277 for (i
= 0; (i
< nmap
-mapoffset
); i
++)
279 ps_rgb(ps
, &(map
[i
+mapoffset
].rgb
));
280 ps_fillbox(ps
, xx0
+i
*boxxh
, y0
, xx0
+(i
+1)*boxxh
, y0
+boxyh
);
282 ps_strfont(ps
, font
, fontsize
);
284 ps_box(ps
, xx0
, y0
, xx0
+(nmap
-mapoffset
)*boxxh
, y0
+boxyh
);
286 yhh
= y0
+boxyh
+3*DDD
;
287 ps_ctext(ps
, xx0
+boxxh
/2, yhh
, map
[0].desc
, eXCenter
);
288 if ((int)strlen(label
) > 0)
290 ps_ctext(ps
, x0
, yhh
, label
, eXCenter
);
292 ps_ctext(ps
, xx0
+((nmap
-mapoffset
)*boxxh
)
293 - boxxh
/2, yhh
, map
[nmap
-1].desc
, eXCenter
);
296 void leg_bicontinuous(t_psdata ps
, real x0
, real x
, real y0
, char *label1
,
297 char *label2
, real fontsize
, char *font
,
298 int nmap1
, t_mapping map1
[], int nmap2
, t_mapping map2
[])
300 real xx1
, xx2
, x1
, x2
;
302 x1
= x
/(nmap1
+nmap2
)*nmap1
; /* width of legend 1 */
303 x2
= x
/(nmap1
+nmap2
)*nmap2
; /* width of legend 2 */
304 xx1
= x0
-(x2
/2.0)-fontsize
; /* center of legend 1 */
305 xx2
= x0
+(x1
/2.0)+fontsize
; /* center of legend 2 */
306 x1
-= fontsize
/2; /* adjust width */
307 x2
-= fontsize
/2; /* adjust width */
308 leg_continuous(ps
, xx1
, x1
, y0
, label1
, fontsize
, font
, nmap1
, map1
, 0);
309 leg_continuous(ps
, xx2
, x2
, y0
, label2
, fontsize
, font
, nmap2
, map2
, 0);
312 static real
box_height(t_matrix
*mat
, t_psrec
*psr
)
314 return mat
->ny
*psr
->yboxsize
;
317 static real
box_dh(t_psrec
*psr
)
319 return psr
->boxspacing
;
322 #define IS_ONCE (i == nmat-1)
323 static real
box_dh_top(gmx_bool bOnce
, t_psrec
*psr
)
327 if (psr
->bTitle
|| (psr
->bTitleOnce
&& bOnce
) )
329 dh
= 2*psr
->titfontsize
;
339 static gmx_bool
box_do_all_x_maj_ticks(t_psrec
*psr
)
341 return (psr
->boxspacing
> (1.5*psr
->X
.majorticklen
));
344 static gmx_bool
box_do_all_x_min_ticks(t_psrec
*psr
)
346 return (psr
->boxspacing
> (1.5*psr
->X
.minorticklen
));
349 static void draw_boxes(t_psdata ps
, real x0
, real y0
, real w
,
350 int nmat
, t_matrix mat
[], t_psrec
*psr
)
355 char **xtick
, **ytick
;
356 real xx
, yy
, dy
, xx00
, yy00
, offset_x
, offset_y
;
357 int i
, j
, x
, y
, ntx
, nty
, strlength
;
359 /* Only necessary when there will be no y-labels */
364 ps_linewidth(ps
, psr
->boxlinewidth
);
366 for (i
= 0; (i
< nmat
); i
++)
368 dy
= box_height(&(mat
[i
]), psr
);
369 ps_box(ps
, x0
-1, yy00
-1, x0
+w
+1, yy00
+dy
+1);
370 yy00
+= dy
+box_dh(psr
)+box_dh_top(IS_ONCE
, psr
);
373 /* Draw the ticks on the axes */
374 ps_linewidth(ps
, psr
->ticklinewidth
);
377 for (i
= 0; (i
< nmat
); i
++)
379 if (mat
[i
].flags
& MAT_SPATIAL_X
)
389 if (mat
[i
].flags
& MAT_SPATIAL_Y
)
400 for (j
= 0; (j
< ntx
); j
++)
402 sprintf(buf
, "%g", mat
[i
].axis_x
[j
]);
403 xtick
[j
] = strdup(buf
);
405 ps_strfont(ps
, psr
->X
.tickfont
, psr
->X
.tickfontsize
);
406 for (x
= 0; (x
< ntx
); x
++)
408 xx
= xx00
+ (x
+ offset_x
)*psr
->xboxsize
;
409 if ( ( bRmod(mat
[i
].axis_x
[x
], psr
->X
.offset
, psr
->X
.major
) ||
410 (psr
->X
.first
&& (x
== 0))) &&
411 ( (i
== 0) || box_do_all_x_maj_ticks(psr
) ) )
413 /* Longer tick marks */
414 ps_line (ps
, xx
, yy00
, xx
, yy00
-psr
->X
.majorticklen
);
415 /* Plot label on lowest graph only */
419 yy00
-DDD
-psr
->X
.majorticklen
-psr
->X
.tickfontsize
*0.8,
423 else if (bRmod(mat
[i
].axis_x
[x
], psr
->X
.offset
, psr
->X
.minor
) &&
424 ( (i
== 0) || box_do_all_x_min_ticks(psr
) ) )
426 /* Shorter tick marks */
427 ps_line(ps
, xx
, yy00
, xx
, yy00
-psr
->X
.minorticklen
);
429 else if (bRmod(mat
[i
].axis_x
[x
], psr
->X
.offset
, psr
->X
.major
) )
431 /* Even shorter marks, only each X.major */
432 ps_line(ps
, xx
, yy00
, xx
, yy00
-(psr
->boxspacing
/2));
435 ps_strfont(ps
, psr
->Y
.tickfont
, psr
->Y
.tickfontsize
);
437 for (j
= 0; (j
< nty
); j
++)
439 sprintf(buf
, "%g", mat
[i
].axis_y
[j
]);
440 ytick
[j
] = strdup(buf
);
443 for (y
= 0; (y
< nty
); y
++)
445 yy
= yy00
+ (y
+ offset_y
)*psr
->yboxsize
;
446 if (bRmod(mat
[i
].axis_y
[y
], psr
->Y
.offset
, psr
->Y
.major
) ||
447 (psr
->Y
.first
&& (y
== 0)))
450 strlength
= max(strlength
, (int)strlen(ytick
[y
]));
451 ps_line (ps
, xx00
, yy
, xx00
-psr
->Y
.majorticklen
, yy
);
452 ps_ctext(ps
, xx00
-psr
->Y
.majorticklen
-DDD
,
453 yy
-psr
->Y
.tickfontsize
/3.0, ytick
[y
], eXRight
);
455 else if (bRmod(mat
[i
].axis_y
[y
], psr
->Y
.offset
, psr
->Y
.minor
) )
458 ps_line(ps
, xx00
, yy
, xx00
-psr
->Y
.minorticklen
, yy
);
464 /* Label on Y-axis */
465 if (!psr
->bYonce
|| i
== nmat
/2)
467 if (strlen(psr
->Y
.label
) > 0)
469 mylab
= psr
->Y
.label
;
473 mylab
= mat
[i
].label_y
;
475 if (strlen(mylab
) > 0)
477 ps_strfont(ps
, psr
->Y
.font
, psr
->Y
.fontsize
);
479 xxx
= x0
-psr
->X
.majorticklen
-psr
->X
.tickfontsize
*strlength
-DDD
;
480 ps_ctext(ps
, yy00
+box_height(&mat
[i
], psr
)/2.0, 612.5-xxx
,
486 yy00
+= box_height(&(mat
[i
]), psr
)+box_dh(psr
)+box_dh_top(IS_ONCE
, psr
);
488 /* Label on X-axis */
489 if (strlen(psr
->X
.label
) > 0)
491 mylab
= psr
->X
.label
;
495 mylab
= mat
[0].label_x
;
497 if (strlen(mylab
) > 0)
499 ps_strfont(ps
, psr
->X
.font
, psr
->X
.fontsize
);
500 ps_ctext(ps
, x0
+w
/2, y0
-DDD
-psr
->X
.majorticklen
-psr
->X
.tickfontsize
*FUDGE
-
501 psr
->X
.fontsize
, mylab
, eXCenter
);
505 static void draw_zerolines(t_psdata out
, real x0
, real y0
, real w
,
506 int nmat
, t_matrix mat
[], t_psrec
*psr
)
508 real xx
, yy
, dy
, xx00
, yy00
;
513 ps_linewidth(out
, psr
->zerolinewidth
);
514 for (i
= 0; (i
< nmat
); i
++)
516 dy
= box_height(&(mat
[i
]), psr
);
517 /* mat[i].axis_x and _y were already set by draw_boxes */
518 if (psr
->X
.lineatzero
)
520 ps_rgb(out
, linecolors
[psr
->X
.lineatzero
]);
521 for (x
= 0; (x
< mat
[i
].nx
); x
++)
523 xx
= xx00
+(x
+0.7)*psr
->xboxsize
;
524 /* draw lines whenever tick label almost zero (e.g. next trajectory) */
525 if (x
!= 0 && x
< mat
[i
].nx
-1 &&
526 fabs(mat
[i
].axis_x
[x
]) <
527 0.1*fabs(mat
[i
].axis_x
[x
+1]-mat
[i
].axis_x
[x
]) )
529 ps_line (out
, xx
, yy00
, xx
, yy00
+dy
+2);
533 if (psr
->Y
.lineatzero
)
535 ps_rgb(out
, linecolors
[psr
->Y
.lineatzero
]);
536 for (y
= 0; (y
< mat
[i
].ny
); y
++)
538 yy
= yy00
+(y
+0.7)*psr
->yboxsize
;
539 /* draw lines whenever tick label almost zero (e.g. next trajectory) */
540 if (y
!= 0 && y
< mat
[i
].ny
-1 &&
541 fabs(mat
[i
].axis_y
[y
]) <
542 0.1*fabs(mat
[i
].axis_y
[y
+1]-mat
[i
].axis_y
[y
]) )
544 ps_line (out
, xx00
, yy
, xx00
+w
+2, yy
);
548 yy00
+= box_height(&(mat
[i
]), psr
)+box_dh(psr
)+box_dh_top(IS_ONCE
, psr
);
552 static void box_dim(int nmat
, t_matrix mat
[], t_matrix
*mat2
, t_psrec
*psr
,
553 int elegend
, gmx_bool bFrame
,
554 real
*w
, real
*h
, real
*dw
, real
*dh
)
557 real ww
, hh
, dww
, dhh
;
563 for (i
= 0; (i
< nmat
); i
++)
565 ww
= max(ww
, mat
[i
].nx
*psr
->xboxsize
);
566 hh
+= box_height(&(mat
[i
]), psr
);
567 maxytick
= max(maxytick
, mat
[i
].nx
);
571 if (mat
[0].label_y
[0])
573 dww
+= 2.0*(psr
->Y
.fontsize
+DDD
);
575 if (psr
->Y
.major
> 0)
577 dww
+= psr
->Y
.majorticklen
+ DDD
+
578 psr
->Y
.tickfontsize
*(log(maxytick
)/log(10.0));
580 else if (psr
->Y
.minor
> 0)
582 dww
+= psr
->Y
.minorticklen
;
585 if (mat
[0].label_x
[0])
587 dhh
+= psr
->X
.fontsize
+2*DDD
;
589 if ( /* fool emacs auto-indent */
590 (elegend
== elBoth
&& (mat
[0].legend
[0] || mat2
[0].legend
[0])) ||
591 (elegend
== elFirst
&& mat
[0].legend
[0]) ||
592 (elegend
== elSecond
&& mat2
[0].legend
[0]) )
594 dhh
+= 2*(psr
->legfontsize
*FUDGE
+2*DDD
);
598 dhh
+= psr
->legfontsize
*FUDGE
+2*DDD
;
600 if (psr
->X
.major
> 0)
602 dhh
+= psr
->X
.tickfontsize
*FUDGE
+2*DDD
+psr
->X
.majorticklen
;
604 else if (psr
->X
.minor
> 0)
606 dhh
+= psr
->X
.minorticklen
;
609 hh
+= (nmat
-1)*box_dh(psr
);
610 hh
+= box_dh_top(TRUE
, psr
);
613 hh
+= (nmat
-1)*box_dh_top(FALSE
, psr
);
622 int add_maps(t_mapping
**newmap
,
623 int nmap1
, t_mapping map1
[], int nmap2
, t_mapping map2
[])
625 static char mapper
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()-_=+{}|;:',<.>/?";
630 nsymbols
= strlen(mapper
);
632 if (nmap
> nsymbols
*nsymbols
)
634 gmx_fatal(FARGS
, "Not enough symbols to merge the two colormaps\n");
636 printf("Combining colormaps of %d and %d elements into one of %d elements\n",
639 for (j
= 0; j
< nmap1
; j
++)
641 map
[j
].code
.c1
= mapper
[j
% nsymbols
];
644 map
[j
].code
.c2
= mapper
[j
/nsymbols
];
646 map
[j
].rgb
.r
= map1
[j
].rgb
.r
;
647 map
[j
].rgb
.g
= map1
[j
].rgb
.g
;
648 map
[j
].rgb
.b
= map1
[j
].rgb
.b
;
649 map
[j
].desc
= map1
[j
].desc
;
651 for (j
= 0; j
< nmap2
; j
++)
654 map
[k
].code
.c1
= mapper
[k
% nsymbols
];
657 map
[k
].code
.c2
= mapper
[k
/nsymbols
];
659 map
[k
].rgb
.r
= map2
[j
].rgb
.r
;
660 map
[k
].rgb
.g
= map2
[j
].rgb
.g
;
661 map
[k
].rgb
.b
= map2
[j
].rgb
.b
;
662 map
[k
].desc
= map2
[j
].desc
;
669 void xpm_mat(const char *outf
, int nmat
, t_matrix
*mat
, t_matrix
*mat2
,
670 gmx_bool bDiag
, gmx_bool bFirstDiag
)
674 int i
, j
, k
, x
, y
, col
;
676 t_mapping
*map
= NULL
;
678 out
= gmx_ffopen(outf
, "w");
680 for (i
= 0; i
< nmat
; i
++)
682 if (!mat2
|| !diff_maps(mat
[i
].nmap
, mat
[i
].map
, mat2
[i
].nmap
, mat2
[i
].map
))
684 write_xpm_m(out
, mat
[0]);
688 nmap
= add_maps(&map
, mat
[i
].nmap
, mat
[i
].map
, mat2
[i
].nmap
, mat2
[i
].map
);
689 for (x
= 0; (x
< mat
[i
].nx
); x
++)
691 for (y
= 0; (y
< mat
[i
].nx
); y
++)
693 if ((x
< y
) || ((x
== y
) && bFirstDiag
)) /* upper left -> map1 */
695 col
= mat
[i
].matrix
[x
][y
];
697 else /* lower right -> map2 */
699 col
= mat
[i
].nmap
+mat
[i
].matrix
[x
][y
];
701 if ((bDiag
) || (x
!= y
))
703 mat
[i
].matrix
[x
][y
] = col
;
707 mat
[i
].matrix
[x
][y
] = 0;
714 if (strcmp(mat
[i
].title
, mat2
[i
].title
) != 0)
716 sprintf(mat
[i
].title
+strlen(mat
[i
].title
), " / %s", mat2
[i
].title
);
718 if (strcmp(mat
[i
].legend
, mat2
[i
].legend
) != 0)
720 sprintf(mat
[i
].legend
+strlen(mat
[i
].legend
), " / %s", mat2
[i
].legend
);
722 write_xpm_m(out
, mat
[i
]);
728 static void tick_spacing(int n
, real axis
[], real offset
, char axisnm
,
729 real
*major
, real
*minor
)
732 gmx_bool bTryAgain
, bFive
;
733 int i
, j
, t
, f
= 0, ten
;
735 real major_fact
[NFACT
] = {5, 4, 2, 1};
736 real minor_fact
[NFACT
] = {5, 4, 4, 5};
738 /* start with interval between 10 matrix points: */
739 space
= max(10*axis
[1]-axis
[0], axis
[min(10, n
-1)]-axis
[0]);
740 /* get power of 10 */
741 ten
= (int)ceil(log(space
)/log(10))-1;
743 for (t
= ten
+2; t
> ten
-3 && bTryAgain
; t
--)
745 for (f
= 0; f
< NFACT
&& bTryAgain
; f
++)
747 space
= pow(10, t
) * major_fact
[f
];
748 /* count how many ticks we would get: */
750 for (j
= 0; j
< n
; j
++)
752 if (bRmod(axis
[j
], offset
, space
) )
757 /* do we have a reasonable number of ticks ? */
758 bTryAgain
= (i
> min(10, n
-1)) || (i
< 5);
763 space
= max(10*axis
[1]-axis
[0], axis
[min(10, n
-1)]-axis
[0]);
764 fprintf(stderr
, "Auto tick spacing failed for %c-axis, guessing %g\n",
768 *minor
= space
/ minor_fact
[f
-1];
769 fprintf(stderr
, "Auto tick spacing for %c-axis: major %g, minor %g\n",
770 axisnm
, *major
, *minor
);
773 void ps_mat(const char *outf
, int nmat
, t_matrix mat
[], t_matrix mat2
[],
774 gmx_bool bFrame
, gmx_bool bDiag
, gmx_bool bFirstDiag
,
775 gmx_bool bTitle
, gmx_bool bTitleOnce
, gmx_bool bYonce
, int elegend
,
776 real size
, real boxx
, real boxy
, const char *m2p
, const char *m2pout
,
780 char buf
[256], *legend
;
784 int i
, j
, x
, y
, col
, leg
= 0;
787 int nmap1
= 0, nmap2
= 0, leg_nmap
;
788 t_mapping
*map1
= NULL
, *map2
= NULL
, *leg_map
;
789 gmx_bool bMap1
, bNextMap1
, bDiscrete
;
792 libm2p
= m2p
? gmxlibfn(m2p
) : m2p
;
793 get_params(libm2p
, m2pout
, &psrec
);
797 if (psr
->X
.major
<= 0)
799 tick_spacing((mat
[0].flags
& MAT_SPATIAL_X
) ? mat
[0].nx
+ 1 : mat
[0].nx
,
800 mat
[0].axis_x
, psr
->X
.offset
, 'X',
801 &(psr
->X
.major
), &(psr
->X
.minor
) );
803 if (psr
->X
.minor
<= 0)
805 psr
->X
.minor
= psr
->X
.major
/ 2;
807 if (psr
->Y
.major
<= 0)
809 tick_spacing((mat
[0].flags
& MAT_SPATIAL_Y
) ? mat
[0].ny
+ 1 : mat
[0].ny
,
810 mat
[0].axis_y
, psr
->Y
.offset
, 'Y',
811 &(psr
->Y
.major
), &(psr
->Y
.minor
) );
813 if (psr
->Y
.minor
<= 0)
815 psr
->Y
.minor
= psr
->Y
.major
/ 2;
820 psr
->xboxsize
= boxx
;
821 psr
->yboxsize
= boxx
;
825 psr
->yboxsize
= boxy
;
828 if (psr
->xboxsize
== 0)
830 psr
->xboxsize
= size
/mat
[0].nx
;
831 printf("Set the x-size of the box to %.3f\n", psr
->xboxsize
);
833 if (psr
->yboxsize
== 0)
835 psr
->yboxsize
= size
/mat
[0].nx
;
836 printf("Set the y-size of the box to %.3f\n", psr
->yboxsize
);
840 for (i
= 0; (i
< nmat
); i
++)
842 if (mat
[i
].nmap
> nmap1
)
851 printf("Selected legend of matrix # %d for display\n", leg
);
856 for (i
= 0; (i
< nmat
); i
++)
858 if (mat2
[i
].nmap
> nmap2
)
860 nmap2
= mat2
[i
].nmap
;
867 printf("Selected legend of matrix # %d for second display\n", leg
);
870 if ( (mat
[0].legend
[0] == 0) && psr
->legend
)
872 strcpy(mat
[0].legend
, psr
->leglabel
);
875 bTitle
= bTitle
&& mat
[nmat
-1].title
[0];
876 bTitleOnce
= bTitleOnce
&& mat
[nmat
-1].title
[0];
877 psr
->bTitle
= bTitle
;
878 psr
->bTitleOnce
= bTitleOnce
;
879 psr
->bYonce
= bYonce
;
881 /* Set up size of box for nice colors */
882 box_dim(nmat
, mat
, mat2
, psr
, elegend
, bFrame
, &w
, &h
, &dw
, &dh
);
884 /* Set up bounding box */
898 out
= ps_open(outf
, 0, 0, x
, y
);
899 ps_linewidth(out
, psr
->linewidth
);
900 ps_init_rgb_box(out
, psr
->xboxsize
, psr
->yboxsize
);
901 ps_init_rgb_nbox(out
, psr
->xboxsize
, psr
->yboxsize
);
902 ps_translate(out
, psr
->xoffs
, psr
->yoffs
);
906 ps_comment(out
, "Here starts the BOX drawing");
907 draw_boxes(out
, x0
, y0
, w
, nmat
, mat
, psr
);
910 for (i
= 0; (i
< nmat
); i
++)
912 if (bTitle
|| (bTitleOnce
&& i
== nmat
-1) )
914 /* Print title, if any */
916 ps_strfont(out
, psr
->titfont
, psr
->titfontsize
);
917 if (!mat2
|| (strcmp(mat
[i
].title
, mat2
[i
].title
) == 0))
919 strcpy(buf
, mat
[i
].title
);
923 sprintf(buf
, "%s / %s", mat
[i
].title
, mat2
[i
].title
);
925 ps_ctext(out
, x0
+w
/2, y0
+box_height(&(mat
[i
]), psr
)+psr
->titfontsize
,
928 sprintf(buf
, "Here starts the filling of box #%d", i
);
929 ps_comment(out
, buf
);
930 for (x
= 0; (x
< mat
[i
].nx
); x
++)
935 xx
= x0
+x
*psr
->xboxsize
;
936 ps_moveto(out
, xx
, y0
);
938 bMap1
= (!mat2
|| (x
< y
|| (x
== y
&& bFirstDiag
)));
939 if ((bDiag
) || (x
!= y
))
941 col
= mat
[i
].matrix
[x
][y
];
947 for (nexty
= 1; (nexty
<= mat
[i
].ny
); nexty
++)
949 bNextMap1
= (!mat2
|| (x
< nexty
|| (x
== nexty
&& bFirstDiag
)));
950 /* TRUE: upper left -> map1 */
951 /* FALSE: lower right -> map2 */
952 if ((nexty
== mat
[i
].ny
) || (!bDiag
&& (x
== nexty
)))
958 nextcol
= mat
[i
].matrix
[x
][nexty
];
960 if ( (nexty
== mat
[i
].ny
) || (col
!= nextcol
) || (bMap1
!= bNextMap1
) )
966 ps_rgb_nbox(out
, &(mat
[i
].map
[col
].rgb
), nexty
-y
);
970 ps_rgb_nbox(out
, &(mat2
[i
].map
[col
].rgb
), nexty
-y
);
975 ps_moverel(out
, 0, psr
->yboxsize
);
983 y0
+= box_height(&(mat
[i
]), psr
)+box_dh(psr
)+box_dh_top(IS_ONCE
, psr
);
986 if (psr
->X
.lineatzero
|| psr
->Y
.lineatzero
)
988 /* reset y0 for first box */
990 ps_comment(out
, "Here starts the zero lines drawing");
991 draw_zerolines(out
, x0
, y0
, w
, nmat
, mat
, psr
);
994 if (elegend
!= elNone
)
996 ps_comment(out
, "Now it's legend time!");
997 ps_linewidth(out
, psr
->linewidth
);
998 if (mat2
== NULL
|| elegend
!= elSecond
)
1000 bDiscrete
= mat
[0].bDiscrete
;
1001 legend
= mat
[0].legend
;
1007 bDiscrete
= mat2
[0].bDiscrete
;
1008 legend
= mat2
[0].legend
;
1014 leg_discrete(out
, psr
->legfontsize
, DDD
, legend
,
1015 psr
->legfontsize
, psr
->legfont
, leg_nmap
, leg_map
);
1019 if (elegend
!= elBoth
)
1021 leg_continuous(out
, x0
+w
/2, w
/2, DDD
, legend
,
1022 psr
->legfontsize
, psr
->legfont
, leg_nmap
, leg_map
,
1027 leg_bicontinuous(out
, x0
+w
/2, w
, DDD
, mat
[0].legend
, mat2
[0].legend
,
1028 psr
->legfontsize
, psr
->legfont
, nmap1
, map1
, nmap2
, map2
);
1031 ps_comment(out
, "Were there, dude");
1037 void make_axis_labels(int nmat
, t_matrix
*mat
)
1041 for (i
= 0; (i
< nmat
); i
++)
1043 /* Make labels for x axis */
1044 if (mat
[i
].axis_x
== NULL
)
1046 snew(mat
[i
].axis_x
, mat
[i
].nx
);
1047 for (j
= 0; (j
< mat
[i
].nx
); j
++)
1049 mat
[i
].axis_x
[j
] = j
;
1052 /* Make labels for y axis */
1053 if (mat
[i
].axis_y
== NULL
)
1055 snew(mat
[i
].axis_y
, mat
[i
].ny
);
1056 for (j
= 0; (j
< mat
[i
].ny
); j
++)
1058 mat
[i
].axis_y
[j
] = j
;
1064 void prune_mat(int nmat
, t_matrix
*mat
, t_matrix
*mat2
, int skip
)
1066 int i
, x
, y
, xs
, ys
;
1068 for (i
= 0; i
< nmat
; i
++)
1070 fprintf(stderr
, "converting %dx%d matrix to %dx%d\n",
1071 mat
[i
].nx
, mat
[i
].ny
,
1072 (mat
[i
].nx
+skip
-1)/skip
, (mat
[i
].ny
+skip
-1)/skip
);
1073 /* walk through matrix */
1075 for (x
= 0; (x
< mat
[i
].nx
); x
++)
1079 mat
[i
].axis_x
[xs
] = mat
[i
].axis_x
[x
];
1082 mat2
[i
].axis_x
[xs
] = mat2
[i
].axis_x
[x
];
1085 for (y
= 0; (y
< mat
[i
].ny
); y
++)
1089 mat
[i
].axis_y
[ys
] = mat
[i
].axis_y
[y
];
1092 mat2
[i
].axis_y
[ys
] = mat2
[i
].axis_y
[y
];
1097 mat
[i
].matrix
[xs
][ys
] = mat
[i
].matrix
[x
][y
];
1100 mat2
[i
].matrix
[xs
][ys
] = mat2
[i
].matrix
[x
][y
];
1108 /* adjust parameters */
1109 mat
[i
].nx
= (mat
[i
].nx
+skip
-1)/skip
;
1110 mat
[i
].ny
= (mat
[i
].ny
+skip
-1)/skip
;
1113 mat2
[i
].nx
= (mat2
[i
].nx
+skip
-1)/skip
;
1114 mat2
[i
].ny
= (mat2
[i
].ny
+skip
-1)/skip
;
1119 void zero_lines(int nmat
, t_matrix
*mat
, t_matrix
*mat2
)
1124 for (i
= 0; i
< nmat
; i
++)
1126 for (m
= 0; m
< (mat2
? 2 : 1); m
++)
1136 for (x
= 0; x
< mats
[i
].nx
-1; x
++)
1138 if (fabs(mats
[i
].axis_x
[x
+1]) < 1e-5)
1140 for (y
= 0; y
< mats
[i
].ny
; y
++)
1142 mats
[i
].matrix
[x
][y
] = 0;
1146 for (y
= 0; y
< mats
[i
].ny
-1; y
++)
1148 if (fabs(mats
[i
].axis_y
[y
+1]) < 1e-5)
1150 for (x
= 0; x
< mats
[i
].nx
; x
++)
1152 mats
[i
].matrix
[x
][y
] = 0;
1160 void write_combined_matrix(int ecombine
, const char *fn
,
1161 int nmat
, t_matrix
*mat1
, t_matrix
*mat2
,
1162 real
*cmin
, real
*cmax
)
1164 int i
, j
, k
, nlevels
;
1165 t_mapping
*map
= NULL
;
1167 real
**rmat1
, **rmat2
;
1170 out
= gmx_ffopen(fn
, "w");
1171 for (k
= 0; k
< nmat
; k
++)
1173 if (mat2
[k
].nx
!= mat1
[k
].nx
|| mat2
[k
].ny
!= mat1
[k
].ny
)
1175 gmx_fatal(FARGS
, "Size of frame %d in 1st (%dx%d) and 2nd matrix (%dx%d) do"
1176 " not match.\n", k
, mat1
[k
].nx
, mat1
[k
].ny
, mat2
[k
].nx
, mat2
[k
].ny
);
1178 printf("Combining two %dx%d matrices\n", mat1
[k
].nx
, mat1
[k
].ny
);
1179 rmat1
= matrix2real(&mat1
[k
], NULL
);
1180 rmat2
= matrix2real(&mat2
[k
], NULL
);
1181 if (NULL
== rmat1
|| NULL
== rmat2
)
1183 gmx_fatal(FARGS
, "Could not extract real data from %s xpm matrices. Note that, e.g.,\n"
1184 "g_rms and g_mdmat provide such data, but not do_dssp.\n",
1185 (NULL
== rmat1
&& NULL
== rmat2
) ? "both" : "one of the" );
1189 for (j
= 0; j
< mat1
[k
].ny
; j
++)
1191 for (i
= 0; i
< mat1
[k
].nx
; i
++)
1195 case ecAdd
: rmat1
[i
][j
] += rmat2
[i
][j
]; break;
1196 case ecSub
: rmat1
[i
][j
] -= rmat2
[i
][j
]; break;
1197 case ecMult
: rmat1
[i
][j
] *= rmat2
[i
][j
]; break;
1198 case ecDiv
: rmat1
[i
][j
] /= rmat2
[i
][j
]; break;
1200 gmx_fatal(FARGS
, "No such combination rule %d for matrices", ecombine
);
1202 rlo
= min(rlo
, rmat1
[i
][j
]);
1203 rhi
= max(rhi
, rmat1
[i
][j
]);
1214 nlevels
= max(mat1
[k
].nmap
, mat2
[k
].nmap
);
1218 "combination results in uniform matrix (%g), no output\n", rhi
);
1221 else if (rlo>=0 || rhi<=0)
1222 write_xpm(out, mat1[k].flags, mat1[k].title, mat1[k].legend,
1223 mat1[k].label_x, mat1[k].label_y,
1224 mat1[k].nx, mat1[k].ny, mat1[k].axis_x, mat1[k].axis_y,
1225 rmat1, rlo, rhi, rhi<=0?red:white, rhi<=0?white:blue,
1228 write_xpm3(out, mat2[k].flags, mat1[k].title, mat1[k].legend,
1229 mat1[k].label_x, mat1[k].label_y,
1230 mat1[k].nx, mat1[k].ny, mat1[k].axis_x, mat1[k].axis_y,
1231 rmat1, rlo, 0, rhi, red, white, blue, &nlevels);
1235 write_xpm(out
, mat1
[k
].flags
, mat1
[k
].title
, mat1
[k
].legend
,
1236 mat1
[k
].label_x
, mat1
[k
].label_y
,
1237 mat1
[k
].nx
, mat1
[k
].ny
, mat1
[k
].axis_x
, mat1
[k
].axis_y
,
1238 rmat1
, rlo
, rhi
, white
, black
, &nlevels
);
1244 void do_mat(int nmat
, t_matrix
*mat
, t_matrix
*mat2
,
1245 gmx_bool bFrame
, gmx_bool bZeroLine
, gmx_bool bDiag
, gmx_bool bFirstDiag
, gmx_bool bTitle
,
1246 gmx_bool bTitleOnce
, gmx_bool bYonce
, int elegend
,
1247 real size
, real boxx
, real boxy
,
1248 const char *epsfile
, const char *xpmfile
, const char *m2p
,
1249 const char *m2pout
, int skip
, int mapoffset
)
1255 for (k
= 0; (k
< nmat
); k
++)
1257 if ((mat2
[k
].nx
!= mat
[k
].nx
) || (mat2
[k
].ny
!= mat
[k
].ny
))
1259 gmx_fatal(FARGS
, "WAKE UP!! Size of frame %d in 2nd matrix file (%dx%d) does not match size of 1st matrix (%dx%d) or the other way around.\n",
1260 k
, mat2
[k
].nx
, mat2
[k
].ny
, mat
[k
].nx
, mat
[k
].ny
);
1262 for (j
= 0; (j
< mat
[k
].ny
); j
++)
1264 for (i
= bFirstDiag
? j
+1 : j
; (i
< mat
[k
].nx
); i
++)
1266 mat
[k
].matrix
[i
][j
] = mat2
[k
].matrix
[i
][j
];
1271 for (i
= 0; (i
< nmat
); i
++)
1273 fprintf(stderr
, "Matrix %d is %d x %d\n", i
, mat
[i
].nx
, mat
[i
].ny
);
1276 make_axis_labels(nmat
, mat
);
1280 prune_mat(nmat
, mat
, mat2
, skip
);
1285 zero_lines(nmat
, mat
, mat
);
1288 if (epsfile
!= NULL
)
1290 ps_mat(epsfile
, nmat
, mat
, mat2
, bFrame
, bDiag
, bFirstDiag
,
1291 bTitle
, bTitleOnce
, bYonce
, elegend
,
1292 size
, boxx
, boxy
, m2p
, m2pout
, mapoffset
);
1294 if (xpmfile
!= NULL
)
1296 xpm_mat(xpmfile
, nmat
, mat
, mat2
, bDiag
, bFirstDiag
);
1300 void gradient_map(rvec grad
, int nmap
, t_mapping map
[])
1305 for (i
= 0; i
< nmap
; i
++)
1308 map
[i
].rgb
.r
= 1-c
*(1-grad
[XX
]);
1309 map
[i
].rgb
.g
= 1-c
*(1-grad
[YY
]);
1310 map
[i
].rgb
.b
= 1-c
*(1-grad
[ZZ
]);
1314 void gradient_mat(rvec grad
, int nmat
, t_matrix mat
[])
1318 for (m
= 0; m
< nmat
; m
++)
1320 gradient_map(grad
, mat
[m
].nmap
, mat
[m
].map
);
1324 void rainbow_map(gmx_bool bBlue
, int nmap
, t_mapping map
[])
1329 for (i
= 0; i
< nmap
; i
++)
1331 c
= (map
[i
].rgb
.r
+ map
[i
].rgb
.g
+ map
[i
].rgb
.b
)/3;
1340 if (c
<= 0.25) /* 0-0.25 */
1343 g
= pow(4*c
, 0.666);
1346 else if (c
<= 0.5) /* 0.25-0.5 */
1350 b
= pow(2-4*c
, 0.666);
1352 else if (c
<= 0.75) /* 0.5-0.75 */
1354 r
= pow(4*c
-2, 0.666);
1361 g
= pow(4-4*c
, 0.666);
1370 void rainbow_mat(gmx_bool bBlue
, int nmat
, t_matrix mat
[])
1374 for (m
= 0; m
< nmat
; m
++)
1376 rainbow_map(bBlue
, mat
[m
].nmap
, mat
[m
].map
);
1380 int gmx_xpm2ps(int argc
, char *argv
[])
1382 const char *desc
[] = {
1383 "[THISMODULE] makes a beautiful color plot of an XPixelMap file.",
1384 "Labels and axis can be displayed, when they are supplied",
1385 "in the correct matrix format.",
1386 "Matrix data may be generated by programs such as [gmx-do_dssp], [gmx-rms] or",
1387 "[gmx-mdmat].[PAR]",
1388 "Parameters are set in the [TT].m2p[tt] file optionally supplied with",
1389 "[TT]-di[tt]. Reasonable defaults are provided. Settings for the [IT]y[it]-axis",
1390 "default to those for the [IT]x[it]-axis. Font names have a defaulting hierarchy:",
1391 "titlefont -> legendfont; titlefont -> (xfont -> yfont -> ytickfont)",
1392 "-> xtickfont, e.g. setting titlefont sets all fonts, setting xfont",
1393 "sets yfont, ytickfont and xtickfont.[PAR]",
1394 "When no [TT].m2p[tt] file is supplied, many settings are taken from",
1395 "command line options. The most important option is [TT]-size[tt],",
1396 "which sets the size of the whole matrix in postscript units.",
1397 "This option can be overridden with the [TT]-bx[tt] and [TT]-by[tt]",
1398 "options (and the corresponding parameters in the [TT].m2p[tt] file),",
1399 "which set the size of a single matrix element.[PAR]",
1400 "With [TT]-f2[tt] a second matrix file can be supplied. Both matrix",
1401 "files will be read simultaneously and the upper left half of the",
1402 "first one ([TT]-f[tt]) is plotted together with the lower right",
1403 "half of the second one ([TT]-f2[tt]). The diagonal will contain",
1404 "values from the matrix file selected with [TT]-diag[tt].",
1405 "Plotting of the diagonal values can be suppressed altogether by",
1406 "setting [TT]-diag[tt] to [TT]none[tt].",
1407 "In this case, a new color map will be generated with",
1408 "a red gradient for negative numbers and a blue for positive.",
1409 "If the color coding and legend labels of both matrices are identical,",
1410 "only one legend will be displayed, else two separate legends are",
1412 "With [TT]-combine[tt], an alternative operation can be selected",
1413 "to combine the matrices. The output range is automatically set",
1414 "to the actual range of the combined matrix. This can be overridden",
1415 "with [TT]-cmin[tt] and [TT]-cmax[tt].[PAR]",
1416 "[TT]-title[tt] can be set to [TT]none[tt] to suppress the title, or to",
1417 "[TT]ylabel[tt] to show the title in the Y-label position (alongside",
1418 "the [IT]y[it]-axis).[PAR]",
1419 "With the [TT]-rainbow[tt] option, dull grayscale matrices can be turned",
1420 "into attractive color pictures.[PAR]",
1421 "Merged or rainbowed matrices can be written to an XPixelMap file with",
1422 "the [TT]-xpm[tt] option."
1426 const char *fn
, *epsfile
= NULL
, *xpmfile
= NULL
;
1427 int i
, nmat
, nmat2
, etitle
, elegend
, ediag
, erainbow
, ecombine
;
1428 t_matrix
*mat
= NULL
, *mat2
= NULL
;
1429 gmx_bool bTitle
, bTitleOnce
, bDiag
, bFirstDiag
, bGrad
;
1430 static gmx_bool bFrame
= TRUE
, bZeroLine
= FALSE
, bYonce
= FALSE
, bAdd
= FALSE
;
1431 static real size
= 400, boxx
= 0, boxy
= 0, cmin
= 0, cmax
= 0;
1432 static rvec grad
= {0, 0, 0};
1434 etSel
, etTop
, etOnce
, etYlabel
, etNone
, etNR
1436 const char *title
[] = { NULL
, "top", "once", "ylabel", "none", NULL
};
1437 /* MUST correspond to enum elXxx as defined at top of file */
1438 const char *legend
[] = { NULL
, "both", "first", "second", "none", NULL
};
1440 edSel
, edFirst
, edSecond
, edNone
, edNR
1442 const char *diag
[] = { NULL
, "first", "second", "none", NULL
};
1444 erSel
, erNo
, erBlue
, erRed
, erNR
1446 const char *rainbow
[] = { NULL
, "no", "blue", "red", NULL
};
1447 /* MUST correspond to enum ecXxx as defined at top of file */
1448 const char *combine
[] = {
1449 NULL
, "halves", "add", "sub", "mult", "div", NULL
1451 static int skip
= 1, mapoffset
= 0;
1453 { "-frame", FALSE
, etBOOL
, {&bFrame
},
1454 "Display frame, ticks, labels, title and legend" },
1455 { "-title", FALSE
, etENUM
, {title
}, "Show title at" },
1456 { "-yonce", FALSE
, etBOOL
, {&bYonce
}, "Show y-label only once" },
1457 { "-legend", FALSE
, etENUM
, {legend
}, "Show legend" },
1458 { "-diag", FALSE
, etENUM
, {diag
}, "Diagonal" },
1459 { "-size", FALSE
, etREAL
, {&size
},
1460 "Horizontal size of the matrix in ps units" },
1461 { "-bx", FALSE
, etREAL
, {&boxx
},
1462 "Element x-size, overrides [TT]-size[tt] (also y-size when [TT]-by[tt] is not set)" },
1463 { "-by", FALSE
, etREAL
, {&boxy
}, "Element y-size" },
1464 { "-rainbow", FALSE
, etENUM
, {rainbow
},
1465 "Rainbow colors, convert white to" },
1466 { "-gradient", FALSE
, etRVEC
, {grad
},
1467 "Re-scale colormap to a smooth gradient from white {1,1,1} to {r,g,b}" },
1468 { "-skip", FALSE
, etINT
, {&skip
},
1469 "only write out every nr-th row and column" },
1470 { "-zeroline", FALSE
, etBOOL
, {&bZeroLine
},
1471 "insert line in [TT].xpm[tt] matrix where axis label is zero"},
1472 { "-legoffset", FALSE
, etINT
, {&mapoffset
},
1473 "Skip first N colors from [TT].xpm[tt] file for the legend" },
1474 { "-combine", FALSE
, etENUM
, {combine
}, "Combine two matrices" },
1475 { "-cmin", FALSE
, etREAL
, {&cmin
}, "Minimum for combination output" },
1476 { "-cmax", FALSE
, etREAL
, {&cmax
}, "Maximum for combination output" }
1478 #define NPA asize(pa)
1480 { efXPM
, "-f", NULL
, ffREAD
},
1481 { efXPM
, "-f2", "root2", ffOPTRD
},
1482 { efM2P
, "-di", NULL
, ffLIBOPTRD
},
1483 { efM2P
, "-do", "out", ffOPTWR
},
1484 { efEPS
, "-o", NULL
, ffOPTWR
},
1485 { efXPM
, "-xpm", NULL
, ffOPTWR
}
1487 #define NFILE asize(fnm)
1489 if (!parse_common_args(&argc
, argv
, PCA_CAN_VIEW
,
1490 NFILE
, fnm
, NPA
, pa
,
1491 asize(desc
), desc
, 0, NULL
, &oenv
))
1496 etitle
= nenum(title
);
1497 elegend
= nenum(legend
);
1498 ediag
= nenum(diag
);
1499 erainbow
= nenum(rainbow
);
1500 ecombine
= nenum(combine
);
1501 bGrad
= opt2parg_bSet("-gradient", NPA
, pa
);
1502 for (i
= 0; i
< DIM
; i
++)
1504 if (grad
[i
] < 0 || grad
[i
] > 1)
1506 gmx_fatal(FARGS
, "RGB value %g out of range (0.0-1.0)", grad
[i
]);
1515 epsfile
= ftp2fn_null(efEPS
, NFILE
, fnm
);
1516 xpmfile
= opt2fn_null("-xpm", NFILE
, fnm
);
1517 if (epsfile
== NULL
&& xpmfile
== NULL
)
1519 if (ecombine
!= ecHalves
)
1521 xpmfile
= opt2fn("-xpm", NFILE
, fnm
);
1525 epsfile
= ftp2fn(efEPS
, NFILE
, fnm
);
1528 if (ecombine
!= ecHalves
&& epsfile
)
1531 "WARNING: can only write result of arithmetic combination "
1532 "of two matrices to .xpm file\n"
1533 " file %s will not be written\n", epsfile
);
1537 bDiag
= ediag
!= edNone
;
1538 bFirstDiag
= ediag
!= edSecond
;
1540 fn
= opt2fn("-f", NFILE
, fnm
);
1541 nmat
= read_xpm_matrix(fn
, &mat
);
1542 fprintf(stderr
, "There %s %d matri%s in %s\n", (nmat
> 1) ? "are" : "is", nmat
, (nmat
> 1) ? "ces" : "x", fn
);
1543 fn
= opt2fn_null("-f2", NFILE
, fnm
);
1546 nmat2
= read_xpm_matrix(fn
, &mat2
);
1547 fprintf(stderr
, "There %s %d matri%s in %s\n", (nmat2
> 1) ? "are" : "is", nmat2
, (nmat2
> 1) ? "ces" : "x", fn
);
1550 fprintf(stderr
, "Different number of matrices, using the smallest number.\n");
1551 nmat
= nmat2
= min(nmat
, nmat2
);
1556 if (ecombine
!= ecHalves
)
1559 "WARNING: arithmetic matrix combination selected (-combine), "
1560 "but no second matrix (-f2) supplied\n"
1561 " no matrix combination will be performed\n");
1566 bTitle
= etitle
== etTop
;
1567 bTitleOnce
= etitle
== etOnce
;
1568 if (etitle
== etYlabel
)
1570 for (i
= 0; (i
< nmat
); i
++)
1572 strcpy(mat
[i
].label_y
, mat
[i
].title
);
1575 strcpy(mat2
[i
].label_y
, mat2
[i
].title
);
1581 gradient_mat(grad
, nmat
, mat
);
1584 gradient_mat(grad
, nmat2
, mat2
);
1587 if (erainbow
!= erNo
)
1589 rainbow_mat(erainbow
== erBlue
, nmat
, mat
);
1592 rainbow_mat(erainbow
== erBlue
, nmat2
, mat2
);
1596 if ((mat2
== NULL
) && (elegend
!= elNone
))
1601 if (ecombine
&& ecombine
!= ecHalves
)
1603 write_combined_matrix(ecombine
, xpmfile
, nmat
, mat
, mat2
,
1604 opt2parg_bSet("-cmin", NPA
, pa
) ? &cmin
: NULL
,
1605 opt2parg_bSet("-cmax", NPA
, pa
) ? &cmax
: NULL
);
1609 do_mat(nmat
, mat
, mat2
, bFrame
, bZeroLine
, bDiag
, bFirstDiag
,
1610 bTitle
, bTitleOnce
, bYonce
,
1611 elegend
, size
, boxx
, boxy
, epsfile
, xpmfile
,
1612 opt2fn_null("-di", NFILE
, fnm
), opt2fn_null("-do", NFILE
, fnm
), skip
,
1616 view_all(oenv
, NFILE
, fnm
);