]> git.uio.no Git - u/mrichter/AliRoot.git/blame - MUON/AliMUONDigitizer.cxx
New segmentation with switch between old and new (Ch. Finck)
[u/mrichter/AliRoot.git] / MUON / AliMUONDigitizer.cxx
CommitLineData
28752ff4 1/**************************************************************************
2 * Copyright(c) 1998-2000, ALICE Experiment at CERN, All rights reserved. *
3 * *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
6 * *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
15
88cb7938 16/* $Id$ */
ba030c0e 17
cf286af7 18#include "AliRun.h"
19#include "AliRunDigitizer.h"
88cb7938 20#include "AliRunLoader.h"
88cb7938 21
22#include "AliMUONDigitizer.h"
23#include "AliMUONConstants.h"
24#include "AliMUONChamber.h"
25#include "AliMUONHitMapA1.h"
28752ff4 26#include "AliMUON.h"
30178c30 27#include "AliMUONLoader.h"
116cbefd 28#include "AliMUONChamber.h"
29#include "AliMUONConstants.h"
116cbefd 30#include "AliMUONDigitizer.h"
28752ff4 31#include "AliMUONTransientDigit.h"
30178c30 32#include "AliMUONHitMapA1.h"
ce3e25a8 33#include "AliMUONTriggerDecision.h"
8c343c7c 34#include "AliLog.h"
30178c30 35
cf286af7 36
37/////////////////////////////////////////////////////////////////////////////////////
38//
39// AliMUONDigitizer should be base abstract class of all digitisers in the MUON
40// module. It implements the common functionality of looping over input streams
41// filling the fTDList and writing the fTDList to the output stream.
42// Inheriting digitizers need to override certain methods to choose and initialize
43// the correct input and output trees, apply the correct detector response if any
44// and implement how the transient digits are generated from the input stream.
45//
46/////////////////////////////////////////////////////////////////////////////////////
28752ff4 47
48ClassImp(AliMUONDigitizer)
49
50//___________________________________________
cf286af7 51AliMUONDigitizer::AliMUONDigitizer() :
52 AliDigitizer(),
53 fHitMap(0),
54 fTDList(0),
55 fTDCounter(0),
56 fMask(0),
57 fSignal(0),
58 fDebug(0)
28752ff4 59{
cf286af7 60// Default constructor.
61// Initializes all pointers to NULL.
62
30178c30 63 fRunLoader = NULL;
64 fGime = NULL;
65 fMUON = NULL;
66 fMUONData = NULL;
ce3e25a8 67 fTrigDec = NULL;
925e6570 68}
28752ff4 69
70//___________________________________________
cf286af7 71AliMUONDigitizer::AliMUONDigitizer(AliRunDigitizer* manager) :
72 AliDigitizer(manager),
73 fHitMap(0),
74 fTDList(0),
75 fTDCounter(0),
76 fMask(0),
77 fSignal(0),
78 fDebug(0)
28752ff4 79{
cf286af7 80// Constructor which should be used rather than the default constructor.
81// Initializes all pointers to NULL.
82
30178c30 83 fRunLoader = NULL;
84 fGime = NULL;
85 fMUON = NULL;
86 fMUONData = NULL;
ce3e25a8 87 fTrigDec = NULL;
925e6570 88}
28752ff4 89
11ca64ac 90//___________________________________________
91AliMUONDigitizer::AliMUONDigitizer(const AliMUONDigitizer& rhs)
92 : AliDigitizer(rhs)
93{
94// Protected copy constructor
95
8c343c7c 96 AliFatal("Not implemented.");
11ca64ac 97}
98
8789635b 99//___________________________________________
100AliMUONDigitizer::~AliMUONDigitizer()
101{
102// Destructor
ce3e25a8 103 if (fMUONData)
104 delete fMUONData;
105
106 if (fTrigDec)
107 delete fTrigDec;
8789635b 108}
109
11ca64ac 110//-------------------------------------------------------------------
111AliMUONDigitizer&
112AliMUONDigitizer::operator=(const AliMUONDigitizer& rhs)
113{
114// Protected assignement operator
115
116 if (this == &rhs) return *this;
117
8c343c7c 118 AliFatal("Not implemented.");
11ca64ac 119
120 return *this;
121}
a713db22 122
123//------------------------------------------------------------------------
124Int_t AliMUONDigitizer::GetSegmentation()
125{
126 if (!fMUON->WhichSegmentation()) {
127 AliFatal("No Segmentation Type defined.");
128 return kFALSE;
129 } else
130 return fMUON->WhichSegmentation();
131
132}
133
28752ff4 134//------------------------------------------------------------------------
cf286af7 135Bool_t AliMUONDigitizer::Init()
28752ff4 136{
cf286af7 137// Does nothing.
138 return kTRUE;
28752ff4 139}
140
141//------------------------------------------------------------------------
cf286af7 142void AliMUONDigitizer::Exec(Option_t* option)
28752ff4 143{
cf286af7 144// The main work loop starts here.
145// The digitization process is broken up into two steps:
146// 1) Loop over input streams and create transient digits from the input.
147// Done in GenerateTransientDigits()
148// 2) Loop over the generated transient digits and write them to the output
149// stream. Done in CreateDigits()
150
8c343c7c 151 AliDebug(1, "Running digitiser.");
cf286af7 152 ParseOptions(option);
153
154 if (fManager->GetNinputs() == 0)
155 {
8c343c7c 156 AliWarning("No inputs set, nothing to do.");
cf286af7 157 return;
925e6570 158 }
cf286af7 159
ce3e25a8 160 if (!FetchLoaders(fManager->GetInputFolderName(0), fRunLoader, fGime) ) return;
30178c30 161 if (! FetchGlobalPointers(fRunLoader) ) return;
ce3e25a8 162 if (! FetchTriggerPointer(fGime) ) return;
cf286af7 163
164 InitArrays();
165
8c343c7c 166 AliDebug(2, Form("Event Number is %d.", fManager->GetOutputEventNr()));
cf286af7 167
168 // Loop over files to merge and to digitize
169 fSignal = kTRUE;
170 for (Int_t inputFile = 0; inputFile < fManager->GetNinputs(); inputFile++)
171 {
172 fMask = fManager->GetMask(inputFile);
8c343c7c 173 AliDebug(2, Form("Digitising folder %d, with fMask = %d: %s", inputFile, fMask,
174 (const char*)fManager->GetInputFolderName(inputFile)));
cf286af7 175
176 if (inputFile != 0)
177 // If this is the first file then we already have the loaders loaded.
30178c30 178 if (! FetchLoaders(fManager->GetInputFolderName(inputFile), fRunLoader, fGime) )
cf286af7 179 continue;
180 else
181 // If this is not the first file then it is assumed to be background.
182 fSignal = kFALSE;
183
30178c30 184 if (! InitInputData(fGime) ) continue;
cf286af7 185 GenerateTransientDigits();
30178c30 186 CleanupInputData(fGime);
925e6570 187 }
cf286af7 188
30178c30 189 Bool_t ok = FetchLoaders(fManager->GetOutputFolderName(), fRunLoader, fGime);
190 if (ok) ok = InitOutputData(fGime);
cf286af7 191 if (ok) CreateDigits();
ce3e25a8 192 if (ok) CreateTrigger();
30178c30 193 if (ok) CleanupOutputData(fGime);
cf286af7 194
195 CleanupArrays();
ce3e25a8 196 CleanupTriggerArrays();
925e6570 197}
cf286af7 198
199//--------------------------------------------------------------------------
200void AliMUONDigitizer::AddOrUpdateTransientDigit(AliMUONTransientDigit* mTD)
201{
202// Checks to see if the transient digit exists in the corresponding fHitMap.
203// If it does then the digit is updated otherwise it is added.
204
205 if (ExistTransientDigit(mTD))
206 {
207 UpdateTransientDigit(mTD);
208 delete mTD; // The new digit can be deleted because it was not added.
209 }
210 else
211 AddTransientDigit(mTD);
925e6570 212}
28752ff4 213
214//------------------------------------------------------------------------
cf286af7 215void AliMUONDigitizer::UpdateTransientDigit(AliMUONTransientDigit* mTD)
28752ff4 216{
cf286af7 217// Update the transient digit that is already in the fTDList by adding the new
218// transient digits charges and track lists to the existing one.
219
8c343c7c 220 AliDebug(4,Form( "Updating transient digit 0x%X", (void*)mTD));
cf286af7 221 // Choosing the maping of the cathode plane of the chamber:
222 Int_t iNchCpl= mTD->Chamber() + (mTD->Cathode()-1) * AliMUONConstants::NCh();
223 AliMUONTransientDigit *pdigit =
224 static_cast<AliMUONTransientDigit*>( fHitMap[iNchCpl]->GetHit(mTD->PadX(),mTD->PadY()) );
225
226 // update charge
227 pdigit->AddSignal( mTD->Signal() );
228 pdigit->AddPhysicsSignal( mTD->Physics() );
229
230 // update list of tracks
231 Int_t ntracks = mTD->GetNTracks();
232 if (ntracks > kMAXTRACKS) // Truncate the number of tracks to kMAXTRACKS if we have to.
233 {
8c343c7c 234 AliDebug(1,Form(
235 "TransientDigit returned the number of tracks to be %d, which is bigger than kMAXTRACKS.",
236 ntracks));
237 AliDebug(1,Form( "Reseting the number of tracks to be %d.", kMAXTRACKS));
cf286af7 238 ntracks = kMAXTRACKS;
925e6570 239 }
cf286af7 240
241 for (Int_t i = 0; i < ntracks; i++)
242 {
243 pdigit->UpdateTrackList( mTD->GetTrack(i), mTD->GetCharge(i) );
925e6570 244 }
245}
28752ff4 246
247//------------------------------------------------------------------------
cf286af7 248void AliMUONDigitizer::AddTransientDigit(AliMUONTransientDigit* mTD)
28752ff4 249{
cf286af7 250// Adds the transient digit to the fTDList and sets the appropriate entry
251// in the fHitMap arrays.
252
8c343c7c 253 AliDebug(4,Form( "Adding transient digit 0x%X", (void*)mTD));
cf286af7 254 // Choosing the maping of the cathode plane of the chamber:
255 Int_t iNchCpl= mTD->Chamber() + (mTD->Cathode()-1) * AliMUONConstants::NCh();
256 fTDList->AddAtAndExpand(mTD, fTDCounter);
257 fHitMap[iNchCpl]->SetHit( mTD->PadX(), mTD->PadY(), fTDCounter);
258 fTDCounter++;
925e6570 259}
28752ff4 260
261//------------------------------------------------------------------------
cf286af7 262Bool_t AliMUONDigitizer::ExistTransientDigit(AliMUONTransientDigit* mTD)
28752ff4 263{
cf286af7 264// Checks if the transient digit already exists on the corresponding fHitMap.
265// i.e. is there a transient digit on the same chamber, cathode and pad position
266// as mTD. If yes then kTRUE is returned else kFASLE is returned.
267
268 // Choosing the maping of the cathode plane of the chamber:
269 Int_t iNchCpl= mTD->Chamber() + (mTD->Cathode()-1) * AliMUONConstants::NCh();
270 return( fHitMap[iNchCpl]->TestHit(mTD->PadX(), mTD->PadY()) );
925e6570 271}
28752ff4 272
cf286af7 273//-----------------------------------------------------------------------
274void AliMUONDigitizer::CreateDigits()
275{
276// Loops over the fTDList for each cathode, gets the correct signal for the
277// digit and adds the new digit to the output stream.
278
a713db22 279 fTDList->Sort(); // sort by idDE
280 AliDebug(2, "Creating digits...");
281 for (Int_t icat = 0; icat < 2; icat++) {
282
283 //
284 // Filling Digit List
285 Int_t nentries = fTDList->GetEntriesFast();
286 for (Int_t nent = 0; nent < nentries; nent++) {
287
288 AliMUONTransientDigit* td = (AliMUONTransientDigit*)fTDList->At(nent);
289 if (td == NULL) continue;
cf286af7 290
a713db22 291 // Must be the same cathode, otherwise we will fill a mixture
292 // of digits from both cathodes.
293 if (icat != td->Cathode() - 1) continue;
cf286af7 294
a713db22 295 AliDebug(3,Form( "Creating digit from transient digit 0x%X", (void*)td));
cf286af7 296
a713db22 297 Int_t q = GetSignalFrom(td);
298 if (q > 0) AddDigit(td, q);
299 }
300 FillOutputData();
925e6570 301 }
302}
28752ff4 303
304//------------------------------------------------------------------------
30178c30 305void AliMUONDigitizer::AddDigit(AliMUONTransientDigit* td, Int_t responseCharge)
28752ff4 306{
cf286af7 307// Prepares the digits, track and charge arrays in preparation for a call to
308// AddDigit(Int_t, Int_t[kMAXTRACKS], Int_t[kMAXTRACKS], Int_t[6])
309// This method is called by CreateDigits() whenever a new digit needs to be added
310// to the output stream trees.
30178c30 311// The responseCharge value is used as the Signal of the new digit.
cf286af7 312// The OnWriteTransientDigit method is also called just before the adding the
313// digit to allow inheriting digitizers to be able to do some specific processing
314// at this point.
315
316 Int_t tracks[kMAXTRACKS];
317 Int_t charges[kMAXTRACKS];
a713db22 318 Int_t digits[7];
88cb7938 319
cf286af7 320 digits[0] = td->PadX();
321 digits[1] = td->PadY();
322 digits[2] = td->Cathode() - 1;
30178c30 323 digits[3] = responseCharge;
cf286af7 324 digits[4] = td->Physics();
325 digits[5] = td->Hit();
a713db22 326 if (GetSegmentation() == 1)
327 digits[6] = 0;
328 else
329 digits[6] = td->DetElemId();
330
cf286af7 331 Int_t nptracks = td->GetNTracks();
a713db22 332 if (nptracks > kMAXTRACKS) {
333
334 AliDebug(1, Form(
335 "TransientDigit returned the number of tracks to be %d, which is bigger than kMAXTRACKS.",
336 nptracks));
337 AliDebug(1, Form("Reseting the number of tracks to be %d.", kMAXTRACKS));
338 nptracks = kMAXTRACKS;
925e6570 339 }
cf286af7 340
a713db22 341 for (Int_t i = 0; i < nptracks; i++) {
342
343 tracks[i] = td->GetTrack(i);
344 charges[i] = td->GetCharge(i);
925e6570 345 }
cf286af7 346
347 // Sort list of tracks according to charge
348 SortTracks(tracks,charges,nptracks);
349
a713db22 350 if (nptracks < kMAXTRACKS ) {
351
352 for (Int_t i = nptracks; i < kMAXTRACKS; i++) {
353 tracks[i] = -1;
354 charges[i] = 0;
355 }
925e6570 356 }
cf286af7 357
8c343c7c 358 AliDebug(4,Form( "Adding digit with charge %d.", responseCharge));
cf286af7 359
360 OnWriteTransientDigit(td);
361 AddDigit(td->Chamber(), tracks, charges, digits);
ce3e25a8 362 AddDigitTrigger(td->Chamber(), tracks, charges, digits);
925e6570 363}
28752ff4 364
cf286af7 365//------------------------------------------------------------------------
366void AliMUONDigitizer::OnCreateTransientDigit(AliMUONTransientDigit* /*digit*/, TObject* /*source_object*/)
367{
368 // Does nothing.
369 //
370 // This is derived by Digitisers that want to trace which digits were made from
371 // which hits.
925e6570 372}
28752ff4 373
b8278504 374//------------------------------------------------------------------------
cf286af7 375void AliMUONDigitizer::OnWriteTransientDigit(AliMUONTransientDigit* /*digit*/)
28752ff4 376{
cf286af7 377 // Does nothing.
378 //
379 // This is derived by Digitisers that want to trace which digits were made from
380 // which hits.
925e6570 381}
cf286af7 382
383//------------------------------------------------------------------------
384Bool_t AliMUONDigitizer::FetchLoaders(const char* foldername, AliRunLoader*& runloader, AliMUONLoader*& muonloader)
385{
386// Fetches the run loader from the current folder, specified by 'foldername'.
387// The muon loader is then loaded from the fetched run loader.
388// kTRUE is returned if no error occurred otherwise kFALSE is returned.
389
8c343c7c 390 AliDebug(3, Form("Fetching run loader and muon loader from folder: %s", foldername));
cf286af7 391
392 runloader = AliRunLoader::GetRunLoader(foldername);
393 if (runloader == NULL)
394 {
8c343c7c 395 AliError(Form("RunLoader not found in folder: %s", foldername));
cf286af7 396 return kFALSE;
397 }
398 muonloader = (AliMUONLoader*) runloader->GetLoader("MUONLoader");
399 if (muonloader == NULL)
400 {
8c343c7c 401 AliError(Form("MUONLoader not found in folder: %s", foldername));
cf286af7 402 return kFALSE;
403 }
404 return kTRUE;
ce3e25a8 405
925e6570 406}
cf286af7 407
408//------------------------------------------------------------------------
409Bool_t AliMUONDigitizer::FetchGlobalPointers(AliRunLoader* runloader)
410{
411// Fetches the AliRun object into the global gAlice pointer from the specified
412// run loader. The AliRun object is loaded into memory using the run loader if
413// not yet loaded. The MUON module object is then loaded from gAlice and
414// AliMUONData fetched from the MUON module.
415// kTRUE is returned if no error occurred otherwise kFALSE is returned.
416
8c343c7c 417 AliDebug(3, Form("Fetching gAlice, MUON module and AliMUONData from runloader 0x%X.",
cf286af7 418 (void*)runloader
8c343c7c 419 ));
cf286af7 420
421 if (runloader->GetAliRun() == NULL) runloader->LoadgAlice();
422 gAlice = runloader->GetAliRun();
423 if (gAlice == NULL)
424 {
8c343c7c 425 AliError(Form("Could not find the AliRun object in runloader 0x%X.", (void*)runloader));
cf286af7 426 return kFALSE;
925e6570 427 }
30178c30 428 fMUON = (AliMUON*) gAlice->GetDetector("MUON");
429 if (fMUON == NULL)
cf286af7 430 {
8c343c7c 431 AliError(Form("Could not find the MUON module in runloader 0x%X.", (void*)runloader));
cf286af7 432 return kFALSE;
925e6570 433 }
88646004 434
435 AliMUONLoader *muonloader = (AliMUONLoader*) runloader->GetLoader("MUONLoader");
436 if (muonloader == NULL)
437 {
8c343c7c 438 AliError( "MUONLoader not found ");
88646004 439 return kFALSE;
440 }
441
442
a20e540f 443 if (fMUONData == NULL) fMUONData = new AliMUONData(muonloader,"MUON","MUON");
30178c30 444 if (fMUONData == NULL)
cf286af7 445 {
8c343c7c 446 AliError(Form("Could not find AliMUONData object in runloader 0x%X.", (void*)runloader));
cf286af7 447 return kFALSE;
925e6570 448 }
ce3e25a8 449
cf286af7 450 return kTRUE;
28752ff4 451}
ce3e25a8 452//-----------------------------------------------------------------------
453Bool_t AliMUONDigitizer::FetchTriggerPointer(AliMUONLoader* loader)
454{
455 if (fMUONData == NULL) {
8c343c7c 456 AliError("MUONData not found");
ce3e25a8 457 return kFALSE;
458 }
459
460 if (fTrigDec == NULL)
461 fTrigDec = new AliMUONTriggerDecision(loader,0,fMUONData);
462
463 return kTRUE;
464}
cf286af7 465//------------------------------------------------------------------------
466void AliMUONDigitizer::ParseOptions(Option_t* options)
467{
468// Called by the Exec method. ParseOptions should parse the option string given to the Exec method.
469//
470// The following options are defined:
471// "debug" - Sets the debug level to 99, which will show all debug messages.
472// "deb" - Same as "debug", implemented for backward comparability.
473//
474// If an invalid option is specified it is simply ignored.
475
476 TString optionString = options;
477 if (optionString.Data() == "debug" ||
478 optionString.Data() == "deb" // maintained for compatability.
479 )
480 {
8c343c7c 481 AliInfo("Called with option \"debug\".");
cf286af7 482 SetDebug(99);
925e6570 483 }
484}
cf286af7 485
486//------------------------------------------------------------------------
487void AliMUONDigitizer::InitArrays()
488{
489// Creates a new fTDList object.
490// Also creates an array of 2 * chamber_number AliMUONHitMapA1 objects
491// in the fHitMaps array. Each one is set to a chamber and cathode
492// specific segmentation model.
493//
494// Note: the fTDList and fHitMap arrays must be NULL before calling this method.
495
8c343c7c 496 AliDebug(2, "Initialising internal arrays.");
497 AliDebug(4, "Creating transient digits list.");
cf286af7 498 fTDList = new TObjArray;
499
500 // Array of pointer of the AliMUONHitMapA1:
501 // two HitMaps per chamber, or one HitMap per cahtode plane
502 fHitMap = new AliMUONHitMapA1* [2*AliMUONConstants::NCh()];
503
504 // Loop over chambers for the definition AliMUONHitMap
505 for (Int_t i = 0; i < AliMUONConstants::NCh(); i++)
506 {
8c343c7c 507 AliDebug(4,Form( "Creating hit map for chamber %d, cathode 1.", i+1));
30178c30 508 AliMUONChamber* chamber = &(fMUON->Chamber(i));
cf286af7 509 AliSegmentation* c1Segmentation = chamber->SegmentationModel(1); // Cathode plane 1
510 fHitMap[i] = new AliMUONHitMapA1(c1Segmentation, fTDList);
8c343c7c 511 AliDebug(4,Form( "Creating hit map for chamber %d, cathode 2.", i+1));
cf286af7 512 AliSegmentation* c2Segmentation = chamber->SegmentationModel(2); // Cathode plane 2
513 fHitMap[i+AliMUONConstants::NCh()] = new AliMUONHitMapA1(c2Segmentation, fTDList);
925e6570 514 }
515}
cf286af7 516
517//------------------------------------------------------------------------
518void AliMUONDigitizer::CleanupArrays()
519{
520// The arrays fTDList and fHitMap are deleted and the pointers set to NULL.
521
8c343c7c 522 AliDebug(2, "Deleting internal arrays.");
cf286af7 523 for(Int_t i = 0; i < 2*AliMUONConstants::NCh(); i++)
524 {
8c343c7c 525 AliDebug(4,Form( "Deleting hit map for chamber %d, cathode %d.",
526 i%AliMUONConstants::NCh()+1, i/AliMUONConstants::NCh()+1));
cf286af7 527 delete fHitMap[i];
925e6570 528 }
cf286af7 529 delete [] fHitMap;
530 fHitMap = NULL;
531
8c343c7c 532 AliDebug(4, "Deleting transient digits list.");
cf286af7 533 fTDList->Delete();
534 delete fTDList;
535 fTDList = NULL;
ce3e25a8 536
925e6570 537}
cf286af7 538
539//------------------------------------------------------------------------
30178c30 540void AliMUONDigitizer::SortTracks(Int_t *tracks, Int_t *charges, Int_t ntr) const
cf286af7 541{
542//
543// Sort the list of tracks contributing to a given digit
544// Only the 3 most significant tracks are actually sorted
545//
546
a713db22 547 if (ntr <= 1) return;
cf286af7 548
a713db22 549 //
550 // Loop over signals, only 3 times
551 //
cf286af7 552
a713db22 553 Int_t qmax;
554 Int_t jmax;
555 Int_t idx[3] = {-2,-2,-2};
556 Int_t jch[3] = {-2,-2,-2};
557 Int_t jtr[3] = {-2,-2,-2};
558 Int_t i, j, imax;
cf286af7 559
a713db22 560 if (ntr < 3) imax = ntr;
561 else imax=3;
cf286af7 562
a713db22 563 for(i = 0; i < imax; i++)
564 {
565 qmax=0;
566 jmax=0;
567
568 for(j = 0; j < ntr; j++)
569 {
570 if ( (i == 1 && j == idx[i-1]) ||
571 (i == 2 && (j == idx[i-1] || j == idx[i-2]))
572 )
573 continue;
574
575 if(charges[j] > qmax)
576 {
577 qmax = charges[j];
578 jmax = j;
579 }
580 }
581
582 if(qmax > 0)
583 {
584 idx[i] = jmax;
585 jch[i] = charges[jmax];
586 jtr[i] = tracks[jmax];
587 }
588
589 }
590
591 for(i = 0; i < 3; i++)
592 {
593 if (jtr[i] == -2)
594 {
595 charges[i] = 0;
596 tracks[i] = 0;
597 }
598 else
599 {
600 charges[i] = jch[i];
601 tracks[i] = jtr[i];
602 }
603 }
925e6570 604}