data analysis scripts
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

772 lines
28 KiB

  1. #define hit_analyse_v2_cxx
  2. #include "hit_analyse_v2.h"
  3. #include <boost/math/statistics/linear_regression.hpp>
  4. int main(int argc, char **argv){
  5. opendatafiles(argc, argv);
  6. histograms(argc, argv);
  7. analyse(argc, argv);
  8. closedatafiles();
  9. return 0;
  10. }
  11. int opendatafiles(int argc, char ** argv){
  12. if (argc>2){
  13. //open bpm data file
  14. filename = Form("%s%s.da2",argv[1],argv[2]);
  15. file.open(filename, ifstream::in | ifstream::binary);
  16. if (!file.is_open())
  17. {
  18. std::cerr << " ### Hitdata: File could not be opened!" << filename << std::endl;
  19. return 0; //file could not be opened
  20. }
  21. else {std::cout << filename << " opened successfully." << std::endl;}
  22. ethercat_ts_filename = Form("%s/ethercat/SVB/timestamp/%s_channel18_timestamp.txt",argv[1],argv[2]);
  23. ethercat_ts_file.open(ethercat_ts_filename, ifstream::in);
  24. if (!ethercat_ts_file.is_open())
  25. {
  26. std::cerr << " ### Hitdata: File could not be opened!" << ethercat_ts_filename << std::endl;
  27. return 0; //file could not be opened
  28. }
  29. else {std::cout << ethercat_ts_filename << " opened successfully." << std::endl;}
  30. ethercat_ic1_filename = Form("%s/ethercat/SVB/%s_channel1.txt",argv[1],argv[2]);
  31. ethercat_ic1_file.open(ethercat_ic1_filename, ifstream::in);
  32. if (!ethercat_ic1_file.is_open())
  33. {
  34. std::cerr << " ### Hitdata: File could not be opened!" << ethercat_ic1_filename << std::endl;
  35. return 0; //file could not be opened
  36. }
  37. else {std::cout << ethercat_ic1_filename << " opened successfully." << std::endl;}
  38. ethercat_ic2_filename = Form("%s/ethercat/SVB/%s_channel2.txt",argv[1],argv[2]);
  39. ethercat_ic2_file.open(ethercat_ic2_filename, ifstream::in);
  40. if (!ethercat_ic2_file.is_open())
  41. {
  42. std::cerr << " ### Hitdata: File could not be opened!" << ethercat_ic2_filename << std::endl;
  43. return 0; //file could not be opened
  44. }
  45. else {std::cout << ethercat_ic2_filename << " opened successfully." << std::endl;}
  46. bpm_ts_filename = Form("%s/root/timestamp/%s_timestamp.txt",argv[1],argv[2]);
  47. bpm_ts_file.open(bpm_ts_filename, ifstream::in);
  48. if (!bpm_ts_file.is_open())
  49. {
  50. std::cerr << " ### Hitdata: File could not be opened!" << bpm_ts_filename << std::endl;
  51. return 0; //file could not be opened
  52. }
  53. else {std::cout << bpm_ts_filename << " opened successfully." << std::endl;}
  54. string visualize_check = argv[5]; //plot data
  55. if (visualize_check == "vis_true") {visualize = true;}
  56. else{ visualize= false;}
  57. }
  58. return 1;
  59. }
  60. int closedatafiles(){
  61. if (file.is_open()) file.close();
  62. // if (timestampfile.is_open()) timestampfile.close();
  63. //if (offsetfile.is_open()) offsetfile.close();
  64. ethercat_ts_file.close();
  65. ethercat_ic1_file.close();
  66. ethercat_ic1_file.close();
  67. bpm_ts_file.close();
  68. // rootFile->Write();
  69. rootFile->Close();
  70. return 1;
  71. }
  72. double * timealign()
  73. {
  74. static double offsetpar[4];
  75. std::vector<double> ts_eth;
  76. std::vector<double> frame_eth;
  77. std::vector<double> ts_bpm;
  78. std::vector<double> frame_bpm;
  79. double dummy1, dummy2;
  80. while (ethercat_ts_file >> dummy1 >> dummy2){
  81. ts_eth.push_back(dummy1);
  82. frame_eth.push_back(dummy2);
  83. }
  84. cout << "size of ts_eth: " << ts_eth.size() << endl;
  85. while (bpm_ts_file >> dummy1 >> dummy2){
  86. ts_bpm.push_back(dummy1);
  87. frame_bpm.push_back(dummy2);
  88. }
  89. cout << "size of ts_bpm: " << ts_bpm.size() << endl;;
  90. auto [c0_eth, c1_eth] = boost::math::statistics::simple_ordinary_least_squares(frame_eth, ts_eth);
  91. auto [c0_bpm, c1_bpm] = boost::math::statistics::simple_ordinary_least_squares(frame_bpm, ts_bpm);
  92. std::cout << "timestamp = " << c0_eth << " + " << c1_eth << "*x" << "\n";
  93. std::cout << "timestamp = " << c0_bpm << " + " << c1_bpm << "*y" << "\n";
  94. // eth_frame(x) = floor(( offsetpar[2] + offsetpar[3]*bpm_frame(y) - offsetpar[0])/offsetpar[1]);
  95. // bpm_frame(y) = (offsetpar[0]+ offsetpar[1]*eth_frame(x) - offsetpar[2]) /offsetpar[3];
  96. //offset = (c0_eth - c0_bpm)*10;
  97. offsetpar[0] = c0_eth;
  98. offsetpar[1] = c1_eth;
  99. offsetpar[2] = c0_bpm;
  100. offsetpar[3] = c1_bpm;
  101. ethercat_ts_file.close();
  102. bpm_ts_file.close();
  103. return offsetpar;
  104. }
  105. void readethercat()
  106. {
  107. double time[2];
  108. double tempic1 = 0.;
  109. double tempic2 = 0.;
  110. while(ethercat_ic1_file >> time[0] >> tempic1){
  111. vec_ic1.push_back(tempic1);
  112. }
  113. while(ethercat_ic2_file >> time[1] >> tempic2){
  114. vec_ic2.push_back(tempic2);
  115. }
  116. // cout << time[0][0] << " " << ethercat.ic1 << " " << ethercat.ic2 << endl;
  117. // cout << time[0][0] << " " << time[0][1] << " " << time[0][0]-time[0][1] << endl;
  118. // cout << time[1][0] << " " << time[1][1] << " " << time[1][0]-time[1][1] << endl;
  119. }
  120. int analyse(int argc, char **argv)
  121. {
  122. int first_frame = 0; // 1440000
  123. int nr_frames = -1;
  124. int increment = 1;
  125. double frameoffset = atof(argv[3]);
  126. double dummy;
  127. double * offset = timealign();
  128. int ethercatoffset = floor((offset[0]+ offset[1]*0.0 - offset[2]) /offset[3] - frameoffset); //start at the 0th ethercat frame
  129. first_frame = ethercatoffset; // start looking in the BPM data only once the ethercat data has started
  130. cout << "first frame: " << first_frame << endl;
  131. ///timestamp finding variables
  132. float fs = 10000; //10kHz fibre bpm
  133. float threshold = 0.5;
  134. // fs = 20kHz for ethercat IC, threshold = 2500
  135. // fs = 10kHz for fBPM, threshold = 0.5
  136. //Decodes timestamp data from synchro stream.
  137. //fs is frame rate in Hz.
  138. //threshold is the threshold value. Use e.g. 0.5 for boolean data
  139. //Timestamper bitrate is assumed to be 250 bps, 4 transmissions/s
  140. int current_pos_in_samples = 0;
  141. int samples_per_50ms = floor(50e-3 * fs);
  142. int samples_per_one_transmission = floor(250e-3 * fs);
  143. int samples_per_bit = floor(4e-3 * fs);
  144. string outfilename;
  145. outfilename+=argv[1];
  146. outfilename+="root/timestamp/";
  147. outfilename+=argv[2];
  148. outfilename+="_timestamp.txt";
  149. // outfile.open(outfilename);
  150. // if (outfile.good()) {cout << outfilename << " opened successfully." << endl;}
  151. // else {cout << outfilename << " opening failed." << endl;}
  152. cout << "samples_per_50ms: " << samples_per_50ms << endl;
  153. cout << "samples_per_one_transmission :" << samples_per_one_transmission << endl;
  154. cout << "samples_per_bit: "<< samples_per_bit << endl;
  155. //%this is used for byte decoding
  156. int bit_multipliers[10] = {0, 1, 2, 4, 8, 16, 32, 64, 128, 0}; //1+byte+1
  157. // %and this for word decoding
  158. int byte_multipliers[4] = {1, 256, 65536, 16777216};
  159. //%Here are positions of each transmission and decoded values
  160. vector<int> block_positions;
  161. vector<float> block_data;
  162. vector<float> byte_data;
  163. vector<float> bit_data;
  164. vector<int> bit_pattern_to_test;
  165. vector<float> sample_buffer;
  166. sample_buffer.assign(floor(4*10*samples_per_bit+samples_per_50ms),0);
  167. float byte_value;
  168. int block_nr = 0;
  169. float block_value;
  170. int nbelowthreshold = 0;
  171. int nabovethreshold = 0;
  172. int last_nbelowthreshold = 0;
  173. int last_nabovethreshold = 0;
  174. float intime;
  175. float analog_in2;
  176. float last_analog_in2 = 0;
  177. int transmission_start_in_samples = 0;
  178. //Read first record to find board configuration
  179. Fullframe sampleframe;
  180. if (sampleframe.read(&file) == 0)
  181. {
  182. std::cerr << " ### Hitdata: First frame could not be read!" << std::endl;
  183. file.close();
  184. return 0;
  185. }
  186. else {
  187. std::cout << "Sample frame size (bytes): " << sampleframe.sizeInFile() << std::endl;
  188. }
  189. //Check file size
  190. file.seekg(0, std::ios::beg);
  191. std::streamsize fsize = file.tellg();
  192. file.seekg(0, std::ios::end);
  193. fsize = file.tellg() - fsize;
  194. //Determine real frames to read
  195. unsigned int max_frames = fsize / sampleframe.sizeInFile();
  196. if ((max_frames == -1) || (max_frames < nr_frames))
  197. nr_frames = max_frames;
  198. std::cout << " Hitdata: Nr frames to be read: " << nr_frames << std::endl;
  199. ///set the background levels from first N events
  200. int bkg_frames = 1000;
  201. if (set_background_v2(0, bkg_frames)==0) return 0;
  202. BPMbeamrecon_Zeroed.Position = -128.;
  203. BPMbeamrecon_Zeroed.Focus = -1.;
  204. BPMbeamrecon_Zeroed.Peak = -1.;
  205. BPMbeamrecon_Zeroed.Position = -128.;
  206. BPMbeamrecon_Zeroed.Rsqr = -1.;
  207. BPMbeamrecon_Zeroed.Skew = -128.;
  208. BPMbeamrecon_Zeroed.Position = -128.;
  209. BPMbeamrecon_Zeroed.Sum = 0.;
  210. BPMbeamrecon_Zeroed.n_channels = 0;
  211. //read board
  212. readethercat(); //get the relevant ethercat data;. fills two vectors for ic1 and ic2
  213. int ethercat_frame = 0;
  214. //Read!
  215. std::cout << "Reading data starting from frame: " << first_frame << std::endl;
  216. file.seekg(first_frame * sampleframe.sizeInFile(), std::ios::beg);
  217. for (int frame_nr = first_frame; frame_nr < nr_frames; frame_nr++)
  218. {
  219. eventID=frame_nr;
  220. // offset = floor((c0_bpm + c1_bpm*currentframe - c0_eth)/c1_eth);
  221. ethercatoffset = floor(( offset[2] + offset[3]*(frame_nr+frameoffset) - offset[0])/offset[1]);
  222. //cout << eventID << " " << ethercatoffset << " " << ( offset[2] + offset[3]*float(frame_nr+frameoffset) - offset[0] ) / offset[1] << endl;
  223. if (ethercatoffset>=0){
  224. ethercat.ic1 = vec_ic1[ethercatoffset]; //not a simple 2:1 frame alignmenmt
  225. ethercat.ic2 = vec_ic2[ethercatoffset];
  226. ethercat.ic1 += vec_ic1[ethercatoffset+1];
  227. ethercat.ic2 += vec_ic2[ethercatoffset+1];
  228. }
  229. else{
  230. continue;
  231. }
  232. if ((frame_nr%100000) == 0)
  233. std::cout << " Frame " << frame_nr << std::endl;
  234. file.seekg((frame_nr*increment) * sampleframe.sizeInFile() , std::ios::beg);
  235. if (sampleframe.read(&file) == 0) //read the next frame and catch if returns error
  236. {
  237. std::cerr << " ### Hitdata: Frame " << frame_nr << " could not be read! Stopping." << std::endl;
  238. file.close(); //read error, finish!
  239. return 0;
  240. }
  241. for (int boardnumber = 0; boardnumber<4; boardnumber++){
  242. board_b[boardnumber] = readboard(sampleframe,boardnumber);//a bit redundant but does some analysis
  243. // std::cout << board_b[0].integratedsignalamp << std::endl;
  244. if (boardnumber==0&&board_b[0].integratedsignalamp>1000 && board_b[0].maxchannel_amp>100.){
  245. BPMbeamrecon_0 = beamreconstruction(board_b[0], 80.); // do the linear regression fit of the beam;
  246. // std::cout << "doing regression" << std::endl;
  247. }
  248. else if (boardnumber==0) {BPMbeamrecon_0=BPMbeamrecon_Zeroed;}
  249. if (boardnumber==1&&board_b[1].integratedsignalamp>1000 && board_b[1].maxchannel_amp>100.){
  250. BPMbeamrecon_1 = beamreconstruction(board_b[1], 80.); // do the linear regression fit of the beam;
  251. // std::cout << "doing regression" << std::endl;
  252. }
  253. else if (boardnumber==1) {BPMbeamrecon_1=BPMbeamrecon_Zeroed;}
  254. if (boardnumber==2&&board_b[2].integratedsignalamp>1000 && board_b[2].maxchannel_amp>100.){
  255. BPMbeamrecon_2 = beamreconstruction(board_b[2], 80.); // do the linear regression fit of the beam;
  256. // std::cout << "doing regression" << std::endl;
  257. }
  258. else if (boardnumber==2) {BPMbeamrecon_2=BPMbeamrecon_Zeroed;}
  259. if (boardnumber==3&&board_b[3].integratedsignalamp>1000 && board_b[3].maxchannel_amp>100.){
  260. BPMbeamrecon_3 = beamreconstruction(board_b[3], 80.); // do the linear regression fit of the beam;
  261. // std::cout << "doing regression" << std::endl;
  262. }
  263. else if (boardnumber==3) {BPMbeamrecon_3=BPMbeamrecon_Zeroed;}
  264. }
  265. // cout << "fill hist " << int(board_b[0].nrChannels) << endl;
  266. for (int j = 0;j< board_b[0].nrChannels;j++){
  267. if (board_b[0].maxchannel_amp>100.) TH2D_b0_signal_vs_channel->Fill(j, board_b[0].channel_amp[j]);
  268. }
  269. for (int j = 0;j< board_b[1].nrChannels;j++){
  270. if (board_b[1].maxchannel_amp>100.) TH2D_b1_signal_vs_channel->Fill(j, board_b[1].channel_amp[j]);
  271. }
  272. for (int j = 0;j< board_b[2].nrChannels;j++){
  273. if (board_b[2].maxchannel_amp>100.) TH2D_b2_signal_vs_channel->Fill(j, board_b[2].channel_amp[j]);
  274. }
  275. for (int j = 0;j< board_b[3].nrChannels;j++){
  276. if (board_b[3].maxchannel_amp>100.) TH2D_b3_signal_vs_channel->Fill(j, board_b[3].channel_amp[j]);
  277. }
  278. ///find timestamps in sma_state data for the BPM
  279. analog_in2 = board_b[3].sma_state;
  280. // cout << current_pos_in_samples << ": " << intime << " " << analog_in2 << " ";
  281. current_pos_in_samples = eventID ;
  282. sample_buffer.erase(sample_buffer.begin());//remove the first bit in the sample_buffer, and then add the new value at the end.
  283. sample_buffer.push_back(analog_in2);
  284. last_nbelowthreshold = nbelowthreshold;
  285. last_nabovethreshold = nabovethreshold;
  286. //look for 50 ms gap between transmissions (1000 * 0.05ms frames in ethercat IC) then process the sample buffer
  287. if (analog_in2<threshold) {
  288. nbelowthreshold++;
  289. nabovethreshold=0;
  290. }
  291. else {
  292. nbelowthreshold=0; //reset search window counter if you go above threshold again without reaching the 50ms gap
  293. nabovethreshold++;
  294. }
  295. // cout <<" below: " << nbelowthreshold << " above: " << nabovethreshold << endl;
  296. // if (last_nbelowthreshold>nbelowthreshold) cout << "last below " << last_nbelowthreshold << endl;
  297. // if (last_nabovethreshold>nabovethreshold) cout << "last above " << last_nabovethreshold << endl;
  298. if (nabovethreshold>=samples_per_50ms+samples_per_bit){ // last stop bit + 50ms above thresholds
  299. nabovethreshold=0; //reset search window counter
  300. transmission_start_in_samples = current_pos_in_samples - samples_per_50ms - 4*10 * samples_per_bit;
  301. //%if the gap was found, proceed to finding start and stop bits in sample buffer...
  302. // cout << transmission_start_in_samples << ": sample buffer[" << sample_buffer.size() << "]" << endl;
  303. // for (auto i: sample_buffer) std::cout << i << " ";
  304. // cout << endl;
  305. // %initialize byte counter
  306. //fill with the middle values where the bits should be
  307. byte_data.clear();
  308. bit_pattern_to_test.clear();
  309. // cout << transmission_start_in_samples << ": bit pattern[40] ";
  310. int count=0;
  311. for (int byte_nr =0; byte_nr<4; byte_nr++){
  312. for (int bit_nr =0; bit_nr<10; bit_nr++){
  313. bit_pattern_to_test.push_back( sample_buffer[ floor((bit_nr + byte_nr*10 + 0.5) *samples_per_bit) ] >=threshold ? 1 : 0); //1 if greater than threshold else 0
  314. // std::cout << bit_pattern_to_test[count] << " ";
  315. count++;
  316. } //10 bits filled
  317. // cout << endl;
  318. } //4 bytes filled
  319. //check that the stop and start bits are in the correct place
  320. if (bit_pattern_to_test[0]==0 && bit_pattern_to_test[9]==1 &&
  321. bit_pattern_to_test[10]==0 && bit_pattern_to_test[19]==1 &&
  322. bit_pattern_to_test[20]==0 && bit_pattern_to_test[29]==1 &&
  323. bit_pattern_to_test[30]==0 && bit_pattern_to_test[39]==1){
  324. //then
  325. // cout << "Timestamp found at entry " << transmission_start_in_samples << endl;
  326. //fill byte
  327. for (int jbyte_nr =0; jbyte_nr<4; jbyte_nr++){
  328. byte_value = 0;
  329. for (int jbit = 1; jbit< 9; jbit++){
  330. byte_value+=bit_pattern_to_test[jbit+ 10*jbyte_nr] * bit_multipliers[jbit];
  331. // cout << bit_pattern_to_test[jbit+ 10*jbyte_nr] << "*" << bit_multipliers[jbit] << "+";
  332. }
  333. // cout << "= "<< byte_value << " " << endl;;
  334. byte_data.push_back(byte_value);
  335. }
  336. // cout << endl;
  337. // %now calculate the result
  338. block_nr++;
  339. block_positions.push_back(transmission_start_in_samples);
  340. block_value=0;
  341. for (int jbyte = 0; jbyte< 4; jbyte++){
  342. block_value+=byte_data[jbyte]*byte_multipliers[jbyte];
  343. }
  344. block_data.push_back(block_value);
  345. if ( block_nr>1) {
  346. // printf("Block %i at %1.1i: %f ms Delta=%f ms\n", block_nr, block_positions[block_nr-1], block_data[block_nr-1],block_data[block_nr-1]- block_data[block_nr-2]);
  347. }
  348. else {
  349. // printf("Block %i at %1.1i: %f ms\n", block_nr, block_positions[block_nr-1], block_data[block_nr-1]);
  350. }
  351. // outfile << std::setprecision(11) << block_data[block_nr-1] << " " << block_positions[block_nr-1] << endl;
  352. }
  353. else{
  354. cout << "Bad Block at entry " << transmission_start_in_samples << endl;
  355. }
  356. //no matter what , clear the sample buffer and try again.
  357. sample_buffer.clear();
  358. sample_buffer.assign(floor(4*10*samples_per_bit+samples_per_50ms),0);
  359. }//end of beloww threshold for 50ms
  360. // cout << "fill tree" << endl;
  361. rootTree->Fill();
  362. } //end of frame loop
  363. outfile.close();
  364. return 1;
  365. }
  366. void histograms(int fargc, char ** argv){
  367. //open output root file
  368. rootfilename = Form("%s/root/%s.root",argv[1],argv[2]);
  369. rootFile = new TFile(rootfilename,"RECREATE");
  370. if ( rootFile->IsOpen() ) {printf("ROOT file opened successfully\n");
  371. }
  372. else { printf("ROOT file failed to open. \n");}
  373. rootTree = new TTree("t","HIT Data Root Tree");
  374. rootTree ->Branch("BPMbeamrecon_0", &BPMbeamrecon_0, "Position/D:Focus:Peak:Rsqr:Skew:Kurtosis:Sum:n_channels/I");
  375. rootTree ->Branch("BPMbeamrecon_1", &BPMbeamrecon_1, "Position/D:Focus:Peak:Rsqr:Skew:Kurtosis:Sum:n_channels/I");
  376. rootTree ->Branch("BPMbeamrecon_2", &BPMbeamrecon_2, "Position/D:Focus:Peak:Rsqr:Skew:Kurtosis:Sum:n_channels/I");
  377. rootTree ->Branch("BPMbeamrecon_3", &BPMbeamrecon_3, "Position/D:Focus:Peak:Rsqr:Skew:Kurtosis:Sum:n_channels/I");
  378. // rootTree ->Branch("board_0", &board_b[0], "channel_amp[320]/D:channel_position[320]:avg_position:avg_width:integratedsignalamp:max_channel_amp:maxchannel/I:nrChannels:board_number:sma_state");
  379. //rootTree ->Branch("board_1", &board_b[1], "channel_amp[320]/D:channel_position[320]:avg_position:avg_width:integratedsignalamp:max_channel_amp:maxchannel/I:nrChannels:board_number:sma_state");
  380. //rootTree ->Branch("board_2", &board_b[2], "channel_amp[320]/D:channel_position[320]:avg_position:avg_width:integratedsignalamp:max_channel_amp:maxchannel/I:nrChannels:board_number:sma_state");
  381. //rootTree ->Branch("board_3", &board_b[3], "channel_amp[320]/D:channel_position[320]:avg_position:avg_width:integratedsignalamp:max_channel_amp:maxchannel/I:nrChannels:board_number:sma_state");
  382. rootTree ->Branch("ethercat",&ethercat,"ic1/D:ic2");
  383. rootTree ->Branch("eventID",&eventID,"eventID/I");
  384. TH2D_b0_signal_vs_channel = new TH2D("TH2D_b0_signal_vs_channel","TH2D_b0_signal_vs_channel",320,0,320,1200,-2000,20000);
  385. TH2D_b1_signal_vs_channel = new TH2D("TH2D_b1_signal_vs_channel","TH2D_b1_signal_vs_channel",320,0,320,1200,-2000,20000);
  386. TH2D_b2_signal_vs_channel = new TH2D("TH2D_b2_signal_vs_channel","TH2D_b2_signal_vs_channel",320,0,320,1200,-2000,20000);
  387. TH2D_b3_signal_vs_channel = new TH2D("TH2D_b3_signal_vs_channel","TH2D_b3_signal_vs_channel",320,0,320,1200,-2000,20000);
  388. }
  389. //Function for average
  390. double avg ( vector<Channel> v )
  391. {
  392. double return_value = 0.0;
  393. int n = v.size();
  394. for ( int i=0; i < n; i++)
  395. {
  396. return_value += v[i].chnumber;
  397. }
  398. return ( return_value / double(n));
  399. }
  400. //****************End of average funtion****************
  401. //Function for variance
  402. double variance ( vector<Channel> v , double mean )
  403. {
  404. double sum = 0.0;
  405. double temp =0.0;
  406. double var =0.0;
  407. for ( int j =0; j < v.size(); j++)
  408. {
  409. temp = pow((v[j].chnumber - mean) , 2);
  410. sum += temp;
  411. }
  412. return var = sum/double(v.size() -2);
  413. }
  414. //****************End of variance funtion****************
  415. int set_background_v2(int start_frame, int max_frames){
  416. std::cout << "Setting background levels." << std::endl;
  417. for (int j = 0; j<320; j++){
  418. for (int k = 0; k<4; k++){
  419. board_b_bkg[k].channel_amp[j] = 0.;
  420. }
  421. }
  422. //Read first record to find board configuration
  423. Fullframe sampleframe;
  424. file.seekg(start_frame * sampleframe.sizeInFile() , std::ios::beg);
  425. if (sampleframe.read(&file) == 0) //read the next frame and catch if returns error
  426. {
  427. std::cerr << " ### Hitdata: First frame could not be read!" << std::endl;
  428. file.close(); //read error, finish!
  429. return 0;
  430. }
  431. //Read
  432. // file.seekg(sampleframe.sizeInFile(), std::ios::beg);
  433. for (int frame_nr = start_frame; frame_nr < max_frames; frame_nr++)
  434. {
  435. file.seekg(frame_nr * sampleframe.sizeInFile() , std::ios::beg);
  436. if (sampleframe.read(&file) == 0) //read the next frame and catch if returns error
  437. {
  438. std::cerr << " ### Hitdata: Frame " << frame_nr << " could not be read!" << std::endl;
  439. file.close(); //read error, finish!
  440. return 0;
  441. }
  442. for (int boardnumber = 0; boardnumber<4; boardnumber++){
  443. for (int j = 0; j<sampleframe.boards[boardnumber].nrChannels;j++){
  444. board_b_bkg[boardnumber].channel_amp[j] += sampleframe.boards[boardnumber].data[j] / double(max_frames);
  445. // std::cout << j << " " << board.channel_amp[j] << " " << dataptr->sensor_data[j] << std::endl;
  446. }
  447. }
  448. }
  449. std::cout << "Background set." << std::endl;
  450. return 1;
  451. }
  452. bpm_frame_v2 readboard(Fullframe frame, int boardnumber){
  453. bpm_frame_v2 board;
  454. board.integratedsignalamp = 0.;
  455. board.maxchannel_amp = 0.;
  456. board.nrChannels = frame.boards[boardnumber].nrChannels;
  457. board.board_number = boardnumber;
  458. board.sma_state = frame.boards[boardnumber].syncframe.sma_state;
  459. // file.seekg(boardnumber*sizeof(BufferData)+4*frame*sizeof(BufferData));
  460. //file.read ((char*)dataptr ,sizeof(BufferData));
  461. if (frame.boards[boardnumber].syncframe.device_nr==boardnumber){
  462. // cout << "nrChannels" << frame.boards[boardnumber].nrChannels << endl;
  463. for (int j = 0; j<frame.boards[boardnumber].nrChannels;j++){
  464. //subtract the background from the data
  465. board.channel_amp[j] = frame.boards[boardnumber].data[j] - board_b_bkg[boardnumber].channel_amp[j];
  466. // std::cout << j << " " << board.channel_amp[j] << " " << frame.boards[boardnumber].data[j] << std::endl;
  467. //sum the signal across channels
  468. board.integratedsignalamp += board.channel_amp[j];
  469. //find the peak channel
  470. if (board.channel_amp[j]> board.maxchannel_amp) {
  471. board.maxchannel = j;
  472. board.maxchannel_amp = board.channel_amp[j];
  473. // cout << maxchannel_b0 << " " <<maxchannelamp_b0 << endl;
  474. }
  475. //set the channel positions in mm
  476. board.channel_position[j] = 0.8*j + 0.2*(floor(j/64));
  477. //cout << board.channel_position[j] << " " << j << " " << (floor(j/64)) << endl;
  478. }
  479. }
  480. else std::cerr << "Error reading board data." << std::endl;
  481. return board;
  482. }
  483. beamRecon beamreconstruction(bpm_frame_v2 frametoanalyse, double threshold = 30.){
  484. ///////////////// linear regression using Integration by parts of gaussian function.
  485. beamRecon beam;
  486. double SumT, SumS, SumS2, SumST, SumT2, SumY, SumYS, SumYT, sigmaABC, muABC,p,c, b, b_den, b_num, SumYYP, SumYYM, MeanY;
  487. TMatrixD M1(3,3);
  488. TMatrixD M1inv(3,3);
  489. TVectorD ABC(3);
  490. TVectorD M2(3);
  491. vector<double> signal_list;
  492. vector<double> channel_list;
  493. channel_list.clear();
  494. SumY = 0.;
  495. SumS = 0.;
  496. SumT = 0.;
  497. SumS2 = 0.;
  498. SumST = 0.;
  499. SumT2 = 0.;
  500. SumYS = 0.;
  501. SumYT = 0.;
  502. b_den = 0.;
  503. b_num = 0.;
  504. b = 0.;
  505. p = 0.;
  506. c = 0.;
  507. SumYYM = 0.;
  508. SumYYP = 0.;
  509. MeanY = 0.;
  510. // const int array_length = sizeof(frametoanalyse.channel_amp)/sizeof(double);
  511. const int array_length = frametoanalyse.nrChannels ;
  512. vector<Channel> channel_reducedlist; //for anomaly detection
  513. vector<Channel> channel_reducedlistcopy; //for anomaly detection
  514. //hardcoded pixels to mask for this data set.
  515. const int arr_0[] = {139 };
  516. //const int arr_1[] = {};
  517. const int arr_2[] = { 11,12 };
  518. const int arr_3[] = { 1, 2, };
  519. vector<int> masked_channels[4];
  520. masked_channels[0].assign( arr_0, arr_0 + sizeof(arr_0) / sizeof(*arr_0) );
  521. // masked_channels[0].assign( arr_0, arr_0 + sizeof(arr_0) / sizeof(*arr_0) );
  522. masked_channels[2].assign( arr_2, arr_2 + sizeof(arr_2) / sizeof(*arr_2) );
  523. masked_channels[3].assign( arr_3, arr_3 + sizeof(arr_3) / sizeof(*arr_3) );
  524. Channel tmp;
  525. int temp_lastneighbour= -128;
  526. for (int i = 0; i< array_length; i++){
  527. if (count( masked_channels[frametoanalyse.board_number].begin(), masked_channels[frametoanalyse.board_number].end(), i)) continue; //check masked pixel list, and do not add it to the list of channels for analysis.
  528. if (frametoanalyse.channel_amp[i]>=threshold) {
  529. // cout << "ch: " << i << endl;
  530. // signal_list.push_back(frametoanalyse.channel_amp[i]);
  531. // channel_list.push_back(frametoanalyse.channel_position[i]);
  532. tmp.amplitude = frametoanalyse.channel_amp[i];
  533. tmp.position = frametoanalyse.channel_position[i];
  534. tmp.chnumber = i;
  535. tmp.last_neighbour = temp_lastneighbour;
  536. temp_lastneighbour = i ;
  537. channel_reducedlist.push_back(tmp);
  538. if (channel_reducedlist.size()>1){
  539. channel_reducedlist[channel_reducedlist.size() - 2].next_neighbour = i;
  540. }
  541. }
  542. }
  543. //anomaly detection
  544. //remove channels without neighbours.
  545. for (int i = 0; i<channel_reducedlist.size() ;i++){
  546. if (abs(channel_reducedlist[i].chnumber - channel_reducedlist[i].last_neighbour)<=1 || abs(channel_reducedlist[i].chnumber-channel_reducedlist[i].next_neighbour)<=1 ){
  547. channel_reducedlistcopy.push_back(channel_reducedlist[i]);
  548. // cout << channel_reducedlist[i].chnumber << " " << channel_reducedlist[i].last_neighbour << " " << channel_reducedlist[i].next_neighbour << endl;
  549. }
  550. }
  551. // channel_reducedlist.clear();//empty list to reuse it.
  552. double cluster_average;
  553. double cluster_variance;
  554. if(channel_reducedlistcopy.size()>2){
  555. cluster_average = avg(channel_reducedlistcopy);
  556. cluster_variance = variance(channel_reducedlistcopy, cluster_average);
  557. // cout << cluster_average << " " << cluster_variance << endl;
  558. }
  559. //include all channels +/- 2*variance of the main cluster
  560. for (int i = 0; i< array_length; i++){
  561. if (abs(i-cluster_average)<2*cluster_variance){
  562. signal_list.push_back(frametoanalyse.channel_amp[i]);
  563. channel_list.push_back(frametoanalyse.channel_position[i]);
  564. }
  565. }
  566. // sort(channel_reducedlist.begin(),channel_reducedlist.end(),CompareChannels);
  567. const int vector_length = channel_list.size();
  568. beam.n_channels = vector_length;
  569. beam.Sum = std::accumulate(signal_list.begin(), signal_list.end(),0);
  570. if (vector_length<=3) return beam;
  571. double S[vector_length];
  572. double T[vector_length];
  573. for(int k=0; k<vector_length;k++){
  574. if (k==0){
  575. S[k]=0.; T[k]=0.;
  576. }
  577. else{
  578. S[k] = S[k-1]+0.5*( signal_list[k] + signal_list[k-1] ) * ( channel_list[k] - channel_list[k-1] );
  579. T[k] = T[k-1]+0.5*( channel_list[k] * signal_list[k] + channel_list[k-1] * signal_list[k-1] ) * ( channel_list[k] - channel_list[k-1] );
  580. }
  581. // cout << S[k] << " " << T[k] << endl;
  582. SumS += S[k]; SumT += T[k];
  583. SumY += signal_list[k];
  584. SumS2 += S[k]*S[k]; SumST += S[k]*T[k]; SumT2 += T[k]*T[k];
  585. SumYS += signal_list[k]*S[k];
  586. SumYT += signal_list[k]*T[k];
  587. MeanY+=signal_list[k];
  588. }
  589. MeanY/=vector_length;
  590. M1(0,0) = SumT2; M1(0,1) = SumST; M1(0,2) = SumT; M1(1,0) = SumST; M1(1,1) = SumS2;
  591. M1(1,2) = SumS; M1(2,0) = SumT; M1(2,1) = SumS;
  592. M1(2,2) = vector_length;
  593. M2(0) = SumYT; M2(1) = SumYS; M2(2) = SumY;
  594. M1inv = M1.Invert(); ABC = M1inv * M2;
  595. //calculate b,p,c ---> y = b*exp(-p*(x-c)*(x-c))
  596. p = -ABC(0)/2.; c = -ABC(1)/ABC(0);
  597. for(int k=0; k<vector_length;k++){
  598. b_num += exp(-p*(channel_list[k]-c)*(channel_list[k]-c)) * signal_list[k];
  599. b_den += exp(-2*p*(channel_list[k]-c)*(channel_list[k]-c));
  600. }
  601. b = b_num/b_den;
  602. for(int k=0; k<vector_length;k++){
  603. SumYYM+= (signal_list[k]-MeanY)*(signal_list[k]-MeanY);
  604. SumYYP+= (b*exp(-p*(channel_list[k]-c)*(channel_list[k]-c)) - MeanY )*(b*exp(-p*(channel_list[k]-c)*( channel_list[k]-c)) - MeanY );
  605. }
  606. // cout << "R-squared = " << SumYYP/SumYYM << endl;
  607. beam.Position = -ABC(1)/ ABC(0);
  608. beam.Focus = 2.3548/sqrt(2*p);
  609. beam.Peak = b;
  610. beam.Rsqr = SumYYP/SumYYM;
  611. beam.Skew = gsl_stats_wskew_m_sd(&signal_list[0],1,&channel_list[0],1,vector_length,beam.Position,beam.Focus/2.3548); //skewness (symmetry)
  612. beam.Kurtosis = gsl_stats_wkurtosis_m_sd(&signal_list[0],1,&channel_list[0],1,vector_length,beam.Position,beam.Focus/2.3548); //excess kurtosis (well behaved tails)
  613. return beam;
  614. }