Index: trunk/Poubelle/archTOI.old/Makefile_nodep
===================================================================
--- trunk/Poubelle/archTOI.old/Makefile_nodep	(revision 554)
+++ trunk/Poubelle/archTOI.old/Makefile_nodep	(revision 555)
@@ -2,8 +2,8 @@
   CXX  = cxx
 endif
-ifndef (CFITSIODIR)
+ifndef CFITSIODIR
   CFITSIODIR = ../cfitsio
 endif
-CPPFLAGS    =-O -g -I$(CFITSIODIR)
+CPPFLAGS    =-O -g -I$(CFITSIODIR) -DANSI
 
 LDLIBS=-L$(CFITSIODIR)/$(HOSTTYPE) -lcfitsio
@@ -21,15 +21,25 @@
 
 clean:
-	rm -f archtoi *.o archdump
+	rm -f archtoi *.o 
 
 
-archtoi: archtoimain.o archtoi.o archeopsfile.o decompress.o toiiter.o toisvr.o archeops.o \
-         ssthandler.o toiinterpolator.o gpsparser.o asigps.o \
+archtoi: archtoimain.o archtoi.o archeopsfile.o archfileset.o \
+         archeops.o decompress.o arcunit.o \
+         tokenizer.o \
+         toi.o toiiter.o toimanager.o toiproducer.o \
+         toiabsorber.o toiderivproducer.o toipullproducer.o \
+	 toirepeater.o toiflagger.o toiinterpolator.o \
+         toillboloproducer.o toilldiluproducer.o \
+         toillgpsproducer.o toillgyroproducer.o toillreglageproducer.o \
+         toillsstproducer.o \
+         gpsparser.o asigps.o toiauxgpsproducer.o toiboloproducer.o \
          auxinterpgps.o tsid.o archparam.o dyffttools.o fft_mayer.o \
          formepulse.o pisteetoile.o sstetoile.o transfelec.o \
-	 gyrohandler.o aa_hadec.o templocator.o plgalcross.o \
-	 arcunit.o
+	 aa_hadec.o templocator.o plgalcross.o \
+	 tsidproducer.o timetoiproducer.o sststarfinder.o \
+         starmatcher.o galcrosslocator.o gyrocalibrator.o \
+         rotspeed.o  gondolageom.o \
+	 nrutil.o lfit.o gaussj.o covsrt.o
 	$(LINK.cc) $^ $(LOADLIBES) $(LDLIBS) -o $@ -lm 
-archdump: archtoidump.o archeopsfile.o decompress.o archeops.o ssthandler.o
-	$(LINK.cc) $^ $(LOADLIBES) $(LDLIBS) -o $@ -lm
 
+
Index: trunk/Poubelle/archTOI.old/archtoi.cc
===================================================================
--- trunk/Poubelle/archTOI.old/archtoi.cc	(revision 554)
+++ trunk/Poubelle/archTOI.old/archtoi.cc	(revision 555)
@@ -214,5 +214,6 @@
 void ArchTOI::endLine_A() {
   if (!ostr) return;
-  *ostr << '\n';
+  *ostr << endl;
+ // *ostr << '\n';
 }
 
Index: trunk/Poubelle/archTOI.old/archtoimain.cc
===================================================================
--- trunk/Poubelle/archTOI.old/archtoimain.cc	(revision 554)
+++ trunk/Poubelle/archTOI.old/archtoimain.cc	(revision 555)
@@ -32,5 +32,5 @@
     }
     
-//   ProfilerInit(collectDetailed, bestTimeBase, 10000, 200);
+//    ProfilerInit(collectDetailed, bestTimeBase, 10000, 200);
 
     if (argv[1] == string("-h")) {
Index: trunk/Poubelle/archTOI.old/formepulse.cc
===================================================================
--- trunk/Poubelle/archTOI.old/formepulse.cc	(revision 554)
+++ trunk/Poubelle/archTOI.old/formepulse.cc	(revision 555)
@@ -140,8 +140,8 @@
 		char s2[32]="Resultatfiltrage.txt";
 		dlout.open(s2,ios::out | ios::trunc);
-		if (!dlout.is_open()){	
-			cerr<<"erreur a l'ouverture du fichier de resultats: "<<s2<<endl;
-			exit(-1);
-		}
+	//	if (!dlout.is_open()){	
+	//		cerr<<"erreur a l'ouverture du fichier de resultats: "<<s2<<endl;
+	//		exit(-1);
+	//	}
 
 		dlout<<"Impulsion courant de: "<<SSTFPulseCourant<<" Ampères"<<endl;
Index: trunk/Poubelle/archTOI.old/galcrosslocator.cc
===================================================================
--- trunk/Poubelle/archTOI.old/galcrosslocator.cc	(revision 554)
+++ trunk/Poubelle/archTOI.old/galcrosslocator.cc	(revision 555)
@@ -9,5 +9,5 @@
 #define alphaZenith     "alphaZenith"
 #define deltaZenith     "deltaZenith"
-#define rotSpeed        "rotSpeed"
+#define rotSpeed        "rotSpeed0"
 #define rotSpeedSample1 "rotSpeedSample1"
 #define rotSpeedSample2 "rotSpeedSample2"
@@ -22,23 +22,33 @@
 #define alphaBolo       "alphaBolo"
 #define deltaBolo       "deltaBolo"
+#define azimuthSST      "azimuthSST"
+#define elvSST          "elvSST"
+#define alphaSST        "alphaSST"
+#define deltaSST        "deltaSST"
 
+// Note : rotSpeed is an estimate, does not take into account balloon drift.
+// accurate value between two galactic crossings has to be determined afterwards
+// as a derived TOI.
 
 GalCrossLocator::GalCrossLocator() {
-  possibleTOIs.insert(TOI(alphaZenith,      TOI::unspec, "", "hours",   "galcross0"));  
-  possibleTOIs.insert(TOI(deltaZenith,      TOI::unspec, "", "degrees", "galcross0"));  
-  possibleTOIs.insert(TOI(rotSpeed,         TOI::unspec, "", "deg/s",   "galcross0"));  
-  possibleTOIs.insert(TOI(rotSpeedSample1,  TOI::unspec, "", "integer", "galcross0"));  
-  possibleTOIs.insert(TOI(rotSpeedSample2,  TOI::unspec, "", "integer", "galcross0"));  
-  possibleTOIs.insert(TOI(lastCrossSample,  TOI::unspec, "", "integer", "galcross0"));  
-  possibleTOIs.insert(TOI(lastCrossSample,  TOI::unspec, "", "integer", "galcross0"));  
-  possibleTOIs.insert(TOI(nextCrossSample,  TOI::unspec, "", "integer", "galcross0"));  
-  possibleTOIs.insert(TOI(azimuthFPC,       TOI::unspec, "", "degrees", "galcross0"));  
-  possibleTOIs.insert(TOI(elvFPC,           TOI::unspec, "", "degrees", "galcross0"));  
-  possibleTOIs.insert(TOI(alphaFPC,         TOI::unspec, "", "hours",   "galcross0"));  
-  possibleTOIs.insert(TOI(deltaFPC,         TOI::unspec, "", "degrees", "galcross0"));  
-  possibleTOIs.insert(TOI(azimuthBolo,      TOI::all,    "", "degrees", "galcross0"));  
-  possibleTOIs.insert(TOI(elvBolo,          TOI::all,    "", "degrees", "galcross0"));  
-  possibleTOIs.insert(TOI(alphaBolo,        TOI::all,    "", "hours",   "galcross0"));  
-  possibleTOIs.insert(TOI(deltaBolo,        TOI::all,    "", "degrees", "galcross0"));  
+  possibleTOIs.insert(TOI(alphaZenith,      TOI::unspec, "interp flag", "hours",   ""));  
+  possibleTOIs.insert(TOI(deltaZenith,      TOI::unspec, "interp flag", "degrees", ""));  
+  possibleTOIs.insert(TOI(rotSpeed,         TOI::unspec, "interp flag", "deg/s",   "galcross0"));  
+  possibleTOIs.insert(TOI(rotSpeedSample1,  TOI::unspec, "interp flag", "integer", "galcross0"));  
+  possibleTOIs.insert(TOI(rotSpeedSample2,  TOI::unspec, "interp flag", "integer", "galcross0"));  
+  possibleTOIs.insert(TOI(lastCrossSample,  TOI::unspec, "interp flag", "integer", "galcross0"));  
+  possibleTOIs.insert(TOI(nextCrossSample,  TOI::unspec, "interp flag", "integer", "galcross0"));  
+  possibleTOIs.insert(TOI(azimuthFPC,       TOI::unspec, "interp flag", "degrees", "galcross0"));  
+  possibleTOIs.insert(TOI(elvFPC,           TOI::unspec, "interp flag", "degrees", "galcross0"));  
+  possibleTOIs.insert(TOI(alphaFPC,         TOI::unspec, "interp flag", "hours",   "galcross0"));  
+  possibleTOIs.insert(TOI(deltaFPC,         TOI::unspec, "interp flag", "degrees", "galcross0"));  
+  possibleTOIs.insert(TOI(azimuthBolo,      TOI::all,    "interp flag", "degrees", "galcross0"));  
+  possibleTOIs.insert(TOI(elvBolo,          TOI::all,    "interp flag", "degrees", "galcross0"));  
+  possibleTOIs.insert(TOI(alphaBolo,        TOI::all,    "interp flag", "hours",   "galcross0"));  
+  possibleTOIs.insert(TOI(deltaBolo,        TOI::all,    "interp flag", "degrees", "galcross0"));  
+  possibleTOIs.insert(TOI(azimuthSST,       TOI::unspec, "interp flag", "degrees", "galcross0"));  
+  possibleTOIs.insert(TOI(elvSST,           TOI::unspec, "interp flag", "degrees", "galcross0"));  
+  possibleTOIs.insert(TOI(alphaSST,         TOI::unspec, "interp flag", "hours",   "galcross0"));  
+  possibleTOIs.insert(TOI(deltaSST,         TOI::unspec, "interp flag", "degrees", "galcross0"));  
 }
 
@@ -55,10 +65,17 @@
 double GalCrossLocator::getValue(long sampleNum, TOI const& toi) {
   if (!canGetValue(sampleNum, toi)) return -1;
+  
+  if (toi.options.find("flag") != toi.options.end()) {
+     int SN1, SN2;
+     tempLocator.getCrossSamples(sampleNum, SN1, SN2);
+     if (sampleNum == SN1 || sampleNum == SN2) return 1;
+     return 0;
+  }
 
-  map<TOI, TOIProducer*> m = neededTOIs[toi];
+  map<TOI, TOIProducer*>  & m = neededTOIs[toi];
   double lat, lon, ts;
   
   for (map<TOI, TOIProducer*>::iterator i = m.begin(); i != m.end(); i++) {
-    TOI inToi = (*i).first;
+    TOI const& inToi = (*i).first;
     TOIProducer* prod =  (*i).second;
     if (inToi.name == "latitude")  lat = prod->getValue(sampleNum, inToi);
@@ -83,4 +100,9 @@
   if (toi.name == alphaBolo)       return tempLocator.getAlphaBolo(sampleNum, toi.index);
   if (toi.name == deltaBolo)       return tempLocator.getDeltaBolo(sampleNum, toi.index);
+
+  if (toi.name == azimuthSST)      return tempLocator.getAzimutSST(sampleNum);
+  if (toi.name == elvSST)          return tempLocator.getElvSST(sampleNum);
+  if (toi.name == alphaSST)        return tempLocator.getAlphaSST(sampleNum);
+  if (toi.name == deltaSST)        return tempLocator.getDeltaSST(sampleNum);
 
   if (toi.name == lastCrossSample || toi.name == rotSpeedSample1) {
Index: trunk/Poubelle/archTOI.old/gyrocalibrator.cc
===================================================================
--- trunk/Poubelle/archTOI.old/gyrocalibrator.cc	(revision 554)
+++ trunk/Poubelle/archTOI.old/gyrocalibrator.cc	(revision 555)
@@ -4,17 +4,30 @@
 // assumption : same calibration for all gyros...
 
+// Warning, current implementation can only output ONE calibration.
+// workaround : clone the object for different options.
+
 
 #include "gyrocalibrator.h"
+#include "archexc.h"
+#include "archparam.h"
 
 #define gyroCal    "gyroCal"
+#define gyroOffset "gyroOffset"
 #define gyroSpeed  "gyroSpeed"
 
 GyroCalibrator::GyroCalibrator() {
-  possibleTOIs.insert(TOI(gyroCal,      TOI::unspec, "linearCal", "deg/s/V"));  
+  possibleTOIs.insert(TOI(gyroCal,      TOI::all,    "linearCal", "deg/s/V"));  
+  possibleTOIs.insert(TOI(gyroOffset,   TOI::all,    "linearCal", "deg/s/V"));  
   possibleTOIs.insert(TOI(gyroSpeed,    TOI::all   , "linearCal", "deg/s"));  
   
-  //needAfter = 3600;  // about one turn...
+  needAfter = 3600;  // about one turn...
   startSample = -1;
+  lastRotSpeed = -1;
   lastFence1 = lastFence2 = -1;
+  for (int i=0; i<3; i++) {
+    lastCalib[i] = -99999;
+    lastOffset[i] = 0;
+  }
+  gyroProducer = NULL;
 }
 
@@ -35,14 +48,136 @@
 }
 
-void GyroCalibrator::dataFeed(TOIProducer* source, TOI const& toi, long sampleNum, double value) {
-  if (toi.name != "gyroV" || toi.index != 2) return;
+void GyroCalibrator::dataFeed(TOIProducer* , TOI const& toi, long sampleNum, double value) {
+ // if (toi.name != "gyroV" || toi.index != 2) return;
+  if (toi.name != "gyroV" ) return;
   
-  if (gyro2.empty()) {
+  if (gyro[2].empty()) {
     startSample = sampleNum;
   }
   
-  gyro2.push_back(value);
+  gyro[toi.index].push_back(value);
+}
+
+void GyroCalibrator::recomputeCalib() {
+  // Integral of gyro signal between the two fences.
+  
+  // can we do it ?
+  for (int i=0; i<3; i++) {
+    lastCalib[i] = -99999;
+  }
+  if (startSample > lastFence1) return;
+  if ((long)gyro[2].size()+startSample < lastFence2) return;
+        
+  double sum[3];
+  for (int i=0; i<3; i++) {
+    sum[i] = 0;
+  }
+  vector<double>::iterator i0     = gyro[0].begin() + (lastFence1-startSample);
+  vector<double>::iterator i1     = gyro[1].begin() + (lastFence1-startSample);
+  vector<double>::iterator i2     = gyro[2].begin() + (lastFence1-startSample);
+  vector<double>::iterator stop2  = gyro[2].begin() + (lastFence2-startSample);
+  for (; i2 != stop2; i0++,i1++,i2++) {
+    sum[0] += *i0;
+    sum[1] += *i1;
+    sum[2] += *i2;
+  }
+    
+  // average of signal
+  sum[0] /= (lastFence2-lastFence1);
+  sum[1] /= (lastFence2-lastFence1);
+  sum[2] /= (lastFence2-lastFence1);
+  
+  lastOffset[0] = sum[0];
+  lastOffset[1] = sum[1];
+  lastOffset[2] = (lastOffset[0] + lastOffset[1])/2.;  // We don't have a better estimate...
+  
+  lastCalib[2]  = lastRotSpeed / (sum[2] - lastOffset[2]);
+  lastCalib[0] = lastCalib[1] = lastCalib[2];          // We don't have a better estimate...
+}
+
+bool GyroCalibrator::fetchFences(long sampleNum) {
+  map<TOI, TOIProducer*> & m = (*(neededTOIs.begin())).second;
+  
+  long oldf2 = lastFence2;
+  for (map<TOI, TOIProducer*>::iterator i = m.begin(); i != m.end(); i++) {
+    TOI const& inToi = (*i).first;
+    TOIProducer* prod =  (*i).second;
+    if (inToi.name == "rotSpeed")        lastRotSpeed = prod->getValue(sampleNum, inToi);
+    if (inToi.name == "rotSpeedSample1") lastFence1   = prod->getValue(sampleNum, inToi);
+    if (inToi.name == "rotSpeedSample2") lastFence2   = prod->getValue(sampleNum, inToi);
+    if (inToi.name == "gyroV")           gyroProducer = prod;
+  }
+  
+  return (oldf2 != lastFence2);
 }
 
 
+bool GyroCalibrator::canGetValue(long sampleNum, TOI const& ) {
+  // We can get value if sampleNum is between the two fences, or
+  // if a new fence later than sampleNum is now available.
+  // In any case, we must have gyro data up to the highest fence.
+  
+  if (startSample > lastFence1) return false; // will never work...
+  if (sampleNum >= lastFence1 && sampleNum < lastFence2 && (gyro[2].size()+startSample >= lastFence2)) return true;
+  if ((long)gyro[2].size()+startSample < lastFence2) return false; // We have to wait for more gyro data
+  if (fetchFences(sampleNum)) {
+    recomputeCalib(); // do it now to keep a consistent state
+  }
+  if (sampleNum >= lastFence1 && sampleNum < lastFence2) {
+    return true;
+  } else {
+    return false;
+  }  
+}
 
+bool GyroCalibrator::canGetValueLater(long sampleNum, TOI const& ) {
+  if (sampleNum >= lastFence1 && sampleNum < lastFence2 && ((long)gyro[2].size()+startSample >= lastFence2)) return false;
+      // because can get now
+  if (sampleNum >= lastFence2) { // check if new fence...
+    if (fetchFences(sampleNum)) {
+      recomputeCalib(); // do it now to keep a consistent state
+    }
+  }
+  if (lastFence1<0 || lastFence2<0) return true;
+  if (sampleNum > lastFence2) return true;
+  return (startSample <= lastFence1 && (long)gyro[2].size()+startSample < lastFence2 && sampleNum > lastFence1);
+}
+
+double GyroCalibrator::getValue(long sampleNum, TOI const& toi) {
+  if (startSample > lastFence1) return -1; // will never work...
+  if ((long)gyro[2].size()+startSample < lastFence2) return -1; // We have to wait for more gyro data
+  if (!(sampleNum >= lastFence1 && sampleNum < lastFence2)) {
+    if (fetchFences(sampleNum)) {
+      if ((long)gyro[2].size()+startSample < lastFence2) return -1; // We have to wait for more gyro data
+      recomputeCalib(); // do it now to keep a consistent state
+    }
+  }
+  
+  if (!(sampleNum >= lastFence1 && sampleNum < lastFence2)) 
+    return -1;
+    
+  if (lastCalib[0] < 0) recomputeCalib();
+    
+  if (toi.name == gyroCal)    return lastCalib[toi.index];
+  if (toi.name == gyroOffset) return lastOffset[toi.index];
+  if (toi.name == gyroSpeed) {
+    TOI toi2 = TOI("gyroV", toi.index); // $CHECK$ maybe should get from reqtoi ?
+    double gv = gyroProducer->getValue(sampleNum, toi2);
+    return (gv-lastOffset[toi.index])*lastCalib[toi.index];
+  }
+  throw ArchExc("Cannot produce "+toi.fullName());
+}
+
+
+void GyroCalibrator::propagateLowBound(TOI const&, long /*sampleNum*/) {
+   if (startSample < lastFence1) {
+     if (gyro[0].size() > lastFence1 - startSample) {
+       for (int i=0; i<3; i++) {
+         vector<double>::iterator x = gyro[i].begin() + lastFence1 - startSample;
+         gyro[i].erase(gyro[i].begin(), x);
+       }
+       startSample = lastFence1;
+     }
+   }
+}
+
Index: trunk/Poubelle/archTOI.old/gyrocalibrator.h
===================================================================
--- trunk/Poubelle/archTOI.old/gyrocalibrator.h	(revision 554)
+++ trunk/Poubelle/archTOI.old/gyrocalibrator.h	(revision 555)
@@ -5,9 +5,9 @@
 #define GYROCALIBRATOR_H
 
-#include "toiderivproducer.h"
+#include "toipullproducer.h"
 
 #include <vector>
 
-class GyroCalibrator : public TOIDerivProducer {
+class GyroCalibrator : public TOIPullProducer {
 public:
   GyroCalibrator();
@@ -16,14 +16,23 @@
 
   virtual bool   canGetValue(long sampleNum, TOI const& toi); // for this samplenum
+  virtual bool   canGetValueLater(long sampleNum, TOI const& toi);  // Might, later but not now
+  
   virtual double getValue(long sampleNum, TOI const& toi);
-
+  
 protected:
   virtual set<TOI>     reqTOIFor(TOI const&);
   virtual void         propagateLowBound(TOI const&, long sampleNum);
   
-private:
+  virtual void recomputeCalib();
+  virtual bool fetchFences(long sampleNum);
+  
+  
   long startSample;
-  vector<double> gyro2; 
+  vector<double> gyro[3]; 
   long lastFence1, lastFence2;
+  double lastRotSpeed; // on gyro 2
+  double lastCalib[3];
+  double lastOffset[3];
+  TOIProducer* gyroProducer;
 };
 
Index: trunk/Poubelle/archTOI.old/mkd
===================================================================
--- trunk/Poubelle/archTOI.old/mkd	(revision 554)
+++ trunk/Poubelle/archTOI.old/mkd	(revision 555)
@@ -2,5 +2,8 @@
 
 cp Makefile_nodep Makefile
+if( ! $?CFITSIODIR ) then
+  setenv CFITSIODIR ../cfitsio
+endif
 foreach f (*.c *.cc)
-  gcc -MM -I../cfitsio $f >> Makefile
+  gcc -MM -I$CFITSIODIR $f >> Makefile
 end
Index: trunk/Poubelle/archTOI.old/pisteetoile.cc
===================================================================
--- trunk/Poubelle/archTOI.old/pisteetoile.cc	(revision 554)
+++ trunk/Poubelle/archTOI.old/pisteetoile.cc	(revision 555)
@@ -1,5 +1,5 @@
-#include "math.h"
+#include <math.h>
 #include <new.h>
-#include "iostream.h"
+#include <iostream.h>
 #include "archparam.h"
 #include "pisteetoile.h"
Index: trunk/Poubelle/archTOI.old/sststarfinder.cc
===================================================================
--- trunk/Poubelle/archTOI.old/sststarfinder.cc	(revision 554)
+++ trunk/Poubelle/archTOI.old/sststarfinder.cc	(revision 555)
@@ -15,4 +15,8 @@
 #define sstStarSN    "sstStarSN"
 #define sstStarUTC   "sstStarUTC"
+
+bool  SSTStarFinder::has2bars=false;
+int   SSTStarFinder::elecOffset=0;
+
 
 
@@ -92,5 +96,5 @@
 
 void SSTStarFinder::dataFeed(long sampleNum, int* diodeSignal) {
-  if (producedTOIs.empty()) return;
+  if (producedTOIs.empty() && processors.empty()) return;
   if (sampleNum == lastFedSample+1) {
 	for(int i=0;i<NbPhotDiodBarette; i++) {	
Index: trunk/Poubelle/archTOI.old/starmatcher.cc
===================================================================
--- trunk/Poubelle/archTOI.old/starmatcher.cc	(revision 554)
+++ trunk/Poubelle/archTOI.old/starmatcher.cc	(revision 555)
@@ -1,16 +1,116 @@
+// starmatcher.cc
+// Eric Aubourg         CEA/DAPNIA/SPP   novembre 1999
+
 #include "starmatcher.h"
 #include "sststarfinder.h"
 #include "toimanager.h"
 #include "archexc.h"
+#include "archparam.h"
+#include "gondolageom.h"
 
 extern "C" {
 #include "aa_hadec.h"
+#define NRANSI
+#include "nrutil.h"
+
+void lfit(float x[], float y[], float sig[], int ndat, float a[], int ia[],
+	int ma, float **covar, float *chisq, void (*funcs)(float, float [], int));
+
+void polfunc(float x, float afunc[], int ma);
+void sinfunc(float x, float afunc[], int ma);
+}
+
+void polfunc(float x, float afunc[], int ma) {
+  afunc[1] = 1;
+  for (int i=2; i<=ma; i++)
+    afunc[i] = afunc[i-1]*x;
+}
+
+void sinfunc(float x, float afunc[], int /*ma*/) {
+  afunc[1] = cos(x);
+  afunc[2] = sin(x);
+  afunc[3] = 1;
+}
+
+
+float polval(float x, float a[], int ma);
+
+float polval(float x, float a[], int ma) {
+  float r = a[ma];
+  for (int i=ma-1; i>0; i--) {
+    r = r*x+a[i];
+  }
+  return r;
 }
 
 #include <stdio.h>
 
+#ifdef __DECCXX
+#define SWAP
+#endif
+#if defined(Linux)  || defined(linux)
+#define SWAP
+#endif
+
+typedef unsigned int4 uint_4;
+typedef unsigned short uint_2;
+
+static inline void bswap4(void* p)
+{
+  uint_4 tmp = *(uint_4*)p;
+  *(uint_4*)p = ((tmp >> 24) & 0x000000FF) | 
+                ((tmp >> 8)  & 0x0000FF00) |
+                ((tmp & 0x0000FF00) << 8)  |
+                ((tmp & 0x000000FF) << 24);
+}
+
+static inline void bswap2(void* p)
+{
+  uint_2 tmp = *(uint_2*)p;
+  *(uint_2*)p = ((tmp >> 8) & 0x00FF) | 
+                ((tmp & 0x00FF) << 8);
+}
+
+
+#define azimuthPendul   "azimuthPendul"
+#define anglePendul     "anglePendul"
+#define azimuthAxis     "azimuthAxis"
+#define elvAxis         "deltaZenith"
+#define alphaAxis       "alphaZenith"
+#define deltaAxis       "deltaZenith"
+#define azimuthFPC      "azimuthFPC"
+#define elvFPC          "elvFPC"
+#define alphaFPC        "alphaFPC"
+#define deltaFPC        "deltaFPC"
+#define azimuthBolo     "azimuthBolo"
+#define elvBolo         "elvBolo"
+#define alphaBolo       "alphaBolo"
+#define deltaBolo       "deltaBolo"
+#define azimuthSST      "azimuthSST"
+#define elvSST          "elvSST"
+#define alphaSST        "alphaSST"
+#define deltaSST        "deltaSST"
+
+
 StarMatcher::StarMatcher() {
-  possibleTOIs.insert(TOI("dummatcher",      TOI::unspec, "", "blabla"));  
-  
+  possibleTOIs.insert(TOI(azimuthSST,       TOI::unspec, "interp", "degrees","sstmatch"));  
+  possibleTOIs.insert(TOI(elvSST,           TOI::unspec, "interp", "degrees","sstmatch"));  
+  possibleTOIs.insert(TOI(alphaSST,         TOI::unspec, "interp", "hours","sstmatch"));  
+  possibleTOIs.insert(TOI(deltaSST,         TOI::unspec, "interp", "degrees","sstmatch"));  
+  possibleTOIs.insert(TOI(azimuthAxis,      TOI::unspec, "interp", "degrees","sstmatch"));  
+  possibleTOIs.insert(TOI(elvAxis,          TOI::unspec, "interp", "degrees","sstmatch"));  
+  possibleTOIs.insert(TOI(alphaAxis,        TOI::unspec, "interp", "hours","sstmatch"));  
+  possibleTOIs.insert(TOI(deltaAxis,        TOI::unspec, "interp", "degrees","sstmatch"));  
+  possibleTOIs.insert(TOI(azimuthPendul,    TOI::unspec, "interp", "degrees","sstmatch"));  
+  possibleTOIs.insert(TOI(anglePendul,      TOI::unspec, "interp", "degrees","sstmatch"));  
+  possibleTOIs.insert(TOI(azimuthFPC,       TOI::unspec, "interp", "degrees", "sstmatch"));  
+  possibleTOIs.insert(TOI(elvFPC,           TOI::unspec, "interp", "degrees", "sstmatch"));  
+  possibleTOIs.insert(TOI(alphaFPC,         TOI::unspec, "interp", "hours",   "sstmatch"));  
+  possibleTOIs.insert(TOI(deltaFPC,         TOI::unspec, "interp", "degrees", "sstmatch"));  
+  possibleTOIs.insert(TOI(azimuthBolo,      TOI::all,    "interp", "degrees", "sstmatch"));  
+  possibleTOIs.insert(TOI(elvBolo,          TOI::all,    "interp", "degrees", "sstmatch"));  
+  possibleTOIs.insert(TOI(alphaBolo,        TOI::all,    "interp", "hours",   "sstmatch"));  
+  possibleTOIs.insert(TOI(deltaBolo,        TOI::all,    "interp", "degrees", "sstmatch"));  
+
   FILE* f;
   
@@ -18,8 +118,44 @@
   if (!f) throw ArchExc("Error opening gsc7.dat");
   
-  fread(&nstars, sizeof(long), 1 , f);
+  int4 n4;
+  fread(&n4, sizeof(int4), 1 , f);
+
+#ifdef SWAP
+  bswap4(&n4);
+#endif
+  nstars = n4;
+
   stars = new gscStar[nstars];
-  fread(stars, sizeof(gscStar), nstars, f);
+  char* compdata = new char[10*nstars];
+  fread(compdata, 10, nstars, f);
   fclose(f);
+  
+  for (int i=0; i<nstars; i++) {
+#ifdef SWAP
+     ((char*)&(stars[i].ra))[0]  = compdata[10*i+3];
+     ((char*)&(stars[i].ra))[1]  = compdata[10*i+2];
+     ((char*)&(stars[i].ra))[2]  = compdata[10*i+1];
+     ((char*)&(stars[i].ra))[3]  = compdata[10*i+0];
+     ((char*)&(stars[i].dec))[0] = compdata[10*i+7];
+     ((char*)&(stars[i].dec))[1] = compdata[10*i+6];
+     ((char*)&(stars[i].dec))[2] = compdata[10*i+5];
+     ((char*)&(stars[i].dec))[3] = compdata[10*i+4];
+     ((char*)&(stars[i].mag))[0] = compdata[10*i+9];
+     ((char*)&(stars[i].mag))[1] = compdata[10*i+8];
+#else
+     ((char*)&(stars[i].ra))[0]  = compdata[10*i+0];
+     ((char*)&(stars[i].ra))[1]  = compdata[10*i+1];
+     ((char*)&(stars[i].ra))[2]  = compdata[10*i+2];
+     ((char*)&(stars[i].ra))[3]  = compdata[10*i+3];
+     ((char*)&(stars[i].dec))[0] = compdata[10*i+4];
+     ((char*)&(stars[i].dec))[1] = compdata[10*i+5];
+     ((char*)&(stars[i].dec))[2] = compdata[10*i+6];
+     ((char*)&(stars[i].dec))[3] = compdata[10*i+7];
+     ((char*)&(stars[i].mag))[0] = compdata[10*i+8];
+     ((char*)&(stars[i].mag))[1] = compdata[10*i+9];
+#endif
+  }
+  
+  delete[] compdata;
 
   TOIProducer* prod = TOIManager::findTOIProducer(TOI("sstStarCount"));
@@ -35,4 +171,6 @@
   }
   
+  lastSeq = 0;
+  
   sprod->registerProcessor(this);
 
@@ -43,75 +181,434 @@
 }
 
+#ifdef STARDUMP
 static ofstream starstream("stars.dat");
+static ofstream cstarstream("cstars.dat");
+static ofstream pendstream("pendul.dat");
+#endif
 
 void StarMatcher::dataFeed(SSTEtoile const& x) {
-  lastStars[(long)x.TEchan] = x;
+  lastStars.push_back(x);
+}
+
+static long lastCleanSave=0;
+
+void nrerror(char * error_text) {
+  throw(string(error_text));
+}
+
+
+void StarMatcher::processStars() {
+
+  if (lastStars.empty()) return;
+
+  map<TOI, TOIProducer*> & m = (*neededTOIs.begin()).second;
+  while (!lastStars.empty()) {
+    SSTEtoile lastStar = lastStars.front();
+    lastStars.pop_front();
+
+    double lat, lon, ts, alpha, delta, az, rspeed;
+    
+    long snstar = (long) lastStar.TEchan;
+  
+    for (map<TOI, TOIProducer*>::iterator i = m.begin(); i != m.end(); i++) {
+      TOI const& inToi = (*i).first;
+      TOIProducer* prod =  (*i).second;
+      if (inToi.name == "latitude")    lat = prod->getValue(snstar, inToi);
+      if (inToi.name == "longitude")   lon = prod->getValue(snstar, inToi);
+      if (inToi.name == "tsid")         ts = prod->getValue(snstar, inToi);
+      if (inToi.name == "alphaSST")  alpha = prod->getValue(snstar, inToi);
+      if (inToi.name == "deltaSST")  delta = prod->getValue(snstar, inToi);
+      if (inToi.name == "azimuthSST")   az = prod->getValue(snstar, inToi);
+      if (inToi.name == "rotSpeed") rspeed = prod->getValue(snstar, inToi);
+    }
+    
+    // correct azimuth using fractional value of TEchan
+    
+    az -= rspeed * archParam.acq.perEch * (lastStar.TEchan-snstar);
+    
+    // find all stars +- 2 deg boresight
+    double dist = 2;
+    double dmin = delta - dist; if (dmin<-90) dmin=-90;
+    double dmax = delta + dist; if (dmax> 90) dmax= 90;
+    double amin = alpha - dist / cos(delta * 3.1415926/180) / 15.;
+    if (amin<0) amin += 24;
+    double amax = alpha + dist / cos(delta * 3.1415926/180) / 15.;
+    if (amax>24) amax -= 24;
+  
+    int a,b,c;
+    a=0; c=nstars-1;
+    while (a+1<c) {
+      b = (a+c)/2;
+      if (stars[b].dec < dmin) a=b; else c=b;
+    }
+    int imin = a;
+    a=0; c=nstars;
+    while (a+1<c) {
+      b = (a+c)/2;
+      if (stars[b].dec < dmax) a=b; else c=b;
+    }
+    int imax = c;
+
+    for (int i=imin; i<=imax; i++) {
+      if (stars[i].ra >= amin && stars[i].ra <= amax) {
+        double ha = (ts/3600. - stars[i].ra) * 15. * 3.1415926/180.;
+        double elv, azim;
+        hadec_aa(lat * 3.1415926/180., ha, stars[i].dec * 3.1415926/180.,
+                 &elv, &azim);
+        elv  *= 180/3.1415926;
+        azim *= 180/3.1415926;
+        if (azim<0) azim += 360;
+      
+        double da = azim-az; if (da>360) da -= 360;
+        if (da < -0.6 || da > 0.4) continue;
+        double elv0 = elv - 1.41/45. * lastStar.NoDiode;
+        if (fabs(elv0-GondolaGeom::elevSST0) > 0.25) continue; // Might be too strong
+        
+#ifdef STARDUMP     
+        starstream << setprecision(10)  << lastStar.TEchan << " " << 
+          lastStar.NoDiode << " " <<
+          alpha << " " << delta << " " <<
+          az << " " << 
+          stars[i].ra << " " << stars[i].dec << " " <<
+          elv << " " << azim << " " <<
+          lastStar.InpCurrent << " " << stars[i].mag << "\n";
+#endif
+          
+        matchStar s;
+        lastSeq++;
+        s.SN       = lastStar.TEchan;
+        s.raGSC    = stars[i].ra;
+        s.decGSC   = stars[i].dec;
+        s.azGSC    = azim;
+        s.elvGSC   = elv;
+        s.nDiode   = lastStar.NoDiode;
+        s.ok       = true;
+        s.seq      = lastSeq;
+        s.lon      = lon;
+        s.lat      = lat;
+        s.ts       = ts;
+        
+        matchStars.push_back(s);
+      }
+    }
+  }
+  
+  // new set of matched stars... Clean, and get parameters...
+  // We don't want more than 20 seconds of data
+  
+  if (matchStars.empty()) return;
+  
+  
+  double snEnd = matchStars.back().SN;
+  deque<matchStar>::iterator it;
+  for (it = matchStars.begin();  it!=matchStars.end(); it++) {
+     if ((snEnd - (*it).SN)*archParam.acq.perEch < 20) 
+       break;
+  }
+  if (it != matchStars.begin()) {
+    matchStars.erase(matchStars.begin(), it);
+  }
+  
+  // we want to clean on the last 5 seconds of data.
+  
+  int nskip=0;
+  for (it = matchStars.begin();  it!=matchStars.end(); it++) {
+     if ((snEnd - (*it).SN)*archParam.acq.perEch < 7) 
+       break;
+     nskip++;
+  }
+  
+  if (matchStars.size()-nskip < 30) return; // pas assez d'etoiles
+  
+  // we remove "bursts" of stars, ie more than 4 stars in the same samplenum
+  
+  long lastSN = 0;
+  deque<matchStar>::iterator lastIt = it;
+  long burstLen = 0;
+  for (deque<matchStar>::iterator it1 = it ;  it1!=matchStars.end(); it1++) {
+    matchStar s = (*it1);
+    if ((long) s.SN == lastSN) {
+      burstLen++;
+      continue;
+    }
+    if (burstLen >= 4) {
+      for (deque<matchStar>::iterator it2=lastIt; it2 != it1; it2++) {
+        (*it2).ok=false;
+      }
+    }
+    burstLen = 1;
+    lastIt = it1;
+    lastSN = s.SN;
+  }
+  // we fit the data to a polynomial, with clipping...
+  
+  float* sn   =  ::vector(1, matchStars.size());
+  float* elv0 =  ::vector(1, matchStars.size());
+  float* azi  =  ::vector(1, matchStars.size());
+  float* sig  =  ::vector(1, matchStars.size());
+  float* ae   =  ::vector(1, 3);
+  float* aa   =  ::vector(1, 3);
+  int*  ia    = ivector(1, 3);
+  float** cov =  matrix(1, 3, 1, 3);
+  int ndata;
+  
+  long sn0 = matchStars.front().SN;
+  long snmin;
+  long snmax;
+  for (int i=0; i<4; i++) {
+    ndata = 0;
+    snmin = 99999999;
+    snmax = -99999999;
+    for (deque<matchStar>::iterator it1 = it ;  it1!=matchStars.end(); it1++) {
+      matchStar s = (*it1);
+      if (!s.ok) continue;
+      double delv, daz;
+      if (i) {
+        delv = polval(s.SN-sn0, ae, 3)-(s.elvGSC - s.nDiode*1.41/45.);
+        daz  = polval(s.SN-sn0, aa, 3)- s.azGSC;
+        if (daz>=180) daz -= 360;
+        if (daz<-180) daz += 360;
+      }
+      double dcutelv=0.2;
+      double dcutaz =0.4;
+      if (i>=2) {
+         dcutelv = 0.05;
+         dcutaz  = 0.1;
+      }
+      if (i>=3) {
+         dcutelv = 0.02;
+         dcutaz  = 0.03;
+      }
+      if (i == 0 || ((fabs(delv)<dcutelv && fabs(daz)<dcutaz) && i<3)) {
+          ndata++;
+          sn  [ndata] = s.SN-sn0;
+          elv0[ndata] = s.elvGSC - s.nDiode*1.41/45.;
+          azi [ndata] = s.azGSC; // $CHECK$  ou ajuster difference avec az galcross ?
+          if (ndata>1 && azi[ndata] - azi[ndata-1] > 180) azi[ndata] -= 360;
+          if (ndata>1 && azi[ndata] - azi[ndata-1] < -180) azi[ndata] += 360;
+          sig [ndata] = 0.01;
+          if (s.SN-sn0 > snmax) snmax = s.SN-sn0;
+          if (s.SN-sn0 < snmin) snmin = s.SN-sn0;
+      }
+      if ((fabs(delv)>=dcutelv || fabs(daz)>=dcutaz) && i==3) {
+          (*it1).ok = false; 
+      }
+    }
+    if (i==3) break;
+    if (ndata<5) return; // on ne peut rien faire
+    ia[1]   =  ia[2] = ia[3] = 1;
+    float chi2;
+    try{
+      lfit(sn, elv0, sig, ndata, ae, ia, 3, cov, &chi2, polfunc);
+      lfit(sn, azi,  sig, ndata, aa, ia, 3, cov, &chi2, polfunc);
+    } catch(string s) {
+      return;
+    }
+  }
+  
+  for (deque<matchStar>::iterator it1 = it ;  it1!=matchStars.end(); it1++) {
+    if ((*it1).ok && (*it1).seq > lastCleanSave) {
+      lastCleanSave = (*it1).seq;
+#ifdef STARDUMP
+      cstarstream <<  (*it1).seq << "\n";
+#endif
+      posInfo info;
+      info.SN      =   (*it1).SN;
+      info.azStar  =   (*it1).azGSC;
+      info.elvStar =   (*it1).elvGSC;
+      info.diodStar=   (*it1).nDiode;
+      info.lon     =   (*it1).lon;
+      info.lat     =   (*it1).lat;
+      info.ts      =   (*it1).ts;
+      posInfos[info.SN] = info;
+    }
+  }
+  
+  // On a des etoiles nettoyees, on va trouver amplitude et phase du
+  // signal en elevation, ce qui va nous donner les deux angles d'Euler
+  // de la pendulation (au premier ordre en theta)
+  
+  // Il faut avoir une periode entiere ou pas loin, sinon on ne peut
+  // rien dire simplement....
+  
+  it = matchStars.end(); it--;
+  if ((((*it).SN) - (*matchStars.begin()).SN)*archParam.acq.perEch < 17) return;
+  
+  long snmid = (((*it).SN) + (*matchStars.begin()).SN)/2;
+    
+  ndata=0;  
+  
+  for (deque<matchStar>::iterator it1 = matchStars.begin() ;  it1!=matchStars.end(); it1++) {
+    if (!(*it1).ok) continue;
+    ndata++;
+    azi[ndata]  = (*it1).azGSC * 3.1415926/180;
+    elv0[ndata] = (*it1).elvGSC - (*it1).nDiode*1.41/45.;
+    sig[ndata]  = 0.01;
+  }
+   ia[1]   =  ia[2] = 1;
+   ia[3] = 0;
+   aa[3] = GondolaGeom::elevSST0;// do not fit elv0
+
+  if (ndata<5) return;
+  float chi2;
+  try {
+    lfit(azi, elv0,  sig, ndata, aa, ia, 3, cov, &chi2, sinfunc);
+  } catch(string s) {
+    return;
+  }
+
+  double c = aa[1];
+  double s = aa[2];
+  
+  // Get rid of bad fits. The cuts are rather ad hoc
+  
+  //if (aa[3] < 39.64 || aa[3] > 39.68) return;
+  if (chi2/ndata > 4) return;
+  if (cov[1][1] > 0.0001) return;
+  if (cov[2][2] > 0.0001) return;
+
+  double ampl = sqrt(c*c+s*s);
+  double phase = atan2(c,s)/(3.1415926/180);
+  
+#ifdef STARDUMP
+  pendstream << snmid << " " << ampl << " " << phase << " " << ndata << " " << chi2/ndata <<  
+       " "  << cov[1][1] << " " << cov[2][2] << '\n';
+#endif
+  
+  pendulInfo info;
+  info.SN          =   snmid;
+  info.azPendul    =   phase;
+  info.angPendul   =   ampl;
+  pendulInfos[info.SN] = info;
+
+  /*
+  double snum = (matchStars.front().SN + matchStars.back().SN)/2-sn0;
+  if (snmin > snum || snmax < snum) return;
+  double elsst = polval(snum, ae, 3);
+  double azsst = polval(snum, aa, 3);
+  
+  if (azsst > 360) azsst -= 360;
+  if (azsst < 0  ) azsst += 360;
+  */
+  
+//  for (set<TOI>::iterator i = producedTOIs.begin(); i!=producedTOIs.end(); i++) {
+//    if ((*i).name == "azimuthSST")  computedValue((*i), snum+sn0, azsst);
+//    if ((*i).name == "elvSST")      computedValue((*i), snum+sn0, elsst);
+//  }
+  
+  free_vector(sn, 1, matchStars.size());
+  free_vector(elv0, 1, matchStars.size());
+  free_vector(azi, 1, matchStars.size());
+  free_vector(sig, 1, matchStars.size());
+  free_vector(ae, 1, 3);
+  free_vector(aa, 1, 3);
+  free_ivector(ia, 1, matchStars.size());
+  free_matrix(cov, 1, 3, 1, 3);
+}
+
+int StarMatcher::getPendulInfo(double sampleNum, pendulInfo& info) {
+  map<double, pendulInfo>::iterator i = pendulInfos.lower_bound(sampleNum);
+  if (i == pendulInfos.begin() && (*i).second.SN >= sampleNum) return -1;
+  if (i == pendulInfos.end()   && (*i).second.SN <= sampleNum) return -1;
+  
+  if ((*i).second.SN > sampleNum) i--;
+  pendulInfo inf1 = (*i).second;
+  i++;
+  pendulInfo inf2 = (*i).second;
+  
+  info.SN = sampleNum;
+  if (inf2.azPendul - inf1.azPendul > 180)  inf2.azPendul -= 360;
+  if (inf2.azPendul - inf1.azPendul < -180) inf2.azPendul += 360;
+  info.azPendul  = inf1.azPendul  + (inf2.azPendul  -  inf1.azPendul) * (sampleNum - inf1.SN) / (inf2.SN - inf1.SN);
+  if (info.azPendul<0)    info.azPendul += 360;
+  if (info.azPendul>360)  info.azPendul += 360;
+  info.angPendul = inf1.angPendul + (inf2.angPendul - inf1.angPendul) * (sampleNum - inf1.SN) / (inf2.SN - inf1.SN);
+  return 0;
 }
 
 
 double StarMatcher::getValue(long sampleNum, TOI const& toi) {
-  if (lastStars.find(sampleNum) == lastStars.end()) return 0;
-  
-  SSTEtoile lastStar = lastStars[sampleNum];
-
-
-  map<TOI, TOIProducer*> m = neededTOIs[toi];
-  double lat, lon, ts, alpha, delta, az;
-  
-  for (map<TOI, TOIProducer*>::iterator i = m.begin(); i != m.end(); i++) {
-    TOI inToi = (*i).first;
-    TOIProducer* prod =  (*i).second;
-    if (inToi.name == "latitude")  lat = prod->getValue(sampleNum, inToi);
-    if (inToi.name == "longitude") lon = prod->getValue(sampleNum, inToi);
-    if (inToi.name == "tsid")       ts = prod->getValue(sampleNum, inToi);
-    if (inToi.name == "alphaFPC")  alpha = prod->getValue(sampleNum, inToi);
-    if (inToi.name == "deltaFPC")  delta = prod->getValue(sampleNum, inToi);
-    if (inToi.name == "azimuthFPC")   az = prod->getValue(sampleNum, inToi);
-  }
-    
-  // find all stars +- 2 deg boresight
-  double dist = 2;
-  double dmin = delta - dist; if (dmin<-90) dmin=-90;
-  double dmax = delta + dist; if (dmax> 90) dmax= 90;
-  double amin = alpha - dist / cos(delta * 3.1415926/180) / 15.;
-  if (amin<0) amin += 24;
-  double amax = alpha + dist / cos(delta * 3.1415926/180) / 15.;
-  if (amax>24) amax -= 24;
-  
-  int a,b,c;
-  a=0; c=nstars-1;
-  while (a+1<c) {
-    b = (a+c)/2;
-    if (stars[b].dec < dmin) a=b; else c=b;
-  }
-  int imin = a;
-  a=0; c=nstars;
-  while (a+1<c) {
-    b = (a+c)/2;
-    if (stars[b].dec < dmax) a=b; else c=b;
-  }
-  int imax = c;
-
-  for (int i=imin; i<=imax; i++) {
-    if (stars[i].ra >= amin && stars[i].ra <= amax) {
-      double ha = (ts/3600. - stars[i].ra) * 15. * 3.1415926/180.;
-      double elv, azim;
-      hadec_aa(lat * 3.1415926/180., ha, stars[i].dec * 3.1415926/180.,
-               &elv, &azim);
-      elv  *= 180/3.1415926;
-      azim *= 180/3.1415926;
-      if (azim<0) azim += 360;
-     
-      starstream << sampleNum << " " << 
-        /*lastStar.TEchan << " " <<*/ lastStar.NoDiode << " " <<
-        alpha << " " << delta << " " <<
-        az << " " << 
-        stars[i].ra << " " << stars[i].dec << " " <<
-        elv << " " << azim << "\n";
-    }
-  }
-  
-  return 1;
-}
+  processStars();
+  
+  // 1. Interpoler la valeur de pendulation
+  // 2. Interpoler la position en azimuth avec les etoiles encadrant
+  
+  pendulInfo pendul;
+  int rc = getPendulInfo(sampleNum, pendul);
+  if (rc) return -99999;
+  if (toi.name == azimuthPendul) return pendul.azPendul;
+  if (toi.name == anglePendul)   return pendul.angPendul;
+  
+  // find nearest matched star
+  map<double, posInfo>::iterator i = posInfos.lower_bound(sampleNum);
+  if (i == posInfos.begin() && (*i).second.SN >= sampleNum) return -1;
+  if (i == posInfos.end()   && (*i).second.SN <= sampleNum) return -1;
+  if ((*i).second.SN > sampleNum) i--;
+  
+  GondolaGeom geom;
+  geom.setEarthPos((*i).second.lon,(*i).second.lat);
+  geom.setTSid((*i).second.ts);
+  
+  for (map<double, posInfo>::iterator it=i; it != posInfos.end(); it++) {
+    posInfo s = (*it).second;
+    double delsn = s.SN - sampleNum;
+    if (delsn * archParam.acq.perEch > 1) break;
+    geom.addStar(delsn, s.azStar, s.elvStar, s.diodStar);
+  }
+  
+  if (i != posInfos.begin()) i--;
+  for (map<double, posInfo>::iterator it=i; it != posInfos.begin(); it--) {
+    posInfo s = (*it).second;
+    double delsn = s.SN - sampleNum;
+    if (-delsn * archParam.acq.perEch > 1) break;
+    geom.addStar(delsn, s.azStar, s.elvStar, s.diodStar);
+  }
+
+  geom.solveStars();
+  
+  if (toi.name == azimuthAxis) return geom.getAzimutAxis();
+  if (toi.name == elvAxis)     return geom.getElvAxis();
+  if (toi.name == alphaAxis)   return geom.getAlphaAxis();
+  if (toi.name == deltaAxis)   return geom.getDeltaAxis();
+  
+  if (toi.name == azimuthSST)  return geom.getAzimutSST();
+  if (toi.name == elvSST)      return geom.getElvSST();
+  if (toi.name == alphaSST)    return geom.getAlphaSST();
+  if (toi.name == deltaSST)    return geom.getDeltaSST();
+  
+  if (toi.name == azimuthFPC)  return geom.getAzimutCenter();
+  if (toi.name == elvFPC)      return geom.getElvCenter();
+  if (toi.name == alphaFPC)    return geom.getAlphaCenter();
+  if (toi.name == deltaFPC)    return geom.getDeltaCenter();
+
+  if (toi.name == azimuthBolo) return geom.getAzimutBolo(toi.index);
+  if (toi.name == elvBolo)     return geom.getElvBolo(toi.index);
+  if (toi.name == alphaBolo)   return geom.getAlphaBolo(toi.index);
+  if (toi.name == deltaBolo)   return geom.getDeltaBolo(toi.index);
+
+  return -99999;
+}
+
+bool StarMatcher::canGetValue(long sampleNum, TOI const& /*toi*/) {
+  processStars();
+
+  map<double, pendulInfo>::iterator i = pendulInfos.begin();
+  if (i == pendulInfos.end()) return false;
+  if (sampleNum < (*i).second.SN) return false;
+  i = pendulInfos.end(); i--;
+  if (sampleNum > (*i).second.SN) return false;
+  
+  return true;
+}
+
+bool StarMatcher::canGetValueLater(long sampleNum, TOI const& /*toi*/) {
+  processStars();
+  
+  map<double, pendulInfo>::iterator i = pendulInfos.end();
+  if (i == pendulInfos.begin()) return true;
+  i--;
+  return (sampleNum > (*i).second.SN);
+}
+
 
 
@@ -121,17 +618,39 @@
   t.insert(TOI("longitude", TOI::unspec, "interp"));
   t.insert(TOI("tsid",      TOI::unspec));
-  t.insert(TOI("alphaFPC",  TOI::unspec, "galcross0"));
-  t.insert(TOI("deltaFPC",  TOI::unspec, "galcross0"));
-  t.insert(TOI("azimuthFPC",  TOI::unspec, "galcross0"));
+  t.insert(TOI("alphaSST",  TOI::unspec, "galcross0"));
+  t.insert(TOI("deltaSST",  TOI::unspec, "galcross0"));
+  t.insert(TOI("azimuthSST",TOI::unspec, "galcross0"));
+  t.insert(TOI("elvSST",    TOI::unspec, "galcross0"));
+  t.insert(TOI("rotSpeed",  TOI::unspec, "galcross0"));
   return t;
 }
 
 void StarMatcher::propagateLowBound(TOI const& toi, long sampleNum) {
-  for (map<long,SSTEtoile>::iterator i = lastStars.begin(); i != lastStars.end(); i++)
-    if ((*i).first < sampleNum) lastStars.erase(i);
-}
-
-
-
-
-
+  map<double, posInfo>::iterator i = posInfos.begin();
+  while (i != posInfos.end() && (*i).first < sampleNum) i++;
+  if (i != posInfos.begin()) {
+    i--;
+    posInfos.erase(posInfos.begin(), i);
+  }
+
+  map<double, pendulInfo>::iterator j = pendulInfos.begin();
+  while (j != pendulInfos.end() && (*j).first < sampleNum) j++;
+  if (j != pendulInfos.begin()) {
+    j--;
+    pendulInfos.erase(pendulInfos.begin(), j);
+  }
+
+  TOIDerivProducer::propagateLowBound(toi, sampleNum);
+}
+
+
+// 1. processStars seulement quand au moins 10 etoiles nouvelles
+// 2. Nettoyer avec fit parabolique sur les 5 dernieres seconde de donnees
+// 3. Garder periodeRotation secondes de donnees nettoyees
+// 4. TF ordre 0 sur ces donnees, amplitude et phase -> theta et phi pendulation,
+//     elevationSST = elv-theta Sin[azimut-phi]
+//     azimutSST    = azimut+theta Cos[azimut-phi] Tan[elv] (+ OFFSET GALCROSS)
+//   le signal le plus propre est l'elevation -> fit dessus, puis
+//   correction azimut SST a partir seconde equation, sans utiliser azimut galcross
+
+
Index: trunk/Poubelle/archTOI.old/starmatcher.h
===================================================================
--- trunk/Poubelle/archTOI.old/starmatcher.h	(revision 554)
+++ trunk/Poubelle/archTOI.old/starmatcher.h	(revision 555)
@@ -1,2 +1,5 @@
+// starmatcher.h
+// Eric Aubourg         CEA/DAPNIA/SPP   novembre 1999
+
 #ifndef STARMATCHER_H
 #define STARMATCHER_H
@@ -4,7 +7,7 @@
 
 #include "sststarfinder.h"
-#include "toipullproducer.h"
+#include "toiderivproducer.h"
 
-class StarMatcher: public SSTStarProcessor, public TOIPullProducer {
+class StarMatcher: public SSTStarProcessor, public TOIDerivProducer {
 public:
   StarMatcher();
@@ -14,9 +17,12 @@
   virtual string getName();
   virtual double getValue(long sampleNum, TOI const& toi);
+  virtual bool   canGetValue(long sampleNum, TOI const& toi);
+  virtual bool   canGetValueLater(long sampleNum, TOI const& toi);
 
 protected:
   virtual set<TOI>     reqTOIFor(TOI const&);
-  void  propagateLowBound(TOI const& toi, long sampleNum);
-#pragma options align=mac68k
+  void propagateLowBound(TOI const& toi, long sampleNum);
+  void processStars();
+
   struct gscStar {
     float ra;
@@ -24,10 +30,51 @@
     short mag; // mag * 100
   };
-#pragma options align=reset
+
   
   gscStar* stars;
   long nstars;
   
-  map<long,SSTEtoile> lastStars;
+  deque<SSTEtoile> lastStars;
+  
+  struct matchStar {
+    double SN;
+    double raGSC;
+    double decGSC;
+    double azGSC;
+    double elvGSC;
+    int    nDiode;
+    bool   ok;
+    long   seq;
+    double lon;
+    double lat;
+    double ts;
+  };
+  
+  long lastSeq;
+  
+  deque<matchStar> matchStars;
+  deque<matchStar> cleanStars;
+  
+  struct pendulInfo {
+    double SN;
+    double azPendul;
+    double angPendul;
+  };
+  
+  struct posInfo {
+    double SN;
+    double azStar;
+    double elvStar;
+    double diodStar;
+    double lon;
+    double lat;
+    double ts;
+  };
+  
+  map<double, posInfo> posInfos; // sampleNum -> info
+  map<double, pendulInfo> pendulInfos; // sampleNum -> info
+  
+  int getPendulInfo(double sampleNum, pendulInfo& info); // interpolate
+  
 };
 
Index: trunk/Poubelle/archTOI.old/subsets.h
===================================================================
--- trunk/Poubelle/archTOI.old/subsets.h	(revision 555)
+++ trunk/Poubelle/archTOI.old/subsets.h	(revision 555)
@@ -0,0 +1,37 @@
+// subsets.h
+// Eric Aubourg         CEA/DAPNIA/SPP   octobre 1999
+
+#ifndef SUBSETS_H
+#define SUBSETS_H
+
+template <class T>
+ set<set<T> > getSetOfSubsets(set<T> const&);
+ 
+ 
+template <class T>
+ set<set<T> > getSetOfSubsets(set<T> const& s) {
+ set<set<T> > subsets;
+ if (s.empty()) {
+   subsets.insert(s);
+   return subsets;
+ }
+ 
+ set<T> s1 = s; 
+ T x = *(s1.begin());
+ s1.erase(s1.begin());
+ set<set<T> > sub1 = getSetOfSubsets(s1);
+ subsets.insert(sub1.begin(), sub1.end());
+ for (set<set<T> >::iterator i = sub1.begin(); i != sub1.end(); i++) {
+   s1 = *i;
+   s1.insert(x);
+   subsets.insert(s1);
+ }
+ return subsets;
+}
+
+// subsets 1 2 3 :
+//    subsets 2 3 :  {} {2} {3} {23}
+//       + 1:        {1} {12} {13} {123}
+ 
+ 
+#endif
Index: trunk/Poubelle/archTOI.old/templocator.cc
===================================================================
--- trunk/Poubelle/archTOI.old/templocator.cc	(revision 554)
+++ trunk/Poubelle/archTOI.old/templocator.cc	(revision 555)
@@ -1,3 +1,4 @@
 #include "templocator.h"
+#include "gondolageom.h"
 #include <math.h>
 extern "C" {
@@ -161,19 +162,19 @@
 }
 
-double TempLocator::getAzimutBolo(int sampleNum, int ibolo) {
-  double elv, az;
-  getAltAzBolo(sampleNum, ibolo, elv, az);
+double TempLocator::getAzimutSST(int sampleNum) {
+  findGeomFromGC(sampleNum);
+  double az = azimBolGC;
+  if (az>360) az -= 360;
+  if (az<0)   az += 360;
   return az;
 }
 
-double TempLocator::getElvBolo(int sampleNum, int ibolo) {
-  double elv, az;
-  getAltAzBolo(sampleNum, ibolo, elv, az);
-  return elv;
-}
-
-double TempLocator::getAlphaBolo(int sampleNum, int ibolo) {
-  double elv, az;
-  getAltAzBolo(sampleNum, ibolo, elv, az);
+double TempLocator::getElvSST(int /*sampleNum*/) {
+  return GondolaGeom::elevSST0;
+}
+
+double TempLocator::getAlphaSST(int sampleNum) {
+  double elv = getElvSST(sampleNum);
+  double az  = getAzimutSST(sampleNum);
   double ha;
   double ra,dec;
@@ -182,5 +183,46 @@
   while (ra>24) ra -= 24;
   while (ra<0) ra += 24;
+  //dec = dec * 180. / M_PI;
+  return ra;
+}
+
+double TempLocator::getDeltaSST(int sampleNum) {
+  double elv = getElvSST(sampleNum);
+  double az  = getAzimutSST(sampleNum);
+  double ha;
+  //double ra;
+  double dec;
+  aa_hadec (lat * M_PI/180, elv * M_PI/180, az * M_PI/180, &ha, &dec);
+  //ra = - (ha * 180. / M_PI / 15) + (ts/3600.);
+  //while (ra>24) ra -= 24;
+  //while (ra<0) ra += 24;
   dec = dec * 180. / M_PI;
+  return dec;
+}
+
+
+
+double TempLocator::getAzimutBolo(int sampleNum, int ibolo) {
+  double elv, az;
+  getAltAzBolo(sampleNum, ibolo, elv, az);
+  return az;
+}
+
+double TempLocator::getElvBolo(int sampleNum, int ibolo) {
+  double elv, az;
+  getAltAzBolo(sampleNum, ibolo, elv, az);
+  return elv;
+}
+
+double TempLocator::getAlphaBolo(int sampleNum, int ibolo) {
+  double elv, az;
+  getAltAzBolo(sampleNum, ibolo, elv, az);
+  double ha;
+  double ra,dec;
+  aa_hadec (lat * M_PI/180, elv * M_PI/180, az * M_PI/180, &ha, &dec);
+  ra = - (ha * 180. / M_PI / 15) + (ts/3600.);
+  while (ra>24) ra -= 24;
+  while (ra<0) ra += 24;
+  //dec = dec * 180. / M_PI;
   return ra;
 }
@@ -190,7 +232,10 @@
   getAltAzBolo(sampleNum, ibolo, elv, az);
   double ha;
-  double ra,dec;
-  aa_hadec (lat * M_PI/180, elv * M_PI/180, az * M_PI/180, &ha, &dec);
-  ra = - (ha * 180. / M_PI / 15) + (ts/3600.);
+  //double ra;
+  double dec;
+  aa_hadec (lat * M_PI/180, elv * M_PI/180, az * M_PI/180, &ha, &dec);
+  //ra = - (ha * 180. / M_PI / 15) + (ts/3600.);
+  //while (ra>24) ra -= 24;
+  //while (ra<0) ra += 24;
   dec = dec * 180. / M_PI;
   return dec;
Index: trunk/Poubelle/archTOI.old/templocator.h
===================================================================
--- trunk/Poubelle/archTOI.old/templocator.h	(revision 554)
+++ trunk/Poubelle/archTOI.old/templocator.h	(revision 555)
@@ -23,4 +23,8 @@
   double getAlphaCenter(int sampleNum);
   double getDeltaCenter(int sampleNum);
+  double getAzimutSST(int sampleNum); // diode 0
+  double getElvSST(int sampleNum);
+  double getAlphaSST(int sampleNum);
+  double getDeltaSST(int sampleNum);
   double getRotSpeed(int sampleNum); // deg/sec
   int    getCrossSamples(int sampleNum, int& SN1, int& SN2);
Index: trunk/Poubelle/archTOI.old/toi.cc
===================================================================
--- trunk/Poubelle/archTOI.old/toi.cc	(revision 554)
+++ trunk/Poubelle/archTOI.old/toi.cc	(revision 555)
@@ -60,5 +60,5 @@
 }
 
-string TOI::fullName() {
+string TOI::fullName() const {
  string s = name;
  if (index == all) { s += " all";}
@@ -67,5 +67,5 @@
    s += string(" ")+idx;
  }
- for (set<string>::iterator i = options.begin(); i!=options.end(); i++) {
+ for (set<string>::const_iterator i = options.begin(); i!=options.end(); i++) {
    s += " " + *i;
  }
Index: trunk/Poubelle/archTOI.old/toi.h
===================================================================
--- trunk/Poubelle/archTOI.old/toi.h	(revision 554)
+++ trunk/Poubelle/archTOI.old/toi.h	(revision 555)
@@ -30,5 +30,5 @@
   void findref();
   
-  string fullName();
+  string fullName() const;
 };
 
Index: trunk/Poubelle/archTOI.old/toiboloproducer.cc
===================================================================
--- trunk/Poubelle/archTOI.old/toiboloproducer.cc	(revision 554)
+++ trunk/Poubelle/archTOI.old/toiboloproducer.cc	(revision 555)
@@ -42,5 +42,5 @@
 void TOIBoloProducer::propagateLowBound(TOI const& toi, long sampleNum) {
   CHKPROD
-  map<TOI, TOIProducer*> need = neededTOIs[toi];
+  map<TOI, TOIProducer*> & need = neededTOIs[toi];
   int hlen = 1;
   for (map<TOI, TOIProducer*>::iterator i = need.begin(); i != need.end(); i++) {
Index: trunk/Poubelle/archTOI.old/toiderivproducer.cc
===================================================================
--- trunk/Poubelle/archTOI.old/toiderivproducer.cc	(revision 554)
+++ trunk/Poubelle/archTOI.old/toiderivproducer.cc	(revision 555)
@@ -6,4 +6,5 @@
 #include "archexc.h"
 #include "requesthandler.h"
+#include "subsets.h"
 
 set<TOI> TOIDerivProducer::reqTOIFor(TOI const&) { 
@@ -61,4 +62,6 @@
   }
   
+  set<string> unusedextra = extraopts;
+  
   // 4. Find producers, distribute remaining options
   map<TOI, TOIProducer*> fullInputTOI;
@@ -66,5 +69,21 @@
   for (set<TOI>::iterator i = inputTOIs.begin(); i != inputTOIs.end(); i++) {
     TOI inTOI = *i;
-    TOIProducer* prod = TOIManager::findTOIProducer(inTOI);
+    //TOIProducer* prod0 = TOIManager::findTOIProducer(inTOI);
+    // Let's see if we get others with options, we have to do this because
+    // of required options, and we have to iterate over all subsets of the options.
+    // This algorithm is NOT correct, but should work for realistic cases...
+    int nmaxopt=-1;
+    TOIProducer* prod=NULL;
+    set<set<string> > optsets = getSetOfSubsets(extraopts);
+    for (set<set<string> >::iterator j = optsets.begin(); j != optsets.end(); j++) {
+      TOI toi2 = inTOI;
+      toi2.options.insert((*j).begin(), (*j).end());
+      TOIProducer* prod0 = TOIManager::findTOIProducer(toi2);
+      if (prod0 == NULL) continue;
+      if ((long) toi2.options.size() > nmaxopt) {
+        prod = prod0;
+        nmaxopt = toi2.options.size();
+      }
+    }
     if (!prod) return false;
     if (!extraopts.empty()) {
@@ -73,5 +92,5 @@
         if (extraopts.find(*j) != extraopts.end()) {
           inTOI.options.insert(*j);
-          extraopts.erase(*j);
+          unusedextra.erase(*j);
         }
       }
@@ -80,5 +99,5 @@
   }
   
-  if (!extraopts.empty()) return false;
+  if (!unusedextra.empty()) return false;
   
   neededTOIs[toi] = fullInputTOI;
@@ -91,5 +110,5 @@
  // if (!canProduce(toi)) throw ArchExc("cannot produce " + toi.name);
   set<string> s = getProperAvailOptions(toi);
-  map<TOI, TOIProducer*> need = neededTOIs[toi];
+  map<TOI, TOIProducer*> & need = neededTOIs[toi];
   for (map<TOI, TOIProducer*>::iterator i = need.begin(); i != need.end(); i++) {
     set<string> s1 = (*i).second->getAvailOptions((*i).first);
@@ -101,5 +120,5 @@
 void TOIDerivProducer::addTOI(TOI& toi, TOIAbsorber* client) {
   TOIProducer::addTOI(toi, client);
-  map<TOI, TOIProducer*> m = neededTOIs[toi];
+  map<TOI, TOIProducer*> & m = neededTOIs[toi];
   for (map<TOI, TOIProducer*>::iterator i = m.begin(); i != m.end(); i++) {
     TOI toi2 = (*i).first;
@@ -117,5 +136,5 @@
 void TOIDerivProducer::propagateLowBound(TOI const& toi, long sampleNum) {
   CHKPROD
-  map<TOI, TOIProducer*> need = neededTOIs[toi];
+  map<TOI, TOIProducer*> & need = neededTOIs[toi];
   for (map<TOI, TOIProducer*>::iterator i = need.begin(); i != need.end(); i++) {
     (*i).second->wontNeedEarlier((*i).first, this, sampleNum);
Index: trunk/Poubelle/archTOI.old/toiinterpolator.cc
===================================================================
--- trunk/Poubelle/archTOI.old/toiinterpolator.cc	(revision 554)
+++ trunk/Poubelle/archTOI.old/toiinterpolator.cc	(revision 555)
@@ -1,82 +1,100 @@
 // toiinterpolator.cc
-// Eric Aubourg         CEA/DAPNIA/SPP   juillet 1999
+// Eric Aubourg         CEA/DAPNIA/SPP   octobre 1999
 
 
 #include "toiinterpolator.h"
+#include "toimanager.h"
+#include "archexc.h"
 
-void TOIInterpolator::enterValue(double value, long sample)
-{
-  // $CHECK$ sample > back.sample
-  if (!hist.empty() && sample == hist.back().t) return; // pour eviter /0
-  hist.push_back(pair(value, sample));
+TOIInterpolator::TOIInterpolator() {
 }
 
-bool TOIInterpolator::needMoreDataFor(long sample)
-{
-  if (hist.empty()) return true;
-  int xx = hist.back().t;
-  return (hist.empty() || sample > xx);
+
+string TOIInterpolator::getName() {
+  return("TOIInterpolator 1.0");
 }
 
-bool TOIInterpolator::canGet(long sample)
-{
-  return (!hist.empty() && (sample >= hist.front().t && sample <= hist.back().t));
+bool TOIInterpolator::canProduce(TOI const& toi) {
+  // 1. Already in cache ?
+  map<TOI, map<TOI, TOIProducer*> >::const_iterator j = neededTOIs.find(toi);
+  if (j != neededTOIs.end()) return true;
+
+  // 2. Should have interp
+  if (toi.options.find("interp") == toi.options.end()) return false;
+  
+  // 3. Can get non interp
+  TOI toi2 = toi;
+  toi2.options.erase("interp");
+  TOIProducer* prod = TOIManager::findTOIProducer(toi2);
+  set<string> opts = prod->getAvailOptions(toi2);
+  if (opts.find("interp") != opts.end()) return false; // already handled
+  if (opts.find("repet") != opts.end()) return false;  // not compatible !
+  
+  map<TOI, TOIProducer*> fullInputTOI;
+  fullInputTOI[toi2] = prod;
+  neededTOIs[toi] = fullInputTOI;
+  return true;
 }
 
-double TOIInterpolator::getEValue(long sample) // can forget before sample
-{
-  if (!canGet(sample)) return -9.e99;   // user should have checked before
-  deque<pair>::iterator i = hist.begin();
-  while ((*i).t < sample) i++;
-  if ((*i).t > sample) i--;
-  double value = (*i).val;
-  if (i != hist.begin()) {
-    i--;
-    hist.erase(hist.begin(), i);
-  }
-  return value;
+set<TOI> TOIInterpolator::reqTOIFor(TOI const& toi) {
+  set<TOI> x;
+  if (!canProduce(toi)) return x;
+  x.insert((*neededTOIs[toi].begin()).first);
+  return x;
 }
 
-double TOIInterpolator::getIValue(long sample) // can forget before sample
-{
-  if (!canGet(sample)) return -9.e99;   // user should have checked before
+bool TOIInterpolator::canGetValue(long sampleNum, TOI const& toi) {
+  map<TOI, TOIProducer*> & inp = neededTOIs[toi];
+  TOIProducer* prod  = (*inp.begin()).second;
+  TOI const&   inTOI = (*inp.begin()).first;
   
-  deque<pair>::iterator i = hist.begin();
-  while ((*i).t < sample) i++;
-  double value;
-  if ((*i).t == sample) {
-    value = (*i).val;
-  } else {    
-    long samp2 = (*i).t;
-    double val2 = (*i).val;
-    i--;
-    long samp1 = (*i).t;
-    double val1 = (*i).val;
-    value = val1 + (val2-val1)*(sample-samp1)/(samp2-samp1);
-  }
-  if (i != hist.begin()) {
-    i--;
-    hist.erase(hist.begin(), i);
-  }
-  return value;
-}
-
-bool TOIInterpolator::isNewValue(long sample) 
-{
-  deque<pair>::iterator i = hist.begin();
-  while (i!=hist.end()) {
-    if ((*i).t == sample) return true;
-    if ((*i).t > sample) return false;
-    i++;
-  }
+  if (prod->canGetValue(sampleNum, inTOI)) return true; // direct
+  if (prod->canGetPrevValue(sampleNum, inTOI) &&
+      prod->canGetNextValue(sampleNum, inTOI)) return true;
   return false;
 }
 
-
-long TOIInterpolator::nextSample(long sampleMin)
-{
-  for (deque<pair>::iterator i = hist.begin(); i<hist.end(); i++) 
-    if ((*i).t >= sampleMin) return (*i).t;
-  return -1;
+bool TOIInterpolator::canGetValueLater(long sampleNum, TOI const& toi) {
+  map<TOI, TOIProducer*> & inp = neededTOIs[toi];
+  TOIProducer* prod  = (*inp.begin()).second;
+  TOI const&   inTOI = (*inp.begin()).first;
+  
+  if (prod->canGetValue(sampleNum, inTOI)) return false; // direct
+  if (prod->canGetValueLater(sampleNum, inTOI)) return true; // direct
+  if (!prod->canGetPrevValue(sampleNum, inTOI)) return false; // no hope
+  if (prod->canGetNextValue(sampleNum, inTOI)) return false; // can get now
+  return true;
 }
 
+double TOIInterpolator::getValue(long sampleNum, TOI const& toi) {
+  map<TOI, TOIProducer*> & inp = neededTOIs[toi];
+  TOIProducer* prod  = (*inp.begin()).second;
+  TOI const&   inTOI = (*inp.begin()).first;
+
+  if (prod->canGetValue(sampleNum, inTOI))
+     return prod->getValue(sampleNum, inTOI); // direct
+     
+  long sn1 = sampleNum;
+  double v1 = prod->getPrevValue(sn1, inTOI);
+  
+  long sn2 = sampleNum;
+  double v2 = prod->getNextValue(sn2, inTOI);
+
+  if (sn1 == sn2) throw ArchExc("Inconsistence in interp, sn1==sn2");
+
+  return v1 + (v2-v1) * (sampleNum-sn1) / (sn2-sn1);
+}
+
+
+void TOIInterpolator::propagateLowBound(TOI const& toi, long sampleNum) {
+  CHKPROD
+  map<TOI, TOIProducer*> & inp = neededTOIs[toi];
+  TOIProducer* prod  = (*inp.begin()).second;
+  TOI const&   inTOI = (*inp.begin()).first;
+  if (prod->canGetPrevValue(sampleNum,toi)) {
+    prod->getPrevValue(sampleNum, toi);
+    sampleNum--;
+    prod->wontNeedEarlier(toi, this, sampleNum);
+  }
+}
+
Index: trunk/Poubelle/archTOI.old/toiinterpolator.h
===================================================================
--- trunk/Poubelle/archTOI.old/toiinterpolator.h	(revision 554)
+++ trunk/Poubelle/archTOI.old/toiinterpolator.h	(revision 555)
@@ -1,4 +1,4 @@
 // toiinterpolator.h
-// Eric Aubourg         CEA/DAPNIA/SPP   juillet 1999
+// Eric Aubourg         CEA/DAPNIA/SPP   octobre 1999
 
 
@@ -6,29 +6,20 @@
 #define TOIINTERPOLATOR_H
 
-#include <deque>
-
-using namespace std;
+#include "toipullproducer.h"
 
 
-class TOIInterpolator {
+class TOIInterpolator : public TOIPullProducer {
 public:
-
-  void enterValue(double value, long sample);
-  bool   needMoreDataFor(long sample);   // need more data ? (for interp)
-  bool   canGet(long sample);        // enough info ?
-  double getIValue(long sample);     // can forget before sample
-  double getEValue(long sample);     // can forget before sample
-  bool   isNewValue(long sample);    
-  long   nextSample(long sampleMin); // the next true sample available
+  TOIInterpolator();
+  virtual string getName();
+  virtual double getValue(long sampleNum, TOI const& toi);
+  virtual bool   canGetValue(long sampleNum, TOI const& toi);
+  virtual bool   canGetValueLater(long sampleNum, TOI const& toi);
+  virtual bool   canProduce(TOI const&);
 
 protected:
-  struct pair {
-    pair(double v, long tt) : val(v), t(tt) {}
-    pair() {}
-    double val;
-    long t;
-  };
-  
-  deque<pair> hist;
+  virtual set<TOI>     reqTOIFor(TOI const&);
+  void                 propagateLowBound(TOI const& toi, long sampleNum);
+
 };
 
Index: trunk/Poubelle/archTOI.old/toiiter.cc
===================================================================
--- trunk/Poubelle/archTOI.old/toiiter.cc	(revision 554)
+++ trunk/Poubelle/archTOI.old/toiiter.cc	(revision 555)
@@ -272,6 +272,10 @@
   if (curSample >= sEnd || archParam.acq.SN2MJD(curSample) >= mjdEnd) return false;
   
-  for (int i=0; i<request.size(); i++)
-    request[i].second->wontNeedEarlier(request[i].first, this, curSample);
+  static long lastClean = 0;
+  if (curSample - lastClean > 100) {
+    for (int i=0; i<request.size(); i++)
+      request[i].second->wontNeedEarlier(request[i].first, this, curSample);
+    lastClean = curSample;
+  }
 
   bool endFound = false;
Index: trunk/Poubelle/archTOI.old/toimanager.cc
===================================================================
--- trunk/Poubelle/archTOI.old/toimanager.cc	(revision 554)
+++ trunk/Poubelle/archTOI.old/toimanager.cc	(revision 555)
@@ -77,4 +77,7 @@
 
 #include "timetoiproducer.h"
+#include "toiinterpolator.h"
+#include "toirepeater.h"
+#include "toiflagger.h"
 #include "toiboloproducer.h"
 #include "sststarfinder.h"
@@ -82,4 +85,6 @@
 #include "galcrosslocator.h"
 #include "starmatcher.h"
+#include "rotspeed.h"
+#include "gyrocalibrator.h"
 
 void TOIManager::registerDefaultProducers() {
@@ -92,4 +97,7 @@
   
   REGPROD(TimeTOIProducer);
+  REGPROD(TOIInterpolator);
+  REGPROD(TOIRepeater);
+  REGPROD(TOIFlagger);
   REGPROD(TOIBoloProducer);
   REGPROD(SSTStarFinder);
@@ -97,4 +105,6 @@
   REGPROD(GalCrossLocator);
   REGPROD(StarMatcher);
+  REGPROD(RotSpeed);
+  REGPROD(GyroCalibrator);
 }
 
Index: trunk/Poubelle/archTOI.old/toiproducer.cc
===================================================================
--- trunk/Poubelle/archTOI.old/toiproducer.cc	(revision 554)
+++ trunk/Poubelle/archTOI.old/toiproducer.cc	(revision 555)
@@ -57,5 +57,5 @@
   // should be nothing left
   if (!extraopts.empty()) return false;
-  
+
   return true;
 }
@@ -129,6 +129,7 @@
 
 class comp2nd { public:bool operator()(pair<long, double> const& a, long b) {return a.first<b;}};
-
-deque<pair<long, double> >::const_iterator TOIProducer::findHist(TOI const& toi,long sampleNum) {
+class comp2ndI { public:bool operator()(long a, pair<long, double> const& b) {return a<b.first;}};
+
+deque<pair<long, double> >::const_iterator TOIProducer::findHistL(TOI const& toi,long sampleNum) {
   CHKPROD
   deque<pair<long, double> >& h = history[toi.ref];
@@ -136,7 +137,18 @@
 }
 
-deque<pair<long, double> >::const_iterator TOIProducer::findHist(deque<pair<long, double> >& h,long sampleNum) {
+deque<pair<long, double> >::const_iterator TOIProducer::findHistL(deque<pair<long, double> >& h,long sampleNum) {
   return lower_bound(h.begin(), h.end(), sampleNum, comp2nd());
 }
+
+deque<pair<long, double> >::const_iterator TOIProducer::findHistH(TOI const& toi,long sampleNum) {
+  CHKPROD
+  deque<pair<long, double> >& h = history[toi.ref];
+  return upper_bound(h.begin(), h.end(), sampleNum, comp2ndI());
+}
+
+deque<pair<long, double> >::const_iterator TOIProducer::findHistH(deque<pair<long, double> >& h,long sampleNum) {
+  return upper_bound(h.begin(), h.end(), sampleNum, comp2ndI());
+}
+
 
 bool TOIProducer::canGetValue(long sampleNum, TOI const& toi) {
@@ -145,5 +157,5 @@
   if (h.empty()) return false;
   if (sampleNum < h.front().first || sampleNum > h.back().first) return false;
-  deque<pair<long, double> >::const_iterator i = findHist(h, sampleNum);
+  deque<pair<long, double> >::const_iterator i = findHistL(h, sampleNum);
   if (i == h.end()) return false;
   return ((*i).first == sampleNum);
@@ -163,5 +175,5 @@
   deque<pair<long, double> >& h = history[toi.ref];
   if (h.empty()) return false;
-  return (sampleNum > h.back().first && sampleNum <= h.front().first);
+  return (sampleNum > h.front().first && sampleNum <= h.back().first);
    // Must be inside, otherwise we don't know if it is prev or simply past
 }
@@ -171,5 +183,5 @@
   deque<pair<long, double> >& h = history[toi.ref];
   if (h.empty()) return false;
-  return (sampleNum >= h.back().first && sampleNum < h.front().first);
+  return (sampleNum >= h.front().first && sampleNum < h.back().first);
 }
 
@@ -179,5 +191,5 @@
 //       << h.front().first 
 //       << " " << h.back().first << endl;
-  deque<pair<long, double> >::const_iterator i = findHist(h, sampleNum);
+  deque<pair<long, double> >::const_iterator i = findHistL(h, sampleNum);
   if (i == h.end()) return -999999;
 //  cout << "found " << (*i).first << endl;
@@ -189,10 +201,12 @@
 double TOIProducer::getPrevValue(long& sampleNum, TOI const& toi) {
   deque<pair<long, double> >& h = history[toi.ref];
-  deque<pair<long, double> >::const_iterator i = findHist(h, sampleNum);
+  deque<pair<long, double> >::const_iterator i = findHistH(h, sampleNum);
   if (i == h.end()) return -999999;
-  if ((*i).first == sampleNum) {
+  pair<long, double> tstpair = *i;
+  while ((*i).first >= sampleNum) {
     if (i == history[toi.ref].begin()) {sampleNum = -99999 ;return -9999;}
     i--;
   }
+  tstpair = *i;
   sampleNum = (*i).first;
   return (*i).second;
@@ -201,10 +215,12 @@
 double TOIProducer::getNextValue(long& sampleNum, TOI const& toi) {
   deque<pair<long, double> >& h = history[toi.ref];
-  deque<pair<long, double> >::const_iterator i = findHist(h, sampleNum);
+  deque<pair<long, double> >::const_iterator i = findHistL(h, sampleNum);
   if (i == h.end()) return -999999;
-  if ((*i).first == sampleNum) {
+  pair<long, double> tstpair = *i;
+  while ((*i).first <= sampleNum) {
     if (i == history[toi.ref].end()) {sampleNum = -99999 ;return -9999;}
     i++;
   }
+  tstpair=*i;
   sampleNum = (*i).first;
   return (*i).second;
@@ -212,11 +228,11 @@
 
 void TOIProducer::computedValue(TOI const& toi, long sampleNum, double value) {
-  map<int, deque<pair<long, double> > >::iterator i = history.find(toi.ref);
-  if (i == history.end()) throw ArchExc("computedValue : bad TOI " + toi.name);
-  deque<pair<long, double> >& h = (*i).second;
+  //map<int, deque<pair<long, double> > >::iterator i = history.find(toi.ref);
+  //if (i == history.end()) throw ArchExc("computedValue : bad TOI " + toi.name);
+  //deque<pair<long, double> >& h = (*i).second;
+  deque<pair<long, double> >& h = history[toi.ref];
   if (!h.empty() && sampleNum <= h.back().first)
     throw ArchExc("computedValue : sampleNum not in sequence for " + toi.name);
   h.push_back(pair<long,double>(sampleNum,value));
-  
   for (map<TOIAbsorber*, set<TOI> >::iterator j = clients.begin(); j != clients.end(); j++) {
     set<TOI>& tois = (*j).second;
Index: trunk/Poubelle/archTOI.old/toiproducer.h
===================================================================
--- trunk/Poubelle/archTOI.old/toiproducer.h	(revision 554)
+++ trunk/Poubelle/archTOI.old/toiproducer.h	(revision 555)
@@ -60,6 +60,8 @@
   map<int, deque<pair<long, double> > >  history;
   
-  deque<pair<long, double> >::const_iterator findHist(TOI const& toi, long sampleNum);
-  deque<pair<long, double> >::const_iterator findHist(deque<pair<long, double> >& h, long sampleNum);
+  deque<pair<long, double> >::const_iterator findHistL(TOI const& toi, long sampleNum);
+  deque<pair<long, double> >::const_iterator findHistL(deque<pair<long, double> >& h, long sampleNum);
+  deque<pair<long, double> >::const_iterator findHistH(TOI const& toi, long sampleNum);
+  deque<pair<long, double> >::const_iterator findHistH(deque<pair<long, double> >& h, long sampleNum);
 };
 
Index: trunk/Poubelle/archTOI.old/toipullproducer.cc
===================================================================
--- trunk/Poubelle/archTOI.old/toipullproducer.cc	(revision 554)
+++ trunk/Poubelle/archTOI.old/toipullproducer.cc	(revision 555)
@@ -10,5 +10,5 @@
 
 bool TOIPullProducer::canGetValue(long sampleNum, TOI const& toi) {
-  map<TOI, TOIProducer*> m = neededTOIs[toi];
+  map<TOI, TOIProducer*> & m = neededTOIs[toi];
   for (map<TOI, TOIProducer*>::iterator i = m.begin(); i != m.end(); i++) {
     if (!(*i).second->canGetValue(sampleNum-needBefore, (*i).first) ||
@@ -27,5 +27,5 @@
 
 bool TOIPullProducer::canGetValueLater(long sampleNum, TOI const& toi) {
-  map<TOI, TOIProducer*> m = neededTOIs[toi];
+  map<TOI, TOIProducer*> & m = neededTOIs[toi];
   for (map<TOI, TOIProducer*>::iterator i = m.begin(); i != m.end(); i++) {
     if (!(*i).second->canGetValueLater(sampleNum+needAfter, (*i).first)) return false;
@@ -46,5 +46,5 @@
 long TOIPullProducer::firstSampleNum(TOI const& toi) {
   long xx = -999999999L;
-  map<TOI, TOIProducer*> m = neededTOIs[toi];
+  map<TOI, TOIProducer*> & m = neededTOIs[toi];
   for (map<TOI, TOIProducer*>::iterator i = m.begin(); i != m.end(); i++) {
     long x = (*i).second->firstSampleNum((*i).first) + needBefore;
@@ -56,5 +56,5 @@
 long TOIPullProducer::lastSampleNum(TOI const& toi) {
   long xx = 999999999L;
-  map<TOI, TOIProducer*> m = neededTOIs[toi];
+  map<TOI, TOIProducer*> & m = neededTOIs[toi];
   for (map<TOI, TOIProducer*>::iterator i = m.begin(); i != m.end(); i++) {
     long x = (*i).second->lastSampleNum((*i).first) - needAfter;
@@ -66,5 +66,5 @@
 void TOIPullProducer::propagateLowBound(TOI const& toi, long sampleNum) {
   CHKPROD
-  map<TOI, TOIProducer*> need = neededTOIs[toi];
+  map<TOI, TOIProducer*> & need = neededTOIs[toi];
   for (map<TOI, TOIProducer*>::iterator i = need.begin(); i != need.end(); i++) {
     (*i).second->wontNeedEarlier((*i).first, this, sampleNum-needBefore);
Index: trunk/Poubelle/archTOI.old/tsidproducer.cc
===================================================================
--- trunk/Poubelle/archTOI.old/tsidproducer.cc	(revision 554)
+++ trunk/Poubelle/archTOI.old/tsidproducer.cc	(revision 555)
@@ -22,7 +22,7 @@
 
 double TSidProducer::getValue(long sampleNum, TOI const& toi) {
-  map<TOI, TOIProducer*> m = neededTOIs[toi];
+  map<TOI, TOIProducer*> & m = neededTOIs[toi];
   // Seulement longitude... 
-  TOI longTOI = (*m.begin()).first;
+  TOI const& longTOI = (*m.begin()).first;
   TOIProducer* longProd =  (*m.begin()).second;
   myTS.setLongitude(longProd->getValue(sampleNum, longTOI));
