00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <ctime>
00024 #include <string>
00025 #include "StuPostScript.h"
00026 #include "PhysicalConstants.h"
00027 #include "StGlobals.hh"
00028
00029
00030
00031
00032 bool StuPostScript::mBlackBackground = false;
00033 bool StuPostScript::mDrawBeamPipe = false;
00034 bool StuPostScript::mTracksWithManyColors = false;
00035 bool StuPostScript::mTracksWithFewColors = false;
00036 bool StuPostScript::mFewerPointsPerTrack = false;
00037 bool StuPostScript::mAddText = false;
00038 bool StuPostScript::mAllGlobalTracks = false;
00039 bool StuPostScript::mSideView = false;
00040 bool StuPostScript::mShowTrackHits = false;
00041 bool StuPostScript::mShowAllHits = false;
00042 const int StuPostScript::mllx = -220;
00043 const int StuPostScript::mlly = -220;
00044 const int StuPostScript::murx = 220;
00045 const int StuPostScript::mury = 220;
00046 const int StuPostScript::mMinFitPoints = 10;
00047 vector<StTrack*> *StuPostScript::mUserTracks = 0;
00048
00049 StuPostScript::StuPostScript() {}
00050
00051 StuPostScript::~StuPostScript() {}
00052
00053 bool StuPostScript::write(const char* filename, const StEvent* event, const char* opt, vector<StTrack*>* userTracks)
00054 {
00055 if (!event) return false;
00056
00057
00058
00059
00060 ofstream ofs(filename);
00061 if (!ofs) return false;
00062
00063
00064
00065
00066 string options(opt);
00067 mBlackBackground = (options.find('b') != string::npos);
00068 mDrawBeamPipe = (options.find('p') != string::npos);
00069 mTracksWithFewColors = (options.find('c') != string::npos);
00070 mTracksWithManyColors = (options.find('C') != string::npos);
00071 mFewerPointsPerTrack = (options.find('f') != string::npos);
00072 if (mTracksWithFewColors && mTracksWithManyColors) mTracksWithFewColors = false;
00073 mAllGlobalTracks = (options.find('a') != string::npos);
00074 mAddText = (options.find('t') != string::npos);
00075 mSideView = (options.find('s') != string::npos);
00076 mShowTrackHits = (options.find('h') != string::npos);
00077 mShowAllHits = (options.find('H') != string::npos);
00078 mUserTracks = userTracks;
00079
00080
00081
00082
00083 writeHeader(ofs, filename);
00084 writeDetectorFrame(ofs);
00085 writeTracks(ofs, event);
00086 if (mShowTrackHits || mShowAllHits) writeHits(ofs, event);
00087 if (mAddText) writeText(ofs, event);
00088 writeTrailor(ofs);
00089
00090
00091
00092
00093 ofs.close();
00094 cout << "StuPostScript::write(): file '" << filename << "' written." << endl;
00095 return true;
00096 };
00097
00098 void StuPostScript::writeHeader(ostream &os, const char* filename) {
00099
00100
00101
00102
00103 time_t now = time(0);
00104 os << "%!PS-Adobe-2.0 EPSF-2.0" << endl;
00105 os << "%%BoundingBox: " << 0 << ' ' << 0 << ' ' << murx-mllx << ' ' << mury-mlly << endl;
00106 os << "%%Title: " << filename << " (STAR Event Display)" << endl;
00107 os << "%%Creator: StuPostScript" << endl;
00108 os << "%%CreationDate: " << ctime(&now);
00109 os << "%%Pages: 0" << endl;
00110 os << "%%EndComments" << endl;
00111
00112
00113
00114 int hitGrayLevel = mBlackBackground ? 1 : 0;
00115 const double boxSize = 1;
00116 os << "/Hit {gsave moveto " << -boxSize/2 << ' ' << boxSize/2
00117 << " rmoveto " << boxSize << " 0 rlineto 0 " << -boxSize
00118 << " rlineto " << -boxSize << " 0 rlineto closepath "
00119 << hitGrayLevel << " setgray 0.2 setlinewidth stroke grestore} def" << endl;
00120 os << "/tHit {gsave " << boxSize/2 << " 0 360 arc closepath "
00121 << hitGrayLevel << " setgray 0.2 setlinewidth stroke grestore} def" << endl;
00122
00123
00124
00125
00126 os << "1 1 scale" << endl;
00127 os << -mllx << ' ' << -mlly << " translate" << endl;
00128
00129
00130
00131
00132 if (mBlackBackground) {
00133 os << "gsave" << endl;
00134 os << "newpath" << endl;
00135 os << mllx << ' ' << mlly << " moveto" << endl;
00136 os << mllx << ' ' << mury << " lineto" << endl;
00137 os << murx << ' ' << mury << " lineto" << endl;
00138 os << murx << ' ' << mlly << " lineto" << endl;
00139 os << "closepath" << endl;
00140 os << "0 setgray" << endl;
00141 os << "fill" << endl;
00142 os << "grestore" << endl;
00143 }
00144 }
00145
00146 void StuPostScript::writeTrailor(ostream &os)
00147 {
00148 os << "%showpage" << endl;
00149 os << "%%EOF" << endl;
00150 }
00151
00152 void StuPostScript::writeDetectorFrame(ostream &os)
00153 {
00154 const double innerRadius = 50;
00155 const double outerRadius = 200;
00156 const double halfLength = 200;
00157 const double beamPipeRadius = 3.5;
00158 const int nSectors = 12;
00159 const double lineWidth = 0.5;
00160
00161 const double angleStep = twopi/nSectors;
00162 const double beginAngle = angleStep/2;
00163 double x, y, angle;
00164
00165
00166
00167
00168 int frameGrayLevel = mBlackBackground ? 1 : 0;
00169
00170
00171
00172
00173 os << "gsave" << endl;
00174 os << "newpath" << endl;
00175 if (mSideView) {
00176 os << -halfLength << ' ' << -innerRadius << " moveto" << endl;
00177 os << 0 << ' ' << 2*innerRadius << " rlineto" << endl;
00178 os << 2*halfLength << ' ' << 0 << " rlineto" << endl;
00179 os << 0 << ' ' << -2*innerRadius << " rlineto" << endl;
00180 }
00181 else {
00182 x = innerRadius*cos(beginAngle);
00183 y = innerRadius*sin(beginAngle);
00184 os << x << ' ' << y << " moveto" << endl;
00185 for (angle = beginAngle+angleStep; angle < twopi; angle += angleStep) {
00186 x = innerRadius*cos(angle);
00187 y = innerRadius*sin(angle);
00188 os << x << ' ' << y << " lineto" << endl;
00189 }
00190 }
00191 os << "closepath" << endl;
00192 os << frameGrayLevel << " setgray" << endl;
00193 os << lineWidth << " setlinewidth" << endl;
00194 os << "stroke" << endl;
00195 os << "grestore" << endl;
00196
00197
00198
00199
00200 os << "gsave" << endl;
00201 os << "newpath" << endl;
00202 if (mSideView) {
00203 os << -halfLength << ' ' << -outerRadius << " moveto" << endl;
00204 os << 0 << ' ' << 2*outerRadius << " rlineto" << endl;
00205 os << 2*halfLength << ' ' << 0 << " rlineto" << endl;
00206 os << 0 << ' ' << -2*outerRadius << " rlineto" << endl;
00207 }
00208 else {
00209 x = outerRadius*cos(beginAngle);
00210 y = outerRadius*sin(beginAngle);
00211 os << x << ' ' << y << " moveto" << endl;
00212 for (angle = beginAngle+angleStep; angle < twopi; angle += angleStep) {
00213 x = outerRadius*cos(angle);
00214 y = outerRadius*sin(angle);
00215 os << x << ' ' << y << " lineto" << endl;
00216 }
00217 }
00218 os << "closepath" << endl;
00219 os << frameGrayLevel << " setgray" << endl;
00220 os << lineWidth << " setlinewidth" << endl;
00221 os << "stroke" << endl;
00222 os << "grestore" << endl;
00223
00224
00225
00226
00227 if (!mSideView) {
00228 os << "gsave" << endl;
00229 for (angle = beginAngle; angle < twopi; angle += angleStep) {
00230 x = innerRadius*cos(angle);
00231 y = innerRadius*sin(angle);
00232 os << x << ' ' << y << " moveto" << endl;
00233 x = outerRadius*cos(angle);
00234 y = outerRadius*sin(angle);
00235 os << x << ' ' << y << " lineto" << endl;
00236 }
00237 os << frameGrayLevel << " setgray" << endl;
00238 os << lineWidth << " setlinewidth" << endl;
00239 os << "stroke" << endl;
00240 os << "grestore" << endl;
00241 }
00242
00243
00244
00245
00246 if (mDrawBeamPipe) {
00247 os << "gsave" << endl;
00248 os << "newpath" << endl;
00249 if (mSideView) {
00250 os << -halfLength << ' ' << -beamPipeRadius << " moveto" << endl;
00251 os << 0 << ' ' << 2*beamPipeRadius << " rlineto" << endl;
00252 os << 2*halfLength << ' ' << 0 << " rlineto" << endl;
00253 os << 0 << ' ' << -2*beamPipeRadius << " rlineto" << endl;
00254 }
00255 else
00256 os << "0 0 " << beamPipeRadius << " 0 360 arc" << endl;
00257 os << "closepath" << endl;
00258 os << frameGrayLevel << " setgray" << endl;
00259 os << lineWidth << " setlinewidth" << endl;
00260 os << "stroke" << endl;
00261 os << "grestore" << endl;
00262 }
00263 }
00264
00265 void StuPostScript::writeTracks(ostream &os, const StEvent* event)
00266 {
00267 const double lineWidth = 0.4;
00268 const double sstep = mFewerPointsPerTrack ? 4 : 1;
00269 const double lightness = 50;
00270 const double saturation = 100;
00271
00272
00273
00274
00275 int trackGrayLevel = mBlackBackground ? 1 : 0;
00276
00277 StTrack *track;
00278 StThreeVectorD p;
00279 unsigned int i;
00280 double slast, pt, red, green, blue, hue;
00281 const StSPtrVecTrackNode& theNodes = event->trackNodes();
00282 int minFitPoints = mAllGlobalTracks ? 1 : mMinFitPoints;
00283 vector<StTrack*> theTracks;
00284
00285
00286
00287
00288 if (mUserTracks) {
00289 for (i=0; i<mUserTracks->size(); i++)
00290 theTracks.push_back((*mUserTracks)[i]);
00291 }
00292 else {
00293 for (i=0; i<theNodes.size(); i++) {
00294 track = theNodes[i]->track(global);
00295 if (track) theTracks.push_back(track);
00296 }
00297 }
00298
00299
00300
00301
00302 for (i=0; i<theTracks.size(); i++) {
00303 track = theTracks[i];
00304 if (track && track->flag() > 0 &&
00305 track->fitTraits().numberOfFitPoints(kTpcId) >= minFitPoints) {
00306 pt = track->geometry()->momentum().perp();
00307 StPhysicalHelixD helix = track->geometry()->helix();
00308 p = track->detectorInfo()->lastPoint();
00309 slast = helix.pathLength(p);
00310 os << "gsave" << endl;
00311 p = helix.origin();
00312 if (mSideView) {
00313 os << p.z() << ' ' << p.y() << " moveto" << endl;
00314 for (double s=0; s<slast; s+= sstep) {
00315 p = helix.at(s);
00316 os << p.z() << ' ' << p.y() << " lineto" << endl;
00317 }
00318 p = helix.at(slast);
00319 os << p.z() << ' ' << p.y() << " lineto" << endl;
00320 }
00321 else {
00322 os << p.x() << ' ' << p.y() << " moveto" << endl;
00323 for (double s=0; s<slast; s+= sstep) {
00324 p = helix.at(s);
00325 os << p.x() << ' ' << p.y() << " lineto" << endl;
00326 }
00327 p = helix.at(slast);
00328 os << p.x() << ' ' << p.y() << " lineto" << endl;
00329 }
00330
00331
00332
00333 if (mTracksWithManyColors) {
00334 hue = 256.*(1.-pt/1.5);
00335 if (pt > 1.5 ) hue = 0;
00336 hls2rgb(hue, lightness, saturation, red, green, blue);
00337 os << red << ' ' << green << ' ' << blue << " setrgbcolor" << endl;
00338 }
00339 else if (mTracksWithFewColors) {
00340 if (pt > 1.0)
00341 os << "1 0 0 setrgbcolor" << endl;
00342 else if (pt > 0.5)
00343 os << "0 1 0 setrgbcolor" << endl;
00344 else
00345 os << "0 0 1 setrgbcolor" << endl;
00346 }
00347 else
00348 os << trackGrayLevel << " setgray" << endl;
00349
00350 os << lineWidth << " setlinewidth" << endl;
00351 os << "stroke" << endl;
00352 os << "grestore" << endl;
00353 }
00354 }
00355 }
00356
00357 void StuPostScript::writeHits(ostream& os, const StEvent* event)
00358 {
00359 unsigned int i, m, n, h;
00360 const StTrack *track;
00361 const StHit *hit;
00362 const StTpcHitCollection *theHits = event->tpcHitCollection();
00363
00364 if (mUserTracks) {
00365 for (i=0; i<mUserTracks->size(); i++) {
00366 track = (*mUserTracks)[i];
00367 if (track->detectorInfo()) {
00368 const StPtrVecHit& trackHits = track->detectorInfo()->hits(kTpcId);
00369 for (m=0; m<trackHits.size(); m++) {
00370 hit = trackHits[m];
00371 os << (mSideView ? hit->position().z() : hit->position().x())
00372 << ' ' << hit->position().y() << " tHit" << endl;
00373 }
00374 }
00375 }
00376 }
00377 else {
00378 for (n=0; n<theHits->numberOfSectors(); n++) {
00379 for (m=0; m<theHits->sector(n)->numberOfPadrows(); m++) {
00380 for (h=0; h<theHits->sector(n)->padrow(m)->hits().size(); h++) {
00381 hit = theHits->sector(n)->padrow(m)->hits()[h];
00382 if (mShowAllHits || (mShowTrackHits && hit->trackReferenceCount())) {
00383 os << (mSideView ? hit->position().z() : hit->position().x())
00384 << ' ' << hit->position().y()
00385 << (hit->trackReferenceCount() ? " tHit" : " Hit") << endl;
00386 }
00387 }
00388 }
00389 }
00390 }
00391 }
00392
00393 void StuPostScript::writeText(ostream& os, const StEvent* event)
00394 {
00395 const int fontsize = 11;
00396 const int textGrayLevel = mBlackBackground ? 1 : 0;
00397
00398 os << "/Helvetica findfont" << endl;
00399 os << fontsize << " scalefont setfont" << endl;
00400 os << "gsave" << endl;
00401 os << textGrayLevel << " setgray" << endl;
00402
00403
00404
00405
00406 double x = mllx+fontsize;
00407 double xn = x + 3.5*fontsize;
00408 double y = mury-2*fontsize;
00409 os << x << ' ' << y << " moveto" << endl;
00410 os << "(run:) show" << endl;
00411 os << xn << ' ' << y << " moveto" << endl;
00412 os << "(" << event->runId() << ") show" << endl;
00413 y -= fontsize+1;
00414 os << x << ' ' << y << " moveto" << endl;
00415 os << "(event:) show" << endl;
00416 os << xn << ' ' << y << " moveto" << endl;
00417 os << "(" << event->id() << ") show" << endl;
00418 y -= fontsize+1;
00419 os << x << ' ' << y << " moveto" << endl;
00420 os << "(trigger:) show" << endl;
00421 os << xn << ' ' << y << " moveto" << endl;
00422 os << "(0x" << hex << event->l1Trigger()->triggerWord() << dec << ") show" << endl;
00423
00424
00425
00426
00427 xn = x + 7*fontsize;
00428 y = mlly+fontsize;
00429 os << x << ' ' << y << " moveto" << endl;
00430 os << "(primary tracks:) show" << endl;
00431 os << xn << ' ' << y << " moveto" << endl;
00432 if (event->primaryVertex())
00433 os << "(" << event->primaryVertex()->numberOfDaughters() << ") show" << endl;
00434 else
00435 os << "(0) show" << endl;
00436 y += fontsize+1;
00437 os << x << ' ' << y << " moveto" << endl;
00438 os << "(global tracks:) show" << endl;
00439 os << xn << ' ' << y << " moveto" << endl;
00440 os << "(" << event->trackNodes().size() << ") show" << endl;
00441
00442
00443
00444
00445 y = mlly+fontsize;
00446 os << murx << ' ' << y << " moveto" << endl;
00447 os << "(vertex: ";
00448 if (event->primaryVertex())
00449 os << event->primaryVertex()->position().x() << ' '
00450 << event->primaryVertex()->position().y() << ' '
00451 << event->primaryVertex()->position().z();
00452 else
00453 os << "N/A";
00454 os << ") dup stringwidth pop -" << fontsize << " exch sub 0 rmoveto show" << endl;
00455
00456 os << "grestore" << endl;
00457 }
00458
00459 #define VALUE(n1, n2, h) ((h < 60) ? (n1 + (n2-n1)*h/60) : ((h<180) ? \
00460 (n2) : ((h<240) ? (n1+(n2-n1)*(240-h)/60) : (n1))))
00461
00462 void StuPostScript::hls2rgb(double hue, double light, double sat,
00463 double &red, double &green, double &blue)
00464 {
00465
00466
00467
00468
00469
00470
00471
00472 double m1, m2;
00473 light /= 100.;
00474 sat /= 100.;
00475
00476 if (light<= 0.5)
00477 m2 = light*(1 + sat);
00478 else
00479 m2 = light + sat - light*sat;
00480 m1 = 2*light - m2;
00481 if ((sat == 0) && (hue == 0)) {
00482 red = light; green = light; blue = light;
00483 }
00484 else {
00485 red = VALUE(m1, m2, (((hue+120) > 360) ? (hue-240) : (hue+120)));
00486 green = VALUE(m1, m2, hue);
00487 blue = VALUE(m1, m2, (((hue-120) < 0) ? (hue+240) : (hue-120)));
00488 }
00489 }
00490 #undef VALUE