]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/TPCLib/OnlineDisplay/HLT-OnlineDisplay-HOMER.C
Added the digit reader classes that allow reading of raw packed and unpacked
[u/mrichter/AliRoot.git] / HLT / TPCLib / OnlineDisplay / HLT-OnlineDisplay-HOMER.C
1 /*
2  * Requirements: Running HLT Analysis Framework
3  *               with TCP-Dump Subscribe listining on 
4  *                  - Cluster: Hostname, Port
5  *                  - Tracker: Hostname, Port
6  *                  - Controlled FilePublisher:  Hostname, Port
7  * Usage :
8  * 
9  * (1) USE the StartDisplayMacro.C , by adding 
10  *             gROOT->Macro("StartDisplayMacro.C"); 
11  *       to the rootlogon.C file      
12  *
13  * (2) IN  StartDisplayMacro.C subject to change are: 
14  * ODH_INIT("<PATH TO GEO FILE>", "<PATH TO LIBRARIES>"); 
15  *      - <PATH TO LIBRARIES> : The path where libHOMERReader_ROOT.so and libHOMERReader.so are located.
16  *      - <PATH TO GEO FILE>  : The path where alice.geom is located.
17  * ODH_CONNECT("<NODE>",<PORT>,"<NODE>",<PORT>,"<NODE>",<PORT>);
18  *      - <NODE> : The port on which the TCPDumpSubscriber is running.
19  *      - <PORT> : The port specified in the TCPDumpSubscriber in the XML configuration file. 
20  *    use first pair for Cluster Data, second for Tracks Data and third for Raw Data...
21  *    but it doesn't matter if you change it.
22  *
23  *
24  * When starting root, Display and Control Bar will pop up.
25  * Nothing will be displayed at the beginning.
26  * - In order to display the geometry. Click <Show Geometry> first.
27  *     Different sets of sectors can be selected also.
28  * - In order to dislpay event's click <Next clusters>, <Next tracks> or <Next clusters and tracks>
29  * Displaying PadRow's:
30  * - as Histogram: 
31  *         once : <Setup PadRow 20 with Histogram> 
32  *         next event : <Display PadRow>
33  * - in Geometry:
34  *         once : <Setup PadRow 20 with Geometry> 
35  *         next event : <Display PadRow>, <Display PadRow with Clusters>, <Display PadRow with Tracks> or <Display PadRow with Clusters and Tracks>
36  */
37
38
39 // gROOT->GetInterpreter()->AddIncludePath( "$ALIHLT_TOPDIR/BASE" );
40 // gROOT->GetInterpreter()->AddIncludePath( "$ALIHLT_TOPDIR/TPCLib" );
41
42 #include "AliHLTDataTypes.h"
43 #include "AliHLTTPCSpacePointData.h"
44 #include "AliHLTTPCClusterDataFormat.h"
45 #include "AliHLTTPCTrackletDataFormat.h"
46 #include "AliHLTTPCDefinitions.h"
47 #include "AliHLTTPCDigitReader.h"
48
49 // include because of connecttofile()
50 #include <stdio.h>
51 #include <stdlib.h>
52 //#include <sys/time.h>
53 //#include <sys/types.h>
54 #include <sys/stat.h>
55 #include <fcntl.h>
56 #include <unistd.h>
57 #include <string.h>
58 #include <errno.h>
59 #include <vector>
60 // #include "MLUCString.hpp"
61 // #include "MLUCCmdlineParser.hpp"
62 // #include "MLUCDynamicLibrary.hpp"
63 #include "AliHLTDataTypes.h"
64 #include "AliHLT_C_Component_WrapperInterface.h"
65
66
67
68 //#include "AliHLTTPCTrackArray.h"
69
70     void* gODH_Reader; /* really HOMERReader* */
71     void* gODH_Display; /* really AliHLTTPCDisplay* */
72
73
74 /* Dummy function to work around the problem that the interpreter does not load the first function properly... */
75 int ODH_Dummy() {
76     return 0;
77 }
78
79 // ########################################################################################################################################
80 int HLT_OnlineDisplay_HOMER() {
81     gODH_Display = NULL;
82     return 0;
83 }
84
85 // ########################################################################################################################################
86 int ODH_Init( char* path_to_geom_file, char* path_to_homer_lib = NULL ) {
87     // --- Load LIBS
88     TString lib;
89     cout << "Loading ROOT libraries (ROOTSYS has to be set)" << endl;
90
91     gSystem->Load("libPhysics");
92     gSystem->Load("libEG");
93 //     if(gSystem->Load("libMC")==-1) {
94     gSystem->Load("libGeom");
95     gSystem->Load("libVMC");
96 //      }
97
98     cout << "Loading ALICE TPC libraries (ALICE_ROOT & ALICE_TARGET have to be set)" << endl;
99     gSystem->Load("libESD");
100     gSystem->Load("libSTEER");
101     gSystem->Load("libRAWData");
102 //     gSystem->Load("libCONTAINERS");
103 //     if(gSystem->Load("libTPC")!=0) {
104     gSystem->Load("libTPCbase");
105     gSystem->Load("libTPCrec");
106     gSystem->Load("libTPCsim");
107     gSystem->Load("libTPCfast");
108 //      }
109
110     cout << "Loading HLT libraries (ALIHLT_LIBDIR has to be set)" << endl;
111     gSystem->Load("$(ALIHLT_LIBDIR)/libHLTbase.so");
112     gSystem->Load("$(ALIHLT_LIBDIR)/libAliHLTTPC.so");
113     cout << "Loading HOMER library" << endl;
114
115     if ( path_to_homer_lib ) {
116         lib = path_to_homer_lib;
117         lib += "/";
118     }
119     else {
120         lib = "";
121     }
122     
123     lib += "libHOMERReader_ROOT.so";
124     gSystem->Load( lib );
125
126
127     // --- Create DISPLAY
128     cout << "Creating display" << endl;
129
130     Char_t *gfile="alice.geom"; // geometrie file
131     TString geoPath;
132     if ( path_to_geom_file ){   
133         geoPath = path_to_geom_file;
134         geoPath += "/";
135     }
136     else {
137         geoPath = "";
138     }
139     geoPath += gfile;
140
141     Int_t slices[] = { 0, 35 };
142     AliHLTTPCDisplay* display = new AliHLTTPCDisplay( slices, geoPath.Data() );
143
144     display->SetSlices();
145     display->DisplayAll(0,kFALSE,kFALSE,kFALSE,kFALSE);
146
147     gODH_Display = (void*)display;
148     return 0;
149 }
150
151 int ODH_SetSliceRange(int minslice,int maxslice){
152   // sets a range of Slices
153   if (!gODH_Display ) return -1;
154   AliHLTTPCDisplay* display = (AliHLTTPCDisplay*)gODH_Display;
155
156   display->SetSlices(minslice,maxslice);
157   display->DisplayAll(0,kFALSE,kFALSE,kFALSE,kFALSE);
158 }
159
160 int ODH_SetSliceRange(int slice){
161   // sets one slice
162   if (!gODH_Display ) return -1;
163   AliHLTTPCDisplay* display = (AliHLTTPCDisplay*)gODH_Display;
164
165   display->SetSlices(slice); 
166   display->DisplayAll(0,kFALSE,kFALSE,kFALSE,kFALSE);
167 }
168
169 int ODH_SetSliceRange(){
170   // sets all Slices
171   if (!gODH_Display ) return -1;
172   AliHLTTPCDisplay* display = (AliHLTTPCDisplay*)gODH_Display;
173
174   display->SetSlices();
175   display->DisplayAll(0,kFALSE,kFALSE,kFALSE,kFALSE);
176 }
177
178 int ODH_SetSlicePair(int slice){
179   // sets a pair of slices
180   if (!gODH_Display ) return -1;
181   AliHLTTPCDisplay* display = (AliHLTTPCDisplay*)gODH_Display;
182
183   display->SetSlicesPair(slice);
184   display->DisplayAll(0,kFALSE,kFALSE,kFALSE,kFALSE);
185 }
186
187 int ODH_SetSlicePair(int minslice, int maxslice){
188   // sets a pair of slices
189   if (!gODH_Display ) return -1;
190   AliHLTTPCDisplay* display = (AliHLTTPCDisplay*)gODH_Display;
191
192   display->SetSlicesPair(minslice,maxslice);
193   display->DisplayAll(0,kFALSE,kFALSE,kFALSE,kFALSE);
194 }
195
196 int ODH_SetInvert(){
197   // sets a pair of slices
198   if (!gODH_Display ) return -1;
199   AliHLTTPCDisplay* display = (AliHLTTPCDisplay*)gODH_Display;
200
201   display->SetInvert();
202   display->DisplayAll(0,kFALSE,kFALSE,kFALSE,kFALSE);
203 }
204
205 int ODH_SetDrawGeo(){
206   // sets a pair of slices
207   if (!gODH_Display ) return -1;
208   AliHLTTPCDisplay* display = (AliHLTTPCDisplay*)gODH_Display;
209
210   display->SetDrawGeo();
211   display->DisplayAll(0,kFALSE,kFALSE,kFALSE,kFALSE);
212 }
213
214 // ########################################################################################################################################
215 int ODH_Connect( char* hostname_clusters, short port_clusters, char* hostname_tracks, short port_tracks, char* hostname_raw, short port_raw ) {
216     HOMERReader* reader;
217     char* hostnames[] = { "NULL", "NULL","NULL" };
218     unsigned short ports[] = { 0, 0, 0 };
219     int cnt=0;
220     if ( hostname_clusters ){
221         hostnames[cnt] = hostname_clusters;
222         ports[cnt] = port_clusters;
223         cnt++;
224     }
225     if ( hostname_tracks ){
226         hostnames[cnt] = hostname_tracks;
227         ports[cnt] = port_tracks;
228         cnt++;
229     }
230     if ( hostname_raw ){
231         hostnames[cnt] = hostname_raw;
232         ports[cnt] = port_raw;
233         cnt++;
234     }
235
236     reader = new HOMERReader( cnt, hostnames, ports );
237     int ret;
238     ret=reader->GetConnectionStatus();
239     if ( ret ) {
240         int ndx = reader->GetErrorConnectionNdx();
241         if ( ndx < cnt ) {
242             printf( "Error establishing connection to TCP source %s:%hu: %s (%d)\n", 
243                     hostnames[ndx], ports[ndx], 
244                     strerror(ret), ret );
245         }
246         else {      
247             printf( "Error establishing connection to unknown source with index %d: %s (%d)\n", 
248                     ndx, 
249                     strerror(ret), ret );
250         }
251         delete reader;
252         reader = NULL;
253     }
254     gODH_Reader = (void*)reader;
255     return ret;
256 }
257
258 // ########################################################################################################################################
259 int ODH_Disconnect() {
260     if ( !gODH_Reader )
261         return 0;
262     HOMERReader* reader = (HOMERReader*)gODH_Reader;
263     delete reader;
264     gODH_Reader = NULL;
265     return 0;
266 }
267
268 // ########################################################################################################################################
269 Int_t ODH_SetupPadRow(Int_t histswitch, Int_t slice, Int_t padrow){  
270     // PADROW 0 - 158
271     if (!gODH_Display ) return -1;
272     AliHLTTPCDisplay* display = (AliHLTTPCDisplay*)gODH_Display;
273
274     // Setup Geometry:  histswitch = 0;
275     // Setup Histogram: histswitch = 1|2|3;
276     display->SetupPadRow(histswitch,slice,padrow);
277
278     return 0;
279 }
280
281 // ########################################################################################################################################
282 int ODH_DisplayNextEvent( Bool_t clusterswitch, Bool_t trackswitch, Bool_t padrowswitch, Float_t* clustersEtaRange = NULL ) {
283     
284     if ( !gODH_Reader || !gODH_Display ) return -1;
285     
286     // -- input datatypes , reverse
287     char* spptID="SRETSULC";
288     //char* spptID="STPECAPS";
289     char* trkID = "SGESKART";
290     //char* trkID = "SGESCART";
291     char* padrowID = "KPWR_LDD";
292
293     Int_t minHits = 0;
294     Bool_t x3don = kFALSE;
295
296     HOMERReader* reader = (HOMERReader*)gODH_Reader;
297     AliHLTTPCDisplay* display = (AliHLTTPCDisplay*)gODH_Display;
298     int ret = reader->ReadNextEvent();
299
300     if ( ret ) {
301         int ndx = reader->GetErrorConnectionNdx();
302         printf( "------------ TRY AGAIN --------------->Error reading event from source %d: %s (%d)\n", ndx, strerror(ret), ret );
303         ODH_DisplayNextEvent( clusterswitch, trackswitch, padrowswitch, clustersEtaRange);
304         return ret;
305     }
306
307     unsigned long blockCnt = reader->GetBlockCnt();
308     printf( "Event 0x%016LX (%Lu) with %lu blocks\n", (ULong64_t)reader->GetEventID(), (ULong64_t)reader->GetEventID(), blockCnt );
309
310     for ( unsigned long i = 0; i < blockCnt; i++ ) {
311         char tmp1[9], tmp2[5];
312         memset( tmp1, 0, 9 );
313         memset( tmp2, 0, 5 );
314         void *tmp11 = tmp1;
315         ULong64_t* tmp12 = (ULong64_t*)tmp11;
316         *tmp12 = reader->GetBlockDataType( i );
317         void *tmp21 = tmp2;
318         ULong_t* tmp22 = (ULong_t*)tmp21;
319         *tmp22 = reader->GetBlockDataOrigin( i );
320         printf( "Block %lu length: %lu - type: %s - origin: %s\n",
321                 i, reader->GetBlockDataLength( i ), tmp1, tmp2 );
322     }
323     
324     display->ResetDisplay();
325
326     // -------------- CLUSTER
327     if ( clusterswitch ) {
328         unsigned long blk = reader->FindBlockNdx( spptID, " CPT",0xFFFFFFFF );
329         printf( "blk: %lu\n", blk );
330         while ( blk != ~(unsigned long)0 ) {        
331             printf( "Found clusters block %lu\n", blk );
332             const AliHLTTPCClusterData* clusterData = (const AliHLTTPCClusterData*)reader->GetBlockData( blk );
333             unsigned long dataLen = reader->GetBlockDataLength( blk );
334             
335             ULong_t spec = reader->GetBlockDataSpec( blk );
336             Int_t patch = AliHLTTPCDefinitions::GetMinPatchNr( spec );
337             Int_t slice = AliHLTTPCDefinitions::GetMinSliceNr( spec );
338             printf( "%lu Clusters found for slice %u - patch %u\n", clusterData->fSpacePointCnt, slice, patch );
339
340             void* tmp30 = clusterData;
341             Byte_t* tmp31 = (Byte_t*)tmp30;
342             unsigned long offset;
343             offset = sizeof(clusterData->fSpacePointCnt);
344             if ( offset <= reader->GetBlockTypeAlignment( blk, 1 ) )
345                 offset = reader->GetBlockTypeAlignment( blk, 1 );
346             tmp31 += offset;
347             tmp30 = tmp31;
348             AliHLTTPCSpacePointData* tmp32 = (AliHLTTPCSpacePointData*)tmp30;
349
350             display->SetupClusterDataForPatch( slice, patch, clusterData->fSpacePointCnt, tmp32 );
351
352             blk = reader->FindBlockNdx( spptID, " CPT", 0xFFFFFFFF, blk+1 );
353             printf( "blk: %lu\n", blk );
354         }
355     }
356
357     // -------------- PADROW
358     if ( padrowswitch ) {
359         Int_t padrow = display->GetPadrow();
360         Int_t patch =  AliHLTTPCTransform::GetPatch(padrow);
361         Int_t maxpatch = patch;
362         AliHLTUInt8_t padslice = (AliHLTUInt8_t) display->GetSlice();
363
364         if (padrow == 30 || padrow == 90 || padrow == 139) maxpatch++;
365       
366         for (Int_t tpatch=patch;tpatch <= maxpatch;tpatch++){
367
368           
369             AliHLTUInt32_t padrowSpec = AliHLTTPCDefinitions::EncodeDataSpecification( padslice, padslice,(AliHLTUInt8_t) tpatch,(AliHLTUInt8_t) tpatch );
370             
371             unsigned long blk;
372             
373             // READ RAW DATA BLOCK
374             blk = reader->FindBlockNdx( padrowID, " CPT", padrowSpec );
375             printf( "Raw Data found for slice %u/patch %u\n", padslice, tpatch );
376             
377             unsigned long rawDataBlock = reader->GetBlockData( blk );
378             unsigned long rawDataLen = reader->GetBlockDataLength( blk );
379             
380             // READ CLUSTERS BLOCK
381             blk = reader->FindBlockNdx( spptID, " CPT", padrowSpec );
382             
383             const AliHLTTPCClusterData* clusterData = (const AliHLTTPCClusterData*)reader->GetBlockData( blk );
384             
385             printf( "%lu Clusters found for slice %u - patch %u\n", clusterData->fSpacePointCnt, padslice, tpatch );
386             
387             void* tmp30 = clusterData;
388             Byte_t* tmp31 = (Byte_t*)tmp30;
389             unsigned long offset;
390             offset = sizeof(clusterData->fSpacePointCnt);
391             if ( offset <= reader->GetBlockTypeAlignment( blk, 1 ) )
392                 offset = reader->GetBlockTypeAlignment( blk, 1 );
393             tmp31 += offset;
394             tmp30 = tmp31;
395             AliHLTTPCSpacePointData* tmp32 = (AliHLTTPCSpacePointData*)tmp30;
396             
397             // DISPLAY RAW DATA AND CLUSTERS
398             display->FillPadRow( tpatch, rawDataBlock, rawDataLen, clusterData->fSpacePointCnt, tmp32);
399         }
400
401
402     }
403
404     AliHLTTPCTrackArray* trackArray = NULL;
405     trackArray = new AliHLTTPCTrackArray;
406     if ( !trackArray ) {
407         printf( "No track array\n" );
408         return -1;
409     }
410
411     // -------------- TRACKS
412     if ( trackswitch ) {
413         unsigned long blk = reader->FindBlockNdx( trkID, " CPT", 0xFFFFFFFF );
414
415         while ( blk != ~(unsigned long)0 ) {
416             printf( "Found tracks in block %lu\n", blk );
417             const AliHLTTPCTrackletData* trackData = (const AliHLTTPCTrackletData*)reader->GetBlockData( blk );
418             if ( !trackData ) {
419                 printf( "No track data for block %lu\n", blk );
420                 continue;
421             }
422             
423             ULong_t spec = reader->GetBlockDataSpec( blk );
424             Int_t patchmin = AliHLTTPCDefinitions::GetMinPatchNr( spec );
425             Int_t patchmax = AliHLTTPCDefinitions::GetMaxPatchNr( spec );
426             Int_t slice = AliHLTTPCDefinitions::GetMinSliceNr( spec );  
427
428             printf( "%lu tracks found for slice %u - patch %u-%u\n", trackData->fTrackletCnt, slice, patchmin, patchmax );
429
430             void* tmp40 = trackData;
431             Byte_t* tmp41 = (Byte_t*)tmp40;
432             unsigned long offset;
433
434             offset = sizeof(trackData->fTrackletCnt);
435
436             if ( offset <= reader->GetBlockTypeAlignment( blk, 1 ) ) offset = reader->GetBlockTypeAlignment( blk, 1 );
437
438             tmp41 += offset;
439             tmp40 = tmp41;
440             AliHLTTPCTrackSegmentData* tmp42 = (AliHLTTPCTrackSegmentData*)tmp40;
441
442             trackArray->FillTracks( trackData->fTrackletCnt, tmp42, slice );
443
444             blk = reader->FindBlockNdx( trkID, " CPT", 0xFFFFFFFF, blk+1 );
445         }
446
447
448     }
449
450     display->SetTracks( trackArray );
451     
452     // DISPLAY
453     display->DisplayAll( minHits, clusterswitch, trackswitch, x3don, 0. /*, clustersEtaRange */ );
454     if ( padrowswitch) display->DrawPadRow(x3don);
455     
456     if ( trackArray )  delete trackArray;   
457
458     return 0;
459 }
460
461 // ########################################################################################################################################
462 // ########################################################################################################################################
463 // ########################################################################################################################################
464 int ODH_SimpleDisplay(char * infiles[7],unsigned int slice){
465     if ( !gODH_Display ) return -1;
466
467     FILE * inFH = 1;
468     AliHLTTPCDisplay* display = (AliHLTTPCDisplay*)gODH_Display;        
469     int i = 1;
470     char* error = NULL;
471     int errorArg = -1;
472     int errorParam = -1;
473
474     AliHLTComponent_DataType dataType;
475     AliHLTUInt32_t dataSpec = ~(AliHLTUInt32_t)0;
476     dataType.fStructSize = sizeof(dataType);
477     memset( dataType.fID, '*', 8 );
478     memset( dataType.fOrigin, '*', 4 );
479     AliHLTComponent_BlockData blocks[7];
480     unsigned long totalRead = 0;
481   
482     // --- get INFILE
483     for (int ii = 0;ii<7;ii++){
484
485         inFH = fopen( infiles[ii], "r");
486         if ( inFH == -1 ) {
487             error = "Unable to open input file for reading";
488             errorArg = i;
489             errorParam = i+1;
490             break;
491         }
492     
493         AliHLTComponent_BlockData newBlock;
494         newBlock.fStructSize = sizeof(AliHLTComponent_BlockData);
495
496         newBlock.fShmKey.fStructSize = sizeof(AliHLTComponent_ShmData);
497         newBlock.fShmKey.fShmType = gkAliHLTComponent_InvalidShmType;
498         newBlock.fShmKey.fShmID = gkAliHLTComponent_InvalidShmID;
499         
500         fseek( inFH, 0, SEEK_END );
501         long sz = ftell(inFH);
502         
503         fseek( inFH, 0, SEEK_SET);
504         newBlock.fPtr = new uint8[ sz ];
505         
506         if ( !newBlock.fPtr ) {
507             fprintf( stderr, "Out of memory trying to allocate memory for input file '%s' of %lu bytes.\n",
508                      infile, sz );
509             return -1;
510         }
511
512         unsigned long curSize = 0;
513         int ret=1;
514         void * tmp50 = newBlock.fPtr;
515         uint8* tmp51 = (uint8*)tmp50;
516         while ( ret>0 ) {
517             ret = fread(tmp51+curSize,1, sz-curSize,inFH);
518
519             if ( ret >= 0 ) {
520                 curSize += (unsigned long)ret;
521                 if ( curSize >= (unsigned long)sz ) {
522                     newBlock.fSize = sz;
523                     blocks[ii] =  newBlock;
524                     break;
525                 }
526             }
527             else {
528                 fprintf( stderr, "%s error reading data from input file after %lu bytes.\n", infile, curSize );
529                 return -1;
530             }
531         }
532     }
533   
534     //  --- Setup CLUSTERS
535     for (int ii = 1;ii<7;ii++){
536         unsigned int patch = ii - 1;
537         const AliHLTTPCClusterData* clusterData = (const AliHLTTPCClusterData*) blocks[ii].fPtr;
538         
539         if ( !clusterData )     {
540             printf( "No ClusterData\n" );
541             return -1;
542         }
543         
544                 void* tmp30 = clusterData;
545         Byte_t* tmp31 = (Byte_t*)tmp30;
546         unsigned long offset;
547         
548         offset = sizeof(clusterData->fSpacePointCnt);
549         
550         tmp31 += offset;
551         tmp30 = tmp31;
552         AliHLTTPCSpacePointData* tmp32 = (AliHLTTPCSpacePointData*)tmp30;
553         
554         display->SetupClusterDataForPatch( slice, patch, clusterData->fSpacePointCnt, tmp32 );
555     }
556
557     // --- Setup TRACKS
558     AliHLTTPCTrackArray* trackArray = NULL;
559     trackArray = new AliHLTTPCTrackArray;
560     
561     if ( !trackArray )  {
562         printf( "No track array\n" );
563         return -1;
564     }
565
566     const AliHLTTPCTrackletData* trackData = (const AliHLTTPCTrackletData*) blocks[0].fPtr;
567     if ( !trackData )
568     {
569         printf( "No track data for block %lu\n", blk );
570         continue;
571     }
572    
573     void* tmp40 = trackData;
574     Byte_t* tmp41 = (Byte_t*)tmp40;
575     unsigned long offset;
576     
577     offset = sizeof(trackData->fTrackletCnt);
578     
579     tmp41 += offset;
580     tmp40 = tmp41;
581     AliHLTTPCTrackSegmentData* tmp42 = (AliHLTTPCTrackSegmentData*)tmp40;
582     
583     trackArray->FillTracks( trackData->fTrackletCnt, tmp42, slice );
584     
585     display->SetTracks( trackArray );
586
587     // --- Display 
588     Int_t minHits = 0; 
589
590     display->SetSlices(0,4);
591     display->DisplayAll( minHits, clusterswitch, trackswitch, kFALSE, 0. /*, clustersEtaRange */ );
592     if ( trackArray ) delete trackArray;
593     
594     return 0;
595
596 } // END ODH_SimpleDisplay