Fixes #882 - looping bug in trxio.c
[gromacs.git] / src / gmxlib / matio.c
blobf059b810214551c23e82280d50ee5c527e77aefc
1 /*
2 *
3 * This source code is part of
4 *
5 * G R O M A C S
6 *
7 * GROningen MAchine for Chemical Simulations
8 *
9 * VERSION 3.2.0
10 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12 * Copyright (c) 2001-2004, The GROMACS development team,
13 * check out http://www.gromacs.org for more information.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * If you want to redistribute modifications, please consider that
21 * scientific software is very special. Version control is crucial -
22 * bugs must be traceable. We will be happy to consider code for
23 * inclusion in the official distribution, but derived work must not
24 * be called official GROMACS. Details are found in the README & COPYING
25 * files - if they are missing, get the official version at www.gromacs.org.
27 * To help us fund GROMACS development, we humbly ask that you cite
28 * the papers on the package - you can find them in the top README file.
30 * For more info, check our website at http://www.gromacs.org
32 * And Hey:
33 * GROningen Mixture of Alchemy and Childrens' Stories
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
39 #include <stdio.h>
40 #include <ctype.h>
41 #include "sysstuff.h"
42 #include "futil.h"
43 #include "string2.h"
44 #include "macros.h"
45 #include "smalloc.h"
46 #include "gmx_fatal.h"
47 #include "matio.h"
48 #include "statutil.h"
49 #include "gmxfio.h"
50 #include "maths.h"
52 #define round(a) (int)(a+0.5)
54 static const char mapper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()-_=+{}|;:',<.>/?";
55 #define NMAP (long int)strlen(mapper)
57 #define MAX_XPM_LINELENGTH 4096
59 real **mk_matrix(int nx, int ny, gmx_bool b1D)
61 int i;
62 real **m;
64 snew(m,nx);
65 if (b1D)
66 snew(m[0], nx*ny);
68 for(i=0; (i<nx); i++)
69 if (b1D)
70 m[i] = &(m[0][i*ny]);
71 else
72 snew(m[i],ny);
74 return m;
77 void done_matrix(int nx, real ***m)
79 int i;
81 for(i=0; (i<nx); i++)
82 sfree((*m)[i]);
83 sfree(*m);
84 *m = NULL;
87 void clear_matrix(int nx, int ny, real **m)
89 int x, y;
91 for(x=0; x<nx; x++)
92 for(y=0; y<ny; y++)
93 m[x][y]=0;
96 gmx_bool matelmt_cmp(t_xpmelmt e1, t_xpmelmt e2)
98 return (e1.c1 == e2.c1) && (e1.c2 == e2.c2);
101 t_matelmt searchcmap(int n,t_mapping map[],t_xpmelmt c)
103 int i;
105 for(i=0; (i<n); i++)
106 if (matelmt_cmp(map[i].code, c))
107 return i;
109 return -1;
112 int getcmap(FILE *in,const char *fn,t_mapping **map)
114 int i,n;
115 char line[STRLEN];
116 char code[STRLEN],desc[STRLEN];
117 double r,g,b;
118 t_mapping *m;
120 if (fgets2(line,STRLEN-1,in) == NULL)
121 gmx_fatal(FARGS,"Not enough lines in colormap file %s"
122 "(just wanted to read number of entries)",fn);
123 sscanf(line,"%d",&n);
124 snew(m,n);
125 for(i=0; (i<n); i++) {
126 if (fgets2(line,STRLEN-1,in) == NULL)
127 gmx_fatal(FARGS,"Not enough lines in colormap file %s"
128 "(should be %d, found only %d)",fn,n+1,i);
129 sscanf(line,"%s%s%lf%lf%lf",code,desc,&r,&g,&b);
130 m[i].code.c1=code[0];
131 m[i].code.c2=0;
132 m[i].desc=strdup(desc);
133 m[i].rgb.r=r;
134 m[i].rgb.g=g;
135 m[i].rgb.b=b;
137 *map=m;
139 return n;
142 int readcmap(const char *fn,t_mapping **map)
144 FILE *in;
145 int n;
147 in=libopen(fn);
148 n=getcmap(in,fn,map);
149 gmx_fio_fclose(in);
151 return n;
154 void printcmap(FILE *out,int n,t_mapping map[])
156 int i;
158 fprintf(out,"%d\n",n);
159 for(i=0; (i<n); i++)
160 fprintf(out,"%c%c %20s %10g %10g %10g\n",
161 map[i].code.c1?map[i].code.c1:' ',
162 map[i].code.c2?map[i].code.c2:' ',
163 map[i].desc,map[i].rgb.r,map[i].rgb.g,map[i].rgb.b);
166 void writecmap(const char *fn,int n,t_mapping map[])
168 FILE *out;
170 out=gmx_fio_fopen(fn,"w");
171 printcmap(out,n,map);
172 gmx_fio_fclose(out);
175 void do_wmap(FILE *out,int i0,int imax,
176 int nlevels,t_rgb rlo,t_rgb rhi,real lo,real hi)
178 int i,nlo;
179 real r,g,b;
181 for(i=0; (i<imax); i++) {
182 nlo=nlevels-i;
183 r=(nlo*rlo.r+i*rhi.r)/nlevels;
184 g=(nlo*rlo.g+i*rhi.g)/nlevels;
185 b=(nlo*rlo.b+i*rhi.b)/nlevels;
186 fprintf(out,"%c %10.3g %10g %10g %10g\n",
187 mapper[i+i0],(nlo*lo+i*hi)/nlevels,r,g,b);
191 static char *fgetline(char **line,int llmax,int *llalloc,FILE *in)
193 char *fg;
195 if (llmax > *llalloc)
197 srenew(*line,llmax+1);
198 *llalloc=llmax;
200 fg=fgets(*line,llmax,in);
201 trim(*line);
203 return fg;
206 void skipstr(char *line)
208 int i,c;
210 ltrim(line);
211 c=0;
212 while((line[c] != ' ') && (line[c] != '\0'))
213 c++;
214 i=c;
215 while(line[c] != '\0')
217 line[c-i] = line[c];
218 c++;
220 line[c-i] = '\0';
223 char *line2string(char **line)
225 int i;
227 if (*line != NULL) {
228 while (((*line)[0] != '\"' ) && ( (*line)[0] != '\0' ))
229 (*line)++;
231 if ((*line)[0] != '\"')
232 return NULL;
233 (*line)++;
235 i=0;
236 while (( (*line)[i] != '\"' ) && ( (*line)[i] != '\0' ))
237 i++;
239 if ((*line)[i] != '\"')
240 *line=NULL;
241 else
242 (*line)[i] = 0;
245 return *line;
248 void parsestring(char *line,const char *label, char *string)
250 if (strstr(line,label)) {
251 if (strstr(line,label) < strchr(line,'\"')) {
252 line2string(&line);
253 strcpy(string,line);
258 void read_xpm_entry(FILE *in,t_matrix *mm)
260 t_mapping *map;
261 char *line_buf=NULL,*line=NULL,*str,buf[256];
262 int i,m,col_len,nch,n_axis_x,n_axis_y,llmax;
263 int llalloc=0;
264 unsigned int r,g,b;
265 double u;
266 gmx_bool bGetOnWithIt,bSetLine;
267 t_xpmelmt c;
269 mm->flags=0;
270 mm->title[0]=0;
271 mm->legend[0]=0;
272 mm->label_x[0]=0;
273 mm->label_y[0]=0;
274 mm->matrix=NULL;
275 mm->axis_x=NULL;
276 mm->axis_y=NULL;
277 mm->bDiscrete=FALSE;
279 llmax = STRLEN;
281 while ((NULL != fgetline(&line_buf,llmax,&llalloc,in)) &&
282 (strncmp(line_buf,"static",6) != 0)) {
283 line = line_buf;
284 parsestring(line,"title",(mm->title));
285 parsestring(line,"legend",(mm->legend));
286 parsestring(line,"x-label",(mm->label_x));
287 parsestring(line,"y-label",(mm->label_y));
288 parsestring(line,"type",buf);
290 if (buf[0] && (gmx_strcasecmp(buf,"Discrete")==0))
291 mm->bDiscrete=TRUE;
293 if (debug)
294 fprintf(debug,"%s %s %s %s\n",
295 mm->title,mm->legend,mm->label_x,mm->label_y);
297 if (strncmp(line,"static",6) != 0)
298 gmx_input("Invalid XPixMap");
299 /* Read sizes */
300 bGetOnWithIt=FALSE;
301 while (!bGetOnWithIt && (NULL != fgetline(&line_buf,llmax,&llalloc,in))) {
302 line = line_buf;
303 while (( line[0] != '\"' ) && ( line[0] != '\0' ))
304 line++;
306 if ( line[0] == '\"' ) {
307 line2string(&line);
308 sscanf(line,"%d %d %d %d",&(mm->nx),&(mm->ny),&(mm->nmap),&nch);
309 if (nch > 2)
310 gmx_fatal(FARGS,"Sorry can only read xpm's with at most 2 caracters per pixel\n");
311 llmax = max(STRLEN,mm->nx+10);
312 bGetOnWithIt=TRUE;
315 if (debug)
316 fprintf(debug,"mm->nx %d mm->ny %d mm->nmap %d nch %d\n",
317 mm->nx,mm->ny,mm->nmap,nch);
319 /* Read color map */
320 snew(map,mm->nmap);
321 m=0;
322 while ((m < mm->nmap) && (NULL != fgetline(&line_buf,llmax,&llalloc,in))) {
323 line = strchr(line_buf,'\"');
324 if (line) {
325 line++;
326 /* Read xpm color map entry */
327 map[m].code.c1 = line[0];
328 if (nch==1)
329 map[m].code.c2 = 0;
330 else
331 map[m].code.c2 = line[1];
332 line += nch;
333 str = strchr(line,'#');
334 if (str) {
335 str++;
336 col_len = 0;
337 while (isxdigit(str[col_len]))
338 col_len++;
339 if (col_len==6) {
340 sscanf(line,"%*s #%2x%2x%2x",&r,&g,&b);
341 map[m].rgb.r=r/255.0;
342 map[m].rgb.g=g/255.0;
343 map[m].rgb.b=b/255.0;
344 } else if (col_len==12) {
345 sscanf(line,"%*s #%4x%4x%4x",&r,&g,&b);
346 map[m].rgb.r=r/65535.0;
347 map[m].rgb.g=g/65535.0;
348 map[m].rgb.b=b/65535.0;
349 } else
350 gmx_file("Unsupported or invalid colormap in X PixMap");
351 } else {
352 str = strchr(line,'c');
353 if (str)
354 str += 2;
355 else
356 gmx_file("Unsupported or invalid colormap in X PixMap");
357 fprintf(stderr,"Using white for color \"%s",str);
358 map[m].rgb.r = 1;
359 map[m].rgb.g = 1;
360 map[m].rgb.b = 1;
362 line=strchr(line,'\"');
363 line++;
364 line2string(&line);
365 map[m].desc = strdup(line);
366 m++;
369 if ( m != mm->nmap )
370 gmx_fatal(FARGS,"Number of read colors map entries (%d) does not match the number in the header (%d)",m,mm->nmap);
371 mm->map = map;
373 /* Read axes, if there are any */
374 n_axis_x=0;
375 n_axis_y=0;
376 bGetOnWithIt=FALSE;
377 bSetLine=FALSE;
378 do {
379 if (bSetLine)
380 line = line_buf;
381 bSetLine = TRUE;
382 if (strstr(line,"x-axis")) {
383 line=strstr(line,"x-axis");
384 skipstr(line);
385 if (mm->axis_x==NULL)
386 snew(mm->axis_x,mm->nx + 1);
387 while (sscanf(line,"%lf",&u)==1) {
388 if (n_axis_x > mm->nx) {
389 gmx_fatal(FARGS,"Too many x-axis labels in xpm (max %d)",mm->nx);
390 } else if (n_axis_x == mm->nx) {
391 mm->flags |= MAT_SPATIAL_X;
393 mm->axis_x[n_axis_x] = u;
394 n_axis_x++;
395 skipstr(line);
398 else if (strstr(line,"y-axis")) {
399 line=strstr(line,"y-axis");
400 skipstr(line);
401 if (mm->axis_y==NULL)
402 snew(mm->axis_y,mm->ny + 1);
403 while (sscanf(line,"%lf",&u)==1) {
404 if (n_axis_y > mm->ny) {
405 gmx_file("Too many y-axis labels in xpm");
406 } else if (n_axis_y == mm->ny) {
407 mm->flags |= MAT_SPATIAL_Y;
409 mm->axis_y[n_axis_y] = u;
410 n_axis_y++;
411 skipstr(line);
414 } while ((line[0] != '\"') && (NULL != fgetline(&line_buf,llmax,&llalloc,in)));
416 /* Read matrix */
417 snew(mm->matrix,mm->nx);
418 for(i=0; i<mm->nx; i++)
419 snew(mm->matrix[i],mm->ny);
420 m=mm->ny-1;
421 bSetLine = FALSE;
422 do {
423 if (bSetLine)
424 line = line_buf;
425 bSetLine = TRUE;
426 if(m%(1+mm->ny/100)==0)
427 fprintf(stderr,"%3d%%\b\b\b\b",(100*(mm->ny-m))/mm->ny);
428 while ((line[0] != '\"') && (line[0] != '\0'))
429 line++;
430 if (line[0] != '\"')
431 gmx_fatal(FARGS,"Not enough caracters in row %d of the matrix\n",m+1);
432 else {
433 line++;
434 for(i=0; i<mm->nx; i++) {
435 c.c1=line[nch*i];
436 if (nch==1)
437 c.c2=0;
438 else
439 c.c2=line[nch*i+1];
440 mm->matrix[i][m]=searchcmap(mm->nmap,mm->map,c);
442 m--;
444 } while ((m>=0) && (NULL != fgetline(&line_buf,llmax,&llalloc,in)));
445 if (m>=0)
446 gmx_incons("Not enough rows in the matrix");
448 sfree(line_buf);
451 int read_xpm_matrix(const char *fnm,t_matrix **matrix)
453 FILE *in;
454 char *line=NULL;
455 int nmat;
456 int llalloc=0;
458 in=gmx_fio_fopen(fnm,"r");
460 nmat=0;
461 while (NULL != fgetline(&line,STRLEN,&llalloc,in)) {
462 if (strstr(line,"/* XPM */")) {
463 srenew(*matrix,nmat+1);
464 read_xpm_entry(in,&(*matrix)[nmat]);
465 nmat++;
468 gmx_fio_fclose(in);
470 if (nmat==0)
471 gmx_file("Invalid XPixMap");
473 sfree(line);
475 return nmat;
478 real **matrix2real(t_matrix *matrix,real **mat)
480 t_mapping *map;
481 double tmp;
482 real *rmap;
483 int i,j,nmap;
485 nmap=matrix->nmap;
486 map=matrix->map;
487 snew(rmap,nmap);
489 for(i=0; i<nmap; i++) {
490 if ((map[i].desc==NULL) || (sscanf(map[i].desc,"%lf",&tmp)!=1)) {
491 fprintf(stderr,"Could not convert matrix to reals,\n"
492 "color map entry %d has a non-real description: \"%s\"\n",
493 i,map[i].desc);
494 sfree(rmap);
495 return NULL;
497 rmap[i]=tmp;
500 if (mat==NULL) {
501 snew(mat,matrix->nx);
502 for(i=0; i<matrix->nx; i++)
503 snew(mat[i],matrix->ny);
505 for(i=0; i<matrix->nx; i++)
506 for(j=0; j<matrix->ny; j++)
507 mat[i][j]=rmap[matrix->matrix[i][j]];
509 sfree(rmap);
511 fprintf(stderr,"Converted a %dx%d matrix with %d levels to reals\n",
512 matrix->nx,matrix->ny,nmap);
514 return mat;
517 void write_xpm_header(FILE *out,
518 const char *title,const char *legend,
519 const char *label_x,const char *label_y,
520 gmx_bool bDiscrete)
522 fprintf(out, "/* XPM */\n");
523 fprintf(out, "/* Generated by %s */\n",Program());
524 fprintf(out, "/* This file can be converted to EPS by the GROMACS program xpm2ps */\n");
525 fprintf(out, "/* title: \"%s\" */\n",title);
526 fprintf(out, "/* legend: \"%s\" */\n",legend);
527 fprintf(out, "/* x-label: \"%s\" */\n",label_x);
528 fprintf(out, "/* y-label: \"%s\" */\n",label_y);
529 if (bDiscrete)
530 fprintf(out,"/* type: \"Discrete\" */\n");
531 else
532 fprintf(out,"/* type: \"Continuous\" */\n");
535 static int calc_nmid(int nlevels,real lo,real mid,real hi)
537 /* Take care that we have at least 1 entry in the mid to hi range
539 return min(max(0,((mid-lo)/(hi-lo))*(nlevels-1)),nlevels-1);
542 void write_xpm_map3(FILE *out,int n_x,int n_y,int *nlevels,
543 real lo,real mid,real hi,
544 t_rgb rlo,t_rgb rmid,t_rgb rhi)
546 int i,nmid;
547 real r,g,b,clev_lo,clev_hi;
549 if (*nlevels > NMAP*NMAP) {
550 fprintf(stderr,"Warning, too many levels (%d) in matrix, using %d only\n",
551 *nlevels,(int)(NMAP*NMAP));
552 *nlevels=NMAP*NMAP;
554 else if (*nlevels < 2) {
555 fprintf(stderr,"Warning, too few levels (%d) in matrix, using 2 instead\n",
556 *nlevels);
557 *nlevels=2;
559 if (!((mid >= lo) && (mid < hi)))
560 gmx_fatal(FARGS,"Lo: %f, Mid: %f, Hi: %f\n",lo,mid,hi);
562 fprintf(out,"static char *gromacs_xpm[] = {\n");
563 fprintf(out,"\"%d %d %d %d\",\n",
564 n_x,n_y,*nlevels,(*nlevels <= NMAP) ? 1 : 2);
566 nmid = calc_nmid(*nlevels,lo,mid,hi);
567 clev_lo = nmid;
568 clev_hi = (*nlevels - 1 - nmid);
569 for(i=0; (i<nmid); i++) {
570 r = rlo.r+(i*(rmid.r-rlo.r)/clev_lo);
571 g = rlo.g+(i*(rmid.g-rlo.g)/clev_lo);
572 b = rlo.b+(i*(rmid.b-rlo.b)/clev_lo);
573 fprintf(out,"\"%c%c c #%02X%02X%02X \" /* \"%.3g\" */,\n",
574 mapper[i % NMAP],
575 (*nlevels <= NMAP) ? ' ' : mapper[i/NMAP],
576 (unsigned int)round(255*r),
577 (unsigned int)round(255*g),
578 (unsigned int)round(255*b),
579 ((nmid - i)*lo + i*mid)/clev_lo);
581 for(i=0; (i<(*nlevels-nmid)); i++) {
582 r = rmid.r+(i*(rhi.r-rmid.r)/clev_hi);
583 g = rmid.g+(i*(rhi.g-rmid.g)/clev_hi);
584 b = rmid.b+(i*(rhi.b-rmid.b)/clev_hi);
585 fprintf(out,"\"%c%c c #%02X%02X%02X \" /* \"%.3g\" */,\n",
586 mapper[(i+nmid) % NMAP],
587 (*nlevels <= NMAP) ? ' ' : mapper[(i+nmid)/NMAP],
588 (unsigned int)round(255*r),
589 (unsigned int)round(255*g),
590 (unsigned int)round(255*b),
591 ((*nlevels - 1 - nmid - i)*mid + i*hi)/clev_hi);
595 static void pr_simple_cmap(FILE *out,real lo,real hi,int nlevel,t_rgb rlo,
596 t_rgb rhi,int i0)
598 int i;
599 real r,g,b,fac;
601 for(i=0; (i<nlevel); i++) {
602 fac = (i+1.0)/(nlevel);
603 r = rlo.r+fac*(rhi.r-rlo.r);
604 g = rlo.g+fac*(rhi.g-rlo.g);
605 b = rlo.b+fac*(rhi.b-rlo.b);
606 fprintf(out,"\"%c%c c #%02X%02X%02X \" /* \"%.3g\" */,\n",
607 mapper[(i+i0) % NMAP],
608 (nlevel <= NMAP) ? ' ' : mapper[(i+i0)/NMAP],
609 (unsigned int)round(255*r),
610 (unsigned int)round(255*g),
611 (unsigned int)round(255*b),
612 lo+fac*(hi-lo));
616 static void pr_discrete_cmap(FILE *out,int *nlevel,int i0)
618 t_rgb rgbd[16] = {
619 { 1.0, 1.0, 1.0 }, /* white */
620 { 1.0, 0.0, 0.0 }, /* red */
621 { 1.0, 1.0, 0.0 }, /* yellow */
622 { 0.0, 0.0, 1.0 }, /* blue */
623 { 0.0, 1.0, 0.0 }, /* green */
624 { 1.0, 0.0, 1.0 }, /* purple */
625 { 1.0, 0.4, 0.0 }, /* orange */
626 { 0.0, 1.0, 1.0 }, /* cyan */
627 { 1.0, 0.4, 0.4 }, /* pink */
628 { 1.0, 1.0, 0.0 }, /* yellow */
629 { 0.4, 0.4, 1.0 }, /* lightblue */
630 { 0.4, 1.0, 0.4 }, /* lightgreen */
631 { 1.0, 0.4, 1.0 }, /* lightpurple */
632 { 1.0, 0.7, 0.4 }, /* lightorange */
633 { 0.4, 1.0, 1.0 }, /* lightcyan */
634 { 0.0, 0.0, 0.0 } /* black */
637 int i,n;
639 *nlevel = min(16,*nlevel);
640 n = *nlevel;
641 for(i=0; (i<n); i++) {
642 fprintf(out,"\"%c%c c #%02X%02X%02X \" /* \"%3d\" */,\n",
643 mapper[(i+i0) % NMAP],
644 (n <= NMAP) ? ' ' : mapper[(i+i0)/NMAP],
645 (unsigned int)round(255*rgbd[i].r),
646 (unsigned int)round(255*rgbd[i].g),
647 (unsigned int)round(255*rgbd[i].b),
654 void write_xpm_map_split(FILE *out,int n_x,int n_y,
655 int *nlevel_top,real lo_top,real hi_top,
656 t_rgb rlo_top,t_rgb rhi_top,
657 gmx_bool bDiscreteColor,
658 int *nlevel_bot,real lo_bot,real hi_bot,
659 t_rgb rlo_bot,t_rgb rhi_bot)
661 int i,ntot;
662 real r,g,b,fac;
664 ntot = *nlevel_top + *nlevel_bot;
665 if (ntot > NMAP)
666 gmx_fatal(FARGS,"Warning, too many levels (%d) in matrix",ntot);
668 fprintf(out,"static char *gromacs_xpm[] = {\n");
669 fprintf(out,"\"%d %d %d %d\",\n",n_x,n_y,ntot,1);
671 if (bDiscreteColor)
672 pr_discrete_cmap(out,nlevel_bot,0);
673 else
674 pr_simple_cmap(out,lo_bot,hi_bot,*nlevel_bot,rlo_bot,rhi_bot,0);
676 pr_simple_cmap(out,lo_top,hi_top,*nlevel_top,rlo_top,rhi_top,*nlevel_bot);
680 void write_xpm_map(FILE *out,int n_x, int n_y,int *nlevels,real lo,real hi,
681 t_rgb rlo,t_rgb rhi)
683 int i,nlo;
684 real invlevel,r,g,b;
686 if (*nlevels > NMAP*NMAP) {
687 fprintf(stderr,"Warning, too many levels (%d) in matrix, using %d only\n",
688 *nlevels,(int)(NMAP*NMAP));
689 *nlevels=NMAP*NMAP;
691 else if (*nlevels < 2) {
692 fprintf(stderr,"Warning, too few levels (%d) in matrix, using 2 instead\n",*nlevels);
693 *nlevels=2;
696 fprintf(out,"static char *gromacs_xpm[] = {\n");
697 fprintf(out,"\"%d %d %d %d\",\n",
698 n_x,n_y,*nlevels,(*nlevels <= NMAP) ? 1 : 2);
700 invlevel=1.0/(*nlevels-1);
701 for(i=0; (i<*nlevels); i++) {
702 nlo=*nlevels-1-i;
703 r=(nlo*rlo.r+i*rhi.r)*invlevel;
704 g=(nlo*rlo.g+i*rhi.g)*invlevel;
705 b=(nlo*rlo.b+i*rhi.b)*invlevel;
706 fprintf(out,"\"%c%c c #%02X%02X%02X \" /* \"%.3g\" */,\n",
707 mapper[i % NMAP],(*nlevels <= NMAP) ? ' ' : mapper[i/NMAP],
708 (unsigned int)round(255*r),
709 (unsigned int)round(255*g),
710 (unsigned int)round(255*b),
711 (nlo*lo+i*hi)*invlevel);
715 void write_xpm_axis(FILE *out, const char *axis, gmx_bool bSpatial, int n,
716 real *label)
718 int i;
720 if (label) {
721 for(i=0;i<(bSpatial ? n+1 : n);i++) {
722 if (i % 80 == 0) {
723 if (i)
724 fprintf(out,"*/\n");
725 fprintf(out,"/* %s-axis: ",axis);
727 fprintf(out,"%g ",label[i]);
729 fprintf(out,"*/\n");
733 void write_xpm_data(FILE *out, int n_x, int n_y, real **matrix,
734 real lo, real hi, int nlevels)
736 int i,j,c;
737 real invlevel;
739 invlevel=(nlevels-1)/(hi-lo);
740 for(j=n_y-1; (j>=0); j--) {
741 if(j%(1+n_y/100)==0)
742 fprintf(stderr,"%3d%%\b\b\b\b",(100*(n_y-j))/n_y);
743 fprintf(out,"\"");
744 for(i=0; (i<n_x); i++) {
745 c=gmx_nint((matrix[i][j]-lo)*invlevel);
746 if (c<0) c=0;
747 if (c>=nlevels) c=nlevels-1;
748 if (nlevels <= NMAP)
749 fprintf(out,"%c",mapper[c]);
750 else
751 fprintf(out,"%c%c",mapper[c % NMAP],mapper[c / NMAP]);
753 if (j > 0)
754 fprintf(out,"\",\n");
755 else
756 fprintf(out,"\"\n");
760 void write_xpm_data3(FILE *out,int n_x,int n_y,real **matrix,
761 real lo,real mid,real hi,int nlevels)
763 int i,j,c=0,nmid;
764 real invlev_lo,invlev_hi;
766 nmid = calc_nmid(nlevels,lo,mid,hi);
767 invlev_hi=(nlevels-1-nmid)/(hi-mid);
768 invlev_lo=(nmid)/(mid-lo);
770 for(j=n_y-1; (j>=0); j--) {
771 if(j%(1+n_y/100)==0)
772 fprintf(stderr,"%3d%%\b\b\b\b",(100*(n_y-j))/n_y);
773 fprintf(out,"\"");
774 for(i=0; (i<n_x); i++) {
775 if (matrix[i][j] >= mid)
776 c=nmid+gmx_nint((matrix[i][j]-mid)*invlev_hi);
777 else if (matrix[i][j] >= lo)
778 c=gmx_nint((matrix[i][j]-lo)*invlev_lo);
779 else
780 c = 0;
782 if (c<0)
783 c=0;
784 if (c>=nlevels)
785 c=nlevels-1;
786 if (nlevels <= NMAP)
787 fprintf(out,"%c",mapper[c]);
788 else
789 fprintf(out,"%c%c",mapper[c % NMAP],mapper[c / NMAP]);
791 if (j > 0)
792 fprintf(out,"\",\n");
793 else
794 fprintf(out,"\"\n");
798 void write_xpm_data_split(FILE *out,int n_x,int n_y,real **matrix,
799 real lo_top,real hi_top,int nlevel_top,
800 real lo_bot,real hi_bot,int nlevel_bot)
802 int i,j,c;
803 real invlev_top,invlev_bot;
805 invlev_top=(nlevel_top-1)/(hi_top-lo_top);
806 invlev_bot=(nlevel_bot-1)/(hi_bot-lo_bot);
808 for(j=n_y-1; (j>=0); j--) {
809 if(j % (1+n_y/100)==0)
810 fprintf(stderr,"%3d%%\b\b\b\b",(100*(n_y-j))/n_y);
811 fprintf(out,"\"");
812 for(i=0; (i<n_x); i++) {
813 if (i < j) {
814 c = nlevel_bot+round((matrix[i][j]-lo_top)*invlev_top);
815 if ((c < nlevel_bot) || (c >= nlevel_bot+nlevel_top))
816 gmx_fatal(FARGS,"Range checking i = %d, j = %d, c = %d, bot = %d, top = %d matrix[i,j] = %f",i,j,c,nlevel_bot,nlevel_top,matrix[i][j]);
818 else if (i > j) {
819 c = round((matrix[i][j]-lo_bot)*invlev_bot);
820 if ((c < 0) || (c >= nlevel_bot+nlevel_bot))
821 gmx_fatal(FARGS,"Range checking i = %d, j = %d, c = %d, bot = %d, top = %d matrix[i,j] = %f",i,j,c,nlevel_bot,nlevel_top,matrix[i][j]);
823 else
824 c = nlevel_bot;
826 fprintf(out,"%c",mapper[c]);
828 if (j > 0)
829 fprintf(out,"\",\n");
830 else
831 fprintf(out,"\"\n");
835 void write_xpm_m(FILE *out, t_matrix m)
837 /* Writes a t_matrix struct to .xpm file */
839 int i,j;
840 gmx_bool bOneChar;
841 t_xpmelmt c;
843 bOneChar=(m.map[0].code.c2 == 0);
844 write_xpm_header(out,m.title,m.legend,m.label_x,m.label_y,
845 m.bDiscrete);
846 fprintf(out,"static char *gromacs_xpm[] = {\n");
847 fprintf(out,"\"%d %d %d %d\",\n",m.nx,m.ny,m.nmap,bOneChar ? 1 : 2);
848 for(i=0; (i<m.nmap); i++)
849 fprintf(out,"\"%c%c c #%02X%02X%02X \" /* \"%s\" */,\n",
850 m.map[i].code.c1,
851 bOneChar ? ' ' : m.map[i].code.c2,
852 (unsigned int)round(m.map[i].rgb.r*255),
853 (unsigned int)round(m.map[i].rgb.g*255),
854 (unsigned int)round(m.map[i].rgb.b*255),m.map[i].desc);
855 write_xpm_axis(out,"x",m.flags & MAT_SPATIAL_X,m.nx,m.axis_x);
856 write_xpm_axis(out,"y",m.flags & MAT_SPATIAL_Y,m.ny,m.axis_y);
857 for(j=m.ny-1; (j>=0); j--) {
858 if(j%(1+m.ny/100)==0)
859 fprintf(stderr,"%3d%%\b\b\b\b",(100*(m.ny-j))/m.ny);
860 fprintf(out,"\"");
861 if (bOneChar)
862 for(i=0; (i<m.nx); i++)
863 fprintf(out,"%c",m.map[m.matrix[i][j]].code.c1);
864 else
865 for(i=0; (i<m.nx); i++) {
866 c=m.map[m.matrix[i][j]].code;
867 fprintf(out,"%c%c",c.c1,c.c2);
869 if (j > 0)
870 fprintf(out,"\",\n");
871 else
872 fprintf(out,"\"\n");
876 void write_xpm3(FILE *out,unsigned int flags,
877 const char *title,const char *legend,
878 const char *label_x,const char *label_y,
879 int n_x,int n_y,real axis_x[],real axis_y[],
880 real *matrix[],real lo,real mid,real hi,
881 t_rgb rlo,t_rgb rmid,t_rgb rhi,int *nlevels)
883 /* See write_xpm.
884 * Writes a colormap varying as rlo -> rmid -> rhi.
887 if (hi <= lo)
888 gmx_fatal(FARGS,"hi (%g) <= lo (%g)",hi,lo);
890 write_xpm_header(out,title,legend,label_x,label_y,FALSE);
891 write_xpm_map3(out,n_x,n_y,nlevels,lo,mid,hi,rlo,rmid,rhi);
892 write_xpm_axis(out,"x",flags & MAT_SPATIAL_X,n_x,axis_x);
893 write_xpm_axis(out,"y",flags & MAT_SPATIAL_Y,n_y,axis_y);
894 write_xpm_data3(out,n_x,n_y,matrix,lo,mid,hi,*nlevels);
897 void write_xpm_split(FILE *out,unsigned int flags,
898 const char *title,const char *legend,
899 const char *label_x,const char *label_y,
900 int n_x,int n_y,real axis_x[],real axis_y[],
901 real *matrix[],
902 real lo_top,real hi_top,int *nlevel_top,
903 t_rgb rlo_top,t_rgb rhi_top,
904 real lo_bot,real hi_bot,int *nlevel_bot,
905 gmx_bool bDiscreteColor,
906 t_rgb rlo_bot,t_rgb rhi_bot)
908 /* See write_xpm.
909 * Writes a colormap varying as rlo -> rmid -> rhi.
912 if (hi_top <= lo_top)
913 gmx_fatal(FARGS,"hi_top (%g) <= lo_top (%g)",hi_top,lo_top);
914 if (hi_bot <= lo_bot)
915 gmx_fatal(FARGS,"hi_bot (%g) <= lo_bot (%g)",hi_bot,lo_bot);
916 if (bDiscreteColor && (*nlevel_bot >= 16))
917 gmx_impl("Can not plot more than 16 discrete colors");
919 write_xpm_header(out,title,legend,label_x,label_y,FALSE);
920 write_xpm_map_split(out,n_x,n_y,nlevel_top,lo_top,hi_top,rlo_top,rhi_top,
921 bDiscreteColor,nlevel_bot,lo_bot,hi_bot,rlo_bot,rhi_bot);
922 write_xpm_axis(out,"x",flags & MAT_SPATIAL_X,n_x,axis_x);
923 write_xpm_axis(out,"y",flags & MAT_SPATIAL_Y,n_y,axis_y);
924 write_xpm_data_split(out,n_x,n_y,matrix,lo_top,hi_top,*nlevel_top,
925 lo_bot,hi_bot,*nlevel_bot);
928 void write_xpm(FILE *out,unsigned int flags,
929 const char *title,const char *legend,
930 const char *label_x,const char *label_y,
931 int n_x,int n_y,real axis_x[],real axis_y[],
932 real *matrix[],real lo,real hi,
933 t_rgb rlo,t_rgb rhi,int *nlevels)
935 /* out xpm file
936 * title matrix title
937 * legend label for the continuous legend
938 * label_x label for the x-axis
939 * label_y label for the y-axis
940 * n_x, n_y size of the matrix
941 * axis_x[] the x-ticklabels
942 * axis_y[] the y-ticklables
943 * *matrix[] element x,y is matrix[x][y]
944 * lo output lower than lo is set to lo
945 * hi output higher than hi is set to hi
946 * rlo rgb value for level lo
947 * rhi rgb value for level hi
948 * nlevels number of color levels for the output
951 if (hi <= lo)
952 gmx_fatal(FARGS,"hi (%f) <= lo (%f)",hi,lo);
954 write_xpm_header(out,title,legend,label_x,label_y,FALSE);
955 write_xpm_map(out,n_x,n_y,nlevels,lo,hi,rlo,rhi);
956 write_xpm_axis(out,"x",flags & MAT_SPATIAL_X,n_x,axis_x);
957 write_xpm_axis(out,"y",flags & MAT_SPATIAL_Y,n_y,axis_y);
958 write_xpm_data(out,n_x,n_y,matrix,lo,hi,*nlevels);