]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWGLF/FORWARD/analysis2/AliCorrectionManagerBase.cxx
Fixes for Coverity issues: 21876, 21795, 21786, 21782, 21781
[u/mrichter/AliRoot.git] / PWGLF / FORWARD / analysis2 / AliCorrectionManagerBase.cxx
CommitLineData
8449e3e0 1#include "AliCorrectionManagerBase.h"
2#include "AliOADBForward.h"
3#include "AliForwardUtil.h"
4#include <AliLog.h>
5#include <TMath.h>
6#include <iostream>
7#include <TROOT.h>
8#include <TSystem.h>
9#include <TBrowser.h>
10#include <TParameter.h>
11#include <TFileMerger.h>
12
13//____________________________________________________________________
14AliCorrectionManagerBase::AliCorrectionManagerBase()
15 : fCorrections(),
16 fIsInit(false),
bfab35d9 17 fRun(kIgnoreValue),
18 fSys(kIgnoreValue),
19 fSNN(kIgnoreValue),
20 fField(kIgnoreField),
8449e3e0 21 fMC(false),
22 fSatellite(false),
23 fDB(0),
24 fDebug(false)
25{
26}
27
28//____________________________________________________________________
29AliCorrectionManagerBase::AliCorrectionManagerBase(Bool_t)
30 : fCorrections(16),
31 fIsInit(false),
bfab35d9 32 fRun(kIgnoreValue),
33 fSys(kIgnoreValue),
34 fSNN(kIgnoreValue),
35 fField(kIgnoreField),
8449e3e0 36 fMC(false),
37 fSatellite(false),
38 fDB(0),
39 fDebug(false)
40{
41 fCorrections.SetOwner(false);
42 fCorrections.SetName("corrections");
43}
44//____________________________________________________________________
45AliCorrectionManagerBase::AliCorrectionManagerBase(const
46 AliCorrectionManagerBase& o)
47 : TObject(o),
48 fCorrections(),
49 fIsInit(o.fIsInit),
50 fRun(o.fRun),
51 fSys(o.fSys),
52 fSNN(o.fSNN),
53 fField(o.fField),
54 fMC(o.fMC),
55 fSatellite(o.fSatellite),
56 fDB(o.fDB),
57 fDebug(o.fDebug)
58{
59 fCorrections.SetOwner(false);
60 Int_t n = o.fCorrections.GetEntriesFast();
61 for (Int_t i = 0; i < n; i++) {
62 fCorrections.AddAt(o.fCorrections.At(i), i);
63 }
64}
65//____________________________________________________________________
66AliCorrectionManagerBase&
67AliCorrectionManagerBase::operator=(const AliCorrectionManagerBase& o)
68{
69 if (&o == this) return *this;
70
71 fIsInit = o.fIsInit;
72 fRun = o.fRun;
73 fSys = o.fSys;
74 fSNN = o.fSNN;
75 fField = o.fField;
76 fMC = o.fMC;
77 fSatellite = o.fSatellite;
78 fDB = o.fDB;
79 fDebug = o.fDebug;
80
81 fCorrections.Clear();
82 Int_t n = o.fCorrections.GetEntriesFast();
83 for (Int_t i = 0; i < n; i++) {
84 fCorrections.AddAt(o.fCorrections.At(i), i);
85 }
86 return *this;
87}
88
89//____________________________________________________________________
90AliCorrectionManagerBase::~AliCorrectionManagerBase()
91{
92 // fCorrections.Delete();
93}
94
95//____________________________________________________________________
96void
97AliCorrectionManagerBase::Print(Option_t* option) const
98{
99 char ind[gROOT->GetDirLevel()+1];
100 for (Int_t i = 0; i < gROOT->GetDirLevel(); i++) ind[i] = ' ';
101 ind[gROOT->GetDirLevel()] = '\0';
102
103 std::cout << ind << GetName() << ":\n"
104 << ind << " Initialised: "
105 << (fIsInit ? "yes" : "no") << std::endl;
106 if (fIsInit)
107 std::cout << ind << " Run number: " << fRun << "\n"
108 << ind << " Collision system: "
109 << AliForwardUtil::CollisionSystemString(fSys) << "\n"
110 << ind << " Sqrt(s_NN): "
111 << AliForwardUtil::CenterOfMassEnergyString(fSNN) << "\n"
112 << ind << " Magnetic field: "
113 << AliForwardUtil::MagneticFieldString(fField) << "\n"
114 << ind << " For simulations: " << (fMC ? "yes" : "no") << "\n"
115 << ind << " For satellites: "
116 << (fSatellite ? "yes" : "no") << std::endl;
117
118 TString opt(option);
119 opt.ToUpper();
120 if (!opt.Contains("R")) return;
121
122 gROOT->IncreaseDirLevel();
123 Int_t n = fCorrections.GetEntriesFast();
124 for (Int_t id = 0; id < n; id++) {
125 const Correction* c = GetCorrection(id);
126 c->Print(option);
127 }
128 gROOT->DecreaseDirLevel();
129
130}
131
132//____________________________________________________________________
133void
134AliCorrectionManagerBase::Browse(TBrowser* b)
135{
136 b->Add(&fCorrections);
137}
138
139//____________________________________________________________________
140void
141AliCorrectionManagerBase::SetPrefix(const TString& prefix)
142{
143 Int_t n = fCorrections.GetEntriesFast();
144 for (Int_t id = 0; id < n; id++) {
145 Correction* c = GetCorrection(id);
146 const char* old = c->GetTitle();
147 TString oldf(gSystem->BaseName(old));
148 c->SetFile(gSystem->ConcatFileName(prefix, oldf));
149 }
150}
151
152//____________________________________________________________________
153Bool_t
154AliCorrectionManagerBase::Store(TObject* o,
155 ULong_t runNo,
156 UShort_t sys,
157 UShort_t sNN,
158 Short_t field,
159 Bool_t mc,
160 Bool_t sat,
161 const char* file,
162 const char* meth) const
163{
164 Bool_t ret = false;
165 Int_t n = fCorrections.GetEntriesFast();
166 for (Int_t id = 0; id < n; id++) {
167 const Correction* c = GetCorrection(id);
168 if (!o->IsA()->InheritsFrom(c->fCls)) continue;
169
170 ret = c->StoreIt(fDB, o, runNo, sys, sNN, field, mc, sat, file, meth);
171 break;
172 }
173 return ret;
174}
175
176//____________________________________________________________________
177Bool_t
178AliCorrectionManagerBase::Append(const TString& addition,
179 const TString& destination) const
180{
181 if (addition.IsNull()) {
182 AliWarning("No addition specified");
183 return false;
184 }
185 if (destination.IsNull()) {
186 AliWarning("No destination storage specified");
187 return false;
188 }
189 TFileMerger merger;
190 merger.SetPrintLevel(1);
191 merger.OutputFile(destination, "UPDATE");
192 merger.AddFile(addition);
193 if (!merger.PartialMerge()) {
194 AliInfoF("Failed to merge %s with %s",
195 addition.Data(), destination.Data());
196 return false;
197 }
198 if (destination.BeginsWith("$OADB_PATH") ||
199 destination.BeginsWith("$ALICE_ROOT"))
200 AliInfoF("Now commit %s to subversion", destination.Data());
201 return true;
202}
203
204//____________________________________________________________________
205void
206AliCorrectionManagerBase::RegisterCorrection(Int_t id, Correction* corr)
207{
208 fCorrections.AddAtAndExpand(corr, id);
209}
210
211//____________________________________________________________________
212void
213AliCorrectionManagerBase::RegisterCorrection(Int_t id,
214 const TString& tableName,
215 const TString& fileName,
216 TClass* cls,
217 UShort_t fields,
218 Bool_t enabled)
219{
220 RegisterCorrection(id,new Correction(tableName,fileName,cls,fields,enabled));
221}
222
223//____________________________________________________________________
224AliCorrectionManagerBase::Correction*
225AliCorrectionManagerBase::GetCorrection(Int_t id)
226{
227 if (id < 0 || id > fCorrections.GetEntriesFast()) return 0;
228 return static_cast<Correction*>(fCorrections.At(id));
229}
230
231//____________________________________________________________________
232const AliCorrectionManagerBase::Correction*
233AliCorrectionManagerBase::GetCorrection(Int_t id) const
234{
235 if (id < 0 || id > fCorrections.GetEntriesFast()) return 0;
236 return static_cast<Correction*>(fCorrections.At(id));
237}
238
239//____________________________________________________________________
240void
241AliCorrectionManagerBase::SetCorrectionFile(Int_t id, const TString& fileName)
242{
243 Correction* c = GetCorrection(id);
244 if (!c) return;
245 c->SetFile(fileName);
246}
247
248//____________________________________________________________________
249Int_t
250AliCorrectionManagerBase::GetId(const TString& what) const
251{
252 Int_t n = fCorrections.GetEntriesFast();
253 for (Int_t id = 0; id < n; id++) {
254 const Correction* c = GetCorrection(id);
255 if (what.EqualTo(c->GetName(), TString::kIgnoreCase)) return id;
256 }
257 return -1;
258}
259
260//____________________________________________________________________
261void
262AliCorrectionManagerBase::EnableCorrection(Int_t id, Bool_t enable)
263{
264 Correction* c = GetCorrection(id);
265 if (!c) {
266 AliWarningF("Cannot enable non-existing correction at %d", id);
267 return;
268 }
269 c->fEnabled = enable;
270}
271
272//____________________________________________________________________
273Int_t
274AliCorrectionManagerBase::GetId(const TObject* obj) const
275{
276 Int_t n = fCorrections.GetEntriesFast();
277 TClass* ocl = obj->IsA();
278 for (Int_t id = 0; id < n; id++) {
279 const Correction* c = GetCorrection(id);
280 if (ocl->InheritsFrom(c->fCls)) return id;
281 }
282 return -1;
283}
284//____________________________________________________________________
285TObject*
286AliCorrectionManagerBase::Get(Int_t id)
287{
288 Correction* c = GetCorrection(id);
289 if (!c) {
290 AliWarningF("Cannot find correction with id %d", id);
291 return 0;
292 }
293 return c->Get();
294}
295//____________________________________________________________________
296const TObject*
297AliCorrectionManagerBase::Get(Int_t id) const
298{
299 const Correction* c = GetCorrection(id);
300 if (!c) {
301 AliWarningF("Cannot find correction with id %d", id);
302 return 0;
303 }
304 return c->Get();
305}
306
307//____________________________________________________________________
308Bool_t
309AliCorrectionManagerBase::InitCorrections(ULong_t run,
310 UShort_t sys,
311 UShort_t sNN,
312 Short_t fld,
313 Bool_t mc,
314 Bool_t sat,
315 Bool_t force)
316{
317 if (force) fIsInit = false;
318 if (!CheckConditions(run, sys, sNN, fld, mc, sat)) return false;
319 if (!ReadCorrections(run, sys, sNN, fld, mc, sat)) return false;
320 fIsInit = true;
321
322 if (fDB) {
323 delete fDB;
324 fDB = 0;
325 }
326
327 return true;
328}
329
330//____________________________________________________________________
331Bool_t
332AliCorrectionManagerBase::CheckConditions(ULong_t run,
333 UShort_t sys,
334 UShort_t sNN,
335 Short_t fld,
336 Bool_t mc,
337 Bool_t sat)
338{
339 if (!fIsInit) return true;
340
341 AliInfo("We are already initialised - checking settings...");
342 Bool_t same = true;
343 if (fRun != run) {
344 same = false;
345 }
346 if (fSys != sys) {
347 AliWarningF("Initialised collision system %s (%d) and "
348 "passed same %s (%d) does not match",
349 AliForwardUtil::CollisionSystemString(fSys), fSys,
350 AliForwardUtil::CollisionSystemString(sys), sys);
351 same = false;
352 }
353 if (TMath::Abs(fSNN - sNN) >= 10) {
354 AliWarningF("Initialised center of mass energy per nuclean "
355 "%s (%d) and passed same %s (%d) does not match",
356 AliForwardUtil::CenterOfMassEnergyString(fSNN), fSNN,
357 AliForwardUtil::CenterOfMassEnergyString(sNN), sNN);
358 same = false;
359 }
360 if (fField != fld) {
361 AliWarningF("Initialied L3 magnetic field %s (%d) and passed "
362 "same %s (%d) does not match",
363 AliForwardUtil::MagneticFieldString(fField), fField,
364 AliForwardUtil::MagneticFieldString(fld), fld);
365 same = false;
366 }
367 if (fMC != mc) {
368 AliWarningF("Initialied data type (%s) and passed "
369 "same (%s) does not match",
370 (fMC ? "MC" : "real"), (mc ? "MC" : "real"));
371 same = false;
372 }
373 if (fSatellite != sat) {
374 AliWarningF("Initialied collision ip type (%s) and passed "
375 "same (%s) does not match",
376 (fSatellite ? "satellite" : "nominal"),
377 (sat ? "satellite" : "nominal"));
378 same = false;
379 }
380 if (!same) {
381 AliWarning("Intialised parameters and these are not the same "
382 "- PROCEED WITH CAUTION!");
383 }
384 else
385 AliInfo("Initialized values consistent with data");
386
387 return true;
388
389}
390
391//____________________________________________________________________
392Bool_t
393AliCorrectionManagerBase::ReadCorrection(Int_t id,
394 ULong_t run,
395 UShort_t sys,
396 UShort_t sNN,
397 Short_t fld,
398 Bool_t mc,
399 Bool_t sat)
400{
401 if (!fDB) {
402 // We should always open the database, since we're not
403 // streamingthat object to disk.
404 fDB = new AliOADBForward;
405 }
406
407 Correction* c = GetCorrection(id);
408 if (!c->fEnabled) return true;
409 return c->ReadIt(fDB, run, sys, sNN, fld, mc, sat, fDebug);
410}
411
412//____________________________________________________________________
413Bool_t
414AliCorrectionManagerBase::ReadCorrections(ULong_t run,
415 UShort_t sys,
416 UShort_t sNN,
417 Short_t fld,
418 Bool_t mc,
419 Bool_t sat)
420{
421 if (fIsInit) return true;
422 if (fRun == run &&
423 fSys == sys &&
424 fField == fld &&
425 fMC == mc &&
426 fSatellite == sat &&
427 TMath::Abs(fSNN - sNN) < 11) {
428 // Already initialized for this - return
429 fIsInit = true;
430 return true;
431 }
432 if (!fDB) {
433 // We should always open the database, since we're not
434 // streamingthat object to disk.
435 fDB = new AliOADBForward;
436 }
437
438 fRun = run;
439 fSys = sys;
440 fSNN = sNN;
441 fField = fld;
442 fMC = mc;
443 fSatellite = sat;
444 Int_t n = fCorrections.GetEntriesFast();
445 Bool_t ret = true;
446 for (Int_t id = 0; id < n; id++)
447 if (!ReadCorrection(id, run, sys, sNN, fld, mc, sat)) ret = false;
448 return ret;
449}
450
451//====================================================================
452AliCorrectionManagerBase::Correction::Correction()
453 : TNamed(),
454 fCls(0),
455 fClientCls(""),
456 fQueryFields(0),
457 fEnabled(false),
458 fLastEntry(),
459 fObject(0)
460{}
461
462//____________________________________________________________________
463AliCorrectionManagerBase::Correction::Correction(const TString& tableName,
464 const TString& fileName,
465 TClass* cls,
466 UShort_t fields,
467 Bool_t enabled)
468 : TNamed(tableName, fileName),
469 fCls(cls),
470 fClientCls(cls->GetName()),
471 fQueryFields(fields),
472 fEnabled(enabled),
473 fLastEntry(""),
474 fObject(0)
475{}
476
477//____________________________________________________________________
478AliCorrectionManagerBase::Correction::Correction(const Correction& o)
479 : TNamed(o),
480 fCls(o.fCls),
481 fClientCls(o.fClientCls),
482 fQueryFields(o.fQueryFields),
483 fEnabled(o.fEnabled),
484 fLastEntry(o.fLastEntry),
485 fObject(o.fObject)
486{}
487
488//____________________________________________________________________
489AliCorrectionManagerBase::Correction&
490AliCorrectionManagerBase::Correction::operator=(const Correction& o)
491{
492 if (&o == this) return *this;
493 SetName(o.GetName());
494 SetTitle(o.GetTitle());
495 fCls = o.fCls;
496 //fClientCls = o.fClientCls;
497 fQueryFields = o.fQueryFields;
498 fEnabled = o.fEnabled;
499 fLastEntry = o.fLastEntry;
500 fObject = o.fObject;
501 return *this;
502}
503
504//____________________________________________________________________
505Bool_t
506AliCorrectionManagerBase::Correction::ReadIt(AliOADBForward* db,
507 ULong_t run,
508 UShort_t sys,
509 UShort_t sNN,
510 Short_t fld,
511 Bool_t mc,
512 Bool_t sat,
513 Bool_t vrb)
514{
515 if (!fEnabled) {
516 AliWarningF("Correction %s not enabled", GetName());
517 return 0;
518 }
519
520 // Assume failure
521 fObject = 0;
522
523 // Massage fields according to settings
bfab35d9 524 if (!(fQueryFields & kRun)) run = kIgnoreValue;
525 if (!(fQueryFields & kSys)) sys = kIgnoreValue;
526 if (!(fQueryFields & kSNN)) sNN = kIgnoreValue;
527 if (!(fQueryFields & kField)) fld = kIgnoreField;
8449e3e0 528 if (!(fQueryFields & kMC)) mc = false;
529 if (!(fQueryFields & kSatellite)) sat = false;
530
531 // Check if table is open, and if not try to open it
532 if (!db->FindTable(fName, true)) {
533 if (!db->Open(fTitle, fName, false, vrb)) {
534 AliWarningF("Failed to open table %s from %s", GetName(), GetTitle());
535 AliWarningF("content of %s for %s:",
536 gSystem->WorkingDirectory(), GetName());
537 gSystem->Exec("pwd; ls -l");
538 return false;
539 }
540 }
541
542 // Query database
543 AliOADBForward::Entry* e = db->Get(fName, run, AliOADBForward::kDefault,
544 sys, sNN, fld, mc, sat);
545 // Check return value
546 if (!e || !e->fData) {
547 AliWarningF("Failed to get %s from database in %s with "
548 "run=%lu sys=%hu sNN=%hu fld=%hd %s %s",
549 GetName(), GetTitle(), run, sys, sNN, fld,
550 (mc ? "MC" : "real"), (sat ? "satellite" : "nominal"));
551 return false;
552 }
553
554 // Ge the returned data
555 TObject* o = e->fData;
556
557 const TClass* cl = TheClass();
558 // Check return class
559 if (!o->IsA()->InheritsFrom(cl)) {
560 AliWarningF("%p is not pointer to a %s object but a %s",
561 o, fCls->GetName(), o->ClassName());
562 return false;
563 }
564
565 // Success
566 fObject = o;
567 fLastEntry = e->GetTitle();
568
569 return true;
570}
571
572//____________________________________________________________________
573Bool_t
574AliCorrectionManagerBase::Correction::StoreIt(AliOADBForward* db,
575 TObject* obj,
576 ULong_t run,
577 UShort_t sys,
578 UShort_t sNN,
579 Short_t fld,
580 Bool_t mc,
581 Bool_t sat,
582 const char* file,
583 const char* meth) const
584{
585 // Info("StoreIt", "Storing run=%lu sys=%hy sNN=%d fld=%d mc=%d sat=%d",
586 // run, sys, sNN, fld, mc, sat);
587 const TClass* cl = TheClass();
588
589 // Check value class
590 if (!obj->IsA()->InheritsFrom(cl)) {
591 AliWarningF("%p is not pointer to a %s object but a %s",
592 obj, cl->GetName(), obj->ClassName());
593 return false;
594 }
595
596 Bool_t local = file || !db;
597 TString fileName = (local ? file : fTitle.Data());
598 AliOADBForward* tdb = (local ? new AliOADBForward : db);
599
600 // Try to open the table read/write
601 if (!tdb->Open(fileName, Form("%s/%s", GetName(), meth), true, true)) {
602 AliWarningF("Failed to open table %s in %s", GetName(), fileName.Data());
603 return false;
604 }
605
606 // Massage fields according to settings
bfab35d9 607 if (!(fQueryFields & kRun)) run = kIgnoreValue;
608 if (!(fQueryFields & kSys)) sys = kIgnoreValue;
609 if (!(fQueryFields & kSNN)) sNN = kIgnoreValue;
610 if (!(fQueryFields & kField)) fld = kIgnoreField;
8449e3e0 611 if (!(fQueryFields & kMC)) mc = false;
612 if (!(fQueryFields & kSatellite)) sat = false;
613
614 // Try to insert the object
615 if (!tdb->Insert(fName, obj, run, sys, sNN, fld, mc, sat)) {
616 AliWarningF("Failed to insert into %s off database in %s with "
617 "run=%lu sys=%hu sNN=%hu fld=%hd %s %s",
618 GetName(), GetTitle(), run, sys, sNN, fld,
619 (mc ? "MC" : "real"), (sat ? "satellite" : "nominal"));
620 return false;
621 }
622
623 if (local) {
624 tdb->Close();
625 delete tdb;
626
627 AliInfoF("Correction object %s written to DB in %s - merge this with "
628 "%s to store for good", obj->GetName(), fileName.Data(),
629 GetTitle());
630 }
631
632 // Success
633 return true;
634}
635//____________________________________________________________________
636TObject*
637AliCorrectionManagerBase::Correction::Get()
638{
639 if (!fEnabled) {
640 AliWarningF("Correction %s not enabled", GetName());
641 return 0;
642 }
643 return fObject;
644}
645//____________________________________________________________________
646const TObject*
647AliCorrectionManagerBase::Correction::Get() const
648{
649 if (!fEnabled) {
650 AliWarningF("Correction %s not enabled", GetName());
651 return 0;
652 }
653 return fObject;
654}
655
656//____________________________________________________________________
657const TClass*
658AliCorrectionManagerBase::Correction::TheClass() const
659{
660 if (fCls) return fCls;
661 if (fClientCls.IsNull()) {
662 AliErrorF("No class name set for correction %s", GetName());
663 return 0;
664 }
665 fCls = gROOT->GetClass(fClientCls);
666 if (!fCls) {
667 AliErrorF("Couldn't get class %s for correction %s",
668 fClientCls.Data(), GetName());
669 return 0;
670 }
671 return fCls;
672}
673
674//____________________________________________________________________
675void
676AliCorrectionManagerBase::Correction::Print(Option_t* option) const
677{
678 char ind[gROOT->GetDirLevel()+1];
679 for (Int_t i = 0; i < gROOT->GetDirLevel(); i++) ind[i] = ' ';
680 ind[gROOT->GetDirLevel()] = '\0';
681
682 std::cout << ind << GetName() << ": " << (fEnabled ? "en" : "dis")
683 << "abled" << std::endl;
684 if (!fEnabled) return;
685
686 TString flds;
687 if (fQueryFields & kRun) flds.Append("run");
688 if (fQueryFields & kSys) flds.Append("|sys");
689 if (fQueryFields & kSNN) flds.Append("|sNN");
690 if (fQueryFields & kField) flds.Append("|field");
691 if (fQueryFields & kMC) flds.Append("|MC");
692 if (fQueryFields & kSatellite) flds.Append("|Satellite");
693 if (flds.BeginsWith("|")) flds.Remove(0,1);
694
695 const TClass* cl = TheClass();
696
697 std::cout << " Path: " << GetTitle() << "\n"
698 << " Data class: " << cl->GetName() << "\n"
699 << " Query fields: " << flds << std::endl;
700
701 if (fObject && !fLastEntry.IsNull())
702 std::cout << " Entry: " << fLastEntry << std::endl;
703
704 TString opt(option);
705 opt.ToUpper();
997ba0f4 706 if (!opt.Contains("D") || !fObject) return;
8449e3e0 707
708 gROOT->IncreaseDirLevel();
709 fObject->Print();
710 gROOT->DecreaseDirLevel();
711}
712
713//____________________________________________________________________
714void
715AliCorrectionManagerBase::Correction::Browse(TBrowser* b)
716{
717 b->Add(const_cast<TClass*>(fCls), "Class");
718 TString flds;
719 if (fQueryFields & kRun) flds.Append("run");
720 if (fQueryFields & kSys) flds.Append("|sys");
721 if (fQueryFields & kSNN) flds.Append("|sNN");
722 if (fQueryFields & kField) flds.Append("|field");
723 if (fQueryFields & kMC) flds.Append("|MC");
724 if (fQueryFields & kSatellite) flds.Append("|Satellite");
725 if (flds.BeginsWith("|")) flds.Remove(0,1);
726
727 b->Add(new TObjString(flds), "Query fields");
728 b->Add(new TParameter<bool>("Enabled", fEnabled));
729 b->Add(new TObjString(fLastEntry), "Entry");
730 if (fObject) b->Add(fObject);
731}
732//
733// EOF
734//