#include #include #include #include #include "recipes.h" void spline(double x[], double y[], int n, double yp1, double ypn, double y2[]); void splint(double xa[], double ya[], double y2a[], int n, double x, double *y); char *paulgetline(char *line, int nchars, FILE *fp); #define MIN(A,B) ((A > B) ? (B) : (A)) int main(int argc, char *argv[]) { FILE *fp1, *fp2; int q, i, j, k, n, n1, n2, a[101], z, *arglist, nanchors=25, z1, z2, pz1, pz2, nf=0, nz=0, xed, Zflag=0, epoxypeakn; int npz=0, bgflag=0, ng=0, pflag=0, pdegree=5, gflag, iflag=0, zarg, oflag=0, oiflag=0, no, o=0, nx=0, ne; double *x, *spec, *back, x1=1100.0, x2=3970.0, delta, hold, xray[101], y[101], yy[101], max, swap, x00; double zap1[20], zap2[20], pzap1[20], pzap2[20], xr1[20], xr2[20], f[20], g[20], **oback, **iback; double *epoxyx, *epoxyy, epoxypeakx=2935.126, epoxyscale; char file1[256], file2[256], ofile[256], ifile[256], line[100], c[20], allfiles[5000], epoxyfile[256]; if (argc == 1) { printf("Usage: pbg [-i] [-bgs] [-o omnibusfilename] [-oi omnibusinputfile] [-p degree]\n"); printf(" [-1 lowwavenumber] [-2 highwavenumber] [-a #anchors] [-z low1 high1 [-z low2 high2] ... ]\n"); printf(" [-pz low1 high1 [-pz low2 high2] ... ] [-f fixedanchor1 [-f fixedanchor2] ... ]\n"); printf(" [-x low 1 high1 [-x low2 high2] ... ] [-g linearpoint1 [-g linearpoint2] ... ]\n"); printf(" [-Z epoxyfilename] [-Zp peaklocation] infile1 [infile2] [infile3]...\n"); printf("-i puts you in interactive mode, giving you a chance to set all other parameters as prompted.\n"); printf("-bgs means output the subtracted spectrum, otherwise the background itself is output.\n"); printf("-o means assemble all output spectra into one omnibus file, in addition to the separate files.\n"); printf("-oi means echo all input spectra into a single file, for your convenience.\n"); printf("-p means polynomial fit, otherwise cubic spline is used.\n"); printf("The background is fitted between lowwavenumber and highwavenumber, using #anchors anchor points.\n"); printf("The -z parameter indicates a subregion of organic peaks to be copied into background after fitting.\n"); printf("The -pz parameter indicates really troublesome regions to be replaced with lines before fitting.\n"); printf("The -f points are wavenumbers of manually fixed anchors.\n"); printf("The -x ranges are forbidden areas - the program will not pick anchors in these regions.\n"); printf("Wavenumber ranges containing a g-point will be fitted with lines, not splines.\n"); printf("-Z indicates that epoxy contamination spectrum epoxyfilename is to be subtracted.\n"); printf("If -Zp is given then the epoxy intensity is determined at peaklocation, otherwise at 3925.126.\n"); printf("Defaults: -bg, lowwavenumber = 1100, highwavenumber = 3970, #anchors = 25, no zap, no fixed anchors\n"); printf("Note: Please ensure that all spectra run together in a single execution are sampled at exactly the same wavenumbers!\n"); exit; } arglist = (int *) malloc((unsigned) 300*sizeof(int)); for (i=1;i x2) { printf("Outside fitted range, rejected. Try again.\n"); i--; } } nf += n; if (!pflag) { printf("Step 6. How many linear (non-spline) segments do you want to define (now there are %d; enter 0 for no more): ", ng); scanf("%d", &n); for (i=0;i x2) { printf("Outside fitted range, rejected. Try again.\n"); i--; } } ng += n; } printf("Step 7. How many regions to copy peaks into background (now there are %d; enter 0 for no more): ", nz); scanf("%d", &n); for (i=0;i x2 || zap2[nz+i] < x1 || zap2[nz+i] > x2) { printf("One of those limits is outside fitted range, rejected. Try again.\n"); i--; } } nz += n; printf("Step 8. How many regions to replace with lines before fitting (now there are %d; enter 0 for no more): ", npz); scanf("%d", &n); for (i=0;i x2 || pzap2[npz+i] < x1 || pzap2[npz+i] > x2) { printf("One of those limits is outside fitted range, rejected. Try again.\n"); i--; } } npz += n; printf("Step 9. How many regions to forbid from anchoring (now there are %d; enter 0 for no more): ", nx); scanf("%d", &n); for (i=0;ij;i--) a[i] = a[i-1]; a[j] = swap; break; } } } for (z=3+nf;z<=nanchors/*-ng*/;z++) { for (j=1;j= xr1[j] && x[i] <= xr2[j]) { xed = 1; break; } } if (!xed && (back[i] - spec[i]) > max) { max = back[i] - spec[i]; a[z] = i; } } if (max == 0.0) { break; } for (j=1;jj;i--) a[i] = a[i-1]; a[j] = swap; break; } } } z--; /* Fill arrays */ for (i=1;i<=z;i++) { xray[i] = x[a[i]]; y[i] = spec[a[i]]; } if (!pflag) { /* Spline and splint */ spline(xray, y, z, 1e32, 1e32, yy); for (j=1;j 0.99e30) y2[1]=u[1]=0.0; else { y2[1] = -0.5; u[1] = (3.0/(x[2]-x[1]))*((y[2]-y[1])/(x[2]-x[1])-yp1); } for (i=2;i<=n-1;i++) { sig=(x[i]-x[i-1])/(x[i+1]-x[i-1]); p=sig*y2[i-1]+2.0; y2[i]=(sig-1.0)/p; u[i]=(y[i+1]-y[i])/(x[i+1]-x[i]) - (y[i]-y[i-1])/(x[i]-x[i-1]); u[i]=(6.0*u[i]/(x[i+1]-x[i-1])-sig*u[i-1])/p; } if (ypn > 0.99e30) qn=un=0.0; else { qn=0.5; un=(3.0/(x[n]-x[n-1]))*(ypn-(y[n]-y[n-1])/(x[n]-x[n-1])); } y2[n]=(un-qn*u[n-1])/(qn*y2[n-1]+1.0); for (k=n-1;k>=1;k--) y2[k]=y2[k]*y2[k+1]+u[k]; free(u); } void splint(double xa[], double ya[], double y2a[], int n, double x, double *y) { static int klo=1, khi=1000; int k; double h, b, a; if (khi == 1000) khi = n; /* Allow increasing xa or decreasing xa */ if (khi-klo != 1 || (xa[khi] < x && xa[klo] < x) || (xa[khi] > x && xa[klo] > x)) { klo=1; khi=n; while(khi-klo>1) { k=(khi+klo) >> 1; if ((xa[k] > x && xa[klo] <= x) || (xa[k] < x && xa[klo] >= x)) khi=k; else klo=k; } } h=xa[khi]-xa[klo]; if (h==0.0) { printf("Splint failure...xa values must be distinct"); return; } a = (xa[khi]-x)/h; b = (x-xa[klo])/h; *y = a*ya[klo]+b*ya[khi]+((a*a*a-a)*y2a[klo]+(b*b*b-b)*y2a[khi])*(h*h)/6.0; } char *paulgetline(char *line, int nchars, FILE *fp) { char c, *startline=line; int n=0; while ((c = fgetc(fp)) != EOF && c != 10 && c !=13 && n++ <= nchars) *line++ = c; if (c == 13) { if ((c = fgetc(fp)) != EOF && c != 10) { ungetc(c, fp); } } *line = '\0'; if (line == startline) return 0x0; else { line = startline; return line; } }