00001 #include <cmath>
00002 #include <algorithm>
00003
00004 #include "Conventions/SimFlag.h"
00005 #include "DatabaseInterface/DbiSqlContext.h"
00006 #include "DatabaseInterface/DbiServices.h"
00007 #include "DcsUser/DcsRadonLevelFinder.h"
00008 #include "MessageService/MsgService.h"
00009
00010 ClassImp(DcsRadonLevelFinder)
00011
00012
00013 #define TIME_MARGIN 24*60*60.
00014
00015
00016 #define TIME_WINDOW 30*24*60*60.
00017
00018
00019
00020
00021 CVSID("$Id: DcsRadonLevelFinder.cxx,v 1.1 2009/06/02 21:24:56 nwest Exp $\n CVSID_DBIRESULTPTR ");
00022
00023 DcsRadonLevelFinder* DcsRadonLevelFinder::fgDcsRadonLevelFinder = 0;
00024
00025
00026 struct earlier : public binary_function<const Dcs_Radon_Level*,const Dcs_Radon_Level*, bool> {
00027 bool operator()(const Dcs_Radon_Level* first,const Dcs_Radon_Level* second) {
00028 return first->GetTimeStamp() < second->GetTimeStamp();
00029 }
00030 };
00031
00032
00033
00034
00035
00036
00037 DcsRadonLevelFinder::DcsRadonLevelFinder() :
00038 fDetector(Detector::kNear),
00039 IsGlobalVersion(false) {
00040
00041 }
00042
00043
00044
00045 DcsRadonLevelFinder::DcsRadonLevelFinder(VldTimeStamp start, VldTimeStamp end, Detector::Detector_t detector) :
00046 fDetector(Detector::kNear),
00047 IsGlobalVersion(false) {
00048 this->NewQuery(start,end,detector);
00049
00050 }
00051
00052
00053
00054 DcsRadonLevelFinder* DcsRadonLevelFinder::Instance() {
00055 if (! fgDcsRadonLevelFinder ) {
00056 fgDcsRadonLevelFinder = new DcsRadonLevelFinder();
00057 fgDcsRadonLevelFinder->IsGlobalVersion = true;
00058 }
00059 return fgDcsRadonLevelFinder;
00060 }
00061
00062
00063
00064 Float_t DcsRadonLevelFinder::GetRadonLevel(VldContext context, Int_t numPoints ) {
00065
00066
00067
00068 VldTimeStamp date(context.GetTimeStamp());
00069 Detector::Detector_t detector(context.GetDetector());
00070 SimFlag::SimFlag_t simflag(context.GetSimFlag());
00071
00072 if ( simflag != SimFlag::kData || ( detector != Detector::kNear && detector != Detector::kFar ) ) return -999.;
00073 return this->GetRadonLevel(date,detector,numPoints);
00074
00075 }
00076
00077
00078
00079 Float_t DcsRadonLevelFinder::GetRadonLevel(VldTimeStamp date, Detector::Detector_t detector, Int_t numPoints ) {
00080
00081
00082
00083
00084
00085
00086 if ( ! this->HasGoodData(date,detector) ) {
00087
00088 if ( ! IsGlobalVersion ) return -999.;
00089
00090
00091
00092 this->NewQuery(VldTimeStamp(date.GetSeconds() - 2*TIME_MARGIN),
00093 VldTimeStamp(date.GetSeconds() + TIME_WINDOW),
00094 detector);
00095 if ( ! this->HasGoodData(date,detector) ) return -999.;
00096 }
00097
00098
00099 struct data_point {Float_t relative_time; Float_t level;};
00100 #define MAX_POINTS 50
00101 data_point buff[MAX_POINTS];
00102
00103 if ( numPoints > MAX_POINTS ) numPoints = MAX_POINTS;
00104
00105
00106 Bool_t interpolate = false;
00107 if ( numPoints <= 0 ) {
00108 interpolate = true;
00109 numPoints = 2;
00110 }
00111
00112
00113 Bool_t tableFull = false;
00114 Int_t nextSlot = 0;
00115
00116 Float_t required_time(date.GetSeconds());
00117 Int_t numRows(fRadonLevelTable.size());
00118
00119 for (Int_t i_row = 0; i_row < numRows; ++i_row ) {
00120 const Dcs_Radon_Level& row(*fRadonLevelTable[i_row]);
00121 if ( ! row.IsValidEntry() ) continue;
00122 Float_t relative_time(row.GetTimeStamp().GetSeconds() - required_time);
00123
00124
00125
00126 if ( tableFull && abs(buff[nextSlot].relative_time) < abs(relative_time) ) break;
00127 buff[nextSlot].relative_time = relative_time;
00128 buff[nextSlot].level = row.GetRadonLevel();
00129 ++nextSlot;
00130 if ( nextSlot >= numPoints ) {
00131 tableFull = true;
00132 nextSlot = 0;
00133 }
00134
00135 }
00136
00137
00138 if ( ! tableFull ) numPoints = nextSlot;
00139
00140 if ( numPoints == 0 ) return -999.;
00141 if ( numPoints == 1 ) return buff[0].level;
00142
00143
00144 if ( interpolate ) {
00145 Float_t t1(buff[0].relative_time);
00146 Float_t t2(buff[1].relative_time);
00147 Float_t l1(buff[0].level);
00148 Float_t l2(buff[1].level);
00149 if ( t1 == t2 ) return (l1+l2)/2.;
00150 return (t1*l2 - t2*l1)/(t1-t2);
00151 }
00152
00153
00154 Float_t sum_l(0.);
00155 for (Int_t i_point = 0; i_point < numPoints; ++i_point ) sum_l += buff[i_point].level;
00156 return sum_l/numPoints;
00157
00158 }
00159
00160
00161
00162
00163 Bool_t DcsRadonLevelFinder::HasGoodData(VldTimeStamp date, Detector::Detector_t detector) const {
00164
00165
00166
00167 if ( detector != fDetector ) return false;
00168
00169 Int_t numRows(fRadonLevelTable.size());
00170 if ( numRows < 1 ) return false;
00171 if ( fRadonLevelTable[0]->GetTimeStamp() > VldTimeStamp(date.GetSeconds() - TIME_MARGIN)
00172 or fRadonLevelTable[numRows-1]->GetTimeStamp() < VldTimeStamp(date.GetSeconds() + TIME_MARGIN) ) return false;
00173 return true;
00174
00175 }
00176
00177
00178
00179 void DcsRadonLevelFinder::NewQuery(VldTimeStamp start, VldTimeStamp end, Detector::Detector_t detector) {
00180
00181
00182 DbiSqlContext sqlContext(DbiSqlContext::kOverlaps,start,end,detector,SimFlag::kData);
00183
00184
00185 fQueryResults.NewQuery(sqlContext,0);
00186
00187
00188 Int_t numRows(fQueryResults.GetNumRows());
00189 fRadonLevelTable.resize(numRows);
00190 for (Int_t i_row = 0; i_row < numRows; ++i_row) fRadonLevelTable[i_row] = fQueryResults.GetRow(i_row);
00191 sort(fRadonLevelTable.begin(),fRadonLevelTable.end(),earlier());
00192
00193 fDetector = detector;
00194
00195 }