source: trunk/MagicSoft/Mars/msim/MPhotonEvent.cc@ 9347

Last change on this file since 9347 was 9342, checked in by tbretz, 18 years ago
*** empty log message ***
File size: 12.1 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of CheObs, the Modular Analysis and Reconstruction
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
7! * It is distributed WITHOUT ANY WARRANTY.
8! *
9! * Permission to use, copy, modify and distribute this software and its
10! * documentation for any purpose is hereby granted without fee,
11! * provided that the above copyright notice appears in all copies and
12! * that both that copyright notice and this permission notice appear
13! * in supporting documentation. It is provided "as is" without express
14! * or implied warranty.
15! *
16!
17!
18! Author(s): Thomas Bretz, 12/2000 <mailto:tbretz@astro.uni-wuerzburg.de>
19! Author(s): Qi Zhe, 06/2007 <mailto:qizhe@astro.uni-wuerzburg.de>
20!
21! Copyright: CheObs Software Development, 2000-2009
22!
23!
24\* ======================================================================== */
25
26/////////////////////////////////////////////////////////////////////////////
27//
28// MPhotonEvent
29//
30// Storage container to store photon collections
31//
32// The class is designed to be extremely fast which is important taking into
33// account the extremely high number of photons. This has some impacts on
34// its handling.
35//
36// The list has to be kept consistent, i.e. without holes.
37//
38// There are two ways to achieve this:
39//
40// a) Use RemoveAt to remove an entry somewhere
41// b) Compress() the TClonesArray afterwards
42//
43// Compress is not the fastes, so there is an easier way.
44//
45// a) When you loop over the list and want to remove an entry copy all
46// following entry backward in the list, so that the hole will
47// be created at its end.
48// b) Call Shrink(n) with n the number of valid entries in your list.
49//
50// To loop over the TClonesArray you can use a TIter which has some
51// unnecessary overhead and therefore is slower than necessary.
52//
53// Since the list is kept consistent you can use a simple loop saving
54// a lot of CPU time taking into account the high number of calls to
55// TObjArrayIter::Next which you would create.
56//
57// Here is an example (how to remove every second entry)
58//
59// ---------------------------------------------------------------------
60//
61// Int_t cnt = 0;
62//
63// const Int_t num = event->GetNumPhotons();
64// for (Int_t idx=0; idx<num; idx++)
65// {
66// if (idx%2==0)
67// continue;
68//
69// MPhotonData *dat = (*event)[idx];
70//
71// (*event)[cnt++] = *dat;
72// }
73//
74// event->Shrink(cnt);
75//
76// ---------------------------------- or -------------------------------
77//
78// TClonesArray &arr = MPhotonEvent->GetArray();
79//
80// Int_t cnt = 0;
81//
82// const Int_t num = arr.GetEntriesFast();
83// for (Int_t idx=0; idx<num; idx++)
84// {
85// if (idx%2==0)
86// continue;
87//
88// MPhotonData *dat = static_cast<MPhotonData*>(arr.UncheckedAt(idx));
89//
90// *static_cast<MPhotonData*>(arr.UncheckedAt(cnt++)) = *dat;
91// }
92//
93// MPhotonEvent->Shrink(cnt);
94//
95// ---------------------------------------------------------------------
96//
97// The flag for a sorted array is for speed reasons not in all conditions
98// maintained automatically. Especially Add() doesn't reset it.
99//
100// So be sure that if you want to sort your array it is really sorted.
101//
102//
103// Version 1:
104// ----------
105// - First implementation
106//
107/////////////////////////////////////////////////////////////////////////////
108#include "MPhotonEvent.h"
109
110#include <fstream>
111#include <iostream>
112
113#include <TMarker.h>
114
115#include <MMath.h>
116
117#include "MArrayF.h"
118
119#include "MLog.h"
120#include "MLogManip.h"
121
122#include "MPhotonData.h"
123
124ClassImp(MPhotonEvent);
125
126using namespace std;
127
128// --------------------------------------------------------------------------
129//
130// Default constructor. It initializes all arrays with zero size.
131//
132MPhotonEvent::MPhotonEvent(const char *name, const char *title)
133 : fData("MPhotonData", 1)
134{
135 fName = name ? name : "MPhotonEvent";
136 fTitle = title ? title : "Corsika Event Data Information";
137
138 fData.SetBit(TClonesArray::kForgetBits);
139 fData.BypassStreamer(kFALSE);
140}
141
142/*
143const char *MPhotonEvent::GetClassName() const
144{
145 return static_cast<TObject*>(fData.GetClass())->GetName();
146}
147*/
148
149// --------------------------------------------------------------------------
150//
151// If n is smaller than the current allocated array size a reference to
152// the n-th entry is returned, otherwise an entry at n is created
153// calling the default constructor. Note, that there is no range check
154// but it is not recommended to call this function with
155// n>fData.GetSize()
156//
157MPhotonData &MPhotonEvent::Add(Int_t n)
158{
159 // Do not modify this. It is optimized for execution
160 // speed and flexibility!
161 TObject *o = n<fData.GetSize() && fData.UncheckedAt(n) ? fData.UncheckedAt(n) : fData.New(n);
162
163 // Now we read a single cherenkov bunch
164 return static_cast<MPhotonData&>(*o);
165}
166
167// --------------------------------------------------------------------------
168//
169// Add a new photon (MPhtonData) at the end of the array.
170// In this case the default constructor of MPhotonData is called.
171//
172// A reference to the new object is returned.
173//
174MPhotonData &MPhotonEvent::Add()
175{
176 return Add(GetNumPhotons());
177}
178
179// --------------------------------------------------------------------------
180//
181// Get the i-th photon from the array. Not, for speed reasons there is no
182// range check so you are responsible that you do not excess the number
183// of photons (GetNumPhotons)
184//
185MPhotonData &MPhotonEvent::operator[](UInt_t idx)
186{
187 return *static_cast<MPhotonData*>(fData.UncheckedAt(idx));
188}
189
190// --------------------------------------------------------------------------
191//
192// Get the i-th photon from the array. Not, for speed reasons there is no
193// range check so you are responsible that you do not excess the number
194// of photons (GetNumPhotons)
195//
196const MPhotonData &MPhotonEvent::operator[](UInt_t idx) const
197{
198 return *static_cast<MPhotonData*>(fData.UncheckedAt(idx));
199}
200
201// --------------------------------------------------------------------------
202//
203// Return a pointer to the first photon if available.
204//
205MPhotonData *MPhotonEvent::GetFirst() const
206{
207 return static_cast<MPhotonData*>(fData.First());
208}
209
210// --------------------------------------------------------------------------
211//
212// Return a pointer to the last photon if available.
213//
214MPhotonData *MPhotonEvent::GetLast() const
215{
216 return static_cast<MPhotonData*>(fData.Last());
217}
218
219// --------------------------------------------------------------------------
220//
221// Return the number of "external" photons, i.e. which are not NightSky
222//
223Int_t MPhotonEvent::GetNumExternal() const
224{
225 Int_t n=0;
226
227 for (int i=0; i<GetNumPhotons(); i++)
228 if ((*this)[i].GetPrimary()!=MMcEvtBasic::kNightSky)
229 n++;
230
231 return n;
232}
233
234// --------------------------------------------------------------------------
235//
236// Return time of first photon, 0 if none in array.
237// Note: If you want this to be the earliest make sure that the array
238// is properly sorted.
239//
240Float_t MPhotonEvent::GetTimeFirst() const
241{
242 const MPhotonData *dat=GetFirst();
243 return dat ? dat->GetTime() : 0;
244}
245
246// --------------------------------------------------------------------------
247//
248// Return time of first photon, 0 if none in array.
249// Note: If you want this to be the latest make sure that the array
250// is properly sorted.
251//
252Float_t MPhotonEvent::GetTimeLast() const
253{
254 const MPhotonData *dat=GetLast();
255 return dat ? dat->GetTime() : 0;
256}
257
258// --------------------------------------------------------------------------
259//
260// Return the median devian from the median of all arrival times.
261// The median deviation is calculated using MMath::MedianDev.
262// It is the half width in which one sigma (~68%) of all times are
263// contained around the median.
264//
265Double_t MPhotonEvent::GetTimeMedianDev() const
266{
267 const UInt_t n = GetNumPhotons();
268
269 MArrayF arr(n);
270 for (UInt_t i=0; i<n; i++)
271 arr[i] = operator[](i).GetTime();
272
273 return MMath::MedianDev(n, arr.GetArray()/*, Double_t &med*/);
274}
275
276// --------------------------------------------------------------------------
277//
278// Read the Event section from the file
279//
280Int_t MPhotonEvent::ReadCorsikaEvt(istream &fin)
281{
282 Int_t n = 0;
283
284 while (1)
285 {
286 // Check the first four bytes
287 char c[4];
288 fin.read(c, 4);
289
290 // End of stream
291 if (!fin)
292 return kFALSE;
293
294 // Check if we found the end of the event
295 if (!memcmp(c, "EVTE", 4))
296 break;
297
298 // The first for byte contained data already --> go back
299 fin.seekg(-4, ios::cur);
300
301 // Do not modify this. It is optimized for execution
302 // speed and flexibility!
303 MPhotonData &ph = Add(n);
304 // It checks how many entries the lookup table has. If it has enough
305 // entries and the entry was already allocated, we can re-use it,
306 // otherwise we have to allocate it.
307
308 // Now we read a single cherenkov bunch. Note that for speed reason we have not
309 // called the constructor if the event was already constructed (virtual table
310 // set), consequently we must make sure that ReadCorsikaEvent does reset
311 // all data mebers no matter whether they are read or not.
312 const Int_t rc = ph.ReadCorsikaEvt(fin);
313
314 // Evaluate result from reading event
315 switch (rc)
316 {
317 case kCONTINUE: continue; // No data in this bunch... skip it.
318 case kFALSE: return kFALSE; // End of stream
319 case kERROR: return kERROR; // Error occured
320 }
321
322 // FIXME: If fNumPhotons!=1 add the photon more than once
323
324 // Now increase the number of entries which are kept,
325 // i.e. keep this photon(s)
326 n++;
327 }
328
329 Shrink(n);
330 fData.UnSort();
331
332 SetReadyToSave();
333
334 //*fLog << all << "Number of photon bunches: " << fData.GetEntriesFast() << endl;
335 return kTRUE;
336}
337
338// --------------------------------------------------------------------------
339//
340Int_t MPhotonEvent::ReadRflEvt(std::istream &fin)
341{
342 Int_t n = 0;
343
344 while (1)
345 {
346 // Check the first four bytes
347 char c[13];
348 fin.read(c, 13);
349
350 // End of stream
351 if (!fin)
352 return kFALSE;
353
354 // Check if we found the end of the event
355 if (!memcmp(c, "\nEND---EVENT\n", 13))
356 break;
357
358 // The first for byte contained data already --> go back
359 fin.seekg(-13, ios::cur);
360
361 // Do not modify this. It is optimized for execution
362 // speed and flexibility!
363 //TObject *o = n<fData.GetSize() && fData.UncheckedAt(n) ? fData.UncheckedAt(n) : fData.New(n);
364
365 // Now we read a single cherenkov bunch
366 //const Int_t rc = static_cast<MPhotonData*>(o)->ReadRflEvt(fin);
367 const Int_t rc = Add(n).ReadRflEvt(fin);
368
369 // Evaluate result from reading event
370 switch (rc)
371 {
372 case kCONTINUE: continue; // No data in this bunch... skip it.
373 case kFALSE: return kFALSE; // End of stream
374 case kERROR: return kERROR; // Error occured
375 }
376
377 // Now increase the number of entries which are kept,
378 // i.e. keep this photon(s)
379 n++;
380 }
381
382 Shrink(n);
383
384 SetReadyToSave();
385
386 //*fLog << all << "Number of photon bunches: " << fData.GetEntriesFast() << endl;
387 return kTRUE;
388}
389
390// --------------------------------------------------------------------------
391//
392// Print the array
393//
394void MPhotonEvent::Print(Option_t *) const
395{
396 fData.Print();
397}
398
399// ------------------------------------------------------------------------
400//
401// You can call Draw() to add the photons to the current pad.
402// The photons are painted each tim ethe pad is updated.
403// Make sure that you use the right (world) coordinate system,
404// like created, eg. by the MHCamera histogram.
405//
406void MPhotonEvent::Paint(Option_t *)
407{
408 MPhotonData *ph=NULL;
409
410 TMarker m;
411 m.SetMarkerStyle(kFullDotMedium); // Gtypes.h
412
413 TIter Next(&fData);
414 while ((ph=(MPhotonData*)Next()))
415 {
416 m.SetX(ph->GetPosY()*10); // north
417 m.SetY(ph->GetPosX()*10); // east
418 m.Paint();
419 }
420}
Note: See TracBrowser for help on using the repository browser.