changed reading hint
[gromacs/adressmacs.git] / src / tools / xpm2ps.c
blobd1701d66aedca4c9ec2f32a3bd6b27bd750ea831
1 /*
2 * $Id$
3 *
4 * This source code is part of
5 *
6 * G R O M A C S
7 *
8 * GROningen MAchine for Chemical Simulations
9 *
10 * VERSION 2.0
12 * Copyright (c) 1991-1999
13 * BIOSON Research Institute, Dept. of Biophysical Chemistry
14 * University of Groningen, The Netherlands
16 * Please refer to:
17 * GROMACS: A message-passing parallel molecular dynamics implementation
18 * H.J.C. Berendsen, D. van der Spoel and R. van Drunen
19 * Comp. Phys. Comm. 91, 43-56 (1995)
21 * Also check out our WWW page:
22 * http://md.chem.rug.nl/~gmx
23 * or e-mail to:
24 * gromacs@chem.rug.nl
26 * And Hey:
27 * Great Red Oystrich Makes All Chemists Sane
29 static char *SRCID_xpm2ps_c = "$Id$";
31 #include <math.h>
32 #include "string2.h"
33 #include "copyrite.h"
34 #include "typedefs.h"
35 #include "macros.h"
36 #include "statutil.h"
37 #include "writeps.h"
38 #include "futil.h"
39 #include "fatal.h"
40 #include "smalloc.h"
41 #include "string2.h"
42 #include "matio.h"
44 #define FUDGE 1.2
45 #define DDD 2
47 typedef struct {
48 int major;
49 int minor;
50 int offset;
51 bool first;
52 real majorticklen;
53 real minorticklen;
54 char label[STRLEN];
55 real fontsize;
56 char font[STRLEN];
57 real tickfontsize;
58 char tickfont[STRLEN];
59 } t_axisdef;
61 typedef struct {
62 int bw;
63 real xoffs,yoffs;
64 bool bTitle;
65 real titfontsize;
66 char titfont[STRLEN];
67 bool legend;
68 real legfontsize;
69 char legfont[STRLEN];
70 char leglabel[STRLEN];
71 char leg2label[STRLEN];
72 real xboxsize;
73 real yboxsize;
74 real boxspacing;
75 t_axisdef X,Y;
76 } t_psrec;
78 void get_params(char *mpin,char *mpout,t_psrec *psr)
80 static char *bools[BOOL_NR+1] = { "no", "yes", NULL };
81 t_inpfile *inp;
82 char *tmp;
83 int ninp;
85 inp=read_inpfile(mpin,&ninp);
86 ETYPE("black&white", psr->bw, bools);
87 STYPE("titlefont", psr->titfont, "Helvetica");
88 RTYPE("titlefontsize", psr->titfontsize, 20.0);
89 ETYPE("legend", psr->legend, bools);
90 STYPE("legendfont", psr->legfont, "Helvetica");
91 STYPE("legendlabel", psr->leglabel, "");
92 STYPE("legend2label", psr->leg2label, psr->leglabel);
93 RTYPE("legendfontsize", psr->legfontsize, 14.0);
94 RTYPE("xbox", psr->xboxsize, 2.0);
95 RTYPE("ybox", psr->yboxsize, 2.0);
96 RTYPE("matrixspacing", psr->boxspacing, 20.0);
97 RTYPE("xoffset", psr->xoffs, 0.0);
98 RTYPE("yoffset", psr->yoffs, 0.0);
99 ITYPE("x-major", psr->X.major, 20);
100 ITYPE("x-minor", psr->X.minor, 5);
101 ITYPE("x-firstmajor", psr->X.offset, 0);
102 ETYPE("x-majorat0", psr->X.first, bools);
103 RTYPE("x-majorticklen", psr->X.majorticklen, 8.0);
104 RTYPE("x-minorticklen", psr->X.minorticklen, 4.0);
105 STYPE("x-label", psr->X.label, "");
106 RTYPE("x-fontsize", psr->X.fontsize, 16.0);
107 STYPE("x-font", psr->X.font, "Helvetica");
108 RTYPE("x-tickfontsize", psr->X.tickfontsize, 10.0);
109 STYPE("x-tickfont", psr->X.tickfont, "Helvetica");
110 ITYPE("y-major", psr->Y.major, 20);
111 ITYPE("y-minor", psr->Y.minor, 5);
112 ITYPE("y-firstmajor", psr->Y.offset, 0);
113 ETYPE("y-majorat0", psr->Y.first, bools);
114 RTYPE("y-majorticklen", psr->Y.majorticklen, 8.0);
115 RTYPE("y-minorticklen", psr->Y.minorticklen, 4.0);
116 STYPE("y-label", psr->Y.label, "");
117 RTYPE("y-fontsize", psr->Y.fontsize, 16.0);
118 STYPE("y-font", psr->Y.font, "Helvetica");
119 RTYPE("y-tickfontsize", psr->Y.tickfontsize, 10.0);
120 STYPE("y-tickfont", psr->Y.tickfont, "Helvetica");
121 if (mpout)
122 write_inpfile(mpout,ninp,inp);
125 t_rgb black={ 0.0, 0.0, 0.0 };
126 #define BLACK (&black)
128 bool diff_maps(int nmap1,t_mapping *map1,int nmap2,t_mapping *map2)
130 int i;
131 bool bDiff,bColDiff=FALSE;
133 if (nmap1 != nmap2)
134 bDiff=TRUE;
135 else {
136 bDiff=FALSE;
137 for(i=0; i<nmap1; i++) {
138 if (!matelmt_cmp(map1[i].code, map2[i].code)) bDiff=TRUE;
139 if (strcmp(map1[i].desc,map2[i].desc) != 0) bDiff=TRUE;
140 if ((map1[i].rgb.r!=map2[i].rgb.r) ||
141 (map1[i].rgb.g!=map2[i].rgb.g) ||
142 (map1[i].rgb.b!=map2[i].rgb.b))
143 bColDiff=TRUE;
145 if (!bDiff && bColDiff)
146 fprintf(stderr,"Warning: two colormaps differ only in RGB value, using one colormap.\n");
149 return bDiff;
152 void leg_discrete(FILE *ps,real x0,real y0,char *label,
153 real fontsize,char *font,int nmap,t_mapping map[])
155 int i;
156 real yhh;
157 real boxhh;
159 boxhh=fontsize+DDD;
160 /* LANDSCAPE */
161 ps_rgb(ps,BLACK);
162 ps_strfont(ps,font,fontsize);
163 yhh=y0+fontsize+3*DDD;
164 if ((int)strlen(label) > 0)
165 ps_ctext(ps,x0,yhh,label,eXLeft);
166 ps_moveto(ps,x0,y0);
167 for(i=0; (i<nmap); i++) {
168 ps_setorigin(ps);
169 ps_rgb(ps,&(map[i].rgb));
170 ps_fillbox(ps,DDD,DDD,DDD+fontsize,boxhh-DDD);
171 ps_rgb(ps,BLACK);
172 ps_box(ps,DDD,DDD,DDD+fontsize,boxhh-DDD);
173 ps_ctext(ps,boxhh+2*DDD,fontsize/3,map[i].desc,eXLeft);
174 ps_unsetorigin(ps);
175 ps_moverel(ps,DDD,-fontsize/3);
179 void leg_continuous(FILE *ps,real x0,real x,real y0,char *label,
180 real fontsize,char *font,
181 int nmap,t_mapping map[])
183 int i;
184 real xx0;
185 real yhh,boxxh,boxyh;
187 boxyh=fontsize;
188 if (x<8*fontsize)
189 x=8*fontsize;
190 boxxh=(real)x/(real)nmap;
191 if (boxxh>fontsize)
192 boxxh=fontsize;
194 /* LANDSCAPE */
195 xx0=x0-(nmap*boxxh)/2.0;
197 for(i=0; (i<nmap); i++) {
198 ps_rgb(ps,&(map[i].rgb));
199 ps_fillbox(ps,xx0+i*boxxh,y0,xx0+(i+1)*boxxh,y0+boxyh);
201 ps_strfont(ps,font,fontsize);
202 ps_rgb(ps,BLACK);
203 ps_box(ps,xx0,y0,xx0+nmap*boxxh,y0+boxyh);
205 yhh=y0+boxyh+3*DDD;
206 ps_ctext(ps,xx0+boxxh/2,yhh,map[0].desc,eXCenter);
207 if ((int)strlen(label) > 0)
208 ps_ctext(ps,x0,yhh,label,eXCenter);
209 ps_ctext(ps,xx0+(nmap*boxxh)-boxxh/2,yhh,map[nmap-1].desc,eXCenter);
212 void leg_bicontinuous(FILE *ps,real x0,real x,real y0,char *label1,char *label2,
213 real fontsize,char *font,
214 int nmap1,t_mapping map1[],int nmap2,t_mapping map2[])
216 real xx1,xx2,x1,x2;
218 x1=x/(nmap1+nmap2)*nmap1;/* width of legend 1 */
219 x2=x/(nmap1+nmap2)*nmap2;/* width of legend 2 */
220 xx1=x0-(x2/2.0)-fontsize;/* center of legend 1 */
221 xx2=x0+(x1/2.0)+fontsize;/* center of legend 2 */
222 x1-=fontsize/2;/* adjust width */
223 x2-=fontsize/2;/* adjust width */
224 leg_continuous(ps,xx1,x1,y0,label1,fontsize,font,nmap1,map1);
225 leg_continuous(ps,xx2,x2,y0,label2,fontsize,font,nmap2,map2);
228 static real box_height(t_matrix *mat,t_psrec *psr)
230 return mat->ny*psr->yboxsize;
233 static real box_dh(t_psrec *psr)
235 return psr->boxspacing;
238 static real box_dh_top(t_psrec *psr)
240 real dh;
242 if (psr->bTitle)
243 dh=2*psr->titfontsize;
244 else
245 dh=0;
247 return dh;
250 static bool box_do_all_x_maj_ticks(t_psrec *psr)
252 return (psr->boxspacing>(1.5*psr->X.majorticklen));
255 static bool box_do_all_x_min_ticks(t_psrec *psr)
257 return (psr->boxspacing>(1.5*psr->X.minorticklen));
260 static void draw_boxes(FILE *out,real x0,real y0,real w,real h,
261 int nmat,t_matrix mat[],t_psrec *psr)
263 char buf[12];
264 real xxx;
265 char **xtick,**ytick;
266 real xx,yy,dy,xx00,yy00;
267 int i,j,x,y,strlength;
269 /* Only necessary when there will be no y-labels */
270 strlength = 0;
272 /* Draw the box */
273 ps_rgb(out,BLACK);
274 yy00=y0;
275 for(i=0; (i<nmat); i++) {
276 dy=box_height(&(mat[i]),psr);
277 ps_box(out,x0-1,yy00-1,x0+w+1,yy00+dy+1);
278 yy00+=dy+box_dh(psr)+box_dh_top(psr);
281 /* Draw the ticks on the axes */
282 xx00=x0-1;
283 yy00=y0-1;
284 for (i=0; (i<nmat); i++) {
285 if (mat[i].axis_x==NULL) {
286 snew(mat[i].axis_x,mat[i].nx);
287 for(j=0; (j<mat[i].nx); j++)
288 mat[i].axis_x[j]=j;
290 /* Make labels for x axis */
291 snew(xtick,mat[i].nx);
292 for(j=0; (j<mat[i].nx); j++) {
293 sprintf(buf,"%g",mat[i].axis_x[j]);
294 xtick[j]=strdup(buf);
296 ps_strfont(out,psr->X.tickfont,psr->X.tickfontsize);
297 for(x=0; (x<mat[i].nx); x++) {
298 xx=xx00+(x+0.7)*psr->xboxsize;
299 if ( ( (x % psr->X.major == psr->X.offset) ||
300 (psr->X.first && (x==0))) &&
301 ( (i == 0) || box_do_all_x_maj_ticks(psr) ) ) {
302 /* Longer tick marks */
303 ps_line (out,xx,yy00,xx,yy00-psr->X.majorticklen);
304 /* Plot label on lowest graph only */
305 if (i == 0)
306 ps_ctext(out,xx,
307 yy00-DDD-psr->X.majorticklen-psr->X.tickfontsize*0.8,
308 xtick[x],eXCenter);
309 } else if ( ( (x-psr->X.offset) % psr->X.minor == 0) &&
310 ( (i == 0) || box_do_all_x_min_ticks(psr) ) ){
311 /* Shorter tick marks */
312 ps_line(out,xx,yy00,xx,yy00-psr->X.minorticklen);
313 } else if (x % psr->X.major == psr->X.offset) {
314 /* Even shorter marks, only each X.offset */
315 ps_line(out,xx,yy00,xx,yy00-(psr->boxspacing/2));
318 ps_strfont(out,psr->Y.tickfont,psr->Y.tickfontsize);
319 /* Make labels for Y axis */
320 if (mat[i].axis_y==NULL) {
321 snew(mat[i].axis_y,mat[i].ny);
322 for(j=0; (j<mat[i].ny); j++)
323 mat[i].axis_y[j]=j;
325 snew(ytick,mat[i].ny);
326 for(j=0; (j<mat[i].ny); j++) {
327 sprintf(buf,"%g",mat[i].axis_y[j]);
328 ytick[j]=strdup(buf);
331 for(y=0; (y<mat[i].ny); y++) {
332 yy=yy00+(y+0.7)*psr->yboxsize;
333 if ( (y % psr->Y.major == psr->Y.offset) || (psr->Y.first && (y==0))) {
334 /* Major ticks */
335 strlength=max(strlength,(int)strlen(ytick[y]));
336 ps_line (out,xx00,yy,xx00-psr->Y.majorticklen,yy);
337 ps_ctext(out,xx00-psr->Y.majorticklen-DDD,
338 yy-psr->Y.tickfontsize/3.0,ytick[y],eXRight);
340 else if ((y-psr->Y.offset) % psr->Y.minor == 0) {
341 /* Minor ticks */
342 ps_line(out,xx00,yy,xx00-psr->Y.minorticklen,yy);
345 sfree(xtick);
346 sfree(ytick);
348 /* Label on Y-axis */
349 ps_strfont(out,psr->Y.font,psr->Y.fontsize);
350 ps_rotate(out,TRUE);
351 xxx=x0-psr->X.majorticklen-psr->X.tickfontsize*strlength-DDD;
352 ps_ctext(out,yy00+box_height(&mat[i],psr)/2.0,612.5-xxx,
353 mat[i].label_y,eXCenter);
354 ps_rotate(out,FALSE);
356 yy00+=box_height(&(mat[i]),psr)+box_dh(psr)+box_dh_top(psr);
358 /* Label on X-axis */
359 ps_strfont(out,psr->X.font,psr->X.fontsize);
360 if (strlen(mat[0].label_x) == 0)
361 ps_ctext(out,x0+w/2,y0-DDD-psr->X.majorticklen-psr->X.tickfontsize*FUDGE-
362 psr->X.fontsize,psr->X.label,eXCenter);
363 else
364 ps_ctext(out,x0+w/2,y0-DDD-psr->X.majorticklen-psr->X.tickfontsize*FUDGE-
365 psr->X.fontsize,mat[0].label_x,eXCenter);
368 static void box_dim(int nmat,t_matrix mat[],t_matrix *mat2,t_psrec *psr,
369 char w_legend,real *w,real *h,real *dw,real *dh)
371 int i,maxytick;
372 real ww,hh,dww,dhh;
374 hh=dww=dhh=0;
375 maxytick=0;
377 ww=0;
378 for(i=0; (i<nmat); i++) {
379 ww=max(ww,mat[i].nx*psr->xboxsize);
380 hh+=box_height(&(mat[i]),psr);
381 maxytick=max(maxytick,mat[i].nx);
383 dww=0;
384 if (mat[0].label_y[0])
385 dww+=2.0*(psr->Y.fontsize+DDD);
386 if (psr->Y.major > 0)
387 dww+=psr->Y.majorticklen+DDD+psr->Y.tickfontsize*(log(maxytick)/log(10.0));
388 else if (psr->Y.minor > 0)
389 dww+=psr->Y.minorticklen;
391 dhh=0;
392 if (mat[0].label_x[0])
393 dhh+=psr->X.fontsize+2*DDD;
394 if (((w_legend == 'b') && (mat[0].legend[0] || mat2[0].legend[0])) ||
395 ((w_legend == 'f') && mat[0].legend[0]) ||
396 ((w_legend == 's') && mat2[0].legend[0]))
397 dhh+=2*(psr->legfontsize*FUDGE+2*DDD);
398 else
399 dhh+=psr->legfontsize*FUDGE+2*DDD;
400 if (psr->X.major > 0)
401 dhh+=psr->X.tickfontsize*FUDGE+2*DDD+psr->X.majorticklen;
402 else if (psr->X.minor > 0)
403 dhh+=psr->X.minorticklen;
405 hh+=(nmat-1)*box_dh(psr)+nmat*box_dh_top(psr);
407 *w=ww;
408 *h=hh;
409 *dw=dww;
410 *dh=dhh;
413 void xpm_mat(char *outf,
414 int nmat,t_matrix *mat,t_matrix *mat2,bool bDiag,bool bFirstDiag)
416 FILE *out;
417 char buf[100];
418 int i,j,k,x,y,col;
419 static char mapper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()-_=+{}|;:',<.>/?";
420 #define NMAP strlen(mapper)
421 int nmap,nmap1,nmap2;
422 t_mapping *map;
424 out=ffopen(outf,"w");
426 for(i=0; i<nmat; i++) {
427 if (!mat2 || !diff_maps(mat[i].nmap,mat[i].map,mat2[i].nmap,mat2[i].map))
428 write_xpm_m(out,mat[0]);
429 else {
430 nmap1=mat[i].nmap;
431 nmap2=mat2[i].nmap;
432 nmap=nmap1+nmap2;
433 snew(map,nmap);
434 if (nmap > NMAP*NMAP)
435 fatal_error(0,"Not enough symbols to merge the two colormaps\n");
436 for(j=0; j<nmap1; j++) {
437 map[j].code.c1=mapper[j % NMAP];
438 if (nmap > NMAP)
439 map[j].code.c2=mapper[j/NMAP];
440 map[j].rgb.r=mat[i].map[j].rgb.r;
441 map[j].rgb.g=mat[i].map[j].rgb.g;
442 map[j].rgb.b=mat[i].map[j].rgb.b;
443 map[j].desc=mat[i].map[j].desc;
445 for(j=0; j<nmap2; j++) {
446 k=j+nmap1;
447 map[k].code.c1=mapper[k % NMAP];
448 if (nmap > NMAP)
449 map[k].code.c2=mapper[k/NMAP];
450 map[k].rgb.r=mat2[i].map[j].rgb.r;
451 map[k].rgb.g=mat2[i].map[j].rgb.g;
452 map[k].rgb.b=mat2[i].map[j].rgb.b;
453 map[k].desc=mat2[i].map[j].desc;
455 for(x=0; (x<mat[i].nx); x++) {
456 for(y=0; (y<mat[i].nx); y++) {
457 if ((x<y) || ((x==y) && bFirstDiag)) /* upper left -> map1 */
458 col=mat[i].matrix[x][y];
459 else /* lower right -> map2 */
460 col=nmap1+mat[i].matrix[x][y];
461 if ((bDiag) || (x!=y))
462 mat[i].matrix[x][y]=col;
463 else
464 mat[i].matrix[x][y]=0;
467 mat[i].nmap=nmap;
468 mat[i].map=map;
469 if (mat2 && (strcmp(mat[i].title,mat2[i].title) != 0))
470 sprintf(mat[i].title,"%s / %s",mat[i].title,mat2[i].title);
471 if (mat2 && (strcmp(mat[i].legend,mat2[i].legend) != 0))
472 sprintf(mat[i].legend,"%s / %s",mat[i].legend,mat2[i].legend);
473 write_xpm_m(out,mat[i]);
476 fclose(out);
479 void ps_mat(char *outf,int nmat,t_matrix mat[],t_matrix mat2[],
480 bool bDiag,bool bFirstDiag,bool bTitle,char w_legend,
481 real boxx,real boxy,char *m2p,char *m2pout)
483 char buf[256],*legend;
484 FILE *out;
485 t_psrec psrec,*psr;
486 int W,H;
487 int i,x,y,col,leg=0;
488 real x0,y0,xx;
489 real w,h,dw,dh;
490 int nmap1=0,nmap2=0,leg_nmap;
491 t_mapping *map1=NULL,*map2=NULL,*leg_map;
492 bool bMap1,bNextMap1,bDiscrete;
494 get_params(libfn(m2p),m2pout,&psrec);
496 psr=&psrec;
498 if (boxx>0) {
499 psr->xboxsize=boxx;
500 psr->yboxsize=boxx;
502 if (boxy>0)
503 psr->yboxsize=boxy;
505 nmap1=0;
506 for (i=0; (i<nmat); i++)
507 if (mat[i].nmap>nmap1) {
508 nmap1=mat[i].nmap;
509 map1=mat[i].map;
510 leg=i+1;
512 if (leg!=1)
513 printf("Selected legend of matrix # %d for display\n",leg);
514 if (mat2) {
515 nmap2=0;
516 for (i=0; (i<nmat); i++)
517 if (mat2[i].nmap>nmap2) {
518 nmap2=mat2[i].nmap;
519 map2=mat2[i].map;
520 leg=i+1;
522 if (leg!=1)
523 printf("Selected legend of matrix # %d for second display\n",leg);
525 if ( (mat[0].legend[0]==0) && psr->legend )
526 strcpy(mat[0].legend, psr->leglabel);
528 bTitle = bTitle && mat[nmat-1].title[0];
529 psr->bTitle = bTitle;
531 /* Set up size of box for nice colors */
532 box_dim(nmat,mat,mat2,psr,w_legend,&w,&h,&dw,&dh);
534 /* Set up bounding box */
535 W=w+dw;
536 H=h+dh;
538 /* Start box at */
539 x0=dw;
540 y0=dh;
542 if (bTitle)
543 out=ps_open(outf,0,0,W+psr->xoffs+5*DDD,H+psr->yoffs+4*DDD+
544 2*psr->titfontsize);
545 else
547 out=ps_open(outf,0,0,W+psr->xoffs+5*DDD,H+psr->yoffs+4*DDD);
548 ps_init_rgb_box(out,psr->xboxsize,psr->yboxsize);
549 ps_init_rgb_nbox(out,psr->xboxsize,psr->yboxsize);
550 ps_translate(out,psr->xoffs,psr->yoffs);
552 ps_comment(out,"Here starts the BOX drawing");
553 draw_boxes(out,x0,y0,w,h,nmat,mat,psr);
555 if (bTitle) {
556 ps_strfont(out,psr->titfont,psr->titfontsize);
557 if (!mat2 || (strcmp(mat[nmat-1].title,mat2[nmat-1].title) == 0))
558 strcpy(buf,mat[nmat-1].title);
559 else
560 sprintf(buf,"%s / %s",mat[nmat-1].title,mat2[nmat-1].title);
561 ps_ctext(out,x0+w/2,y0+h+2*DDD+psr->titfontsize,
562 buf,eXCenter);
566 /* LANDSCAPE */
567 for(i=0; (i<nmat); i++) {
568 if (bTitle) {
569 /* Print title, if any */
570 ps_rgb(out,BLACK);
571 ps_strfont(out,psr->titfont,psr->titfontsize);
572 if (!mat2 || (strcmp(mat[i].title,mat2[i].title) == 0))
573 strcpy(buf,mat[i].title);
574 else
575 sprintf(buf,"%s / %s",mat[i].title,mat2[i].title);
576 ps_ctext(out,x0+w/2,y0+box_height(&(mat[i]),psr)+psr->titfontsize,
577 buf,eXCenter);
579 sprintf(buf,"Here starts the filling of box #%d",i);
580 ps_comment(out,buf);
581 for(x=0; (x<mat[i].nx); x++) {
582 int nexty;
583 int nextcol;
585 xx=x0+x*psr->xboxsize;
586 ps_moveto(out,xx,y0);
587 y=0;
588 bMap1 = (!mat2 || (x<y || (x==y && bFirstDiag)));
589 if ((bDiag) || (x!=y))
590 col = mat[i].matrix[x][y];
591 else
592 col = -1;
593 for(nexty=1; (nexty<=mat[i].ny); nexty++) {
594 bNextMap1 = (!mat2 || (x<nexty || (x==nexty && bFirstDiag)));
595 /* TRUE: upper left -> map1 */
596 /* FALSE: lower right -> map2 */
597 if ((nexty==mat[i].ny) || (!bDiag && (x==nexty)))
598 nextcol = -1;
599 else
600 nextcol=mat[i].matrix[x][nexty];
601 if ( (nexty==mat[i].ny) || (col!=nextcol) || (bMap1!=bNextMap1) ) {
602 if (col >= 0)
603 if (bMap1)
604 ps_rgb_nbox(out,&(mat[i].map[col].rgb),nexty-y);
605 else
606 ps_rgb_nbox(out,&(mat2[i].map[col].rgb),nexty-y);
607 else
608 ps_moverel(out,0,psr->yboxsize);
609 y=nexty;
610 bMap1=bNextMap1;
611 col=nextcol;
615 y0+=box_height(&(mat[i]),psr)+box_dh(psr)+box_dh_top(psr);
618 if (w_legend != 'n') {
619 ps_comment(out,"Now it's legend time!");
620 if ((mat2==NULL) || (w_legend != 's')) {
621 bDiscrete = mat[0].bDiscrete;
622 legend = mat[0].legend;
623 leg_nmap = nmap1;
624 leg_map = map1;
625 } else {
626 bDiscrete = mat2[0].bDiscrete;
627 legend = mat2[0].legend;
628 leg_nmap = nmap2;
629 leg_map = map2;
631 if (bDiscrete)
632 leg_discrete(out,psr->legfontsize,DDD,legend,
633 psr->legfontsize,psr->legfont,leg_nmap,leg_map);
634 else {
635 if (w_legend != 'b')
636 leg_continuous(out,x0+w/2,w/2,DDD,legend,
637 psr->legfontsize,psr->legfont,leg_nmap,leg_map);
638 else
639 leg_bicontinuous(out,x0+w/2,w,DDD,mat[0].legend,mat2[0].legend,
640 psr->legfontsize,psr->legfont,nmap1,map1,nmap2,map2);
642 ps_comment(out,"Were there, dude");
645 ps_close(out);
648 void do_mat(int nmat,t_matrix *mat,int nmat2,t_matrix *mat2,
649 bool bDiag,bool bFirstDiag,bool bTitle,char w_legend,
650 real boxx,real boxy,
651 char *epsfile,char *xpmfile,char *m2p,char *m2pout)
653 int i,j,k,copy_start;
655 if (mat2) {
656 for (k=0; (k<nmat); k++) {
657 if ((mat2[k].nx!=mat[k].nx) || (mat2[k].ny!=mat[k].ny))
658 fatal_error(0,"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",
659 k,mat2[k].nx,mat2[k].ny,mat[k].nx,mat[k].ny);
660 for (j=0; (j<mat[k].ny); j++) {
661 if (bFirstDiag)
662 copy_start = j+1;
663 else
664 copy_start = j;
665 for (i=copy_start; (i<mat[k].nx); i++)
666 mat[k].matrix[i][j]=mat2[k].matrix[i][j];
670 for(i=0; (i<nmat); i++)
671 fprintf(stderr,"Matrix %d is %d x %d\n",i,mat[i].nx,mat[i].ny);
674 if (epsfile!=NULL)
675 ps_mat(epsfile,nmat,mat,mat2,bDiag,bFirstDiag,
676 bTitle,w_legend,boxx,boxy,m2p,m2pout);
677 if (xpmfile!=NULL)
678 xpm_mat(xpmfile,nmat,mat,mat2,bDiag,bFirstDiag);
681 void rainbow_map(char *rainbow, int nmat, t_matrix mat[])
683 t_mapping *map;
684 int m,i;
685 real c,r,g,b;
687 for(m=0; m<nmat; m++) {
688 map = mat[m].map;
689 for(i=0; i<mat[m].nmap; i++) {
690 c = (map[i].rgb.r + map[i].rgb.g + map[i].rgb.b)/3;
691 if (c > 1)
692 c = 1;
693 if (rainbow[0] == 'b')
694 c = 1 - c;
695 if (c <= 0.25) {
696 r = 0;
697 g = pow(4*c,0.666);
698 b = 1;
699 } else if (c <= 0.5) {
700 r = 0;
701 g = 1;
702 b = pow(2-4*c,0.666);
703 } else if (c <= 0.75) {
704 r = pow(4*c-2,0.666);
705 g = 1;
706 b = 0;
707 } else {
708 r = 1;
709 g = pow(4-4*c,0.666);
710 b = 0;
712 map[i].rgb.r = r;
713 map[i].rgb.g = g;
714 map[i].rgb.b = b;
719 int main(int argc,char *argv[])
721 static char *desc[] = {
722 "xpm2ps makes a beautiful color plot of an XPixelMap file.",
723 "Labels and axis can be displayed, when they are supplied",
724 "in the correct matrix format.",
725 "Matrix data may be generated by programs such as do_dssp, g_rms or",
726 "g_mdmat.[PAR]",
727 "Parameters are set in the [TT]m2p[tt] file optionally supplied with",
728 "[TT]-di[tt]. Reasonable defaults are supplied in a library file.[PAR]",
729 "With [TT]-f2[tt] a 2nd matrix file can be supplied, both matrix",
730 "files will be read simultaneously and the upper left half of the",
731 "first one ([TT]-f[tt]) is plotted together with the lower right",
732 "half of the second one ([TT]-f2[tt]). The diagonal will contain",
733 "values from the matrix file selected with [TT]-diag[tt].",
734 "Plotting of the diagonal values can be suppressed altogether by",
735 "setting [TT]-diag[tt] to [TT]none[tt].[PAR]",
736 "If the color coding and legend labels of both matrices are identical,",
737 "only one legend will be displayed, else two separate legends are",
738 "displayed.[PAR]",
739 "[TT]-title[tt] can be set to [TT]none[tt] to suppress the title, or to",
740 "[TT]ylabel[tt] to show the title in the Y-label position (alongside",
741 "the Y-axis).[PAR]",
742 "With the [TT]-rainbow[tt] option dull grey-scale matrices can be turned",
743 "into attractive color pictures.[PAR]",
744 "Merged or rainbowed matrices can be written to an XPixelMap file with",
745 "the [TT]-xpm[tt] option."
748 char *fn,*epsfile=NULL,*xpmfile=NULL;
749 char w_legend;
750 int i,nmat,nmat2;
751 t_matrix *mat=NULL,*mat2=NULL;
752 bool bTitle,bDiag,bFirstDiag;
753 static real boxx=0,boxy=0;
754 static char *title[] = { NULL, "top", "ylabel", "none", NULL };
755 static char *legend[] = { NULL, "both", "first", "second", "none", NULL };
756 static char *diag[] = { NULL, "first", "second", "none", NULL };
757 static char *rainbow[] = { NULL, "no", "blue", "red", NULL };
758 t_pargs pa[] = {
759 { "-title", FALSE, etENUM, {title}, "Show title at" },
760 { "-legend", FALSE, etENUM, {legend}, "Show legend" },
761 { "-diag", FALSE, etENUM, {diag}, "Diagonal" },
762 { "-bx", FALSE, etREAL, {&boxx},
763 "Box x-size (also y-size when -by is not set)" },
764 { "-by", FALSE, etREAL, {&boxy}, "Box y-size" },
765 { "-rainbow", FALSE, etENUM, {rainbow}, "Rainbow colors, convert white to" }
767 t_filenm fnm[] = {
768 { efXPM, "-f", NULL, ffREAD },
769 { efXPM, "-f2", "root2", ffOPTRD },
770 { efM2P, "-di", NULL, ffLIBRD },
771 { efM2P, "-do", "out", ffOPTWR },
772 { efEPS, "-o", NULL, ffOPTWR },
773 { efXPM, "-xpm",NULL, ffOPTWR }
775 #define NFILE asize(fnm)
777 CopyRight(stdout,argv[0]);
778 parse_common_args(&argc,argv,PCA_CAN_VIEW,FALSE,
779 NFILE,fnm,asize(pa),pa,
780 asize(desc),desc,0,NULL);
782 if (ftp2bSet(efEPS,NFILE,fnm))
783 epsfile=ftp2fn(efEPS,NFILE,fnm);
784 if (opt2bSet("-xpm",NFILE,fnm))
785 xpmfile=opt2fn("-xpm",NFILE,fnm);
786 if ((epsfile==NULL) && (xpmfile==NULL))
787 epsfile=ftp2fn(efEPS,NFILE,fnm);
789 bDiag = (diag[0][0] != 'n');
790 bFirstDiag = (diag[0][0] != 's');
792 fn=opt2fn("-f",NFILE,fnm);
793 nmat=read_xpm_matrix(fn,&mat);
794 fprintf(stderr,"There are %d matrices in %s\n",nmat,fn);
795 if (opt2bSet("-f2",NFILE,fnm)) {
796 fn=opt2fn("-f2",NFILE,fnm);
797 nmat2=read_xpm_matrix(fn,&mat2);
798 fprintf(stderr,"There are %d matrices in %s\n",nmat2,fn);
799 if (nmat != nmat2) {
800 fprintf(stderr,"Different number of matrices, using the smallest number.\n");
801 nmat=nmat2=min(nmat,nmat2);
804 else {
805 nmat2=0;
807 bTitle = (title[0][0] == 't');
808 if (title[0][0] == 'y') {
809 bTitle=FALSE; /* don't print title in two places at once */
810 for (i=0; (i<nmat); i++)
811 strcpy(mat[i].label_y, mat[i].title);
812 for (i=0; (i<nmat2); i++)
813 strcpy(mat2[i].label_y, mat2[i].title);
815 if (rainbow[0][0] != 'n') {
816 rainbow_map(rainbow[0],nmat,mat);
817 rainbow_map(rainbow[0],nmat2,mat2);
820 w_legend = legend[0][0];
821 if ((mat2 == NULL) && (w_legend != 'n'))
822 w_legend = 'f';
824 do_mat(nmat,mat,nmat2,mat2,bDiag,bFirstDiag,bTitle,w_legend,
825 boxx,boxy,epsfile,xpmfile,
826 opt2fn_null("-di",NFILE,fnm),opt2fn_null("-do",NFILE,fnm));
828 if (bDoView())
829 viewps(ftp2fn(efEPS,NFILE,fnm));
831 thanx(stdout);
833 return 0;