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