source: Sophya/trunk/Poubelle/archTOI.old/starmatcher.cc@ 577

Last change on this file since 577 was 577, checked in by ansari, 26 years ago

SST

File size: 27.4 KB
RevLine 
[555]1// starmatcher.cc
2// Eric Aubourg CEA/DAPNIA/SPP novembre 1999
3
[534]4#include "starmatcher.h"
5#include "sststarfinder.h"
6#include "toimanager.h"
7#include "archexc.h"
[555]8#include "archparam.h"
9#include "gondolageom.h"
[577]10#include "polfitclip.h"
[534]11
[577]12#define STARDUMP
13
[534]14extern "C" {
15#include "aa_hadec.h"
[555]16#define NRANSI
17#include "nrutil.h"
18
[577]19void lfit(double x[], double y[], double sig[], int ndat, double a[], int ia[],
20 int ma, double **covar, double *chisq, void (*funcs)(double, double [], int));
[555]21
[577]22void polfunc(double x, double afunc[], int ma);
23void sinfunc(double x, double afunc[], int ma);
[534]24}
25
[577]26void polfunc(double x, double afunc[], int ma) {
[555]27 afunc[1] = 1;
28 for (int i=2; i<=ma; i++)
29 afunc[i] = afunc[i-1]*x;
30}
31
[577]32void sinfunc(double x, double afunc[], int /*ma*/) {
[555]33 afunc[1] = cos(x);
34 afunc[2] = sin(x);
35 afunc[3] = 1;
36}
37
38
[577]39double polval(double x, double a[], int ma);
[555]40
[577]41double polval(double x, double a[], int ma) {
42 double r = a[ma];
[555]43 for (int i=ma-1; i>0; i--) {
44 r = r*x+a[i];
45 }
46 return r;
47}
48
[534]49#include <stdio.h>
50
[555]51#ifdef __DECCXX
52#define SWAP
53#endif
54#if defined(Linux) || defined(linux)
55#define SWAP
56#endif
57
58typedef unsigned int4 uint_4;
59typedef unsigned short uint_2;
60
61static inline void bswap4(void* p)
62{
63 uint_4 tmp = *(uint_4*)p;
64 *(uint_4*)p = ((tmp >> 24) & 0x000000FF) |
65 ((tmp >> 8) & 0x0000FF00) |
66 ((tmp & 0x0000FF00) << 8) |
67 ((tmp & 0x000000FF) << 24);
68}
69
70static inline void bswap2(void* p)
71{
72 uint_2 tmp = *(uint_2*)p;
73 *(uint_2*)p = ((tmp >> 8) & 0x00FF) |
74 ((tmp & 0x00FF) << 8);
75}
76
77
78#define azimuthPendul "azimuthPendul"
79#define anglePendul "anglePendul"
80#define azimuthAxis "azimuthAxis"
81#define elvAxis "deltaZenith"
82#define alphaAxis "alphaZenith"
83#define deltaAxis "deltaZenith"
84#define azimuthFPC "azimuthFPC"
85#define elvFPC "elvFPC"
86#define alphaFPC "alphaFPC"
87#define deltaFPC "deltaFPC"
88#define azimuthBolo "azimuthBolo"
89#define elvBolo "elvBolo"
90#define alphaBolo "alphaBolo"
91#define deltaBolo "deltaBolo"
92#define azimuthSST "azimuthSST"
93#define elvSST "elvSST"
94#define alphaSST "alphaSST"
95#define deltaSST "deltaSST"
96
97
[534]98StarMatcher::StarMatcher() {
[555]99 possibleTOIs.insert(TOI(azimuthSST, TOI::unspec, "interp", "degrees","sstmatch"));
100 possibleTOIs.insert(TOI(elvSST, TOI::unspec, "interp", "degrees","sstmatch"));
101 possibleTOIs.insert(TOI(alphaSST, TOI::unspec, "interp", "hours","sstmatch"));
102 possibleTOIs.insert(TOI(deltaSST, TOI::unspec, "interp", "degrees","sstmatch"));
103 possibleTOIs.insert(TOI(azimuthAxis, TOI::unspec, "interp", "degrees","sstmatch"));
104 possibleTOIs.insert(TOI(elvAxis, TOI::unspec, "interp", "degrees","sstmatch"));
105 possibleTOIs.insert(TOI(alphaAxis, TOI::unspec, "interp", "hours","sstmatch"));
106 possibleTOIs.insert(TOI(deltaAxis, TOI::unspec, "interp", "degrees","sstmatch"));
107 possibleTOIs.insert(TOI(azimuthPendul, TOI::unspec, "interp", "degrees","sstmatch"));
108 possibleTOIs.insert(TOI(anglePendul, TOI::unspec, "interp", "degrees","sstmatch"));
109 possibleTOIs.insert(TOI(azimuthFPC, TOI::unspec, "interp", "degrees", "sstmatch"));
110 possibleTOIs.insert(TOI(elvFPC, TOI::unspec, "interp", "degrees", "sstmatch"));
111 possibleTOIs.insert(TOI(alphaFPC, TOI::unspec, "interp", "hours", "sstmatch"));
112 possibleTOIs.insert(TOI(deltaFPC, TOI::unspec, "interp", "degrees", "sstmatch"));
113 possibleTOIs.insert(TOI(azimuthBolo, TOI::all, "interp", "degrees", "sstmatch"));
114 possibleTOIs.insert(TOI(elvBolo, TOI::all, "interp", "degrees", "sstmatch"));
115 possibleTOIs.insert(TOI(alphaBolo, TOI::all, "interp", "hours", "sstmatch"));
116 possibleTOIs.insert(TOI(deltaBolo, TOI::all, "interp", "degrees", "sstmatch"));
117
[534]118 FILE* f;
119
120 f = fopen("gsc7.dat","r");
121 if (!f) throw ArchExc("Error opening gsc7.dat");
122
[555]123 int4 n4;
124 fread(&n4, sizeof(int4), 1 , f);
125
126#ifdef SWAP
127 bswap4(&n4);
128#endif
129 nstars = n4;
130
[534]131 stars = new gscStar[nstars];
[555]132 char* compdata = new char[10*nstars];
133 fread(compdata, 10, nstars, f);
[534]134 fclose(f);
[555]135
136 for (int i=0; i<nstars; i++) {
137#ifdef SWAP
138 ((char*)&(stars[i].ra))[0] = compdata[10*i+3];
139 ((char*)&(stars[i].ra))[1] = compdata[10*i+2];
140 ((char*)&(stars[i].ra))[2] = compdata[10*i+1];
141 ((char*)&(stars[i].ra))[3] = compdata[10*i+0];
142 ((char*)&(stars[i].dec))[0] = compdata[10*i+7];
143 ((char*)&(stars[i].dec))[1] = compdata[10*i+6];
144 ((char*)&(stars[i].dec))[2] = compdata[10*i+5];
145 ((char*)&(stars[i].dec))[3] = compdata[10*i+4];
146 ((char*)&(stars[i].mag))[0] = compdata[10*i+9];
147 ((char*)&(stars[i].mag))[1] = compdata[10*i+8];
148#else
149 ((char*)&(stars[i].ra))[0] = compdata[10*i+0];
150 ((char*)&(stars[i].ra))[1] = compdata[10*i+1];
151 ((char*)&(stars[i].ra))[2] = compdata[10*i+2];
152 ((char*)&(stars[i].ra))[3] = compdata[10*i+3];
153 ((char*)&(stars[i].dec))[0] = compdata[10*i+4];
154 ((char*)&(stars[i].dec))[1] = compdata[10*i+5];
155 ((char*)&(stars[i].dec))[2] = compdata[10*i+6];
156 ((char*)&(stars[i].dec))[3] = compdata[10*i+7];
157 ((char*)&(stars[i].mag))[0] = compdata[10*i+8];
158 ((char*)&(stars[i].mag))[1] = compdata[10*i+9];
159#endif
160 }
161
162 delete[] compdata;
[534]163
164 TOIProducer* prod = TOIManager::findTOIProducer(TOI("sstStarCount"));
165 if (!prod) {
166 cerr << "StarMatcher : cannot find producer for sstStarCount" << endl;
167 exit(-1);
168 }
169
170 SSTStarFinder* sprod = dynamic_cast<SSTStarFinder*>(prod);
171 if (!sprod) {
172 cerr << "StarMatcher : producer for sstStarCount is not a SSTStarFinder" << endl;
173 exit(-1);
174 }
175
[555]176 lastSeq = 0;
177
[534]178 sprod->registerProcessor(this);
179
180}
181
182string StarMatcher::getName() {
183 return("StarMatcher 1.0");
184}
185
[555]186#ifdef STARDUMP
[534]187static ofstream starstream("stars.dat");
[555]188static ofstream cstarstream("cstars.dat");
189static ofstream pendstream("pendul.dat");
190#endif
[577]191static ofstream logstream("starmatch.log");
[534]192
193void StarMatcher::dataFeed(SSTEtoile const& x) {
[555]194 lastStars.push_back(x);
[534]195}
196
[555]197static long lastCleanSave=0;
[534]198
[555]199void nrerror(char * error_text) {
200 throw(string(error_text));
201}
[534]202
203
[555]204void StarMatcher::processStars() {
205
206 if (lastStars.empty()) return;
207
208 map<TOI, TOIProducer*> & m = (*neededTOIs.begin()).second;
209 while (!lastStars.empty()) {
210 SSTEtoile lastStar = lastStars.front();
211 lastStars.pop_front();
212
213 double lat, lon, ts, alpha, delta, az, rspeed;
214
215 long snstar = (long) lastStar.TEchan;
[534]216
[555]217 for (map<TOI, TOIProducer*>::iterator i = m.begin(); i != m.end(); i++) {
218 TOI const& inToi = (*i).first;
219 TOIProducer* prod = (*i).second;
220 if (inToi.name == "latitude") lat = prod->getValue(snstar, inToi);
221 if (inToi.name == "longitude") lon = prod->getValue(snstar, inToi);
222 if (inToi.name == "tsid") ts = prod->getValue(snstar, inToi);
223 if (inToi.name == "alphaSST") alpha = prod->getValue(snstar, inToi);
224 if (inToi.name == "deltaSST") delta = prod->getValue(snstar, inToi);
225 if (inToi.name == "azimuthSST") az = prod->getValue(snstar, inToi);
226 if (inToi.name == "rotSpeed") rspeed = prod->getValue(snstar, inToi);
227 }
228
229 // correct azimuth using fractional value of TEchan
230
231 az -= rspeed * archParam.acq.perEch * (lastStar.TEchan-snstar);
232
233 // find all stars +- 2 deg boresight
234 double dist = 2;
235 double dmin = delta - dist; if (dmin<-90) dmin=-90;
236 double dmax = delta + dist; if (dmax> 90) dmax= 90;
237 double amin = alpha - dist / cos(delta * 3.1415926/180) / 15.;
238 if (amin<0) amin += 24;
239 double amax = alpha + dist / cos(delta * 3.1415926/180) / 15.;
240 if (amax>24) amax -= 24;
241
242 int a,b,c;
243 a=0; c=nstars-1;
244 while (a+1<c) {
245 b = (a+c)/2;
246 if (stars[b].dec < dmin) a=b; else c=b;
247 }
248 int imin = a;
249 a=0; c=nstars;
250 while (a+1<c) {
251 b = (a+c)/2;
252 if (stars[b].dec < dmax) a=b; else c=b;
253 }
254 int imax = c;
255
256 for (int i=imin; i<=imax; i++) {
257 if (stars[i].ra >= amin && stars[i].ra <= amax) {
258 double ha = (ts/3600. - stars[i].ra) * 15. * 3.1415926/180.;
259 double elv, azim;
260 hadec_aa(lat * 3.1415926/180., ha, stars[i].dec * 3.1415926/180.,
261 &elv, &azim);
262 elv *= 180/3.1415926;
263 azim *= 180/3.1415926;
264 if (azim<0) azim += 360;
265
266 double da = azim-az; if (da>360) da -= 360;
267 if (da < -0.6 || da > 0.4) continue;
268 double elv0 = elv - 1.41/45. * lastStar.NoDiode;
269 if (fabs(elv0-GondolaGeom::elevSST0) > 0.25) continue; // Might be too strong
270
271#ifdef STARDUMP
272 starstream << setprecision(10) << lastStar.TEchan << " " <<
273 lastStar.NoDiode << " " <<
274 alpha << " " << delta << " " <<
275 az << " " <<
276 stars[i].ra << " " << stars[i].dec << " " <<
277 elv << " " << azim << " " <<
278 lastStar.InpCurrent << " " << stars[i].mag << "\n";
279#endif
280
281 matchStar s;
282 lastSeq++;
283 s.SN = lastStar.TEchan;
284 s.raGSC = stars[i].ra;
285 s.decGSC = stars[i].dec;
286 s.azGSC = azim;
287 s.elvGSC = elv;
288 s.nDiode = lastStar.NoDiode;
289 s.ok = true;
290 s.seq = lastSeq;
291 s.lon = lon;
292 s.lat = lat;
293 s.ts = ts;
294
295 matchStars.push_back(s);
296 }
297 }
[534]298 }
[555]299
300 // new set of matched stars... Clean, and get parameters...
[577]301 // We don't want more than 30 seconds of data
[555]302
303 if (matchStars.empty()) return;
304
305
306 double snEnd = matchStars.back().SN;
307 deque<matchStar>::iterator it;
308 for (it = matchStars.begin(); it!=matchStars.end(); it++) {
[577]309 if ((snEnd - (*it).SN)*archParam.acq.perEch < 30 ||
310 (*it).seq > lastCleanSave)
[555]311 break;
312 }
313 if (it != matchStars.begin()) {
[577]314 it--;
315 }
316 if (it != matchStars.begin()) {
[555]317 matchStars.erase(matchStars.begin(), it);
318 }
319
320 // we want to clean on the last 5 seconds of data.
321
322 int nskip=0;
323 for (it = matchStars.begin(); it!=matchStars.end(); it++) {
[577]324 if ((snEnd - (*it).SN)*archParam.acq.perEch < 5)
[555]325 break;
326 nskip++;
327 }
328
329 if (matchStars.size()-nskip < 30) return; // pas assez d'etoiles
330
331 // we remove "bursts" of stars, ie more than 4 stars in the same samplenum
332
333 long lastSN = 0;
334 deque<matchStar>::iterator lastIt = it;
335 long burstLen = 0;
336 for (deque<matchStar>::iterator it1 = it ; it1!=matchStars.end(); it1++) {
337 matchStar s = (*it1);
338 if ((long) s.SN == lastSN) {
339 burstLen++;
340 continue;
341 }
342 if (burstLen >= 4) {
343 for (deque<matchStar>::iterator it2=lastIt; it2 != it1; it2++) {
[577]344 //if ((*it2).ok)
345 // logstream << " kill " << (*it2).seq << " " << setprecision(11) << (*it2).SN << " burst" << '\n';
[555]346 (*it2).ok=false;
347 }
348 }
349 burstLen = 1;
350 lastIt = it1;
351 lastSN = s.SN;
352 }
353 // we fit the data to a polynomial, with clipping...
354
[577]355 //double* sn = ::vector(1, matchStars.size());
356 double* elv0 = ::vector(1, matchStars.size());
357 double* azi = ::vector(1, matchStars.size());
358 double* sig = ::vector(1, matchStars.size());
359 //double* ae = ::vector(1, 3);
360 double* aa = ::vector(1, 3);
[555]361 int* ia = ivector(1, 3);
[577]362 double** cov = matrix(1, 3, 1, 3);
[555]363 int ndata;
364
[577]365 //long sn0 = matchStars.front().SN;
366 long sn0 = (*it).SN;
367 PolFitClip2 fitElvAz(matchStars.size(), 2); fitElvAz.setClip(0.1,0,2,3);
368 ndata = 0;
369
370 double oldAz = -1;
371 for (deque<matchStar>::iterator it1 = it ; it1!=matchStars.end(); it1++) {
372 matchStar s1 = (*it1);
373 if (!s1.ok) continue;
374 double az = s1.azGSC;
375 if (ndata > 0 && az - oldAz > 180) az -= 360;
376 if (ndata > 0 && az - oldAz < -180) az += 360;
377 fitElvAz.addData(s1.SN-sn0, s1.elvGSC - s1.nDiode*1.41/45., az);
378 oldAz = az;
379 ndata++;
380 }
381
382 double celv[3], caz[3];
383 if (fitElvAz.doFit(celv,caz)) return;
384 //if (fitElvAz.doFit()) return;
385
386 //logstream << "*** Fit sig=" << fitElvAz.getSigmaY() << " " << fitElvAz.getSigmaZ()
387 // << " n =" << fitElvAz.getNData() << " " << fitElvAz.getNDataUsed()
388 // << " SN :" << fitElvAz.getXMin() + sn0 << " - " << fitElvAz.getXMax() + sn0 << '\n';
389 //logstream << " sn0 = " << sn0 << "; snmin =" << fitElvAz.getXMin() + sn0 << "; snmax ="
390 // << fitElvAz.getXMax() + sn0 << '\n';
391 //logstream << " fitelv[x_] := " << celv[2] << " x^2 + " << celv[1] << " x + " << celv[0] << '\n';
392 //logstream << " fitaz[x_] := " << caz[2] << " x^2 + " << caz[1] << " x + " << caz[0] << '\n';
393
394 //if (fitElvAz.getSigmaY() > 0.05 || fitElvAz.getSigmaZ() > 0.05) return;
395 if (fitElvAz.getNDataUsed() < 5 ||
396 (double)fitElvAz.getNDataUsed()/fitElvAz.getNData() < .5) return;
397
398 double dcutElv = fitElvAz.getSigmaY()*3;
399 double dcutAz = fitElvAz.getSigmaZ()*3;
400
401 if (dcutElv < 0.05) dcutElv = 0.05;
402 if (dcutAz < 0.05) dcutAz = 0.05;
403
404 // don't kill borders of fit....
405 //if (matchStars.end() - it > 6)
406 // for (deque<matchStar>::iterator it1 = it+3 ; it1!=matchStars.end()-3; it1++) {
407 for (deque<matchStar>::iterator it1 = it ; it1!=matchStars.end(); it1++) {
408 matchStar sss = (*it1);
409 if (!sss.ok) continue;
410 if (fabs(fitElvAz.valueY(sss.SN-sn0)-(sss.elvGSC - sss.nDiode*1.41/45.)) > dcutElv) {
411 (*it1).ok = false;
412 //logstream << " kill " << sss.seq << " " << setprecision(11) << sss.SN << " "
413 // << fitElvAz.valueY(sss.SN-sn0)-(sss.elvGSC - sss.nDiode*1.41/45.) << '\n';
414 continue;
[555]415 }
[577]416 double daz = fitElvAz.valueZ(sss.SN-sn0) - sss.azGSC;
417 if (daz>=180) daz -= 360;
418 if (daz<-180) daz += 360;
419 if (fabs(daz) > dcutAz) (*it1).ok = false;
420 if (!(*it1).ok) {
421 //logstream << " kill " << sss.seq << " " << setprecision(11) << sss.SN << " "
422 // << fitElvAz.valueY(sss.SN-sn0)-(sss.elvGSC - sss.nDiode*1.41/45.) << " "
423 // << daz << '\n';
[555]424 }
425 }
[577]426
427 bool gotNewStars = false;
428 for (deque<matchStar>::iterator it1 = matchStars.begin() ; it1!=it; it1++) {
[555]429 if ((*it1).ok && (*it1).seq > lastCleanSave) {
[577]430 gotNewStars = true;
[555]431 lastCleanSave = (*it1).seq;
432#ifdef STARDUMP
433 cstarstream << (*it1).seq << "\n";
434#endif
435 posInfo info;
436 info.SN = (*it1).SN;
437 info.azStar = (*it1).azGSC;
438 info.elvStar = (*it1).elvGSC;
439 info.diodStar= (*it1).nDiode;
440 info.lon = (*it1).lon;
441 info.lat = (*it1).lat;
442 info.ts = (*it1).ts;
443 posInfos[info.SN] = info;
444 }
445 }
446
[577]447 if (!gotNewStars) return;
448
[555]449 // On a des etoiles nettoyees, on va trouver amplitude et phase du
450 // signal en elevation, ce qui va nous donner les deux angles d'Euler
451 // de la pendulation (au premier ordre en theta)
452
453 // Il faut avoir une periode entiere ou pas loin, sinon on ne peut
[577]454 // rien dire simplement.... -> we want to run on the last 18 seconds of
455 // data before the last fully cleaned star (it).
[555]456
[577]457 deque<matchStar>::iterator itstart;
[555]458
[577]459 for (itstart = matchStars.begin(); itstart != it; itstart++) {
460 if (((*it).SN - (*itstart).SN)*archParam.acq.perEch < 19)
461 break;
462 }
463
464 if (((*it).SN - (*itstart).SN)*archParam.acq.perEch < 15) return;
465
466
467 // it = matchStars.end(); it--;
468 // if (((*it).SN - matchStars.front().SN)*archParam.acq.perEch < 17) return;
469
470 // $CHECK$ utiliser plutot le SN moyen/median de tous les points effectivement utilises.
471 long snmid = ((*it).SN + (*itstart).SN)/2;
[534]472
[555]473 ndata=0;
[577]474 double snmean = 0;
475
476 logstream << "PendFit : " << setprecision(11) << (*itstart).SN << '-' << (*it).SN << " "
477 << setprecision(4)
478 << ((*it).SN - (*itstart).SN)*archParam.acq.perEch << " " ;
479
480 for (deque<matchStar>::iterator it1 = itstart ; it1!=it; it1++) {
481 matchStar st = *it1;
482 if (!st.ok) continue;
[555]483 ndata++;
[577]484 snmean += st.SN;
485 azi[ndata] = st.azGSC * 3.1415926/180;
486 elv0[ndata] = st.elvGSC - st.nDiode*1.41/45.;
[555]487 sig[ndata] = 0.01;
[534]488 }
[577]489 if (ndata) snmean /= ndata;
490
491 ia[1] = ia[2] = 1;
492 ia[3] = 0;
493 aa[3] = GondolaGeom::elevSST0;// do not fit elv0
[555]494
495 if (ndata<5) return;
[577]496 double chi2;
[555]497 try {
498 lfit(azi, elv0, sig, ndata, aa, ia, 3, cov, &chi2, sinfunc);
[577]499 } catch(string st) {
[555]500 return;
[534]501 }
502
[577]503 double cc = aa[1];
504 double ss = aa[2];
[555]505
[577]506 logstream << setprecision(11) << snmean << setprecision(4)
507 << " cs=" << cc << " " << ss << " chi2r=" << chi2/ndata
508 << " cov " << cov[1][1] << " " << cov[2][2] << '\n';
509
[555]510 // Get rid of bad fits. The cuts are rather ad hoc
511
512 //if (aa[3] < 39.64 || aa[3] > 39.68) return;
[577]513 if (chi2/ndata > 9) return;
[555]514 if (cov[1][1] > 0.0001) return;
515 if (cov[2][2] > 0.0001) return;
516
[577]517 double ampl = sqrt(cc*cc+ss*ss);
518 double phase = atan2(cc,ss)/(3.1415926/180);
[555]519
520
521 pendulInfo info;
[577]522 info.SN = snmean;
523 info.azPendul = 180-phase;
524 if (info.azPendul > 360) info.azPendul -= 360;
525 if (info.azPendul < 0) info.azPendul += 360;
[555]526 info.angPendul = ampl;
527 pendulInfos[info.SN] = info;
528
[577]529#ifdef STARDUMP
530 pendstream << setprecision(11) << snmean << " "
531 << setprecision(4) << ampl << " " << info.azPendul << " " << ndata << " " << chi2/ndata << " "
532 << cov[1][1] << " " << cov[2][2] << '\n';
533#endif
[555]534 /*
535 double snum = (matchStars.front().SN + matchStars.back().SN)/2-sn0;
536 if (snmin > snum || snmax < snum) return;
537 double elsst = polval(snum, ae, 3);
538 double azsst = polval(snum, aa, 3);
539
540 if (azsst > 360) azsst -= 360;
541 if (azsst < 0 ) azsst += 360;
542 */
543
544// for (set<TOI>::iterator i = producedTOIs.begin(); i!=producedTOIs.end(); i++) {
545// if ((*i).name == "azimuthSST") computedValue((*i), snum+sn0, azsst);
546// if ((*i).name == "elvSST") computedValue((*i), snum+sn0, elsst);
547// }
548
[577]549 //free_vector(sn, 1, matchStars.size());
[555]550 free_vector(elv0, 1, matchStars.size());
551 free_vector(azi, 1, matchStars.size());
552 free_vector(sig, 1, matchStars.size());
[577]553 //free_vector(ae, 1, 3);
[555]554 free_vector(aa, 1, 3);
555 free_ivector(ia, 1, matchStars.size());
556 free_matrix(cov, 1, 3, 1, 3);
557}
558
[577]559
560// $CHECK$ do a polynomial fit with several points...
[555]561int StarMatcher::getPendulInfo(double sampleNum, pendulInfo& info) {
[577]562
563 PolFitClip2 fitPendul(30,2);
564
[555]565 map<double, pendulInfo>::iterator i = pendulInfos.lower_bound(sampleNum);
566 if (i == pendulInfos.begin() && (*i).second.SN >= sampleNum) return -1;
567 if (i == pendulInfos.end() && (*i).second.SN <= sampleNum) return -1;
568
569 if ((*i).second.SN > sampleNum) i--;
[577]570
571 int nn=0;
572 double aziprev=0, azicur=0, azi0=0;
573 for (map<double, pendulInfo>::iterator ii=i; ii != pendulInfos.begin(); ii--) {
574 nn++;
575 pendulInfo inf1 = (*ii).second;
576 aziprev = azicur;
577 azicur = inf1.azPendul;
578 if (nn==1) azi0 = azicur;
579 if (nn>1 && azicur - aziprev > 180) azicur -= 360;
580 if (nn>1 && azicur - aziprev < -180) azicur += 360;
581 fitPendul.addData(inf1.SN, inf1.angPendul, azicur);
582 if (nn>=5) break;
583 }
584
585 azicur = azi0;
586 if (i != pendulInfos.end()) i++;
587 for (map<double, pendulInfo>::iterator ii=i; ii != pendulInfos.end(); ii++) {
588 nn++;
589 pendulInfo inf1 = (*ii).second;
590 aziprev = azicur;
591 azicur = inf1.azPendul;
592 if (nn>1 && azicur - aziprev > 180) azicur -= 360;
593 if (nn>1 && azicur - aziprev < -180) azicur += 360;
594 fitPendul.addData(inf1.SN, inf1.angPendul, azicur);
595 if (nn>=10) break;
596 }
597
598 if (fitPendul.doFit()) return -1;
599
600 info.SN = sampleNum;
601 info.azPendul = fitPendul.valueZ(sampleNum);
602 if (info.azPendul > 360) info.azPendul -= 360;
603 if (info.azPendul < 0) info.azPendul += 360;
604 info.angPendul = fitPendul.valueY(sampleNum);
605 return 0;
606}
607
608#if 0
609
610int StarMatcher::getPendulInfo(double sampleNum, pendulInfo& info) {
611 static double* sn = ::vector(1, 100);
612 static double* aziP = ::vector(1, 100);
613 static double* ampP = ::vector(1, 100);
614 static double* sig = ::vector(1, 100);
615 static double* aAzi = ::vector(1, 3);
616 static double* aAmp = ::vector(1, 3);
617 static int* ia = ::ivector(1,3);
618 static double** cov = ::matrix(1,3,1,3);
619 int ndata = 0;
620 map<double, pendulInfo>::iterator i = pendulInfos.lower_bound(sampleNum);
621 if (i == pendulInfos.begin() && (*i).second.SN >= sampleNum) return -1;
622 if (i == pendulInfos.end() && (*i).second.SN <= sampleNum) return -1;
623
624 if ((*i).second.SN > sampleNum) i--;
625
626 int nn=0;
627 for (map<double, pendulInfo>::iterator ii=i; ii != pendulInfos.begin(); ii--) {
628 nn++;
629 ndata++;
630 pendulInfo inf1 = (*ii).second;
631 sn[ndata] = inf1.SN;
632 ampP[ndata] = inf1.angPendul;
633 aziP[ndata] = inf1.azPendul;
634 int prev = ndata-1;
635 if (ndata>1 && aziP[ndata] - aziP[prev] > 180) aziP[ndata] -= 360;
636 if (ndata>1 && aziP[ndata] - aziP[prev] < -180) aziP[ndata] += 360;
637 sig[ndata] = 1;
638 if (nn>=50) break;
639 }
640
641 nn=0;
642 if (i != pendulInfos.end()) i++;
643 for (map<double, pendulInfo>::iterator ii=i; ii != pendulInfos.end(); ii++) {
644 nn++;
645 ndata++;
646 pendulInfo inf1 = (*ii).second;
647 sn[ndata] = inf1.SN;
648 ampP[ndata] = inf1.angPendul;
649 aziP[ndata] = inf1.azPendul;
650 int prev = ndata-1;
651 if (nn==1) prev=1;
652 if (ndata>1 && aziP[ndata] - aziP[prev] > 180) aziP[ndata] -= 360;
653 if (ndata>1 && aziP[ndata] - aziP[prev] < -180) aziP[ndata] += 360;
654 sig[ndata] = 1;
655 if (nn>=50) break;
656 }
657
658 if (ndata < 3) return -1;
659
660 ia[1] = ia[2] = ia[3] = 1;
661 double chi2;
662 try {
663 lfit(sn, aziP, sig, ndata, aAzi, ia, 3, cov, &chi2, polfunc);
664 lfit(sn, ampP, sig, ndata, aAmp, ia, 3, cov, &chi2, polfunc);
665 } catch(string st) {
666 return -1;
667 }
668
669 info.SN = sampleNum;
670 info.azPendul = polval(sampleNum, aAzi, 3);
671 if (info.azPendul > 360) info.azPendul -= 360;
672 if (info.azPendul < 0) info.azPendul += 360;
673 info.angPendul = polval(sampleNum, aAmp, 3);
674 return 0;
675}
676
677#endif
678
679#if 0
680
681int StarMatcher::getPendulInfo(double sampleNum, pendulInfo& info) {
682 map<double, pendulInfo>::iterator i = pendulInfos.lower_bound(sampleNum);
683 if (i == pendulInfos.begin() && (*i).second.SN >= sampleNum) return -1;
684 if (i == pendulInfos.end() && (*i).second.SN <= sampleNum) return -1;
685
686 if ((*i).second.SN > sampleNum) i--;
[555]687 pendulInfo inf1 = (*i).second;
688 i++;
689 pendulInfo inf2 = (*i).second;
690
691 info.SN = sampleNum;
692 if (inf2.azPendul - inf1.azPendul > 180) inf2.azPendul -= 360;
693 if (inf2.azPendul - inf1.azPendul < -180) inf2.azPendul += 360;
694 info.azPendul = inf1.azPendul + (inf2.azPendul - inf1.azPendul) * (sampleNum - inf1.SN) / (inf2.SN - inf1.SN);
695 if (info.azPendul<0) info.azPendul += 360;
696 if (info.azPendul>360) info.azPendul += 360;
697 info.angPendul = inf1.angPendul + (inf2.angPendul - inf1.angPendul) * (sampleNum - inf1.SN) / (inf2.SN - inf1.SN);
698 return 0;
699}
700
[577]701#endif
[555]702
[577]703
[555]704double StarMatcher::getValue(long sampleNum, TOI const& toi) {
705 processStars();
706
707 // 1. Interpoler la valeur de pendulation
708 // 2. Interpoler la position en azimuth avec les etoiles encadrant
709
710 pendulInfo pendul;
711 int rc = getPendulInfo(sampleNum, pendul);
712 if (rc) return -99999;
713 if (toi.name == azimuthPendul) return pendul.azPendul;
714 if (toi.name == anglePendul) return pendul.angPendul;
715
716 // find nearest matched star
717 map<double, posInfo>::iterator i = posInfos.lower_bound(sampleNum);
718 if (i == posInfos.begin() && (*i).second.SN >= sampleNum) return -1;
719 if (i == posInfos.end() && (*i).second.SN <= sampleNum) return -1;
720 if ((*i).second.SN > sampleNum) i--;
721
[577]722 // $CHECK$ if time spent here, can keep a GondolaGeom object for several
723 // samples...
[555]724 GondolaGeom geom;
725 geom.setEarthPos((*i).second.lon,(*i).second.lat);
726 geom.setTSid((*i).second.ts);
[577]727 geom.setPendulation(pendul.azPendul, pendul.angPendul);
[555]728
[577]729 int ns=0;
[555]730 for (map<double, posInfo>::iterator it=i; it != posInfos.end(); it++) {
731 posInfo s = (*it).second;
732 double delsn = s.SN - sampleNum;
[577]733 ns++;
734 //if (delsn * archParam.acq.perEch > 1 && ns > 4) break;
735 if (delsn * archParam.acq.perEch > 5) break;
[555]736 geom.addStar(delsn, s.azStar, s.elvStar, s.diodStar);
[534]737 }
738
[555]739 if (i != posInfos.begin()) i--;
[577]740 ns = 0;
[555]741 for (map<double, posInfo>::iterator it=i; it != posInfos.begin(); it--) {
742 posInfo s = (*it).second;
743 double delsn = s.SN - sampleNum;
[577]744 ns++;
745 //if (-delsn * archParam.acq.perEch > 1 && ns > 4) break;
746 if (-delsn * archParam.acq.perEch > 5) break;
[555]747 geom.addStar(delsn, s.azStar, s.elvStar, s.diodStar);
748 }
749
[577]750 if (geom.solveStars()) return -99999;
[555]751
752 if (toi.name == azimuthAxis) return geom.getAzimutAxis();
753 if (toi.name == elvAxis) return geom.getElvAxis();
754 if (toi.name == alphaAxis) return geom.getAlphaAxis();
755 if (toi.name == deltaAxis) return geom.getDeltaAxis();
756
757 if (toi.name == azimuthSST) return geom.getAzimutSST();
758 if (toi.name == elvSST) return geom.getElvSST();
759 if (toi.name == alphaSST) return geom.getAlphaSST();
760 if (toi.name == deltaSST) return geom.getDeltaSST();
761
762 if (toi.name == azimuthFPC) return geom.getAzimutCenter();
763 if (toi.name == elvFPC) return geom.getElvCenter();
764 if (toi.name == alphaFPC) return geom.getAlphaCenter();
765 if (toi.name == deltaFPC) return geom.getDeltaCenter();
766
767 if (toi.name == azimuthBolo) return geom.getAzimutBolo(toi.index);
768 if (toi.name == elvBolo) return geom.getElvBolo(toi.index);
769 if (toi.name == alphaBolo) return geom.getAlphaBolo(toi.index);
770 if (toi.name == deltaBolo) return geom.getDeltaBolo(toi.index);
771
772 return -99999;
[534]773}
774
[555]775bool StarMatcher::canGetValue(long sampleNum, TOI const& /*toi*/) {
776 processStars();
[534]777
[555]778 map<double, pendulInfo>::iterator i = pendulInfos.begin();
779 if (i == pendulInfos.end()) return false;
780 if (sampleNum < (*i).second.SN) return false;
781 i = pendulInfos.end(); i--;
782 if (sampleNum > (*i).second.SN) return false;
783
784 return true;
785}
786
787bool StarMatcher::canGetValueLater(long sampleNum, TOI const& /*toi*/) {
788 processStars();
789
790 map<double, pendulInfo>::iterator i = pendulInfos.end();
791 if (i == pendulInfos.begin()) return true;
792 i--;
[577]793 return (sampleNum+4000> (*i).second.SN);
[555]794}
795
796
797
[534]798set<TOI> StarMatcher::reqTOIFor(TOI const&) {
799 set<TOI> t;
800 t.insert(TOI("latitude", TOI::unspec, "interp"));
801 t.insert(TOI("longitude", TOI::unspec, "interp"));
802 t.insert(TOI("tsid", TOI::unspec));
[555]803 t.insert(TOI("alphaSST", TOI::unspec, "galcross0"));
804 t.insert(TOI("deltaSST", TOI::unspec, "galcross0"));
805 t.insert(TOI("azimuthSST",TOI::unspec, "galcross0"));
806 t.insert(TOI("elvSST", TOI::unspec, "galcross0"));
807 t.insert(TOI("rotSpeed", TOI::unspec, "galcross0"));
[534]808 return t;
809}
810
811void StarMatcher::propagateLowBound(TOI const& toi, long sampleNum) {
[577]812 // we want to keep some past information to interpolate...
813 // keep 1000 sampleNums (easier than a number of posinfos...)
814
815 sampleNum -= 4000;
816
[555]817 map<double, posInfo>::iterator i = posInfos.begin();
818 while (i != posInfos.end() && (*i).first < sampleNum) i++;
819 if (i != posInfos.begin()) {
820 i--;
821 posInfos.erase(posInfos.begin(), i);
822 }
823
824 map<double, pendulInfo>::iterator j = pendulInfos.begin();
825 while (j != pendulInfos.end() && (*j).first < sampleNum) j++;
826 if (j != pendulInfos.begin()) {
827 j--;
828 pendulInfos.erase(pendulInfos.begin(), j);
829 }
830
831 TOIDerivProducer::propagateLowBound(toi, sampleNum);
[534]832}
833
834
[555]835// 1. processStars seulement quand au moins 10 etoiles nouvelles
836// 2. Nettoyer avec fit parabolique sur les 5 dernieres seconde de donnees
837// 3. Garder periodeRotation secondes de donnees nettoyees
838// 4. TF ordre 0 sur ces donnees, amplitude et phase -> theta et phi pendulation,
839// elevationSST = elv-theta Sin[azimut-phi]
840// azimutSST = azimut+theta Cos[azimut-phi] Tan[elv] (+ OFFSET GALCROSS)
841// le signal le plus propre est l'elevation -> fit dessus, puis
842// correction azimut SST a partir seconde equation, sans utiliser azimut galcross
[534]843
844
Note: See TracBrowser for help on using the repository browser.