CbmRoot
Loading...
Searching...
No Matches
CbmRichRonchiAna.cxx
Go to the documentation of this file.
1/* Copyright (C) 2018-2019 GSI/JINR-LIT, Darmstadt/Dubna
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Semen Lebedev [committer] */
4
5#include "CbmRichRonchiAna.h"
6
7#include <boost/gil/extension/io/tiff.hpp>
8#include <boost/gil/gil_all.hpp>
9//#include <boost/gil/extension/io/tiff_dynamic_io.hpp>
10
11
12#include "CbmDrawHist.h"
13#include "TCanvas.h"
14#include "TEllipse.h"
15#include "TGeoArb8.h"
16#include "TGeoManager.h"
17#include "TH2D.h"
18#include "TH3D.h"
19#include "TLine.h"
20#include "TVector3.h"
21
22#include <iostream>
23#include <set>
24
25#include <math.h>
26
27using namespace boost::gil;
28using namespace std;
29
30// For Ubuntu one needs dev version of libtiff
31// sudo apt-get install libtiff-dev
32
34 : // constructor
35
36 // constant values
37 fPi(3.141592654)
38 , fRadiusMirror(3000000)
39 , // in microns !!! MIGHT HAVE TO BE CHANGED TO DISTANCE_MIRROR-POINTSOURCE IF IT IS NOT IN THE CENTER OF CURVATURE
40 fEdgeLengthCCD(13300)
41 , // in microns
42 fCcdPixelSize(13)
43 , // in microns
44 fPitchGrid(200)
45 , // in microns
46 fImageWidth(1024)
47 , // in pixels
48
49 // values to be measured first
50 fDistRulingCCD(21200)
51 , // in microns
52 fDistMirrorCCD(3118500)
53 , // in microns
54 fDistMirrorRuling(fDistMirrorCCD - fDistRulingCCD)
55 , // in microns
56 fOffsetCCDOptAxisX(0)
57 , //(7500), // in microns
58 fOffsetCCDOptAxisY(-58000)
59 , // in microns
60 fOffsetLEDOpticalAxisX(0)
61 , //(14500), //(13000), // in microns
62 fOffsetLEDOpticalAxisY(57000)
63 , // in microns
64 fCenterCcdX(0)
65 , // in pixels
66 fCenterCcdY(0) // in pixels
67{
68}
69
71
73{
74 // Initialization
75 vector<vector<double>> dataV;
76 vector<vector<double>> dataH;
77
78 if (fTiffFileNameV == "" || fTiffFileNameH == "") {
79 Fatal("CbmRichRonchiAna::Run:", "No FileNameV or FileNameH!");
80 }
81 else {
82 cout << "FileNameV: " << fTiffFileNameV << endl << "FileNameH: " << fTiffFileNameH << endl;
85 }
86
87 int width = dataV.size();
88 int height = dataV[0].size();
89
90
92 // initialisierung der histogramme: name, groesse usw
93 TH2D* hInitH =
94 new TH2D("hInitH", "hInitH;X [pixel];Y [pixel];Intensity", width, -.5, width - 0.5, height, -0.5, height - 0.5);
95 TH2D* hMeanIntensityH = new TH2D("hMeanIntensityH", "hMeanIntensityH;X [pixel];Y [pixel];Intensity", width, -.5,
96 width - 0.5, height, -0.5, height - 0.5);
97 TH2D* hPeakH =
98 new TH2D("hPeakH", "hPeakH;X [pixel];Y [pixel];Intensity", width, -.5, width - 0.5, height, -0.5, height - 0.5);
99 TH2D* hSmoothLinesH = new TH2D("hSmoothLinesH", "hSmoothLinesH;X [pixel];Y [pixel];Intensity", width, -.5,
100 width - 0.5, height, -0.5, height - 0.5);
101 TH2D* hLineSearchH = new TH2D("hLineSearchH", "hLineSearchH;X [pixel];Y [pixel];Intensity", width, -.5, width - 0.5,
102 height, -0.5, height - 0.5);
103
104 TH2D* hInitV =
105 new TH2D("hInitV", "hInitV;X [pixel];Y [pixel];Intensity", width, -.5, width - 0.5, height, -0.5, height - 0.5);
106 TH2D* hMeanIntensityV = new TH2D("hMeanIntensityV", "hMeanIntensityV;X [pixel];Y [pixel];Intensity", width, -.5,
107 width - 0.5, height, -0.5, height - 0.5);
108 TH2D* hPeakV =
109 new TH2D("hPeakV", "hPeakV;X [pixel];Y [pixel];Intensity", width, -.5, width - 0.5, height, -0.5, height - 0.5);
110 TH2D* hSmoothLinesV = new TH2D("hSmoothLinesV", "hSmoothLinesV;X [pixel];Y [pixel];Intensity", width, -.5,
111 width - 0.5, height, -0.5, height - 0.5);
112 TH2D* hLineSearchV = new TH2D("hLineSearchV", "hLineSearchV;X [pixel];Y [pixel];Intensity", width, -.5, width - 0.5,
113 height, -0.5, height - 0.5);
114
115 TH2D* hSuperpose = new TH2D("hSuperpose", "hSuperpose;X [pixel];Y [pixel];Intensity", width, -.5, width - 0.5, height,
116 -0.5, height - 0.5);
117
118 // vertical image
119 DoRotation(dataV);
120 FillH2WithVector(hInitV, dataV);
121 DoMeanIntensityY(dataV);
122 FillH2WithVector(hMeanIntensityV, dataV);
123 DoPeakFinderY(dataV);
124 FillH2WithVector(hPeakV, dataV);
125 DoSmoothLines(dataV);
126 FillH2WithVector(hSmoothLinesV, dataV);
127 DoLineSearch(dataV);
128 FillH2WithVector(hLineSearchV, dataV);
129 DoRotation(dataV);
130
131
132 // horizontal image
133 FillH2WithVector(hInitH, dataH);
134 DoMeanIntensityY(dataH);
135 FillH2WithVector(hMeanIntensityH, dataH);
136 DoPeakFinderY(dataH);
137 FillH2WithVector(hPeakH, dataH);
138 DoSmoothLines(dataH);
139 FillH2WithVector(hSmoothLinesH, dataH);
140 DoLineSearch(dataH);
141 FillH2WithVector(hLineSearchH, dataH);
142
143 // finding intersections
144 vector<CbmRichRonchiIntersectionData> intersections = DoIntersection(dataH, dataV);
145 vector<vector<double>> dataSup = DoSuperpose(dataH, dataV);
146 FillH2WithVector(hSuperpose, dataSup);
147
148 DoOrderLines(intersections, "x");
149 DoOrderLines(intersections, "y");
150
151 DoLocalNormal(intersections);
152 DoSphere(intersections);
153
154 // DrawGeomanager();
155
156 DoDeviation(intersections);
157
158 {
159 TCanvas* c = new TCanvas("ronchi_2d_horizontal", "ronchi_2d_horizontal", 1500, 1000);
160 c->Divide(3, 2);
161 c->cd(1);
162 DrawH2(hInitH);
163 c->cd(2);
164 DrawH2(hMeanIntensityH);
165 c->cd(3);
166 DrawH2(hPeakH);
167 c->cd(4);
168 DrawH2(hSmoothLinesH);
169 c->cd(5);
170 DrawH2(hLineSearchH);
171 }
172
173 {
174 TCanvas* c = new TCanvas("ronchi_2d_vertical", "ronchi_2d_vertical", 1500, 1000);
175 c->Divide(3, 2);
176 c->cd(1);
177 DrawH2(hInitV);
178 c->cd(2);
179 DrawH2(hMeanIntensityV);
180 c->cd(3);
181 DrawH2(hPeakV);
182 c->cd(4);
183 DrawH2(hSmoothLinesV);
184 c->cd(5);
185 DrawH2(hLineSearchV);
186 }
187
188 {
189 TCanvas* c2 = new TCanvas("ronchi_1d_slices_horizontal", "ronchi_1d_slices_horizontal", 1200, 600);
190 c2->Divide(2, 1);
191
192 TH1D* h1 = hInitH->ProjectionY("_py2", 250, 250);
193 TH1D* h2 = hInitH->ProjectionY("_py3", 300, 300);
194 TH1D* hM1 = hMeanIntensityH->ProjectionY("_pyM1", 250, 250);
195 TH1D* hM2 = hMeanIntensityH->ProjectionY("_pyM2", 300, 300);
196 TH1D* hP1 = hPeakH->ProjectionY("_pyP1", 250, 250);
197 TH1D* hP2 = hPeakH->ProjectionY("_pyP2", 300, 300);
198 c2->cd(1);
199 DrawH1({h1, hM1, hP1}, {"Init", "Mean", "Peak"});
200 c2->cd(2);
201 DrawH1({h2, hM2, hP2}, {"Init", "Mean", "Peak"});
202 }
203
204
205 {
206 TCanvas* c = new TCanvas("ronchi_2d_intersection", "ronchi_2d_intersection", 1000, 1000);
207 DrawH2(hSuperpose);
208 for (size_t i = 0; i < intersections.size(); i++) {
209 TEllipse* center = new TEllipse(intersections[i].fPixelX, intersections[i].fPixelY, 5);
210 center->Draw();
211 }
212 }
213
214 vector<int> colors = {kBlack, kGreen, kBlue, kRed, kYellow, kOrange, kCyan, kGray, kMagenta, kYellow + 2, kRed + 3};
215 {
216 TCanvas* c = new TCanvas("ronchi_2d_intersection_x", "ronchi_2d_intersection_x", 1000, 1000);
217 DrawH2(hSuperpose);
218 for (size_t i = 0; i < intersections.size(); i++) {
219 TEllipse* center = new TEllipse(intersections[i].fPixelX, intersections[i].fPixelY, 5);
220 center->SetFillColor(colors[intersections[i].fOrderedLineX % colors.size()]);
221 center->Draw();
222 }
223 }
224
225 {
226 TCanvas* c = new TCanvas("ronchi_2d_intersection_y", "ronchi_2d_intersection_y", 1000, 1000);
227 DrawH2(hSuperpose);
228 for (size_t i = 0; i < intersections.size(); i++) {
229 TEllipse* center = new TEllipse(intersections[i].fPixelX, intersections[i].fPixelY, 5);
230 center->SetFillColor(colors[intersections[i].fOrderedLineY % colors.size()]);
231 center->Draw();
232 }
233 }
234}
235
236vector<vector<double>> CbmRichRonchiAna::ReadTiffFile(const string& fileName)
237{
238 cout << "ReadTiffFile:" << fileName << endl;
239 vector<vector<double>> data;
240 //rgba8_image_t img;
241 rgb16_image_t img;
242 read_and_convert_image(fileName, img, boost::gil::tiff_tag());
243 // tiff_read_and_convert_image(fileName, img);
244 int height = img.height();
245 int width = img.width();
246
247 data.resize(width);
248
249 auto view = const_view(img);
250 for (int x = 0; x < width; ++x) {
251 auto it = view.col_begin(x);
252 data[x].resize(height);
253 for (int y = 0; y < height; ++y) {
254 int r = boost::gil::at_c<0>(it[y]);
255 //int g = boost::gil::at_c<1>(it[y]);
256 //int b = boost::gil::at_c<2>(it[y]);
257 //int a = boost::gil::at_c<3>(it[y]);
258 data[x][y] = r;
259 }
260 }
261 return data;
262}
263
264// rotating the image (actually flipping diagonally arranged corners)
265void CbmRichRonchiAna::DoRotation(vector<vector<double>>& data)
266{
267 int nX = data.size();
268 int nY = data[0].size();
269 for (int x = 0; x < nX; x++) {
270 for (int y = x + 1; y < nY; y++) {
271 swap(data[x][y], data[y][x]);
272 }
273 }
274}
275
276// drawing histogram
277void CbmRichRonchiAna::FillH2WithVector(TH2* hist, const vector<vector<double>>& data)
278{
279 int nX = data.size();
280 int nY = data[0].size();
281
282 for (int x = 0; x < nX; x++) {
283 for (int y = 0; y < nY; y++) {
284 if (data[x][y] != 0) {
285 hist->SetBinContent(x, y, data[x][y]);
286 }
287 }
288 }
289}
290
291// averaging intensity with neighboured values
292void CbmRichRonchiAna::DoMeanIntensityY(vector<vector<double>>& data)
293{
294 int nX = data.size();
295 int nY = data[0].size();
296
297 int halfAvWindow = 5; // number of neighbour pixels to each side to average over
298 double threshold =
299 6500; // threshold for average intensity to delete areas that are too dark (and so don't belong to mirror image)
300 vector<double> weightsX = {1., 0.75, 0.4, 0.2, 0.08, 0.04}; // weightings in dependence of distance of current pixel
301 vector<double> weightsY = {1., 0.75, 0.4, 0.2, 0.08, 0.04};
302
303 vector<vector<double>> dataNew(nX, std::vector<double>(nY, 0.));
304
305 for (int x = 0; x < nX; x++) {
306 for (int y = 0; y < nY; y++) {
307 double total = 0.;
308 double weightSum = 0.;
309 for (int xW = -halfAvWindow; xW <= halfAvWindow;
310 xW++) { // scanning window around current pixel to calculate average intensity
311 for (int yW = -halfAvWindow; yW <= halfAvWindow; yW++) {
312
313 int xWAbs = std::abs(xW);
314 int yWAbs = std::abs(yW);
315
316 double weightX =
317 (xWAbs < (int) weightsX.size())
318 ? weightsX[xWAbs]
319 : weightsX[weightsX.size()
320 - 1]; // if corresponding pixel is farther away than number of weights, take smallest ...
321 double weightY =
322 (yWAbs < (int) weightsY.size()) ? weightsY[yWAbs] : weightsY[weightsY.size() - 1]; // ... weight value
323
324 double weight = weightX * weightY;
325 weightSum += weight;
326 int indX = x + xW;
327 if (indX < 0) indX = 0; // preventing counting not existing pixels (beyond image)
328 if (indX >= nX) indX = nX - 1;
329 int indY = y + yW;
330 if (indY < 0) indY = 0;
331 if (indY >= nY) indY = nY - 1;
332
333 total += data[indX][indY] * weight;
334 }
335 }
336
337 dataNew[x][y] = total / weightSum; // averaged intensity
338 if (dataNew[x][y] <= threshold)
339 dataNew[x][y] = 0.; // deleting pixels that are too dark; to yield only data for mirror and not background
340 }
341 }
342 data = dataNew;
343}
344
345// getting a one dimensional line
346void CbmRichRonchiAna::DoPeakFinderY(vector<vector<double>>& data)
347{
348 int nX = data.size();
349 int nY = data[0].size();
350 int halfWindow = 5;
351 int samePeakCounterCut = 5;
352
353 vector<vector<double>> dataNew(nX, std::vector<double>(nY, 0.));
354
355 for (int x = 0; x < nX; x++) {
356 for (int y = halfWindow; y < nY - halfWindow; y++) {
357 bool isPeak = (data[x][y] > 0. && data[x][y] >= data[x][y - 1])
358 && (data[x][y] >= data[x][y + 1]); // comparing current pixel with direct neighbours in y direction
359 if (!isPeak) continue;
360
361 // check if it is a plateau
362 int samePeakCounter = 0;
363 for (int yS = y; yS < nY; yS++) {
364 if (data[x][y] == data[x][yS]) {
365 samePeakCounter++;
366 }
367 else {
368 break;
369 }
370 }
371 if (samePeakCounter >= samePeakCounterCut) { // if plateau, then jump beyond it
372 y = y + samePeakCounter + 1;
373 continue;
374 }
375
376 bool isBiggest = true;
377 for (int iW = -halfWindow; iW <= halfWindow; iW++) { // comparing current pixel with 'halfWindow' next neighbours
378 if (iW == 0) continue;
379 if (data[x][y + iW] > data[x][y]) {
380 isBiggest = false;
381 break;
382 }
383 }
384 bool hasNeighbourPeak =
385 (dataNew[x][y - 2] > 0. || dataNew[x][y - 1] > 0. || dataNew[x][y + 1] > 0. || dataNew[x][y + 2] > 0.);
386
387 if (isBiggest && isPeak && !hasNeighbourPeak)
388 dataNew[x][y] =
389 data[x][y]; // set value if is the biggest of 'halfWindow' neighbours and has no neighboured peak
390 }
391 }
392 data = dataNew;
393}
394
395// smoothing lines by calculating mean position in y
396void CbmRichRonchiAna::DoSmoothLines(vector<vector<double>>& data)
397{
398 int meanHalfLength = 8;
399 int meanHalfHeight = 3;
400 int nX = data.size();
401 int nY = data[0].size();
402
403 vector<vector<double>> dataNew(nX, std::vector<double>(nY, 0.));
404
405 for (int x = meanHalfLength; x < nX - meanHalfLength; x++) { // scanning whole image (except small border)
406 for (int y = meanHalfHeight; y < nY - meanHalfHeight; y++) {
407 if (data[x][y] == 0.) continue;
408 double sumY = 0.;
409 int counter = 0;
410 for (
411 int x2 = -meanHalfLength; x2 <= meanHalfLength;
412 x2++) { // scanning small window around current pixel and summing up positions in y of current and neighboured pixels
413 for (int y2 = -meanHalfHeight; y2 <= meanHalfHeight; y2++) {
414 if (data[x + x2][y + y2] > 0) {
415 sumY += y + y2;
416 counter++;
417 }
418 }
419 }
420 int newY = (int) sumY / counter; // average y-value of pixel
421 dataNew[x][newY] = data[x][y];
422 }
423 }
424
425 data = dataNew;
426}
427
428void CbmRichRonchiAna::DoLineSearch(vector<vector<double>>& data)
429{
430 int nX = data.size();
431 int nY = data[0].size();
432
433 int missingCounterCut = 15;
434 int missingCounterTotalCut = 25;
435 int halfWindowY = 2;
436
437 vector<vector<double>> dataNew(nX, std::vector<double>(nY, 0.));
438 double curIndex = 0.; // why double?
439
440 for (int x = 0; x < nX; x++) { // scanning whole image
441 for (int y = 0; y < nY; y++) {
442 if (data[x][y] > 0. && dataNew[x][y] == 0.) { // if this line pixel is not filled yet in 'dataNew'
443 curIndex++; // line index
444 dataNew[x][y] = curIndex; // found line is indexed
445 int missingCounterTotal = 0.;
446 int missingCounter = 0.;
447 int curY = y;
448 for (int x1 = x + 1; x1 < nX; x1++) { // drawing line in x; values are not intensity but line index
449 bool isFound = false;
450 for (int y1 = -halfWindowY; y1 <= halfWindowY; y1++) {
451 if (data[x1][curY + y1] > 0.
452 && dataNew[x1][curY + y1] == 0.) { // if pixel of line in next column is found ...
453 dataNew[x1][curY + y1] = curIndex; // ... fill current pixel with line index
454 curY += y1;
455 isFound = true;
456 break;
457 }
458 }
459 if (
460 !isFound) { // to prevent indexing lines with wrong index (e.g. if gap is too big and next found line would not be continuation of current line)
461 missingCounterTotal++;
462 missingCounter++;
463 }
464 else {
465 missingCounter = 0;
466 }
467 if (missingCounterTotal >= missingCounterTotalCut || missingCounter >= missingCounterCut) break;
468 }
469 }
470 }
471 }
472 cout << "curIndex:" << curIndex << endl;
473 data = dataNew;
474}
475
476
477// finding intersections
478vector<CbmRichRonchiIntersectionData> CbmRichRonchiAna::DoIntersection(vector<vector<double>>& dataH,
479 const vector<vector<double>>& dataV)
480{
481 int nX = dataV.size();
482 int nY = dataV[0].size();
483
484 vector<CbmRichRonchiIntersectionData> intersections;
485
486 for (int x = 0; x < nX; x++) {
487 for (int y = 0; y < nY; y++) {
488 if (dataH[x][y] > 0.
489 && dataV[x][y]
490 > 0.) { // filling vector with data if both vertical and horizontal image have data greater ZERO here
492 data.fPixelX = x;
493 data.fPixelY = y;
494 data.fLineY =
495 dataH[x][y]; // 'data[x][y]' contains the line index now, not intensity (see prev. function 'DoLineSearch')
496 data.fLineX = dataV[x][y];
497 intersections.push_back(data);
498 }
499 }
500 }
501 cout << "intersections.size(): " << intersections.size() << endl;
502
503 // remove close intersections
504 set<int> removeSet;
505 for (size_t i1 = 0; i1 < intersections.size(); i1++) {
506 for (size_t i2 = i1 + 1; i2 < intersections.size(); i2++) {
507 double dX = intersections[i1].fPixelX
508 - intersections[i2].fPixelX; // distances in x and y of current observed intersections
509 double dY = intersections[i1].fPixelY - intersections[i2].fPixelY;
510 double dist = std::sqrt(dX * dX + dY * dY);
511 if (dist <= 10.) { // if their distance is below a certain threshold, insert content to 'removeSet'
512 // cout << i1 << " " << i2 << " " << intersections[i1].fPixelX << " " << intersections[i1].fPixelY << " "
513 // << intersections[i2].fPixelX << " " << intersections[i2].fPixelY << " " << dist << endl;
514 removeSet.insert(i2); // set of values from one of both close intersections is stored in 'removeSet'
515 }
516 }
517 }
518
519 set<int>::iterator it;
520 for (it = removeSet.begin(); it != removeSet.end(); ++it) {
521 swap(intersections[*it],
522 intersections
523 [intersections.size()
524 - 1]); // move one of both double counted intersections to the end of vector and remove these afterwards
525 intersections.resize(intersections.size() - 1);
526 }
527 cout << "removeSet.size():" << removeSet.size() << " intersections.size(): " << intersections.size() << endl;
528
529 return intersections;
530}
531
532// superposing horizontal and vertical image
533vector<vector<double>> CbmRichRonchiAna::DoSuperpose(const vector<vector<double>>& dataH,
534 const vector<vector<double>>& dataV)
535{
536 int nX = dataV.size();
537 int nY = dataV[0].size();
538
539 vector<vector<double>> dataSup(nX, std::vector<double>(nY, 0.));
540 for (int x = 0; x < nX; x++) {
541 for (int y = 0; y < nY; y++) {
542 dataSup[x][y] = dataH[x][y] + dataV[x][y]; // data of horizontal and vertical image are being summed
543 }
544 }
545 return dataSup;
546}
547
548void CbmRichRonchiAna::DoOrderLines(vector<CbmRichRonchiIntersectionData>& intersections, const string& option)
549{
550 map<int, CbmRichRonchiLineData> linesMap; // lineIndex to lineData
551 vector<CbmRichRonchiLineData> lines;
552
553 // indexing intersection points with either 'x' or 'y' and assign values from class 'Cbm...LineData' and storing in map
554 for (auto const& curIntr : intersections) {
555 int lineInd =
556 (option == "x") ? curIntr.fLineX : curIntr.fLineY; // fLineX/Y is the line index, set in 'DoLineSearch'
557 linesMap[lineInd].fMeanPrimary +=
558 (option == "x") ? curIntr.fPixelX : curIntr.fPixelY; // fPixelX/Y are the x/y-values, set in 'DoIntersection')
559 linesMap[lineInd].fMeanSecondary += (option == "x") ? curIntr.fPixelY : curIntr.fPixelX;
560 linesMap[lineInd].fNofPoints++; //fNofPoints is never set back?
561 linesMap[lineInd].fLineInd = lineInd;
562 }
563
564 for (auto& kv : linesMap) {
565 kv.second.fMeanPrimary = (double) kv.second.fMeanPrimary
566 / kv.second.fNofPoints; // calculating mean values of x and y positions to enable sorting
567 kv.second.fMeanSecondary = (double) kv.second.fMeanSecondary / kv.second.fNofPoints;
568 lines.push_back(kv.second);
569 //cout << kv.first << " mean:" << kv.second.fMean << " nPoints:" << kv.second.fNofPoints << " lineInd:" << kv.second.fLineInd<< endl;
570 }
571
572 sort(lines.begin(), lines.end(), [](const CbmRichRonchiLineData& lhs, const CbmRichRonchiLineData& rhs) {
573 return lhs.fMeanPrimary < rhs.fMeanPrimary;
574 });
575
576 // find first line with many points
577 int lineIndMany = 0;
578 for (size_t i = 0; i < lines.size() - 1; i++) {
579 if (lines[i].fNofPoints >= 35) {
580 lineIndMany = i; //dataSup
581 break;
582 }
583 }
584
585 // for the left edges we need to go other direction
586 for (int i = lineIndMany - 1; i >= 1; i--) {
587 if (AreTwoSegmentsSameLine(&lines[i], &lines[i - 1])) {
588 UpdateIntersectionLineInd(intersections, &lines[i], &lines[i - 1], option);
589 i--; // skip next line
590 }
591 }
592
593 for (size_t i = lineIndMany; i < lines.size() - 1; i++) {
594 if (AreTwoSegmentsSameLine(&lines[i], &lines[i + 1])) {
595 UpdateIntersectionLineInd(intersections, &lines[i], &lines[i + 1], option);
596 i++; // skip next line
597 }
598 }
599
600 // now we need to assign numbers in correct order
601 int newLineIndex = 1;
602 set<int> duplicateLines; // duplicates can occure for line segments
603 for (auto& curLine : lines) {
604 if (duplicateLines.find(curLine.fLineInd) != duplicateLines.end()) continue;
605 duplicateLines.insert(curLine.fLineInd);
606 for (auto& curIntr : intersections) {
607 if (option == "x" && curIntr.fLineX == curLine.fLineInd) curIntr.fOrderedLineX = newLineIndex;
608 if (option == "y" && curIntr.fLineY == curLine.fLineInd) curIntr.fOrderedLineY = newLineIndex;
609 }
610 newLineIndex++;
611 }
612 cout << "newLineIndex:" << newLineIndex << endl;
613}
614
616{
617 int nofPointsMergeCut = 25;
618 double pixelDistMergeCut = 200.;
619 double pixelDiffMergeCut = 15.;
620
621 return (line1->fNofPoints < nofPointsMergeCut && line2->fNofPoints < nofPointsMergeCut
622 && abs(line1->fMeanSecondary - line2->fMeanSecondary) > pixelDistMergeCut
623 && abs(line1->fMeanPrimary - line2->fMeanPrimary) <= pixelDiffMergeCut);
624}
625
626void CbmRichRonchiAna::UpdateIntersectionLineInd(vector<CbmRichRonchiIntersectionData>& intersections,
628 const string& option)
629{
630 for (auto& curIntr : intersections) {
631 if (option == "x" && curIntr.fLineX == line2->fLineInd) curIntr.fLineX = line1->fLineInd;
632 if (option == "y" && curIntr.fLineY == line2->fLineInd) curIntr.fLineY = line1->fLineInd;
633 }
634 line2->fLineInd = line1->fLineInd;
635}
636
637void CbmRichRonchiAna::DoLocalNormal(vector<CbmRichRonchiIntersectionData>& data)
638{
639 int xMin = 1000;
640 int xMax = -1000;
641 int yMin = 1000;
642 int yMax = -1000;
643
644 // extracting minimal and maximum x and y values
645 for (size_t i = 0; i < data.size(); i++) {
646 if (data[i].fOrderedLineX < xMin) xMin = data[i].fOrderedLineX;
647 if (data[i].fOrderedLineX > xMax) xMax = data[i].fOrderedLineX;
648 if (data[i].fOrderedLineY < yMin) yMin = data[i].fOrderedLineY;
649 if (data[i].fOrderedLineY > yMax) yMax = data[i].fOrderedLineY;
650 }
651
652 int centerLineX = (xMax - xMin) / 2; // horizontal and vertical
653 int centerLineY = (yMax - yMin) / 2;
654
655 fCenterCcdX = -1;
656 fCenterCcdY = -1;
657 // defining reference point to calculate slopes
658 for (size_t i = 0; i < data.size(); i++) {
659 if (fCenterCcdX == -1 && data[i].fOrderedLineX == centerLineX) {
660 fCenterCcdX = data[i].fPixelX + 20; // correction parameter in X
661 }
662 if (fCenterCcdY == -1 && data[i].fOrderedLineY == centerLineY) {
663 fCenterCcdY = data[i].fPixelY + 20; // correction parameter in Y
664 }
665 }
666
667 cout << "xMin:" << xMin << " xMax:" << xMax << " yMin:" << yMin << " yMax:" << yMax << endl;
668 cout << "centerLineX:" << centerLineX << " centerLineY:" << centerLineY << endl;
669 cout << "fCenterCcdX:" << fCenterCcdX << " fCenterCcdY:" << fCenterCcdY << endl;
670
671 for (size_t i = 0; i < data.size(); i++) {
672 // X and Y positions on CCD in microns
673 int ccdX = (data[i].fPixelX - fCenterCcdX) * fCcdPixelSize;
674 int ccdY = (data[i].fPixelY - fCenterCcdY) * fCcdPixelSize;
675
676 data[i].fCcdV.SetXYZ(ccdX, ccdY, 0.);
677
678 // XYZ positions on ronchi ruling in microns
679 data[i].fRulingV.SetXYZ((data[i].fOrderedLineX - centerLineX) * fPitchGrid,
680 (data[i].fOrderedLineY - centerLineY) * fPitchGrid, fDistRulingCCD);
681
682 // slopes in X and Y direction of reflected beam
683 double sRefX =
684 -(data[i].fRulingV.X() - data[i].fCcdV.X()) / fDistRulingCCD; // 'minus' because Ruling is behind CoC
685 double sRefY = -(data[i].fRulingV.Y() - data[i].fCcdV.Y()) / fDistRulingCCD;
686
687 // extrapolating X and Y positions on mirror in microns
688 data[i].fMirrorV.SetXYZ(ccdX + (sRefX * fDistMirrorRuling), ccdY + (sRefY * fDistMirrorRuling), fDistMirrorCCD);
689
690 //cout << "fMirrorV_xyz = [" << data[i].fMirrorV.X() << ", " << data[i].fMirrorV.Y() << ", " << data[i].fMirrorV.Z() << "]" << endl;
691
692 // calculating angles between optical axis of mirror and incident resp. reflected beam
693 double mirrorCenterDist = sqrt(pow(data[i].fMirrorV.X() + fOffsetCCDOptAxisX, 2)
694 + pow(data[i].fMirrorV.Y() + fOffsetCCDOptAxisY,
695 2)); // distance from mirrors center in microns
696 double sagitta =
697 fRadiusMirror - sqrt(pow(fRadiusMirror, 2) - pow(mirrorCenterDist, 2)); // to calculate cathetus length
698 double cathetus = fRadiusMirror - sagitta; // if point source is in the center of curvature !!
699
700 double angleIncX =
701 atan(data[i].fMirrorV.X()
702 / cathetus); // if point source is in the center of curvature (CoC), otherwise add offset in Z direction !!
703 double angleIncY = atan((data[i].fMirrorV.Y() - sqrt(fOffsetLEDOpticalAxisY * fOffsetLEDOpticalAxisY)
705 / cathetus);
706 double angleRefX = atan(sRefX);
707 double angleRefY = atan(sRefY);
708 data[i].fNormalRadX = ((angleIncX + angleRefX) / 2.0);
709 data[i].fNormalRadY = ((angleIncY + angleRefY) / 2.0);
710
711 // data[i].fNormalX = tan(angleNormalX);
712 // data[i].fNormalY = tan(angleNormalY);
713
714 double segmentSize = 3500; // half segment size; for the moment just assume that all segments have the same size
715 data[i].fTL.SetXYZ(data[i].fMirrorV.X() - segmentSize, data[i].fMirrorV.Y() + segmentSize, data[i].fMirrorV.Z());
716 RotatePointImpl(&data[i].fTL, &data[i].fTLRot, data[i].fNormalRadX, data[i].fNormalRadY, &data[i].fMirrorV);
717
718 data[i].fTR.SetXYZ(data[i].fMirrorV.X() + segmentSize, data[i].fMirrorV.Y() + segmentSize, data[i].fMirrorV.Z());
719 RotatePointImpl(&data[i].fTR, &data[i].fTRRot, data[i].fNormalRadX, data[i].fNormalRadY, &data[i].fMirrorV);
720
721 data[i].fBL.SetXYZ(data[i].fMirrorV.X() - segmentSize, data[i].fMirrorV.Y() - segmentSize, data[i].fMirrorV.Z());
722 RotatePointImpl(&data[i].fBL, &data[i].fBLRot, data[i].fNormalRadX, data[i].fNormalRadY, &data[i].fMirrorV);
723
724 data[i].fBR.SetXYZ(data[i].fMirrorV.X() + segmentSize, data[i].fMirrorV.Y() - segmentSize, data[i].fMirrorV.Z());
725 RotatePointImpl(&data[i].fBR, &data[i].fBRRot, data[i].fNormalRadX, data[i].fNormalRadY, &data[i].fMirrorV);
726 }
727
728 /*// correction value to ZERO reference point at center of mirror
729 for (int i = 0; i < data.size(); i++) {
730 if (data[i].fOrderedLineX == centerLineX && data[i].fOrderedLineY == centerLineY) {
731 double radius = sqrt(pow(data[i].fTL.X(),2) + pow(data[i].fTL.Y(),2));
732 double sagitta2 = fRadiusMirror - sqrt(pow(fRadiusMirror,2) - pow(radius,2));
733 fCorrection = (double)(data[i].fTL.Z() - sagitta2 - fRadiusMirror);
734 cout << "fTL.Z_Sagitta = " << fRadiusMirror - data[i].fTL.Z() << ", sagitta2 = " << sagitta2 << endl;
735 cout << "CORRECTION = " << (double)fCorrection << endl << endl;
736 }
737 }*/
738
739 {
740 DrawXYMum(data);
741 }
742
743 {
744 TCanvas* c = new TCanvas("ronchi_xz_mum_lineY20", "ronchi_xz_mum_lineY20", 1800, 900);
745 c->Divide(2, 1);
746 c->cd(1);
747 DrawXZProjection(data, 20, 1.);
748 c->cd(2);
749 DrawXZProjection(data, 20, 0.025);
750 }
751
752 {
753 DrawMirrorSegments(data, 20, 20);
754 }
755}
756
757// constructing spherical surface
758void CbmRichRonchiAna::DoSphere(vector<CbmRichRonchiIntersectionData>& data)
759{
760 int xMin = 1000;
761 int xMax = -1000;
762 int yMin = 1000;
763 int yMax = -1000;
764
765 // extracting minimal and maximum x and y values
766 for (size_t i = 0; i < data.size(); i++) {
767 if (data[i].fOrderedLineX < xMin) xMin = data[i].fOrderedLineX;
768 if (data[i].fOrderedLineX > xMax) xMax = data[i].fOrderedLineX;
769 if (data[i].fOrderedLineY < yMin) yMin = data[i].fOrderedLineY;
770 if (data[i].fOrderedLineY > yMax) yMax = data[i].fOrderedLineY;
771 }
772
773 // assigning segments to their position on mirror plane (according to their values after rotation, before sphere construction)
774 // in X direction
775 for (int iX = xMin; iX <= xMax; iX++) {
776 int iPX = GetMinIndexForLineX(iX,
777 data); // 'GetMinIndex..' to get index of 'data' for current intersection
778 int iPX0 = GetMinIndexForLineX(iX - 1, data);
779 if (iPX < 0 || iPX0 < 0) continue;
780 double shiftX = data[iPX0].fTRRot.X() - data[iPX].fTLRot.X(); // horizontal distance between neighboured corners
781 data[iPX].fTLRot.SetXYZ(data[iPX].fTLRot.X() + shiftX, data[iPX].fTLRot.Y(), data[iPX].fTLRot.Z());
782 data[iPX].fTRRot.SetXYZ(data[iPX].fTRRot.X() + shiftX, data[iPX].fTRRot.Y(), data[iPX].fTRRot.Z());
783 data[iPX].fBLRot.SetXYZ(data[iPX].fBLRot.X() + shiftX, data[iPX].fBLRot.Y(), data[iPX].fBLRot.Z());
784 data[iPX].fBRRot.SetXYZ(data[iPX].fBRRot.X() + shiftX, data[iPX].fBRRot.Y(), data[iPX].fBRRot.Z());
785 }
786
787 // in Y direction
788 for (int iY = yMin; iY <= yMax; iY++) {
789 int iPY = GetMinIndexForLineY(iY, data);
790 int iPY0 = GetMinIndexForLineY(iY - 1, data);
791 if (iPY < 0 || iPY0 < 0) continue;
792 double shiftY = data[iPY0].fTRRot.Y() - data[iPY].fBRRot.Y();
793 data[iPY].fTLRot.SetXYZ(data[iPY].fTLRot.X(), data[iPY].fTLRot.Y() + shiftY, data[iPY].fTLRot.Z());
794 data[iPY].fTRRot.SetXYZ(data[iPY].fTRRot.X(), data[iPY].fTRRot.Y() + shiftY, data[iPY].fTRRot.Z());
795 data[iPY].fBLRot.SetXYZ(data[iPY].fBLRot.X(), data[iPY].fBLRot.Y() + shiftY, data[iPY].fBLRot.Z());
796 data[iPY].fBRRot.SetXYZ(data[iPY].fBRRot.X(), data[iPY].fBRRot.Y() + shiftY, data[iPY].fBRRot.Z());
797 }
798
799 DrawMirrorSegments(data, 32, 32);
800
801 // inserting X and Y shifts in f..Sph vectors
802 for (int iX = xMin; iX <= xMax; iX++) {
803 int iPX = GetMinIndexForLineX(iX, data);
804 if (iPX < 0) continue;
805 for (int iY = yMin; iY <= yMax; iY++) {
806 int iC = GetIndexForLineXLineY(iX, iY, data);
807 if (iC < 0) continue;
808 int iPY = GetMinIndexForLineY(iY, data);
809 if (iPY < 0) continue;
810
811 double shiftX = data[iPX].fTLRot.X() - data[iC].fTLRot.X();
812 double shiftY = data[iPY].fTLRot.Y() - data[iC].fTLRot.Y();
813
814 data[iC].fTLSph.SetXYZ(data[iC].fTLRot.X() + shiftX, data[iC].fTLRot.Y() + shiftY, data[iC].fTLRot.Z());
815 data[iC].fTRSph.SetXYZ(data[iC].fTRRot.X() + shiftX, data[iC].fTRRot.Y() + shiftY, data[iC].fTRRot.Z());
816 data[iC].fBLSph.SetXYZ(data[iC].fBLRot.X() + shiftX, data[iC].fBLRot.Y() + shiftY, data[iC].fBLRot.Z());
817 data[iC].fBRSph.SetXYZ(data[iC].fBRRot.X() + shiftX, data[iC].fBRRot.Y() + shiftY, data[iC].fBRRot.Z());
818 }
819 }
820
821 // align Z positions in Y
822 for (int iX = xMin; iX <= xMax; iX++) {
823 for (int iY = yMin; iY <= yMax; iY++) {
824 int iC = GetIndexForLineXLineY(iX, iY, data);
825 //int iPX = GetIndexForLineXLineY(iX - 1, iY, data);
826 int iPY = GetIndexForLineXLineY(iX, iY - 1, data);
827 if (iPY < 0) iPY = GetIndexForLineXLineY(iX, iY - 2, data); // one missing measurement is allowed
828 if (iC < 0) continue;
829
830 if (iPY >= 0) {
831 //double shiftZAdd = (iPX > 0)?data[iPX].fTRSph.Z() - data[iC].fTLSph.Z():0;
832 double shiftZ = data[iPY].fTLSph.Z() - data[iC].fBLSph.Z();
833 data[iC].fTLSph.SetZ(data[iC].fTLSph.Z() + shiftZ);
834 data[iC].fTRSph.SetZ(data[iC].fTRSph.Z() + shiftZ);
835 data[iC].fBLSph.SetZ(data[iC].fBLSph.Z() + shiftZ);
836 data[iC].fBRSph.SetZ(data[iC].fBRSph.Z() + shiftZ);
837 }
838 }
839 }
840
841 // align Z positions in X
842 for (int iX = xMin; iX <= xMax; iX++) {
843 int iPX = GetIndexForLineXLineY(iX, 30, data);
844 int iPX0 = GetIndexForLineXLineY(iX - 1, 30, data);
845 if (iPX0 < 0) iPX0 = GetIndexForLineXLineY(iX - 2, 30, data); // one missing measurement is allowed
846 if (iPX < 0 || iPX0 < 0) continue;
847 double shiftZ = data[iPX0].fTRSph.Z() - data[iPX].fTLSph.Z();
848 for (int iY = yMin; iY <= yMax; iY++) {
849 int iC = GetIndexForLineXLineY(iX, iY, data);
850 data[iC].fTLSph.SetZ(data[iC].fTLSph.Z() + shiftZ);
851 data[iC].fTRSph.SetZ(data[iC].fTRSph.Z() + shiftZ);
852 data[iC].fBLSph.SetZ(data[iC].fBLSph.Z() + shiftZ);
853 data[iC].fBRSph.SetZ(data[iC].fBRSph.Z() + shiftZ);
854 }
855 }
856
857 {
859 DrawMirrorSegmentsSphere(data, 21, 21);
860 DrawMirrorSegmentsSphere(data, 30, 30);
861 DrawMirrorSegmentsSphere(data, 40, 40);
862 }
863}
864
865int CbmRichRonchiAna::GetMinIndexForLineX(int lineX, vector<CbmRichRonchiIntersectionData>& data)
866{
867 int ind = -1;
868 for (int iY = 0; iY < 2000; iY++) {
869 ind = GetIndexForLineXLineY(lineX, iY, data);
870 if (ind != -1) return ind;
871 }
872 return ind;
873}
874
875
876int CbmRichRonchiAna::GetMinIndexForLineY(int lineY, vector<CbmRichRonchiIntersectionData>& data)
877{
878 int ind = -1;
879 for (int iX = 0; iX < 2000; iX++) {
880 ind = GetIndexForLineXLineY(iX, lineY, data);
881 if (ind != -1) return ind;
882 }
883 return ind;
884}
885
886
887int CbmRichRonchiAna::GetIndexForLineXLineY(int lineX, int lineY, vector<CbmRichRonchiIntersectionData>& data)
888{
889 for (size_t i = 0; i < data.size(); i++) {
890 if (data[i].fOrderedLineX == lineX && data[i].fOrderedLineY == lineY)
891 return i; // returns 'data' index of currently investigated intersection
892 }
893 return -1;
894}
895
896void CbmRichRonchiAna::DoDeviation(vector<CbmRichRonchiIntersectionData>& data)
897{
898 double mirX = 0.;
899 double mirY = 0.;
900 double mirZ = 0.;
901
902 int correctionValue = 11800;
903 int threshold = 0; //-50000;
904
905 for (size_t i = 0; i < data.size(); i++) {
906 double meanX = 0.25 * (data[i].fTLSph.X() + data[i].fTRSph.X() + data[i].fBLSph.X() + data[i].fBRSph.X());
907 double meanY = 0.25 * (data[i].fTLSph.Y() + data[i].fTRSph.Y() + data[i].fBLSph.Y() + data[i].fBRSph.Y());
908 double meanZ = 0.25 * (data[i].fTLSph.Z() + data[i].fTRSph.Z() + data[i].fBLSph.Z() + data[i].fBRSph.Z());
909 double dX = mirX - meanX;
910 double dY = mirY - meanY;
911 double dZ = mirZ - meanZ;
912 double d = sqrt(dZ * dZ); //sqrt(dX*dX + dY*dY + dZ*dZ);
913
914 // cout << "dX/dY/dZ = " << dX << "/" << dY << "/" << dZ << endl;
915 // cout << "d = " << d << endl;
916
917 //double mirrorCenterDist = sqrt(pow(data[i].fMirrorV.X(), 2) + pow(data[i].fMirrorV.Y(), 2)); // distance from mirrors center in microns
918 double mirrorCenterDist = sqrt(pow(meanX, 2) + pow(meanY, 2)); // distance from mirrors center in microns
919 double sagitta = fRadiusMirror - sqrt(pow(fRadiusMirror, 2) - pow(mirrorCenterDist, 2));
920 //data[i].fDeviation = d - fRadiusMirror + sagitta;
921
922 data[i].fDeviation = d - (fDistMirrorCCD - sagitta); // (Ist-Soll) !! change to fDistMIrrorCCD
923 }
924 TH2D* hMirrorHeight =
925 new TH2D("hMirrorDeviation", "hMirrorDeviation;index X;index Y;Deviation [mum]", 60, -0.5, 59.5, 60, -0.5, 59.5);
926 TCanvas* c = new TCanvas("mirror_deviation", "mirror_deviation", 1000, 1000);
927 for (size_t i = 0; i < data.size(); i++) {
928 if (data[i].fDeviation > threshold) {
929 hMirrorHeight->SetBinContent(data[i].fOrderedLineX, data[i].fOrderedLineY, data[i].fDeviation - correctionValue);
930 }
931 }
932 DrawH2(hMirrorHeight);
933}
934
935void CbmRichRonchiAna::DrawXYMum(vector<CbmRichRonchiIntersectionData>& data)
936{
937 vector<int> colors = {kBlack, kGreen, kBlue, kRed, kYellow, kOrange, kCyan, kGray, kMagenta, kYellow + 2, kRed + 3};
938 TH2D* hCcdXY = new TH2D("hCcdXY", "hCcdXY;CCD_X [mum];CCD_Y [mum];", 1, -7000, 7000, 1, -7000, 7000);
939 TH2D* hRulingXY = new TH2D("hRulingXY", "hRulingXY;Ruling_X [mum];Ruling_Y [mum];", 1, -7000, 7000, 1, -7000, 7000);
940 TH2D* hMirrorXY =
941 new TH2D("hMirrorXY", "hMirrorXY;Mirror_X [mum];Mirror_Y [mum];", 1, -250000, 250000, 1, -250000, 250000);
942 TCanvas* c = new TCanvas("ronchi_xy_mum", "ronchi_xy_mum", 1800, 600);
943 c->Divide(3, 1);
944 c->cd(1);
945 DrawH2(hCcdXY);
946 gPad->SetRightMargin(0.10);
947 for (size_t i = 0; i < data.size(); i++) {
948 TEllipse* center = new TEllipse(data[i].fCcdV.X(), data[i].fCcdV.Y(), 50);
949 center->SetFillColor(colors[data[i].fOrderedLineX % colors.size()]);
950 center->Draw();
951 }
952
953 c->cd(2);
954 DrawH2(hRulingXY);
955 gPad->SetRightMargin(0.10);
956 for (size_t i = 0; i < data.size(); i++) {
957 TEllipse* center = new TEllipse(data[i].fRulingV.X(), data[i].fRulingV.Y(), 50);
958 center->SetFillColor(colors[data[i].fOrderedLineX % colors.size()]);
959 center->Draw();
960 }
961
962 c->cd(3);
963 DrawH2(hMirrorXY);
964 gPad->SetRightMargin(0.10);
965 for (size_t i = 0; i < data.size(); i++) {
966 TEllipse* center = new TEllipse(data[i].fMirrorV.X(), data[i].fMirrorV.Y(), 2500);
967 center->SetFillColor(colors[data[i].fOrderedLineX % colors.size()]);
968 center->Draw();
969 }
970}
971
972void CbmRichRonchiAna::DrawXZProjection(vector<CbmRichRonchiIntersectionData>& data, int orderedLineY, double scale)
973{
974 string histName = "hZX_lineY" + to_string(orderedLineY) + "_scale" + to_string(scale);
975
976 TH2D* hZX =
977 new TH2D(histName.c_str(), (histName + ";Z [mum];X [mum];").c_str(), 100, -0.02 * scale * fDistMirrorRuling,
978 1.05 * scale * fDistMirrorRuling, 100, scale * -250000, scale * 250000);
979 DrawH2(hZX);
980 gPad->SetRightMargin(0.10);
981 for (size_t i = 0; i < data.size(); i++) {
982 if (data[i].fOrderedLineY != orderedLineY) continue;
983
984 TEllipse* ccdEllipse = new TEllipse(data[i].fCcdV.Z(), data[i].fCcdV.X(), scale * 20000, scale * 2000);
985 ccdEllipse->SetFillColor(kRed);
986 ccdEllipse->Draw();
987
988 TEllipse* rulingEllipse = new TEllipse(data[i].fRulingV.Z(), data[i].fRulingV.X(), scale * 20000, scale * 2000);
989 rulingEllipse->SetFillColor(kBlue);
990 rulingEllipse->Draw();
991
992 TEllipse* mirrorEllipse = new TEllipse(data[i].fMirrorV.Z(), data[i].fMirrorV.X(), scale * 20000, scale * 2000);
993 mirrorEllipse->SetFillColor(kGreen);
994 mirrorEllipse->Draw();
995
996 TLine* rulingLine = new TLine(data[i].fCcdV.Z(), data[i].fCcdV.X(), data[i].fRulingV.Z(), data[i].fRulingV.X());
997 rulingLine->Draw();
998
999 TLine* mirrorLine =
1000 new TLine(data[i].fRulingV.Z(), data[i].fRulingV.X(), data[i].fMirrorV.Z(), data[i].fMirrorV.X());
1001 mirrorLine->Draw();
1002
1003 double xNorm = data[i].fMirrorV.X() - fDistMirrorRuling * tan(data[i].fNormalRadX);
1004 TLine* mirrorLineNorm = new TLine(fDistRulingCCD, xNorm, data[i].fMirrorV.Z(), data[i].fMirrorV.X());
1005 mirrorLineNorm->SetLineColor(kBlue);
1006 mirrorLineNorm->Draw();
1007 }
1008}
1009
1010
1011void CbmRichRonchiAna::DrawMirrorSegments(vector<CbmRichRonchiIntersectionData>& data, int orderedLineX,
1012 int orderedLineY)
1013{
1014 string cName = "ronchi_mirror_segments_rot_lineX" + to_string(orderedLineX) + "_lineY" + to_string(orderedLineY);
1015 TCanvas* c = new TCanvas(cName.c_str(), cName.c_str(), 1800, 900);
1016 c->Divide(2, 1);
1017
1018 string histNameXY = "hXY_mirror_segments_rot_lineX" + to_string(orderedLineX) + "_lineY" + to_string(orderedLineY);
1019 TH2D* hXY =
1020 new TH2D(histNameXY.c_str(), (histNameXY + "hXY;X [mum];Y [mum];").c_str(), 1, -250000, 250000, 1, -250000, 250000);
1021 vector<int> colors = {kBlack, kGreen, kBlue, kRed, kYellow, kOrange, kCyan, kGray, kMagenta, kYellow + 2, kRed + 3};
1022 c->cd(1);
1023 DrawH2(hXY); // boxes
1024 gPad->SetRightMargin(0.10);
1025 for (size_t i = 0; i < data.size(); i++) {
1026 int color = colors[data[i].fOrderedLineY % colors.size()];
1027 DrawOneMirrorSegment(data[i].fTLRot, data[i].fTRRot, data[i].fBLRot, data[i].fBRRot, color);
1028 }
1029
1030 double hSize = 250000;
1031 string histNameZX = "hZX_mirror_segments_lrot_ineX" + to_string(orderedLineX) + "_lineY" + to_string(orderedLineY);
1032 TH2D* hZX = new TH2D(histNameZX.c_str(), (histNameZX + ";Z [mum];X [mum];").c_str(), 100, fDistMirrorRuling - hSize,
1033 fDistMirrorRuling + hSize, 100, -1. * hSize, hSize);
1034 c->cd(2);
1035 DrawH2(hZX);
1036 gPad->SetRightMargin(0.10);
1037 for (size_t i = 0; i < data.size(); i++) {
1038 if (data[i].fOrderedLineY != orderedLineY) continue;
1039
1040 TEllipse* mirrorEllipse = new TEllipse(data[i].fMirrorV.Z(), data[i].fMirrorV.X(), 2000, 2000);
1041 mirrorEllipse->SetFillColor(kGreen);
1042 mirrorEllipse->Draw();
1043
1044 TLine* rulingLine = new TLine(data[i].fCcdV.Z(), data[i].fCcdV.X(), data[i].fRulingV.Z(), data[i].fRulingV.X());
1045 rulingLine->Draw();
1046
1047 TLine* mirrorLine =
1048 new TLine(data[i].fRulingV.Z(), data[i].fRulingV.X(), data[i].fMirrorV.Z(), data[i].fMirrorV.X());
1049 mirrorLine->Draw();
1050
1051 double xNorm = data[i].fMirrorV.X() - fDistMirrorRuling * tan(data[i].fNormalRadX);
1052 TLine* mirrorLineNorm = new TLine(fDistRulingCCD, xNorm, data[i].fMirrorV.Z(), data[i].fMirrorV.X());
1053 mirrorLineNorm->SetLineColor(kBlue);
1054 mirrorLineNorm->Draw();
1055
1056 TLine* mirrorLineSeg = new TLine(data[i].fTRRot.Z(), data[i].fTRRot.X(), data[i].fTLRot.Z(), data[i].fTLRot.X());
1057 mirrorLineSeg->SetLineColor(kRed);
1058 mirrorLineSeg->Draw();
1059 }
1060}
1061
1062void CbmRichRonchiAna::DrawMirrorSegmentsSphereAll(vector<CbmRichRonchiIntersectionData>& data)
1063{
1064 string cName = "ronchi_mirror_segments_sphere_all";
1065 TCanvas* c = new TCanvas(cName.c_str(), cName.c_str(), 900, 900);
1066
1067 string histNameXY = "hXY_mirror_segments_sphere_all";
1068 TH2D* hXY =
1069 new TH2D(histNameXY.c_str(), (histNameXY + "hXY;X [mum];Y [mum];").c_str(), 1, -250000, 250000, 1, -250000, 250000);
1070 vector<int> colors = {kBlack, kGreen, kBlue, kRed, kYellow, kOrange, kCyan, kGray, kMagenta, kYellow + 2, kRed + 3};
1071 DrawH2(hXY); // boxes
1072 gPad->SetRightMargin(0.10);
1073 for (size_t i = 0; i < data.size(); i++) {
1074 int color = colors[data[i].fOrderedLineY % colors.size()];
1075 DrawOneMirrorSegment(data[i].fTLSph, data[i].fTRSph, data[i].fBLSph, data[i].fBRSph, color);
1076 }
1077}
1078
1079void CbmRichRonchiAna::DrawMirrorSegmentsSphere(vector<CbmRichRonchiIntersectionData>& data, int orderedLineX,
1080 int orderedLineY)
1081{
1082 string cName = "ronchi_mirror_segments_sphere_lineX" + to_string(orderedLineX) + "_lineY" + to_string(orderedLineY);
1083 TCanvas* c = new TCanvas(cName.c_str(), cName.c_str(), 1800, 900);
1084 c->Divide(2, 1);
1085
1086 string histNameXY = "hXY_mirror_segments_sphere_lineX" + to_string(orderedLineX) + "_lineY" + to_string(orderedLineY);
1087 TH2D* hXY =
1088 new TH2D(histNameXY.c_str(), (histNameXY + "hXY;X [mum];Y [mum];").c_str(), 1, -250000, 250000, 1, -250000, 250000);
1089 vector<int> colors = {kBlack, kGreen, kBlue, kRed, kYellow, kOrange, kCyan, kGray, kMagenta, kYellow + 2, kRed + 3};
1090 c->cd(1);
1091 DrawH2(hXY); // boxes
1092 gPad->SetRightMargin(0.10);
1093 for (size_t i = 0; i < data.size(); i++) {
1094 if (data[i].fOrderedLineX == orderedLineX)
1095 DrawOneMirrorSegment(data[i].fTLSph, data[i].fTRSph, data[i].fBLSph, data[i].fBRSph, kBlue);
1096 if (data[i].fOrderedLineY == orderedLineY)
1097 DrawOneMirrorSegment(data[i].fTLSph, data[i].fTRSph, data[i].fBLSph, data[i].fBRSph, kRed);
1098 }
1099
1100 double hSize = 20000;
1101 string histNameZX = "hZX_mirror_segments_sphere_lineX" + to_string(orderedLineX) + "_lineY" + to_string(orderedLineY);
1102 TH2D* hZX = new TH2D(histNameZX.c_str(), (histNameZX + ";Z [mum];X(Y) [mum];").c_str(), 100,
1103 data[0].fBRSph.Z() - 0.25 * hSize, data[0].fBRSph.Z() + hSize, 100, -1. * 250000, 250000);
1104 c->cd(2);
1105 DrawH2(hZX);
1106 gPad->SetRightMargin(0.10);
1107 for (size_t i = 0; i < data.size(); i++) {
1108 if (data[i].fOrderedLineX == orderedLineX) {
1109 TLine* mirrorLineSeg = new TLine(data[i].fBRSph.Z(), data[i].fBRSph.Y(), data[i].fTRSph.Z(), data[i].fTRSph.Y());
1110 mirrorLineSeg->SetLineColor(kBlue);
1111 mirrorLineSeg->Draw();
1112 }
1113
1114 if (data[i].fOrderedLineY == orderedLineY) {
1115 TLine* mirrorLineSeg = new TLine(data[i].fTRSph.Z(), data[i].fTRSph.X(), data[i].fTLSph.Z(), data[i].fTLSph.X());
1116 mirrorLineSeg->SetLineColor(kRed);
1117 mirrorLineSeg->Draw();
1118 }
1119 }
1120}
1121
1122// void CbmRichRonchiAna::DrawMirrorSegmentsSphere(vector<CbmRichRonchiIntersectionData> &data, int orderedLineX, int orderedLineY)
1123// {
1124// string cName = "ronchi_mirror_segments_sphere_lineX" + to_string(orderedLineX) + "_lineY" + to_string(orderedLineY);
1125// TCanvas *c = new TCanvas(cName.c_str(), cName.c_str(), 1800, 900);
1126// c->Divide(2, 1);
1127
1128// string histNameXY = "hXY_mirror_segments_sphere_lineX" + to_string(orderedLineX) + "_lineY" + to_string(orderedLineY);
1129// TH2D *hXY = new TH2D(histNameXY.c_str(), (histNameXY + "hXY;X [mum];Y [mum];").c_str(), 1, -250000, 250000, 1, -250000, 250000);
1130// vector<int> colors = {kBlack, kGreen, kBlue, kRed, kYellow, kOrange, kCyan, kGray, kMagenta, kYellow + 2, kRed + 3};
1131// c->cd(1);
1132// DrawH2(hXY); // boxes
1133// gPad->SetRightMargin(0.10);
1134// for (size_t i = 0; i < data.size(); i++){
1135// if (data[i].fOrderedLineX == orderedLineX) DrawOneMirrorSegment(data[i].fTLSph, data[i].fTRSph, data[i].fBLSph, data[i].fBRSph, kBlue);
1136// if (data[i].fOrderedLineY == orderedLineY) DrawOneMirrorSegment(data[i].fTLSph, data[i].fTRSph, data[i].fBLSph, data[i].fBRSph, kRed);
1137// }
1138
1139// double hSize = 10000;
1140// int corr = 9400;
1141
1142// string histNameZX = "hZX_mirror_segments_sphere_lineX" + to_string(orderedLineX) + "_lineY" + to_string(orderedLineY);
1143// TH2D *hZX = new TH2D(histNameZX.c_str(), (histNameZX + ";Z [mum];X(Y) [mum];").c_str(), 100, data[0].fBRSph.Z()-(fDistMirrorCCD) - 1.0*hSize, data[0].fBRSph.Z()-(fDistMirrorCCD) + 1.0*hSize, 100, -1. * 250000, 250000);
1144// c->cd(2);
1145// DrawH2(hZX);
1146// gPad->SetRightMargin(0.10);
1147// for (size_t i = 0; i < data.size(); i++) {
1148
1149// double meanX = 0.25 * ( data[i].fTLSph.X() + data[i].fTRSph.X() + data[i].fBLSph.X() + data[i].fBRSph.X() );
1150// double meanY = 0.25 * ( data[i].fTLSph.Y() + data[i].fTRSph.Y() + data[i].fBLSph.Y() + data[i].fBRSph.Y() );
1151// double meanZ = 0.25 * ( data[i].fTLSph.Z() + data[i].fTRSph.Z() + data[i].fBLSph.Z() + data[i].fBRSph.Z() );
1152// double mirrorCenterDist = sqrt(pow(meanX, 2) + pow(meanY-fOffsetCCDOptAxisY, 2)); // distance from mirrors center in microns
1153// double sagitta = fRadiusMirror - sqrt(pow(fRadiusMirror, 2) - pow(mirrorCenterDist, 2));
1154// double zIdeal = (fDistMirrorCCD) - sagitta;
1155
1156// if (data[i].fOrderedLineX == orderedLineX) {
1157// //TLine *mirrorLineSeg = new TLine(data[i].fBRSph.Z(), data[i].fBRSph.Y(), data[i].fTRSph.Z(), data[i].fTRSph.Y());
1158// TLine *mirrorLineSeg = new TLine(data[i].fBRSph.Z()-zIdeal-corr, data[i].fBRSph.Y(), data[i].fTRSph.Z()-zIdeal-corr, data[i].fTRSph.Y());
1159// mirrorLineSeg->SetLineColor(kBlue);
1160// mirrorLineSeg->Draw();
1161// }
1162
1163// if (data[i].fOrderedLineY == orderedLineY) {
1164// TLine *mirrorLineSeg = new TLine(data[i].fTRSph.Z()-zIdeal, data[i].fTRSph.X(), data[i].fTLSph.Z()-zIdeal, data[i].fTLSph.X());
1165// mirrorLineSeg->SetLineColor(kRed);
1166// mirrorLineSeg->Draw();
1167// }
1168// }
1169// }
1170
1171void CbmRichRonchiAna::DrawOneMirrorSegment(const TVector3& tl, const TVector3& tr, const TVector3& bl,
1172 const TVector3& br, int color)
1173{
1174 TLine* line1 = new TLine(tl.X(), tl.Y(), tr.X(), tr.Y());
1175 line1->SetLineColor(color);
1176 line1->Draw();
1177
1178 TLine* line2 = new TLine(tr.X(), tr.Y(), br.X(), br.Y());
1179 line2->SetLineColor(color);
1180 line2->Draw();
1181
1182 TLine* line3 = new TLine(br.X(), br.Y(), bl.X(), bl.Y());
1183 line3->SetLineColor(color);
1184 line3->Draw();
1185
1186 TLine* line4 = new TLine(bl.X(), bl.Y(), tl.X(), tl.Y());
1187 line4->SetLineColor(color);
1188 line4->Draw();
1189}
1190
1191
1192void CbmRichRonchiAna::RotatePointImpl(TVector3* inPos, TVector3* outPos, Double_t rotX, Double_t rotY, TVector3* cV)
1193{
1194 double x = inPos->X() - cV->X();
1195 double y = inPos->Y() - cV->Y();
1196 double z = inPos->Z() - cV->Z();
1197
1198 double sinY = sin(rotY);
1199 double cosY = cos(rotY);
1200 double sinX = sin(rotX);
1201 double cosX = cos(rotX);
1202
1203 double xNew = x * cosX - y * sinX * sinY + z * cosY * sinX + cV->X();
1204 double yNew = y * cosY + z * sinY + cV->Y();
1205 double zNew = -x * sinX - y * sinY * cosX + z * cosY * cosX + cV->Z();
1206
1207 outPos->SetXYZ(xNew, yNew, zNew);
1208}
1209
ClassImp(CbmConverterManager)
void SetDefaultDrawStyle()
void DrawH1(TH1 *hist, HistScale logx, HistScale logy, const string &drawOpt, Int_t color, Int_t lineWidth, Int_t lineStyle, Int_t markerSize, Int_t markerStyle)
void DrawH2(TH2 *hist, HistScale logx, HistScale logy, HistScale logz, const string &drawOpt)
Helper functions for drawing 1D and 2D histograms and graphs.
friend fvec sqrt(const fvec &a)
friend fvec cos(const fvec &a)
friend fvec sin(const fvec &a)
void DoSphere(vector< CbmRichRonchiIntersectionData > &intersections)
void RotatePointImpl(TVector3 *inPos, TVector3 *outPos, Double_t rotX, Double_t rotY, TVector3 *cV)
void DoPeakFinderY(vector< vector< double > > &data)
void DoSmoothLines(vector< vector< double > > &data)
void DrawOneMirrorSegment(const TVector3 &tl, const TVector3 &tr, const TVector3 &bl, const TVector3 &br, int color)
int GetMinIndexForLineX(int lineX, vector< CbmRichRonchiIntersectionData > &data)
void DrawXYMum(vector< CbmRichRonchiIntersectionData > &data)
vector< CbmRichRonchiIntersectionData > DoIntersection(vector< vector< double > > &dataH, const vector< vector< double > > &dataV)
void DoDeviation(vector< CbmRichRonchiIntersectionData > &data)
void DrawMirrorSegments(vector< CbmRichRonchiIntersectionData > &data, int orderedLineX, int orderedLineY)
void DoLocalNormal(vector< CbmRichRonchiIntersectionData > &data)
void DrawXZProjection(vector< CbmRichRonchiIntersectionData > &data, int orderedLineY, double scale)
bool AreTwoSegmentsSameLine(const CbmRichRonchiLineData *line1, const CbmRichRonchiLineData *line2)
void DoLineSearch(vector< vector< double > > &data)
void FillH2WithVector(TH2 *hist, const vector< vector< double > > &data)
void DrawMirrorSegmentsSphere(vector< CbmRichRonchiIntersectionData > &data, int orderedLineX, int orderedLineY)
vector< vector< double > > ReadTiffFile(const string &fileName)
void DoMeanIntensityY(vector< vector< double > > &data)
void DrawMirrorSegmentsSphereAll(vector< CbmRichRonchiIntersectionData > &data)
void DoRotation(vector< vector< double > > &data)
void UpdateIntersectionLineInd(vector< CbmRichRonchiIntersectionData > &intersections, CbmRichRonchiLineData *line1, CbmRichRonchiLineData *line2, const string &option)
vector< vector< double > > DoSuperpose(const vector< vector< double > > &dataH, const vector< vector< double > > &dataV)
int GetMinIndexForLineY(int lineY, vector< CbmRichRonchiIntersectionData > &data)
void DoOrderLines(vector< CbmRichRonchiIntersectionData > &intersections, const string &option)
int GetIndexForLineXLineY(int lineX, int lineY, vector< CbmRichRonchiIntersectionData > &data)
Hash for CbmL1LinkKey.