A freeze group can now be allowed to move rigidly in some dimension by using "freezed...
[gromacs/rigid-bodies.git] / src / tools / gmx_sas.c
blob4cd049de80bcd677b4ed3d1c970d92d38a9ff01d
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.3.2
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-2007, 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 Machine for Chemical Simulation
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38 #include <math.h>
39 #include <stdlib.h>
41 #include "sysstuff.h"
42 #include "string.h"
43 #include "typedefs.h"
44 #include "smalloc.h"
45 #include "macros.h"
46 #include "vec.h"
47 #include "xvgr.h"
48 #include "pbc.h"
49 #include "copyrite.h"
50 #include "futil.h"
51 #include "statutil.h"
52 #include "index.h"
53 #include "nsc.h"
54 #include "pdbio.h"
55 #include "confio.h"
56 #include "rmpbc.h"
57 #include "names.h"
58 #include "atomprop.h"
59 #include "physics.h"
60 #include "tpxio.h"
61 #include "gmx_ana.h"
64 typedef struct {
65 atom_id aa,ab;
66 real d2a,d2b;
67 } t_conect;
69 void add_rec(t_conect c[],atom_id i,atom_id j,real d2)
71 if (c[i].aa == NO_ATID) {
72 c[i].aa = j;
73 c[i].d2a = d2;
75 else if (c[i].ab == NO_ATID) {
76 c[i].ab = j;
77 c[i].d2b = d2;
79 else if (d2 < c[i].d2a) {
80 c[i].aa = j;
81 c[i].d2a = d2;
83 else if (d2 < c[i].d2b) {
84 c[i].ab = j;
85 c[i].d2b = d2;
87 /* Swap them if necessary: a must be larger than b */
88 if (c[i].d2a < c[i].d2b) {
89 j = c[i].ab;
90 c[i].ab = c[i].aa;
91 c[i].aa = j;
92 d2 = c[i].d2b;
93 c[i].d2b = c[i].d2a;
94 c[i].d2a = d2;
98 void do_conect(const char *fn,int n,rvec x[])
100 FILE *fp;
101 int i,j;
102 t_conect *c;
103 rvec dx;
104 real d2;
106 fprintf(stderr,"Building CONECT records\n");
107 snew(c,n);
108 for(i=0; (i<n); i++)
109 c[i].aa = c[i].ab = NO_ATID;
111 for(i=0; (i<n); i++) {
112 for(j=i+1; (j<n); j++) {
113 rvec_sub(x[i],x[j],dx);
114 d2 = iprod(dx,dx);
115 add_rec(c,i,j,d2);
116 add_rec(c,j,i,d2);
119 fp = ffopen(fn,"a");
120 for(i=0; (i<n); i++) {
121 if ((c[i].aa == NO_ATID) || (c[i].ab == NO_ATID))
122 fprintf(stderr,"Warning dot %d has no conections\n",i+1);
123 fprintf(fp,"CONECT%5d%5d%5d\n",i+1,c[i].aa+1,c[i].ab+1);
125 ffclose(fp);
126 sfree(c);
129 void connelly_plot(const char *fn,int ndots,real dots[],rvec x[],t_atoms *atoms,
130 t_symtab *symtab,int ePBC,matrix box,gmx_bool bSave)
132 static const char *atomnm="DOT";
133 static const char *resnm ="DOT";
134 static const char *title ="Connely Dot Surface Generated by g_sas";
136 int i,i0,r0,ii0,k;
137 rvec *xnew;
138 t_atoms aaa;
140 if (bSave) {
141 i0 = atoms->nr;
142 r0 = atoms->nres;
143 srenew(atoms->atom,atoms->nr+ndots);
144 srenew(atoms->atomname,atoms->nr+ndots);
145 srenew(atoms->resinfo,r0+1);
146 atoms->atom[i0].resind = r0;
147 t_atoms_set_resinfo(atoms,i0,symtab,resnm,r0+1,' ',0,' ');
148 srenew(atoms->pdbinfo,atoms->nr+ndots);
149 snew(xnew,atoms->nr+ndots);
150 for(i=0; (i<atoms->nr); i++)
151 copy_rvec(x[i],xnew[i]);
152 for(i=k=0; (i<ndots); i++) {
153 ii0 = i0+i;
154 atoms->atomname[ii0] = put_symtab(symtab,atomnm);
155 atoms->pdbinfo[ii0].type = epdbATOM;
156 atoms->pdbinfo[ii0].atomnr= ii0;
157 atoms->atom[ii0].resind = r0;
158 xnew[ii0][XX] = dots[k++];
159 xnew[ii0][YY] = dots[k++];
160 xnew[ii0][ZZ] = dots[k++];
161 atoms->pdbinfo[ii0].bfac = 0.0;
162 atoms->pdbinfo[ii0].occup = 0.0;
164 atoms->nr = i0+ndots;
165 atoms->nres = r0+1;
166 write_sto_conf(fn,title,atoms,xnew,NULL,ePBC,box);
167 atoms->nres = r0;
168 atoms->nr = i0;
170 else {
171 init_t_atoms(&aaa,ndots,TRUE);
172 aaa.atom[0].resind = 0;
173 t_atoms_set_resinfo(&aaa,0,symtab,resnm,1,' ',0,' ');
174 snew(xnew,ndots);
175 for(i=k=0; (i<ndots); i++) {
176 ii0 = i;
177 aaa.atomname[ii0] = put_symtab(symtab,atomnm);
178 aaa.pdbinfo[ii0].type = epdbATOM;
179 aaa.pdbinfo[ii0].atomnr= ii0;
180 aaa.atom[ii0].resind = 0;
181 xnew[ii0][XX] = dots[k++];
182 xnew[ii0][YY] = dots[k++];
183 xnew[ii0][ZZ] = dots[k++];
184 aaa.pdbinfo[ii0].bfac = 0.0;
185 aaa.pdbinfo[ii0].occup = 0.0;
187 aaa.nr = ndots;
188 write_sto_conf(fn,title,&aaa,xnew,NULL,ePBC,box);
189 do_conect(fn,ndots,xnew);
190 free_t_atoms(&aaa,FALSE);
192 sfree(xnew);
195 real calc_radius(char *atom)
197 real r;
199 switch (atom[0]) {
200 case 'C':
201 r = 0.16;
202 break;
203 case 'O':
204 r = 0.13;
205 break;
206 case 'N':
207 r = 0.14;
208 break;
209 case 'S':
210 r = 0.2;
211 break;
212 case 'H':
213 r = 0.1;
214 break;
215 default:
216 r = 1e-3;
218 return r;
221 void sas_plot(int nfile,t_filenm fnm[],real solsize,int ndots,
222 real qcut,gmx_bool bSave,real minarea,gmx_bool bPBC,
223 real dgs_default,gmx_bool bFindex, const output_env_t oenv)
225 FILE *fp,*fp2,*fp3=NULL,*vp;
226 const char *flegend[] = { "Hydrophobic", "Hydrophilic",
227 "Total", "D Gsolv" };
228 const char *vlegend[] = { "Volume (nm\\S3\\N)", "Density (g/l)" };
229 const char *or_and_oa_legend[] = { "Average (nm\\S2\\N)", "Standard deviation (nm\\S2\\N)" };
230 const char *vfile;
231 real t;
232 gmx_atomprop_t aps=NULL;
233 gmx_rmpbc_t gpbc=NULL;
234 t_trxstatus *status;
235 int ndefault;
236 int i,j,ii,nfr,natoms,flag,nsurfacedots,res;
237 rvec *xtop,*x;
238 matrix topbox,box;
239 t_topology top;
240 char title[STRLEN];
241 int ePBC;
242 gmx_bool bTop;
243 t_atoms *atoms;
244 gmx_bool *bOut,*bPhobic;
245 gmx_bool bConnelly;
246 gmx_bool bResAt,bITP,bDGsol;
247 real *radius,*dgs_factor=NULL,*area=NULL,*surfacedots=NULL;
248 real at_area,*atom_area=NULL,*atom_area2=NULL;
249 real *res_a=NULL,*res_area=NULL,*res_area2=NULL;
250 real totarea,totvolume,totmass=0,density,harea,tarea,fluc2;
251 atom_id **index,*findex;
252 int *nx,nphobic,npcheck,retval;
253 char **grpname,*fgrpname;
254 real dgsolv;
256 bITP = opt2bSet("-i",nfile,fnm);
257 bResAt = opt2bSet("-or",nfile,fnm) || opt2bSet("-oa",nfile,fnm) || bITP;
259 bTop = read_tps_conf(ftp2fn(efTPS,nfile,fnm),title,&top,&ePBC,
260 &xtop,NULL,topbox,FALSE);
261 atoms = &(top.atoms);
263 if (!bTop) {
264 fprintf(stderr,"No tpr file, will not compute Delta G of solvation\n");
265 bDGsol = FALSE;
266 } else {
267 bDGsol = strcmp(*(atoms->atomtype[0]),"?") != 0;
268 if (!bDGsol) {
269 fprintf(stderr,"Warning: your tpr file is too old, will not compute "
270 "Delta G of solvation\n");
271 } else {
272 printf("In case you use free energy of solvation predictions:\n");
273 please_cite(stdout,"Eisenberg86a");
277 aps = gmx_atomprop_init();
279 if ((natoms=read_first_x(oenv,&status,ftp2fn(efTRX,nfile,fnm),
280 &t,&x,box))==0)
281 gmx_fatal(FARGS,"Could not read coordinates from statusfile\n");
283 if ((ePBC != epbcXYZ) || (TRICLINIC(box))) {
284 fprintf(stderr,"\n\nWARNING: non-rectangular boxes may give erroneous results or crashes.\n"
285 "Analysis based on vacuum simulations (with the possibility of evaporation)\n"
286 "will certainly crash the analysis.\n\n");
288 snew(nx,2);
289 snew(index,2);
290 snew(grpname,2);
291 fprintf(stderr,"Select a group for calculation of surface and a group for output:\n");
292 get_index(atoms,ftp2fn_null(efNDX,nfile,fnm),2,nx,index,grpname);
294 if (bFindex) {
295 fprintf(stderr,"Select a group of hydrophobic atoms:\n");
296 get_index(atoms,ftp2fn_null(efNDX,nfile,fnm),1,&nphobic,&findex,&fgrpname);
298 snew(bOut,natoms);
299 for(i=0; i<nx[1]; i++)
300 bOut[index[1][i]] = TRUE;
302 /* Now compute atomic readii including solvent probe size */
303 snew(radius,natoms);
304 snew(bPhobic,nx[0]);
305 if (bResAt) {
306 snew(atom_area,nx[0]);
307 snew(atom_area2,nx[0]);
308 snew(res_a,atoms->nres);
309 snew(res_area,atoms->nres);
310 snew(res_area2,atoms->nres);
312 if (bDGsol)
313 snew(dgs_factor,nx[0]);
315 /* Get a Van der Waals radius for each atom */
316 ndefault = 0;
317 for(i=0; (i<natoms); i++) {
318 if (!gmx_atomprop_query(aps,epropVDW,
319 *(atoms->resinfo[atoms->atom[i].resind].name),
320 *(atoms->atomname[i]),&radius[i]))
321 ndefault++;
322 /* radius[i] = calc_radius(*(top->atoms.atomname[i])); */
323 radius[i] += solsize;
325 if (ndefault > 0)
326 fprintf(stderr,"WARNING: could not find a Van der Waals radius for %d atoms\n",ndefault);
327 /* Determine which atom is counted as hydrophobic */
328 if (bFindex) {
329 npcheck = 0;
330 for(i=0; (i<nx[0]); i++) {
331 ii = index[0][i];
332 for(j=0; (j<nphobic); j++) {
333 if (findex[j] == ii) {
334 bPhobic[i] = TRUE;
335 if (bOut[ii])
336 npcheck++;
340 if (npcheck != nphobic)
341 gmx_fatal(FARGS,"Consistency check failed: not all %d atoms in the hydrophobic index\n"
342 "found in the normal index selection (%d atoms)",nphobic,npcheck);
344 else
345 nphobic = 0;
347 for(i=0; (i<nx[0]); i++) {
348 ii = index[0][i];
349 if (!bFindex) {
350 bPhobic[i] = fabs(atoms->atom[ii].q) <= qcut;
351 if (bPhobic[i] && bOut[ii])
352 nphobic++;
354 if (bDGsol)
355 if (!gmx_atomprop_query(aps,epropDGsol,
356 *(atoms->resinfo[atoms->atom[ii].resind].name),
357 *(atoms->atomtype[ii]),&(dgs_factor[i])))
358 dgs_factor[i] = dgs_default;
359 if (debug)
360 fprintf(debug,"Atom %5d %5s-%5s: q= %6.3f, r= %6.3f, dgsol= %6.3f, hydrophobic= %s\n",
361 ii+1,*(atoms->resinfo[atoms->atom[ii].resind].name),
362 *(atoms->atomname[ii]),
363 atoms->atom[ii].q,radius[ii]-solsize,dgs_factor[i],
364 BOOL(bPhobic[i]));
366 fprintf(stderr,"%d out of %d atoms were classified as hydrophobic\n",
367 nphobic,nx[1]);
369 fp=xvgropen(opt2fn("-o",nfile,fnm),"Solvent Accessible Surface","Time (ps)",
370 "Area (nm\\S2\\N)",oenv);
371 xvgr_legend(fp,asize(flegend) - (bDGsol ? 0 : 1),flegend,oenv);
372 vfile = opt2fn_null("-tv",nfile,fnm);
373 if (vfile) {
374 if (!bTop) {
375 gmx_fatal(FARGS,"Need a tpr file for option -tv");
377 vp=xvgropen(vfile,"Volume and Density","Time (ps)","",oenv);
378 xvgr_legend(vp,asize(vlegend),vlegend,oenv);
379 totmass = 0;
380 ndefault = 0;
381 for(i=0; (i<nx[0]); i++) {
382 real mm;
383 ii = index[0][i];
385 if (!query_atomprop(atomprop,epropMass,
386 *(top->atoms.resname[top->atoms.atom[ii].resnr]),
387 *(top->atoms.atomname[ii]),&mm))
388 ndefault++;
389 totmass += mm;
391 totmass += atoms->atom[ii].m;
393 if (ndefault)
394 fprintf(stderr,"WARNING: Using %d default masses for density calculation, which most likely are inaccurate\n",ndefault);
396 else
397 vp = NULL;
399 gmx_atomprop_destroy(aps);
401 if (bPBC)
402 gpbc = gmx_rmpbc_init(&top.idef,ePBC,natoms,box);
404 nfr=0;
405 do {
406 if (bPBC)
407 gmx_rmpbc(gpbc,natoms,box,x);
409 bConnelly = (nfr==0 && opt2bSet("-q",nfile,fnm));
410 if (bConnelly) {
411 if (!bTop)
412 gmx_fatal(FARGS,"Need a tpr file for Connelly plot");
413 flag = FLAG_ATOM_AREA | FLAG_DOTS;
414 } else {
415 flag = FLAG_ATOM_AREA;
417 if (vp) {
418 flag = flag | FLAG_VOLUME;
421 if (debug)
422 write_sto_conf("check.pdb","pbc check",atoms,x,NULL,ePBC,box);
424 retval = nsc_dclm_pbc(x,radius,nx[0],ndots,flag,&totarea,
425 &area,&totvolume,&surfacedots,&nsurfacedots,
426 index[0],ePBC,bPBC ? box : NULL);
427 if (retval)
428 gmx_fatal(FARGS,"Something wrong in nsc_dclm_pbc");
430 if (bConnelly)
431 connelly_plot(ftp2fn(efPDB,nfile,fnm),
432 nsurfacedots,surfacedots,x,atoms,
433 &(top.symtab),ePBC,box,bSave);
434 harea = 0;
435 tarea = 0;
436 dgsolv = 0;
437 if (bResAt)
438 for(i=0; i<atoms->nres; i++)
439 res_a[i] = 0;
440 for(i=0; (i<nx[0]); i++) {
441 ii = index[0][i];
442 if (bOut[ii]) {
443 at_area = area[i];
444 if (bResAt) {
445 atom_area[i] += at_area;
446 atom_area2[i] += sqr(at_area);
447 res_a[atoms->atom[ii].resind] += at_area;
449 tarea += at_area;
450 if (bDGsol)
451 dgsolv += at_area*dgs_factor[i];
452 if (bPhobic[i])
453 harea += at_area;
456 if (bResAt)
457 for(i=0; i<atoms->nres; i++) {
458 res_area[i] += res_a[i];
459 res_area2[i] += sqr(res_a[i]);
461 fprintf(fp,"%10g %10g %10g %10g",t,harea,tarea-harea,tarea);
462 if (bDGsol)
463 fprintf(fp," %10g\n",dgsolv);
464 else
465 fprintf(fp,"\n");
467 /* Print volume */
468 if (vp) {
469 density = totmass*AMU/(totvolume*NANO*NANO*NANO);
470 fprintf(vp,"%12.5e %12.5e %12.5e\n",t,totvolume,density);
472 if (area) {
473 sfree(area);
474 area = NULL;
476 if (surfacedots) {
477 sfree(surfacedots);
478 surfacedots = NULL;
480 nfr++;
481 } while (read_next_x(oenv,status,&t,natoms,x,box));
483 if (bPBC)
484 gmx_rmpbc_done(gpbc);
486 fprintf(stderr,"\n");
487 close_trj(status);
488 ffclose(fp);
489 if (vp)
490 ffclose(vp);
492 /* if necessary, print areas per atom to file too: */
493 if (bResAt) {
494 for(i=0; i<atoms->nres; i++) {
495 res_area[i] /= nfr;
496 res_area2[i] /= nfr;
498 for(i=0; i<nx[0]; i++) {
499 atom_area[i] /= nfr;
500 atom_area2[i] /= nfr;
502 fprintf(stderr,"Printing out areas per atom\n");
503 fp = xvgropen(opt2fn("-or",nfile,fnm),"Area per residue over the trajectory","Residue",
504 "Area (nm\\S2\\N)",oenv);
505 xvgr_legend(fp, asize(or_and_oa_legend),or_and_oa_legend,oenv);
506 fp2 = xvgropen(opt2fn("-oa",nfile,fnm),"Area per atom over the trajectory","Atom #",
507 "Area (nm\\S2\\N)",oenv);
508 xvgr_legend(fp2, asize(or_and_oa_legend),or_and_oa_legend,oenv);
509 if (bITP) {
510 fp3 = ftp2FILE(efITP,nfile,fnm,"w");
511 fprintf(fp3,"[ position_restraints ]\n"
512 "#define FCX 1000\n"
513 "#define FCY 1000\n"
514 "#define FCZ 1000\n"
515 "; Atom Type fx fy fz\n");
517 for(i=0; i<nx[0]; i++) {
518 ii = index[0][i];
519 res = atoms->atom[ii].resind;
520 if (i==nx[0]-1 || res!=atoms->atom[index[0][i+1]].resind) {
521 fluc2 = res_area2[res]-sqr(res_area[res]);
522 if (fluc2 < 0)
523 fluc2 = 0;
524 fprintf(fp,"%10d %10g %10g\n",
525 atoms->resinfo[res].nr,res_area[res],sqrt(fluc2));
527 fluc2 = atom_area2[i]-sqr(atom_area[i]);
528 if (fluc2 < 0)
529 fluc2 = 0;
530 fprintf(fp2,"%d %g %g\n",index[0][i]+1,atom_area[i],sqrt(fluc2));
531 if (bITP && (atom_area[i] > minarea))
532 fprintf(fp3,"%5d 1 FCX FCX FCZ\n",ii+1);
534 if (bITP)
535 ffclose(fp3);
536 ffclose(fp);
539 /* Be a good citizen, keep our memory free! */
540 sfree(x);
541 sfree(nx);
542 for(i=0;i<2;i++)
544 sfree(index[i]);
545 sfree(grpname[i]);
547 sfree(bOut);
548 sfree(radius);
549 sfree(bPhobic);
551 if(bResAt)
553 sfree(atom_area);
554 sfree(atom_area2);
555 sfree(res_a);
556 sfree(res_area);
557 sfree(res_area2);
559 if(bDGsol)
561 sfree(dgs_factor);
565 int gmx_sas(int argc,char *argv[])
567 const char *desc[] = {
568 "[TT]g_sas[tt] computes hydrophobic, hydrophilic and total solvent accessible surface area.",
569 "As a side effect, the Connolly surface can be generated as well in",
570 "a [TT].pdb[tt] file where the nodes are represented as atoms and the vertices",
571 "connecting the nearest nodes as CONECT records.",
572 "The program will ask for a group for the surface calculation",
573 "and a group for the output. The calculation group should always",
574 "consists of all the non-solvent atoms in the system.",
575 "The output group can be the whole or part of the calculation group.",
576 "The average and standard deviation of the area over the trajectory can be plotted",
577 "per residue and atom as well (options [TT]-or[tt] and [TT]-oa[tt]).",
578 "In combination with the latter option an [TT].itp[tt] file can be",
579 "generated (option [TT]-i[tt])",
580 "which can be used to restrain surface atoms.[PAR]",
581 "By default, periodic boundary conditions are taken into account,",
582 "this can be turned off using the [TT]-nopbc[tt] option.[PAR]",
583 "With the [TT]-tv[tt] option the total volume and density of the molecule can be",
584 "computed.",
585 "Please consider whether the normal probe radius is appropriate",
586 "in this case or whether you would rather use e.g. 0. It is good",
587 "to keep in mind that the results for volume and density are very",
588 "approximate. For example, in ice Ih, one can easily fit water molecules in the",
589 "pores which would yield a volume that is too low, and surface area and density",
590 "that are both too high."
593 output_env_t oenv;
594 static real solsize = 0.14;
595 static int ndots = 24;
596 static real qcut = 0.2;
597 static real minarea = 0.5, dgs_default=0;
598 static gmx_bool bSave = TRUE,bPBC=TRUE,bFindex=FALSE;
599 t_pargs pa[] = {
600 { "-probe", FALSE, etREAL, {&solsize},
601 "Radius of the solvent probe (nm)" },
602 { "-ndots", FALSE, etINT, {&ndots},
603 "Number of dots per sphere, more dots means more accuracy" },
604 { "-qmax", FALSE, etREAL, {&qcut},
605 "The maximum charge (e, absolute value) of a hydrophobic atom" },
606 { "-f_index", FALSE, etBOOL, {&bFindex},
607 "Determine from a group in the index file what are the hydrophobic atoms rather than from the charge" },
608 { "-minarea", FALSE, etREAL, {&minarea},
609 "The minimum area (nm^2) to count an atom as a surface atom when writing a position restraint file (see help)" },
610 { "-pbc", FALSE, etBOOL, {&bPBC},
611 "Take periodicity into account" },
612 { "-prot", FALSE, etBOOL, {&bSave},
613 "Output the protein to the Connelly [TT].pdb[tt] file too" },
614 { "-dgs", FALSE, etREAL, {&dgs_default},
615 "Default value for solvation free energy per area (kJ/mol/nm^2)" }
617 t_filenm fnm[] = {
618 { efTRX, "-f", NULL, ffREAD },
619 { efTPS, "-s", NULL, ffREAD },
620 { efXVG, "-o", "area", ffWRITE },
621 { efXVG, "-or", "resarea", ffOPTWR },
622 { efXVG, "-oa", "atomarea", ffOPTWR },
623 { efXVG, "-tv", "volume", ffOPTWR },
624 { efPDB, "-q", "connelly", ffOPTWR },
625 { efNDX, "-n", "index", ffOPTRD },
626 { efITP, "-i", "surfat", ffOPTWR }
628 #define NFILE asize(fnm)
630 CopyRight(stderr,argv[0]);
631 parse_common_args(&argc,argv,PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE,
632 NFILE,fnm,asize(pa),pa,asize(desc),desc,0,NULL,&oenv);
633 if (solsize < 0) {
634 solsize=1e-3;
635 fprintf(stderr,"Probe size too small, setting it to %g\n",solsize);
637 if (ndots < 20) {
638 ndots = 20;
639 fprintf(stderr,"Ndots too small, setting it to %d\n",ndots);
642 please_cite(stderr,"Eisenhaber95");
644 sas_plot(NFILE,fnm,solsize,ndots,qcut,bSave,minarea,bPBC,dgs_default,bFindex,
645 oenv);
647 do_view(oenv,opt2fn("-o",NFILE,fnm),"-nxy");
648 do_view(oenv,opt2fn_null("-or",NFILE,fnm),"-nxy");
649 do_view(oenv,opt2fn_null("-oa",NFILE,fnm),"-nxy");
651 thanx(stderr);
653 return 0;