StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ObjExporter.h
1 
2 #include "GenFit/FitStatus.h"
3 #include "GenFit/GFRaveVertexFactory.h"
4 #include <math.h>
5 
6 #include "StEvent/StEvent.h"
7 #include "StEvent/StFttCollection.h"
8 #include "StEvent/StFttCluster.h"
9 
10 class StEvent;
11 
12 float DEGS_TO_RAD = 3.14159f/180.0f;
13 float SCALE = 0.1;
14 
15 class ObjExporter {
16 public:
17 
18  // extra output for info and debug
19  const static bool verbose = false;
20 
21  // write a single vertex
22  void vert( ofstream &of, float x, float y, float z ){
23  of << "v " << x << " " << y << " " << z << endl;
24  numVertices++;
25  }
26  void vert( ofstream &of, TVector3 v ){
27  of << "v " << v.X() << " " << v.Y() << " " << v.Z() << endl;
28  numVertices++;
29  }
30 
31  // write a sphere with given sub-divsions to output file
32  void sphere(TVector3 pt, float radius, int nLatitude, int nLongitude, ofstream &fout){
33  int p, s, i, j;
34  float x, y, z, out;
35  int nPitch = nLongitude + 1;
36 
37  float pitchInc = (180. / (float)nPitch) * DEGS_TO_RAD;
38  float rotInc = (360. / (float)nLatitude) * DEGS_TO_RAD;
39 
40  //## PRINT VERTICES:
41  vert(fout, pt.X(), pt.Y()+radius, pt.Z()); // Top vertex.
42  vert(fout, pt.X(), pt.Y()-radius, pt.Z()); // Bottom vertex.
43 
44  int fVert = numVertices; // Record the first vertex index for intermediate vertices.
45  for(p=1; p<nPitch; p++) { // Generate all "intermediate vertices":
46  out = fabs(radius * sin((float)p * pitchInc));
47  y = radius * cos(p * pitchInc);
48  for(s=0; s<nLatitude; s++) {
49  x = out * cos(s * rotInc);
50  z = out * sin(s * rotInc);
51  fout << TString::Format("v %g %g %g\n", x+pt.X(), y+pt.Y(), z+pt.Z()).Data();
52  numVertices++;
53  }
54  }
55 
56  //## OUTPUT FACES BETWEEN INTERMEDIATE POINTS:
57 
58  for(p=1; p<nPitch-1; p++) {
59  for(s=0; s<nLatitude; s++) {
60  i = p*nLatitude + s;
61  j = (s==nLatitude-1) ? i-nLatitude : i;
62  fout << TString::Format("f %d %d %d %d\n",
63  (i+1-nLatitude)+fVert, (j+2-nLatitude)+fVert, (j+2)+fVert, (i+1)+fVert);
64  }
65  }
66 
67  //## OUTPUT TRIANGULAR FACES CONNECTING TO TOP AND BOTTOM VERTEX:
68 
69  int offLastVerts = fVert + (nLatitude * (nLongitude-1));
70  for(s=0; s<nLatitude; s++)
71  {
72  j = (s==nLatitude-1) ? -1 : s;
73  fout << TString::Format("f %d %d %d\n", fVert-1, (j+2)+fVert, (s+1)+fVert ).Data();
74  fout << TString::Format("f %d %d %d\n", fVert, (s+1)+offLastVerts, (j+2)+offLastVerts).Data();
75  }
76  } // sphere
77 
78  // output a single face
79  void face( ofstream &fout, int anchor, int v0, int v1, int v2 ){
80  fout << TString::Format("f %d %d %d\n", anchor+v0, anchor+v1, anchor+v2).Data();
81  }
82  void face( ofstream &fout, int anchor, int v0, int v1, int v2, int v3 ){
83  fout << TString::Format("f %d %d %d %d\n", anchor+v0, anchor+v1, anchor+v2, anchor+v3).Data();
84  }
85  // output a general prism
86  void prism( ofstream &fout, TVector3 po, TVector3 ds ){
87  int fVert = numVertices; // Record the first vertex index for intermediate vertices.
88  // x-y at z=0
89  vert( fout, po.X(), po.Y(), po.Z() ); // 1
90  vert( fout, po.X() + ds.X(), po.Y(), po.Z() ); // 2
91  vert( fout, po.X() + ds.X(), po.Y() + ds.Y(), po.Z() ); // 3
92  vert( fout, po.X(), po.Y() + ds.Y(), po.Z() ); // 4
93 
94  // x-y at z=+dz
95  vert( fout, po.X(), po.Y(), po.Z() + ds.Z() ); // 5
96  vert( fout, po.X() + ds.X(), po.Y(), po.Z() + ds.Z() ); // 6
97  vert( fout, po.X() + ds.X(), po.Y() + ds.Y(), po.Z() + ds.Z() ); // 7
98  vert( fout, po.X(), po.Y() + ds.Y(), po.Z() + ds.Z() ); // 8
99 
100  face( fout, fVert, 1, 2, 3, 4 ); // bottom face
101  face( fout, fVert, 5, 6, 7, 8 ); // top face
102  face( fout, fVert, 1, 2, 6, 5 ); // side 1
103  face( fout, fVert, 2, 3, 7, 6 ); // side 2
104  face( fout, fVert, 3, 4, 8, 7 ); // side 3
105  face( fout, fVert, 1, 4, 8, 5 ); // side 4
106  }
107 
108  // output a tri
109  void tri( ofstream &fout, TVector3 v0, float dz, float w, float h, float phi ) {
110 
111  int fVert = numVertices;
112  float dphi = 0.1/2;
113  float yp = v0.Y() + (sin( phi + dphi ) + cos( phi + dphi ) ) * h;
114  float yn = v0.Y() + (sin( phi - dphi ) + cos( phi - dphi ) ) * h;
115  float xp = v0.X() + (cos( phi + dphi ) - sin( phi + dphi)) * h;
116  float xn = v0.X() + (cos( phi - dphi ) - sin( phi - dphi)) * h;
117  // top face
118  vert( fout, v0.X(), v0.Y(), v0.Z() ); // 1
119  vert( fout, xp, yp, v0.Z() );
120  vert( fout, xn, yn, v0.Z() );
121 
122  // top face
123  vert( fout, v0.X(), v0.Y(), v0.Z() - dz ); // 4
124  vert( fout, xp, yp, v0.Z() - dz );
125  vert( fout, xn, yn, v0.Z() - dz );
126 
127  face( fout, fVert, 1, 2, 3 ); // top
128  face( fout, fVert, 4, 5, 6 ); // bottom
129  face( fout, fVert, 1, 2, 5, 4 ); // side 1
130  face( fout, fVert, 2, 3, 6, 5 ); // side 2
131  face( fout, fVert, 3, 1, 4, 6 ); // side 3
132  }
133 
134  // Compute a track projection as a linear (straight) extrapolation from two points from full projections
135  static TVector3 projectAsStraightLine( genfit::Track * t, float z0, float z1, float zf, float * cov, TVector3 &mom ) {
136  TVector3 tv3A = trackPosition( t, z0, cov, mom );
137  TVector3 tv3B = trackPosition( t, z1, cov, mom );
138 
139  if (verbose){
140  LOG_INFO << "Straight Line Projection using" << endm;
141  LOG_INFO << "A.x = " << tv3A.X() << endm;
142  LOG_INFO << "B.x = " << tv3B.X() << endm;
143  }
144 
145  double dxdz = ( tv3B.X() - tv3A.X() ) / ( tv3B.Z() - tv3A.Z() );
146  double dydz = ( tv3B.Y() - tv3A.Y() ) / ( tv3B.Z() - tv3A.Z() );
147 
148  double dx = dxdz * ( zf - z1 );
149  double dy = dydz * ( zf - z1 );
150  TVector3 r( tv3B.X() + dx, tv3B.Y() + dy, zf );
151  return r;
152  }
153 
154  // Project a track to a given z-plane and return its position, momentum, and cov matrix
155  static TVector3 trackPosition( genfit::Track * t, float z, float * cov, TVector3 &mom ){
156 
157  int iPoint = 0;
158  try {
159  auto plane = genfit::SharedPlanePtr(
160  // these normals make the planes face along z-axis
161  new genfit::DetPlane(TVector3(0, 0, z), TVector3(1, 0, 0), TVector3(0, 1, 0) )
162  );
163 
164  genfit::MeasuredStateOnPlane tst = t->getFittedState(iPoint);
165  auto TCM = t->getCardinalRep()->get6DCov(tst);
166  // returns the track length if needed
167  t->getCardinalRep()->extrapolateToPlane(tst, plane, false, true);
168 
169  TCM = t->getCardinalRep()->get6DCov(tst);
170 
171  // can get the projected positions if needed
172  float x = tst.getPos().X();
173  float y = tst.getPos().Y();
174  float _z = tst.getPos().Z();
175 
176  mom.SetXYZ( tst.getMom().X(), tst.getMom().Y(), tst.getMom().Z() );
177 
178  if ( cov ){
179  cov[0] = TCM(0,0); cov[1] = TCM(1,0); cov[2] = TCM(2,0);
180  cov[3] = TCM(0,1); cov[4] = TCM(1,1); cov[5] = TCM(2,1);
181  cov[6] = TCM(0,2); cov[7] = TCM(1,2); cov[8] = TCM(2,2);
182  }
183 
184 
185  return TVector3( x, y, _z );
186  } catch ( genfit::Exception e ){
187  LOG_INFO << "Track projection Failed from trackPoint " << iPoint << " E: " << e.what() << endm;
188  return TVector3( -990, -990, -990 );
189  }
190 
191 
192  return TVector3( -990, -990, -990 );
193  }
194 
195  // Utility method
196  static TVector3 trackPosition( genfit::Track * t, float z ){
197  float cov[9];
198  TVector3 mom;
199  return trackPosition( t, z, cov, mom);
200  }
201 
202  // Output the sTGC strips into a useful format for event display
203  void output_ftt_strips(
204  ofstream &fout,
205  StEvent * event ){
206 
207  fout << "\n" << endl;
208  fout << "o fttStrips" << endl;
209  fout << "usemtl stgc_hits\n" << endl;
210  float pz[] = {280.90499, 303.70498, 326.60501, 349.40499};
211  TVector3 cp;
212 
213 
214  for ( size_t i = 0; i < event->fttCollection()->numberOfClusters(); i++ ){
215  StFttCluster* c = event->fttCollection()->clusters()[i];
216  if ( c->nStrips() < 2 ) continue;
217  float dw = 0.05, dlh = 60.0, dlv = 60.0;
218  float mx = 0.0, my = 0.0;
219  float sx = 1.0, sy = 1.0;
220 
221 
222  if ( c->quadrant() == kFttQuadrantA ){
223  mx = 0; my = 0;
224  sx = 1.0; sy = 1.0;
225  } else if ( c->quadrant() == kFttQuadrantB ){
226  mx = 10.16*SCALE; my = 0.0*SCALE;
227  sy = -1;
228  dlv = -dlv;
229 
230  } else if ( c->quadrant() == kFttQuadrantC ){
231  mx = -10.16*SCALE ; my = -00.0*SCALE;
232  sx = -1.0; sy = -1.0;
233  dlh = -dlh; dlv = -dlv;
234 
235  } else if ( c->quadrant() == kFttQuadrantD ){
236  sx = -1;
237  dlh = -dlh;
238  }
239 
240  cp.SetZ( -pz[ c->plane() ] * SCALE );
241  if ( c->orientation() == kFttHorizontal ){
242  cp.SetY( my + sy * c->x()/10.0 * SCALE );
243  cp.SetX( mx );
244  prism( fout, cp, TVector3( dlh * SCALE, dw, dw ) );
245  } else if ( c->orientation() == kFttVertical ){
246  cp.SetX( mx + sx * c->x()/10.0 * SCALE );
247  cp.SetY( my );
248  prism( fout, cp, TVector3( dw, dlv * SCALE, dw ) );
249  }
250  }
251  } // ftt_strips
252 
253  // Output the event info into a useful format for event display
254  void output( std::string filename,
255  StEvent * event,
256  std::vector< Seed_t> seeds,
257  std::vector< genfit::Track *> tracks,
258  const std::vector< genfit::GFRaveVertex *> &vertices,
259  std::vector<TVector3> &fttHits,
260  std::vector<TVector3> &fstHits,
261  std::vector<TVector3> &fcsPreHits, // EPD = preshower
262  std::vector<TVector3> &fcsClusters,
263  std::vector<float> &fcsClusterEnergy
264  ){
265 
266  LOG_INFO << "Writing: " << filename << endm;
267  numVertices = 0;
268  // OPEN output
269  ofstream ofile( (filename + ".obj" ).c_str() );
270 
271  ofile << "\nmtllib materials.mtl\n\n" << endl;
272 
273 
274  output_ftt_strips( ofile, event );
275 
276  // Write FWD vertices
277  TVector3 startPos;
278  if ( vertices.size() > 0 ){
279  ofile << "o FwdVertices" << endl;
280  for ( auto v : vertices ) {
281  startPos.SetXYZ( v->getPos().X(), v->getPos().Y(), v->getPos().Z() );
282  sphere( TVector3( v->getPos().X() * SCALE, v->getPos().Y() * SCALE, -v->getPos().Z() * SCALE ), 0.5, 10, 10, ofile );
283  }
284  }
285 
286  // Write FTT hits (points)
287  if ( verbose ){
288  LOG_INFO << "Viz has " << fttHits.size() << " FTT Hits" << endm;
289  }
290  if ( fttHits.size() > 0 ){
291  ofile << "\n" << endl;
292  ofile << "o fttHits" << endl;
293  ofile << "usemtl stgc_hits\n" << endl;
294  for ( auto p : fttHits ){
295  sphere( TVector3( p.X() * SCALE, p.Y() * SCALE, -p.Z() * SCALE ), 0.15, 12, 12, ofile );
296  }
297  }
298 
299  // write FST hits
300  if ( verbose ){
301  LOG_INFO << "Viz has " << fstHits.size() << " FST Hits" << endm;
302  }
303  if ( fstHits.size() > 0 ) {
304  ofile << "\n" << endl;
305  ofile << "o fstHits" << endl;
306  ofile << "usemtl fst_hits\n" << endl;
307  for ( auto p : fstHits ){
308 
309  float fstphi = TMath::ATan2( p.Y(), p.X() );
310  printf( "FST PHI: %f \n", fstphi );
311  // tri( ofile, TVector3( p.X() * SCALE, p.Y() * SCALE, -p.Z() * SCALE ), 0.1f, 0.1f, 3.0f, fstphi );
312  sphere( TVector3( p.X() * SCALE, p.Y() * SCALE, -p.Z() * SCALE ), 0.3, 10, 10, ofile );
313  }
314  }
315 
316  // Output the EPD hits
317  if (verbose){
318  LOG_INFO << "Viz has " << fcsPreHits.size() << " EPD Hits" << endm;
319  }
320  if ( fcsPreHits.size() > 0 ){
321  ofile << "\n" << endl;
322  ofile << "o epd" << endl;
323  ofile << "usemtl fcs_hits\n" << endl;
324  for ( auto p : fcsPreHits ){
325 
326  sphere( TVector3( p.X() * SCALE, p.Y() * SCALE, -p.Z() * SCALE ), 0.25, 10, 10, ofile );
327  }
328  }
329 
330  if (verbose){
331  LOG_INFO << "Viz has " << fcsClusters.size() << " FCS Hits" << endm;
332  }
333  if ( fcsClusters.size() > 0 ){
334  ofile << "\n" << endl;
335  ofile << "o fcs" << endl;
336  ofile << "usemtl fcs_hits\n" << endl;
337  int i = 0;
338  for ( auto p : fcsClusters ){
339  // sphere( TVector3( p.X() * SCALE, p.Y() * SCALE, -p.Z() * SCALE ), 0.75, 10, 10, ofile );
340  TVector3 ds = TVector3( 1, 1, fcsClusterEnergy[i] );
341  prism( ofile, TVector3( p.X() * SCALE, p.Y() * SCALE, -p.Z() * SCALE ), ds );
342  i++;
343  }
344  }
345 
346  // Write the track seeds
347  if (verbose){
348  LOG_INFO << "Viz has " << seeds.size() << " seeds" << endm;
349  }
350  if ( seeds.size() > 0 ){
351  ofile << "\n\no FwdSeeds\n" << endl;
352  ofile << "usemtl seeds\n" << endl;
353  // numVertices = 0;
354  for ( auto s : seeds ) {
355  size_t vStart = numVertices;
356  for ( auto h : s ){
357 
358  vert( ofile, h->getX() * SCALE, h->getY() * SCALE, -h->getZ() * SCALE );
359 
360  }
361 
362  ofile << "l ";
363  for ( size_t i = vStart; i < numVertices; i++){
364  ofile << i+1 << " ";
365  }
366  ofile << endl;
367  }
368  }
369 
370  // uncomment if you want a separate file for tracks
371  // ofile.open( (filename + "_tracks.obj" ).c_str() );
372  // numVertices = 0;
373  // EXPORT TRACKS
374 
375  if (verbose){
376  LOG_INFO << "Viz has " << tracks.size() << " tracks Hits" << endm;
377  }
378  if ( tracks.size() > 0 ){
379  ofile << "\n\no FwdTracks\n" << endl;
380  ofile << "usemtl tracks\n" << endl;
381  float zStep = 5.0; // cm
382  for ( auto t : tracks ) {
383  size_t vStart = numVertices;
384 
385 
386  TVector3 lpoint;
387  for ( float z = startPos.Z(); z < 875; z += zStep ){
388  TVector3 point = trackPosition( t, z );
389  if ( point.X() < -900 && point.Y() < -900 ) break;
390  if ( point.X() < -90 && point.Y() < -90 ) { z+= 50; continue;}
391 
392  vert( ofile, point.X() * SCALE, point.Y() * SCALE, -point.Z() * SCALE );
393  lpoint = point;
394  }
395 
396  ofile << "l ";
397  for ( size_t i = vStart; i < numVertices; i++){
398  ofile << i+1 << " ";
399  }
400  ofile << endl;
401  } // for t in tracks
402  } // if tracks.size() > 0
403 
404  ofile.close();
405  }
406 
407  size_t numVertices;
408 
409 };