00001 #include "CoilTools.h"
00002
00003 #include "BfldDbiCoilLimits.h"
00004 #include "BfldDbiCoilState.h"
00005 #include "Dcs_Mag_Near.h"
00006
00007 #include <MessageService/MsgService.h>
00008 CVSID("$Id: CoilTools.cxx,v 1.18 2007/12/07 00:37:46 rhatcher Exp $");
00009 using namespace std;
00010
00011 #include <DatabaseInterface/DbiTableProxyRegistry.h>
00012 #include <DatabaseInterface/DbiSqlContext.h>
00013 #include <DatabaseInterface/DbiResultPtr.h>
00014 #include <DatabaseInterface/DbiValidityRec.h>
00015 #include <DatabaseInterface/DbiWriter.h>
00016 #include <DatabaseInterface/DbiWriter.tpl>
00017
00018 #include <cmath>
00019 #include <cassert>
00020
00021 ClassImp(CoilTools)
00022
00023 CoilTools* CoilTools::fgInstance = 0;
00024
00025
00026
00027
00028
00029 template <class T>
00030 void CoilTools::ExtendedQuery(const VldContext& vldc,
00031 DbiResultPtr<T>& resultPtr,
00032 VldRange& resultRange)
00033 {
00034 MSG("Dcs",Msg::kDebug)
00035 << " CoilTools::ExtendedQuery<" << typeid(T).name()
00036 << "> looking for " << vldc.AsString("sql") << endl;
00037
00038
00039 Detector::Detector_t det = vldc.GetDetector();
00040 SimFlag::SimFlag_t sflg = vldc.GetSimFlag();
00041 VldTimeStamp minTime = vldc.GetTimeStamp();
00042 VldTimeStamp maxTime = vldc.GetTimeStamp();
00043 minTime.Add(-60*60);
00044 maxTime.Add(+fWindow);
00045
00046 DbiSqlContext econtext(DbiSqlContext::kOverlaps,
00047 minTime,maxTime,det,sflg);
00048
00049 resultPtr.NewQuery(econtext,fTask);
00050
00051 resultRange = VldRange(det,sflg,minTime,maxTime,"econtext");
00052
00053 const DbiValidityRec* dbiVldRec = resultPtr.GetValidityRec();
00054
00055
00056
00057 if ( dbiVldRec->IsGap() ) {
00058 MAXMSG("Dcs",Msg::kInfo,10)
00059 << " CoilTools::ExtendedQuery<" << typeid(T).name()
00060 << "> saw a gap for " << vldc.AsString("c")
00061
00062 << endl;
00063 }
00064
00065 MSG("Dcs",Msg::kDebug)
00066 << "CoilTools::ExtendedQuery<" << typeid(T).name() << "> narrow "
00067 << resultRange.AsString("acs-")
00068
00069 << " found " << resultPtr.GetNumRows() << " rows " << endl;
00070
00071 }
00072
00073
00074
00075 template <class T>
00076 void CoilTools::LocalQuery(const VldContext& vldc,
00077 DbiResultPtr<T>& extResPtr,
00078 std::map<int, const T*>& resultAggMap,
00079 VldRange& resultRange)
00080 {
00081
00082
00083
00084
00085
00086
00087
00088 MSG("Dcs",Msg::kDebug)
00089 << " Local looking for " << vldc.AsString("sql") << endl;
00090
00091
00092 resultAggMap.clear();
00093 resultRange = VldRange();
00094
00095
00096 std::map<int, VldTimeStamp> lastCreationDateMap;
00097 std::map<int, VldRange> aggRangeMap;
00098 std::map<int, UInt_t> iSeqNoUsed;
00099 typedef std::map<int, const T*> resMap_t;
00100 typedef typename resMap_t::iterator resItr_t;
00101 resItr_t resItr;
00102
00103 VldTimeStamp tsVldc = vldc.GetTimeStamp();
00104
00105
00106 for ( UInt_t irow = 0; irow < extResPtr.GetNumRows(); ++irow ) {
00107 const T* ptrRow = extResPtr.GetRow(irow);
00108 int aggNo = ptrRow->GetAggregateNo();
00109 const DbiValidityRec* dbiVldRec = extResPtr.GetValidityRec(ptrRow);
00110 const VldRange& rowRange = dbiVldRec->GetVldRange();
00111 if ( rowRange.IsCompatible(vldc) ) {
00112 VldTimeStamp foundCreationDate = dbiVldRec->GetCreationDate();
00113 MSG("Dcs",Msg::kVerbose)
00114 << " row " << irow
00115 << " SEQNO " << dbiVldRec->GetSeqNo()
00116 << " created " << foundCreationDate.AsString("sql")
00117 << " vld " << rowRange.AsString("acs-")
00118 << endl;
00119
00120 const T* oldRow = resultAggMap[aggNo];
00121 if ( ! oldRow ) lastCreationDateMap[aggNo] = VldTimeStamp::GetBOT();
00122
00123
00124 if ( foundCreationDate > lastCreationDateMap[aggNo] ) {
00125 lastCreationDateMap[aggNo] = foundCreationDate;
00126 resultAggMap[aggNo] = ptrRow;
00127 aggRangeMap[aggNo] = rowRange;
00128 iSeqNoUsed[aggNo] = dbiVldRec->GetSeqNo();
00129 }
00130 }
00131 }
00132
00133
00134 std::map<int, VldTimeStamp> maxStart;
00135 std::map<int, VldTimeStamp> minEnd;
00136 for ( resItr=resultAggMap.begin() ; resItr!=resultAggMap.end() ; ++resItr) {
00137 int aggNo = resItr->first;
00138 maxStart[aggNo] = aggRangeMap[aggNo].GetTimeStart();
00139 minEnd[aggNo] = aggRangeMap[aggNo].GetTimeEnd();
00140 MSG("Dcs",Msg::kVerbose)
00141 << " aggNo " << aggNo
00142 << " iSeqNoUsed " << iSeqNoUsed[aggNo] << " "
00143 << aggRangeMap[aggNo].AsString("acs-") << endl;
00144 }
00145
00146
00147 for ( UInt_t irow = 0; irow < extResPtr.GetNumRows(); ++irow ) {
00148 const T* ptrRow = extResPtr.GetRow(irow);
00149 int aggNo = ptrRow->GetAggregateNo();
00150 if ( ptrRow == resultAggMap[aggNo] ) continue;
00151 const DbiValidityRec* dbiVldRec = extResPtr.GetValidityRec(ptrRow);
00152 const VldRange& rowRange = dbiVldRec->GetVldRange();
00153 VldTimeStamp foundCreationDate = dbiVldRec->GetCreationDate();
00154
00155
00156 if ( foundCreationDate < lastCreationDateMap[aggNo] ) continue;
00157
00158
00159
00160 VldTimeStamp thisStart = rowRange.GetTimeStart();
00161 VldTimeStamp thisEnd = rowRange.GetTimeEnd();
00162
00163
00164
00165
00166 if ( thisEnd < maxStart[aggNo] ) continue;
00167 if ( thisStart > minEnd[aggNo] ) continue;
00168
00169
00170
00171
00172
00173
00174
00175
00176 if ( thisEnd < tsVldc && thisEnd > maxStart[aggNo] ) {
00177 MSG("Dcs",Msg::kVerbose)
00178 << " row " << irow << " trim aggno=" << aggNo
00179 << " low " << maxStart[aggNo].AsString("sql")
00180 << " SEQNO " << dbiVldRec->GetSeqNo()
00181 << " created " << foundCreationDate.AsString("sql")
00182 << " vld " << aggRangeMap[aggNo].AsString("acs-")
00183 << endl;
00184 maxStart[aggNo] = thisEnd;
00185 }
00186
00187 if ( thisStart > tsVldc && thisStart < minEnd[aggNo] ) {
00188 MSG("Dcs",Msg::kVerbose)
00189 << " row " << irow << " trim aggno=" << aggNo
00190 << " high " << minEnd[aggNo].AsString("sql")
00191 << " SEQNO " << dbiVldRec->GetSeqNo()
00192 << " created " << foundCreationDate.AsString("sql")
00193 << " vld " << aggRangeMap[aggNo].AsString("acs-")
00194 << endl;
00195 minEnd[aggNo] = thisStart;
00196 }
00197 }
00198
00199 resultRange = VldRange(0xFFFF,0xFFFF,
00200 VldTimeStamp::GetBOT(),VldTimeStamp::GetEOT(),
00201 "CoilTools::LocalQuery");
00202 for ( resItr=resultAggMap.begin() ; resItr!=resultAggMap.end() ; ++resItr) {
00203 int aggNo = resItr->first;
00204
00205 aggRangeMap[aggNo].SetTimeStart(maxStart[aggNo]);
00206 aggRangeMap[aggNo].SetTimeEnd(minEnd[aggNo]);
00207
00208 resultRange.TrimTo(aggRangeMap[aggNo]);
00209 MSG("Dcs",Msg::kDebug)
00210 << " trimmed aggNo " << aggNo << " SEQNO "
00211 << extResPtr.GetValidityRec(resultAggMap[aggNo])->GetSeqNo()
00212 << " VldRange " << aggRangeMap[aggNo].AsString("acs-") << endl;
00213 }
00214 MSG("Dcs",Msg::kDebug)
00215 << " overall final VldRange " << resultRange.AsString("acs-") << endl;
00216
00217 int nfound = resultAggMap.size();
00218 if ( nfound == 0 ) {
00219 MSG("Dcs",Msg::kDebug)
00220 << "LocalQuery<" << typeid(T).name()
00221 << " saw no appropriate rows" << endl;
00222 } else if ( nfound != GetNCoils(vldc) ) {
00223 MSG("Dcs",Msg::kDebug)
00224 << "LocalQuery<" << typeid(T).name() << " saw " << nfound
00225 << " matching rows (expected " << GetNCoils(vldc) << " for "
00226 << vldc << " in "
00227 << extResPtr.GetValidityRec()->GetVldRange().AsString("acs-")
00228 << endl;
00229 }
00230
00231 }
00232
00233
00234
00235 int CoilTools::GetNCoils(const VldContext& vldc)
00236 {
00237
00238 switch (vldc.GetDetector()) {
00239 case Detector::kNear: return 1;
00240 case Detector::kFar: return 2;
00241 default: return 0;
00242 }
00243 }
00244
00245
00246
00247 CoilTools::CoilTools()
00248 : fWindow(2*24*60*60)
00249 , fTask(0)
00250 {
00251
00252 fCoilStateSet.clear();
00253 fMagNearSet.clear();
00254 }
00255
00256
00257
00258 CoilTools& CoilTools::Instance()
00259 {
00260
00261
00262
00263 static Cleaner cleaner;
00264
00265
00266 if ( ! fgInstance ) {
00267 MSG("Dcs",Msg::kDebug) << "create CoilTools::fgInstance " << endl;
00268 cleaner.UseMe();
00269 fgInstance = new CoilTools();
00270 }
00271
00272
00273 if ( ! fgInstance ) {
00274 MSG("Dcs",Msg::kFatal)
00275 << "Could not create CoilTools::fgInstance !!" << endl;
00276 assert(fgInstance);
00277 }
00278
00279
00280 return *fgInstance;
00281
00282 }
00283
00284
00285
00286
00287
00288 void CoilTools::Distill(VldTimeStamp start,
00289 VldTimeStamp end,
00290 Int_t sm,
00291 Float_t curr,
00292 Detector::Detector_t NearOrFar) {
00293
00294
00295 if ((sm > 2) || (sm < 1)) {
00296 MSG("Dcs", Msg::kError) << "HOWL! Bad SM " << sm << endl;
00297 exit(-1);
00298 }
00299 CoilTools::CheckNearOrFar(NearOrFar);
00300
00301
00302
00303 static Bool_t first = true;
00304 static Double_t MaxTime;
00305 static Double_t MaxDelay;
00306 static Double_t MaxSmallGap;
00307 static Float_t MaxDeltaCurrent;
00308 if (first) {
00309 first = false;
00310 if (NearOrFar == Detector::kFar) {
00311 MSG("Dcs", Msg::kInfo) << "Distilling the Far Detector Coil" << endl;
00312 MaxTime = 3600.0;
00313
00314
00315
00316 MaxDelay = 900.0;
00317
00318
00319
00320
00321
00322
00323
00324
00325 MaxSmallGap = 150.0;
00326
00327
00328
00329
00330
00331
00332
00333 MaxDeltaCurrent = 0.015;
00334
00335
00336
00337
00338
00339 } else {
00340 MSG("Dcs", Msg::kInfo) << "Distilling the Near Detector Coil" << endl;
00341 MaxTime = 3600.0;
00342
00343
00344
00345 MaxDelay = 2700.0;
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 MaxSmallGap = 2700.0;
00356
00357
00358
00359
00360 MaxDeltaCurrent = 5.1;
00361
00362
00363
00364 }
00365 }
00366
00367
00368 static const VldTimeStamp BOT = VldTimeStamp::GetBOT();
00369 static const VldTimeStamp EOT = VldTimeStamp::GetEOT();
00370
00371
00372 static VldTimeStamp LastDistillTime[2] = {BOT, BOT};
00373 static Float_t LastDistillCurrent[2] = {0.0, 0.0};
00374
00375
00376 static VldTimeStamp LastReadTime[2] = {BOT, BOT};
00377 static Float_t LastReadCurrent[2] = {0.0, 0.0};
00378
00379
00380 static VldTimeStamp SaveReadTime[2] = {BOT, BOT};
00381 static Float_t SaveReadCurrent[2] = {0.0, 0.0};
00382
00383
00384 Int_t smindex = sm - 1;
00385
00386
00387
00388
00389 if ((start == EOT) &&
00390 (SaveReadTime[smindex] != BOT) &&
00391 (SaveReadTime[smindex] != EOT)) {
00392 MSG("Dcs", Msg::kInfo) << "SM" << sm << " Forced dump of this row "<< endl;
00393
00394 if (SaveReadTime[smindex] == LastReadTime[smindex]) {
00395 MSG("Dcs", Msg::kInfo) << " Row already just dumped "<< endl;
00396 } else {
00397 CoilTools::WriteRow(SaveReadTime[smindex],LastReadTime[smindex],sm,
00398 SaveReadCurrent[smindex],NearOrFar);
00399 }
00400
00401 SaveReadTime[smindex] = BOT;
00402 SaveReadCurrent[smindex] = 0.0;
00403 return;
00404 }
00405
00406
00407
00408
00409 if (LastReadTime[smindex] == BOT)
00410 if (!CoilTools::GetLast(start,sm,&LastReadTime[smindex],
00411 &LastReadCurrent[smindex],NearOrFar)) {
00412 SaveReadTime[smindex] = LastReadTime[smindex];
00413 SaveReadCurrent[smindex] = LastReadCurrent[smindex];
00414 } else {
00415 MSG("Dcs", Msg::kError) << "HOWL! Can't get initial conditions from DB" << endl;
00416
00417
00418 }
00419
00420
00421 MSG("Dcs", Msg::kDebug) << "SM" << sm << " Start: " << start.AsString("s")
00422 << " End: " << end.AsString("s") << "\tCurr: "
00423 << curr << endl;
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436 Float_t DeltaTime = (Double_t)start - (Double_t)SaveReadTime[smindex];
00437 Float_t DeltaDelay = (Double_t)start - (Double_t)LastReadTime[smindex];
00438 Float_t DeltaCurrent = curr - SaveReadCurrent[smindex];
00439
00440
00441
00442
00443
00444
00445
00446 if ((DeltaDelay > MaxSmallGap) && (DeltaDelay < MaxDelay)) {
00447 if ((fabs(curr) < 79.0) || (fabs(LastReadCurrent[smindex]) < 79.0)) {
00448
00449 MSG("Dcs", Msg::kSynopsis) << "SM" << sm << " SAVED: DeltaTime = "
00450 << DeltaTime << " DeltaDelay "
00451 << DeltaDelay << " DeltaCurrent = "
00452 << DeltaCurrent << endl;
00453 MSG("Dcs", Msg::kWarning) << "SM" << sm << " GAP from "
00454 << LastReadTime[smindex].AsString("s")
00455 << " to "
00456 << start.AsString("s")
00457 << " with low current " << curr << endl;
00458 CoilTools::WriteRow(SaveReadTime[smindex],LastReadTime[smindex],sm,
00459 SaveReadCurrent[smindex],NearOrFar);
00460
00461 LastDistillTime[smindex] = SaveReadTime[smindex];
00462 LastDistillCurrent[smindex] = SaveReadCurrent[smindex];
00463 SaveReadTime[smindex] = start;
00464 SaveReadCurrent[smindex] = curr;
00465 } else {
00466
00467 MSG("Dcs", Msg::kWarning) << "SM" << sm << " GAP of " << DeltaDelay
00468 << " skipped since current is " << curr
00469 << endl;
00470 }
00471 }
00472
00473 if ((DeltaTime >= MaxTime) ||
00474 (fabs(DeltaCurrent) >= MaxDeltaCurrent) ||
00475 (DeltaDelay >= MaxDelay)) {
00476 MSG("Dcs", Msg::kSynopsis) << "SM" << sm << " SAVED: DeltaTime = "
00477 << DeltaTime << " DeltaDelay "
00478 << DeltaDelay << " DeltaCurrent = "
00479 << DeltaCurrent << endl;
00480
00481
00482
00483
00484
00485
00486
00487 if (SaveReadTime[smindex] != BOT) {
00488 if (DeltaDelay < MaxDelay) {
00489 CoilTools::WriteRow(SaveReadTime[smindex],start,sm,
00490 SaveReadCurrent[smindex],NearOrFar);
00491 } else {
00492 MSG("Dcs", Msg::kWarning) << "SM" << sm << " GAP from "
00493 << LastReadTime[smindex].AsString("s")
00494 << " to " << start.AsString("s") << endl;
00495 CoilTools::WriteRow(SaveReadTime[smindex],
00496 LastReadTime[smindex],sm,SaveReadCurrent[smindex],
00497 NearOrFar);
00498 }
00499 LastDistillTime[smindex] = SaveReadTime[smindex];
00500 LastDistillCurrent[smindex] = SaveReadCurrent[smindex];
00501 }
00502
00503 SaveReadTime[smindex] = start;
00504 SaveReadCurrent[smindex] = curr;
00505 }
00506
00507
00508 LastReadTime[smindex] = start;
00509 LastReadCurrent[smindex] = curr;
00510 }
00511
00512
00513
00514
00515 void CoilTools::WriteRow(VldTimeStamp start,
00516 VldTimeStamp end,
00517 Int_t sm,
00518 Float_t curr,
00519 Detector::Detector_t NearOrFar) {
00520
00521 CoilTools::CheckNearOrFar(NearOrFar);
00522
00523
00524 UInt_t status = 0;
00525
00526 VldContext vldc(NearOrFar,SimFlag::kData,start);
00527 std::pair<Float_t,Float_t> limits = CoilCurrentLimits(vldc);
00528
00529 if (NearOrFar == Detector::kFar) {
00530
00531 if (curr < 0.0) status |= CoilStatus::kReverse;
00532
00533
00534 if (fabs(curr) < fabs(limits.first) ||
00535 fabs(curr) > fabs(limits.second) ) {
00536 status |= CoilStatus::kBad;
00537 status |= CoilStatus::kBadCurrent;
00538 }
00539 } else {
00540
00541 if (curr > 0.0) status |= CoilStatus::kReverse;
00542
00543
00544
00545 if (fabs(curr) < fabs(limits.first) ||
00546 fabs(curr) > fabs(limits.second) ) {
00547 status |= CoilStatus::kBad;
00548 status |= CoilStatus::kBadCurrent;
00549 }
00550 }
00551 CoilTools::Write(start,end,sm,curr,status,NearOrFar);
00552
00553
00554
00555
00556 MSG("Dcs", Msg::kInfo) << "SM" << sm << " DISTILLED: Start: "
00557 << start.AsString("s")
00558 << " End: " << end.AsString("s")<< "\tCurr: "
00559 << curr << " " << CoilStatus::MaskToString(status)
00560 << endl;
00561 }
00562
00563
00564
00565
00566
00567
00568 Int_t CoilTools::GetLast(VldTimeStamp start,
00569 Int_t sm,
00570 VldTimeStamp *LastTime,
00571 Float_t *LastCurr,
00572 Detector::Detector_t NearOrFar) {
00573
00574 CoilTools::CheckNearOrFar(NearOrFar);
00575
00576
00577
00578
00579
00580
00581 DbiSqlContext myContext = DbiSqlContext("TIMEEND <= \'");
00582 myContext << start.AsString("s") << '\'';
00583
00584
00585 if (NearOrFar == Detector::kNear) {
00586 myContext << " AND AGGREGATENO = 1 AND DETECTORMASK & 1 ORDER BY TIMEEND DESC LIMIT 1";
00587 } else {
00588 if (sm==1)
00589 myContext << " AND AGGREGATENO = 1 AND DETECTORMASK & 2 ORDER BY TIMEEND DESC LIMIT 1";
00590 else
00591 myContext << " AND AGGREGATENO = 2 AND DETECTORMASK & 2 ORDER BY TIMEEND DESC LIMIT 1";
00592 }
00593
00594
00595 DbiResultPtr<BfldDbiCoilState> rsPtr1("BFLDDBICOILSTATE",myContext);
00596
00597 Int_t numRows = rsPtr1.GetNumRows();
00598 MSG("Dcs", Msg::kDebug) << "The context: " << myContext.GetString()
00599 << " selected " << numRows
00600 << " rows from the BFLDDBICOILSTATE table" << endl;
00601
00602 Bool_t FoundIt = false;
00603
00604 for (int i = 0; i < numRows; ++i) {
00605
00606 const BfldDbiCoilState* mag = rsPtr1.GetRow(i);
00607
00608 if (mag->GetSupermodule() == sm) {
00609
00610 const DbiValidityRec* v_rec = rsPtr1.GetValidityRec(mag);
00611 const VldRange& v_range = v_rec->GetVldRange();
00612 *LastTime = v_range.GetTimeEnd();
00613
00614 *LastCurr=mag->GetCurrent();
00615 FoundIt = true;
00616 break;
00617 }
00618 }
00619 if (FoundIt) {
00620 MSG("Dcs", Msg::kInfo) << "SM" << sm << " Got last time in DB as "
00621 << LastTime->AsString("s")
00622 << " with current " << *LastCurr << " given "
00623 << start.AsString("s") << endl;
00624 return(0);
00625 } else {
00626 MSG("Dcs", Msg::kError) << "SM" << sm << " No last time in DB given "
00627 << start.AsString("s") << endl;
00628 return(-1);
00629 }
00630 }
00631
00632
00633
00634
00635
00636 void CoilTools::FixFormat() {
00637
00638 MsgService* msvc = MsgService::Instance();
00639 MsgStream* mstr = msvc->GetStream("Dcs");
00640
00641
00642
00643 mstr->SetLogLevel(Msg::kDebug);
00644
00645
00646
00647
00648
00649
00650 mstr->AttachOStream(Msg::kWarning,"distill-gaps.log");
00651 mstr->AttachOStream(Msg::kError,"distill-gaps.log");
00652 mstr->AttachOStream(Msg::kInfo,"distill-gaps.log");
00653 mstr->AttachOStream(Msg::kDebug,"distill-gaps.log");
00654 mstr->AttachOStream(Msg::kSynopsis,"distill-gaps.log");
00655
00656
00657 mstr->RemoveFormat(Msg::kWarning,
00658 Msg::kPriority+Msg::kName+Msg::kTime+Msg::kFile+Msg::kCVSId+Msg::kLine);
00659
00660 mstr->RemoveFormat(Msg::kDebug,
00661 Msg::kPriority+Msg::kName+Msg::kTime+Msg::kFile+Msg::kLine);
00662 }
00663
00664
00665
00666
00667 void CoilTools::CheckNearOrFar(Detector::Detector_t NearOrFar) {
00668 if (!((NearOrFar == Detector::kNear) || (NearOrFar == Detector::kFar))) {
00669 MSG("Dcs", Msg::kError) << "HOWL! Bad Detector Type "
00670 << Detector::AsString(NearOrFar) << endl;
00671 exit(-1);
00672 }
00673 }
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683 Bool_t CoilTools::IsOK(const VldContext& vldc)
00684 {
00685
00686 switch ( vldc.GetDetector() ) {
00687 case Detector::kFar:
00688 return CoilTools::Instance().IsCoilStateOK(vldc);
00689 break;
00690 case Detector::kNear:
00691 return CoilTools::Instance().IsMagNearOK(vldc);
00692 break;
00693 default:
00694 return false;
00695 }
00696 }
00697
00698 Bool_t CoilTools::IsReverse(const VldContext& vldc)
00699 {
00700
00701 switch ( vldc.GetDetector() ) {
00702 case Detector::kFar:
00703 return CoilTools::Instance().IsCoilStateReverse(vldc);
00704 break;
00705 case Detector::kNear:
00706 return CoilTools::Instance().IsMagNearReverse(vldc);
00707 break;
00708 default:
00709 return false;
00710 }
00711 }
00712
00713 std::pair<Float_t,Float_t> CoilTools::CoilCurrent(const VldContext& vldc)
00714 {
00715
00716 std::pair<Float_t,Float_t> coil_currents(0,0);
00717
00718 const BfldDbiCoilState* farsm1;
00719 const BfldDbiCoilState* farsm2;
00720 const Dcs_Mag_Near *nearstate;
00721 switch ( vldc.GetDetector() ) {
00722 case Detector::kFar:
00723 farsm1 = CoilTools::Instance().GetCoilState(vldc,1);
00724 farsm2 = CoilTools::Instance().GetCoilState(vldc,2);
00725 if (farsm1) coil_currents.first = farsm1->GetCurrent();
00726 if (farsm1) coil_currents.second = farsm2->GetCurrent();
00727 break;
00728 case Detector::kNear:
00729 nearstate = CoilTools::Instance().GetMagNear(vldc);
00730 if (nearstate) {
00731
00732 coil_currents.first = coil_currents.second = nearstate->GetCurrent();
00733 }
00734 break;
00735 default:
00736 break;
00737 }
00738 return coil_currents;
00739 }
00740
00741
00742
00743 Bool_t CoilTools::IsOK(VldTimeStamp now, Detector::Detector_t det)
00744 {
00745
00746 VldContext vldc(det,SimFlag::kData,now);
00747 return CoilTools::IsOK(vldc);
00748 }
00749
00750 Bool_t CoilTools::IsReverse(VldTimeStamp now, Detector::Detector_t det)
00751 {
00752
00753 VldContext vldc(det,SimFlag::kData,now);
00754 return CoilTools::IsReverse(vldc);
00755 }
00756
00757
00758 std::pair<Float_t,Float_t> CoilTools::CoilCurrentLimits(const VldContext& vldc)
00759 {
00760 std::pair<Float_t,Float_t> limits(0,0);
00761
00762
00763 Dbi::Task task = Dbi::kDefaultTask;
00764 DbiResultPtr<BfldDbiCoilLimits> rsptr_limits(vldc,task,Dbi::kDisabled);
00765 Int_t numrows = rsptr_limits.GetNumRows();
00766 if ( numrows > 0 ) {
00767 if ( numrows > 1 ) {
00768 MAXMSG("Dcs",Msg::kWarning,4)
00769 << "More than one BfldDbiCoilLimits entry for VLD " << vldc << endl;
00770 }
00771 const BfldDbiCoilLimits* limits_row = rsptr_limits.GetRow(0);
00772 limits = limits_row->GetLimits();
00773
00774
00775 static int lastSeqNo = 0;
00776 const DbiValidityRec* vldrec = rsptr_limits.GetValidityRec(limits_row);
00777 int currSeqNo = vldrec->GetSeqNo();
00778 if ( currSeqNo != lastSeqNo ) {
00779 MSG("Dcs",Msg::kSynopsis)
00780 << "BfldDbiCoilLimits: "
00781 << limits.first << " to " << limits.second
00782 << ", using SEQNO " << currSeqNo
00783 << endl
00784 << " for "
00785 << vldrec->GetVldRange().AsString("acs-")
00786 << endl;
00787 lastSeqNo = currSeqNo;
00788 }
00789 } else {
00790
00791 switch ( vldc.GetDetector() ) {
00792 case Detector::kNear:
00793
00794
00795
00796
00797
00798
00799
00800 limits.first = 4800.0;
00801 limits.second = 5100.0;
00802 break;
00803 case Detector::kFar:
00804 limits.first = 79.0;
00805 limits.second = 81.0;
00806 break;
00807 default:
00808 MAXMSG("Dcs",Msg::kInfo,4)
00809 << "Calling CoilCurrentLimits() on Detector::k"
00810 << Detector::AsString(vldc.GetDetector())
00811 << " is non-sensical" << endl;
00812 break;
00813 }
00814 MAXMSG("Dcs",Msg::kInfo,1)
00815 << "No DBI entry for BfldDbiCoilLimits for " << endl
00816 << " VldContext = " << vldc << endl
00817 << " use: " << limits.first << " to " << limits.second << endl;
00818 }
00819
00820
00821 return limits;
00822 }
00823
00824
00825 const BfldDbiCoilState* CoilTools::GetCoilState(const VldContext& vldc, int ism)
00826 {
00827
00828 if ( ! fExtendedRangeCoilState.IsCompatible(vldc) ) {
00829 ExtendedQuery<BfldDbiCoilState>(vldc,fDRPCoilState,fExtendedRangeCoilState);
00830 fLocalRangeCoilState = VldRange();
00831 }
00832
00833 if ( ! fLocalRangeCoilState.IsCompatible(vldc) )
00834 LocalQuery<BfldDbiCoilState>(vldc,fDRPCoilState,
00835 fCoilStateSet,fLocalRangeCoilState);
00836
00837
00838 if ( ism < 0 || ism > GetNCoils(vldc) ) return 0;
00839 return fCoilStateSet[ism];
00840 }
00841
00842
00843
00844 Bool_t CoilTools::IsCoilStateOK(const VldContext& vldc)
00845 {
00846
00847 int nOK=0, nBad=0;
00848
00849 int ncoils = GetNCoils(vldc);
00850 for (int icoil = 1; icoil <= ncoils ; ++icoil ) {
00851 const BfldDbiCoilState* coilState = GetCoilState(vldc,icoil);
00852 if ( ! coilState ) {
00853
00854
00855
00856 if (vldc.GetSimFlag() != SimFlag::kData) ++nOK;
00857 } else {
00858 if ( coilState->IsOK() ) ++nOK;
00859 else ++nBad;
00860 }
00861 }
00862
00863 if ( nOK == ncoils ) return true;
00864 if ( nBad == ncoils ) return false;
00865
00866
00867 static VldTimeStamp lastWarning = VldTimeStamp::GetBOT();
00868 VldTimeStamp thisTime = vldc.GetTimeStamp();
00869
00870 const int timeDelta = 60*20;
00871 if ( TMath::Abs(lastWarning.GetSec()-thisTime.GetSec()) > timeDelta ) {
00872 MSG("Dcs",Msg::kWarning)
00873 << "CoilTools saw inconsistent OK state " << endl
00874 << " nOK=" << nOK << " nBad=" << nBad << " of " << ncoils << " coils "
00875 << " for " << vldc.AsString("c") << endl
00876 << " suppress further warnings in the next " << timeDelta
00877 << " seconds." << endl;
00878 lastWarning = thisTime;
00879 }
00880 return false;
00881
00882 }
00883
00884
00885
00886 Bool_t CoilTools::IsCoilStateReverse(const VldContext& vldc)
00887 {
00888
00889 int nfwd=0, nrev=0;
00890
00891 int ncoils = GetNCoils(vldc);
00892 for (int icoil = 1; icoil <= ncoils ; ++icoil ) {
00893 const BfldDbiCoilState* coilState = GetCoilState(vldc,icoil);
00894 if ( ! coilState ) {
00895
00896
00897
00898 if (vldc.GetSimFlag() != SimFlag::kData) ++nfwd;
00899 } else {
00900 if ( coilState->GetStatus() & CoilStatus::kReverse ) ++nrev;
00901 else ++nfwd;
00902 }
00903 }
00904
00905 if ( nfwd == ncoils ) return false;
00906 if ( nrev == ncoils ) return true;
00907
00908 static VldTimeStamp lastWarning = VldTimeStamp::GetBOT();
00909 VldTimeStamp thisTime = vldc.GetTimeStamp();
00910
00911 const int timeDelta = 60*20;
00912 if ( TMath::Abs(lastWarning.GetSec()-thisTime.GetSec()) > timeDelta ) {
00913 MSG("Dcs",Msg::kWarning)
00914 << "CoilTools saw inconsistent polarities " << endl
00915 << " nforward=" << nfwd << " nreverse=" << nrev
00916 << " for " << vldc.AsString("c") << endl
00917 << " suppress further warnings in the next " << timeDelta
00918 << " seconds." << endl;
00919 lastWarning = thisTime;
00920 }
00921 return true;
00922
00923 }
00924
00925
00926
00927 const Dcs_Mag_Near* CoilTools::GetMagNear(const VldContext& vldc)
00928 {
00929
00930 if ( ! fExtendedRangeMagNear.IsCompatible(vldc) ) {
00931 ExtendedQuery<Dcs_Mag_Near>(vldc,fDRPMagNear,fExtendedRangeMagNear);
00932 fLocalRangeMagNear = VldRange();
00933 }
00934
00935 if ( ! fLocalRangeMagNear.IsCompatible(vldc) )
00936 LocalQuery<Dcs_Mag_Near>(vldc,fDRPMagNear,fMagNearSet,fLocalRangeMagNear);
00937
00938 return fMagNearSet[1];
00939
00940 }
00941
00942
00943
00944 Bool_t CoilTools::IsMagNearOK(const VldContext& vldc)
00945 {
00946
00947 const Dcs_Mag_Near* magNear = GetMagNear(vldc);
00948
00949 if ( ! magNear ) {
00950
00951
00952 if (vldc.GetSimFlag() == SimFlag::kData) return false;
00953 else return true;
00954 }
00955
00956 std::pair<Float_t,Float_t> limits = CoilCurrentLimits(vldc);
00957 Float_t curr = magNear->GetCurrent();
00958
00959
00960 if (((fabs(curr) < fabs(limits.first)) ||
00961 fabs(curr) > fabs(limits.second)) ||
00962 (magNear->GetInterLocksComplete() == 0) ||
00963 (magNear->GetPowerSupplyOn() == 0) ||
00964 (magNear->GetGroundFault() == 1) ||
00965 (magNear->GetOverCurrentDC() == 1) ||
00966 (magNear->GetOverTemperature() == 1) ) {
00967 return false;
00968 } else {
00969 return true;
00970 }
00971
00972 }
00973
00974
00975
00976 Bool_t CoilTools::IsMagNearReverse(const VldContext& vldc)
00977 {
00978
00979 const Dcs_Mag_Near* magNear = GetMagNear(vldc);
00980
00981 if ( ! magNear ) {
00982
00983
00984 if (vldc.GetSimFlag() == SimFlag::kData) return true;
00985 else return false;
00986 }
00987
00988 return magNear->GetPolarity();
00989 }
00990
00991
00992
00993 void CoilTools::Write(VldTimeStamp start,
00994 VldTimeStamp end,
00995 Int_t sm,
00996 Float_t curr,
00997 UInt_t status,
00998 Detector::Detector_t det) {
00999
01000 Int_t aggNo = sm;
01001 Dbi::Task task = 0;
01002 VldRange OutputRange(det,SimFlag::kData,start,end,"BfldDbiCoilState");
01003
01004 DbiWriter<BfldDbiCoilState> writer(OutputRange,aggNo,task);
01005
01006 BfldDbiCoilState row0(curr,status,(UInt_t)sm);
01007 writer << row0;
01008 writer.Close();
01009 }
01010
01011