StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StuPostScript.cc
1 /***************************************************************************
2  *
3  * $Id: StuPostScript.cc,v 1.4 2018/06/29 17:21:24 perev Exp $
4  *
5  * Author: Thomas Ullrich, April 2002
6  ***************************************************************************
7  *
8  * Description: PostScript Event Display
9  *
10  ***************************************************************************
11  *
12  * $Log: StuPostScript.cc,v $
13  * Revision 1.4 2018/06/29 17:21:24 perev
14  * Irakli_Jun29
15  *
16  * Revision 1.3 2002/10/11 17:34:14 ullrich
17  * Hits on tracks drawn as circles not diamonds
18  *
19  * Revision 1.2 2002/06/25 02:43:12 ullrich
20  * Added drawing of hits.
21  *
22  * Revision 1.1 2002/04/23 03:15:28 ullrich
23  * Initial Revision.
24  *
25  **************************************************************************/
26 #include <ctime>
27 #include <string>
28 #include "StuPostScript.h"
29 #include "PhysicalConstants.h"
30 #include "StGlobals.hh"
31 
32 //
33 // Initialize static data member
34 //
35 bool StuPostScript::mBlackBackground = false;
36 bool StuPostScript::mDrawBeamPipe = false;
37 bool StuPostScript::mTracksWithManyColors = false;
38 bool StuPostScript::mTracksWithFewColors = false;
39 bool StuPostScript::mFewerPointsPerTrack = false;
40 bool StuPostScript::mAddText = false;
41 bool StuPostScript::mAllGlobalTracks = false;
42 bool StuPostScript::mSideView = false;
43 bool StuPostScript::mShowTrackHits = false;
44 bool StuPostScript::mShowAllHits = false;
45 const int StuPostScript::mllx = -220;
46 const int StuPostScript::mlly = -220;
47 const int StuPostScript::murx = 220;
48 const int StuPostScript::mury = 220;
49 const int StuPostScript::mMinFitPoints = 10;
50 vector<StTrack*> *StuPostScript::mUserTracks = 0;
51 
52 StuPostScript::StuPostScript() {/* noop*/}
53 
54 StuPostScript::~StuPostScript() {/* noop*/}
55 
56 bool StuPostScript::write(const char* filename, const StEvent* event, const char* opt, vector<StTrack*>* userTracks)
57 {
58  if (!event) return false;
59 
60  //
61  // Open EPS file
62  //
63  ofstream ofs(filename);
64  if (!ofs) return false;
65 
66  //
67  // Unpack options
68  //
69  string options(opt);
70  mBlackBackground = (options.find('b') != string::npos);
71  mDrawBeamPipe = (options.find('p') != string::npos);
72  mTracksWithFewColors = (options.find('c') != string::npos);
73  mTracksWithManyColors = (options.find('C') != string::npos);
74  mFewerPointsPerTrack = (options.find('f') != string::npos);
75  if (mTracksWithFewColors && mTracksWithManyColors) mTracksWithFewColors = false;
76  mAllGlobalTracks = (options.find('a') != string::npos);
77  mAddText = (options.find('t') != string::npos);
78  mSideView = (options.find('s') != string::npos);
79  mShowTrackHits = (options.find('h') != string::npos);
80  mShowAllHits = (options.find('H') != string::npos);
81  mUserTracks = userTracks;
82 
83  //
84  // Write PostSCript to file
85  //
86  writeHeader(ofs, filename);
87  writeDetectorFrame(ofs);
88  writeTracks(ofs, event);
89  if (mShowTrackHits || mShowAllHits) writeHits(ofs, event);
90  if (mAddText) writeText(ofs, event);
91  writeTrailor(ofs);
92 
93  //
94  // Close file
95  //
96  ofs.close();
97  cout << "StuPostScript::write(): file '" << filename << "' written." << endl;
98  return true;
99 };
100 
101 void StuPostScript::writeHeader(ostream &os, const char* filename) {
102 
103  //
104  // EPS Header
105  //
106  time_t now = time(0);
107  os << "%!PS-Adobe-2.0 EPSF-2.0" << endl;
108  os << "%%BoundingBox: " << 0 << ' ' << 0 << ' ' << murx-mllx << ' ' << mury-mlly << endl;
109  os << "%%Title: " << filename << " (STAR Event Display)" << endl;
110  os << "%%Creator: StuPostScript" << endl;
111  os << "%%CreationDate: " << ctime(&now);
112  os << "%%Pages: 0" << endl;
113  os << "%%EndComments" << endl;
114  //
115  // Definitions
116  //
117  int hitGrayLevel = mBlackBackground ? 1 : 0;
118  const double boxSize = 1;
119  os << "/Hit {gsave moveto " << -boxSize/2 << ' ' << boxSize/2
120  << " rmoveto " << boxSize << " 0 rlineto 0 " << -boxSize
121  << " rlineto " << -boxSize << " 0 rlineto closepath "
122  << hitGrayLevel << " setgray 0.2 setlinewidth stroke grestore} def" << endl;
123  os << "/tHit {gsave " << boxSize/2 << " 0 360 arc closepath "
124  << hitGrayLevel << " setgray 0.2 setlinewidth stroke grestore} def" << endl;
125 
126  //
127  // Scaling and translation
128  //
129  os << "1 1 scale" << endl;
130  os << -mllx << ' ' << -mlly << " translate" << endl;
131 
132  //
133  // Draw black background
134  //
135  if (mBlackBackground) {
136  os << "gsave" << endl;
137  os << "newpath" << endl;
138  os << mllx << ' ' << mlly << " moveto" << endl;
139  os << mllx << ' ' << mury << " lineto" << endl;
140  os << murx << ' ' << mury << " lineto" << endl;
141  os << murx << ' ' << mlly << " lineto" << endl;
142  os << "closepath" << endl;
143  os << "0 setgray" << endl;
144  os << "fill" << endl;
145  os << "grestore" << endl;
146  }
147 }
148 
149 void StuPostScript::writeTrailor(ostream &os)
150 {
151  os << "%showpage" << endl; // not for EPS files
152  os << "%%EOF" << endl;
153 }
154 
155 void StuPostScript::writeDetectorFrame(ostream &os)
156 {
157  const double innerRadius = 50;
158  const double outerRadius = 200;
159  const double halfLength = 200;
160  const double beamPipeRadius = 3.5;
161  const int nSectors = 12;
162  const double lineWidth = 0.5;
163 
164  const double angleStep = twopi/nSectors;
165  const double beginAngle = angleStep/2;
166  double x, y, angle;
167 
168  //
169  // Handle options
170  //
171  int frameGrayLevel = mBlackBackground ? 1 : 0;
172 
173  //
174  // Inner field cage
175  //
176  os << "gsave" << endl;
177  os << "newpath" << endl;
178  if (mSideView) {
179  os << -halfLength << ' ' << -innerRadius << " moveto" << endl;
180  os << 0 << ' ' << 2*innerRadius << " rlineto" << endl;
181  os << 2*halfLength << ' ' << 0 << " rlineto" << endl;
182  os << 0 << ' ' << -2*innerRadius << " rlineto" << endl;
183  }
184  else {
185  x = innerRadius*cos(beginAngle);
186  y = innerRadius*sin(beginAngle);
187  os << x << ' ' << y << " moveto" << endl;
188  for (angle = beginAngle+angleStep; angle < twopi; angle += angleStep) {
189  x = innerRadius*cos(angle);
190  y = innerRadius*sin(angle);
191  os << x << ' ' << y << " lineto" << endl;
192  }
193  }
194  os << "closepath" << endl;
195  os << frameGrayLevel << " setgray" << endl;
196  os << lineWidth << " setlinewidth" << endl;
197  os << "stroke" << endl;
198  os << "grestore" << endl;
199 
200  //
201  // Outer field cage
202  //
203  os << "gsave" << endl;
204  os << "newpath" << endl;
205  if (mSideView) {
206  os << -halfLength << ' ' << -outerRadius << " moveto" << endl;
207  os << 0 << ' ' << 2*outerRadius << " rlineto" << endl;
208  os << 2*halfLength << ' ' << 0 << " rlineto" << endl;
209  os << 0 << ' ' << -2*outerRadius << " rlineto" << endl;
210  }
211  else {
212  x = outerRadius*cos(beginAngle);
213  y = outerRadius*sin(beginAngle);
214  os << x << ' ' << y << " moveto" << endl;
215  for (angle = beginAngle+angleStep; angle < twopi; angle += angleStep) {
216  x = outerRadius*cos(angle);
217  y = outerRadius*sin(angle);
218  os << x << ' ' << y << " lineto" << endl;
219  }
220  }
221  os << "closepath" << endl;
222  os << frameGrayLevel << " setgray" << endl;
223  os << lineWidth << " setlinewidth" << endl;
224  os << "stroke" << endl;
225  os << "grestore" << endl;
226 
227  //
228  // Sector bounderies
229  //
230  if (!mSideView) {
231  os << "gsave" << endl;
232  for (angle = beginAngle; angle < twopi; angle += angleStep) {
233  x = innerRadius*cos(angle);
234  y = innerRadius*sin(angle);
235  os << x << ' ' << y << " moveto" << endl;
236  x = outerRadius*cos(angle);
237  y = outerRadius*sin(angle);
238  os << x << ' ' << y << " lineto" << endl;
239  }
240  os << frameGrayLevel << " setgray" << endl;
241  os << lineWidth << " setlinewidth" << endl;
242  os << "stroke" << endl;
243  os << "grestore" << endl;
244  }
245 
246  //
247  // Beampipe
248  //
249  if (mDrawBeamPipe) {
250  os << "gsave" << endl;
251  os << "newpath" << endl;
252  if (mSideView) {
253  os << -halfLength << ' ' << -beamPipeRadius << " moveto" << endl;
254  os << 0 << ' ' << 2*beamPipeRadius << " rlineto" << endl;
255  os << 2*halfLength << ' ' << 0 << " rlineto" << endl;
256  os << 0 << ' ' << -2*beamPipeRadius << " rlineto" << endl;
257  }
258  else
259  os << "0 0 " << beamPipeRadius << " 0 360 arc" << endl;
260  os << "closepath" << endl;
261  os << frameGrayLevel << " setgray" << endl;
262  os << lineWidth << " setlinewidth" << endl;
263  os << "stroke" << endl;
264  os << "grestore" << endl;
265  }
266 }
267 
268 void StuPostScript::writeTracks(ostream &os, const StEvent* event)
269 {
270  const double lineWidth = 0.4;
271  const double sstep = mFewerPointsPerTrack ? 4 : 1;
272  const double lightness = 50;
273  const double saturation = 100;
274 
275  //
276  // Handle options
277  //
278  int trackGrayLevel = mBlackBackground ? 1 : 0;
279 
280  StTrack *track;
281  StThreeVectorD p;
282  unsigned int i;
283  double slast, pt, red, green, blue, hue;
284  const StSPtrVecTrackNode& theNodes = event->trackNodes();
285  int minFitPoints = mAllGlobalTracks ? 1 : mMinFitPoints;
286  vector<StTrack*> theTracks;
287 
288  //
289  // Prepare list of tracks to plot
290  //
291  if (mUserTracks) {
292  for (i=0; i<mUserTracks->size(); i++)
293  theTracks.push_back((*mUserTracks)[i]);
294  }
295  else {
296  for (i=0; i<theNodes.size(); i++) {
297  track = (StTrack *) theNodes[i]->track(global);
298  if (track) theTracks.push_back(track);
299  }
300  }
301 
302  //
303  // Write out tracks
304  //
305  for (i=0; i<theTracks.size(); i++) {
306  track = theTracks[i];
307  if (track && track->flag() > 0 &&
308  track->fitTraits().numberOfFitPoints(kTpcId) >= minFitPoints) {
309  pt = track->geometry()->momentum().perp();
310  StPhysicalHelixD helix = track->geometry()->helix();
311  p = track->detectorInfo()->lastPoint();
312  slast = helix.pathLength(p);
313  os << "gsave" << endl;
314  p = helix.origin();
315  if (mSideView) {
316  os << p.z() << ' ' << p.y() << " moveto" << endl;
317  for (double s=0; s<slast; s+= sstep) {
318  p = helix.at(s);
319  os << p.z() << ' ' << p.y() << " lineto" << endl;
320  }
321  p = helix.at(slast);
322  os << p.z() << ' ' << p.y() << " lineto" << endl;
323  }
324  else {
325  os << p.x() << ' ' << p.y() << " moveto" << endl;
326  for (double s=0; s<slast; s+= sstep) {
327  p = helix.at(s);
328  os << p.x() << ' ' << p.y() << " lineto" << endl;
329  }
330  p = helix.at(slast);
331  os << p.x() << ' ' << p.y() << " lineto" << endl;
332  }
333  //
334  // Color codes
335  //
336  if (mTracksWithManyColors) {
337  hue = 256.*(1.-pt/1.5);
338  if (pt > 1.5 ) hue = 0;
339  hls2rgb(hue, lightness, saturation, red, green, blue);
340  os << red << ' ' << green << ' ' << blue << " setrgbcolor" << endl;
341  }
342  else if (mTracksWithFewColors) {
343  if (pt > 1.0)
344  os << "1 0 0 setrgbcolor" << endl;
345  else if (pt > 0.5)
346  os << "0 1 0 setrgbcolor" << endl;
347  else
348  os << "0 0 1 setrgbcolor" << endl;
349  }
350  else // B&W
351  os << trackGrayLevel << " setgray" << endl;
352 
353  os << lineWidth << " setlinewidth" << endl;
354  os << "stroke" << endl;
355  os << "grestore" << endl;
356  }
357  }
358 }
359 
360 void StuPostScript::writeHits(ostream& os, const StEvent* event)
361 {
362  unsigned int i, m, n, h;
363  const StTrack *track;
364  const StHit *hit;
365  const StTpcHitCollection *theHits = event->tpcHitCollection();
366 
367  if (mUserTracks) {
368  for (i=0; i<mUserTracks->size(); i++) {
369  track = (*mUserTracks)[i];
370  if (track->detectorInfo()) {
371  const StPtrVecHit& trackHits = track->detectorInfo()->hits(kTpcId);
372  for (m=0; m<trackHits.size(); m++) {
373  hit = trackHits[m];
374  os << (mSideView ? hit->position().z() : hit->position().x())
375  << ' ' << hit->position().y() << " tHit" << endl;
376  }
377  }
378  }
379  }
380  else {
381  for (n=0; n<theHits->numberOfSectors(); n++) {
382  for (m=0; m<theHits->sector(n)->numberOfPadrows(); m++) {
383  for (h=0; h<theHits->sector(n)->padrow(m)->hits().size(); h++) {
384  hit = theHits->sector(n)->padrow(m)->hits()[h];
385  if (mShowAllHits || (mShowTrackHits && hit->trackReferenceCount())) {
386  os << (mSideView ? hit->position().z() : hit->position().x())
387  << ' ' << hit->position().y()
388  << (hit->trackReferenceCount() ? " tHit" : " Hit") << endl;
389  }
390  }
391  }
392  }
393  }
394 }
395 
396 void StuPostScript::writeText(ostream& os, const StEvent* event)
397 {
398  const int fontsize = 11;
399  const int textGrayLevel = mBlackBackground ? 1 : 0;
400 
401  os << "/Helvetica findfont" << endl;
402  os << fontsize << " scalefont setfont" << endl;
403  os << "gsave" << endl;
404  os << textGrayLevel << " setgray" << endl;
405 
406  //
407  // Run, event, and trigger in upper left
408  //
409  double x = mllx+fontsize;
410  double xn = x + 3.5*fontsize;
411  double y = mury-2*fontsize;
412  os << x << ' ' << y << " moveto" << endl;
413  os << "(run:) show" << endl;
414  os << xn << ' ' << y << " moveto" << endl;
415  os << "(" << event->runId() << ") show" << endl;
416  y -= fontsize+1;
417  os << x << ' ' << y << " moveto" << endl;
418  os << "(event:) show" << endl;
419  os << xn << ' ' << y << " moveto" << endl;
420  os << "(" << event->id() << ") show" << endl;
421  y -= fontsize+1;
422  os << x << ' ' << y << " moveto" << endl;
423  os << "(trigger:) show" << endl;
424  os << xn << ' ' << y << " moveto" << endl;
425  os << "(0x" << hex << event->l1Trigger()->triggerWord() << dec << ") show" << endl;
426 
427  //
428  // Number of tracks in upper right
429  //
430  xn = x + 7*fontsize;
431  y = mlly+fontsize;
432  os << x << ' ' << y << " moveto" << endl;
433  os << "(primary tracks:) show" << endl;
434  os << xn << ' ' << y << " moveto" << endl;
435  if (event->primaryVertex())
436  os << "(" << event->primaryVertex()->numberOfDaughters() << ") show" << endl;
437  else
438  os << "(0) show" << endl;
439  y += fontsize+1;
440  os << x << ' ' << y << " moveto" << endl;
441  os << "(global tracks:) show" << endl;
442  os << xn << ' ' << y << " moveto" << endl;
443  os << "(" << event->trackNodes().size() << ") show" << endl;
444 
445  //
446  // Primary Vertex
447  //
448  y = mlly+fontsize;
449  os << murx << ' ' << y << " moveto" << endl;
450  os << "(vertex: ";
451  if (event->primaryVertex())
452  os << event->primaryVertex()->position().x() << ' '
453  << event->primaryVertex()->position().y() << ' '
454  << event->primaryVertex()->position().z();
455  else
456  os << "N/A";
457  os << ") dup stringwidth pop -" << fontsize << " exch sub 0 rmoveto show" << endl;
458 
459  os << "grestore" << endl;
460 }
461 
462 #define VALUE(n1, n2, h) ((h < 60) ? (n1 + (n2-n1)*h/60) : ((h<180) ? \
463  (n2) : ((h<240) ? (n1+(n2-n1)*(240-h)/60) : (n1))))
464 
465 void StuPostScript::hls2rgb(double hue, double light, double sat,
466  double &red, double &green, double &blue)
467 {
468  //
469  // Input: hue = [0-360]
470  // light = [0-100]
471  // saturation = [0-100]
472  //
473  // Output: red, green, blue = [0-1]
474  //
475  double m1, m2;
476  light /= 100.;
477  sat /= 100.;
478 
479  if (light<= 0.5)
480  m2 = light*(1 + sat);
481  else
482  m2 = light + sat - light*sat;
483  m1 = 2*light - m2;
484  if ((sat == 0) && (hue == 0)) {
485  red = light; green = light; blue = light;
486  }
487  else {
488  red = VALUE(m1, m2, (((hue+120) > 360) ? (hue-240) : (hue+120)));
489  green = VALUE(m1, m2, hue);
490  blue = VALUE(m1, m2, (((hue-120) < 0) ? (hue+240) : (hue-120)));
491  }
492 }
493 #undef VALUE
Definition: StHit.h:125
pair< double, double > pathLength(double r) const
path length at given r (cylindrical r)
Definition: StHelix.cc:351
const StThreeVector< double > & origin() const
-sign(q*B);
Definition: StHelix.hh:224