/[PAMELA software]/DarthVader/RunInfo/src/RunInfo.cpp
ViewVC logotype

Contents of /DarthVader/RunInfo/src/RunInfo.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.9 - (show annotations) (download)
Tue Sep 5 13:21:10 2006 UTC (18 years, 3 months ago) by mocchiut
Branch: MAIN
Changes since 1.8: +3 -1 lines
THIS VERSION DOES NOT COMPILE - S4 and RunInfo are fixed

1 //
2 #include <sstream>
3 //
4 #include <TObject.h>
5 #include <TChain.h>
6 #include <TSystem.h>
7 #include <TSystemFile.h>
8 #include <TArrayI.h>
9 #include <TFile.h>
10 #include <TTree.h>
11 #include <TDirectory.h>
12 #include <TSQLServer.h>
13 #include <TSQLRow.h>
14 #include <TSQLResult.h>
15 //
16 #include <GLTables.h>
17 #include <RunInfo.h>
18 ClassImp(SoftInfo);
19 ClassImp(ItoRunInfo);
20 //
21 using namespace std;
22 //
23
24 SoftInfo::SoftInfo() {
25 TRIG_ver = "";
26 TOF_ver = "";
27 AC_ver = "";
28 TRK_ver = "";
29 ORB_ver = "";
30 CAL_ver = "";
31 ND_ver = "";
32 S4_ver = "";
33 }
34
35 void SoftInfo::Clear(){
36 TRIG_ver = "";
37 TOF_ver = "";
38 AC_ver = "";
39 TRK_ver = "";
40 ORB_ver = "";
41 CAL_ver = "";
42 ND_ver = "";
43 S4_ver = "";
44 }
45
46
47 /**
48 * Fills a struct cSoftInfo with values from a SoftInfo object (to put data into a F77 common).
49 */
50 void SoftInfo::GetLevel2Struct(cSoftInfo *l2) const{
51 l2->FillTrigWith(TRIG_ver);
52 l2->FillTofWith(TOF_ver);
53 l2->FillAcWith(AC_ver);
54 l2->FillTrkWith(TRK_ver);
55 l2->FillOrbWith(ORB_ver);
56 l2->FillCalWith(CAL_ver);
57 l2->FillNdWith(ND_ver);
58 l2->FillS4With(S4_ver);
59 }
60 /***********************/
61
62 ItoRunInfo::ItoRunInfo() {
63 reprocessing = false;
64 updating = false;
65 isreadonly = true;
66 first_file_entry = 0;
67 last_file_entry = 0;
68 file_entries = 0;
69 totnorun = 0;
70 this->GL_RUN::Clear();
71 version = new SoftInfo();
72 norun = 0;
73 runlist = new TArrayI(500);
74 file = NULL;
75 newtree = new TTree();
76 }
77
78 ItoRunInfo::ItoRunInfo(TFile *processFl){
79 //
80 file=(TFile*)processFl;
81 dbc=NULL;
82 processFolder = "";
83 idRun = 0;
84 Detector = "NONE";
85 //
86 reprocessing = false;
87 updating = false;
88 first_file_entry = 0;
89 last_file_entry = 0;
90 file_entries = 0;
91 version = new SoftInfo();
92 norun = 0;
93 totnorun = 0;
94 runlist = new TArrayI(500);
95 //
96 }
97
98
99
100 TChain *ItoRunInfo::LoadRunInfoTree(TList *fl){
101 //
102 TChain *Tout=0;
103 //
104 TChain *RI = 0;
105 TChain *SI = 0;
106 RI = new TChain("RunInfo");
107 SI = new TChain("SoftInfo");
108 // loop over files and create chains
109 TIter next(fl);
110 TSystemFile *questo = 0;
111 while ( (questo = (TSystemFile*) next()) ) {
112 TString name = questo->GetName();
113 RI->Add(name);
114 SI->Add(name);
115 };
116 //
117 RI->SetBranchAddress("RunInfo", GetPointerToRI());
118 Tout = RI;
119 SI->SetBranchAddress("SoftInfo", GetPointerToSI());
120 Tout->AddFriend("SoftInfo");
121 //
122 return Tout;
123 //
124 }
125
126 ItoRunInfo::ItoRunInfo(TSQLServer *db, TFile *processFl, TString processFld){
127 //
128 file=(TFile*)processFl;
129 dbc=(TSQLServer*)db;
130 processFolder = processFld;
131 //
132 reprocessing = false;
133 updating = false;
134 first_file_entry = 0;
135 last_file_entry = 0;
136 file_entries = 0;
137 version = new SoftInfo();
138 norun = 0;
139 totnorun = 0;
140 runlist = new TArrayI(500);
141 //
142 }
143
144 void ItoRunInfo::CopyFromTo(GL_RUN *glrun,GL_RUN *newrun,SoftInfo *sinfo, SoftInfo *newver){
145 //
146 if ( glrun && newrun ){
147 //
148 // printf("copy \n");
149 //
150 newrun->ID = glrun->ID ;
151 newrun->ID_RUN_FRAG = glrun-> ID_RUN_FRAG ;
152 newrun->ID_ROOT_L0 = glrun->ID_ROOT_L0 ;
153 newrun->ID_ROOT_L2 = glrun->ID_ROOT_L2 ;
154 newrun->RUNHEADER_TIME = glrun->RUNHEADER_TIME ;
155 newrun->RUNTRAILER_TIME = glrun->RUNTRAILER_TIME ;
156 newrun->EV_FROM = glrun->EV_FROM ;
157 newrun->EV_TO = glrun->EV_TO ;
158 newrun->TRK_CALIB_USED = glrun->TRK_CALIB_USED ;
159 newrun->EFF_WRK_SCHEDULE = glrun->EFF_WRK_SCHEDULE ;
160 newrun->PRH_VAR_TRG_MODE_A = glrun->PRH_VAR_TRG_MODE_A ;
161 newrun->PRH_VAR_TRG_MODE_B = glrun->PRH_VAR_TRG_MODE_B ;
162 newrun->ACQ_BUILD_INFO =glrun->ACQ_BUILD_INFO ;
163 newrun->ACQ_VAR_INFO = glrun->ACQ_VAR_INFO ;
164 newrun->RUNHEADER_OBT = glrun->RUNHEADER_OBT ;
165 newrun->RUNTRAILER_OBT = glrun->RUNTRAILER_OBT ;
166 newrun->RUNHEADER_PKT = glrun->RUNHEADER_PKT ;
167 newrun->RUNTRAILER_PKT = glrun->RUNTRAILER_PKT ;
168 newrun->NEVENTS = glrun->NEVENTS ;
169 newrun->LAST_TIMESYNC = glrun->LAST_TIMESYNC ;
170 newrun->OBT_TIMESYNC = glrun->OBT_TIMESYNC ;
171 newrun->COMPILATIONTIMESTAMP = glrun->COMPILATIONTIMESTAMP ;
172 newrun->FAV_WRK_SCHEDULE = glrun->FAV_WRK_SCHEDULE ;
173 newrun->RM_ACQ_AFTER_CALIB = glrun->RM_ACQ_AFTER_CALIB ;
174 newrun->RM_ACQ_SETTING_MODE = glrun->RM_ACQ_SETTING_MODE ;
175 newrun->PKT_COUNTER = glrun->PKT_COUNTER ;
176 newrun->PKT_READY_COUNTER = glrun->PKT_READY_COUNTER ;
177 newrun->TRK_CALIB_USED = glrun->TRK_CALIB_USED ;
178 newrun->CAL_DSP_MASK = glrun->CAL_DSP_MASK ;
179 newrun->BOOT_NUMBER = glrun->BOOT_NUMBER ;
180 newrun->VALIDATION = glrun->VALIDATION ;
181 //
182 };
183 //
184 if ( newver && sinfo ){
185 //
186 newver->TRIG_ver = sinfo->TRIG_ver;
187 newver->TOF_ver = sinfo->TOF_ver;
188 newver->AC_ver = sinfo->AC_ver;
189 newver->TRK_ver = sinfo->TRK_ver;
190 newver->ORB_ver = sinfo->ORB_ver;
191 newver->CAL_ver = sinfo->CAL_ver;
192 newver->S4_ver = sinfo->S4_ver;
193 newver->ND_ver = sinfo->ND_ver;
194 //
195 };
196 }
197
198 Int_t ItoRunInfo::Update(UInt_t run, TString Detector, TString Version){
199 //
200 isreadonly = false;
201 idRun = run;
202 //
203 Bool_t debug = true;
204 //
205 Bool_t ismydir = false;
206 //
207 if ( !strcmp(processFolder.Data(),"") ){
208 processFolder = "runinfoFolder";
209 ismydir = true;
210 };
211 //
212 GL_RUN *oldrun = new GL_RUN();
213 GL_RUN *newrun = new GL_RUN();
214 SoftInfo *oldver = new SoftInfo();
215 SoftInfo *newver = new SoftInfo();
216 //
217 this->GL_RUN::Clear();
218 version->Clear();
219 //
220 norun = 0;
221 //
222 Bool_t found = false;
223 Int_t error = 0;
224 //
225 TTree *oldtree = 0;
226 //
227 // Try to get the tree Run in the processed file
228 //
229 oldtree = (TTree*)file->Get("Run");
230 //
231 // Look for detector's versions if we are updating a single detector
232 //
233 if ( debug ) printf("Detector -%s- \n",Detector.Data());
234 if ( !strcmp(Detector.Data(),"NONE") ){
235 version->TRIG_ver = Version;
236 version->TOF_ver = Version;
237 version->AC_ver = Version;
238 version->TRK_ver = Version;
239 version->ORB_ver = Version;
240 version->CAL_ver = Version;
241 version->S4_ver = Version;
242 version->ND_ver = Version;
243 } else {
244 if ( !strcmp(Detector.Data(),"TRIG") ) version->TRIG_ver = Version;
245 if ( !strcmp(Detector.Data(),"TOF") ) version->TOF_ver = Version;
246 if ( !strcmp(Detector.Data(),"AC") ) version->AC_ver = Version;
247 if ( !strcmp(Detector.Data(),"TRK") ) version->TRK_ver = Version;
248 if ( !strcmp(Detector.Data(),"CALO") ) version->CAL_ver = Version;
249 if ( !strcmp(Detector.Data(),"S4") ) version->S4_ver = Version;
250 if ( !strcmp(Detector.Data(),"ND") ) version->ND_ver = Version;
251 if ( !strcmp(Detector.Data(),"ORB") ) version->ORB_ver = Version;
252 if ( strcmp(Detector.Data(),"TRIG") && strcmp(Detector.Data(),"TOF") && strcmp(Detector.Data(),"AC") && strcmp(Detector.Data(),"TRK") && strcmp(Detector.Data(),"CALO") && strcmp(Detector.Data(),"S4") && strcmp(Detector.Data(),"ND") && strcmp(Detector.Data(),"ORB") ) return(-804);
253 };
254 //
255 if ( !oldtree ) {
256 //
257 if ( strcmp(Detector.Data(),"NONE") ) return(-803);
258 updating = false;
259 if ( debug ) printf(" RunInfo: creating Run tree in this file\n");
260 //
261 } else {
262 //
263 updating = true;
264 if ( debug ) printf(" RunInfo: updating versioning information \n");
265 //
266 };
267 //
268 file->cd();
269 //
270 // Prepare a new tree to upgrade the contents of the old tree
271 //
272 newtree = new TTree("Run-new","PAMELA Level2 data from the GL_RUN table");
273 newtree->Branch("RunInfo","GL_RUN",&newrun);
274 newtree->Branch("SoftInfo","SoftInfo",&newver);
275 //
276 //
277 if ( !updating ){
278 if ( idRun == 0 ){
279 if ( debug ) printf("\n RUNINFO - ERROR: reprocessing data but no RunInfo tree in Level2 file. \n");
280 return(-805);
281 };
282 //
283 error = Query_GL_RUN(idRun, dbc);
284 //
285 if ( error ){
286 if ( debug ) printf("\n RUNINFO - ERROR: Query_GL_RUN exited with non zero error\n");
287 return(error);
288 };
289 if ( ID == 0 ){
290 if ( debug ) printf("\n RUNINFO - ERROR: no run with ID_RUN = %u \n",idRun);
291 return(-5);
292 };
293 //
294 //
295 CopyFromTo((GL_RUN*)this,newrun,version,newver);
296 //
297 // fill the tree;
298 //
299 newtree->Fill();
300 //
301 totnorun = 1;
302 reprocessing = false;
303 first_file_entry = 0;
304 last_file_entry = (UInt_t)(EV_TO - EV_FROM);
305 norun = 1;
306 runlist->AddAt((Int_t)ID,0);
307 //
308 newtree->SetName("Run");
309 //
310 file->cd();
311 //
312 delete newver;
313 delete newrun;
314 delete oldver;
315 delete oldrun;
316 //
317 return(0);
318 //
319 } else {
320 //
321 //
322 oldtree->SetBranchAddress("RunInfo",&oldrun);
323 oldtree->SetBranchAddress("SoftInfo",&oldver);
324 //
325 totnorun = oldtree->GetEntries();
326 //
327 if ( totnorun > 500 ){
328 if ( debug ) printf("\n RUNINFO - ERROR: can not handle more than 500 runs!\n");
329 return(-806);
330 };
331 //
332 found = false;
333 //
334 for ( UInt_t run = 0; run < totnorun; run++){
335 //
336 oldtree->GetEntry(run);
337 //
338 CopyFromTo(oldrun,newrun,oldver,newver);
339 //
340 file_entries += (oldrun->EV_TO - oldrun->EV_FROM + 1);
341 //
342 if ( debug ) printf("totnorun %i idRun %i newrun->ID %i \n",(int)totnorun,(int)idRun,(int)newrun->ID);
343 //
344 if ( idRun == 0 || idRun == newrun->ID ) {
345 //
346 if ( debug ) printf(" Updating run number %u \n",idRun);
347 //
348 found = true;
349 //
350 runlist->AddAt(newrun->ID,norun);
351 norun++;
352 //
353 if ( !strcmp(Detector.Data(),"NONE") ){
354 //
355 // update infromations querying the DB
356 //
357 error = Query_GL_RUN(newrun->ID, dbc);
358 //
359 if ( error ){
360 if ( debug ) printf("\n RUNINFO - ERROR: Query_GL_RUN exited with non zero error\n");
361 return(error);
362 };
363 //
364 CopyFromTo((GL_RUN*)this,newrun,NULL,NULL);
365 //
366 } else {
367 //
368 if ( !strcmp(Detector.Data(),"TRIG") ){
369 newver->TRIG_ver = version->TRIG_ver;
370 newver->TOF_ver = oldver->TOF_ver;
371 newver->AC_ver = oldver->AC_ver;
372 newver->TRK_ver = oldver->TRK_ver;
373 newver->ORB_ver = oldver->ORB_ver;
374 newver->CAL_ver = oldver->CAL_ver;
375 newver->S4_ver = oldver->S4_ver;
376 newver->ND_ver = oldver->ND_ver;
377 if ( strcmp(oldver->TRIG_ver.Data(),"") ) reprocessing = true;
378 };
379 if ( !strcmp(Detector.Data(),"TOF") ){
380 newver->TRIG_ver = oldver->TRIG_ver;
381 newver->TOF_ver = version->TOF_ver;
382 newver->AC_ver = oldver->AC_ver;
383 newver->TRK_ver = oldver->TRK_ver;
384 newver->ORB_ver = oldver->ORB_ver;
385 newver->CAL_ver = oldver->CAL_ver;
386 newver->S4_ver = oldver->S4_ver;
387 newver->ND_ver = oldver->ND_ver;
388 if ( strcmp(oldver->TOF_ver.Data(),"") ) reprocessing = true;
389 };
390 if ( !strcmp(Detector.Data(),"AC") ){
391 newver->TRIG_ver = oldver->TRIG_ver;
392 newver->TOF_ver = oldver->TOF_ver;
393 newver->TRK_ver = oldver->TRK_ver;
394 newver->ORB_ver = oldver->ORB_ver;
395 newver->CAL_ver = oldver->CAL_ver;
396 newver->S4_ver = oldver->S4_ver;
397 newver->ND_ver = oldver->ND_ver;
398 newver->AC_ver = version->AC_ver;
399 if ( strcmp(oldver->AC_ver.Data(),"") ) reprocessing = true;
400 };
401 if ( !strcmp(Detector.Data(),"TRK") ){
402 newver->TRIG_ver = oldver->TRIG_ver;
403 newver->TOF_ver = oldver->TOF_ver;
404 newver->CAL_ver = oldver->CAL_ver;
405 newver->ORB_ver = oldver->ORB_ver;
406 newver->S4_ver = oldver->S4_ver;
407 newver->ND_ver = oldver->ND_ver;
408 newver->AC_ver = oldver->AC_ver;
409 newver->TRK_ver = version->TRK_ver;
410 if ( strcmp(oldver->TRK_ver.Data(),"") ) reprocessing = true;
411 };
412 if ( !strcmp(Detector.Data(),"ORB") ){
413 newver->TRIG_ver = oldver->TRIG_ver;
414 newver->TOF_ver = oldver->TOF_ver;
415 newver->CAL_ver = oldver->CAL_ver;
416 newver->TRK_ver = oldver->TRK_ver;
417 newver->S4_ver = oldver->S4_ver;
418 newver->ND_ver = oldver->ND_ver;
419 newver->AC_ver = oldver->AC_ver;
420 newver->ORB_ver = version->ORB_ver;
421 if ( strcmp(oldver->ORB_ver.Data(),"") ) reprocessing = true;
422 };
423 if ( !strcmp(Detector.Data(),"CALO") ){
424 newver->TRIG_ver = oldver->TRIG_ver;
425 newver->TOF_ver = oldver->TOF_ver;
426 newver->S4_ver = oldver->S4_ver;
427 newver->ORB_ver = oldver->ORB_ver;
428 newver->ND_ver = oldver->ND_ver;
429 newver->AC_ver = oldver->AC_ver;
430 newver->TRK_ver = oldver->TRK_ver;
431 newver->CAL_ver = version->CAL_ver;
432 if ( strcmp(oldver->CAL_ver.Data(),"") ) reprocessing = true;
433 };
434 if ( !strcmp(Detector.Data(),"S4") ){
435 newver->TRIG_ver = oldver->TRIG_ver;
436 newver->TOF_ver = oldver->TOF_ver;
437 newver->ND_ver = oldver->ND_ver;
438 newver->AC_ver = oldver->AC_ver;
439 newver->TRK_ver = oldver->TRK_ver;
440 newver->ORB_ver = oldver->ORB_ver;
441 newver->CAL_ver = oldver->CAL_ver;
442 newver->S4_ver = version->S4_ver;
443 if ( strcmp(oldver->S4_ver.Data(),"") ) reprocessing = true;
444 };
445 if ( !strcmp(Detector.Data(),"ND") ){
446 newver->TRIG_ver = oldver->TRIG_ver;
447 newver->TOF_ver = oldver->TOF_ver;
448 newver->S4_ver = oldver->S4_ver;
449 newver->AC_ver = oldver->AC_ver;
450 newver->ORB_ver = oldver->ORB_ver;
451 newver->TRK_ver = oldver->TRK_ver;
452 newver->CAL_ver = oldver->CAL_ver;
453 newver->ND_ver = version->ND_ver;
454 if ( strcmp(oldver->ND_ver.Data(),"") ) reprocessing = true;
455 };
456 };
457 //
458 last_file_entry = first_file_entry + (oldrun->EV_TO - oldrun->EV_FROM + 1);
459 //
460 } else {
461 if ( !found ) first_file_entry += (oldrun->EV_TO - oldrun->EV_FROM + 1);
462 };
463 //
464 file->cd();
465 newtree->Fill();
466 //
467 };
468 //
469 file->cd();
470 if ( oldtree ) oldtree->Delete("all");
471 newtree->SetName("Run");
472 //
473 delete newver;
474 delete newrun;
475 delete oldver;
476 delete oldrun;
477 //
478 if ( !found ){
479 if ( debug ) printf("\n RUNINFO - ERROR: no run with ID_RUN = %u \n",idRun);
480 return(-5);
481 };
482 //
483 // newtree->Write();
484 };
485 return(0);
486 }
487
488 Int_t ItoRunInfo::Read(UInt_t idRun){
489 //
490 isreadonly = true;
491 //
492 Bool_t debug = false;
493 //
494 SoftInfo *newver = new SoftInfo();
495 GL_RUN *newrun = new GL_RUN();
496 //
497 // Try to get the tree Run in the processed file
498 //
499 newtree = (TTree*)file->Get("Run");
500 //
501 if ( !newtree ) {
502 //
503 printf("\n RUNINFO - ERROR: no RunInfo tree in Level2 file. \n");
504 return(-801);
505 //
506 } else {
507 //
508 printf(" RunInfo: opening RunInfo tree \n");
509 //
510 newtree->SetBranchAddress("RunInfo",&newrun);
511 newtree->SetBranchAddress("SoftInfo",&newver);
512 //
513 totnorun = newtree->GetEntries();
514 //
515 if ( totnorun > 500 ){
516 if ( debug ) printf("\n RUNINFO - ERROR: can not handle more than 500 runs!\n");
517 return(-806);
518 };
519 //
520 first_file_entry = 0;
521 //
522 for ( UInt_t run = 0; run < totnorun; run++){
523 //
524 newtree->GetEntry(run);
525 //
526 file_entries += (newrun->EV_TO - newrun->EV_FROM + 1);
527 //
528 if ( debug ) printf("totnorun %i newrun->ID %i \n",(int)totnorun,(int)newrun->ID);
529 //
530 CopyFromTo(newrun,(GL_RUN*)this,newver,version);
531 if ( idRun == ID || idRun == 0 ){
532 runlist->AddAt(newrun->ID,norun);
533 norun++;
534 };
535 last_file_entry = first_file_entry + (newrun->EV_TO - newrun->EV_FROM + 1);
536 };
537 };
538 if ( debug ) printf("norun %i \n",(int)norun);
539 Int_t error = 0;
540 error = GetRunInfo(idRun);
541 delete newver;
542 delete newrun;
543 if ( error ) return(error);
544 return(0);
545 }
546
547 void ItoRunInfo::Close(){
548 reprocessing = false;
549 updating = false;
550 first_file_entry = 0;
551 last_file_entry = 0;
552 file_entries = 0;
553 norun = 0;
554 delete runlist;
555 file = new TFile();
556 if ( isreadonly ) newtree->Delete();
557 }
558
559 void ItoRunInfo::Clear(){
560 if ( newtree ) newtree->Delete();
561 }
562
563 UInt_t ItoRunInfo::GetRunForEntry(UInt_t entry){
564 //
565 UInt_t startfrom = 0;
566 //
567 if ( entry >= (UInt_t)first_file_entry && entry <= (UInt_t)last_file_entry ) return(ID);
568 //
569 if ( entry > (UInt_t)last_file_entry ){
570 for ( UInt_t nrun = 0; nrun < norun; nrun++){
571 if ( ID == (UInt_t)runlist->At(nrun) ) {
572 startfrom = nrun+1;
573 break;
574 };
575 };
576 } else {
577 startfrom = 0;
578 };
579 //
580 if ( startfrom >= norun ) startfrom = 0;
581 //
582 retry:
583 //
584 for ( UInt_t nrun = startfrom; nrun < norun; nrun++){
585 GetRunInfo((UInt_t)runlist->At(nrun));
586 if ( entry >= (UInt_t)first_file_entry && entry <= (UInt_t)last_file_entry ){
587 return((UInt_t)runlist->At(nrun));
588 };
589 };
590 if ( startfrom ){
591 startfrom = 0;
592 goto retry;
593 };
594 printf(" ERROR! run not found \n");
595 return(0);
596 }
597
598 Int_t ItoRunInfo::GetRunInfo(UInt_t run){
599 Bool_t found = false;
600 SoftInfo *nwver = new SoftInfo();
601 GL_RUN *nwrun = new GL_RUN();
602 //
603 newtree->SetBranchAddress("RunInfo",&nwrun);
604 newtree->SetBranchAddress("SoftInfo",&nwver);
605 //
606 last_file_entry = 0;
607 first_file_entry = 0;
608 //
609 totnorun = newtree->GetEntries();
610 //
611 for ( UInt_t nrun = 0; nrun < totnorun; nrun++){
612 newtree->GetEntry(nrun);
613 //
614 if ( nwrun->ID == run || run == 0 ){
615 CopyFromTo(nwrun,(GL_RUN*)this,nwver,version);
616 found = true;
617 last_file_entry = first_file_entry + (nwrun->EV_TO - nwrun->EV_FROM + 1);
618 };
619 if ( !found ) first_file_entry += (nwrun->EV_TO - nwrun->EV_FROM + 1);
620 };
621 delete nwver;
622 delete nwrun;
623 if ( found ) return(0);
624 return(-800);
625 }
626

  ViewVC Help
Powered by ViewVC 1.1.23