HiVector DriftCorrect::Solve(const HiVector &d) { ostringstream hist; _data = d; if ( _skipFit || (!gotGoodLines(d))) { _b2 = _data; _coefs = HiVector(4, 0.0); _uncert = _coefs; _cc = HiVector(2, 0.0); _chisq = 0.0; if ( !gotGoodLines(d) ) { hist << "NotEnoughLines(GoodLines[" << goodLines(d) << "],MinimumLines[" << _minLines << "]);"; } hist << "SkipFit(TRUE: Not using LMFit)"; _history.add(hist.str()); } else { hist << "Fit("; _b2 = HiVector(goodLines(_data)); if ( success(curvefit()) ) { _coefs = coefs(); _uncert = uncert(); hist << "Solved,#Iters[" << nIterations() << "],ChiSq[" << Chisq() << "],DoF[" << DoF() << "])"; _history.add(hist.str()); _history.add("a0("+ToString(_coefs[0])+"+-"+ToString(_uncert[0])+")"); _history.add("a1("+ToString(_coefs[1])+"+-"+ToString(_uncert[1])+")"); _history.add("a2("+ToString(_coefs[2])+"+-"+ToString(_uncert[2])+")"); _history.add("a3("+ToString(_coefs[3])+"+-"+ToString(_uncert[3])+")"); } else { // Punt, fit a straight line to the data _cc = poly_fit(d); HiVector a(4); a[0] = _cc[0]; a[1] = _cc[1]; a[2] = 0.0; a[3] = 0.0; _coefs = a; hist << "Failed::Reason("<< statusstr() << "),#Iters[" << nIterations() << "])"; _history.add(hist.str()); _history.add("a0("+ToString(_coefs[0])+")"); _history.add("a1("+ToString(_coefs[1])+")"); _history.add("a2("+ToString(_coefs[2])+")"); _history.add("a3("+ToString(_coefs[3])+")"); if ( _useLinFit ) { _history.add("OnFailureUse(LinearFit(Zf))"); } else { _skipFit = true; _history.add("OnFailureUse(ZfBuffer)"); } } } return (Yfit()); }
bvec lorentzian_fit(double *x,bvec y) { bvec d=poly_fit(x,1/y,2); bvec out(3,y.nboot,y.njack); //for(int i=0;i<3;i++) cout<<i<<" = "<<d[i]<<endl; out[1]=-0.5*d[1]/d[2]; //x0 out[0]=1/(d[0]-sqr(out[1])*d[2]); //N out[2]=1/sqrt(d[2]*out[0]); //sigma //cout<<"arg:"<<d[2]*out[0]<<endl; //for(int i=0;i<3;i++) cout<<i<<" out= "<<out[i]<<endl; return out; }
/** * @brief Compute the initial guess of the fit * * This method provides the non-linear fit with an initial guess of the * solution. It involves a linear fit to the latter half of the data to * provide the first two coefficents, the difference of the averages of the * residuals at both ends of the data set and 5 times the last line time as * the final (fourth) element...a bit involved really. * * @return NLVector 4-element vector of the initial guess coefficients */ NonLinearLSQ::NLVector DriftCorrect::guess() { int n = _data.dim(); int nb = n - _badLines; HiVector b1 = _data.subarray(0, nb-1); LowPassFilterComp gfilter(b1, _history, _sWidth, _sIters); int nb2 = nb/2; _b2 = gfilter.ref(); HiVector cc = poly_fit(_b2.subarray(nb2,_b2.dim()-1), nb2-1); // Compute the 3rd term guess by getting the average of the residual // at both ends of the data set. Statistics s; // Get the head of the data set int n0 = MIN(nb, 20); for ( int k = 0 ; k < n0 ; k++ ) { double d = _b2[k] - (cc[0] + cc[1] * _timet(k)); s.AddData(&d, 1); } double head = s.Average(); // Get the tail of the data set s.Reset(); n0 = (int) (0.9 * nb); for ( int l = n0 ; l < nb ; l++ ) { double d = _b2[l] - (cc[0] + cc[1] * _timet(l)); s.AddData(&d, 1); } double tail = s.Average(); // Populate the guess with the results NLVector g(4, 0.0); g[0] = cc[0]; g[1] = cc[1]; g[2] = head-tail; g[3] = -5.0/_timet(nb-1); _guess = g; _history.add("Guess["+ToString(_guess[0])+ ","+ ToString(_guess[1])+ ","+ ToString(_guess[2])+ ","+ ToString(_guess[3])+ "]"); return (g); }
int ws_inv_cmod5(double sigma0, double phi0, double theta0, double *wnd1, double *wnd2, double min_ws, double max_ws, int npts, double hh) { // ws_cmod5 will return a 2-element array where the first element is the sigma0 // that you'd get at min_ws, and the second element is the sigma0 that you get // at max_ws; // (phi0 is phi_diff, the diff between wind_dir and r_look, and theta0 is incidence angle) // Note that the 0.0 (last parameter) is r_look according to ws_cmod5, but the ws_cmod5 function // doesn't make use of it ...or more accurately, it's already built into the phi0 value. g_assert(max_ws > min_ws); g_assert(npts > 0); double *wd; int i; // Make an npts-element array of windspeeds that range from min_ws to max_ws linearly wd = maken(min_ws, max_ws, npts); g_assert(wd != NULL); // Calculate an npts-element array of normalized radar cross section (NRCS) using // the CMOD5 algorithm double *sg0 = ws_cmod5(wd, npts, phi0, theta0, 0.0); // Returned sg0[] has npts elements in it g_assert(sg0 != NULL); // See lines 118-123 in ws_inv_cmod5.pro // NOTE: The CMOD5 and CMOD4 algorithms need an adjustment when the polarization // is HH (since the original algorithms were developed for VV polarization only) // hh == -3 when polarization is VV, hh == 0.6 when polarization is HH // FIXME: Add cases for hh eq to -1 and -2 double rr = (hh > 0.0) ? ws_pol_ratio(theta0, hh) : 1.0; sigma0 = (hh != -3) ? sigma0 / rr : sigma0; // HH adjustment or not // If sigma0 is lower than what you'd get at minimum windspeed, then set the windspeed to // the minimum and return. (Line 129) double min_nrcs = arr_min(sg0, npts); // Min should be sg0[0], but make sure... if (sigma0 < min_nrcs) { *wnd1 = wd[0]; *wnd2 = WND1_IS_MINIMUM_WIND; FREE(wd); FREE(sg0); return 0; } // Create sign of differences array int ct=0; double *s = (double *)MALLOC(sizeof(double) * npts); for (i=0; i<npts; i++) { s[i] = SIGN(sg0[i] - sigma0); ct += s[i] == 0 ? 1 : 0; s[i] = (ct > 0 && s[i] == 0) ? 1.0 : s[i]; } // Count the sign changes ct = 0; int ww = -1; // Where first sign change occurs int ww2 = -1; // Where second sign change occurs for (i=1; i<npts; i++) { ct += (s[i] != s[i-1]) ? 1 : 0; ww = (ct > 0 && ww < 0) ? i : ww; ww2 = (ct > 0 && ww > 0 && ww2 < 0) ? i : ww2; } // Calculate wind for the 3 cases (no sign changes, one sign change, two sign changes, and other) switch(ct) { case 0: { // No sign changes means sigma0 > max(sg0[]) int nn = npts; double max_sg0 = arr_max(sg0, npts); int idx_first_max = -1; int *w = (int *)CALLOC(nn, sizeof(int)); int wx = 0; for (i=0; i<npts; i++) { if (sg0[i] >= max_sg0) { idx_first_max = (idx_first_max < 0) ? i : idx_first_max; w[wx++] = i; // Collect indices of max's } } if (idx_first_max == nn - 1) { // Last element was the largest element, so send back max wind *wnd1 = wd[nn-1]; *wnd2 = WND_FROM_MAX_SIGMA0; } else { int ix1 = (w[0] - 1 >= 0) ? w[0] - 1 : 0; int ix2 = w[0]; int ix3 = w[0] + 1; double fit1; double *f1 = poly_fit(wd, sg0, ix1, ix2, ix3, 2, &fit1); *wnd1 = (f1[1]+sqrt(f1[1]*f1[1]-4.0*f1[2]*(f1[0]-sg0[ix2])))/2/f1[2]; *wnd2 = WND_FROM_MAX_SIGMA0; } FREE(w); } break; case 1: { // Single solution int ix1 = ww; int ix2 = (ww+1) > npts - 1 ? npts - 1 : ww+1; int ix3 = (ww+2) > npts - 1 ? npts - 1 : ww+2; double fit1; double *f1 = poly_fit(wd, sg0, ix1, ix2, ix3, 2, &fit1); *wnd1 = (f1[1]+sqrt(f1[1]*f1[1]-4.0*f1[2]*(f1[0]-sigma0)))/2/f1[2]; *wnd2 = WND1_IS_ONLY_SOLUTION; } break; case 2: { // Two solutions (usually lowest answer of the two is best answer) int ix1 = ww; int ix2 = (ww+1) > npts - 1 ? npts - 1 : ww+1; int ix3 = (ww+2) > npts - 1 ? npts - 1 : ww+2; int ix4 = ww2; int ix5 = (ww2+1) > npts - 1 ? npts - 1 : ww2+1; int ix6 = (ww2+2) > npts - 1 ? npts - 1 : ww2+2; double fit1, fit2; double *f1 = poly_fit(wd, sg0, ix1, ix2, ix3, 2, &fit1); double *f2 = poly_fit(wd, sg0, ix4, ix5, ix6, 2, &fit2); *wnd1 = (f1[1]+sqrt(f1[1]*f1[1]-4.0*f1[2]*(f1[0]-sigma0)))/2/f1[2]; *wnd2 = (f2[1]+sqrt(f2[1]*f2[1]-4.0*f2[2]*(f2[0]-sigma0)))/2/f2[2]; } break; default: *wnd1 = WND_FROM_MAX_SIGMA0; *wnd2 = WND_FROM_MAX_SIGMA0; break; } FREE(s); FREE(wd); FREE(sg0); return 0; }
int main(int narg,char **arg) { if(narg<2) { fprintf(stderr,"Error, use: %s file\n",arg[0]); exit(1); } grace out("fit_xmax.xmg"); FILE *fin=open_file(arg[1],"r"); const char color[3][1024]={"blue","green","red"}; int nmu; read_formatted_from_file_expecting((char*)&nmu,fin,"%d","nmu"); double muI[nmu],muI2[nmu]; bvec xmax[3];xmax[0]=xmax[1]=xmax[2]=bvec(nmu,99,2); for(int imu=0;imu<nmu;imu++) { char path[1024]; read_formatted_from_file((char*)&(muI[imu]),fin,"%lg","path"); read_formatted_from_file(path,fin,"%s","path"); for(int det=0;det<3;det++) xmax[det][imu]=get_xmax(path,det); muI2[imu]=sqr(muI[imu]); if(muI[imu]<0) muI2[imu]*=-1; } for(int det=0;det<3;det++) { bvec par_fit4=poly_fit(muI2,xmax[det],2); bvec par_fit6=poly_fit(muI2,xmax[det],3); bvec par_fitR=rat21_fit(par_fit4,muI2,xmax[det]); cout<<chi2_pol(par_fit4,muI2,xmax[det])/(nmu-3)<<endl; cout<<chi2_pol(par_fit6,muI2,xmax[det])/(nmu-4)<<endl; { double p[4]={par_fitR[0][nboot],par_fitR[1][nboot],par_fitR[2][nboot],par_fitR[3][nboot]}; cout<<chi2_rat21(p)/(nmu-4)<<endl; } int nfit=300; double mu2F[nfit+1],mu2F_min=-0.5,mu2F_max=muI2[nmu-1]; bvec xmaxF4(nfit+1,99,2); bvec xmaxF6(nfit+1,99,2); bvec xmaxFR(nfit+1,99,2); for(int ifit=0;ifit<=nfit;ifit++) { double x=mu2F[ifit]=mu2F_min+(mu2F_max-mu2F_min)/nfit*ifit; xmaxF4[ifit]=pol(par_fit4,x); xmaxF6[ifit]=pol(par_fit6,x); for(int iboot=0;iboot<=nboot;iboot++) { double p[4]={par_fitR[0][iboot],par_fitR[1][iboot],par_fitR[2][iboot],par_fitR[3][iboot]}; xmaxFR[ifit].data[iboot]=ratfun21(x,p); } } out.set(2,"none","square"); out.print_graph(muI2,xmax[det]); out.new_set(); out.set(1,color[det]); out.polygon(mu2F,xmaxF4); out.new_set(); out.set(1,color[det]); out.polygon(mu2F,xmaxF6); out.new_set(); out.set(1,color[det]); out.polygon(mu2F,xmaxFR); out.new_set(); cout<<par_fit4[1]<<endl; cout<<par_fit6[1]<<endl; cout<<par_fitR[1]-par_fitR[3]*par_fitR[0]<<endl; } return 0; }