correct for omission
[u/mrichter/AliRoot.git] / STEER / AliDCSSensorArray.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16
17 ///////////////////////////////////////////////////////////////////////////////
18 //                                                                           //
19 //  Calibration class for DCS sensors                                        //
20 //  Authors: Marian Ivanov and Haavard Helstrup                              //
21 //                                                                           //
22 ///////////////////////////////////////////////////////////////////////////////
23
24 #include "AliDCSSensorArray.h"
25 #include "AliLog.h"
26 #include <TMath.h>
27
28 ClassImp(AliDCSSensorArray)
29
30 const Double_t kSecInHour = 3600.; // seconds in one hour
31 const UInt_t   kMinMapTime = 60;   // don't fit maps shorter than one minute
32
33 //_____________________________________________________________________________
34 AliDCSSensorArray::AliDCSSensorArray():TNamed(), 
35   fMinGraph(10),
36   fMinPoints(10),
37   fIter(10),
38   fMaxDelta(0.0),
39   fFitReq(2),
40   fValCut(-1),
41   fDiffCut(-1),
42   fStartTime (2000,1,1,0,0,0),
43   fEndTime   (2000,1,1,0,0,0),
44   fSensors(0)
45 {
46   //
47   // AliDCSSensorArray default constructor
48   //
49
50 }
51 //_____________________________________________________________________________
52 AliDCSSensorArray::AliDCSSensorArray(TClonesArray *arr):TNamed(),
53   fMinGraph(10),
54   fMinPoints(10),
55   fIter(10),
56   fMaxDelta(0.0),
57   fFitReq(2),
58   fValCut(-1),
59   fDiffCut(-1),
60   fStartTime (2000,1,1,0,0,0),
61   fEndTime   (2000,1,1,0,0,0),
62   fSensors(arr)
63 {
64   //
65   // AliDCSSensorArray special constructor taking TClonesArray from ReadList
66   //
67
68 }
69 //_____________________________________________________________________________
70 AliDCSSensorArray::AliDCSSensorArray(Int_t run, const char* dbEntry) :
71   TNamed(),
72   fMinGraph(10),
73   fMinPoints(10),
74   fIter(10),
75   fMaxDelta(0.0),
76   fFitReq(2),
77   fValCut(-1),
78   fDiffCut(-1),
79   fStartTime (2000,1,1,0,0,0),
80   fEndTime   (2000,1,1,0,0,0),
81   fSensors(0)
82 {
83   //
84   // Read configuration from OCDB
85   //
86
87   AliCDBEntry *entry = AliCDBManager::Instance()->Get(dbEntry,run);
88   TTree *tree = (TTree*) entry->GetObject();
89   fSensors = AliDCSSensor::ReadTree(tree);
90 }
91 //_____________________________________________________________________________
92 AliDCSSensorArray::AliDCSSensorArray(UInt_t startTime, UInt_t endTime,
93                        TTree* confTree) :
94   TNamed(),
95   fMinGraph(10),
96   fMinPoints(10),
97   fIter(10),
98   fMaxDelta(0.0),
99   fFitReq(2),
100   fValCut(-1),
101   fDiffCut(-1),
102   fStartTime (2000,1,1,0,0,0),
103   fEndTime   (2000,1,1,0,0,0),
104   fSensors(0)
105
106 {
107   //
108   // AliDCSSensorArray constructor for Shuttle preprocessor
109   //  (confTree read from OCDB)
110   //
111   fSensors = AliDCSSensor::ReadTree(confTree);
112   fSensors->BypassStreamer(kFALSE);
113   fStartTime = TTimeStamp((time_t)startTime,0);
114   fEndTime   = TTimeStamp((time_t)endTime,0);
115 }
116
117
118 //_____________________________________________________________________________
119 AliDCSSensorArray::AliDCSSensorArray(UInt_t startTime, UInt_t endTime,
120                        TClonesArray *sensors) :
121   TNamed(),
122   fMinGraph(10),
123   fMinPoints(10),
124   fIter(10),
125   fMaxDelta(0.0),
126   fFitReq(2),
127   fValCut(-1),
128   fDiffCut(-1),
129   fStartTime (2000,1,1,0,0,0),
130   fEndTime   (2000,1,1,0,0,0),
131   fSensors(sensors)
132
133 {
134   //
135   // AliDCSSensorArray constructor for Shuttle preprocessor
136   //  (TClonesArray of AliDCSSensor objects)
137   //
138   fStartTime = TTimeStamp((time_t)startTime,0);
139   fEndTime   = TTimeStamp((time_t)endTime,0);
140 }
141
142 //_____________________________________________________________________________
143 AliDCSSensorArray::AliDCSSensorArray(const AliDCSSensorArray &c):TNamed(c),
144   fMinGraph(c.fMinGraph),
145   fMinPoints(c.fMinPoints),
146   fIter(c.fIter),
147   fMaxDelta(c.fMaxDelta),
148   fFitReq(c.fFitReq),
149   fValCut(c.fValCut),
150   fDiffCut(c.fDiffCut),
151   fStartTime (c.fStartTime),
152   fEndTime   (c.fEndTime),
153   fSensors(0)
154
155 {
156   //
157   // AliDCSSensorArray copy constructor
158   //
159
160   fSensors = (TClonesArray*)c.fSensors->Clone();
161 }
162
163 ///_____________________________________________________________________________
164 AliDCSSensorArray::~AliDCSSensorArray()
165 {
166   //
167   // AliDCSSensorArray destructor
168   //
169   fSensors->Delete();
170   delete fSensors;
171
172 }
173
174 //_____________________________________________________________________________
175 AliDCSSensorArray &AliDCSSensorArray::operator=(const AliDCSSensorArray &c)
176 {
177   //
178   // Assignment operator
179   //
180   if (this != &c) {
181      fSensors->Delete();
182      new (this) AliDCSSensorArray(c);
183      fSensors = (TClonesArray*)c.fSensors->Clone();
184   }
185   return *this;
186 }
187
188 //____________________________________________________________________________
189
190 void AliDCSSensorArray::SetGraph(TMap *map)
191 {
192   //
193   // Read graphs from DCS maps
194   //
195   Int_t nsensors = fSensors->GetEntries();
196   for ( Int_t isensor=0; isensor<nsensors; isensor++) {
197     AliDCSSensor *entry = (AliDCSSensor*)fSensors->At(isensor);
198     TString stringID = entry->GetStringID();
199     TGraph *gr = (TGraph*)map->GetValue(stringID.Data());
200     if ( gr !=0 ) {
201        entry->SetGraph((TGraph*)gr->Clone());
202     } else {
203        entry->SetGraph(0);
204     }
205   }
206 }
207 //_____________________________________________________________________________
208 void AliDCSSensorArray::MakeSplineFit(TMap *map, Bool_t keepMap)
209 {
210   //
211   // Make spline fits from DCS maps
212   //
213   Int_t nsensors = fSensors->GetEntries();
214   for ( Int_t isensor=0; isensor<nsensors; isensor++) {
215     AliDCSSensor *entry = (AliDCSSensor*)fSensors->At(isensor);
216     TString stringID = entry->GetStringID();
217     TGraph *gr = (TGraph*)map->GetValue(stringID.Data());
218     if (!gr ) {
219       entry->SetFit(0);
220       entry->SetGraph(0);
221       AliWarning(Form("sensor %s: no input graph",stringID.Data()));
222       continue;
223     }
224     UInt_t timeDiff = entry->GetEndTime() - entry->GetStartTime();
225     if ( timeDiff < kMinMapTime ) {
226       AliWarning(Form("sensor %s: map length < 60 s, DCS graph kept.",stringID.Data()));
227       entry->SetGraph((TGraph*)gr->Clone());
228     } else {
229       AliSplineFit *fit = new AliSplineFit();
230       fit->SetMinPoints(fMinGraph);
231       fit->InitKnots(gr,fMinPoints,fIter,fMaxDelta);
232       fit->SplineFit(fFitReq);
233       fit->Cleanup();
234       if (fit) {
235         entry->SetFit(fit);
236       } else {
237         AliWarning(Form("sensor %s: no fit performed, DCS graph kept.",stringID.Data()));
238         entry->SetGraph((TGraph*)gr->Clone());
239       }
240     }
241     if (keepMap) entry->SetGraph((TGraph*)gr->Clone());
242   }
243 }
244 //_____________________________________________________________________________
245 void AliDCSSensorArray::MakeSplineFitAddPoints(TMap *map)
246 {
247   //
248   // Make spline fits from DCS maps
249   //
250   Int_t nsensors = fSensors->GetEntries();
251   for ( Int_t isensor=0; isensor<nsensors; isensor++) {
252     AliDCSSensor *entry = (AliDCSSensor*)fSensors->At(isensor);
253
254   // fetch old points from existing graph
255
256     TGraph *gr = entry->GetGraph();
257     if (!gr) {
258       gr = new TGraph();
259       entry->SetGraph(gr);
260     } 
261     TString stringID = entry->GetStringID();
262
263   // fetch new points from DCS map
264   
265     TGraph *grAdd = (TGraph*)map->GetValue(stringID.Data());
266     if (!grAdd ) return;
267
268   // add new points to end of graph
269   
270     Int_t nPointsOld=gr->GetN();
271     Int_t nPointsAdd=grAdd->GetN();
272     gr->Expand(nPointsOld+nPointsAdd);
273     gr->Set(nPointsOld+nPointsAdd);
274     Double_t *addX=grAdd->GetX();
275     Double_t *addY=grAdd->GetY();
276     for (Int_t i=0;i<nPointsAdd;i++) {
277       gr->SetPoint(nPointsOld+i,addX[i],addY[i]);
278     }
279  
280    // make fit to complete graph
281    
282     AliSplineFit *fit = new AliSplineFit();
283     fit->SetMinPoints(fMinGraph);
284     fit->InitKnots(gr,fMinPoints,fIter,fMaxDelta);
285     fit->SplineFit(fFitReq);
286     fit->Cleanup();
287     if (fit) {
288       AliSplineFit *oldFit = entry->GetFit();
289       if (oldFit) delete oldFit;
290       entry->SetFit(fit);
291     } else {
292       AliWarning(Form("sensor %s: no new fit performed. If available, old fit kept.",stringID.Data()));
293     }
294   }
295 }
296
297 //_____________________________________________________________________________
298 Int_t AliDCSSensorArray::NumFits() const 
299 {
300  //
301  // Return number of sensors where a succesful fit has been made
302  //
303   Int_t nfit=0;
304   Int_t nsensors = fSensors->GetEntries();
305   for ( Int_t isensor=0; isensor<nsensors; isensor++) {
306     AliDCSSensor *entry = (AliDCSSensor*)fSensors->At(isensor);
307     if (entry->GetFit()) nfit++;
308   }    
309   return nfit;
310 }
311 //_____________________________________________________________________________
312 Double_t AliDCSSensorArray::GetValue(UInt_t timeSec, Int_t sensor) 
313 {
314   //
315   // Return sensor value at time timeSec (obtained from fitted function)
316   //  timeSec = time in seconds from start of run
317   //
318
319   AliDCSSensor *entry = (AliDCSSensor*)fSensors->At(sensor);
320   return entry->GetValue(TTimeStamp((time_t)fStartTime.GetSec()+timeSec,0));
321 }
322
323
324 //_____________________________________________________________________________
325 TMap* AliDCSSensorArray::ExtractDCS(TMap *dcsMap, Bool_t keepStart)
326 {
327  //
328  // Extract temperature graphs from DCS maps
329  //
330  TMap *values = new TMap;
331  TObjArray * valueSet;
332  //
333  // Keep global start/end times
334  //    to avoid extrapolations, the fits will only be valid from first 
335  //    measured point to last measured point. This is consistent with hardware,
336  //    as there would be a new measured point if the value changed.
337  
338  TTimeStamp startTime=fStartTime;
339  TTimeStamp endTime=fEndTime;
340  
341  Int_t nsensors = fSensors->GetEntries();
342  for ( Int_t isensor=0; isensor<nsensors; isensor++) {
343    AliDCSSensor *entry = (AliDCSSensor*)fSensors->At(isensor);
344    TString stringID = entry->GetStringID();
345    TPair *pair = (TPair*)dcsMap->FindObject(stringID.Data());
346    if ( pair ) {                            // only try to read values
347                                             // if DCS object available
348      valueSet = (TObjArray*)pair->Value();
349      TGraph *graph = MakeGraph(valueSet,keepStart);   // MakeGraph sets start/end time
350                                             // per sensor
351      values->Add(new TObjString(stringID.Data()),graph);
352      entry->SetStartTime(fStartTime);
353      entry->SetEndTime(fEndTime);
354    }
355  }
356  // Reset global start/end time 
357  //    ..... yes, I know this won't get a prize for structured programming..:-)
358
359  fStartTime=startTime;
360  fEndTime=endTime;
361  return values;
362 }
363
364
365 //_____________________________________________________________________________
366 TGraph* AliDCSSensorArray::MakeGraph(TObjArray* valueSet, Bool_t keepStart){
367   //
368   // Make graph of temperature values read from DCS map
369   //   (spline fit parameters will subsequently be obtained from this graph) 
370   //
371   Int_t nentries = valueSet->GetEntriesFast(); 
372   if ( nentries == 0 ) return 0;
373   
374   Float_t *x = new Float_t[nentries];
375   Float_t *y = new Float_t[nentries];
376   Int_t time0=0, previousTime=0;
377   TTimeStamp firstTime(0);
378   TTimeStamp lastTime(0);
379   if (keepStart) { 
380      firstTime = fStartTime;
381      time0 = firstTime.GetSec();
382   }
383   Int_t out=0;
384   Int_t skipped=0;
385   AliDCSValue *val = (AliDCSValue *)valueSet->At(0);
386   AliDCSValue::Type type = val->GetType();
387   if ( type == AliDCSValue::kInvalid || type == AliDCSValue::kBool ) return 0;
388   Float_t value;
389   for (Int_t i=0; i<nentries; i++){
390     val = (AliDCSValue *)valueSet->At(i);
391     if (!val) continue;
392     if (time0==0){
393       time0=val->GetTimeStamp();
394       firstTime= TTimeStamp((time_t)val->GetTimeStamp(),0);
395       lastTime=TTimeStamp((time_t)val->GetTimeStamp(),0);
396      }
397     switch ( type )
398     { 
399       case AliDCSValue::kFloat:
400         value = val->GetFloat();
401         break;
402       case AliDCSValue::kChar:
403         value = static_cast<Float_t>(val->GetChar());
404         break;
405       case AliDCSValue::kInt:
406         value = static_cast<Float_t>(val->GetInt());
407         break;
408       case AliDCSValue::kUInt:
409         value = static_cast<Float_t>(val->GetUInt());
410         break;
411       default:
412         continue;
413     }
414     if (fValCut>0 && TMath::Abs(value)>fValCut) continue;   // refuse values greater than cut
415     if (fDiffCut>0 ) {
416       if ( out>0 && skipped<10 && TMath::Abs(value-y[out-1])>fDiffCut) {
417         skipped++;                               // refuse values changing 
418         continue;                                // by > cut  in one time step
419       }                                          
420       skipped=0;
421     }                                         
422     if (val->GetTimeStamp()-time0>1000000) continue;
423     if (val->GetTimeStamp()-previousTime < 1 ) continue;   // refuse duplicate recordings
424     previousTime=val->GetTimeStamp();
425     lastTime=TTimeStamp((time_t)val->GetTimeStamp(),0);
426     x[out] = (val->GetTimeStamp()-time0)/kSecInHour; // give times in fractions of hours 
427     y[out] = val->GetFloat();
428     out++;    
429   }
430   if (!keepStart) fStartTime=firstTime;
431   fEndTime=lastTime;
432   TGraph * graph = new TGraph(out,x,y);
433   delete [] x;
434   delete [] y;
435   return graph;
436 }
437
438 //_____________________________________________________________________________
439 void AliDCSSensorArray::RemoveGraphDuplicates(Double_t tolerance){
440 //
441 //   Remove points with same y value as the previous measured point
442 //   (to save space for non-fitted graphs -- i.e. last measured point used)
443 //
444   Int_t nsensors = fSensors->GetEntries();
445   for ( Int_t isensor=0; isensor<nsensors; isensor++) {
446     AliDCSSensor *entry = (AliDCSSensor*)fSensors->At(isensor);
447     TGraph *graph = entry->GetGraph();
448     Double_t x=-999.,y=-999., x0=-999.,y0=-999.;
449     if (graph) {
450       Int_t npoints=graph->GetN();
451       if (npoints>1) {
452         for (Int_t i=npoints-1;i>0;i--) {
453            graph->GetPoint(i,x,y);
454            graph->GetPoint(i-1,x0,y0);
455            if ( TMath::Abs(y-y0) < TMath::Abs(tolerance*y0) ) graph->RemovePoint(i);
456          }
457       }
458     }
459    }
460 }    
461
462   
463 //_____________________________________________________________________________
464 AliDCSSensor* AliDCSSensorArray::GetSensor(Int_t IdDCS) 
465 {
466  //
467  //  Return sensor information for sensor specified by IdDCS
468  //
469  Int_t nsensors = fSensors->GetEntries();
470  for (Int_t isensor=0; isensor<nsensors; isensor++) {
471    AliDCSSensor *entry = (AliDCSSensor*)fSensors->At(isensor);
472    if (entry->GetIdDCS() == IdDCS) return entry;
473  }
474  return 0;
475 }
476 //_____________________________________________________________________________
477 AliDCSSensor* AliDCSSensorArray::GetSensor(const TString& stringID)
478 {
479  //
480  //  Return sensor information for sensor specified by stringID
481  //
482  Int_t nsensors = fSensors->GetEntries();
483  for (Int_t isensor=0; isensor<nsensors; isensor++) {
484    AliDCSSensor *entry = (AliDCSSensor*)fSensors->At(isensor);
485    if (entry->GetStringID() == stringID) return entry;
486  }
487  return 0;
488 }
489 //_____________________________________________________________________________
490 AliDCSSensor* AliDCSSensorArray::GetSensor(Double_t x, Double_t y, Double_t z)
491 {
492  //
493  //  Return sensor closest to given position
494  //
495  Int_t nsensors = fSensors->GetEntries();
496  Double_t dist2min=1e99;
497  Double_t xs,ys,zs,dist2;
498  Int_t ind=-1;
499  for (Int_t isensor=0; isensor<nsensors; isensor++) {
500    AliDCSSensor *entry = (AliDCSSensor*)fSensors->At(isensor);
501    xs = entry->GetX();
502    ys = entry->GetY();
503    zs = entry->GetZ();
504    dist2 = (x-xs)*(x-xs) + (y-ys)*(y-ys) + (z-zs)*(z-zs);
505    if (dist2 < dist2min) {
506       ind=isensor;
507       dist2min = dist2;
508    }
509  }
510  if ( ind >= 0 ) {
511     return (AliDCSSensor*)fSensors->At(ind);
512  } else {
513     return 0;
514  }
515 }
516 //_____________________________________________________________________________
517 AliDCSSensor* AliDCSSensorArray::GetSensorNum(Int_t ind)
518 {
519  //
520  //  Return sensor given by array index
521  //
522  return (AliDCSSensor*)fSensors->At(ind);
523 }
524
525 //_____________________________________________________________________________
526 Int_t AliDCSSensorArray::SetSensor(const TString& stringID,
527                           const  AliDCSSensor& sensor)
528 {
529  //
530  //  Update sensor information for sensor specified by stringID
531  //
532  Int_t nsensors = fSensors->GetEntries();
533  for (Int_t isensor=0; isensor<nsensors; isensor++) {
534    AliDCSSensor *entry = (AliDCSSensor*)fSensors->At(isensor);
535    if (entry->GetStringID() == stringID) 
536      {
537       new ((*fSensors)[isensor])AliDCSSensor(sensor);
538       return isensor;
539      }
540  }
541  return -1;
542 }
543 //_____________________________________________________________________________
544 void AliDCSSensorArray::SetSensorNum(const Int_t ind, const AliDCSSensor& sensor)
545 {
546  //
547  //  Update sensor information for sensor at index ind
548  //
549    new ((*fSensors)[ind])AliDCSSensor(sensor);
550    return;
551 }
552 //_____________________________________________________________________________
553 void AliDCSSensorArray::RemoveSensorNum(Int_t ind)
554 {
555  //
556  //  Return sensor given by array index
557  //
558
559   delete fSensors->RemoveAt(ind);
560   fSensors->Compress();
561 }
562 //_____________________________________________________________________________
563 void AliDCSSensorArray::RemoveSensor(Int_t IdDCS)
564 {
565  //
566  //  Deletes Sensor by given IdDCS
567  //
568
569   Int_t nsensors = fSensors->GetEntries();
570   for (Int_t isensor=0; isensor<nsensors; isensor++) { // loop over sensors
571     AliDCSSensor *entry = (AliDCSSensor*)fSensors->At(isensor);
572     if (entry->GetIdDCS()==IdDCS) {
573       delete fSensors->RemoveAt(isensor);
574       break;
575     }
576   }
577   fSensors->Compress();
578 }
579 //_____________________________________________________________________________
580 TArrayI AliDCSSensorArray::OutsideThreshold(Double_t threshold, UInt_t timeSec, Bool_t below) const
581 {
582  //
583  // Return sensors with values outside threshold at time defined by second
584  // parameter
585  // By default sensors with values below threshold are listed, if third
586  // parameter is set to kFALSE sensors with values above threshold are listed
587  //
588   Int_t nsensors = fSensors->GetEntries();
589   TArrayI array(nsensors);
590   Int_t outside=0;
591   for (Int_t isensor=0; isensor<nsensors; isensor++) { // loop over sensors
592     AliDCSSensor *entry = (AliDCSSensor*)fSensors->At(isensor);
593     Double_t val=entry->GetValue(timeSec);
594     if (below) {
595       if (val<threshold) array[outside++] = entry->GetIdDCS();
596     } else {
597       if (val>threshold) array[outside++] = entry->GetIdDCS();
598     }    
599   }
600   array.Set(outside);
601   return array;
602 }
603  
604 //_____________________________________________________________________________
605 Int_t AliDCSSensorArray::GetFirstIdDCS() const
606 {
607  //
608  //  Return DCS Id of first sensor
609  //
610  if ( fSensors != 0 ) {
611     return ((AliDCSSensor*)fSensors->At(0))->GetIdDCS();
612  } else {
613     return 0;
614  }
615 }
616
617 //_____________________________________________________________________________
618 Int_t AliDCSSensorArray::GetLastIdDCS() const 
619 {
620  //
621  //  Return DCS Id of last sensor
622  //
623  if ( fSensors != 0 ) {
624     Int_t last = fSensors->GetEntries();
625     return ((AliDCSSensor*)fSensors->At(last-1))->GetIdDCS();
626  } else {
627     return 0;
628  }
629 }
630 //_____________________________________________________________________________
631 void AliDCSSensorArray::ClearGraph()
632 {
633   //
634   // Delete DCS graphs from all sensors in array
635   //
636    
637    Int_t nsensors = fSensors->GetEntries();
638    for ( Int_t isensor=0; isensor<nsensors; isensor++) {
639      AliDCSSensor *sensor = (AliDCSSensor*)fSensors->At(isensor);
640      TGraph *gr = sensor->GetGraph();
641      if ( gr != 0 ) {
642        delete gr;
643        gr = 0;
644      }
645      sensor->SetGraph(0);
646    }
647 }
648 //_____________________________________________________________________________
649 void AliDCSSensorArray::ClearFit()
650 {
651   //
652   // Delete spline fits from all sensors in array
653   //
654
655    Int_t nsensors = fSensors->GetEntries();
656    for ( Int_t isensor=0; isensor<nsensors; isensor++) {
657      AliDCSSensor *sensor = (AliDCSSensor*)fSensors->At(isensor);
658      AliSplineFit *fit = sensor->GetFit();
659      if ( fit != 0 ) {
660        delete fit;
661        fit = 0;
662      }
663      sensor->SetFit(0);
664    }
665 }
666 //_____________________________________________________________________________
667 void AliDCSSensorArray::AddSensors(AliDCSSensorArray *newSensors)
668 {
669   //
670   // add sensors from two sensor arrays
671   //
672   
673   Int_t numNew = newSensors->NumSensors();
674   Int_t numOld = fSensors->GetEntries();
675   fSensors->Expand(numOld+numNew);
676   for (Int_t i=0;i<numNew;i++) {
677     AliDCSSensor *sens = newSensors->GetSensorNum(i);
678     new ((*fSensors)[numOld+i]) AliDCSSensor(*sens);
679   }
680 }  
681