~mbogomilov/maus/devel3

« back to all changes in this revision

Viewing changes to src/map/MapCppGlobalRawTracks/MapCppGlobalRawTracks.cc

  • Committer: Durga Rajaram
  • Date: 2014-01-14 04:39:44 UTC
  • mfrom: (663.38.24 merge)
  • mto: (698.1.1 release)
  • mto: This revision was merged to the branch mainline in revision 693.
  • Revision ID: durga@fnal.gov-20140114043944-qf0i8nksnwu74cll
candidate 0.7.6 - trunk r1026

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* This file is part of MAUS: http://micewww.pp.rl.ac.uk:8080/projects/maus
 
2
 *
 
3
 * MAUS is free software: you can redistribute it and/or modify
 
4
 * it under the terms of the GNU General Public License as published by
 
5
 * the Free Software Foundation, either version 3 of the License, or
 
6
 * (at your option) any later version.
 
7
 *
 
8
 * MAUS is distributedTrackReconstructor in the hope that it will be useful,
 
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
 * GNU General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU General Public License
 
14
 * along with MAUS.  If not, see <http://www.gnu.org/licenses/>.
 
15
 *
 
16
 */
 
17
 /* Author: Peter Lane
 
18
 */
 
19
 
 
20
#include "src/map/MapCppGlobalRawTracks/MapCppGlobalRawTracks.hh"
 
21
 
 
22
// C++
 
23
#include <algorithm>
 
24
#include <cmath>
 
25
#include <map>
 
26
#include <string>
 
27
#include <vector>
 
28
 
 
29
// External
 
30
#include "TLorentzVector.h"
 
31
#include "TMinuit.h"
 
32
#include "CLHEP/Random/RandGauss.h"
 
33
#include "CLHEP/Units/PhysicalConstants.h"
 
34
#include "json/json.h"
 
35
 
 
36
// Legacy/G4MICE
 
37
#include "Config/MiceModule.hh"
 
38
#include "Utils/Exception.hh"
 
39
 
 
40
// MAUS
 
41
#include "Converter/DataConverters/JsonCppSpillConverter.hh"
 
42
#include "Converter/DataConverters/CppJsonSpillConverter.hh"
 
43
#include "DataStructure/Data.hh"
 
44
#include "DataStructure/GlobalEvent.hh"
 
45
#include "DataStructure/MCEvent.hh"
 
46
#include "DataStructure/ReconEvent.hh"
 
47
#include "DataStructure/SciFiTrackPoint.hh"
 
48
#include "DataStructure/TOFEventSpacePoint.hh"
 
49
#include "DataStructure/ThreeVector.hh"
 
50
#include "DataStructure/Global/ReconEnums.hh"
 
51
#include "DataStructure/Global/BasePoint.hh"
 
52
#include "DataStructure/Global/SpacePoint.hh"
 
53
#include "DataStructure/Global/Track.hh"
 
54
#include "DataStructure/Global/TrackPoint.hh"
 
55
#include "src/common_cpp/Optics/CovarianceMatrix.hh"
 
56
#include "Recon/Global/DataStructureHelper.hh"
 
57
#include "Recon/Global/Detector.hh"
 
58
#include "Recon/Global/Particle.hh"
 
59
#include "src/common_cpp/Simulation/MAUSGeant4Manager.hh"
 
60
#include "Utils/Globals.hh"
 
61
#include "Utils/JsonWrapper.hh"
 
62
#include "Utils/CppErrorHandler.hh"
 
63
 
 
64
namespace MAUS {
 
65
 
 
66
namespace GlobalDS = ::MAUS::DataStructure::Global;
 
67
using MAUS::recon::global::DataStructureHelper;
 
68
using MAUS::recon::global::Detector;
 
69
using MAUS::recon::global::DetectorMap;
 
70
using MAUS::recon::global::Particle;
 
71
 
 
72
MapCppGlobalRawTracks::MapCppGlobalRawTracks() {
 
73
}
 
74
 
 
75
MapCppGlobalRawTracks::~MapCppGlobalRawTracks() {
 
76
}
 
77
 
 
78
bool MapCppGlobalRawTracks::birth(std::string configuration_string) {
 
79
  // parse the JSON document.
 
80
  try {
 
81
    const Json::Value configuration
 
82
      = JsonWrapper::StringToJson(configuration_string);
 
83
 
 
84
    DataStructureHelper::GetInstance().GetDetectorAttributes(
 
85
        configuration, detectors_);
 
86
  } catch(Exception& exception) {
 
87
    MAUS::CppErrorHandler::getInstance()->HandleExceptionNoJson(
 
88
      exception, MapCppGlobalRawTracks::kClassname);
 
89
    return false;
 
90
  } catch(std::exception& exc) {
 
91
    MAUS::CppErrorHandler::getInstance()->HandleStdExcNoJson(
 
92
      exc, MapCppGlobalRawTracks::kClassname);
 
93
    return false;
 
94
  }
 
95
 
 
96
  MAUSGeant4Manager * const simulator = MAUSGeant4Manager::GetInstance();
 
97
  MAUSPrimaryGeneratorAction::PGParticle reference_pgparticle
 
98
    = simulator->GetReferenceParticle();
 
99
  switch (reference_pgparticle.pid) {
 
100
    case MAUS::DataStructure::Global::kEPlus:
 
101
    case MAUS::DataStructure::Global::kMuPlus:
 
102
    case MAUS::DataStructure::Global::kPiPlus:
 
103
      beam_polarity_ = 1;
 
104
      break;
 
105
    case MAUS::DataStructure::Global::kEMinus:
 
106
    case MAUS::DataStructure::Global::kMuMinus:
 
107
    case MAUS::DataStructure::Global::kPiMinus:
 
108
      beam_polarity_ = -1;
 
109
      break;
 
110
    default:
 
111
      throw(Exception(Exception::nonRecoverable,
 
112
                   "Reference particle is not a pion+/-, muon+/-, or e+/-.",
 
113
                   "MapCppGlobalRawTracks::birth()"));
 
114
  }
 
115
 
 
116
  return true;  // Sucessful parsing
 
117
}
 
118
 
 
119
std::string MapCppGlobalRawTracks::process(std::string run_data_string) {
 
120
  // parse the JSON document.
 
121
  Json::Value run_data_json
 
122
    = Json::Value(JsonWrapper::StringToJson(run_data_string));
 
123
  if (run_data_json.isNull() || run_data_json.empty()) {
 
124
    return std::string("{\"errors\":{\"bad_json_document\":"
 
125
                        "\"Failed to parse input document\"}}");
 
126
  }
 
127
 
 
128
  JsonCppSpillConverter deserialize;
 
129
  MAUS::Data * run_data = deserialize(&run_data_json);
 
130
  if (!run_data) {
 
131
    return std::string("{\"errors\":{\"failed_json_cpp_conversion\":"
 
132
                        "\"Failed to convert Json to C++ Data object\"}}");
 
133
  }
 
134
 
 
135
  const MAUS::Spill * spill = run_data->GetSpill();
 
136
  MAUS::ReconEventPArray * recon_events = spill->GetReconEvents();
 
137
  if (!recon_events) {
 
138
    return run_data_string;
 
139
  }
 
140
 
 
141
  MAUS::ReconEventPArray::const_iterator recon_event;
 
142
  MAUS::GlobalEvent * global_event;
 
143
  for (recon_event = recon_events->begin();
 
144
      recon_event != recon_events->end();
 
145
      ++recon_event) {
 
146
    global_event = new GlobalEvent();
 
147
    // Load the ReconEvent, and import it into the GlobalEvent
 
148
    AssembleRawTracks(*recon_event, global_event);
 
149
  }
 
150
 
 
151
  // Serialize the Spill for passing on to the next map in the workflow
 
152
  CppJsonSpillConverter serialize;
 
153
  Json::FastWriter writer;
 
154
  std::string output = writer.write(*serialize(run_data));
 
155
  /*
 
156
  std::cout << "DEBUG MapCppGlobalRawTracks::process(): "
 
157
            << "Output: " << std::endl
 
158
            << output << std::endl;
 
159
  */
 
160
  delete run_data;
 
161
 
 
162
  return output;
 
163
}
 
164
 
 
165
bool MapCppGlobalRawTracks::death() {
 
166
  return true;  // successful
 
167
}
 
168
 
 
169
/** AssembleRawTracks - load data provided by the DAQ system or via digitized MC
 
170
 *
 
171
 *  Pseudocode:
 
172
 *    1) Deserialize TOF and SciFi events
 
173
 *    2) Assemble all raw track permutations
 
174
 *    3) Prune any raw tracks that are unlickly or impossible
 
175
 *    4) Serialize raw tracks
 
176
 */
 
177
void MapCppGlobalRawTracks::AssembleRawTracks(
 
178
    MAUS::ReconEvent * recon_event,
 
179
    MAUS::GlobalEvent * global_event) {
 
180
 
 
181
  // Load TOF and SciFi tracks from the appropriate recon event trees
 
182
  GlobalDS::TrackPArray tracks;
 
183
  /*
 
184
  std::cout << "DEBUG MapCppGlobalRawTracks::AssembleRawTracks(): "
 
185
            << "Loading TOF track..." << std::endl;
 
186
  */
 
187
  LoadTOFTrack(recon_event, tracks);
 
188
  // size_t tof_track_count = tracks.size();
 
189
  /*
 
190
  std::cout << "DEBUG MapCppGlobalRawTracks::AssembleRawTracks(): "
 
191
            << "Loaded " << tof_track_count << " TOF tracks." << std::endl;
 
192
  */
 
193
  /*
 
194
  GlobalDS::TrackPArray sci_fi_tracks;
 
195
  std::cout << "DEBUG MapCppGlobalRawTracks::AssembleRawTracks(): "
 
196
            << "Loading SciFi track..." << std::endl;
 
197
  */
 
198
  LoadSciFiTracks(recon_event, tracks);
 
199
  /*
 
200
  size_t sci_fi_track_count = tracks.size() - tof_track_count;
 
201
  std::cout << "DEBUG MapCppGlobalRawTracks::AssembleRawTracks(): "
 
202
            << "Loaded " << sci_fi_track_count << " SciFi tracks."
 
203
            << std::endl;
 
204
  */
 
205
  GlobalDS::TrackPArray::iterator track;
 
206
  for (track = tracks.begin(); track != tracks.end(); ++track) {
 
207
    if ((*track)->GetTrackPoints().size() >= 2) {
 
208
      (*track)->SortTrackPointsByZ();
 
209
      (*track)->set_mapper_name(kClassname);
 
210
      global_event->add_track_recursive(*track);
 
211
    } else {
 
212
      std::cout << "DEBUG MapCppGlobalRawTracks::AssembleRawTracks(): "
 
213
                << "Skipping track with only " << (*track)->GetTrackPoints().size() << " points."
 
214
                << std::endl;
 
215
    }
 
216
  }
 
217
 
 
218
  recon_event->SetGlobalEvent(global_event);
 
219
}
 
220
 
 
221
/** LoadTOFTrack
 
222
 */
 
223
void MapCppGlobalRawTracks::LoadTOFTrack(
 
224
    MAUS::ReconEvent const * const recon_event,
 
225
    GlobalDS::TrackPArray & tof_tracks) {
 
226
  const int particle_event_number = recon_event->GetPartEventNumber();
 
227
  const TOFEvent * tof_event = recon_event->GetTOFEvent();
 
228
  const TOFEventSpacePoint space_point_events
 
229
    = tof_event->GetTOFEventSpacePoint();
 
230
  const std::vector<TOFSpacePoint> tof0_space_points
 
231
    = space_point_events.GetTOF0SpacePointArray();
 
232
  const std::vector<TOFSpacePoint> tof1_space_points
 
233
    = space_point_events.GetTOF1SpacePointArray();
 
234
  const std::vector<TOFSpacePoint> tof2_space_points
 
235
    = space_point_events.GetTOF2SpacePointArray();
 
236
 
 
237
  // FIXME: Each space point in a particular detector is a separate track branch
 
238
 
 
239
  std::cout << "DEBUG LoadTOFTrack: space points in TOF0: "
 
240
            << tof0_space_points.size() << "\tTOF1: "
 
241
            << tof1_space_points.size() << "\tTOF2: "
 
242
            << tof2_space_points.size() << std::endl;
 
243
  if (tof0_space_points.size() != tof1_space_points.size()) {
 
244
    std::cout << "DEBUG LoadTOFTrack: track has different number of "
 
245
              << "space points in TOF0 (" << tof0_space_points.size() << ")"
 
246
              << " and TOF1 (" << tof1_space_points.size() << ")...skipping."
 
247
              << std::endl;
 
248
    return;
 
249
  } else if (tof0_space_points.size() == 0) {
 
250
    std::cout << "DEBUG LoadTOFTrack: track has no space points...skipping."
 
251
              << std::endl;
 
252
    return;
 
253
  }
 
254
 
 
255
  GlobalDS::Track * track = new GlobalDS::Track();
 
256
 
 
257
  TLorentzVector last_position[3];
 
258
  TLorentzVector deltas[3];
 
259
 
 
260
  GlobalDS::TrackPointPArray track_points;
 
261
 
 
262
  // FIXME(Lane) Replace hard coded slab to coordinate conversion once
 
263
  // Mark Reiner's code has been incorporated into TOF space point code.
 
264
  MAUS::recon::global::DetectorMap::const_iterator tof0_mapping
 
265
    = detectors_.find(GlobalDS::kTOF0);
 
266
  if (tof0_mapping == detectors_.end()) {
 
267
      throw(Exception(Exception::nonRecoverable,
 
268
                   "Unable to find info for detector TOF0",
 
269
                   "MapCppGlobalRawTracks::LoadTOFTrack()"));
 
270
  }
 
271
  const Detector& tof0 = tof0_mapping->second;
 
272
  std::vector<TOFSpacePoint>::const_iterator tof0_space_point;
 
273
  for (tof0_space_point = tof0_space_points.begin();
 
274
       tof0_space_point != tof0_space_points.end();
 
275
       ++tof0_space_point) {
 
276
    GlobalDS::TrackPoint * track_point = new GlobalDS::TrackPoint();
 
277
    track_point->set_particle_event(particle_event_number);
 
278
    PopulateTOFTrackPoint(tof0, tof0_space_point, 40., 10, track_point);
 
279
    track_points.push_back(track_point);
 
280
 
 
281
    last_position[0] = track_point->get_position();
 
282
  }
 
283
 
 
284
  MAUS::recon::global::DetectorMap::const_iterator tof1_mapping
 
285
    = detectors_.find(GlobalDS::kTOF1);
 
286
  if (tof1_mapping == detectors_.end()) {
 
287
      throw(Exception(Exception::nonRecoverable,
 
288
                   "Unable to find info for detector TOF1",
 
289
                   "MapCppGlobalRawTracks::LoadTOFTrack()"));
 
290
  }
 
291
  const Detector& tof1 = tof1_mapping->second;
 
292
  std::vector<TOFSpacePoint>::const_iterator tof1_space_point;
 
293
  for (tof1_space_point = tof1_space_points.begin();
 
294
       tof1_space_point != tof1_space_points.end();
 
295
       ++tof1_space_point) {
 
296
    GlobalDS::TrackPoint * track_point = new GlobalDS::TrackPoint();
 
297
    track_point->set_particle_event(particle_event_number);
 
298
    PopulateTOFTrackPoint(tof1, tof1_space_point, 60., 7, track_point);
 
299
    track_points.push_back(track_point);
 
300
 
 
301
    last_position[1] = track_point->get_position();
 
302
  }
 
303
  deltas[0] = last_position[1] - last_position[0];
 
304
  deltas[1] = deltas[0];
 
305
 
 
306
  MAUS::recon::global::DetectorMap::const_iterator tof2_mapping
 
307
    = detectors_.find(GlobalDS::kTOF2);
 
308
  if (tof2_mapping == detectors_.end()) {
 
309
      throw(Exception(Exception::nonRecoverable,
 
310
                   "Unable to find info for detector TOF2",
 
311
                   "MapCppGlobalRawTracks::LoadTOFTrack()"));
 
312
  }
 
313
  const Detector& tof2 = tof2_mapping->second;
 
314
  std::vector<TOFSpacePoint>::const_iterator tof2_space_point;
 
315
  for (tof2_space_point = tof2_space_points.begin();
 
316
       tof2_space_point != tof2_space_points.end();
 
317
       ++tof2_space_point) {
 
318
    GlobalDS::TrackPoint * track_point = new GlobalDS::TrackPoint();
 
319
    track_point->set_particle_event(particle_event_number);
 
320
    PopulateTOFTrackPoint(tof2, tof2_space_point, 60., 10, track_point);
 
321
    track_points.push_back(track_point);
 
322
 
 
323
    last_position[2] = track_point->get_position();
 
324
  }
 
325
  deltas[2] = last_position[2] - last_position[1];
 
326
 
 
327
  // Approximate momenta by using tof0/tof1 and tof1/tof2 position deltas
 
328
  TLorentzVector momenta[3];
 
329
  for (size_t index = 0; index < 3; ++index) {
 
330
    MAUSGeant4Manager * const simulator = MAUSGeant4Manager::GetInstance();
 
331
    MAUSPrimaryGeneratorAction::PGParticle reference_pgparticle
 
332
      = simulator->GetReferenceParticle();
 
333
    momenta[index] = TLorentzVector(reference_pgparticle.px,
 
334
                                    reference_pgparticle.py,
 
335
                                    reference_pgparticle.pz,
 
336
                                    reference_pgparticle.energy);
 
337
  }
 
338
 
 
339
  // Set each track point's 4-momentum and add to the track
 
340
  std::vector<GlobalDS::TrackPoint *>::iterator track_point;
 
341
  size_t point_index = 0;
 
342
  for (track_point = track_points.begin();
 
343
       track_point != track_points.end();
 
344
       ++track_point) {
 
345
    (*track_point)->set_momentum(momenta[point_index++]);
 
346
 
 
347
    track->AddTrackPoint(*track_point);
 
348
  }
 
349
 
 
350
  MAUSGeant4Manager * const simulator = MAUSGeant4Manager::GetInstance();
 
351
  MAUSPrimaryGeneratorAction::PGParticle reference_pgparticle
 
352
    = simulator->GetReferenceParticle();
 
353
  const GlobalDS::PID particle_id = GlobalDS::PID(reference_pgparticle.pid);
 
354
  track->set_pid(particle_id);
 
355
 
 
356
  tof_tracks.push_back(track);
 
357
}
 
358
 
 
359
/** PopulateTOFTrackPoint
 
360
 */
 
361
void MAUS::MapCppGlobalRawTracks::PopulateTOFTrackPoint(
 
362
    const Detector & detector,
 
363
    const std::vector<TOFSpacePoint>::const_iterator & tof_space_point,
 
364
    const double slab_width,
 
365
    const size_t number_of_slabs,
 
366
    GlobalDS::TrackPoint * track_point) {
 
367
  DataStructureHelper helper = DataStructureHelper::GetInstance();
 
368
  const double z = helper.GetDetectorZPosition(detector.id());
 
369
  std::cerr << "DEBUG MapCppGlobalRawTracks::PopulateTOFTrackPoint: "
 
370
            << std::endl
 
371
            << "\tPhys. Event #: " << tof_space_point->GetPhysEventNumber()
 
372
            << std::endl;
 
373
  std::cerr << "DEBUG MapCppGlobalRawTracks::PopulateTOFTrackPoint: " << std::endl
 
374
            << "\tID: " << detector.id() << std::endl
 
375
            << "\tz-position: " << z << std::endl
 
376
            << "\tUncertainties: " << detector.uncertainties() << std::endl;
 
377
  double max_xy = slab_width * ::floor(number_of_slabs / 2.0);
 
378
  if (number_of_slabs % 2 == 0) {
 
379
    max_xy -= slab_width / 2.0;
 
380
  }
 
381
  std::cerr << "DEBUG MapCppGlobalRawTracks::PopulateTOFTrackPoint: " << std::endl
 
382
            << "\t# Slabs: " << number_of_slabs << std::endl
 
383
            << "\tSlab Width: " << slab_width << std::endl
 
384
            << "\tMax X/Y Value: " << max_xy << std::endl;
 
385
 
 
386
  GlobalDS::SpacePoint * space_point = new GlobalDS::SpacePoint();
 
387
 
 
388
  space_point->set_detector(detector.id());
 
389
 
 
390
  // FIXME(Lane) not sure what to put here
 
391
  space_point->set_geometry_path("");
 
392
 
 
393
  // GetSlaby() gets the number of the slab that is *oriented* in the y
 
394
  // direction For TOF0 this is the slab that gives an approximate x coordinate)
 
395
  // and vice versa. For TOF1 and TOF2 it yields the y coordinate.
 
396
  const double x = slab_width * tof_space_point->GetSlaby() - max_xy;
 
397
  const double y = slab_width * tof_space_point->GetSlabx() - max_xy;
 
398
  const double t = tof_space_point->GetTime();
 
399
  TLorentzVector position(x, y, z, t);
 
400
  space_point->set_position(position);
 
401
  static_cast<GlobalDS::BasePoint*>(track_point)->operator=(*space_point);
 
402
  track_point->set_space_point(space_point);
 
403
  track_point->set_mapper_name(kClassname);
 
404
 
 
405
  track_point->set_position(position);
 
406
  CovarianceMatrix covariances = detector.uncertainties();
 
407
  TLorentzVector position_errors(::sqrt(covariances(3, 3)),
 
408
                                  ::sqrt(covariances(5, 5)),
 
409
                                  0.,
 
410
                                  ::sqrt(covariances(1, 1)));
 
411
  track_point->set_position_error(position_errors);
 
412
 
 
413
  TLorentzVector momentum_errors(::sqrt(covariances(4, 4)),
 
414
                                  ::sqrt(covariances(6, 6)),
 
415
                                  0.,
 
416
                                  ::sqrt(covariances(2, 2)));
 
417
  track_point->set_momentum_error(momentum_errors);
 
418
 
 
419
  track_point->set_charge(tof_space_point->GetChargeProduct());
 
420
}
 
421
 
 
422
/** FindEnergy
 
423
 */
 
424
double MapCppGlobalRawTracks::FindEnergy(const double mass,
 
425
                                         const double delta_z,
 
426
                                         const double actual_delta_t) const {
 
427
  MAUSGeant4Manager * const simulator = MAUSGeant4Manager::GetInstance();
 
428
  MAUSPrimaryGeneratorAction::PGParticle reference_pgparticle
 
429
    = simulator->GetReferenceParticle();
 
430
  const double reference_energy = reference_pgparticle.energy;
 
431
  const double slab_length = 25.;  // mm
 
432
  const double drift_length = delta_z - 2 * slab_length;
 
433
  const double beta_0 = delta_z / actual_delta_t / ::CLHEP::c_light;
 
434
  const double gamma_0 = 1. / std::sqrt(1 - beta_0*beta_0);
 
435
  const double E_0 = gamma_0 * mass;
 
436
  double E = E_0;
 
437
  double beta[4];
 
438
  double delta_t[3];
 
439
  double E_max = reference_energy + 50.;  // allow for momentum spread
 
440
  double E_min = 0;
 
441
  if (beta_0 > 1) {
 
442
    E = E_max;
 
443
  }
 
444
  bool energy_too_low = false;
 
445
 
 
446
  for (size_t iteration = 0; iteration < 10; ++iteration) {
 
447
    double slab_energy_loss = 0.;
 
448
    for (size_t index = 0; index < 4; ++index) {
 
449
      beta[index] = ::sqrt(1 - ::pow(mass / (E - slab_energy_loss), 2));
 
450
      if (beta[index] == 0.) {
 
451
        energy_too_low = true;
 
452
      }
 
453
      slab_energy_loss += TOFSlabEnergyLoss(beta[index], mass);
 
454
      if ((slab_energy_loss > E) || (slab_energy_loss != slab_energy_loss)) {
 
455
        energy_too_low = true;
 
456
      }
 
457
    }
 
458
    delta_t[0] = slab_length / ((beta[0] + beta[1]) / 2) / ::CLHEP::c_light;
 
459
    delta_t[1] = drift_length / beta[1] / ::CLHEP::c_light;
 
460
    delta_t[2] = slab_length / ((beta[1] + beta[2]) / 2) / ::CLHEP::c_light;
 
461
    double total_delta_t = 0.;
 
462
    for (size_t index = 0; index < 3; ++index) {
 
463
      total_delta_t += delta_t[index];
 
464
    }
 
465
    const double residual_delta_t = actual_delta_t - total_delta_t;
 
466
    std::cout << "DEBUG FindEnergy: Actual dt = " << actual_delta_t
 
467
              << "\tdt = " << total_delta_t << std::endl;
 
468
    std::cout << "DEBUG FindEnergy: Min E = " << E_min
 
469
              << "\tMax E = " << E_max << std::endl;
 
470
    if (energy_too_low || (total_delta_t != total_delta_t)
 
471
        || (residual_delta_t < 0.)) {
 
472
      // energy is too low
 
473
      E_min = E;
 
474
      E = (E + E_max) / 2;
 
475
      energy_too_low = false;
 
476
    } else if (residual_delta_t > 0.) {
 
477
      // energy is too high
 
478
      E_max = E;
 
479
      E = (E_min + E) / 2;
 
480
    }
 
481
    std::cout << "DEBUG FindEnergy: E[" << iteration << "] = " << E << std::endl;
 
482
  }
 
483
 
 
484
  return E;
 
485
}
 
486
 
 
487
/** TOFSlabEnergyLoss
 
488
 */
 
489
double MapCppGlobalRawTracks::TOFSlabEnergyLoss(const double beta,
 
490
                                                const double mass) const {
 
491
  const size_t slab_length = 25;  // mm steps
 
492
  double E_0 = mass / ::sqrt(1 - beta*beta);
 
493
  double beta_i = beta;
 
494
  double E_i = E_0;
 
495
  for (size_t step = 0; step < slab_length; ++step) {
 
496
    const double dEdx = TOFMeanStoppingPower(beta_i, mass);
 
497
    E_i -= dEdx;
 
498
    if (E_i < mass) {
 
499
      E_i = mass;
 
500
      break;
 
501
    }
 
502
    beta_i = ::sqrt(1 - ::pow(mass / E_i, 2));
 
503
    std::cout << "DEBUG TOFSlabEnergyLoss: dE/dx[" << step << "]: " << dEdx
 
504
              << "\t E_i: " << E_i
 
505
              << "\t mass: " << mass << "\tbeta_i: " << beta_i << std::endl;
 
506
  }
 
507
  return E_0 - E_i;
 
508
}
 
509
 
 
510
/** TOFMeanStoppingPower
 
511
 */
 
512
double MapCppGlobalRawTracks::TOFMeanStoppingPower(const double beta,
 
513
                                                   const double mass) const {
 
514
  const double gamma = 1. / ::sqrt(1-beta*beta);
 
515
  const double beta2 = beta*beta;
 
516
  const double gamma2 = gamma*gamma;
 
517
  // values are for polystyrene
 
518
  const double density = 1.060;  // g cm^-3
 
519
  const double me = 0.510998918;  // electron mass (MeV/c^2)
 
520
  const double K = 0.307075;  // MeV g^-2 cm^2 mol
 
521
  const double Tmax = 2 * me * beta2 * gamma2
 
522
                    / (1 + 2 * gamma * me/mass + ::pow(me/mass, 2));
 
523
  const double Z_over_A = 0.53768;
 
524
  const double I = 6.87e-5;  // MeV (68.7 eV)
 
525
 
 
526
  std::cout << "DEBUG TOFMeanStoppingPower: beta: " << beta << "\tgamma: "
 
527
            << gamma << "\tTmax: " << Tmax << std::endl;
 
528
  double density_effect = 0.;
 
529
  const double x0 = 0.1647;
 
530
  const double x1 = 2.5031;
 
531
  const double Cbar = 3.2999;
 
532
  const double a = 0.1645;
 
533
  const double k = 3.2224;
 
534
  const double x = beta * gamma;
 
535
  if (x >= x1) {
 
536
    density_effect = 2 * ::log(10) * x - Cbar;
 
537
  } else if ((x0 <= x) && (x < x1)) {
 
538
    density_effect = 2 * ::log(10) * x - Cbar + a * ::pow(x1-x, k);
 
539
  }  // (x < x0)
 
540
 
 
541
  const double log_operand = 2 * me * beta2 * gamma2 * Tmax / (I*I);
 
542
  std::cout << "DEBUG TOFMeanStoppingPower: ln operand: " << log_operand
 
543
            << std::endl;
 
544
 
 
545
  // Bethe-Bloch equation times the density of polystyrene in MeV / mm
 
546
  const double stopping_power
 
547
    = K * Z_over_A / beta2
 
548
    * (  0.5 * ::log(log_operand) - beta2 - density_effect / 2)
 
549
    * density / 10.;
 
550
  std::cout << "DEBUG TOFMeanStoppingPower: Stopping Power: " << stopping_power
 
551
            << std::endl;
 
552
 
 
553
  return stopping_power;
 
554
}
 
555
 
 
556
/** LoadSciFiTracks
 
557
 *  Assumes tracks have already been added to each recon_event.
 
558
 */
 
559
void MapCppGlobalRawTracks::LoadSciFiTracks(
 
560
    MAUS::ReconEvent const * const recon_event,
 
561
    GlobalDS::TrackPArray & tracks) {
 
562
  if (tracks.size() == 0) {
 
563
    // Add a new track if none previously existed
 
564
    GlobalDS::Track * track = new GlobalDS::Track();
 
565
    tracks.push_back(track);
 
566
  }
 
567
  const size_t num_global_tracks = tracks.size();
 
568
 
 
569
  const int particle_event_number = recon_event->GetPartEventNumber();
 
570
 
 
571
  SciFiEvent const * const scifi_event = recon_event->GetSciFiEvent();
 
572
  SciFiTrackPArray scifi_tracks = scifi_event->scifitracks();
 
573
 
 
574
  // Duplicate each global track for each additional SciFi track. When done
 
575
  // the order will be A1,B1,C1,...,A2,B2,C2,...; where A,B,C represent unique
 
576
  // global tracks and 1,2,3 index the SciFi track.
 
577
  const size_t num_scifi_tracks = scifi_tracks.size();
 
578
  tracks.resize(num_global_tracks * num_scifi_tracks);
 
579
  GlobalDS::TrackPArray::iterator track;
 
580
  for (size_t copy_index = 1; copy_index < num_scifi_tracks; ++copy_index) {
 
581
    track = tracks.begin();
 
582
    for (size_t trk_index = 0; trk_index < num_global_tracks; ++trk_index) {
 
583
      tracks.push_back(new GlobalDS::Track(**track));
 
584
      ++track;
 
585
    }
 
586
  }
 
587
  track = tracks.begin();
 
588
 
 
589
  std::cout << "DEBUG MapCppGlobalRawTracks::LoadSciFiTrack: " << std::endl
 
590
            << "\t# Previous Global Tracks: " << num_global_tracks << std::endl
 
591
            << "\t# SciFi Tracks: " << num_scifi_tracks << std::endl
 
592
            << "\tNew # Global Tracks: " << tracks.size() << std::endl;
 
593
 
 
594
  SciFiTrackPArray::const_iterator scifi_track = scifi_tracks.begin();
 
595
  for (; scifi_track != scifi_tracks.end(); ++scifi_track) {
 
596
    SciFiTrackPointPArray scifi_track_points
 
597
      = (*scifi_track)->scifitrackpoints();
 
598
    SciFiTrackPointPArray::const_iterator scifi_track_point
 
599
      = scifi_track_points.begin();
 
600
    GlobalDS::TrackPArray::iterator track_begin = track;
 
601
    GlobalDS::TrackPArray::iterator track_end = track + num_global_tracks;
 
602
    for (; scifi_track_point != scifi_track_points.end(); ++scifi_track_point) {
 
603
      const int tracker = (*scifi_track_point)->tracker();
 
604
      const int station = (*scifi_track_point)->station();
 
605
      std::cout << "DEBUG MapCppGlobalRawTracks::LoadSciFiTrack: " << std::endl
 
606
                << "\tTracker: " << tracker << "\tStation: " << station
 
607
                << "\tPz: " << (*scifi_track_point)->pz() << std::endl;
 
608
      const GlobalDS::DetectorPoint detector_id = GlobalDS::DetectorPoint(
 
609
          GlobalDS::kTracker0 + 6 * tracker + station);
 
610
      MAUS::recon::global::DetectorMap::const_iterator detector_mapping
 
611
        = detectors_.find(detector_id);
 
612
      if (detector_mapping == detectors_.end()) {
 
613
        std::stringstream message;
 
614
        message << "Couldn't find configuration for detector Tracker "
 
615
                << tracker << " Station " << station
 
616
                << "(id=" << detector_id << ")";
 
617
        throw(Exception(Exception::nonRecoverable,
 
618
                     message.str(),
 
619
                     "MapCppGlobalRawTracks::LoadSciFiTrack()"));
 
620
      }
 
621
      const Detector& detector = detector_mapping->second;
 
622
      GlobalDS::TrackPoint * track_point = new GlobalDS::TrackPoint();
 
623
      track_point->set_particle_event(particle_event_number);
 
624
      PopulateSciFiTrackPoint(detector, scifi_track_point, track_point);
 
625
 
 
626
      MAUSGeant4Manager * const simulator = MAUSGeant4Manager::GetInstance();
 
627
      MAUSPrimaryGeneratorAction::PGParticle reference_pgparticle
 
628
        = simulator->GetReferenceParticle();
 
629
      const GlobalDS::PID particle_id = GlobalDS::PID(reference_pgparticle.pid);
 
630
 
 
631
      // For each SciFi track, add it's track points to the associated set of
 
632
      // global track copies
 
633
      for (; track != track_end; ++track) {
 
634
        if (track == tracks.end()) {
 
635
          throw(Exception(Exception::nonRecoverable,
 
636
                       "insufficient number of global tracks to accomodate"
 
637
                       "the number of SciFi tracks",
 
638
                       "MapCppGlobalRawTracks::LoadSciFiTracks()"));
 
639
        }
 
640
        // FIXME(Lane) this will have to change once PID functionality exists
 
641
        (*track)->set_pid(particle_id);
 
642
 
 
643
        std::cout << "DEBUG MapCppGlobalRawTracks::LoadSciFiTracks(): "
 
644
                  << "Adding track point...";
 
645
        (*track)->AddTrackPoint(track_point);
 
646
        std::cout << "DONE!" << std::endl;
 
647
      }  // end for loop over global tracks
 
648
      track = track_begin;  // reset for next SciFi track point
 
649
    }  // end for loop over SciFi track points
 
650
    track += num_global_tracks;  // go to the next set of global tracks
 
651
  }  // end for loop over SciFi tracks
 
652
}
 
653
 
 
654
/** PopulateSciFiTrackPoint
 
655
 */
 
656
void MapCppGlobalRawTracks::PopulateSciFiTrackPoint(
 
657
    const MAUS::recon::global::Detector & detector,
 
658
    const SciFiTrackPointPArray::const_iterator & scifi_track_point,
 
659
    GlobalDS::TrackPoint * track_point) {
 
660
  GlobalDS::SpacePoint * space_point = new GlobalDS::SpacePoint();
 
661
 
 
662
  space_point->set_detector(detector.id());
 
663
 
 
664
  // FIXME(Lane) not sure what to put here
 
665
  space_point->set_geometry_path("");
 
666
 
 
667
  MAUSGeant4Manager * const simulator = MAUSGeant4Manager::GetInstance();
 
668
  MAUSPrimaryGeneratorAction::PGParticle reference_pgparticle
 
669
    = simulator->GetReferenceParticle();
 
670
 
 
671
  DataStructureHelper helper = DataStructureHelper::GetInstance();
 
672
  const double x = (detector.id() <= GlobalDS::kTracker0_5)?
 
673
                   -(*scifi_track_point)->x():(*scifi_track_point)->x();
 
674
  const double y = (*scifi_track_point)->y();
 
675
  const double z = helper.GetDetectorZPosition(detector.id());
 
676
  std::cout << "DEBUG MapCppGlobalRawTracks::PopulateSciFiTrackPoint: "
 
677
            << "z position of detector with ID " << detector.id() << " is "
 
678
            << z << std::endl;
 
679
  // No timestamp in the SciFiEvent/Track/TrackPoint data structure
 
680
  const double time = 0.;
 
681
  TLorentzVector four_position(x, y, z, time);
 
682
  space_point->set_position(four_position);
 
683
 
 
684
  static_cast<GlobalDS::BasePoint*>(track_point)->operator=(*space_point);
 
685
  track_point->set_space_point(space_point);
 
686
 
 
687
  track_point->set_mapper_name(kClassname);
 
688
 
 
689
  const double Px = (*scifi_track_point)->px();
 
690
  const double Py = (*scifi_track_point)->py();
 
691
  const double Pz = (*scifi_track_point)->pz();
 
692
  const double momentum = ::sqrt(Px*Px + Py*Py + Pz*Pz);
 
693
  const GlobalDS::PID particle_id = GlobalDS::PID(reference_pgparticle.pid);
 
694
  const double beta = Beta(particle_id, momentum);
 
695
  const double energy = momentum / beta;
 
696
  TLorentzVector four_momentum(Px, Py, Pz, energy);
 
697
  track_point->set_momentum(four_momentum);
 
698
  std::cout << "DEBUG MapCppGlobalRawTracks::PopulateSciFiTrackPoint(): "
 
699
            << "\tSciFi Space Point:" << std::endl
 
700
            << std::setprecision(10)
 
701
            << "\tTime: " << time << "\tEnergy: " << energy << std::endl
 
702
            << "\t4-Position: (" << four_position.X() << ", "
 
703
            << four_position.Y() << ", " << four_position.Z() << ", "
 
704
            << four_position.T() << ")" << std::endl
 
705
            << "\tMomentum: (" << four_momentum.Px() << ", "
 
706
            << four_momentum.Py() << ", " << four_momentum.Pz() << ", "
 
707
            << four_momentum.Pt() << ")" << std::endl;
 
708
  CovarianceMatrix covariances = detector.uncertainties();
 
709
  TLorentzVector position_errors(::sqrt(covariances(3, 3)),
 
710
                                  ::sqrt(covariances(5, 5)),
 
711
                                  0.,
 
712
                                  ::sqrt(covariances(1, 1)));
 
713
  track_point->set_position_error(position_errors);
 
714
 
 
715
  TLorentzVector momentum_errors(::sqrt(covariances(4, 4)),
 
716
                                  ::sqrt(covariances(6, 6)),
 
717
                                  0.,
 
718
                                  ::sqrt(covariances(2, 2)));
 
719
  track_point->set_momentum_error(momentum_errors);
 
720
 
 
721
  // track_point->set_charge((*scifi_track_point)->get_npe());
 
722
  std::cout << "DEBUG MapCppGlobalRawTracks::PopulateSciFiTrackPoint(): END!"
 
723
            << std::endl;
 
724
}
 
725
 
 
726
/* Take an educated guess at the particle ID based on the axial velocity
 
727
 * of the particle (beta)
 
728
 */
 
729
GlobalDS::PID MapCppGlobalRawTracks::IdentifyParticle(const double beta) {
 
730
  MAUSGeant4Manager * const simulator = MAUSGeant4Manager::GetInstance();
 
731
  MAUSPrimaryGeneratorAction::PGParticle reference_pgparticle
 
732
    = simulator->GetReferenceParticle();
 
733
  const double reference_momentum = reference_pgparticle.pz;  // good enough
 
734
  const double beta_pi = Beta(GlobalDS::kPiPlus, reference_momentum);
 
735
  const double beta_mu = Beta(GlobalDS::kMuPlus, reference_momentum);
 
736
  const double beta_e = Beta(GlobalDS::kEPlus, reference_momentum);
 
737
  std::cout << "DEBUG MapCppGlobalRawTracks::IdentifyParticle(): " << std::endl
 
738
            << "\tbeta = " << beta << "\tbeta_pi = " << beta_pi << std::endl
 
739
            << "\tbeta_mu = " << beta_mu << "\tbeta_e = " << beta_e << std::endl;
 
740
 
 
741
  const double beta_fit[3] = {
 
742
    std::abs(1. - beta / beta_pi),
 
743
    std::abs(1. - beta / beta_mu),
 
744
    std::abs(1. - beta / beta_e)
 
745
  };
 
746
  std::cout << "DEBUG MapCppGlobalRawTracks::IdentifyParticle(): "
 
747
            << "beta fits {" << std::endl << std::setprecision(4)
 
748
            << "\t" << 1. - beta / beta_pi
 
749
            << "\t" << beta_fit[1]
 
750
            << "\t" << beta_fit[2]
 
751
            << std::endl << "}" << std::endl;
 
752
  size_t min_index = 0;
 
753
  for (size_t index = 1; index < 3; ++index) {
 
754
    if (beta_fit[index] < beta_fit[min_index]) {
 
755
      min_index = index;
 
756
    }
 
757
  }
 
758
 
 
759
  GlobalDS::PID particle_id = GlobalDS::kNoPID;
 
760
  switch (min_index) {
 
761
    case 0: particle_id = GlobalDS::PID(GlobalDS::kPiPlus * beam_polarity_);
 
762
            break;
 
763
    case 1: particle_id = GlobalDS::PID(GlobalDS::kMuPlus * beam_polarity_);
 
764
            break;
 
765
    case 2: particle_id = GlobalDS::PID(GlobalDS::kEPlus * beam_polarity_);
 
766
            break;
 
767
  }
 
768
 
 
769
  return particle_id;
 
770
}
 
771
 
 
772
double MapCppGlobalRawTracks::Beta(GlobalDS::PID pid, const double momentum) {
 
773
  const double mass = Particle::GetInstance().GetMass(pid);
 
774
  const double one_over_beta_squared
 
775
    = 1+ (mass*mass) / (momentum*momentum);
 
776
  return 1. / std::sqrt(one_over_beta_squared);
 
777
}
 
778
 
 
779
const std::string MapCppGlobalRawTracks::kClassname
 
780
  = "MapCppGlobalRawTracks";
 
781
 
 
782
}  // namespace MAUS
 
783