• Main Page
  • Data Structures
  • Files

time.c

Go to the documentation of this file.
00001 /*
00002  * This file is part of Titan2Reader
00003  *
00004  * Copyright (C) 2006, Sebastien Judenherc <sebastien.judenherc@agecodagis.com>
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
00019  * USA
00020  *
00021  */
00022 
00023 #include <stdlib.h>
00024 #include <stdio.h>
00025 #include <time.h>
00026 #include <ctype.h>
00027 #include <math.h>
00028 #include <errno.h>
00029 #include <unistd.h>
00030 #include <string.h>
00031 #include <sys/types.h>
00032 #include <sys/stat.h>
00033 #include <assert.h>
00034 #include <fcntl.h>
00035 #include <dirent.h>
00036 
00037 #include "common.h"
00038 
00039 #define DTMAX1 5.e-3
00040 #define DTMAX2 5.e-6
00041 
00042 int fileNameOptions=ADD_CHANNEL_CODE; //<! channel naming options
00043 
00044 char * auxChannelName[] = { "PwrSupply", "IntTemp", "AUX02", "AUX03", "AUX04", "AUX05", "AUX06", "AUX07", "AUX08",
00045                              "AUX09", "AUX10", "AUX11", "AUX12", "AUX13", "AUX14", "AUX15" };
00046 char * auxChannelUnit[] = { "0.1V", "0.1°C", "count", "count", "count", "count", "count", "count",
00047                              "count", "count", "count", "count", "count", "count", "count", "count" };
00048 
00049 int buggyMykerinos=0; //<! is current station a buggy mykerinos ?
00050 int warnFixBuggyMykerinos=0; //<! not warned yet
00051 
00052 char dayDirPrefix[255]; //<! the daydir prefix
00053 int timeWarningNow=0; //<! a time warning occurred
00054 
00055 struct InfoHeaderType infoHeader[MAX_CHANNEL]; //<! data header for each channel
00056 
00057 struct Titan2TimeType lastExtTime = { 0, 0 }; //<! last pulse time
00058 struct Titan2TimeType lastIntTime = { 0, 0 }; //<! last pulse
00059 struct Titan2TimeType roundedTime = { 0, 0 }; //<! external time valid for titan1 and titan2
00060 
00061 int knownUSecond=0; //<! have we seen an extend time frame ?
00062 int knownSecond=0; //<! have we seen a time frame ?
00063 int knownExtGps=0; //<! have we seen an GPS external time frame ?
00064 int knownTime=0; //<! have we seen any time-related frame
00065 
00066 FILE * dtFile=NULL;
00067 char dtFileName[255];
00068 struct Titan2TimeType dtFileTime = { 0, 0 }; //<! first time of the dt file
00069 int dtUseLine;
00070 
00071 double lastDt=1.e16; 
00072 
00073 int nCached=0; 
00074 double *dtCached=NULL; //<! internal cache management
00075 double *TCached=NULL; //<! internal cache management
00076 char dtCachedFile[255];
00077 
00078 char testForStation[128]; //<! the station for which we are looking for a dt/dft file
00079 
00080 int emptyDir=0; //<! 1 if absolutely NO dt file can be found in the dt directory
00081 
00087 time_t lastShiftComputation=0; //<! last time for which we estimated the approx shift
00088 double lastShiftComputed=0.0; //<! last computed approx shift
00089 
00092 static int IsTitan1Time(void)
00093 {
00094         if (((knownUSecond==0)||(knownExtGps==0))&&(knownTime==1)&&(knownSecond==1))
00095         {
00096                 return(1);
00097         }
00098         return(0);
00099 }
00100 
00101 
00103 void ResetTimes(void)
00104 {
00105         nCached=0;
00106         if (dtCached) { free(dtCached); dtCached=NULL; };
00107         if (TCached) { free(TCached); TCached=NULL; };
00108 
00109         emptyDir=0;
00110         knownTime=0;
00111         knownUSecond=0;
00112         knownSecond=0;
00113         knownExtGps=0;
00114 
00115         lastShiftComputation=0;
00116         lastShiftComputed=0.0;
00117 
00118         memset(&(HWConfig.digitizer),0,sizeof(struct DigitizerType));
00119 
00120         memset(&lastExtTime,0,sizeof(struct Titan2TimeType));
00121         memset(&lastIntTime,0,sizeof(struct Titan2TimeType));
00122         memset(&roundedTime,0,sizeof(struct Titan2TimeType));
00123         memset(&currentTime,0,sizeof(struct Titan2TimeType));
00124         memset(&correctedTime,0,sizeof(struct Titan2TimeType));
00125         memset(&pulseTime,0,sizeof(struct Titan2TimeType));
00126         memset(&gpsExtTime,0,sizeof(struct Titan2TimeType));
00127         memset(&gpsIntTime,0,sizeof(struct Titan2TimeType));
00128 }
00129 
00131 int InWindow(void)
00132 {
00133         int bw;
00134         if (onlyTag[0])
00135         {
00136                 if (strcmp(currentTag,onlyTag)!=0)
00137                 {
00138                         return(0);
00139                 }
00140         }
00141         if ((skipTime>beginWindow)&&(skipTime<endWindow))
00142         {
00143                 bw=skipTime;
00144         }
00145         else
00146         {
00147                 bw=beginWindow;
00148         }
00149         if (
00150                         (
00151                          !( 
00152                                  ((bw>0)&&(correctedTime.usecond>>32<bw))||
00153                                  ((endWindow>0)&&(correctedTime.usecond>>32>endWindow))
00154                                  )
00155                          )&&
00156                         ((currentTime.usecond>0)||(extractTit))
00157                         )
00158         {
00159                 return(1);
00160         }
00161         return(0);
00162 }
00163 
00164 
00166 int DtFileSelect(const struct dirent* t)
00167 {
00168         int l;
00169         char s[128];
00170         l=strlen(t->d_name);
00171         // reject short names
00172         if (l<strlen(testForStation)+4)
00173         {
00174                 return(0);
00175         }
00176         strcpy(s,testForStation);
00177         strcat(s,".dft");
00178         // accept files ending with testForStation".dft"
00179         if (0==strcmp(t->d_name+l-strlen(testForStation)-4,s))
00180         {
00181                 return(1);
00182         }
00183         strcpy(s,testForStation);
00184         strcat(s,".flt");
00185         // accept files ending with testForStation".dft"
00186         if (0==strcmp(t->d_name+l-strlen(testForStation)-4,s))
00187         {
00188                 return(1);
00189         }
00190 #ifndef IGNORE_DT_FILE
00191         strcpy(s,testForStation);
00192         strcat(s,".dt");
00193         // accept files ending with testForStation".dt"
00194         if (0==strcmp(t->d_name+l-strlen(testForStation)-3,s))
00195         {
00196                 return(1);
00197         }
00198         // still here ? the file does not match
00199 #endif
00200         return(0);
00201 }
00202 
00209 int ReadDtLine(char *line, double *T, double *dt, char *fn)
00210 {
00211         if (6!=str2time(line,T))
00212         {
00213                 PrintError("format error in %s: %s",fn,line);
00214                 return(-1);
00215         }
00216         if (1!=sscanf(line,"%*s %lf",dt))
00217         {
00218                 //PrintError("format error in %s: %s", fn,line);
00219                 return(-1);
00220         }
00221         return(0);
00222 }
00223 
00228 int TimeFileSort(const void * a, const void * b)
00229 {
00230         struct dirent **e1 = (struct dirent **)a;
00231         struct dirent **e2 = (struct dirent **)b;
00232         int l1,l2;
00233         l1=strlen((*e1)->d_name);
00234         l2=strlen((*e2)->d_name);
00235         // if the extension is the same
00236         if (strcmp((*e1)->d_name+l1-3,(*e2)->d_name+l2-3)==0)
00237         {
00238                 // return the regular comparison result
00239                 return(__alphasort(e1,e2));
00240         }
00241 
00242         // if a is "dft", then a is the first (-1)
00243         if (strcmp((*e1)->d_name+l1-3,"dft")==0)
00244         {
00245                 return(-1);
00246         }
00247         // if b is "dt", then a is the first (-1)
00248         if (strcmp((*e2)->d_name+l2-2,"dt")==0)
00249         {
00250                 return(-1);
00251         }
00252         // if b is "dft", then b is the first (1)
00253         if (strcmp((*e2)->d_name+l2-3,"dft")==0)
00254         {
00255                 return(1);
00256         }
00257         // if a is "dt", then b is the first (1)
00258         if (strcmp((*e1)->d_name+l1-2,"dt")==0)
00259         {
00260                 return(1);
00261         }
00262         // the flt case does not need to be examined
00263         return(0);
00264 }
00265 
00268 void FillDtCache(char *fileName)
00269 {
00270         FILE *f;
00271         char line[128];
00272         int nalloc=0;
00273         double T,dt;
00274         PrintLog("reading '%s' for dt cache\n",fileName);
00275         strcpy(dtCachedFile,fileName);
00276 
00277         if (dtCached) { free(dtCached); dtCached=NULL; };
00278         if (TCached) { free(TCached); TCached=NULL; };
00279         nCached=0;
00280 
00281         f=fopen(fileName,"rt");
00282         if (!f)
00283         {
00284                 return;
00285         }
00286 
00287         while (fgets(line,127,f)!=NULL)
00288         {
00289                 if (line[0]=='#')
00290                 {
00291                         continue;
00292                 }
00293                 if (nCached>=nalloc-1)
00294                 {
00295                         nalloc+=4096;
00296                         dtCached=(double *)realloc(dtCached,nalloc*sizeof(double));
00297                         if (dtCached==0)
00298                         {
00299                                 PrintError("realloc dtCached: %m\n");
00300                         }
00301                         TCached=(double *)realloc(TCached,nalloc*sizeof(double));
00302                         if (TCached==0)
00303                         {
00304                                 PrintError("realloc TCached: %m\n");
00305                         }
00306                 }
00307                 // read the line
00308                 if (0==ReadDtLine(line,&T,&dt,fileName))
00309                 {
00310                         dtCached[nCached]=dt;
00311                         TCached[nCached] =T;
00312                         nCached++;
00313                 }
00314         }
00315         fclose(f);
00316 }
00317 
00324 int GetInterpolatedShift(double t, double *ts, int *age, char *station, char *file)
00325 {
00326         int ok=NO_TIME_CORRECTION,i,l,j;
00327         int nfiles=0;
00328         int notFoundInCache=1;
00329         char line[129];
00330         char dtfilename[255];
00331         FILE *f;
00332         double T1,T2,dt1,dt2,dt;
00333         struct dirent **dtfile=NULL;
00334         T1=-1.;
00335         T2=1.e20;
00336         dt1=dt2=dt=0.0;
00337 
00338         if (0!=strcmp(testForStation,station))
00339         {
00340                 emptyDir=0;
00341                 strcpy(testForStation,station);
00342         }
00343         // if we already know that no dt file can be found, skip that
00344         if (emptyDir!=0)
00345         {
00346                 return(ok);
00347         }
00348         // if the time is in the cache
00349         if (nCached>0)
00350         {
00351                 if ((TCached[0]<=t)&&(TCached[nCached-1]>=t))
00352                 {
00353                         register int i;
00354                         // find the last T before
00355                         for (i=0; i<nCached; i++)
00356                         {
00357                                 if (TCached[i]>t)
00358                                 {
00359                                         if (i) i--;
00360                                         T1=TCached[i];
00361                                         dt1=dtCached[i];
00362                                         // find the first T after
00363                                         for (; i<nCached; i++)
00364                                         {
00365                                                 if (TCached[i]>t)
00366                                                 {
00367                                                         T2=TCached[i];
00368                                                         dt2=dtCached[i];
00369                                                         // work with cache
00370                                                         notFoundInCache=0;
00371                                                         if (file)
00372                                                         {
00373                                                                 strcpy(file,dtCachedFile);
00374                                                         }
00375                                                         i=nCached;
00376                                                         break;
00377                                                 }
00378                                         }
00379                                 }
00380                         }
00381                 }
00382         }
00383         // else
00384         if (notFoundInCache)
00385         {
00386                 // for each dt file in the current directory:
00387                 // any file named *.STATION.dft, *.STATION.flt, or *.STATION.dt (in that order)
00388                 nfiles=__scandir(TDBPath(TDB_PATH_DFT,station),&dtfile,DtFileSelect,TimeFileSort);
00389                 PrintDebug("scanning '%s' for '%s' ...%d\n",TDBPath(TDB_PATH_DFT,station),station,nfiles);
00390                 if (nfiles==0)
00391                 {
00392                         emptyDir=1;
00393                         return(ok);
00394                 }
00395                 for (i=0; i<nfiles; i++)
00396                 {
00397                         sprintf(dtfilename,"%s/%s",TDBPath(TDB_PATH_DFT,station),dtfile[i]->d_name);
00398                         // open the file
00399                         f=fopen(dtfilename,"rt");
00400                         if (!f)
00401                         {
00402                                 PrintError("%s: %m\n",dtfilename);
00403                                 continue;
00404                         }
00405                         l=0;
00406                         // read the first valid
00407                         for (j=0; (l<5)&&(fgets(line,127,f)!=NULL); )
00408                         {
00409                                 if (line[0]=='#')
00410                                 {
00411                                         continue;
00412                                 }
00413                                 if (ReadDtLine(line,&T1,&dt1,dtfilename)<0)
00414                                 {
00415                                         continue;
00416                                 }
00417                                 break;
00418                         }
00419                         // if the begin of the file is after t
00420                         if (T1>t)
00421                         {
00422                                 // close the file
00423                                 fclose(f);
00424                                 // skip this file
00425                                 break;
00426                                 // endif
00427                         }
00428                         // seek to 1000bytes before the end of the file
00429                         fseek(f,SEEK_END,-1000);
00430                         // read a line
00431                         fgets(line,127,f);
00432                         // read the rest of the file and find the last time
00433                         while (fgets(line,127,f)!=NULL)
00434                         {
00435                                 if (line[0]=='#')
00436                                 {
00437                                         continue;
00438                                 }
00439                                 // find the earliest T(=T2) after t
00440                                 if (ReadDtLine(line,&T2,&dt,dtfilename)<0)
00441                                 {
00442                                         continue;
00443                                 }
00444                         }
00445                         // close the file
00446                         fclose(f);
00447                         // if t is in the file
00448                         if ((T1<t)&&(T2>t))
00449                         // then
00450                         {
00451                                 // copy the entire file in the cache
00452                                 FillDtCache(dtfilename);
00453                                 // then scan the cache to find T1<t<T2
00454 
00455                                 // find the last T before
00456                                 for (i=0; i<nCached; i++)
00457                                 {
00458                                         if (TCached[i]>t)
00459                                         {
00460                                                 if (i) i--;
00461                                                 T1=TCached[i];
00462                                                 dt1=dtCached[i];
00463                                                 // find the first T after
00464                                                 for (; i<nCached; i++)
00465                                                 {
00466                                                         if (TCached[i]>t)
00467                                                         {
00468                                                                 T2=TCached[i];
00469                                                                 dt2=dtCached[i];
00470                                                                 // work with cache
00471                                                                 notFoundInCache=0;
00472                                                                 if (file)
00473                                                                 {
00474                                                                         strcpy(file,dtCachedFile);
00475                                                                 }
00476                                                                 i=nCached;
00477                                                                 break;
00478                                                         }
00479                                                 }
00480                                         }
00481                                 }
00482                                 // stop
00483                                 break;
00484                         // endif
00485                         }
00486                 // end for
00487                 }
00488         // end if (time in the cahce)
00489         }
00490         PrintDebug("T1=%f t=%f T2=%f\n",T1,t,T2);
00491 
00492         // if T1 AND T2 could be found
00493         if ((T1>0.)&&(T2<1.e18))
00494         // then
00495         {
00496                 // dt=(t-T1)*(dt2-dt1)/(T2-T1)
00497                 *ts=dt1+(t-T1)*(dt2-dt1)/(T2-T1);
00498                 // ok=1
00499                 ok=INTERPOLATION_CORRECTION;
00500                 *age=(int)(t-T1);
00501         // endif
00502         }
00503         else
00504         {
00505                 // if we are before the first pulse
00506                 if (T2<1.e18)
00507                 {
00508                         ok=EXTENDED_CORRECTION;
00509                         *age=(int)(t-T2); // will probably be negative
00510                         *ts=dt2;
00511                 }
00512                 // if we are after the last pulse
00513                 if (T1>0.)
00514                 {
00515                         ok=EXTENDED_CORRECTION;
00516                         *age=(int)(T1-t);
00517                         *ts=dt1;
00518                 }
00519         }
00520         // free the allocated buffers
00521         if (nfiles>0)
00522         {
00523                 for (i=0; i<nfiles; i++)
00524                 {
00525                         free(dtfile[i]);
00526                 }
00527                 free(dtfile);
00528         }
00529         PrintDebug("ok=%d ts=%f age=%d\n",ok,*ts,*age);
00530         return(ok);
00531 }
00532 
00533 double GetExtraTcorr(struct InfoHeaderType *ih)
00534 {
00535         char fn[128];
00536         char line[128];
00537         double delay;
00538         FILE *f;
00539         // supposer qu'on ne connaît pas ce cas
00540         ih->extraTcorrUsed=0;
00541         // si un fichier de dérive n'a pas été utilisé, on sort
00542         if (strlen(ih->driftFile)==0)
00543         {
00544                 return(0.0);
00545         }
00546 
00547         // déterminer quel fichier ouvrir
00548         sprintf(line,"%s/extra_tcorr",TDBPath(TDB_PATH_TC,ih->station));
00549         // ouvrir le fichier
00550         f=fopen(line,"rt");
00551         // si ok
00552         if (f!=NULL)
00553         {
00554                 // tant qu'on peut encore lire
00555                 while (!feof(f))
00556                 {
00557                         // lire une ligne
00558                         if (NULL==fgets(line,79,f))
00559                         {
00560                                 break;
00561                         }
00562                         // ignorer les commentaires et le formats faux
00563                         // extraire le nom de fichier et le délai
00564                         if ((line[0]=='#')||(2!=sscanf(line,"%s %lf",fn,&delay)))
00565                         {
00566                                 continue;
00567                         }
00568                         // si le nom de fichier correspond à celui qui est utilisé
00569                         if (strcmp(ih->driftFile,fn)==0)
00570                         {
00571                                 // fermer le fichier
00572                                 fclose(f);
00573                                 // lever le flag dans la structure
00574                                 ih->extraTcorrUsed=1;
00575                                 // retourner le délai lu
00576                                 return(delay);
00577                         // finsi
00578                         }
00579                 // fin tant
00580                 }
00581         // fin si
00582         }
00583         // retourner 0
00584         return(0.0);
00585 }
00586 
00587 // this is to allow some more correction from a localfile named FrameSkip.STA
00588 // lecture du fichier FrameSkip.station pour une correction supplémentaire
00589 double GetFrameSkip(double starttime,char * station)
00590 {
00591         // supposer la correction nulle
00592         double correction=0.0,tdate,c;
00593         char fn[128],line[80],sdate[50];
00594         FILE *f;
00595         // contruire le nom du fichier à lire
00596         sprintf(fn,TDBPath(TDB_PATH_TC,station),"/FrameSkip.%s",station);
00597         f=fopen(fn,"rt");
00598         // si le fichier existe
00599         if (f!=NULL)
00600         // alors
00601         {
00602                 // tant qu'on est pas à la fin du fichier
00603                 while (!feof(f))
00604                 {
00605                         // lire une ligne
00606                         if (NULL==fgets(line,79,f))
00607                         {
00608                                 break;
00609                         }
00610                         // ignorer les commentaires et le formats faux
00611                         if ((line[0]=='#')||(2!=sscanf(line,"%s %lf",sdate,&c)))
00612                         {
00613                                 continue;
00614                         }
00615                         tdate=1.e38;
00616                         // lire la date et la correction
00617                         if (3>str2time(sdate, &tdate))
00618                         {
00619                                 continue;
00620                         }
00621                         // si la date lue est antérieure à starttime
00622                         if (tdate<starttime)
00623                         // alors
00624                         {
00625                                 // la correction est la correction lue
00626                                 correction=c;
00627                         // finsi
00628                         }
00629                 // fin tant
00630                 }
00631                 // fermer le fichier
00632                 fclose(f);
00633         // finsi
00634         }
00635         if (fabs(correction)>0.1)
00636         {
00637                 PrintWarning("%s: %.4fs observed delay (%.0f %.0f)\n",
00638                                 fn,correction,tdate,starttime);
00639         }
00640         // retourner la correction
00641         return(correction);
00642 }
00643 
00648 double ADCDelay(struct DigitizerType *digitizer, int ch)
00649 {
00650         // do not compute anything for aux channels
00651         if (ch>=MAX_OSIRIS_CHANNEL)
00652         {
00653                 return(0.0);
00654         }
00655         if ((digitizer->ok)&&(!IsTitan1Time()))
00656         {
00657                 if (digitizer->adcDelay<0.1)
00658                 {
00659                         // in this case, the ADC is a 1251 !
00660                         return(2.5/16000.);
00661                 }
00662                 else
00663                 {
00664                         return((double)digitizer->adcDelay/(double)digitizer->adcFrequency);
00665                 }
00666         }
00667         else
00668         {
00669                 int mch=PrimaryChannel(ch);
00670                 return(
00671                                 ((double)digitizer->adcDelay*(double)infoHeader[mch].sr.div)/
00672                                (double)infoHeader[mch].sr.base
00673                                 );
00674         }
00675 }
00676 
00680 double Titan1FilterDelayTime(int ch)
00681 {
00682         double fprim;
00683         double delay;
00684         int R;
00685         // do not compute anything for aux channels
00686         if (ch>=MAX_OSIRIS_CHANNEL)
00687         {
00688                 return(0.0);
00689         }
00690         delay=0.0;
00691         if (ch<6)
00692         {
00693                 return(0.0);
00694         }
00695         if (oldHWConfig.srExp[ch-6].div<=0)
00696         {
00697                 return(0.0);
00698         }
00699         // set the initial frequency
00700         fprim=(double)oldHWConfig.srExp[ch-6].base/(double)oldHWConfig.srExp[ch-6].div;
00701         // set the initial ratio
00702         R=oldHWConfig.srExp[ch-6].base*oldHWConfig.srExp[ch].div/
00703                 (oldHWConfig.srExp[ch-6].div*oldHWConfig.srExp[ch].base);
00704         while ((R!=0)&&((R%2)==0))
00705         {
00706                 delay+=(double)(128-1)/(2.*(double)(fprim));
00707                 R/=2;
00708                 fprim/=2.0;
00709         }
00710         return(delay);
00711 }
00712 
00717 double FixBuggyMykerinos(struct DigitizerType *d, double f)
00718 {
00719         // if the station is not Mykerinos
00720         if (d->adcDecimationLength!=0)
00721         {
00722                 // the fix is not necessary
00723                 return(0.0);
00724         }
00725         // else
00726         if (buggyMykerinos)
00727         {
00728                 // if not already warned
00729                 if (warnFixBuggyMykerinos==0)
00730                 // then
00731                 {
00732                         // warn !
00733                         PrintWarning("Mykerinos-T generates Titan2 data version (%d.%d.%d) with timing error that have been fixed. The data created by rtitan2 are corrected but the Mykerinos-T should be upgraded.\n",
00734                                         HWConfig.formatVersion,
00735                                         HWConfig.formatMajor,
00736                                         HWConfig.formatMinor);
00737                         // warnFixBuggyMykerinos=1
00738                         warnFixBuggyMykerinos=1;
00739                 // endif
00740                 }
00741                 return(2.0/f);
00742         }
00743         // endif
00744         return(0.0);
00745 }
00746 
00749 void SetBuggyMykerinos(int yes)
00750 {
00751         buggyMykerinos=yes;
00752 }
00753 
00759 double FilterDelayTime(struct DigitizerType *digitizer, struct Titan2SRType *sr, int ch)
00760 {
00761 #define ONE 1
00762         int fprim,R;
00763         double delay;
00764 
00765         // do not compute anything for aux channels
00766         if (ch>=MAX_OSIRIS_CHANNEL)
00767         {
00768                 return(0.0);
00769         }
00770 
00771         if (digitizer->adcFrequency<=0)
00772         {
00773                 return(Titan1FilterDelayTime(ch));
00774         }
00775 
00776         delay=0.;
00777         if (sr->npts==0)
00778         {
00779                 PrintError("cannot compute a filter delay with F=0\n");
00780                 timeWarningNow=1;
00781                 timeWarning++;
00782                 return(0.0);
00783         }
00784         // then the titan2 case
00785         // first fprim, if defined
00786         if ((digitizer->adcDecimation)&&(digitizer->adcDecimationLength>1))
00787         {
00788                 // compute the delay for the first filter
00789                 delay+=(double)(digitizer->adcDecimationLength-ONE)/
00790                         (2.*(double)digitizer->adcFrequency);
00791         }
00792 
00793         // determine the decimations 1/5 and 1/2 that lead to the f, starting
00794         // from fprim=freq0/decim0
00795 
00796         // where we start:
00797         fprim=digitizer->adcFrequency;
00798         if (digitizer->adcDecimation)
00799         {
00800                 fprim/=digitizer->adcDecimation;
00801         }
00802 
00803         // now compute the delays for the 1/2 and 1/5 decimations
00804 
00805         // R=fprim/f
00806         R=fprim/sr->npts;
00807         // 1/5
00808         while ((R!=0)&&((R%5)==0))
00809         {
00810                 delay+=(double)(digitizer->secondDecimationLength-ONE)/(2.*(double)(fprim));
00811                 delay+=FixBuggyMykerinos(digitizer,fprim);
00812                 R/=5;
00813                 fprim/=5;
00814         }
00815         // 1/2
00816         while ((R!=0)&&((R%2)==0))
00817         {
00818                 delay+=(double)(digitizer->secondDecimationLength-ONE)/(2.*(double)(fprim));
00819                 delay+=FixBuggyMykerinos(digitizer,fprim);
00820                 R/=2;
00821                 fprim/=2;
00822         }
00823         return(delay);
00824 }
00825 
00831 unsigned int FilterChain(struct DigitizerType *digitizer, struct Titan2SRType *sr, int ch)
00832 {
00833         int fprim,R;
00834         unsigned int ret;
00835 
00836         if (digitizer->adcFrequency<=0)
00837         {
00838                 return(0);
00839         }
00840 
00841         if (sr->npts==0)
00842         {
00843                 return(0);
00844         }
00845         // first fprim, if defined
00846         if ((digitizer->adcDecimation)&&(digitizer->adcDecimationLength>1))
00847         {
00848                 ret=1;
00849         }
00850         else
00851         {
00852                 ret=0;
00853         }
00854         ret<<=8;
00855 
00856         // determine the decimations 1/5 and 1/2 that lead to the f, starting
00857         // from fprim=freq0/decim0
00858 
00859         // where we start:
00860         fprim=digitizer->adcFrequency;
00861         if (digitizer->adcDecimation)
00862         {
00863                 fprim/=digitizer->adcDecimation;
00864         }
00865 
00866         // now compute the delays for the 1/2 and 1/5 decimations
00867 
00868         // R=fprim/f
00869         R=fprim/sr->npts;
00870         // 1/5
00871         while ((R!=0)&&((R%5)==0))
00872         {
00873                 R/=5;
00874                 fprim/=5;
00875                 ret++;
00876         }
00877         ret<<=8;
00878         // 1/2
00879         while ((R!=0)&&((R%2)==0))
00880         {
00881                 R/=2;
00882                 fprim/=2;
00883                 ret++;
00884         }
00885         return(ret);
00886 }
00887 
00888 
00893 int CorrectTime(double t, struct InfoHeaderType *header)
00894 {
00895         int ret;
00896 
00897         ret=NO_TIME_CORRECTION;
00898         if (header->pulse.usecond<=0)
00899         {
00900                 // save the pulse time
00901                 memcpy(&(header->pulse),&pulseTime,sizeof(struct Titan2TimeType));
00902                 // save the external pulse time
00903                 memcpy(&(header->external),&roundedTime,sizeof(struct Titan2TimeType));
00904         }
00905 
00906         if (header->pulse.usecond>0)
00907         {
00908                 header->otshift=DiffTimeT2T1(&(header->external),&(header->pulse),NULL);
00909         }
00910         else
00911         {
00912                 header->otshift=DiffTimeT2T1(&(header->external),&(header->pulse),NULL);
00913                 header->tshift=header->otshift=0.0;
00914         }
00915         // fetch the time shift for the given time using the requested method
00916         switch (header->correctionMethod)
00917         {
00918                 case AUTO_CORRECTION:
00919                 case INTERPOLATION_CORRECTION:
00920                         ret=header->correctionMethod;
00921                         // use an interpolation, this requires the total time drift
00922                         // to be known (cache or dt file)
00923                         if (GetInterpolatedShift(t,
00924                                                 &(header->tshift),
00925                                                 &(header->pulseAge),
00926                                                 header->station,
00927                                                 header->driftFile)!=NO_TIME_CORRECTION)
00928                         {
00929                                 break;
00930                         }
00931                         else
00932                         {
00933                                 if (header->correctionMethod!=AUTO_CORRECTION)
00934                                 {
00935                                         PrintWarning("could not interpolate the time "
00936                                                         "shift, falling back to "
00937                                                         "LAST_PULSE_CORRECTION\n");
00938                                 }
00939                         }
00940                         // use the last pulse
00941                 case LAST_PULSE_CORRECTION:
00942                         // ICI tester le cas où la correction est impossible
00943                         if (header->pulse.usecond>0)
00944                         {
00945                                 ret=header->correctionMethod;
00946                                 header->tshift=header->otshift;
00947                                 break;
00948                         }
00949                 case NO_TIME_CORRECTION:
00950                         if (header->correctionMethod!=NO_TIME_CORRECTION)
00951                         {
00952                                 if (extractingData!=0)
00953                                 {
00954                                         PrintWarning("no time correction could be performed\n");
00955                                 }
00956                         }
00957                         ret=NO_TIME_CORRECTION;
00958                         header->tshift=0.0;
00959         }
00960         if ((header->correctionMethod!=ret)&&(header->correctionMethod!=NO_TIME_CORRECTION))
00961         {
00962                 if (extractingData!=0)
00963                 {
00964                         PrintWarning("could not apply the requested correction method\n");
00965                         timeWarningNow=1;
00966                         timeWarning++;
00967                 }
00968         }
00969         return(ret);
00970 }
00971 
00974 double GetApproximatedShift(void)
00975 {
00976         struct InfoHeaderType header;
00977         int i;
00978         if (HWConfig.fieldIdent[0]==0)
00979         {
00980                 return(0.0);
00981         }
00982         if (abs((currentTime.usecond>>32)-lastShiftComputation)<3600)
00983         {
00984                 return(lastShiftComputed);
00985         }
00986         lastShiftComputation=currentTime.usecond>>32;
00987         memset(&header,0,sizeof(struct InfoHeaderType));
00988         if (saveShift)
00989         {
00990                 header.correctionMethod=LAST_PULSE_CORRECTION;
00991         }
00992         else
00993         {
00994                 header.correctionMethod=AUTO_CORRECTION;
00995         }
00996         strcpy(header.station,HWConfig.fieldIdent);
00997 
00998         // save the pulse time
00999         memcpy(&(header.pulse),&pulseTime,sizeof(struct Titan2TimeType));
01000         // save the external pulse time
01001         memcpy(&(header.external),&roundedTime,sizeof(struct Titan2TimeType));
01002         // save the channel number
01003         i=CorrectTime(currentTime.usecond>>32, &header);
01004         lastShiftComputed=header.tshift;
01005         return(header.tshift);
01006 }
01007 
01012 double CorrectChannelStartTime(int ch)
01013 {
01014         double T;
01015         T=US2S*(double)infoHeader[ch].uncorrected.usecond;
01016 
01017         // if the channel is a real one
01018         if (ch<MAX_OSIRIS_CHANNEL)
01019         {
01020                 // compute the ADC delay
01021                 infoHeader[ch].tadc=ADCDelay(&(oldHWConfig.digitizer),ch);
01022 
01023                 // compute the filter delay
01024                 infoHeader[ch].tfilter=FilterDelayTime(&(oldHWConfig.digitizer),&(infoHeader[ch].sr),ch);
01025 
01026                 // fetch the corrected time
01027                 infoHeader[ch].correctionMethod=CorrectTime(
01028                                 (time_t)(infoHeader[ch].uncorrected.usecond>>32),
01029                                 &(infoHeader[ch]));
01030                 // compute the final time
01031                 T-=infoHeader[ch].tadc;
01032                 T-=infoHeader[ch].tfilter;
01033                 if (noTimeCorrection==0)
01034                 {
01035                         T-=infoHeader[ch].tshift;
01036                 }
01037                 infoHeader[ch].correctedTime=T;
01038         }
01039         // else the channel is a pseudo channel (1Hz, no correction)
01040         else
01041         {
01042                 infoHeader[ch].correctedTime=floor(T+0.5);
01043         }
01044         return(T);
01045 }
01046 
01047 // determine the primary channel for a possibly secondary channel
01048 // @param channel the channel
01049 // @return the primary channel associated
01050 int PrimaryChannel(int channel)
01051 {
01052         if (IsTitan1Time())
01053         {
01054                 return(channel>5)?(channel-6):channel;
01055         }
01056         else
01057         {
01058                 return(channel);
01059         }
01060 }
01061 
01069 double DiffTimeT2T1(struct Titan2TimeType *t1, struct Titan2TimeType *t2, struct Titan2TimeType *td)
01070 {
01071         double diff;
01072         if (td)
01073         {
01074                 td->usecond=t2->usecond-t1->usecond;
01075                 diff=US2S*(double)td->usecond;
01076         }
01077         else
01078         {
01079                 diff=US2S*(double)(t2->usecond-t1->usecond);
01080         }
01081         return(diff);
01082 }
01083 
01091 double TimeAdd(struct Titan2TimeType *t1, struct Titan2TimeType *t2, struct Titan2TimeType *ts)
01092 {
01093         ts->usecond=t1->usecond+t2->usecond;
01094         return(