]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - STEER/AliDCSSensorArray.cxx
Warnings
[u/mrichter/AliRoot.git] / STEER / AliDCSSensorArray.cxx
index 808825b65500bb867145992a754c4e75a712d34a..9a98107b3caddc2d20e1eb26c616dc20f34d4ba7 100644 (file)
 ///////////////////////////////////////////////////////////////////////////////
 
 #include "AliDCSSensorArray.h"
+#include "AliLog.h"
 
 ClassImp(AliDCSSensorArray)
 
-const Int_t  kMinGraph = 10;       // minimum #points of graph to be fitted
-const Int_t  kMinPoints = 10;      // minimum number of points per knot in fit
-const Int_t  kIter = 10;           // number of iterations for spline fit
-const Double_t  kMaxDelta = 0.00;  // precision parameter for spline fit
-const Int_t  kFitReq = 2;          // fit requirement, 2 = continuous 2nd derivative
+const Double_t kSecInHour = 3600.; // seconds in one hour
+const UInt_t   kMinMapTime = 60;   // don't fit maps shorter than one minute
 
 //_____________________________________________________________________________
 AliDCSSensorArray::AliDCSSensorArray():TNamed(), 
-  fFirstSensor(0),
-  fLastSensor(0),
+  fMinGraph(10),
+  fMinPoints(10),
+  fIter(10),
+  fMaxDelta(0.0),
+  fFitReq(2),
+  fValCut(-1),
+  fDiffCut(-1),
   fStartTime (2000,1,1,0,0,0),
   fEndTime   (2000,1,1,0,0,0),
   fSensors(0)
@@ -45,56 +48,105 @@ AliDCSSensorArray::AliDCSSensorArray():TNamed(),
 
 }
 //_____________________________________________________________________________
-AliDCSSensorArray::AliDCSSensorArray(Int_t prevRun, const char* dbEntry) : 
+AliDCSSensorArray::AliDCSSensorArray(TClonesArray *arr):TNamed(),
+  fMinGraph(10),
+  fMinPoints(10),
+  fIter(10),
+  fMaxDelta(0.0),
+  fFitReq(2),
+  fValCut(-1),
+  fDiffCut(-1),
+  fStartTime (2000,1,1,0,0,0),
+  fEndTime   (2000,1,1,0,0,0),
+  fSensors(arr)
+{
+  //
+  // AliDCSSensorArray special constructor taking TClonesArray from ReadList
+  //
+
+}
+//_____________________________________________________________________________
+AliDCSSensorArray::AliDCSSensorArray(Int_t run, const char* dbEntry) :
   TNamed(),
-  fFirstSensor(0),
-  fLastSensor(0),
+  fMinGraph(10),
+  fMinPoints(10),
+  fIter(10),
+  fMaxDelta(0.0),
+  fFitReq(2),
+  fValCut(-1),
+  fDiffCut(-1),
   fStartTime (2000,1,1,0,0,0),
   fEndTime   (2000,1,1,0,0,0),
   fSensors(0)
 {
   //
-  // Read positions etc. from data base entry for previous run
-  // Delete all fits and graphs
+  // Read configuration from OCDB
   //
-   AliDCSSensorArray *temp=0;
-   AliCDBEntry* entry = 
-       AliCDBManager::Instance()->Get(dbEntry,prevRun); 
-   if (entry){
-     entry->SetOwner(kTRUE);
-     temp = (AliDCSSensorArray*)entry->GetObject();
-   } 
 
-   TGraph *gr;
-   AliSplineFit* fit;
+  AliCDBEntry *entry = AliCDBManager::Instance()->Get(dbEntry,run);
+  TTree *tree = (TTree*) entry->GetObject();
+  fSensors = AliDCSSensor::ReadTree(tree);
+}
+//_____________________________________________________________________________
+AliDCSSensorArray::AliDCSSensorArray(UInt_t startTime, UInt_t endTime,
+                       TTree* confTree) :
+  TNamed(),
+  fMinGraph(10),
+  fMinPoints(10),
+  fIter(10),
+  fMaxDelta(0.0),
+  fFitReq(2),
+  fValCut(-1),
+  fDiffCut(-1),
+  fStartTime (2000,1,1,0,0,0),
+  fEndTime   (2000,1,1,0,0,0),
+  fSensors(0)
 
-// Delete previous values
-   
-   Int_t nsensors = temp->fSensors->GetEntries();
-   for ( Int_t isensor=0; isensor<nsensors; isensor++) {
-     AliDCSSensor *entry = (AliDCSSensor*)temp->fSensors->At(isensor);
-     gr = entry->GetGraph();
-     if ( gr != 0 ) {
-       delete gr;
-       gr = 0;
-     }
-     fit = entry->GetFit();
-     if ( fit != 0 ) {
-       delete fit;
-       fit = 0;
-     }
-   }    
-   
-   new (this) AliDCSSensorArray(*temp);
-   delete temp;
+{
+  //
+  // AliDCSSensorArray constructor for Shuttle preprocessor
+  //  (confTree read from OCDB)
+  //
+  fSensors = AliDCSSensor::ReadTree(confTree);
+  fSensors->BypassStreamer(kFALSE);
+  fStartTime = TTimeStamp((time_t)startTime,0);
+  fEndTime   = TTimeStamp((time_t)endTime,0);
 }
 
 
+//_____________________________________________________________________________
+AliDCSSensorArray::AliDCSSensorArray(UInt_t startTime, UInt_t endTime,
+                       TClonesArray *sensors) :
+  TNamed(),
+  fMinGraph(10),
+  fMinPoints(10),
+  fIter(10),
+  fMaxDelta(0.0),
+  fFitReq(2),
+  fValCut(-1),
+  fDiffCut(-1),
+  fStartTime (2000,1,1,0,0,0),
+  fEndTime   (2000,1,1,0,0,0),
+  fSensors(sensors)
+
+{
+  //
+  // AliDCSSensorArray constructor for Shuttle preprocessor
+  //  (TClonesArray of AliDCSSensor objects)
+  //
+  fStartTime = TTimeStamp((time_t)startTime,0);
+  fEndTime   = TTimeStamp((time_t)endTime,0);
+}
 
 //_____________________________________________________________________________
 AliDCSSensorArray::AliDCSSensorArray(const AliDCSSensorArray &c):TNamed(c),
-  fFirstSensor(c.fFirstSensor),
-  fLastSensor(c.fLastSensor),
+  fMinGraph(c.fMinGraph),
+  fMinPoints(c.fMinPoints),
+  fIter(c.fIter),
+  fMaxDelta(c.fMaxDelta),
+  fFitReq(c.fFitReq),
+  fValCut(c.fValCut),
+  fDiffCut(c.fDiffCut),
   fStartTime (c.fStartTime),
   fEndTime   (c.fEndTime),
   fSensors(0)
@@ -104,8 +156,7 @@ AliDCSSensorArray::AliDCSSensorArray(const AliDCSSensorArray &c):TNamed(c),
   // AliDCSSensorArray copy constructor
   //
 
-  ((AliDCSSensorArray &) c).Copy(*this);
-
+  fSensors = (TClonesArray*)c.fSensors->Clone();
 }
 
 ///_____________________________________________________________________________
@@ -125,125 +176,255 @@ AliDCSSensorArray &AliDCSSensorArray::operator=(const AliDCSSensorArray &c)
   //
   // Assignment operator
   //
-
-  if (this != &c) ((AliDCSSensorArray &) c).Copy(*this);
+  if (this != &c) {
+     fSensors->Delete();
+     new (this) AliDCSSensorArray(c);
+     fSensors = (TClonesArray*)c.fSensors->Clone();
+  }
   return *this;
-
 }
 
-//_____________________________________________________________________________
-void AliDCSSensorArray::Copy(TObject &c) const
+//____________________________________________________________________________
+
+void AliDCSSensorArray::SetGraph(TMap *map)
 {
   //
-  // Copy function
+  // Read graphs from DCS maps
   //
-
-  TObject::Copy(c);
+  Int_t nsensors = fSensors->GetEntries();
+  for ( Int_t isensor=0; isensor<nsensors; isensor++) {
+    AliDCSSensor *entry = (AliDCSSensor*)fSensors->At(isensor);
+    TString stringID = entry->GetStringID();
+    TGraph *gr = (TGraph*)map->GetValue(stringID.Data());
+    if ( gr !=0 ) {
+       entry->SetGraph((TGraph*)gr->Clone());
+    } else {
+       entry->SetGraph(0);
+    }
+  }
 }
 //_____________________________________________________________________________
-void AliDCSSensorArray::SetGraph(TMap *map, const char *amandaString) 
+void AliDCSSensorArray::MakeSplineFit(TMap *map, Bool_t keepMap)
 {
-  // 
-  // Read graphs from DCS maps 
   //
-  char dname[100];
+  // Make spline fits from DCS maps
+  //
   Int_t nsensors = fSensors->GetEntries();
   for ( Int_t isensor=0; isensor<nsensors; isensor++) {
     AliDCSSensor *entry = (AliDCSSensor*)fSensors->At(isensor);
-    Int_t dcsSensor=entry->GetIdDCS();
-    sprintf(dname,amandaString,dcsSensor);
-    TGraph *gr = (TGraph*)map->GetValue(dname);
-    entry->SetGraph(gr);
-  } 
-}  
+    TString stringID = entry->GetStringID();
+    TGraph *gr = (TGraph*)map->GetValue(stringID.Data());
+    if (!gr ) {
+      entry->SetFit(0);
+      entry->SetGraph(0);
+      AliWarning(Form("sensor %s: no input graph",stringID.Data()));
+      continue;
+    }
+    UInt_t timeDiff = entry->GetEndTime() - entry->GetStartTime();
+    if ( timeDiff < kMinMapTime ) {
+      AliWarning(Form("sensor %s: map length < 60 s, DCS graph kept.",stringID.Data()));
+      entry->SetGraph((TGraph*)gr->Clone());
+    } else {
+      AliSplineFit *fit = new AliSplineFit();
+      fit->SetMinPoints(fMinGraph);
+      fit->InitKnots(gr,fMinPoints,fIter,fMaxDelta);
+      fit->SplineFit(fFitReq);
+      fit->Cleanup();
+      if (fit) {
+        entry->SetFit(fit);
+      } else {
+        AliWarning(Form("sensor %s: no fit performed, DCS graph kept.",stringID.Data()));
+        entry->SetGraph((TGraph*)gr->Clone());
+      }
+    }
+    if (keepMap) entry->SetGraph((TGraph*)gr->Clone());
+  }
+}
 //_____________________________________________________________________________
-void AliDCSSensorArray::MakeSplineFit(TMap *map, const char *amandaString) 
+void AliDCSSensorArray::MakeSplineFitAddPoints(TMap *map)
 {
-  // 
-  // Make spline fits from DCS maps 
   //
-  char dname[100];
+  // Make spline fits from DCS maps
+  //
   Int_t nsensors = fSensors->GetEntries();
   for ( Int_t isensor=0; isensor<nsensors; isensor++) {
     AliDCSSensor *entry = (AliDCSSensor*)fSensors->At(isensor);
-    Int_t dcsSensor=entry->GetIdDCS();
-    sprintf(dname,amandaString,dcsSensor);
-    TGraph *gr = (TGraph*)map->GetValue(dname);
-    if (gr->GetN() < kMinGraph ) continue;    
+
+  // fetch old points from existing graph
+
+    TGraph *gr = entry->GetGraph();
+    if (!gr) {
+      gr = new TGraph();
+      entry->SetGraph(gr);
+    } 
+    TString stringID = entry->GetStringID();
+
+  // fetch new points from DCS map
+  
+    TGraph *grAdd = (TGraph*)map->GetValue(stringID.Data());
+    if (!grAdd ) return;
+
+  // add new points to end of graph
+  
+    Int_t nPointsOld=gr->GetN();
+    Int_t nPointsAdd=grAdd->GetN();
+    gr->Expand(nPointsOld+nPointsAdd);
+    gr->Set(nPointsOld+nPointsAdd);
+    Double_t *addX=grAdd->GetX();
+    Double_t *addY=grAdd->GetY();
+    for (Int_t i=0;i<nPointsAdd;i++) {
+      gr->SetPoint(nPointsOld+i,addX[i],addY[i]);
+    }
+   // make fit to complete graph
+   
     AliSplineFit *fit = new AliSplineFit();
-    fit->InitKnots(gr,kMinPoints,kIter,kMaxDelta);
-    fit->SplineFit(kFitReq);
-    entry->SetStartTime(fStartTime);
+    fit->SetMinPoints(fMinGraph);
+    fit->InitKnots(gr,fMinPoints,fIter,fMaxDelta);
+    fit->SplineFit(fFitReq);
     fit->Cleanup();
-    entry->SetFit(fit);
-  } 
-}  
+    if (fit) {
+      AliSplineFit *oldFit = entry->GetFit();
+      if (oldFit) delete oldFit;
+      entry->SetFit(fit);
+    } else {
+      AliWarning(Form("sensor %s: no new fit performed. If available, old fit kept.",stringID.Data()));
+    }
+  }
+}
 
+//_____________________________________________________________________________
+Int_t AliDCSSensorArray::NumFits() const 
+{
+ //
+ // Return number of sensors where a succesful fit has been made
+ //
+  Int_t nfit=0;
+  Int_t nsensors = fSensors->GetEntries();
+  for ( Int_t isensor=0; isensor<nsensors; isensor++) {
+    AliDCSSensor *entry = (AliDCSSensor*)fSensors->At(isensor);
+    if (entry->GetFit()) nfit++;
+  }    
+  return nfit;
+}
 //_____________________________________________________________________________
 Double_t AliDCSSensorArray::GetValue(UInt_t timeSec, Int_t sensor) 
 {
-  // 
+  //
   // Return sensor value at time timeSec (obtained from fitted function)
   //  timeSec = time in seconds from start of run
   //
+
   AliDCSSensor *entry = (AliDCSSensor*)fSensors->At(sensor);
-  return entry->GetValue(timeSec);
+  return entry->GetValue(TTimeStamp((time_t)fStartTime.GetSec()+timeSec,0));
 }
-    
+
 
 //_____________________________________________________________________________
-TMap* AliDCSSensorArray::ExtractDCS(TMap *dcsMap, const char *amandaString) 
+TMap* AliDCSSensorArray::ExtractDCS(TMap *dcsMap, Bool_t keepStart)
 {
  //
  // Extract temperature graphs from DCS maps
  //
  TMap *values = new TMap;
  TObjArray * valueSet;
+ //
+ // Keep global start/end times
+ //    to avoid extrapolations, the fits will only be valid from first 
+ //    measured point to last measured point. This is consistent with hardware,
+ //    as there would be a new measured point if the value changed.
+ TTimeStamp startTime=fStartTime;
+ TTimeStamp endTime=fEndTime;
  Int_t nsensors = fSensors->GetEntries();
  for ( Int_t isensor=0; isensor<nsensors; isensor++) {
    AliDCSSensor *entry = (AliDCSSensor*)fSensors->At(isensor);
-   Int_t dcsSensor=entry->GetIdDCS();
-   TString DPname = Form (amandaString,dcsSensor);
-   TPair *pair = (TPair*)dcsMap->FindObject(DPname.Data());
-   valueSet = (TObjArray*)pair->Value();
-   TGraph *graph = MakeGraph(valueSet);
-   values->Add(new TObjString(DPname.Data()),graph);
+   TString stringID = entry->GetStringID();
+   TPair *pair = (TPair*)dcsMap->FindObject(stringID.Data());
+   if ( pair ) {                            // only try to read values
+                                            // if DCS object available
+     valueSet = (TObjArray*)pair->Value();
+     TGraph *graph = MakeGraph(valueSet,keepStart);   // MakeGraph sets start/end time
+                                            // per sensor
+     values->Add(new TObjString(stringID.Data()),graph);
+     entry->SetStartTime(fStartTime);
+     entry->SetEndTime(fEndTime);
+   }
  }
+ // Reset global start/end time 
+ //    ..... yes, I know this won't get a prize for structured programming..:-)
+
+ fStartTime=startTime;
+ fEndTime=endTime;
  return values;
 }
 
 //_____________________________________________________________________________
-TGraph* AliDCSSensorArray::MakeGraph(TObjArray* valueSet){
+TGraph* AliDCSSensorArray::MakeGraph(TObjArray* valueSet, Bool_t keepStart){
   //
   // Make graph of temperature values read from DCS map
   //   (spline fit parameters will subsequently be obtained from this graph) 
   //
   Int_t nentries = valueSet->GetEntriesFast(); 
+  if ( nentries == 0 ) return 0;
+  
   Float_t *x = new Float_t[nentries];
   Float_t *y = new Float_t[nentries];
   Int_t time0=0;
+  TTimeStamp firstTime(0);
+  TTimeStamp lastTime(0);
+  if (keepStart) { 
+     firstTime = fStartTime;
+     time0 = firstTime.GetSec();
+  }
   Int_t out=0;
   Int_t skipped=0;
-  Float_t value;  
+  AliDCSValue *val = (AliDCSValue *)valueSet->At(0);
+  AliDCSValue::Type type = val->GetType();
+  if ( type == AliDCSValue::kInvalid || type == AliDCSValue::kBool ) return 0;
+  Float_t value;
   for (Int_t i=0; i<nentries; i++){
-    AliDCSValue * val = (AliDCSValue *)valueSet->At(i);
+    val = (AliDCSValue *)valueSet->At(i);
     if (!val) continue;
     if (time0==0){
       time0=val->GetTimeStamp();
+      firstTime= TTimeStamp((time_t)val->GetTimeStamp(),0);
+      lastTime=TTimeStamp((time_t)val->GetTimeStamp(),0);
+     }
+    switch ( type )
+    { 
+      case AliDCSValue::kFloat:
+        value = val->GetFloat();
+        break;
+      case AliDCSValue::kChar:
+        value = static_cast<Float_t>(val->GetChar());
+       break;
+      case AliDCSValue::kInt:
+        value = static_cast<Float_t>(val->GetInt());
+       break;
+      case AliDCSValue::kUInt:
+        value = static_cast<Float_t>(val->GetUInt());
+       break;
+      default:
+        continue;
     }
-    value = val->GetFloat();
-    if (TMath::Abs(value)>100) continue;   // refuse values exceeding 100
-    if ( out>0 && skipped<10 && TMath::Abs(value-y[out-1])>5) {
-      skipped++;                               // refuse temperatures changing 
-      continue;                                // by > 5 degrees in one time step
-    }                                          
-    skipped=0;                                       
+    if (fValCut>0 && TMath::Abs(value)>fValCut) continue;   // refuse values greater than cut
+    if (fDiffCut>0 ) {
+      if ( out>0 && skipped<10 && TMath::Abs(value-y[out-1])>fDiffCut) {
+        skipped++;                               // refuse values changing 
+        continue;                                // by > cut  in one time step
+      }                                          
+      skipped=0;
+    }                                        
     if (val->GetTimeStamp()-time0>1000000) continue;
-    x[out] = (val->GetTimeStamp()-time0)/3600.0; // give times in fractions of hours 
+    lastTime=TTimeStamp((time_t)val->GetTimeStamp(),0);
+    x[out] = (val->GetTimeStamp()-time0)/kSecInHour; // give times in fractions of hours 
     y[out] = val->GetFloat();
-    out++;
-    
+    out++;    
   }
+  if (!keepStart) fStartTime=firstTime;
+  fEndTime=lastTime;
   TGraph * graph = new TGraph(out,x,y);
   delete [] x;
   delete [] y;
@@ -264,7 +445,20 @@ AliDCSSensor* AliDCSSensorArray::GetSensor(Int_t IdDCS)
  return 0;
 }
 //_____________________________________________________________________________
-AliDCSSensor* AliDCSSensorArray::GetSensor(Double_t x, Double_t y, Double_t z) 
+AliDCSSensor* AliDCSSensorArray::GetSensor(const TString& stringID)
+{
+ //
+ //  Return sensor information for sensor specified by stringID
+ //
+ Int_t nsensors = fSensors->GetEntries();
+ for (Int_t isensor=0; isensor<nsensors; isensor++) {
+   AliDCSSensor *entry = (AliDCSSensor*)fSensors->At(isensor);
+   if (entry->GetStringID() == stringID) return entry;
+ }
+ return 0;
+}
+//_____________________________________________________________________________
+AliDCSSensor* AliDCSSensorArray::GetSensor(Double_t x, Double_t y, Double_t z)
 {
  //
  //  Return sensor closest to given position
@@ -282,7 +476,7 @@ AliDCSSensor* AliDCSSensorArray::GetSensor(Double_t x, Double_t y, Double_t z)
    if (dist2 < dist2min) {
       ind=isensor;
       dist2min = dist2;
-   } 
+   }
  }
  if ( ind >= 0 ) {
     return (AliDCSSensor*)fSensors->At(ind);
@@ -290,3 +484,169 @@ AliDCSSensor* AliDCSSensorArray::GetSensor(Double_t x, Double_t y, Double_t z)
     return 0;
  }
 }
+//_____________________________________________________________________________
+AliDCSSensor* AliDCSSensorArray::GetSensorNum(Int_t ind)
+{
+ //
+ //  Return sensor given by array index
+ //
+ return (AliDCSSensor*)fSensors->At(ind);
+}
+
+//_____________________________________________________________________________
+Int_t AliDCSSensorArray::SetSensor(const TString& stringID,
+                          const  AliDCSSensor& sensor)
+{
+ //
+ //  Update sensor information for sensor specified by stringID
+ //
+ Int_t nsensors = fSensors->GetEntries();
+ for (Int_t isensor=0; isensor<nsensors; isensor++) {
+   AliDCSSensor *entry = (AliDCSSensor*)fSensors->At(isensor);
+   if (entry->GetStringID() == stringID) 
+     {
+      new ((*fSensors)[isensor])AliDCSSensor(sensor);
+      return isensor;
+     }
+ }
+ return -1;
+}
+//_____________________________________________________________________________
+void AliDCSSensorArray::SetSensorNum(const Int_t ind, const AliDCSSensor& sensor)
+{
+ //
+ //  Update sensor information for sensor at index ind
+ //
+   new ((*fSensors)[ind])AliDCSSensor(sensor);
+   return;
+}
+//_____________________________________________________________________________
+void AliDCSSensorArray::RemoveSensorNum(Int_t ind)
+{
+ //
+ //  Return sensor given by array index
+ //
+
+  delete fSensors->RemoveAt(ind);
+  fSensors->Compress();
+}
+//_____________________________________________________________________________
+void AliDCSSensorArray::RemoveSensor(Int_t IdDCS)
+{
+ //
+ //  Deletes Sensor by given IdDCS
+ //
+
+  Int_t nsensors = fSensors->GetEntries();
+  for (Int_t isensor=0; isensor<nsensors; isensor++) { // loop over sensors
+    AliDCSSensor *entry = (AliDCSSensor*)fSensors->At(isensor);
+    if (entry->GetIdDCS()==IdDCS) {
+      delete fSensors->RemoveAt(isensor);
+      break;
+    }
+  }
+  fSensors->Compress();
+}
+//_____________________________________________________________________________
+TArrayI AliDCSSensorArray::OutsideThreshold(Double_t threshold, UInt_t timeSec, Bool_t below) const
+{
+ //
+ // Return sensors with values outside threshold at time defined by second
+ // parameter
+ // By default sensors with values below threshold are listed, if third
+ // parameter is set to kFALSE sensors with values above threshold are listed
+ //
+  Int_t nsensors = fSensors->GetEntries();
+  TArrayI array(nsensors);
+  Int_t outside=0;
+  for (Int_t isensor=0; isensor<nsensors; isensor++) { // loop over sensors
+    AliDCSSensor *entry = (AliDCSSensor*)fSensors->At(isensor);
+    Double_t val=entry->GetValue(timeSec);
+    if (below) {
+      if (val<threshold) array[outside++] = entry->GetIdDCS();
+    } else {
+      if (val>threshold) array[outside++] = entry->GetIdDCS();
+    }    
+  }
+  array.Set(outside);
+  return array;
+}
+//_____________________________________________________________________________
+Int_t AliDCSSensorArray::GetFirstIdDCS() const
+{
+ //
+ //  Return DCS Id of first sensor
+ //
+ if ( fSensors != 0 ) {
+    return ((AliDCSSensor*)fSensors->At(0))->GetIdDCS();
+ } else {
+    return 0;
+ }
+}
+
+//_____________________________________________________________________________
+Int_t AliDCSSensorArray::GetLastIdDCS() const 
+{
+ //
+ //  Return DCS Id of last sensor
+ //
+ if ( fSensors != 0 ) {
+    Int_t last = fSensors->GetEntries();
+    return ((AliDCSSensor*)fSensors->At(last-1))->GetIdDCS();
+ } else {
+    return 0;
+ }
+}
+//_____________________________________________________________________________
+void AliDCSSensorArray::ClearGraph()
+{
+  //
+  // Delete DCS graphs from all sensors in array
+  //
+   
+   Int_t nsensors = fSensors->GetEntries();
+   for ( Int_t isensor=0; isensor<nsensors; isensor++) {
+     AliDCSSensor *sensor = (AliDCSSensor*)fSensors->At(isensor);
+     TGraph *gr = sensor->GetGraph();
+     if ( gr != 0 ) {
+       delete gr;
+       gr = 0;
+     }
+     sensor->SetGraph(0);
+   }
+}
+//_____________________________________________________________________________
+void AliDCSSensorArray::ClearFit()
+{
+  //
+  // Delete spline fits from all sensors in array
+  //
+
+   Int_t nsensors = fSensors->GetEntries();
+   for ( Int_t isensor=0; isensor<nsensors; isensor++) {
+     AliDCSSensor *sensor = (AliDCSSensor*)fSensors->At(isensor);
+     AliSplineFit *fit = sensor->GetFit();
+     if ( fit != 0 ) {
+       delete fit;
+       fit = 0;
+     }
+     sensor->SetFit(0);
+   }
+}
+//_____________________________________________________________________________
+void AliDCSSensorArray::AddSensors(AliDCSSensorArray *newSensors)
+{
+  //
+  // add sensors from two sensor arrays
+  //
+  
+  Int_t numNew = newSensors->NumSensors();
+  Int_t numOld = fSensors->GetEntries();
+  fSensors->Expand(numOld+numNew);
+  for (Int_t i=0;i<numNew;i++) {
+    AliDCSSensor *sens = newSensors->GetSensorNum(i);
+    new ((*fSensors)[numOld+i]) AliDCSSensor(*sens);
+  }
+}  
+