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