MiniballSort
Loading...
Searching...
No Matches
mb_sort.cc
Go to the documentation of this file.
1// My code include.
2#include "mb_sort.hh"
3
4// GUI Header
5#ifndef __MINIBALLGUI_HH
6#include "MiniballGUI.hh"
7#endif
8
9// Settings header
10#ifndef __SETTINGS_HH
11# include "Settings.hh"
12#endif
13
14// Calibration header
15#ifndef __CALIBRATION_HH
16# include "Calibration.hh"
17#endif
18
19// Reaction header
20#ifndef __REACTION_HH
21# include "Reaction.hh"
22#endif
23
24// Converter headers
25#ifndef __MIDASCONVERTER_HH
26# include "MidasConverter.hh"
27#endif
28#ifndef __MBSCONVERTER_HH
29# include "MbsConverter.hh"
30#endif
31#ifndef __MEDCONVERTER_HH
32# include "MedConverter.hh"
33#endif
34
35// EventBuilder header
36#ifndef __EVENTBUILDER_HH
37# include "EventBuilder.hh"
38#endif
39
40// Histogrammer header
41#ifndef __HISTOGRAMMER_HH
42# include "Histogrammer.hh"
43#endif
44
45// DataSpy header
46#ifndef __DATASPY_HH
47# include "DataSpy.hh"
48#endif
49
50// MiniballGUI header
51#ifndef __MINIBALLGUI_HH
52# include "MiniballGUI.hh"
53#endif
54
55// MiniballAngleFit header
56#ifndef __MINIBALLANGLEFITTER_HH
57# include "MiniballAngleFitter.hh"
58#endif
59
60// MiniballCDCalibrator header
61#ifndef __CDCALIBRATOR_HH
62# include "CDCalibrator.hh"
63#endif
64
65
66// Command line interface
67#ifndef __COMMAND_LINE_INTERFACE_HH
69#endif
70
71
72
73// Default parameters and name
74std::string output_name;
75std::string datadir_name;
76std::string name_set_file;
77std::string name_cal_file;
78std::string name_react_file;
79std::string name_angle_file = "";
80std::vector<std::string> input_names;
81
82// a flag at the input to force the conversion and other things
83bool flag_convert = false;
84bool flag_events = false;
85bool flag_source = false;
86bool flag_ebis = false;
87
88// select what steps of the analysis to be forced
89std::vector<bool> force_convert;
90bool force_sort = false;
91bool force_events = false;
92
93// Flag for somebody needing help on command line
94bool help_flag = false;
95
96// Flag if we want to launch the GUI for sorting
97bool gui_flag = false;
98
99// Input data type
100bool flag_midas = false;
101bool flag_mbs = false;
102bool flag_med = false;
103
104// Do we want to fit the 22Ne angle data?
105bool flag_angle_fit = false;
106
107// Do we want to do the CD calibration
108bool flag_cdcal = false;
109std::string cdcal_strips;
110unsigned char cdcal_pid = 12;
111unsigned char cdcal_nid = 2;
112
113// DataSpy
114bool flag_spy = false;
115bool flag_alive = true;
117
118// Monitoring input file
119bool flag_monitor = false;
120int mon_time = -1; // update time in seconds
121
122// Settings file
123std::shared_ptr<MiniballSettings> myset;
124
125// Calibration file
126std::shared_ptr<MiniballCalibration> mycal;
127bool overwrite_cal = false;
128
129// Reaction file
130std::shared_ptr<MiniballReaction> myreact;
131
132// Server and controls for the GUI
133std::unique_ptr<THttpServer> serv;
134int port_num = 8030;
135std::string spy_hists_file;
136std::vector<std::vector<std::string>> physhists;
137short spylayout[2] = {2,2};
138
139// Struct for passing to the thread
140typedef struct thptr {
141
142 std::shared_ptr<MiniballCalibration> mycal;
143 std::shared_ptr<MiniballSettings> myset;
144 std::shared_ptr<MiniballReaction> myreact;
145 std::vector<std::vector<std::string>> physhists;
146 short spylayout[2];
148
150
151
152// Pointers to the thread events TODO: sort out inhereted class stuff
153std::shared_ptr<MiniballConverter> conv_mon;
154std::shared_ptr<MiniballMbsConverter> conv_mbs_mon;
155std::shared_ptr<MiniballMidasConverter> conv_midas_mon;
156std::shared_ptr<MiniballEventBuilder> eb_mon;
157std::shared_ptr<MiniballHistogrammer> hist_mon;
158
160 conv_mon->ResetHists();
161}
162
164 eb_mon->ResetHists();
165}
166
168 hist_mon->ResetHists();
169}
170
172 bRunMon = kFALSE;
173}
174
176 bRunMon = kTRUE;
177}
178
179void signal_callback_handler( int signum ) {
180 std::cout << "Caught signal " << signum << endl;
181 flag_alive = false;
182}
183
184// Function to call the monitoring loop
185void* monitor_run( void* ptr ){
186
187 // This doesn't make sense for MED data which is historical
188 if( flag_med ) return 0;
189
190 // Get the settings, file etc.
191 thptr *inputptr = (thptr*)ptr;
192
193 // Load macros in thread
194 std::string rootline = ".L " + std::string(CUR_DIR) + "include/MonitorMacros.hh";
195 gROOT->ProcessLine( rootline.data() );
196
197 // This function is called to run when monitoring
198 if( flag_mbs ){
199 conv_mbs_mon = std::make_shared<MiniballMbsConverter>( inputptr->myset );
200 conv_mon.reset( conv_mbs_mon.get() );
201 }
202 else if( flag_midas ) {
203 conv_midas_mon = std::make_shared<MiniballMidasConverter>( inputptr->myset );
204 conv_mon.reset( conv_midas_mon.get() );
205 }
206 eb_mon = std::make_shared<MiniballEventBuilder>( inputptr->myset );
207 hist_mon = std::make_shared<MiniballHistogrammer>( inputptr->myreact, inputptr->myset );
208
209 // Data blocks for Data spy
210 if( flag_spy && ( myset->GetBlockSize() != 0x10000 && flag_midas ) ) {
211
212 // only 64 kB supported atm
213 std::cerr << "Currently only supporting 64 kB block size" << std::endl;
214 exit(1);
215
216 }
217
218 // Daresbury MIDAS DataSpy
219 DataSpy myspy;
220 long long buffer[8*1024];
221 int file_id = 0;
222 if( flag_spy && flag_midas ) myspy.Open( file_id );
223 int spy_length = 0;
224
225 // GSI MBS EventServer
226 MBS mbs;
227 if( flag_spy && flag_mbs ) mbs.OpenEventServer( "localhost", 8020 );
228
229 // Data/Event counters
230 int start_block = 0, start_subevt = 0;
231 int nblocks = 0, nsubevts = 0;
232 unsigned long nbuild = 0;
233
234 // Filenames for spy
235 std::string spyname_singles = datadir_name + "/singles.root";
236 std::string spyname_events = datadir_name + "/events.root";
237 std::string spyname_hists = datadir_name + "/hists.root";
238
239 // Converter setup
240 if( !flag_spy ) curFileMon = input_names.at(0); // maybe change in GUI later?
241 if( flag_source ) conv_mon->SourceOnly();
242 if( flag_ebis ) conv_mon->EBISOnly();
243 conv_mon->AddCalibration( inputptr->mycal );
244 conv_mon->SetOutput( spyname_singles );
245 conv_mon->MakeTree();
246 conv_mon->MakeHists();
247
248 // Add canvas and hists for spy
249 hist_mon->SetSpyHists( inputptr->physhists, inputptr->spylayout );
250
251 // Update server settings
252 // title of web page
253 std::string toptitle;
254 if( !flag_spy ) toptitle = curFileMon.substr( curFileMon.find_last_of("/")+1,
255 curFileMon.length()-curFileMon.find_last_of("/")-1 );
256 else toptitle = "DataSpy ";
257 toptitle += " (" + std::to_string( mon_time ) + " s)";
258 serv->SetItemField("/", "_toptitle", toptitle.data() );
259
260 // While the sort is running
261 while( inputptr->flag_alive ) {
262 //while( true ) {
263
264 // bRunMon can be set by the GUI
265 while( bRunMon ) {
266
267 // Convert - from MIDAS file
268 if( !flag_spy && flag_midas ) {
269
270 nblocks = conv_midas_mon->ConvertFile( curFileMon, start_block );
271 start_block = nblocks;
272
273 }
274
275 // Convert - from MBS file
276 else if( !flag_spy && flag_mbs ) {
277
278 nsubevts = conv_mbs_mon->ConvertFile( curFileMon, start_subevt );
279 start_subevt = nsubevts;
280
281 }
282
283 // Convert - from MIDAS shared memory
284 else if( flag_spy && flag_midas ){
285
286 // Clean up the trees before we start
287 conv_midas_mon->GetSortedTree()->Reset();
288 conv_midas_mon->GetMbsInfo()->Reset();
289
290 // Empty the previous data vector and reset counters
291 conv_midas_mon->StartFile();
292
293 // First check if we have data
294 std::cout << "Looking for data from DataSpy" << std::endl;
295 spy_length = myspy.Read( file_id, (char*)buffer, inputptr->myset->GetBlockSize() );
296 if( spy_length == 0 && bFirstRun ) {
297 std::cout << "No data yet on first pass" << std::endl;
298 gSystem->Sleep( 2e3 );
299 continue;
300 }
301
302 // Keep reading until we have all the data
303 // This could be multi-threaded to process data and go back to read more
304 int wait_time = 50; // ms - between each read
305 int block_ctr = 0;
306 long byte_ctr = 0;
307 int poll_ctr = 0;
308 while( block_ctr < 1024 && poll_ctr < 1000 * mon_time / wait_time ){
309
310 //std::cout << "Got " << spy_length << " bytes of data from DataSpy" << std::endl;
311 if( spy_length > 0 ) {
312 nblocks = conv_midas_mon->ConvertBlock( (char*)buffer, 0 );
313 block_ctr += nblocks;
314 //gSystem->Sleep(1); // wait 1 ms before reading next block
315 }
316 else {
317 gSystem->Sleep( wait_time ); // wait for new data in buffer
318 poll_ctr++;
319 }
320
321 // Read a new block
322 spy_length = myspy.Read( file_id, (char*)buffer, inputptr->myset->GetBlockSize() );
323 byte_ctr += spy_length;
324
325 //std::cout << block_ctr << " blocks in " << poll_ctr << " polls" << std::endl;
326
327 }
328
329 // Finish the last block
330 if( spy_length > 0 ) {
331 nblocks = conv_midas_mon->ConvertBlock( (char*)buffer, 0 );
332 block_ctr += nblocks;
333 }
334
335 std::cout << "Got " << byte_ctr << " bytes of data in " << block_ctr << " blocks from DataSpy" << std::endl;
336
337 // Sort the packets we just got, then do the rest of the analysis
338 conv_midas_mon->SortTree();
339 conv_midas_mon->PurgeOutput();
340
341 }
342
343 // Convert - from MBS event server
344 else if( flag_spy && flag_mbs ){
345
346 // Empty the previous data vector and reset counters
347 conv_mbs_mon->StartFile();
348
349 // First check if we have data
350 std::cout << "Looking for data from MBSEventServer" << std::endl;
351 conv_mbs_mon->SetMBSEvent( mbs.GetNextEventFromStream() );
352 conv_mbs_mon->ProcessBlock(0);
353 conv_mbs_mon->SortTree();
354 conv_mbs_mon->PurgeOutput();
355
356 }
357
358
359 // Only do the rest if it is not a source run
360 if( !flag_source ) {
361
362 // Event builder
363 if( bFirstRun ) {
364 eb_mon->SetOutput( spyname_events, true );
365 eb_mon->StartFile();
366
367 }
368 // TODO: This could be done better with smart pointers
369 TTree *sorted_tree = conv_mon->GetSortedTree()->CloneTree();
370 TTree *mbsinfo_tree = conv_mon->GetMbsInfo()->CloneTree();
371 eb_mon->SetInputTree( sorted_tree );
372 eb_mon->SetMBSInfoTree( mbsinfo_tree );
373 eb_mon->GetTree()->Reset();
374 nbuild = eb_mon->BuildEvents();
375 eb_mon->PurgeOutput();
376 delete sorted_tree;
377 delete mbsinfo_tree;
378
379 // Histogrammer
380 if( bFirstRun ) {
381 hist_mon->SetOutput( spyname_hists, true );
382 }
383 if( nbuild ) {
384 // TODO: This could be done better with smart pointers
385 TTree *evt_tree = eb_mon->GetTree()->CloneTree();
386 hist_mon->SetInputTree( evt_tree );
387 hist_mon->FillHists();
388 hist_mon->PurgeOutput();
389 delete evt_tree;
390 }
391
392 // If this was the first time we ran, do stuff?
393 if( bFirstRun ) {
394
395 hist_mon->PlotDefaultHists();
396 hist_mon->PlotPhysicsHists();
397 bFirstRun = kFALSE;
398
399 }
400
401 }
402
403 // This makes things unresponsive!
404 // Unless we are threading?
405 gSystem->Sleep( mon_time * 1e3 );
406
407 } // bRunMon
408
409 } // always running until ctrl+c
410
411 // Close the dataSpy before exiting (no point really)
412 if( flag_spy && flag_midas ) myspy.Close( file_id );
413 if( flag_spy && flag_mbs ) mbs.CloseEventServer();
414
415 // Close all outputs
416 conv_mon->CloseOutput();
417 eb_mon->CloseOutput();
418 hist_mon->CloseOutput();
419
420 return 0;
421
422}
423
424//void* start_http( void* ptr ){
426
427 // Server for JSROOT
428 std::string server_name = "http:" + std::to_string(port_num) + "?top=MiniballDAQMonitoring";
429 serv = std::make_unique<THttpServer>( server_name.data() );
430 serv->SetReadOnly(kFALSE);
431
432 // enable monitoring and
433 // specify items to draw when page is opened
434 serv->SetItemField("/","_monitoring","5000");
435 //serv->SetItemField("/","_layout","grid2x2");
436 //serv->SetItemField("/","_drawitem","[hpxpy,hpx,Debug]");
437 serv->SetItemField("/","drawopt","[colz,hist]");
438
439 // register simple start/stop commands
440 serv->RegisterCommand("/Start", "StartMonitor()");
441 serv->RegisterCommand("/Stop", "StopMonitor()");
442 serv->RegisterCommand("/ResetAll", "ResetAll()");
443 serv->RegisterCommand("/ResetSingles", "ResetConv()");
444 serv->RegisterCommand("/ResetEvents", "ResetEvnt()");
445 serv->RegisterCommand("/ResetHists", "ResetHist()");
446
447 // hide commands so the only show as buttons
448 //serv->Hide("/Start");
449 //serv->Hide("/Stop");
450 //serv->Hide("/Reset");
451
452 return;
453
454}
455
456// Function to read histogram info from a file into a 2D vector
458
459 // Check if the user gave a file
460 if( spy_hists_file.length() == 0 ) {
461
462 std::cout << "Default spy hists" << std::endl;
463
464 // If not, just use some defaults
465 spylayout[0] = 2; // x
466 spylayout[1] = 3; // y
467 physhists.push_back( {"ParticleSpectra/pE_theta_coinc", "TH2", "colz"} );
468 physhists.push_back( {"ParticleSpectra/pE_dE0", "TH2", "colz"} );
469 physhists.push_back( {"GammaRaySingles/gE_singles_ebis", "TH1", "hist"} );
470 physhists.push_back( {"GammaRaySingles/gE_singles_dc_ebis", "TH1", "hist"} );
471 physhists.push_back( {"GammaRayParticleCoincidences/gE_recoil_dc_ejectile", "TH1", "hist"} );
472 physhists.push_back( {"GammaRayParticleCoincidences/gE_recoil_dc_recoil", "TH1", "hist"} );
473
474 return;
475
476 }
477
478 std::ifstream infile( spy_hists_file );
479 std::string line;
480
481 // Check it's open
482 if( !infile.is_open() ) {
483
484 std::cerr << "Error: Could not open file " << spy_hists_file << std::endl;
485 return;
486
487 }
488
489 // Check for comments first
490 std::getline( infile, line );
491 while( line.at(0) == '#' )
492 std::getline( infile, line );
493
494 // Read first line: number of histograms in x direction on canvas
495 std::istringstream iss(line);
496 iss >> spylayout[0];
497
498 // Read second line: number of histograms in y direction on canvas
499 std::getline( infile, line );
500 iss = std::istringstream(line);
501 iss >> spylayout[1];
502
503 // Read the file line by line
504 while( std::getline( infile, line ) ) {
505
506 // skip empty lines
507 if( line.length() == 0 ) continue;
508
509 // Stream the line and check for a new item
510 std::string name, classType = "TH1", drawOption = "hist";
511 iss = std::istringstream(line);
512 iss >> name >> classType >> drawOption;
513
514 // If we got something, add it to the list
515 if( name.length() > 0 )
516 physhists.push_back({name, classType, drawOption});
517
518 }
519
520 infile.close();
521 return;
522
523}
524
526
527 //------------------------//
528 // Run conversion to ROOT //
529 //------------------------//
530 // TODO: Find a better way to have a converter object without creating everything thrice
531 MiniballMidasConverter conv_midas( myset );
532 MiniballMbsConverter conv_mbs( myset );
533 MiniballMedConverter conv_med( myset );
534 std::cout << "\n +++ Miniball Analysis:: processing MiniballConverter +++" << std::endl;
535
536 TFile *rtest;
537 std::ifstream ftest;
538 std::string name_input_file;
539 std::string name_output_file;
540
541 // Check each file
542 for( unsigned int i = 0; i < input_names.size(); i++ ){
543
544 name_input_file = input_names.at(i).substr( input_names.at(i).find_last_of("/")+1,
545 input_names.at(i).length() - input_names.at(i).find_last_of("/")-1 );
546 name_input_file = name_input_file.substr( 0, name_input_file.find_last_of(".") );
547
548 if( flag_source ) name_output_file = name_input_file + "_source.root";
549 else name_output_file = name_input_file + ".root";
550
551 name_output_file = datadir_name + "/" + name_output_file;
552 name_input_file = input_names.at(i);
553
554 force_convert.push_back( false );
555
556 // If input doesn't exist, skip it
557 ftest.open( name_input_file.data() );
558 if( !ftest.is_open() ) {
559
560 std::cerr << name_input_file << " does not exist" << std::endl;
561 continue;
562
563 }
564 else ftest.close();
565
566 // If output doesn't exist, we have to convert it anyway
567 // The convert flag will force it to be converted
568 ftest.open( name_output_file.data() );
569 if( !ftest.is_open() ) force_convert.at(i) = true;
570 else {
571
572 ftest.close();
573 rtest = new TFile( name_output_file.data() );
574 if( rtest->IsZombie() ) force_convert.at(i) = true;
575 if( rtest->TestBit(TFile::kRecovered) ){
576 std::cout << name_output_file << " possibly corrupted, reconverting" << std::endl;
577 force_convert.at(i) = true;
578 }
579 if( !flag_convert && !force_convert.at(i) )
580 std::cout << name_output_file << " already converted" << std::endl;
581 rtest->Close();
582
583 }
584
585 if( flag_convert || force_convert.at(i) ) {
586
587 std::cout << name_input_file << " --> ";
588 std::cout << name_output_file << std::endl;
589
590 if( flag_mbs ) {
591
592 if( flag_source ) conv_mbs.SourceOnly();
593 if( flag_ebis ) conv_mbs.EBISOnly();
594 conv_mbs.SetOutput( name_output_file );
595 conv_mbs.AddCalibration( mycal );
596 conv_mbs.MakeTree();
597 conv_mbs.MakeHists();
598 conv_mbs.ConvertFile( name_input_file );
599
600 // Sort the tree before writing and closing
601 if( !flag_source ){
602 conv_mbs.BuildMbsIndex();
603 if( myset->GetMbsEventMode() )
604 conv_mbs.SortTree(false);
605 else conv_mbs.SortTree();
606 }
607 conv_mbs.CloseOutput();
608
609 }
610
611 else if( flag_midas ) {
612
613 if( flag_source ) conv_midas.SourceOnly();
614 if( flag_ebis ) conv_midas.EBISOnly();
615 conv_midas.SetOutput( name_output_file );
616 conv_midas.AddCalibration( mycal );
617 conv_midas.MakeTree();
618 conv_midas.MakeHists();
619 conv_midas.ConvertFile( name_input_file );
620
621 // Sort the tree before writing and closing
622 if( !flag_source ) conv_midas.SortTree();
623 conv_midas.CloseOutput();
624
625 }
626
627 else if( flag_med ){
628
629 if( flag_source ) conv_med.SourceOnly();
630 if( flag_ebis ) conv_med.EBISOnly();
631 conv_med.SetOutput( name_output_file );
632 conv_med.AddCalibration( mycal );
633 conv_med.MakeTree();
634 conv_med.MakeHists();
635 conv_med.ConvertFile( name_input_file );
636
637 // Sort the tree before writing and closing
638 if( !flag_source ){
639 conv_med.BuildMbsIndex();
640 if( myset->GetMbsEventMode() )
641 conv_med.SortTree(false);
642 else conv_med.SortTree();
643 }
644 conv_med.CloseOutput();
645
646 }
647
648 }
649
650 }
651
652 return;
653
654}
655
656bool do_build() {
657
658 //-----------------------//
659 // Physics event builder //
660 //-----------------------//
662 std::cout << "\n +++ Miniball Analysis:: processing MiniballEventBuilder +++" << std::endl;
663
664 TFile *rtest;
665 std::ifstream ftest;
666 std::string name_input_file;
667 std::string name_output_file;
668 bool return_flag = false;
669
670 // Update calibration file if given
672
673 // Do event builder for each file individually
674 for( unsigned int i = 0; i < input_names.size(); i++ ){
675
676 name_input_file = input_names.at(i).substr( input_names.at(i).find_last_of("/")+1,
677 input_names.at(i).length() - input_names.at(i).find_last_of("/")-1 );
678 name_input_file = name_input_file.substr( 0, name_input_file.find_last_of(".") );
679
680 name_output_file = datadir_name + "/" + name_input_file + "_events.root";
681 name_input_file = datadir_name + "/" + name_input_file + ".root";
682
683 // If input doesn't exist, skip it
684 ftest.open( name_input_file.data() );
685 if( !ftest.is_open() ) {
686
687 std::cerr << name_input_file << " does not exist" << std::endl;
688 continue;
689
690 }
691 else {
692
693 ftest.close();
694 return_flag = true;
695
696 }
697
698 // We need to do event builder if we just converted it
699 // specific request to do new event build with -e
700 // this is useful if you need to add a new calibration
701 if( flag_convert || force_convert.at(i) || flag_events )
702 force_events = true;
703
704 // If it doesn't exist, we have to sort it anyway
705 else {
706
707 ftest.open( name_output_file.data() );
708 if( !ftest.is_open() ) force_events = true;
709 else {
710
711 ftest.close();
712 rtest = new TFile( name_output_file.data() );
713 if( rtest->IsZombie() ) force_events = true;
714 if( rtest->TestBit(TFile::kRecovered) ){
715 std::cout << name_output_file << " possibly corrupted, rebuilding" << std::endl;
716 force_events = true;
717 }
718 if( !force_events )
719 std::cout << name_output_file << " already built" << std::endl;
720 rtest->Close();
721
722 }
723
724 }
725
726 if( force_events ) {
727
728 std::cout << name_input_file << " --> ";
729 std::cout << name_output_file << std::endl;
730
731 eb.SetInputFile( name_input_file );
732 eb.SetOutput( name_output_file );
733 eb.BuildEvents();
734 eb.CloseOutput();
735
736 force_events = false;
737
738 }
739
740 }
741
742 return return_flag;
743
744}
745
746void do_hist() {
747
748 //------------------------------//
749 // Finally make some histograms //
750 //------------------------------//
752 std::cout << "\n +++ Miniball Analysis:: processing MiniballHistogrammer +++" << std::endl;
753
754 std::ifstream ftest;
755 std::string name_input_file;
756
757 std::vector<std::string> name_hist_files;
758
759 // We are going to chain all the event files now
760 for( unsigned int i = 0; i < input_names.size(); i++ ){
761
762 name_input_file = input_names.at(i).substr( input_names.at(i).find_last_of("/")+1,
763 input_names.at(i).length() - input_names.at(i).find_last_of("/")-1 );
764 name_input_file = name_input_file.substr( 0,
765 name_input_file.find_last_of(".") );
766 name_input_file = datadir_name + "/" + name_input_file + "_events.root";
767
768 ftest.open( name_input_file.data() );
769 if( !ftest.is_open() ) {
770
771 std::cerr << name_input_file << " does not exist" << std::endl;
772 continue;
773
774 }
775 else ftest.close();
776
777 name_hist_files.push_back( name_input_file );
778
779 }
780
781 // Only do something if there are valid files
782 if( name_hist_files.size() ) {
783
784 hist.SetOutput( output_name );
785 hist.SetInputFile( name_hist_files );
786 hist.FillHists();
787 hist.CloseOutput();
788
789 }
790
791 return;
792
793}
794
796
797 //------------------------------------------//
798 // Run angle fitting routine with 22Ne data //
799 //------------------------------------------//
800 MiniballAngleFitter angle_fit( myset, myreact );
801 std::cout << "\n +++ Miniball Analysis:: processing MiniballAngleFitter +++" << std::endl;
802
803 TFile *rtest;
804 std::ifstream ftest;
805 std::string name_input_file;
806 std::string name_output_file = "22Ne_angle_fit.root";
807 std::string hadd_file_list = "";
808 std::string name_results_file = "22Ne_angle_fit.cal";
809
810 // Check each file
811 for( unsigned int i = 0; i < input_names.size(); i++ ){
812
813 name_input_file = input_names.at(i).substr( input_names.at(i).find_last_of("/")+1,
814 input_names.at(i).length() - input_names.at(i).find_last_of("/")-1 );
815 name_input_file = name_input_file.substr( 0,
816 name_input_file.find_last_of(".") );
817 name_input_file = datadir_name + "/" + name_input_file + "_events.root";
818
819 // Add to list if the converted file exists
820 ftest.open( name_input_file.data() );
821 if( ftest.is_open() ) {
822
823 ftest.close();
824 rtest = new TFile( name_input_file.data() );
825 if( !rtest->IsZombie() ) {
826 hadd_file_list += " " + name_input_file;
827 }
828 else {
829 std::cout << "Skipping " << name_input_file;
830 std::cout << ", it's broken" << std::endl;
831 }
832 rtest->Close();
833
834 }
835
836 else {
837
838 std::cout << "Skipping " << name_input_file;
839 std::cout << ", file does not exist" << std::endl;
840
841 }
842
843 }
844
845 // If we have some ROOT files, add them and pass to the fitter
846 if( input_names.size() ){
847
848 // Perform the hadd (doesn't work on Windows)
849 gErrorIgnoreLevel = kError;
850 std::string cmd = "hadd -k -T -v 0 -f ";
851 cmd += name_output_file;
852 cmd += hadd_file_list;
853 gSystem->Exec( cmd.data() );
854 gErrorIgnoreLevel = kInfo;
855
856 // Give this file to the angle fitter
857 if( !angle_fit.SetInputROOTFile( name_output_file ) ) return;
858
859 }
860
861 // Otherwise we have to take the energies from the file
862 else if( !angle_fit.SetInputEnergiesFile( name_angle_file ) ) return;
863
864 // Perform the fitting
865 angle_fit.DoFit();
866
867 // Save the experimental energies and angles to a file
868 if( input_names.size() )
869 angle_fit.SaveExpEnergies( "22Ne_fitted_energies.dat" );
870 angle_fit.SaveReactionFile( name_results_file );
871
872 // Close the ROOT file
873 angle_fit.CloseROOTFile();
874
875}
876
877
878void do_cdcal(){
879
880 //-----------------------//
881 // Physics event builder //
882 //-----------------------//
884 std::cout << "\n +++ Miniball Analysis:: processing CD Calibrator +++" << std::endl;
885
886 std::ifstream ftest;
887 std::string name_input_file;
888 std::vector<std::string> name_hist_files;
889
890 // Update calibration file if given
891 if( overwrite_cal )
892 cdcal.AddCalibration( mycal );
893
894 else {
895
896 std::cout << "Please provide a calibration file to run cdcal... Exiting;" << std::endl;
897 return;
898
899 }
900
901 // We are going to chain all the event files now
902 for( unsigned int i = 0; i < input_names.size(); i++ ){
903
904 name_input_file = input_names.at(i).substr( input_names.at(i).find_last_of("/")+1,
905 input_names.at(i).length() - input_names.at(i).find_last_of("/")-1 );
906 name_input_file = name_input_file.substr( 0,
907 name_input_file.find_last_of(".") );
908 name_input_file = datadir_name + "/" + name_input_file + ".root";
909
910 ftest.open( name_input_file.data() );
911 if( !ftest.is_open() ) {
912
913 std::cerr << name_input_file << " does not exist" << std::endl;
914 continue;
915
916 }
917 else ftest.close();
918
919 name_hist_files.push_back( name_input_file );
920
921 }
922
923 // Only do something if there are valid files
924 if( name_hist_files.size() ) {
925
926 cdcal.SetPsideTagId( cdcal_pid );
927 cdcal.SetNsideTagId( cdcal_nid );
928 cdcal.SetOutput( output_name );
929 cdcal.SetInputFile( name_hist_files );
930 cdcal.FillHists();
931 cdcal.CloseOutput();
932
933 }
934
935 return;
936
937}
938
939int main( int argc, char *argv[] ){
940
941 // Command line interface, stolen from MiniballCoulexSort
942 std::unique_ptr<CommandLineInterface> interface = std::make_unique<CommandLineInterface>();
943
944 interface->Add("-i", "List of input files", &input_names );
945 interface->Add("-o", "Output file for histogram file", &output_name );
946 interface->Add("-s", "Settings file", &name_set_file );
947 interface->Add("-c", "Calibration file", &name_cal_file );
948 interface->Add("-r", "Reaction file", &name_react_file );
949 interface->Add("-f", "Flag to force new ROOT conversion", &flag_convert );
950 interface->Add("-e", "Flag to force new event builder (new calibration)", &flag_events );
951 interface->Add("-source", "Flag to define an source only run", &flag_source );
952 interface->Add("-ebis", "Flag to define an EBIS only run, discarding data >4ms after an EBIS event", &flag_ebis );
953 interface->Add("-midas", "Flag to define input as MIDAS data type (FEBEX with Daresbury firmware - default)", &flag_midas );
954 interface->Add("-mbs", "Flag to define input as MBS data type (FEBEX with GSI firmware)", &flag_mbs );
955 interface->Add("-med", "Flag to define input as MED data type (DGF and MADC)", &flag_med );
956 interface->Add("-anglefit", "Flag to run the angle fit", &flag_angle_fit );
957 interface->Add("-angledata", "File containing 22Ne segment energies", &name_angle_file );
958 interface->Add("-cdcal", "Make the CD calibration plots with pid and nid as the reference strips, given in the string format p<pid>n<nid>", &cdcal_strips );
959 interface->Add("-spy", "Flag to run the DataSpy", &flag_spy );
960 interface->Add("-spyhists", "File containing histograms for monitoring in the spy", &spy_hists_file );
961 interface->Add("-m", "Monitor input file every X seconds", &mon_time );
962 interface->Add("-p", "Port number for web server (default 8030)", &port_num );
963 interface->Add("-d", "Directory to put the sorted data default is /path/to/data/sorted", &datadir_name );
964 interface->Add("-g", "Launch the GUI", &gui_flag );
965 interface->Add("-h", "Print this help", &help_flag );
966
967 interface->CheckFlags( argc, argv );
968 if( help_flag ) {
969
970 interface->CheckFlags( 1, argv );
971 return 0;
972
973 }
974
975 // If we are launching the GUI
976 if( gui_flag || argc == 1 ) {
977
978 TApplication theApp( "App", &argc, argv );
979 new MiniballGUI();
980 theApp.Run();
981
982 return 0;
983
984 }
985
986 // Check if we are doing the angle fit
987 if( flag_angle_fit ) {
988
989 if( input_names.size() == 0 && name_angle_file.length() > 0 )
990 std::cout << "Angle fitting using energies from a file" << std::endl;
991
992 else if( input_names.size() > 0 && name_angle_file.length() == 0 )
993 std::cout << "Angle fitting using 22Ne data files, with automatic peak fitting" << std::endl;
994
995 else {
996
997 std::cout << "When fitting the 22Ne angle data, you must give segments energy file as input" << std::endl;
998 std::cout << "using the -angledata flag. Alternatively, you can give the raw data files using" << std::endl;
999 std::cout << "the -i flag and the peaks will be automatically fitted from the events file." << std::endl;
1000 return 1;
1001
1002 }
1003
1004 }
1005
1006 // Check we have data files
1007 else if( !input_names.size() && !flag_spy ) {
1008
1009 std::cout << "You have to provide at least one input file unless you are in DataSpy mode!" << std::endl;
1010 return 1;
1011
1012 }
1013
1014 // Check if we are doing the CD calibration
1015 if( cdcal_strips.length() > 0 ) {
1016
1017 flag_cdcal = true;
1018 std::stringstream ss(cdcal_strips);
1019 unsigned char str1, str2;
1020 unsigned int id1, id2;
1021 ss >> str1 >> id1 >> str2 >> id2;
1022
1023 if( str1 == 'p' ) cdcal_pid = id1;
1024 if( str2 == 'p' ) cdcal_pid = id2;
1025 if( str1 == 'n' ) cdcal_nid = id1;
1026 if( str2 == 'n' ) cdcal_nid = id2;
1027
1028 }
1029
1030
1031 // Check if it should be MIDAS, MBS or MED format
1032 if( !flag_midas && !flag_mbs && !flag_med && !flag_spy && !name_angle_file.length() ){
1033
1034 std::string extension = input_names.at(0).substr( input_names.at(0).find_last_of(".")+1,
1035 input_names.at(0).length()-input_names.at(0).find_last_of(".")-1 );
1036
1037 if( extension == "lmd" ) {
1038
1039 flag_mbs = true;
1040 std::cout << "Assuming we have MBS data because of the .lmd extension" << std::endl;
1041 std::cout << "Forcing the data block size to 32 kB" << std::endl;
1042
1043 }
1044
1045 else if( extension == "med" ) {
1046
1047 flag_med = true;
1048 std::cout << "Assuming we have MED data because of the .med extension" << std::endl;
1049 std::cout << "Forcing the data block size to 32 kB" << std::endl;
1050
1051 }
1052
1053 else flag_midas = true;
1054
1055 }
1056
1057 // Check if we should be monitoring the input
1058 if( flag_spy ) {
1059
1060 // Register signal and signal handler for DataSpy only
1061 //std::signal( SIGINT, signal_callback_handler );
1062
1063 flag_monitor = true;
1064 if( mon_time < 0 ) mon_time = 30;
1065 std::cout << "Getting data from shared memory every " << mon_time;
1066 std::cout << " seconds using DataSpy" << std::endl;
1067
1068 }
1069
1070 else if( mon_time >= 0 && input_names.size() == 1 && !flag_angle_fit ) {
1071
1072 flag_monitor = true;
1073 std::cout << "Running sort in a loop every " << mon_time;
1074 std::cout << " seconds\nMonitoring " << input_names.at(0) << std::endl;
1075
1076 }
1077
1078 else if( mon_time >= 0 && input_names.size() != 1 ) {
1079
1080 flag_monitor = false;
1081 std::cout << "Cannot monitor multiple input files, switching to normal mode" << std::endl;
1082
1083 }
1084
1085 // Check data type for spy
1086 if( flag_spy && !flag_midas && !flag_mbs && !flag_med ){
1087
1088 std::cout << "Assuming MIDAS data for spy" << std::endl;
1089 flag_midas = true;
1090
1091 }
1092
1093 // Check the directory we are writing to
1094 if( datadir_name.length() == 0 ) {
1095
1096 if( bool( input_names.size() ) ) {
1097
1098 // Probably in the current working directory
1099 if( input_names.at(0).find("/") == std::string::npos )
1100 datadir_name = "./sorted";
1101
1102 // Called from a different directory
1103 else {
1104
1105 datadir_name = input_names.at(0).substr( 0,
1106 input_names.at(0).find_last_of("/") );
1107 datadir_name += "/sorted";
1108
1109 }
1110
1111 }
1112
1113 else if( flag_spy ) datadir_name = "./dataspy";
1114 else if( flag_angle_fit ) datadir_name = "./positions";
1115 else datadir_name = "./mb_sort_outputs";
1116
1117 }
1118
1119 // Create the directory if it doesn't exist (not Windows compliant)
1120 std::string cmd = "mkdir -p " + datadir_name;
1121 gSystem->Exec( cmd.data() );
1122 std::cout << "Sorted data files being saved to " << datadir_name << std::endl;
1123
1124 // Check the ouput file name
1125 if( output_name.length() == 0 ) {
1126
1127 if( bool( input_names.size() ) ) {
1128
1129 std::string name_input_file = input_names.at(0).substr( input_names.at(0).find_last_of("/")+1,
1130 input_names.at(0).length() - input_names.at(0).find_last_of("/")-1 );
1131 name_input_file = name_input_file.substr( 0,
1132 name_input_file.find_last_of(".") );
1133
1134 if( flag_angle_fit ) {
1135
1136 output_name = datadir_name + "/" + name_input_file + "_results.root";
1137
1138 }
1139
1140 else if( flag_cdcal ) {
1141
1142 output_name = datadir_name + "/" + name_input_file + "_cdcal.root";
1143
1144 }
1145
1146 else if( input_names.size() > 1 ) {
1147
1148 output_name = datadir_name + "/" + name_input_file + "_hists_";
1149 output_name += std::to_string(input_names.size()) + "_subruns.root";
1150
1151 }
1152
1153 else
1154 output_name = datadir_name + "/" + name_input_file + "_hists.root";
1155
1156 }
1157
1158 else output_name = datadir_name + "/monitor_hists.root";
1159
1160 }
1161
1162 // Check we have a Settings file
1163 if( name_set_file.length() > 0 ) {
1164
1165 // Test if the file exists
1166 std::ifstream ftest;
1167 ftest.open( name_set_file.data() );
1168 if( !ftest.is_open() ) {
1169
1170 std::cout << name_set_file << " does not exist.";
1171 std::cout << " Using defaults" << std::endl;
1172 name_set_file = "dummy";
1173
1174 }
1175
1176 else {
1177
1178 ftest.close();
1179 std::cout << "Settings file: " << name_set_file << std::endl;
1180
1181 }
1182
1183 }
1184 else {
1185
1186 std::cout << "No settings file provided. Using defaults." << std::endl;
1187 name_set_file = "dummy";
1188
1189 }
1190
1191 // Check we have a calibration file
1192 if( name_cal_file.length() > 0 ) {
1193
1194 // Test if the file exists
1195 std::ifstream ftest;
1196 ftest.open( name_cal_file.data() );
1197 if( !ftest.is_open() ) {
1198
1199 std::cout << name_cal_file << " does not exist.";
1200 std::cout << " Using defaults" << std::endl;
1201 name_cal_file = "dummy";
1202
1203 }
1204
1205 else {
1206
1207 ftest.close();
1208 std::cout << "Calibration file: " << name_cal_file << std::endl;
1209 overwrite_cal = true;
1210
1211 }
1212
1213 }
1214 else {
1215
1216 std::cout << "No calibration file provided. Using defaults." << std::endl;
1217 name_cal_file = "dummy";
1218
1219 }
1220
1221 // Check we have a reaction file
1222 if( name_react_file.length() > 0 ) {
1223
1224 // Test if the file exists
1225 std::ifstream ftest;
1226 ftest.open( name_react_file.data() );
1227 if( !ftest.is_open() ) {
1228
1229 std::cout << name_react_file << " does not exist.";
1230 std::cout << " Using defaults" << std::endl;
1231 name_react_file = "dummy";
1232
1233 }
1234
1235 else {
1236
1237 ftest.close();
1238 std::cout << "Reaction file: " << name_react_file << std::endl;
1239
1240 }
1241
1242 }
1243 else {
1244
1245 std::cout << "No reaction file provided. Using defaults." << std::endl;
1246 name_react_file = "dummy";
1247
1248 }
1249
1250 myset = std::make_shared<MiniballSettings>( name_set_file );
1251 mycal = std::make_shared<MiniballCalibration>( name_cal_file, myset );
1252 if( flag_mbs || flag_med ) mycal->SetDefaultQint();
1253 mycal->ReadCalibration();
1254 myreact = std::make_shared<MiniballReaction>( name_react_file, myset );
1255
1256 // Force data block size for MBS and MED data
1257 if( flag_mbs ) myset->SetBlockSize( 0x8000 );
1258 else if( flag_med ) myset->SetBlockSize( 0x4000 );
1259
1260 // Turn of MBS event sorting for MIDAS and MED files
1261 if( flag_midas || flag_med ) myset->SetMbsEventMode(false);
1262
1263
1264 //-------------------//
1265 // Online monitoring //
1266 //-------------------//
1267 if( flag_monitor || flag_spy ) {
1268
1269 // Don't support MBS data spy
1270 if( flag_mbs && flag_spy ){
1271
1272 std::cout << "MBS data spy not yet supported" << std::endl;
1273 return 0;
1274
1275 }
1276
1277 // Don't support MED data spy (historical data)
1278 if( flag_med && flag_spy ){
1279
1280 std::cout << "MED data spy not supported because data is historical" << std::endl;
1281 return 0;
1282
1283 }
1284
1285 // Read the histogram list from the file
1287
1288 // Make some data for the thread
1289 thread_data data;
1290 data.mycal = mycal;
1291 data.myset = myset;
1292 data.myreact = myreact;
1293 data.flag_alive = flag_alive;
1294 data.physhists = physhists;
1295 data.spylayout[0] = spylayout[0];
1296 data.spylayout[1] = spylayout[1];
1297
1298 // Start the HTTP server from the main thread (should usually do this)
1299 start_http();
1300 gSystem->ProcessEvents();
1301
1302 // Thread for the monitor process
1303 TThread *th0 = new TThread( "monitor", monitor_run, (void*)&data );
1304 th0->Run();
1305
1306 // wait until we finish
1307 while( flag_alive ){
1308
1309 gSystem->Sleep(10);
1310 gSystem->ProcessEvents();
1311
1312 }
1313
1314 return 0;
1315
1316 }
1317
1318
1319
1320 //------------------//
1321 // Run the analysis //
1322 //------------------//
1323 do_convert();
1324 if( flag_angle_fit ){
1325 do_build();
1326 do_angle_fit();
1327 }
1328 else if( flag_cdcal ) {
1329 do_cdcal();
1330 }
1331 else if( !flag_source ) {
1332 if( do_build() )
1333 do_hist();
1334 }
1335
1336 std::cout << "\n\nFinished!\n";
1337
1338 return 0;
1339
1340}
int Open(int id)
Definition DataSpy.cc:13
int Read(int id, char *data, unsigned int length)
Definition DataSpy.cc:186
int Close(int id)
Definition DataSpy.cc:80
int OpenEventServer(std::string _server, unsigned short _port)
Definition MbsFormat.cc:181
const MBSEvent * GetNextEventFromStream()
Definition MbsFormat.cc:495
void CloseEventServer()
Definition MbsFormat.cc:219
void SaveExpEnergies(std::string energy_file)
bool SetInputEnergiesFile(std::string fname)
bool SetInputROOTFile(std::string fname)
void SaveReactionFile(std::string fname)
void SetOutput(std::string output_file_name, bool cWrite=false)
void SetNsideTagId(unsigned char id)
unsigned long FillHists()
void SetInputFile(std::vector< std::string > input_file_names)
void SetPsideTagId(unsigned char id)
void AddCalibration(std::shared_ptr< MiniballCalibration > mycal)
void AddCalibration(std::shared_ptr< MiniballCalibration > mycal)
Definition Converter.hh:79
unsigned long long int SortTree(bool do_sort=true)
Definition Converter.cc:489
void SetOutput(std::string output_file_name)
Definition Converter.cc:111
void AddCalibration(std::shared_ptr< MiniballCalibration > mycal)
void SetInputFile(std::string input_file_name)
unsigned long BuildEvents()
void SetOutput(std::string output_file_name, bool cWrite=false)
void SetOutput(std::string output_file_name, bool cWrite=false)
unsigned long FillHists()
void SetInputFile(std::vector< std::string > input_file_names)
int ConvertFile(std::string input_file_name, unsigned long start_block=0, long end_block=-1)
int ConvertFile(std::string input_file_name, unsigned long start_block=0, long end_block=-1)
int ConvertFile(std::string input_file_name, unsigned long start_block=0, long end_block=-1)
std::string name_set_file
Definition mb_sort.cc:76
int main(int argc, char *argv[])
Definition mb_sort.cc:939
bool flag_events
Definition mb_sort.cc:84
std::shared_ptr< MiniballSettings > myset
Definition mb_sort.cc:123
std::shared_ptr< MiniballConverter > conv_mon
Definition mb_sort.cc:153
struct thptr thread_data
std::shared_ptr< MiniballReaction > myreact
Definition mb_sort.cc:130
bool flag_med
Definition mb_sort.cc:102
void ReadSpyHistogramList()
Definition mb_sort.cc:457
std::unique_ptr< THttpServer > serv
Definition mb_sort.cc:133
unsigned char cdcal_nid
Definition mb_sort.cc:111
std::shared_ptr< MiniballHistogrammer > hist_mon
Definition mb_sort.cc:157
std::string datadir_name
Definition mb_sort.cc:75
bool gui_flag
Definition mb_sort.cc:97
bool flag_midas
Definition mb_sort.cc:100
void * monitor_run(void *ptr)
Definition mb_sort.cc:185
void stop_monitor()
Definition mb_sort.cc:171
bool help_flag
Definition mb_sort.cc:94
std::shared_ptr< MiniballMbsConverter > conv_mbs_mon
Definition mb_sort.cc:154
void do_angle_fit()
Definition mb_sort.cc:795
std::string output_name
Definition mb_sort.cc:74
bool flag_alive
Definition mb_sort.cc:115
bool flag_ebis
Definition mb_sort.cc:86
bool flag_angle_fit
Definition mb_sort.cc:105
void reset_conv_hists()
Definition mb_sort.cc:159
int port_num
Definition mb_sort.cc:134
bool flag_mbs
Definition mb_sort.cc:101
short spylayout[2]
Definition mb_sort.cc:137
void do_convert()
Definition mb_sort.cc:525
std::shared_ptr< MiniballEventBuilder > eb_mon
Definition mb_sort.cc:156
std::vector< bool > force_convert
Definition mb_sort.cc:89
int mon_time
Definition mb_sort.cc:120
std::string name_cal_file
Definition mb_sort.cc:77
void start_http()
Definition mb_sort.cc:425
std::string cdcal_strips
Definition mb_sort.cc:109
std::shared_ptr< MiniballMidasConverter > conv_midas_mon
Definition mb_sort.cc:155
std::string name_react_file
Definition mb_sort.cc:78
void signal_callback_handler(int signum)
Definition mb_sort.cc:179
bool flag_convert
Definition mb_sort.cc:83
void reset_evnt_hists()
Definition mb_sort.cc:163
std::string spy_hists_file
Definition mb_sort.cc:135
int open_spy_data
Definition mb_sort.cc:116
std::string name_angle_file
Definition mb_sort.cc:79
std::vector< std::string > input_names
Definition mb_sort.cc:80
void do_hist()
Definition mb_sort.cc:746
unsigned char cdcal_pid
Definition mb_sort.cc:110
bool flag_monitor
Definition mb_sort.cc:119
bool do_build()
Definition mb_sort.cc:656
std::shared_ptr< MiniballCalibration > mycal
Definition mb_sort.cc:126
void do_cdcal()
Definition mb_sort.cc:878
bool flag_spy
Definition mb_sort.cc:114
void start_monitor()
Definition mb_sort.cc:175
bool flag_source
Definition mb_sort.cc:85
std::vector< std::vector< std::string > > physhists
Definition mb_sort.cc:136
void reset_phys_hists()
Definition mb_sort.cc:167
bool force_sort
Definition mb_sort.cc:90
bool force_events
Definition mb_sort.cc:91
bool flag_cdcal
Definition mb_sort.cc:108
bool overwrite_cal
Definition mb_sort.cc:127
Bool_t bRunMon
Definition mb_sort.hh:33
std::string curFileMon
Definition mb_sort.hh:35
Bool_t bFirstRun
Definition mb_sort.hh:34
std::vector< std::vector< std::string > > physhists
Definition mb_sort.cc:145
std::shared_ptr< MiniballReaction > myreact
Definition mb_sort.cc:144
std::shared_ptr< MiniballCalibration > mycal
Definition mb_sort.cc:142
short spylayout[2]
Definition mb_sort.cc:146
std::shared_ptr< MiniballSettings > myset
Definition mb_sort.cc:143
bool flag_alive
Definition mb_sort.cc:147