/* * test.c - test for zernike.c * * Copyright 2013 Edward V. Emelianoff * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include "zernike.h" /**/ double IdxsOri[] = {2., // смещение, 0 1.1, -0.8, // наклон, 1-2 5.5, -3.2, 0., // астигматизм, дефокус, аст., 3-5 6.8, 5.5, 0., 0.,// трилистник, кома, 6-9 0., 0., 3.3, 1.4, 8.}; // 10-14 /** double IdxsOri[] = {1., // смещение, 0 1., 1., // наклон, 1-2 1., 1., 0., // астигматизм, дефокус, аст., 3-5 1., 1., 0., 0.,// трилистник, кома, 6-9 0., 0., 1., 1., 1.}; // 10-14 **/ const int ORI_SZ = 15; const int W = 16, H = 16, Pmax = 8; //#define PLOT_ #define RAD 57.2957795130823 #define D2R(x) ((x) / RAD) #define R2D(x) ((x) * RAD) void plotRD(double *A, double *A1, int W, int H){ int i,j; double S = 0., N = 0.; printf("\n\nRemaining abs. differences:\n"); for(j = 0; j < H; j++){ for(i = 0; i < W; i++){ double d = fabs(A1[j*W+i] - A[j*W+i]); if(d > DBL_EPSILON){ N++; S += d; } printf("%5.2f ", d); } printf("\n"); } double dA = S/N; printf("average abs difference: %g\n", dA); if(dA < 1.) return; printf("Corrected diff:\n"); for(j = 0; j < H; j++){ for(i = 0; i < W; i++){ double X = 0.; if(fabs(A1[j*W+i]) > DBL_EPSILON) // X = A1[j*W+i]+dA; X = fabs(A1[j*W+i] - A[j*W+i])-dA; printf("%6.2f ", X); } printf("\n"); } } int main(int argc, char **argv){ int i, j, lastidx; double *Z, *Zidxs; #if 0 //double xstart, ystart; double pt = 4. / ((W>H) ? W-1 : H-1); #ifdef PLOT_ Z = zernfunN(1, W,H, NULL); printf("\nZernike for square matrix: \n"); for(j = 0; j < H; j++){ for(i = 0; i < W; i++) printf("%5.2f ", Z[j*W+i]); printf("\n"); } FREE(Z); #endif Z = Zcompose(ORI_SZ, IdxsOri, W, H); #ifdef PLOT_ printf("\n\nDecomposition for image: \n"); for(j = 0; j < H; j++){ for(i = 0; i < W; i++) printf("%6.2f ", Z[j*W+i]); printf("\n"); } #endif /* xstart = (W-1)/2., ystart = (H-1)/2.; for(j = 0; j < H; j++){ for(i = 0; i < W; i++){ double yy = (j - ystart)*pt, xx = (i - xstart)*pt; if((xx*xx + yy*yy) <= 1.) Z[j*W+i] = //100*(xx*xx*xx*xx*xx-yy*yy*yy); 100.*(xx-0.3)*yy+200.*xx*yy*yy+300.*yy*yy*yy*yy; printf("%6.2f ", Z[j*W+i]); } printf("\n"); } */ Zidxs = Zdecompose(Pmax, W, H, Z, &j, &lastidx); printf("\nCoefficients: "); for(i = 0; i <= lastidx; i++) printf("%5.3f, ", Zidxs[i]); double *Zd = Zcompose(j, Zidxs, W, H); #ifdef PLOT_ printf("\n\nComposed image:\n"); for(j = 0; j < H; j++){ for(i = 0; i < W; i++) printf("%6.2f ", Zd[j*W+i]); printf("\n"); } plotRD(Z, Zd, W, H); #endif FREE(Zd); //W--, H--; point *testArr = MALLOC(point, W*H); /* xstart = (W-1)/2., ystart = (H-1)/2.; for(j = 0; j < H; j++){ point *p = &testArr[j*W]; for(i = 0; i < W; i++, p++){ double yy = (j - ystart)*pt, xx = (i - xstart)*pt; if((xx*xx + yy*yy) <= 1.){ //p->x = 500.*xx*xx*xx*xx; //p->y = -300.*yy*yy; p->x = 100.*yy+200.*yy*yy; p->y = 100.*(xx-0.3)+400.*xx*yy+1200.*yy*yy*yy; } printf("(%4.1f,%4.1f) ",p->x, p->y); } printf("\n"); } */ for(j = 1; j < H-1; j++){ point *p = &testArr[j*W+1]; double *d = &Z[j*W+1]; for(i = 1; i < W-1; i++, p++, d++){ p->x = (d[1]-d[-1])/pt; p->y = (d[W]-d[-W])/pt; } } #ifdef PLOT_ printf("\n\nGradients of field\n"); for(j = 0; j < H; j++){ point *p = &testArr[j*W]; for(i = 0; i < W; i++, p++) printf("(%4.1f,%4.1f) ",p->x, p->y); printf("\n"); } #endif //Pmax = 2; double *_Zidxs = gradZdecompose(Pmax, W, H, testArr, &j, &lastidx); printf("\nCoefficients: "); for(i = 0; i <= lastidx; i++) printf("%5.3f, ", _Zidxs[i]); //lastidx = j; point *gZd = gradZcompose(j, _Zidxs, W, H); #ifdef PLOT_ printf("\n\nComposed image:\n"); for(j = 0; j < H; j++){ point *p = &gZd[j*W]; for(i = 0; i < W; i++, p++) printf("(%4.1f,%4.1f) ",p->x, p->y); printf("\n"); } printf("\n\nRemaining abs differences:\n"); for(j = 0; j < H; j++){ point *p = &gZd[j*W]; point *d = &testArr[j*W]; for(i = 0; i < W; i++, p++, d++) printf("%5.2f ",sqrt((p->x-d->x)*(p->x-d->x)+(p->y-d->y)*(p->y-d->y))); printf("\n"); } #endif FREE(gZd); FREE(testArr); lastidx++; double *ZidxsN = convGradIdxs(_Zidxs, lastidx); printf("\nCoefficients for Zernike:\n i n m Z[i] gradZ[i] S[i] Zori[i]\n"); for(i = 0; i < lastidx; i++){ int n,m; convert_Zidx(i, &n, &m); printf("%2d%3d%3d%8.1f%8.1f%8.1f", i, n,m, Zidxs[i], ZidxsN[i],_Zidxs[i]); if(i < ORI_SZ) printf("%8.1f", IdxsOri[i]); printf("\n"); } FREE(Zidxs); #ifdef PLOT_ printf("\n\nComposed image:\n"); Zd = Zcompose(lastidx, ZidxsN, W, H); for(j = 0; j < H; j++){ for(i = 0; i < W; i++) printf("%6.1f ", Zd[j*W+i]); printf("\n"); } plotRD(Z, Zd, W, H); FREE(Zd); #endif FREE(_Zidxs); FREE(ZidxsN); #endif // 0 int Sz = 256; double dTh = D2R(360./32); polar *P = MALLOC(polar, Sz), *Pptr = P; void print256(double *Par){ for(j = 0; j < 32; j++){ for(i = 0; i < 8; i++) printf("%6.1f", Par[i*32+j]); printf("\n"); } } double Z_PREC = get_prec(); void print256diff(double *Ori, double *App){ printf(RED "Difference" OLDCOLOR " from original in percents:\t\t\t\t\tabs:\n"); for(j = 0; j < 32; j++){ for(i = 0; i < 8; i++){ double den = Ori[i*32+j]; if(fabs(den) > Z_PREC) printf("%6.0f", fabs(App[i*32+j]/den-1.)*100.); else printf(" /0 "); } printf("\t"); for(i = 0; i < 8; i++) printf("%7.3f", fabs(App[i*32+j]-Ori[i*32+j])); printf("\n"); } } void print_std(double *p1, double *p2, int sz){ int i; double d = 0., d2 = 0., dmax = 0.; for(i = 0; i < sz; i++, p1++, p2++){ double delta = (*p2) - (*p1); d += delta; d2 += delta*delta; double m = fabs(delta); if(m > dmax) dmax = m; } d /= sz; printf("\n" GREEN "Std: %g" OLDCOLOR ", max abs diff: %g\n\n", (d2/sz - d*d), dmax); } void print_idx_diff(double *idx){ int i; double *I = idx; //printf("\nDifferences of indexes (i-i0 / i/i0):\n"); printf("\nidx (app / real):\n"); for(i = 0; i < ORI_SZ; i++, I++) printf("%d: (%3.1f / %3.1f), ", i, *I, IdxsOri[i]); //printf("%d: (%3.1f / %3.1f), ", i, *I - IdxsOri[i], *I/IdxsOri[i]); print_std(idx, IdxsOri, ORI_SZ); printf("\n"); } void mktest__(double* (*decomp_fn)(int, int, polar*, double*, int*, int*), char *msg){ Zidxs = decomp_fn(Pmax, Sz, P, Z, &j, &lastidx); printf("\n" RED "%s, coefficients (%d):" OLDCOLOR "\n", msg, lastidx); lastidx++; for(i = 0; i < lastidx; i++) printf("%5.3f, ", Zidxs[i]); printf("\nComposing: %s(%d, Zidxs, %d, P)\n", msg, lastidx, Sz); double *comp = ZcomposeR(lastidx, Zidxs, Sz, P); print_std(Z, comp, Sz); print_idx_diff(Zidxs); print256diff(Z, comp); FREE(comp); FREE(Zidxs); printf("\n"); } #define mktest(a) mktest__(a, #a) double R_holes[] = {.175, .247, .295, .340, .379, .414, .448, .478}; for(i = 0; i < 8; i++){ // double RR = (double)i * 0.1 + 0.3; // double RR = (double)i * 0.14+0.001; // double RR = (double)i * 0.07 + 0.5; double RR = R_holes[i]; // / 0.5; double Th = 0.; for(j = 0; j < 32; j++, Pptr++, Th += dTh){ Pptr->r = RR; Pptr->theta = Th; } } Z = ZcomposeR(ORI_SZ, IdxsOri, Sz, P); printf(RED "Original:" OLDCOLOR "\n"); print256(Z); mktest(ZdecomposeR); mktest(QR_decompose); mktest(LS_decompose); // ann_Z(4, Sz, P, NULL); //polar P1[] = {{0.2, 0.}, {0.6, M_PI_2}, {0.1, M_PI}, {0.92, 3.*M_PI_2}}; //ann_Z(8, 4, P1, NULL); /* double id_ann[] = {1.,2.,0.1,-1.,0.5}; Z = ann_Zcompose(5, id_ann, Sz, P); */ FREE(Z); Z = ann_Zcompose(ORI_SZ, IdxsOri, Sz, P); printf(RED "Annular:" OLDCOLOR "\n"); print256(Z); Zidxs = ann_Zdecompose(7, Sz, P, Z, &j, &lastidx); printf("\nann_Zdecompose, coefficients:\n"); for(i = 0; i <= lastidx; i++) printf("%5.3f, ", Zidxs[i]); double *comp = ann_Zcompose(lastidx, Zidxs, Sz, P); print_std(Z, comp, Sz); print_idx_diff(Zidxs); print256diff(Z, comp); FREE(comp); FREE(Zidxs); /* * TEST for gradients on hartmann's net */ point *gradZ = MALLOC(point, Sz); Pptr = P; point *dP = gradZ; for(i = 0; i < Sz; i++, Pptr++, dP++){ double x = Pptr->r * cos(Pptr->theta), y = Pptr->r * sin(Pptr->theta); double x2 _U_ = x*x, x3 _U_ = x*x2; double y2 _U_ = y*y, y3 _U_ = y*y2; double sx, cx; sincos(x, &sx, &cx); double val = 1000.*x3 + y2 + 30.*cx*y3; Z[i] = val; val *= 0.05; dP->x = 3000.*x2 - 30.*sx*y3 + val * drand48(); dP->y = 2.*y + 90.*cx*y2 + val * drand48(); /* double val = 50.*x3*y3 + 3.*x2*y2 - 2.*x*y3 - 8.*x3*y + 7.*x*y; Z[i] = val; val *= 0.05; // 5% from value dP->x = 150.*x2*y3 + 6.*x*y2 - 2.*y3 - 24.*x2*y + 7.*y + val * drand48(); // + error 5% dP->y = 150.*x3*y2 + 6.*x2*y - 6.*x*y2 - 8.*x3 + 7.*x + val * drand48(); */ } printf("\n" RED "Z cubic:" OLDCOLOR "\n"); print256(Z); mktest(ZdecomposeR); mktest(LS_decompose); mktest(QR_decompose); Zidxs = LS_gradZdecomposeR(Pmax+2, Sz, P, gradZ, &i, &lastidx); lastidx++; printf("\n" RED "GradZ decompose, coefficients (%d):" OLDCOLOR "\n", lastidx); for(i = 0; i < lastidx; i++) printf("%5.3f, ", Zidxs[i]); comp = ZcomposeR(lastidx, Zidxs, Sz, P); double averD = 0.; for(i = 0; i < Sz; i++) averD += Z[i] - comp[i]; averD /= (double)Sz; printf("Z0 = %g\n", averD); for(i = 0; i < Sz; i++) comp[i] += averD; print256diff(Z, comp); FREE(comp); FREE(Zidxs); Zidxs = gradZdecomposeR(Pmax+2, Sz, P, gradZ, &i, &lastidx); /* point *gZd = gradZcomposeR(lastidx, Zidxs, Sz, P); printf("\n\nRemaining abs differences:\n"); for(i = 0; i < Sz; i++){ point p = gZd[i]; point d = gradZ[i]; printf("%5.2f ",sqrt((p.x-d.x)*(p.x-d.x)+(p.y-d.y)*(p.y-d.y))); } printf("\n"); FREE(gZd); */ // double *ZidxsN = convGradIdxs(Zidxs, lastidx); // FREE(Zidxs); Zidxs = ZidxsN; lastidx++; printf("\n" RED "GradZ decompose, coefficients (%d):" OLDCOLOR "\n", lastidx); for(i = 0; i < lastidx; i++) printf("%5.3f, ", Zidxs[i]); comp = ZcomposeR(lastidx, Zidxs, Sz, P); averD = 0.; for(i = 0; i < Sz; i++) averD += Z[i] - comp[i]; averD /= (double)Sz; printf("Z0 = %g\n", averD); for(i = 0; i < Sz; i++) comp[i] += averD; print256diff(Z, comp); FREE(comp); FREE(Zidxs); FREE(Z); return 0; }