]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONPadStatusMaker.cxx
First version of the occupancy DA, which should have been committed with a previous...
[u/mrichter/AliRoot.git] / MUON / AliMUONPadStatusMaker.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 // $Id$
17
18 //-----------------------------------------------------------------------------
19 /// \class AliMUONPadStatusMaker
20 ///
21 /// Make a 2DStore of pad statuses, using different sources of information,
22 /// like pedestal values, gain values, and HV values.
23 ///
24 /// \author Laurent Aphecetche
25 //-----------------------------------------------------------------------------
26
27 #include "AliMUONPadStatusMaker.h"
28
29 #include "AliMUON2DMap.h"
30 #include "AliMUON2DStoreValidator.h"
31 #include "AliMUONCalibParamNI.h"
32 #include "AliMUONCalibrationData.h"
33 #include "AliMUONStringIntMap.h"
34 #include "AliMUONVCalibParam.h"
35 #include "AliMUONTrackerData.h"
36
37 #include "AliMpArea.h"
38 #include "AliMpArrayI.h"
39 #include "AliMpConstants.h"
40 #include "AliMpDDLStore.h"
41 #include "AliMpDEManager.h"
42 #include "AliMpDetElement.h"
43 #include "AliMpDCSNamer.h"
44 #include "AliMpManuUID.h"
45
46 #include "AliCDBEntry.h"
47 #include "AliCDBManager.h"
48 #include "AliCodeTimer.h"
49 #include "AliDCSValue.h"
50 #include "AliLog.h"
51
52 #include <Riostream.h>
53 #include <TArrayI.h>
54 #include <TExMap.h>
55 #include <TFile.h>
56 #include <TKey.h>
57 #include <TMap.h>
58 #include <TROOT.h>
59 #include <TString.h>
60 #include <TSystem.h>
61
62 /// \cond CLASSIMP
63 ClassImp(AliMUONPadStatusMaker)
64 /// \endcond
65
66 //_____________________________________________________________________________
67 AliMUONPadStatusMaker::AliMUONPadStatusMaker(const AliMUONCalibrationData& calibData)
68 : fkCalibrationData(calibData),
69 fGainA1Limits(0,1E30),
70 fGainA2Limits(-1E-30,1E30),
71 fGainThresLimits(0,4095),
72 fHVSt12Limits(0,5000),
73 fHVSt345Limits(0,5000),
74 fPedMeanLimits(0,4095),
75 fPedSigmaLimits(0,4095),
76 fManuOccupancyLimits(0,1.0),
77 fBusPatchOccupancyLimits(0,1.0),
78 fDEOccupancyLimits(0,1.0),
79 fStatus(new AliMUON2DMap(true)),
80 fHV(new TExMap),
81 fPedestals(calibData.Pedestals()),
82 fGains(calibData.Gains()),
83 fTrackerData(0x0)
84 {
85   /// ctor
86   AliDebug(1,Form("ped store %s gain store %s",
87                   fPedestals->ClassName(),
88                   fGains->ClassName()));
89   
90   if ( calibData.OccupancyMap() )
91   {
92     AliInfo("Will use occupancy map to cut, if so required in AliMUONRecoParam");    
93     /// create a tracker data from the occupancy map
94     fTrackerData = new AliMUONTrackerData("OCC","OCC",*(calibData.OccupancyMap()));
95   }    
96 }
97
98 //_____________________________________________________________________________
99 AliMUONPadStatusMaker::~AliMUONPadStatusMaker()
100 {
101   /// dtor.
102   delete fStatus;
103   delete fHV;
104   delete fTrackerData;
105 }
106
107 //_____________________________________________________________________________
108 TString
109 AliMUONPadStatusMaker::AsString(Int_t status)
110 {
111   /// return a human readable version of the integer status
112   
113   Int_t pedStatus;
114   Int_t gainStatus;
115   Int_t hvStatus;
116   Int_t occStatus;
117   
118   DecodeStatus(status,pedStatus,hvStatus,gainStatus,occStatus);
119   
120   TString s;
121   
122   if ( pedStatus & kPedMeanZero ) s += "& Ped Mean is Zero ";
123   if ( pedStatus & kPedMeanTooLow ) s += "& Ped Mean Too Low ";
124   if ( pedStatus & kPedMeanTooHigh ) s += "& Ped Mean Too High ";
125   if ( pedStatus & kPedSigmaTooLow ) s += "& Ped Sigma Too Low ";
126   if ( pedStatus & kPedSigmaTooHigh ) s += "& Ped Sigma Too High ";
127   if ( pedStatus & kPedMissing ) s += "& Ped is missing ";
128   
129         if ( gainStatus & kGainA1TooLow ) s+="& Gain A1 is Too Low ";
130         if ( gainStatus & kGainA1TooHigh ) s+="& Gain A1 is Too High ";
131         if ( gainStatus & kGainA2TooLow ) s+="& Gain A2 is Too Low ";
132         if ( gainStatus & kGainA2TooHigh ) s+="& Gain A2 is Too High ";
133         if ( gainStatus & kGainThresTooLow ) s+="& Gain Thres is Too Low ";
134         if ( gainStatus & kGainThresTooHigh ) s+="& Gain Thres is Too High ";
135         if ( gainStatus & kGainMissing ) s+="& Gain is missing ";
136         
137         if ( hvStatus & kHVError ) s+="& HV is on error ";
138         if ( hvStatus & kHVTooLow ) s+="& HV is Too Low ";
139         if ( hvStatus & kHVTooHigh ) s+="& HV is Too High ";
140         if ( hvStatus & kHVChannelOFF ) s+="& HV has channel OFF ";
141         if ( hvStatus & kHVSwitchOFF ) s+="& HV has switch OFF ";
142         if ( hvStatus & kHVMissing ) s+="& HV is missing ";
143
144   if ( occStatus & kManuOccupancyTooHigh ) s+="& manu occupancy too high ";
145   if ( occStatus & kManuOccupancyTooLow ) s+="& manu occupancy too low ";
146   if ( occStatus & kBusPatchOccupancyTooHigh ) s+="& bus patch occupancy too high ";
147   if ( occStatus & kBusPatchOccupancyTooLow ) s+="& bus patch occupancy too low ";
148   if ( occStatus & kDEOccupancyTooHigh ) s+="& DE occupancy too high ";
149   if ( occStatus & kDEOccupancyTooLow ) s+="& DE occupancy too low ";
150   
151   if ( s[0] == '&' ) s[0] = ' ';
152   
153   return s;
154 }
155
156 //_____________________________________________________________________________
157 TString
158 AliMUONPadStatusMaker::AsCondition(Int_t mask)
159 {
160   /// return a human readable version of the mask's equivalent condition
161   
162   TString s(AsString(mask));
163   
164   s.ReplaceAll("&","|");
165   
166   return s;
167 }
168
169 //_____________________________________________________________________________
170 Int_t
171 AliMUONPadStatusMaker::BuildStatus(Int_t pedStatus, 
172                                    Int_t hvStatus, 
173                                    Int_t gainStatus,
174                                    Int_t occStatus)
175 {
176   /// Build a complete status from specific parts (ped,hv,gain)
177   
178   return ( hvStatus & 0xFF ) | ( ( pedStatus & 0xFF ) << 8 ) | 
179   ( ( gainStatus & 0xFF ) << 16 ) |
180   ( ( occStatus & 0xFF ) << 24 ) ;
181 }
182
183 //_____________________________________________________________________________
184 void
185 AliMUONPadStatusMaker::DecodeStatus(Int_t status, 
186                                     Int_t& pedStatus, 
187                                     Int_t& hvStatus, 
188                                     Int_t& gainStatus,
189                                     Int_t& occStatus)
190 {
191   /// Decode complete status into specific parts (ped,hv,gain)
192   
193   occStatus = ( status & 0xFF000000 ) >> 24;
194   gainStatus = ( status & 0xFF0000 ) >> 16;
195   pedStatus = ( status & 0xFF00 ) >> 8;
196   hvStatus = (status & 0xFF);
197 }
198
199 //_____________________________________________________________________________
200 Bool_t 
201 AliMUONPadStatusMaker::HVSt12Status(Int_t detElemId, Int_t sector,
202                                     Bool_t& hvChannelTooLow,
203                                     Bool_t& hvChannelTooHigh,
204                                     Bool_t& hvChannelON) const
205 {
206   /// Get HV status for one HV sector of St12
207   
208   /// For a given PCB in a given DE, get the HV status (both the channel
209   /// and the switch).
210   /// Returns false if hv switch changed during the run.
211   
212   AliCodeTimerAuto("")
213   
214   Bool_t error = kFALSE;
215   hvChannelTooLow = kFALSE;
216   hvChannelTooHigh = kFALSE;
217   hvChannelON = kTRUE;
218
219   AliMpDCSNamer hvNamer("TRACKER");
220   
221   TString hvChannel(hvNamer.DCSChannelName(detElemId,sector));
222   
223   TMap* hvMap = fkCalibrationData.HV();
224   TPair* hvPair = static_cast<TPair*>(hvMap->FindObject(hvChannel.Data()));
225   if (!hvPair)
226   {
227     AliError(Form("Did not find expected alias (%s) for DE %d",
228                   hvChannel.Data(),detElemId));  
229     error = kTRUE;
230   }
231   else
232   {
233     TObjArray* values = static_cast<TObjArray*>(hvPair->Value());
234     if (!values)
235     {
236       AliError(Form("Could not get values for alias %s",hvChannel.Data()));
237       error = kTRUE;
238     }
239     else
240     {
241       // find out min and max value, and makes a cut
242       Float_t hvMin(1E9);
243       Float_t hvMax(0);
244       TIter next(values);
245       AliDCSValue* val;
246       
247       while ( ( val = static_cast<AliDCSValue*>(next()) ) )
248       {
249         Float_t hv = val->GetFloat();
250         hvMin = TMath::Min(hv,hvMin);
251         hvMax = TMath::Max(hv,hvMax);
252       }
253       
254       float lowThreshold = fHVSt12Limits.X();
255       float highThreshold = fHVSt12Limits.Y();
256             
257       if ( hvMin < lowThreshold ) hvChannelTooLow = kTRUE;
258       if ( hvMax > highThreshold ) hvChannelTooHigh = kTRUE;
259       if ( hvMin < 1 ) hvChannelON = kFALSE;
260     }
261   }
262   
263   return error;
264 }
265
266 //_____________________________________________________________________________
267 Bool_t 
268 AliMUONPadStatusMaker::HVSt345Status(Int_t detElemId, Int_t pcbIndex,
269                                      Bool_t& hvChannelTooLow,
270                                      Bool_t& hvChannelTooHigh,
271                                      Bool_t& hvChannelON,
272                                      Bool_t& hvSwitchON) const
273 {
274   /// For a given PCB in a given DE, get the HV status (both the channel
275   /// and the switch).
276   /// Returns false if something goes wrong (in particular if 
277   /// hv switch changed during the run).
278   
279   AliCodeTimerAuto("")
280   
281   Bool_t error = kFALSE;
282   hvChannelTooLow = kFALSE;
283   hvChannelTooHigh = kFALSE;
284   hvSwitchON = kTRUE;
285   hvChannelON = kTRUE;
286   
287   AliMpDCSNamer hvNamer("TRACKER");
288   
289   TString hvChannel(hvNamer.DCSChannelName(detElemId));
290   
291   TMap* hvMap = fkCalibrationData.HV();
292   
293   TPair* hvPair = static_cast<TPair*>(hvMap->FindObject(hvChannel.Data()));
294   if (!hvPair)
295   {
296     AliError(Form("Did not find expected alias (%s) for DE %d",
297                   hvChannel.Data(),detElemId));  
298     error = kTRUE;
299   }
300   else
301   {
302     TObjArray* values = static_cast<TObjArray*>(hvPair->Value());
303     if (!values)
304     {
305       AliError(Form("Could not get values for alias %s",hvChannel.Data()));
306       error = kTRUE;
307     }
308     else
309     {
310       // find out min and max value, and makes a cut
311       Float_t hvMin(1E9);
312       Float_t hvMax(0);
313       TIter next(values);
314       AliDCSValue* val;
315       
316       while ( ( val = static_cast<AliDCSValue*>(next()) ) )
317       {
318         Float_t hv = val->GetFloat();
319         hvMin = TMath::Min(hv,hvMin);
320         hvMax = TMath::Max(hv,hvMax);
321       }
322
323       float lowThreshold = fHVSt345Limits.X();
324       float highThreshold = fHVSt345Limits.Y();
325
326       if ( hvMin < lowThreshold ) hvChannelTooLow = kTRUE;
327       else if ( hvMax > highThreshold ) hvChannelTooHigh = kTRUE;
328       if ( hvMin < 1 ) hvChannelON = kFALSE;
329     }
330   }
331   
332   TString hvSwitch(hvNamer.DCSSwitchName(detElemId,pcbIndex));
333   TPair* switchPair = static_cast<TPair*>(hvMap->FindObject(hvSwitch.Data()));
334   if (!switchPair)
335   {
336     AliError(Form("Did not find expected alias (%s) for DE %d PCB %d",
337                   hvSwitch.Data(),detElemId,pcbIndex));
338     error = kTRUE;
339   }
340   else
341   {
342     TObjArray* values = static_cast<TObjArray*>(switchPair->Value());
343     if (!values)
344     {    
345       AliError(Form("Could not get values for alias %s",hvSwitch.Data()));
346       error = kTRUE;
347     }
348     else
349     {
350       // we'll count the number of ON/OFF for this pad, to insure
351       // consistency (i.e. if status changed during the run, we should
352       // at least notify this fact ;-) and hope it's not the norm)
353       Int_t nTrue(0);
354       Int_t nFalse(0);
355       TIter next(values);
356       AliDCSValue* val;
357       
358       while ( ( val = static_cast<AliDCSValue*>(next()) ) )
359       {
360         if ( val->GetBool() )
361         {
362           ++nTrue;
363         }
364         else
365         {
366           ++nFalse;
367         }
368       }
369       
370       if ( (nTrue>0 && nFalse>0) )
371       {
372         AliWarning(Form("Status of HV Switch %s changed during this run nTrue=%d nFalse=%d! Will consider it OFF",
373                         hvSwitch.Data(),nTrue,nFalse));
374         error = kTRUE;
375       }
376       
377       if ( nFalse ) hvSwitchON = kFALSE;
378     }
379   }
380   return error;
381 }
382
383 //_____________________________________________________________________________
384 Int_t
385 AliMUONPadStatusMaker::HVStatus(Int_t detElemId, Int_t manuId) const
386 {
387   /// Get HV status of one manu
388   
389   AliCodeTimerAuto("")
390   
391   if ( !fkCalibrationData.HV() ) return kMissing;
392
393   Long_t lint = fHV->GetValue(AliMpManuUID::BuildUniqueID(detElemId,manuId));
394   
395   if ( lint ) 
396   {
397     return (Int_t)(lint - 1);
398   }
399
400   Int_t status(0);
401   
402   AliMpDCSNamer hvNamer("TRACKER");
403   
404   switch ( AliMpDEManager::GetStationType(detElemId) )
405   {
406     case AliMp::kStation12:
407     {
408       int sector = hvNamer.ManuId2Sector(detElemId,manuId);
409       if ( sector >= 0 ) 
410       {
411         Bool_t hvChannelTooLow, hvChannelTooHigh, hvChannelON;
412         Bool_t error = HVSt12Status(detElemId,sector,
413                                     hvChannelTooLow,
414                                     hvChannelTooHigh,
415                                     hvChannelON);
416         if ( error ) status |= kHVError;
417         if ( hvChannelTooLow ) status |= kHVTooLow;
418         if ( hvChannelTooHigh ) status |= kHVTooHigh; 
419         if ( !hvChannelON ) status |= kHVChannelOFF;
420         // assign this status to all the other manus handled by the same HV channel
421         SetHVStatus(detElemId,sector,status);
422       }
423     }
424       break;
425     case AliMp::kStation345:
426     {
427       int pcbIndex = hvNamer.ManuId2PCBIndex(detElemId,manuId);
428       if ( pcbIndex >= 0 ) 
429       {
430         Bool_t hvChannelTooLow, hvChannelTooHigh, hvChannelON,hvSwitchON;
431         Bool_t error = HVSt345Status(detElemId,pcbIndex,
432                                      hvChannelTooLow,hvChannelTooHigh,
433                                      hvChannelON,hvSwitchON);
434         if ( error ) status |= kHVError;
435         if ( hvChannelTooLow ) status |= kHVTooLow;
436         if ( hvChannelTooHigh ) status |= kHVTooHigh; 
437         if ( !hvSwitchON ) status |= kHVSwitchOFF; 
438         if ( !hvChannelON) status |= kHVChannelOFF;
439         // assign this status to all the other manus handled by the same HV channel
440         SetHVStatus(detElemId,pcbIndex,status);
441       }
442     }
443       break;
444     default:
445       break;
446   }
447   
448   return status;
449 }
450
451 //_____________________________________________________________________________
452 AliMUONVCalibParam* 
453 AliMUONPadStatusMaker::Neighbours(Int_t detElemId, Int_t manuId) const
454 {
455   /// Get the neighbours parameters for a given manu
456   AliMUONVStore* neighbourStore = fkCalibrationData.Neighbours();
457   return static_cast<AliMUONVCalibParam*>(neighbourStore->FindObject(detElemId,manuId));
458 }
459
460 //_____________________________________________________________________________
461 AliMUONVStore* 
462 AliMUONPadStatusMaker::NeighboursStore() const
463 {
464   /// Return the store containing all the neighbours
465   return fkCalibrationData.Neighbours();
466 }
467
468 //_____________________________________________________________________________
469 AliMUONVCalibParam*
470 AliMUONPadStatusMaker::ComputeStatus(Int_t detElemId, Int_t manuId) const
471 {
472   /// Compute the status of a given manu, using all available information,
473   /// i.e. pedestals, gains, and HV
474   
475   AliMUONVCalibParam* param = new AliMUONCalibParamNI(1,AliMpConstants::ManuNofChannels(),detElemId,manuId,-1);
476   fStatus->Add(param);
477
478   AliMUONVCalibParam* pedestals = static_cast<AliMUONVCalibParam*>(fPedestals->FindObject(detElemId,manuId));
479
480   AliMUONVCalibParam* gains = static_cast<AliMUONVCalibParam*>(fGains->FindObject(detElemId,manuId));
481   
482   Int_t hvStatus = HVStatus(detElemId,manuId);
483
484   Int_t occStatus = OccupancyStatus(detElemId,manuId);
485   
486   for ( Int_t manuChannel = 0; manuChannel < param->Size(); ++manuChannel )
487   {
488     Int_t pedStatus(0);
489     
490     if (pedestals) 
491     {
492       Float_t pedMean = pedestals->ValueAsFloatFast(manuChannel,0);
493       Float_t pedSigma = pedestals->ValueAsFloatFast(manuChannel,1);
494       if ( pedMean < fPedMeanLimits.X() ) pedStatus |= kPedMeanTooLow;
495       else if ( pedMean > fPedMeanLimits.Y() ) pedStatus |= kPedMeanTooHigh;
496       if ( pedSigma < fPedSigmaLimits.X() ) pedStatus |= kPedSigmaTooLow;
497       else if ( pedSigma > fPedSigmaLimits.Y() ) pedStatus |= kPedSigmaTooHigh;
498       if ( pedMean == 0 ) pedStatus |= kPedMeanZero;
499     }
500     else
501     {
502       pedStatus = kPedMissing;
503     }
504     
505     Int_t gainStatus(0);
506   
507     if ( gains ) 
508     {
509       Float_t a0 = gains->ValueAsFloatFast(manuChannel,0);
510       Float_t a1 = gains->ValueAsFloatFast(manuChannel,1);
511       Float_t thres = gains->ValueAsFloatFast(manuChannel,2);
512   
513       if ( a0 < fGainA1Limits.X() ) gainStatus |= kGainA1TooLow;
514       else if ( a0 > fGainA1Limits.Y() ) gainStatus |= kGainA1TooHigh;
515       if ( a1 < fGainA2Limits.X() ) gainStatus |= kGainA2TooLow;
516       else if ( a1 > fGainA2Limits.Y() ) gainStatus |= kGainA2TooHigh;
517       if ( thres < fGainThresLimits.X() ) gainStatus |= kGainThresTooLow;
518       else if ( thres > fGainThresLimits.Y() ) gainStatus |= kGainThresTooHigh;
519     }
520     else
521     {
522       gainStatus = kGainMissing;
523     }
524     
525     Int_t status = BuildStatus(pedStatus,hvStatus,gainStatus,occStatus);
526       
527     param->SetValueAsIntFast(manuChannel,0,status);
528   }
529   
530   return param;
531 }
532
533 //_____________________________________________________________________________
534 Int_t 
535 AliMUONPadStatusMaker::OccupancyStatus(Int_t detElemId, Int_t manuId) const
536 {
537   /// Get the "other" status for a given manu
538  
539   Int_t rv(0);
540   
541   if ( fTrackerData ) 
542   {
543     const Int_t occIndex = 2;
544     
545     Double_t occ = fTrackerData->DetectionElement(detElemId,occIndex);
546     
547     if ( occ <= fDEOccupancyLimits.X() )
548     {
549       rv |= kDEOccupancyTooLow;
550     } 
551     else if ( occ > fDEOccupancyLimits.Y() )
552     {
553       rv |= kDEOccupancyTooHigh;
554     }
555     
556     Int_t busPatchId = AliMpDDLStore::Instance()->GetBusPatchId(detElemId,manuId);
557     
558     occ = fTrackerData->BusPatch(busPatchId,occIndex);
559
560     if ( occ <= fBusPatchOccupancyLimits.X() )
561     {
562       rv |= kBusPatchOccupancyTooLow;
563     } 
564     else if ( occ > fBusPatchOccupancyLimits.Y() )
565     {
566       rv |= kBusPatchOccupancyTooHigh;
567     }
568     
569     occ = fTrackerData->Manu(detElemId,manuId,occIndex);
570     
571     if ( occ <= fManuOccupancyLimits.X() )
572     {
573       rv |= kManuOccupancyTooLow;
574     } 
575     else if ( occ > fManuOccupancyLimits.Y() )
576     {
577       rv |= kManuOccupancyTooHigh;
578     }
579   }
580   return rv;
581 }
582
583 //_____________________________________________________________________________
584 AliMUONVCalibParam* 
585 AliMUONPadStatusMaker::PadStatus(Int_t detElemId, Int_t manuId) const
586 {
587   /// Get the status container for a given manu
588   
589   AliMUONVCalibParam* param = static_cast<AliMUONVCalibParam*>(fStatus->FindObject(detElemId,manuId));
590   if (!param)
591   {
592     // not already there, so compute it now
593     AliCodeTimerAuto("ComputeStatus");
594     param = ComputeStatus(detElemId,manuId);
595   }
596   return param;
597 }
598
599 //_____________________________________________________________________________
600 Int_t 
601 AliMUONPadStatusMaker::PadStatus(Int_t detElemId, Int_t manuId, Int_t manuChannel) const
602 {
603   /// Get the status for a given channel
604   
605   AliMUONVCalibParam* param = static_cast<AliMUONVCalibParam*>(fStatus->FindObject(detElemId,manuId));
606   if (!param)
607   {
608     // not already there, so compute it now
609     param = ComputeStatus(detElemId,manuId);
610   }
611   return param->ValueAsInt(manuChannel,0);
612 }
613
614 //_____________________________________________________________________________
615 void
616 AliMUONPadStatusMaker::SetHVStatus(Int_t detElemId, Int_t index, Int_t status) const
617 {
618   /// Assign status to all manus in a given HV "zone" (defined by index, meaning
619   /// is different thing from St12 and St345)
620   
621   AliCodeTimerAuto("")
622   
623   AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(detElemId);
624   
625   const AliMpArrayI* manus = de->ManusForHV(index);
626   
627   for ( Int_t i = 0; i < manus->GetSize(); ++ i ) 
628   {
629     Int_t manuId = manus->GetValue(i);
630     fHV->Add(AliMpManuUID::BuildUniqueID(detElemId,manuId),status + 1);
631   }
632 }