00001 #include "jsoc_main.h"
00002 #include "limb_fit.h"
00003 #include "fresize.h"
00004 #include "gapfill.h"
00005
00006
00007
00008
00009 const double rad_corr_fac=1.00130;
00010 const double foc_corr=-1.08490;
00011 const double high=1.03;
00012 const double low=0.97;
00013
00014 const double limit_var=1.8;
00015 const double limit_cc=15.0;
00016
00017
00018 #define kLimbFit_lim 8
00019
00020 const int lim=kLimbFit_lim;
00021
00022
00023
00024
00025 const int parsize=2*kLimbFit_lim+1;
00026
00027
00028
00029 #define kLimbFit_gapfill_order 11
00030
00031 const int gapfill_order=kLimbFit_gapfill_order;
00032 const int gapfill_method=11;
00033 const float gapfill_regular=0.0025;
00034
00035
00036
00037 const int gapfill_order2=kLimbFit_gapfill_order/2;
00038
00039 const int min_imcnf=80;
00040 const int max_imcnf=1024;
00041
00042 char *X0_MP_key="X0_MP";
00043 char *Y0_MP_key="Y0_MP";
00044 char *RSUN_OBS_key="RSUN_OBS";
00045 char *IMSCL_MP_key="IMSCL_MP";
00046
00047 char *HCAMID_key="HCAMID";
00048 char *HCFTID_key="HCFTID";
00049 char *MISSVAL_key="MISSVALS";
00050
00051 int light_val1=2;
00052 int light_val2=3;
00053
00054 const double percent_good=0.75;
00055
00056
00057 int limb_fit(DRMS_Record_t *record, float *image_in, double *rsun_lf, double *x0_lf, double *y0_lf, int nx, int ny, int method)
00058 {
00059
00060 void cross_corr(int nx, int ny, double *a, double *b);
00061 int is_parab(double *arr, int n, int nmax);
00062 void free_mem(struct mempointer *memory);
00063
00064
00065 int status_res, status_gap;
00066 int status,status1,status2;
00067
00068
00069 int i, j;
00070
00071
00072 struct fresize_struct fresizes;
00073
00074 struct fill_struct fills;
00075
00076 static int config_id=0;
00077 static unsigned char mask[4096*4096];
00078
00079
00080
00081 *x0_lf=NAN;
00082 *y0_lf=NAN;
00083 *rsun_lf=NAN;
00084
00085
00086
00087
00088 size_t bytes_read;
00089 int new_config_id;
00090 new_config_id=drms_getkey_int(record, "HIMGCFID", &status);
00091
00092 FILE *maskfile;
00093
00094 if (status == DRMS_SUCCESS && new_config_id >= min_imcnf && new_config_id <=max_imcnf)
00095 {
00096 if (config_id != new_config_id)
00097 {
00098
00099 unsigned char *mk;
00100 mk=(unsigned char *)(malloc(sizeof(unsigned char)));
00101
00102 config_id=new_config_id;
00103
00104
00105 maskfile=fopen("/home/jsoc/hmi/tables/cropmask.105", "rb");
00106 if (maskfile==NULL){fputs("mask file not found", stderr); status_res=2; free(mk); return status;}
00107 for (j=0; j<ny; ++j) for (i=0; i<nx; ++i)
00108 {
00109 bytes_read=fread(mk,sizeof(unsigned char),1,maskfile);
00110 mask[j*nx+i]=mk[0];
00111 }
00112 free(mk);
00113 fclose(maskfile);
00114 }
00115 }
00116 else
00117 {
00118 status_res=2; return status_res;
00119 }
00120
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 const int nxx=nx/4;
00132 const int nyy=nx/4;
00133
00134 const int binx=nx/nxx;
00135 const int biny=nx/nyy;
00136
00137 int k,l;
00138
00139 long double akl[3][3];
00140 long double bl[3];
00141 long double cof[3];
00142
00143
00144
00145
00146
00147 int rcount=0;
00148
00149 double dx, ds;
00150
00151 int ispar;
00152 int camid, focid, missvals;
00153 double cx, cy, rad;
00154 double image_scl;
00155 double rsun_obs;
00156
00157
00158 cx=drms_getkey_float(record,X0_MP_key,&status);
00159 if (status != 0 || isnan(cx)){status_res=2; return status_res;}
00160
00161
00162 cy=drms_getkey_float(record,Y0_MP_key,&status);
00163 if (status != 0 || isnan(cx)){status_res=2; return status_res;}
00164
00165
00166 rsun_obs=drms_getkey_double(record,RSUN_OBS_key,&status1);
00167 image_scl=drms_getkey_float(record,IMSCL_MP_key,&status2);
00168
00169 camid=drms_getkey_int(record,HCAMID_key,&status);
00170 focid=drms_getkey_int(record,HCFTID_key,&status);
00171 missvals=drms_getkey_int(record,MISSVAL_key,&status);
00172
00173
00174 long long recnum;
00175 double date;
00176 int fsn=drms_getkey_int(record, "FSN", &status);
00177
00178
00179
00180 if ((camid != light_val1 && camid != light_val2) || focid < 1 || focid > 16){status_res=2; return status_res;}
00181 if (missvals > nx/4*ny){status_res=2; return status_res;}
00182
00183
00184 if (status1 == 0 && status2 == 0 && !isnan(image_scl) && image_scl > 0.0 && !isnan(rsun_obs) && rsun_obs > 0.0){rad=(double)rsun_obs/image_scl*rad_corr_fac+foc_corr*((double)focid-11.0);} else {status_res=2; return status_res;}
00185
00186
00187 if (nx != ny){printf("Limb finder does not work for non-square images\n"); status_res=2; return status_res;}
00188
00189
00190
00191 int nr=(int)(rad*(high-low)/2.0)*2+1;
00192 int nphi=(int)(rad/4.0*2.0*M_PI);
00193
00194
00195
00196 struct mempointer memory;
00197
00198 double *xrp, *yrp, *imrphi, *rc, *phic;
00199
00200 xrp=(double *)(malloc(nr*nphi*sizeof(double)));
00201 yrp=(double *)(malloc(nr*nphi*sizeof(double)));
00202 imrphi=(double *)(calloc(nr*nphi,sizeof(double)));
00203 rc=(double *)(malloc(nr*sizeof(double)));
00204 phic=(double *)(malloc(nphi*sizeof(double)));
00205
00206 double *avgphi, *imhp, *imro, *parab;
00207 float *image, *cnorm, *ierror, *imcp;
00208 unsigned char *mask_p;
00209
00210 avgphi=(double *)(calloc(nr, sizeof(double)));
00211
00212
00213 imhp=(double *)(calloc(nxx*nyy, sizeof(double)));
00214 imro=(double *)(calloc(nxx*nyy, sizeof(double)));
00215 image=(float *)(malloc(nxx*nyy*sizeof(float)));
00216 parab=(double *)(malloc(parsize*sizeof(double)));
00217 mask_p=(unsigned char *)(malloc(nx*nx*sizeof(unsigned char)));
00218 cnorm=(float *)(malloc(nx*nx*sizeof(float)));
00219 ierror=(float *)(malloc(nx*nx*sizeof(float)));
00220 imcp=(float *)(malloc(nx*nx*sizeof(float)));
00221
00222 if (imhp == NULL || imro == NULL || image == 0 || parab == NULL || mask_p == NULL || cnorm == NULL || ierror ==NULL){printf("can not allocate memory\n");}
00223
00224 memory.xrp=xrp;
00225 memory.yrp=yrp;
00226 memory.imrphi=imrphi;
00227 memory.rc=rc;
00228 memory.phic=phic;
00229 memory.avgphi=avgphi;
00230 memory.imhp=imhp;
00231 memory.imro=imro;
00232 memory.image=image;
00233 memory.parab=parab;
00234 memory.mask_p=mask_p;
00235 memory.cnorm=cnorm;
00236 memory.ierror=ierror;
00237 memory.imcp=imcp;
00238
00239 double rad0=rad/(double)binx;
00240 double cx0=cx/(double)binx;
00241 double cy0=cy/(double)biny;
00242
00243 double cxn=(double)nx/2.0-0.5;
00244 double cyn=(double)ny/2.0-0.5;
00245
00246 double radmax=(double)nx/2.0;
00247 double radmin=(double)nx/2.0*0.85;
00248
00249 rcount=0;
00250 #pragma omp parallel for reduction(+:rcount) private(i,j,dx)
00251 for (j=0; j<ny; ++j)
00252 for (i=0; i<nx; ++i)
00253 {
00254 imcp[j*nx+i]=image_in[j*nx+i];
00255 if (isnan(image_in[j*nx+i])){mask_p[j*nx+i]=2;} else {mask_p[j*nx+i]=0;}
00256 dx=sqrt(pow((double)i-cxn,2)+pow((double)j-cyn,2));
00257 if (dx > radmin && dx < radmax && mask[j*nx+i] == 1)
00258 {
00259 if (isnan(image_in[j*nx+i])){mask_p[j*nx+i]=1; ++rcount;}
00260 }
00261 }
00262
00263
00264
00265
00266
00267 if (rcount > 0)
00268 {
00269
00270 status_gap=init_fill(gapfill_method, gapfill_regular,
00271 gapfill_order,gapfill_order2,gapfill_order2,&fills, NULL, "/home/jsoc/cvs/Development/JSOC");
00272 if (status_gap == 0){fgap_fill(&fills,imcp,nx,nx,nx,mask_p,cnorm,ierror); free_fill(&fills);} else {status_res=2; printf("gapfill not successful 2 \n"); free_fill(&fills); free_mem(&memory); return status_res;}
00273 }
00274
00275
00276
00277 init_fresize_boxcar(&fresizes,2,4);
00278
00279 status=fresize(&fresizes,imcp, image, nx,nx,nx,nxx,nyy,nxx,0,0,NAN);
00280
00281 free_fresize(&fresizes);
00282
00283 if (status != 0){printf("resize not successful\n");}
00284
00285
00286 #pragma omp parallel for private(i,j,dx)
00287 for (j=1; j<(nyy-1); ++j)
00288 for (i=1; i<(nxx-1); ++i)
00289 {
00290 dx=sqrt(pow((double)i-cxn/binx,2)+pow((double)j-cyn/biny,2));
00291 if (dx > radmin/binx && dx < radmax/binx)
00292 {
00293 if(!isnan(image[j*nxx+i-1]) && !isnan(image[j*nxx+i+1]) && !isnan(image[(j+1)*nxx+i]) && !isnan(image[(j-1)*nxx+i]))
00294 {
00295 imhp[j*nxx+i]=sqrt(pow((double)image[j*nxx+i-1]-(double)image[j*nxx+i+1],2)+pow((double)image[(j+1)*nxx+i]-(double)image[(j-1)*nxx+i],2));
00296 imro[(nyy-j-1)*nxx+nxx-1-i]=imhp[j*nxx+i];
00297
00298 }
00299 }
00300
00301 }
00302
00303
00304
00305
00306
00308
00309 int max, xmax, ymax;
00310 double fmax=0.0, favg=0.0, denom;
00311 double xfra, yfra;
00312
00313
00314
00315
00316
00317 cross_corr(nxx,nyy, imhp, imro);
00318
00319
00320 for (j=0; j<nyy; ++j)
00321 for (i=0; i<nxx; ++i)
00322 {
00323 if (imro[j*nxx+i] > fmax){max=j*nxx+i; fmax=imro[j*nxx+i];}
00324 favg=favg+imro[j*nxx+i];
00325 }
00326
00327
00328
00329 if (favg/(double)(nxx*nyy)*limit_cc< fmax)
00330 {
00331 xmax=max % nxx;
00332 ymax=max/nxx;
00333
00334 if (xmax*ymax > 0 && xmax < (nxx-1) && ymax < (nyy-1))
00335 {
00336 denom = fmax*2.0 - imro[ymax*nxx+xmax-1] - imro[ymax*nxx+xmax+1];
00337 xfra = ((double)xmax-0.5) + (fmax-imro[ymax*nxx+xmax-1])/denom;
00338 denom = fmax*2.0 - imro[(ymax-1)*nxx+xmax] - imro[(ymax+1)*nxx+xmax];
00339 yfra = ((double)ymax-0.5) + (fmax-imro[(ymax-1)*nxx+xmax])/denom;
00340 }
00341
00342 cx0=(double)xfra/2.0+(double)nxx/4.0-0.5;
00343 cy0=(double)yfra/2.0+(double)nyy/4.0-0.5;
00344
00345 *x0_lf=(double)cx0*(double)binx;
00346 *y0_lf=(double)cy0*(double)biny;
00347 }
00348 else
00349 {status_res=2; free_mem(&memory); return status_res;}
00350
00351
00353
00354
00355
00356
00357
00358
00359 for (i=0; i<nr; ++i)rc[i]=((high-low)*(double)i/(double)(nr-1)+low)*rad;
00360 for (j=0; j<nphi; ++j) phic[j]=(double)j/(double)nphi*2.0f*(double)M_PI;
00361
00362 #pragma omp parallel for private(i,j)
00363 for (j=0; j<nphi; ++j)
00364 for (i=0; i<nr; ++i)
00365 {
00366 xrp[j*nr+i]=rc[i]/4.0*cos(phic[j])+(*x0_lf)/4.0;
00367 yrp[j*nr+i]=rc[i]/4.0*sin(phic[j])+(*y0_lf)/4.0;
00368 }
00369
00370
00371
00372
00373
00374 int xl,xu,yl,yu;
00375 double rx, ry;
00376 double wg[2*lim+1];
00377
00378 #pragma omp parallel for private(i,j,xl,yl,xu,yu,rx,ry)
00379 for (j=0; j<nphi; ++j)
00380 for (i=0; i<nr; ++i)
00381 {
00382 xl=floor(xrp[j*nr+i]);
00383 xu=xl+1;
00384
00385 yl=floor(yrp[j*nr+i]);
00386 yu=yl+1;
00387
00388 rx=(double)xu-(xrp[j*nr+i]);
00389 ry=(double)yu-(yrp[j*nr+i]);
00390
00391 if (xl >= 0 && xu < nxx && yl >= 0 && yu < nyy)
00392 {
00393 imrphi[j*nr+i]=rx*ry*imhp[yl*nxx+xl]+(1.0-rx)*ry*imhp[yl*nxx+xu]+rx*(1.0-ry)*imhp[yu*nxx+xl]+(1.0-rx)*(1.0-ry)*imhp[yu*nxx+xu];
00394 }
00395
00396 }
00397
00398
00399 fmax=0.0; max=0;
00400
00401 for (i=0; i<(2*lim+1); ++i){wg[i]=1.0-pow(sin(M_PI/(float)(2*lim)*(float)i+M_PI/2.0),4);}
00402
00403
00404 if (method == 1)
00405 {
00406 for (i=0; i<nr; ++i) for (j=0; j<nphi; ++j) avgphi[i]=avgphi[i]+imrphi[j*nr+i]/(double)nphi;
00407
00408
00409
00410
00411 for (k=0; k<=2; ++k) for (l=0; l<=2; ++l) akl[k][l]=0.0;
00412 for (k=0; k<=2; ++k) bl[k]=0.0;
00413
00414 for (i=0; i<nr; ++i) if (avgphi[i] > fmax){fmax=avgphi[i]; max=i;}
00415
00416
00417
00418 if ((max-lim) >= 0 && (max+lim) < nr) for (i=(max-lim+1); i<=(max+lim-1); ++i){parab[i-max+lim]=avgphi[i]; ispar=is_parab(parab, parsize, lim);} else ispar=1;
00419
00420
00421 if (ispar == 0 )
00422 {
00423 for (k=0; k<=2; ++k) for (l=0; l<=2; ++l) for (i=(max-lim); i<=(max+lim); ++i) akl[k][l]=akl[k][l]+wg[i-(max-lim)]*pow((long double)rc[i], k+l);
00424 for (k=0; k<=2; ++k) for (i=(max-lim); i<=(max+lim); ++i) bl[k]=bl[k]+wg[i-(max-lim)]*pow((long double)rc[i], k)*(long double)avgphi[i];
00425
00426
00427
00428 long double det=akl[0][0]*(akl[1][1]*akl[2][2]-akl[2][1]*akl[1][2]) - akl[1][0]*(akl[2][2]*akl[0][1]-akl[2][1]*akl[0][2]) + akl[2][0]*(akl[1][2]*akl[0][1]-akl[1][1]*akl[0][2]);
00429 long double invmat[3][3];
00430
00431 invmat[0][0]=(akl[2][2]*akl[1][1]-akl[2][1]*akl[1][2])/det;
00432 invmat[1][0]=-(akl[2][2]*akl[0][1]-akl[2][1]*akl[0][2])/det; invmat[0][1]=invmat[1][0];
00433 invmat[2][0]=(akl[1][2]*akl[0][1]-akl[1][1]*akl[0][2])/det; invmat[0][2]=invmat[2][0];
00434 invmat[1][1]=(akl[2][2]*akl[0][0]-akl[2][0]*akl[0][2])/det;
00435 invmat[2][1]=-(akl[1][2]*akl[0][0]-akl[1][0]*akl[0][2])/det; invmat[1][2]=invmat[2][1];
00436 invmat[2][2]=(akl[1][1]*akl[0][0]-akl[1][0]*akl[0][1])/det;
00437
00438
00439 for (k=0; k<=2; ++k) cof[k]=0.0;
00440 for (k=0; k<=2; ++k) for (l=0; l<=2; ++l) cof[l]=cof[l]+invmat[k][l]*bl[k];
00441 double rad_ip=(double)(-cof[1]/cof[2]/2.0);
00442
00443 *rsun_lf=(double)rad_ip;
00444 status_res=0;
00445 }
00446 else
00447 {
00448 status_res=1;
00449 }
00450
00451 }
00452
00453
00454
00455
00456 if (method == 0)
00457 {
00458 double *rad_ipa=(double *)(malloc(nphi*sizeof(double)));
00459
00460 for (j=0; j<nphi; ++j){
00461
00462 for (i=0; i<nr; ++i) avgphi[i]=imrphi[j*nr+i];
00463 for (k=0; k<=2; ++k) for (l=0; l<=2; ++l) akl[k][l]=0.0;
00464 for (k=0; k<=2; ++k) bl[k]=0.0;
00465
00466 fmax=0.0; max=0;
00467 for (i=0; i<nr; ++i) if (avgphi[i] > fmax){fmax=avgphi[i]; max=i;}
00468
00469 if ((max-lim) >= 0 && (max+lim) < nr){for (i=(max-lim); i<=(max+lim); ++i)parab[i-max+lim]=avgphi[i]; ispar=is_parab(parab, parsize, lim);} else ispar=1;
00470
00471 if (ispar == 0)
00472 {
00473 for (k=0; k<=2; ++k) for (l=0; l<=2; ++l) for (i=(max-lim); i<=(max+lim); ++i) akl[k][l]=akl[k][l]+wg[i-(max-lim)]*pow((long double)rc[i], k+l);
00474 for (k=0; k<=2; ++k) for (i=(max-lim); i<=(max+lim); ++i) bl[k]=bl[k]+wg[i-(max-lim)]*pow((long double)rc[i], k)*(long double)avgphi[i];
00475
00476
00477
00478 long double det=akl[0][0]*(akl[1][1]*akl[2][2]-akl[2][1]*akl[1][2]) - akl[1][0]*(akl[2][2]*akl[0][1]-akl[2][1]*akl[0][2]) + akl[2][0]*(akl[1][2]*akl[0][1]-akl[1][1]*akl[0][2]);
00479 long double invmat[3][3];
00480 invmat[0][0]=(akl[2][2]*akl[1][1]-akl[2][1]*akl[1][2])/det;
00481 invmat[1][0]=-(akl[2][2]*akl[0][1]-akl[2][1]*akl[0][2])/det; invmat[0][1]=invmat[1][0];
00482 invmat[2][0]=(akl[1][2]*akl[0][1]-akl[1][1]*akl[0][2])/det; invmat[0][2]=invmat[2][0];
00483 invmat[1][1]=(akl[2][2]*akl[0][0]-akl[2][0]*akl[0][2])/det;
00484 invmat[2][1]=-(akl[1][2]*akl[0][0]-akl[1][0]*akl[0][2])/det; invmat[1][2]=invmat[2][1];
00485 invmat[2][2]=(akl[1][1]*akl[0][0]-akl[1][0]*akl[0][1])/det;
00486
00487
00488 for (k=0; k<=2; ++k) cof[k]=0.0;
00489 for (k=0; k<=2; ++k) for (l=0; l<=2; ++l) cof[l]=cof[l]+invmat[k][l]*bl[k];
00490 rad_ipa[j]=(double)(-cof[1]/cof[2]/2.0);
00491
00492 }
00493 else
00494 {
00495 rad_ipa[j]=NAN;
00496 }
00497 }
00498
00499
00500
00501 double rad_ipv=0.0;
00502 double rad_count=0.0;
00503 for (i=0; i<nphi; ++i)
00504 {
00505 if (!isnan(rad_ipa[i])) if (fabs(rad_ipa[i]-rad) < limit_var){rad_ipv+=rad_ipa[i]; rad_count=rad_count+1.0;}
00506 }
00507
00508
00509 if (rad_count/(double)nphi > percent_good){*rsun_lf=(double)(rad_ipv/rad_count); status_res=0;} else {status_res=1;}
00510
00511 free(rad_ipa);
00512 }
00513
00514
00515 if (status_res == 1){*x0_lf=NAN; *y0_lf=NAN;}
00516 free_mem(&memory);
00517
00518 return status_res;
00519
00520 }
00521
00522 void free_mem(struct mempointer *memory)
00523 {
00524 free(memory->imhp);
00525 free(memory->imro);
00526 free(memory->mask_p);
00527 free(memory->image);
00528
00529 free(memory->avgphi);
00530 free(memory->xrp);
00531 free(memory->yrp);
00532 free(memory->imrphi);
00533 free(memory->rc);
00534 free(memory->phic);
00535 free(memory->parab);
00536 free(memory->cnorm);
00537 free(memory->ierror);
00538 free(memory->imcp);
00539
00540
00541 return;
00542 }
00543
00544
00545
00546 int is_parab(double *arr, int n, int nmax)
00547 {
00548 int i;
00549 int status=0;
00550
00551 if (nmax < n)
00552 {
00553 for (i=(nmax+1); i<n; ++i)
00554 {
00555 if (arr[i] >= arr[i-1]) status=1;
00556 }
00557 for (i=0; i<nmax; ++i)
00558 {
00559 if (arr[i+1] <= arr[i]) status=1;
00560 }
00561 }
00562 else
00563 {
00564 status=1;
00565 }
00566 return status;
00567 }
00568
00569
00570
00571
00572 void cross_corr(int nx, int ny, double *imhp, double *imro)
00573
00574 {
00575
00576
00577 double a[nx][ny];
00578 double b[nx][ny];
00579
00580
00581 fftw_complex ac[nx][ny/2+1], bc[nx][ny/2+1];
00582 fftw_plan p;
00583 long i,j;
00584
00585 double scale=1./((double)(nx*ny));
00586
00587
00588 #pragma omp parallel for private(i,j)
00589 for (j=0; j<ny; ++j)
00590 for (i=0; i<nx; ++i)
00591 {
00592 a[i][j]=(double)imhp[j*nx+i];
00593 b[i][j]=(double)imro[j*nx+i];
00594 }
00595
00596
00597
00598 p = fftw_plan_dft_r2c_2d(nx, ny, &a[0][0], &ac[0][0], FFTW_ESTIMATE);
00599 fftw_execute(p);
00600 fftw_destroy_plan(p);
00601
00602
00603
00604 p = fftw_plan_dft_r2c_2d(nx, ny, &b[0][0], &bc[0][0], FFTW_ESTIMATE);
00605 fftw_execute(p);
00606 fftw_destroy_plan(p);
00607
00608
00609
00610
00611 #pragma omp parallel for private(i,j)
00612 for (i = 0; i < nx; ++i){
00613 for (j = 0; j < ny/2+1; ++j){
00614 ac[i][j]=ac[i][j]*conj(bc[i][j])*scale*scale;
00615 }
00616 }
00617
00618
00619 p = fftw_plan_dft_c2r_2d(nx, ny, &ac[0][0], &b[0][0], FFTW_ESTIMATE);
00620 fftw_execute(p);
00621 fftw_destroy_plan(p);
00622
00623
00624
00625 #pragma omp parallel for private(i,j)
00626 for (i = 0; i < ny; ++i){
00627 for (j = 0; j < nx; ++j){
00628 imro[j*nx+i]=b[(i+nx/2) % nx][(j+ny/2) % ny];
00629 }
00630 }
00631
00632
00633 }
00634
00635
00636
00637
00638
00639
00640