Merged HLT tag v1-2 with ALIROOT tag v3-09-Release.
authorloizides <loizides@f7af4fe6-9843-0410-8265-dc069ae4e863>
Sun, 27 Jul 2003 21:04:39 +0000 (21:04 +0000)
committerloizides <loizides@f7af4fe6-9843-0410-8265-dc069ae4e863>
Sun, 27 Jul 2003 21:04:39 +0000 (21:04 +0000)
201 files changed:
HLT/Makefile
HLT/Makefile.conf
HLT/Makefile.rules [new file with mode: 0644]
HLT/bin/ali.sh [new file with mode: 0755]
HLT/bin/alone.sh [new file with mode: 0755]
HLT/bin/cleanall.sh [new file with mode: 0755]
HLT/bin/compileall.sh [new file with mode: 0755]
HLT/bin/root.sh [new file with mode: 0755]
HLT/bin/sethlt.csh [new file with mode: 0755]
HLT/bin/sethlt.sh [new file with mode: 0755]
HLT/bin/sethlt_cern.csh [new file with mode: 0755]
HLT/bin/sethlt_cern.sh [new file with mode: 0755]
HLT/bin/usehlt.csh [new file with mode: 0755]
HLT/bin/usehlt.sh [new file with mode: 0755]
HLT/comp/AliL3ClusterFitter.cxx
HLT/comp/AliL3ClusterFitter.h
HLT/comp/AliL3CompLinkDef.h
HLT/comp/AliL3Compress.cxx
HLT/comp/AliL3Compress.h
HLT/comp/AliL3DataCompressor.cxx
HLT/comp/AliL3DataCompressor.h
HLT/comp/AliL3FitUtilities.h
HLT/comp/AliL3ModelTrack.cxx
HLT/comp/AliL3ModelTrack.h
HLT/comp/AliL3Modeller.cxx
HLT/comp/AliL3Modeller.h
HLT/comp/AliL3Models.h
HLT/comp/Makefile
HLT/comp/bitio.h
HLT/comp/errhand.h
HLT/doc/README [new file with mode: 0644]
HLT/exa/Eval.C [deleted file]
HLT/exa/MakePileup.C [new file with mode: 0644]
HLT/exa/MakePythia.C [new file with mode: 0644]
HLT/exa/PlotPythiaEvent.C [new file with mode: 0644]
HLT/exa/SetTrackingParameters_1000bf02.C [new file with mode: 0644]
HLT/exa/SetTrackingParameters_1000bf04.C [new file with mode: 0644]
HLT/exa/SetTrackingParameters_2000bf02.C [new file with mode: 0644]
HLT/exa/SetTrackingParameters_2000bf04.C [new file with mode: 0644]
HLT/exa/SetTrackingParameters_4000bf02.C [new file with mode: 0644]
HLT/exa/SetTrackingParameters_4000bf04.C [new file with mode: 0644]
HLT/exa/SetTrackingParameters_8000bf02.C [new file with mode: 0644]
HLT/exa/SetTrackingParameters_8000bf04.C [new file with mode: 0644]
HLT/exa/SetTrackingParameters_pp.C [new file with mode: 0644]
HLT/exa/binary.C
HLT/exa/display.C
HLT/exa/eval.C [deleted file]
HLT/exa/fill_pp.C [new file with mode: 0644]
HLT/exa/make_init.C [deleted file]
HLT/exa/read.C
HLT/exa/rootlogon.C
HLT/exa/runMakePileup.C [new file with mode: 0644]
HLT/exa/runcf.C [new file with mode: 0644]
HLT/exa/runhough.C
HLT/exa/runkalman.C [new file with mode: 0644]
HLT/exa/runtracker.C
HLT/exa/runtracker_pp.C [new file with mode: 0644]
HLT/exa/trigger_pp.C
HLT/hough/AliL3Histogram.cxx
HLT/hough/AliL3Histogram.h
HLT/hough/AliL3Histogram1D.cxx
HLT/hough/AliL3Histogram1D.h
HLT/hough/AliL3HistogramAdaptive.cxx
HLT/hough/AliL3HistogramAdaptive.h
HLT/hough/AliL3Hough.cxx
HLT/hough/AliL3Hough.h
HLT/hough/AliL3HoughBaseTransformer.cxx
HLT/hough/AliL3HoughBaseTransformer.h
HLT/hough/AliL3HoughClusterTransformer.cxx
HLT/hough/AliL3HoughClusterTransformer.h
HLT/hough/AliL3HoughDisplay.cxx
HLT/hough/AliL3HoughDisplay.h
HLT/hough/AliL3HoughEval.cxx
HLT/hough/AliL3HoughEval.h
HLT/hough/AliL3HoughGlobalMerger.cxx
HLT/hough/AliL3HoughGlobalMerger.h
HLT/hough/AliL3HoughIntMerger.cxx
HLT/hough/AliL3HoughIntMerger.h
HLT/hough/AliL3HoughLinkDef.h
HLT/hough/AliL3HoughMaxFinder.cxx
HLT/hough/AliL3HoughMaxFinder.h
HLT/hough/AliL3HoughMerger.cxx
HLT/hough/AliL3HoughMerger.h
HLT/hough/AliL3HoughTest.cxx
HLT/hough/AliL3HoughTest.h
HLT/hough/AliL3HoughTrack.cxx
HLT/hough/AliL3HoughTrack.h
HLT/hough/AliL3HoughTransformer.cxx
HLT/hough/AliL3HoughTransformer.h
HLT/hough/AliL3HoughTransformerGlobal.cxx [new file with mode: 0644]
HLT/hough/AliL3HoughTransformerGlobal.h [new file with mode: 0644]
HLT/hough/AliL3HoughTransformerLUT.cxx
HLT/hough/AliL3HoughTransformerLUT.h
HLT/hough/AliL3HoughTransformerNew.cxx [new file with mode: 0644]
HLT/hough/AliL3HoughTransformerNew.h [new file with mode: 0644]
HLT/hough/AliL3HoughTransformerVhdl.cxx
HLT/hough/AliL3HoughTransformerVhdl.h
HLT/hough/Makefile
HLT/hough/Makefile.standalone [deleted file]
HLT/kalman/AliL3Kalman.cxx [new file with mode: 0644]
HLT/kalman/AliL3Kalman.h [new file with mode: 0644]
HLT/kalman/AliL3KalmanTrack.cxx [new file with mode: 0644]
HLT/kalman/AliL3KalmanTrack.h [new file with mode: 0644]
HLT/misc/AliL3AltroMemHandler.cxx
HLT/misc/AliL3AltroMemHandler.h
HLT/misc/AliL3DataHandler.cxx
HLT/misc/AliL3DataHandler.h
HLT/misc/AliL3FFloat.cxx
HLT/misc/AliL3FFloat.h
HLT/misc/AliL3MiscLinkDef.h
HLT/misc/AliL3Stopwatch.cxx
HLT/misc/AliL3Stopwatch.h
HLT/misc/AliL3TPCMapping-iroc.generated [new file with mode: 0644]
HLT/misc/AliL3TPCMapping-oroc.generated [new file with mode: 0644]
HLT/misc/AliL3TPCMapping.cxx [new file with mode: 0644]
HLT/misc/AliL3TPCMapping.h [new file with mode: 0644]
HLT/misc/AliL3TransBit.cxx
HLT/misc/AliL3TransBit.h
HLT/misc/AliL3VHDLClusterFinder.cxx
HLT/misc/AliL3VHDLClusterFinder.h
HLT/misc/Makefile
HLT/programs/MakePileup.cxx [deleted file]
HLT/programs/MakePileup.h [deleted file]
HLT/programs/Makefile
HLT/programs/ali2raw.cxx
HLT/programs/convcosmicsfile.cxx [new file with mode: 0644]
HLT/programs/gettransform.cxx
HLT/programs/read.cxx
HLT/programs/runhough.cxx
HLT/programs/runit.cxx
HLT/programs/runtracker.cxx
HLT/programs/runvhdlcf.cxx
HLT/programs/runvhdlhough.cxx [new file with mode: 0644]
HLT/programs/speedtest.cxx
HLT/sim/AliL3Generator.h
HLT/src/AliL3Benchmark.cxx
HLT/src/AliL3Benchmark.h
HLT/src/AliL3ClustFinder.cxx [deleted file]
HLT/src/AliL3ClustFinder.h [deleted file]
HLT/src/AliL3ClustFinderNew.cxx
HLT/src/AliL3ClustFinderNew.h
HLT/src/AliL3ConfMapFit.cxx
HLT/src/AliL3ConfMapFit.h
HLT/src/AliL3ConfMapPoint.cxx
HLT/src/AliL3ConfMapPoint.h
HLT/src/AliL3ConfMapTrack.cxx
HLT/src/AliL3ConfMapTrack.h
HLT/src/AliL3ConfMapper.cxx
HLT/src/AliL3ConfMapper.h
HLT/src/AliL3DigitData.h
HLT/src/AliL3Display.cxx
HLT/src/AliL3Display.h
HLT/src/AliL3Evaluate.cxx
HLT/src/AliL3Evaluate.h
HLT/src/AliL3FileHandler.cxx
HLT/src/AliL3FileHandler.h
HLT/src/AliL3Fitter.cxx
HLT/src/AliL3Fitter.h
HLT/src/AliL3GlobalMerger.cxx
HLT/src/AliL3GlobalMerger.h
HLT/src/AliL3InterMerger.cxx
HLT/src/AliL3InterMerger.h
HLT/src/AliL3Logger.cxx
HLT/src/AliL3Logger.h
HLT/src/AliL3Logging.h
HLT/src/AliL3MemHandler.cxx
HLT/src/AliL3MemHandler.h
HLT/src/AliL3Merger.cxx
HLT/src/AliL3Merger.h
HLT/src/AliL3RawDataFileHandler.cxx [new file with mode: 0644]
HLT/src/AliL3RawDataFileHandler.h [new file with mode: 0644]
HLT/src/AliL3RootTypes.h
HLT/src/AliL3SpacePointData.h
HLT/src/AliL3SrcLinkDef.h [moved from HLT/src/AliL3LinkDef.h with 89% similarity]
HLT/src/AliL3StandardIncludes.h
HLT/src/AliL3Track.cxx
HLT/src/AliL3Track.h
HLT/src/AliL3TrackArray.cxx
HLT/src/AliL3TrackArray.h
HLT/src/AliL3TrackMerger.cxx
HLT/src/AliL3TrackMerger.h
HLT/src/AliL3TrackSegmentData.h
HLT/src/AliL3Transform.cxx
HLT/src/AliL3Transform.h
HLT/src/AliL3Vertex.cxx
HLT/src/AliL3Vertex.h
HLT/src/AliL3VertexArray.cxx
HLT/src/AliL3VertexArray.h
HLT/src/AliL3VertexData.h
HLT/src/AliL3VertexFinder.cxx
HLT/src/AliL3VertexFinder.h
HLT/src/AliLevel3.cxx
HLT/src/AliLevel3.h
HLT/src/Makefile
HLT/trigger/AliD0toKpi.cxx [new file with mode: 0644]
HLT/trigger/AliD0toKpi.h [new file with mode: 0644]
HLT/trigger/AliD0vtxFinderBkg_pp_VTX.C [new file with mode: 0644]
HLT/trigger/AliD0vtxFinderSgn_pp_VTX.C [new file with mode: 0644]
HLT/trigger/AliL3Trigger.h
HLT/trigger/AliL3TriggerLinkDef.h [new file with mode: 0644]
HLT/trigger/Makefile [new file with mode: 0644]

index 38607a3..c5700a5 100644 (file)
@@ -1,9 +1,10 @@
 #$Id$
-###########################
-# Makefile for HLT code.  #
-#                         #
-# Author: Anders Vestbo   #                    
-###########################
+###############################
+# Makefile for HLT code.      #
+#                             #
+# Author: Anders Vestbo,      #
+#         Constantin Loizides #                    
+###############################
 
 LIBS = src hough comp misc
 MAKEDIRS = $(LIBS) programs
@@ -16,3 +17,20 @@ libs:
 
 clean:
        for i in $(MAKEDIRS) ; do cd $$i && $(MAKE) clean ; cd .. ; done
+
+print:
+       @echo "ROOTSYS           = $(ROOTSYS)"
+       @echo "ALICE_ROOT        = $(ALICE_ROOT)"
+       @echo ""
+       @echo "ALIHLT_BASEDIR    = $(ALIHLT_BASEDIR)"
+       @echo "ALIHLT_TOPDIR     = $(ALIHLT_TOPDIR)"
+       @echo "ALIHLT_MLUCDIR    = $(ALIHLT_MLUCDIR)"
+       @echo "ALIHLT_USEPACKAGE = $(ALIHLT_USEPACKAGE)"
+       @echo "ALIHLT_NOLOGGING  = $(ALIHLT_NOLOGGING)"
+       @echo "ALIHLT_DOMC       = $(ALIHLT_DOMC)"
+       @echo "ALIHLT_HAVEASV    = $(ALIHLT_HAVEASV)"
+       @echo "ALIHLT_ALIDETECT  = $(ALIHLT_ALIDETECT)"
+
+help:
+       cat doc/README
+
index 08ceed3..ac32e5e 100644 (file)
@@ -1,53 +1,74 @@
 #$Id$
-###########################
-# Makefile for HLT code.  #
-#                         #
-# Author: Anders Vestbo   #                    
-###########################
+################################
+# Makefile.conf for HLT code.  #
+#                              #
+# Author: Anders Vestbo,       #
+#         Constantin Loizide   #                    
+################################
 
-#Define whether you want to run with ALIROOT or only ROOT
-#Only one of them should be defined
-ifndef USEPACKAGE
-USEPACKAGE = ALIROOT
-#USEPACKAGE = ROOT
-#USEPACKAGE = STANDALONE
+#Specify the directory where the level3code tree is located.
+ifndef ALIHLT_TOPDIR
+ALIHLT_TOPDIR = $(HOME)/workcode/level3code
 endif
 
-#Specify the directory where the level3code tree is located.
-ifndef TOPDIR
-TOPDIR = $(HOME)/workcode/level3code
+#Define directory to contain additional hlt code, such as logging classes.
+ifndef ALIHLT_BASEDIR
+ALIHLT_BASEDIR = /prog/alice/level3
 endif
 
-#Define directory to contain additional L3 code, such as logging classes.
-ifndef LEVEL3
-LEVEL3 = /prog/alice/level3
+#Define directory where libs will be stored
+ifndef ALIHLT_LIBDIR
+ALIHLT_LIBDIR = $(ALIHLT_BASEDIR)/lib_$(USER)
 endif
-ifndef LIBDIR
-LIBDIR = $(LEVEL3)/lib_$(USERNAME)
+
+#Define whether you want to run with ALIROOT or only ROOT
+#Only one of them should be defined
+ifndef ALIHLT_USEPACKAGE
+ALIHLT_USEPACKAGE = ALIROOT
+#ALIHLT_USEPACKAGE = ROOT
+#ALIHLT_USEPACKAGE = STANDALONE
 endif
 
-#Switch on/off HLT logging classes
-#NOLOGGING = 1
+#Switch off special HLT logging classes
+ifeq ($(ALIHLT_NOLOGGING),true)
+NOLOGGING = 1
+endif
 
-#Switch on/off saving MC data through the chain.
+#Switch on saving MC data through the chain.
 #This will only have an effect if you are running with aliroot.
-#DO_MC = 1 
+ifeq ($(ALIHLT_DOMC),true)
+DOMC = 1
+endif
 
-#Switch of  if you are not using patched AliTPC 
-#This will only have an effect if you are running with aliroot.
+#Switch on effective digit data handling 
+#in case you are not using patched AliTPC. 
+#This only has an effect if using ALIROOT.
+ifeq ($(ALIHLT_HAVEASV),true)
 ASVVERSION = 1
+endif
 
-#If you are compiling on the alpha, use this flag:
-#EXTRACXXFLAGS += -mcpu=ev6
+#Switch on ALIROOT version detection by cvs command
+ifeq ($(ALIHLT_ALIDETECT),true)
+USECVS = 1
+endif
+
+#----------------------------------------------------
+#Some compiler flags or defines: You can use your
+#own setting by defining them outside (make -e)
+#----------------------------------------------------
 
 CXX          = g++
-LD           = g++
-GCCVERSION   = $(shell $(CXX) --version | head -n 1 | cut -d" " -f 3 | cut -d. -f 1)
+LD           = $(CXX)
+GCCVERSION   = $(shell $(CXX) --version | head -n 1 | cut -d" " -f 3 | cut -d. -f 1 | cut -d" " -f1)
 
 CXXGCC3FLAGS = -DGCCVERSION=$(GCCVERSION)
 #CXXGCC3FLAGS += -pedantic
 #CXXGCC3FLAGS += -Wno-deprecated
+#CXXGCC3FLAGS += -Woverloaded-virtual
+
+#If you are compiling on the alpha, use this flag:
+#EXTRACXXFLAGS += -mcpu=ev6
 
-CXXFLAGS     = -O2 -Wall -fPIC -Woverloaded-virtual $(CXXGCC3FLAGS) $(EXTRACXXFLAGS) 
+CXXFLAGS     = -O2 -Wall -fPIC $(CXXGCC3FLAGS) $(EXTRACXXFLAGS) 
 LDFLAGS      = -O2 $(EXTRALDFLAGS)
 SOFLAGS      = -shared
diff --git a/HLT/Makefile.rules b/HLT/Makefile.rules
new file mode 100644 (file)
index 0000000..910a4b1
--- /dev/null
@@ -0,0 +1,132 @@
+#$Id$
+################################
+# Makefile.rules for HLT code. #
+#                              #
+# Author: Anders Vestbo,       #
+#         Constantin Loizide   #                    
+################################
+
+#----------------------------------------------------
+# !!! Dont change anything here !!!
+#----------------------------------------------------
+
+DEFSTR = -Dno_root
+OBJDIR = lib_alone
+INCLUDES = -I$(ALIHLT_TOPDIR)/hough -I$(ALIHLT_TOPDIR)/src -I$(ALIHLT_TOPDIR)/comp -I$(ALIHLT_TOPDIR)/misc -I$(ALIHLT_TOPDIR)/trigger
+
+ifeq ($(ALIHLT_USEPACKAGE),ROOT) 
+INCLUDES += -I$(ROOTSYS)/include 
+DEFSTR = -Duse_root
+OBJDIR = lib_ROOT
+ROOTSTR := $(shell $(ROOTSYS)/bin/root -n -b -q  | grep Version | cut -b 17-25 | cut -d" " -f1)
+DEFSTR += -DROOTVERSION=\"$(ROOTSTR)\" 
+endif
+
+ifeq ($(ALIHLT_USEPACKAGE),ALIROOT)
+INCLUDES += -I$(ROOTSYS)/include -I$(ALICE_ROOT)/include/ -I$(ALICE_ROOT)/TPC -I$(ALICE_ROOT)/CONTAINERS -I$(ALICE_ROOT)/STEER
+DEFSTR = -Duse_aliroot -Duse_root
+OBJDIR = lib
+ROOTSTR := $(shell $(ROOTSYS)/bin/root -n -b -q  | grep Version | cut -b 17-25 | cut -d" " -f1)
+DEFSTR += -DROOTVERSION=\"$(ROOTSTR)\" 
+ifeq ($(USECVS),1)
+ALIROOTSTR := $(shell if test -n "`cd $(ALICE_ROOT)/STEER/ && cvs stat AliRun.cxx | grep "Sticky Tag" | grep none`"; then echo HEAD; else cd $(ALICE_ROOT)/STEER/ && cvs stat AliRun.cxx | grep "Sticky Tag" | cut -b 18- | cut -d" " -f1; fi)
+DEFSTR += -Duse_cvs
+else
+ALIROOTSTR = "Unknown"
+endif
+DEFSTR += -DALIROOTVERSION=\"$(ALIROOTSTR)\"
+endif
+
+ifeq ($(DOMC),1)
+DEFSTR += -Ddo_mc
+endif
+
+ifneq ($(NOLOGGING),1)
+DEFSTR += -Duse_logging
+ifdef ALIHLT_MLUCDIR
+INCLUDES += -I$(ALIHLT_MLUCDIR)/include
+else
+INCLUDES += -I/prog/alice/level3/kip/MLUC/include
+endif
+endif
+
+ifeq ($(ASVVERSION),1)
+DEFSTR += -DASVVERSION
+endif
+
+DEFSTR += $(EXTRADEF)
+
+DICT  = $(MODNAME)Cint-$(ALIHLT_USEPACKAGE).cxx
+DICTH = $(MODNAME)Cint-$(ALIHLT_USEPACKAGE).h
+DICTO = $(OBJDIR)/$(MODNAME)Cint-$(ALIHLT_USEPACKAGE).o
+
+
+ifndef OBJS
+ifeq ($(OBJDIR),lib_alone)
+HDRS = $(SRCS:.cxx=.h) 
+OBJS = $(patsubst %.cxx,$(OBJDIR)/%.o,$(SRCS))
+else
+HDRS = $(SRCS:.cxx=.h) $(MODNAME)LinkDef.h
+OBJS = $(patsubst %.cxx,$(OBJDIR)/%.o,$(SRCS)) $(DICTO)
+endif
+endif
+
+ALIHLT_LIBSO = $(ALIHLT_LIBDIR)/lib$(MODNAME).so
+
+#Default Targets  
+#
+
+all: $(OBJDIR) $(ALIHLT_LIBDIR) $(ALIHLT_LIBSO) 
+
+$(ALIHLT_LIBSO): $(OBJS)
+       $(LD) $(SOFLAGS) $(LDFLAGS) $^ -o $@
+
+$(DICT): $(HDRS)
+       @echo "Generating dictionary..."
+       rootcint -f $(DICT) -c $(INCLUDES) -DGCCVERSION=$(GCCVERSION) $(DEFSTR) -include AliL3StandardIncludes.h $(HDRS)
+
+$(OBJDIR)/%.o: %.cxx 
+       $(CXX) $(CXXFLAGS) $(DEFSTR) -c $(INCLUDES) -o $@ $<
+
+$(OBJDIR): 
+       test ! -e $(OBJDIR) && mkdir -p $(OBJDIR)
+
+$(ALIHLT_LIBDIR):
+       test ! -e $(ALIHLT_LIBDIR) && mkdir -p $(ALIHLT_LIBDIR)
+
+help:
+       cat $(ALIHLT_TOPDIR)/doc/README
+
+print:
+       @echo "MODNAME           = $(MODNAME)" 
+       @echo "ALIHLT_BASEDIR    = $(ALIHLT_BASEDIR)"
+       @echo "ALIHLT_TOPDIR     = $(ALIHLT_TOPDIR)"
+       @echo "ALIHLT_MLUCDIR    = $(ALIHLT_MLUCDIR)"
+       @echo "ALIHLT_USEPACKAGE = $(ALIHLT_USEPACKAGE)"
+       @echo "ALIHLT_NOLOGGING  = $(ALIHLT_NOLOGGING)"
+       @echo "ALIHLT_DOMC       = $(ALIHLT_DOMC)"
+       @echo "ALIHLT_HAVEASV    = $(ALIHLT_HAVEASV)"
+       @echo "ALIHLT_ALIDETECT  = $(ALIHLT_ALIDETECT)"
+       @echo "ROOTSTR           = $(ROOTSTR)"
+       @echo "ALIROOTSTR        = $(ALIROOTSTR)"
+
+printall: print
+       @echo "ALIHLT_LIBSO      = $(ALIHLT_LIBSO)"
+       @echo "DEFSTR            = $(DEFSTR)"
+       @echo "OBJDIR            = $(OBJDIR)"
+       @echo "INCLUDES          = $(INCLUDES)"
+       @echo "SRCS              = $(SRCS)"
+       @echo "HRDS              = $(HDRS)"
+       @echo "OBJS              = $(OBJS)"
+
+clean:
+       rm -f $(OBJDIR)/*.o
+       rm -f $(ALIHLT_LIBSO)
+       rm -f $(DICT) $(DICTH) 
+       rm -rf $(OBJDIR)
+
+so:
+       rm -f $(ALIHLT_LIBSO)
+
+
+.phony: print clean so
diff --git a/HLT/bin/ali.sh b/HLT/bin/ali.sh
new file mode 100755 (executable)
index 0000000..3ef813c
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/bash
+###########
+# $Id$
+
+export ALIHLT_USEPACKAGE=ALIROOT
+export ALIHLT_LIBDIR=$ALIHLT_TOPDIR/lib_$ALIHLT_USEPACKAGE
+
+cd $ALIHLT_TOPDIR
+make libs
+
+
diff --git a/HLT/bin/alone.sh b/HLT/bin/alone.sh
new file mode 100755 (executable)
index 0000000..64ebd9b
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/bash
+###########
+# $Id$
+
+export ALIHLT_USEPACKAGE=STANDALONE
+export ALIHLT_LIBDIR=$ALIHLT_TOPDIR/lib_$ALIHLT_USEPACKAGE
+
+cd $ALIHLT_TOPDIR
+make libs
+
diff --git a/HLT/bin/cleanall.sh b/HLT/bin/cleanall.sh
new file mode 100755 (executable)
index 0000000..4883a90
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/bash
+###########
+# $Id$
+
+for i in ROOT ALIROOT STANDALONE; do
+ export ALIHLT_USEPACKAGE=$i
+ export ALIHLT_LIBDIR=$ALIHLT_TOPDIR/lib_$USEPACKAGE
+
+ cd $ALIHLT_TOPDIR
+ make clean
+ cd ..
+done
diff --git a/HLT/bin/compileall.sh b/HLT/bin/compileall.sh
new file mode 100755 (executable)
index 0000000..649a4b4
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/bash
+###########
+# $Id$
+
+for i in ROOT ALIROOT STANDALONE; do
+ export ALIHLT_USEPACKAGE=$i
+ export ALIHLT_LIBDIR=$ALIHLT_TOPDIR/lib_$ALIHLT_USEPACKAGE
+ echo  $ALIHLT_LIBDIR
+ cd $ALIHLT_TOPDIR
+ #make libs
+ cd ..
+done
+
diff --git a/HLT/bin/root.sh b/HLT/bin/root.sh
new file mode 100755 (executable)
index 0000000..fceb31d
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/bash
+###########
+# $Id$
+
+export ALIHLT_USEPACKAGE=ROOT
+export ALIHLT_LIBDIR=$ALIHLT_TOPDIR/lib_$ALIHLT_USEPACKAGE
+
+cd $ALIHLT_TOPDIR
+make libs
diff --git a/HLT/bin/sethlt.csh b/HLT/bin/sethlt.csh
new file mode 100755 (executable)
index 0000000..c377f06
--- /dev/null
@@ -0,0 +1,28 @@
+#!/bin/csh
+###########
+# $Id$
+
+setenv CVS_RSH ssh
+setenv CVSROOT ${USER}@kjekspc1.fi.uib.no:/cvs/hltcvs
+
+setenv ALIHLT_USEPACKAGE ALIROOT
+#setenv ALIHLT_USEPACKAGE ROOT
+#setenv ALIHLT_USEPACKAGE STANDALONE
+
+setenv ALIHLT_BASEDIR $HOME/work/hlt
+setenv ALIHLT_TOPDIR ${ALIHLT_BASEDIR}/level3code
+setenv ALIHLT_LIBDIR ${ALIHLT_TOPDIR}/lib_${ALIHLT_USEPACKAGE}
+
+setenv ALIHLT_NOLOGGING false
+setenv ALIHLT_DOMC true
+setenv ALIHLT_HAVEASV true
+setenv ALIHLT_ALIDETECT true
+
+setenv ALIHLT_MLUCDIR ${ALIHLT_BASEDIR}/kip/MLUC
+
+setenv ALIHLT_DATADIR /data1/head
+#setenv ALIHLT_TRANSFORMFILE ${ALIHLT_DATADIR}/l3transform.config
+#setenv ALIHLT_GEOPATH ${ALIHLT_DATADIR}
+
+setenv LD_LIBRARY_PATH ${ROOTSYS}/lib\:${ALICE_ROOT}/lib/tgt_${ALICE_TARGET}\:${ALIHLT_MLUCDIR}/lib
+
diff --git a/HLT/bin/sethlt.sh b/HLT/bin/sethlt.sh
new file mode 100755 (executable)
index 0000000..dafe5fe
--- /dev/null
@@ -0,0 +1,37 @@
+#!/bin/bash
+###########
+# $Id$
+
+export CVS_RSH=ssh
+export CVSROOT=$USER@kjekspc1.fi.uib.no:/cvs/hltcvs
+#export CVSIGNORE="lib src hough comp exa programs misc trigger sim 
+#AliL3CompCint.h AliL3CompCint.cxx AliL3HoughCint.h 
+#AliL3HoughCint.cxx AliL3Cint.cxx AliL3Cint.h lib_ROOT lib_ALIROOT
+#AliL3MiscCint.cxx AliL3MiscCint.h"
+
+export ALIHLT_USEPACKAGE=ALIROOT
+#export ALIHLT_USEPACKAGE=ROOT
+#export ALIHLT_USEPACKAGE=STANDALONE
+
+export ALIHLT_BASEDIR=$HOME/work/hlt
+export ALIHLT_TOPDIR=$ALIHLT_BASEDIR/level3code
+export ALIHLT_LIBDIR=$ALIHLT_TOPDIR/lib_$ALIHLT_USEPACKAGE
+
+export ALIHLT_NOLOGGING=false
+export ALIHLT_DOMC=true
+export ALIHLT_HAVEASV=true
+export ALIHLT_ALIDETECT=true
+
+export ALIHLT_MLUCDIR=/usr/local/kip/MLUC
+
+#export ALIHLT_DATADIR=/mnt/local/alidata/head
+#export ALIHLT_TRANSFORMFILE=$ALIHLT_DATADIR/l3transform.config
+#export ALIHLT_GEOPATH=$ALIDATADIR
+
+
+if test -z "$LD_LIBRARY_PATH"; then
+  export LD_LIBRARY_PATH=$ALIHLT_MLUCDIR/lib:$ALIHLT_LIBDIR
+elif test -z "`echo $LD_LIBRARY_PATH | grep $ALIHLT_MLUCDIR/lib`"; 
+then
+  export LD_LIBRARY_PATH=$ALIHLT_MLUCDIR/lib:$ALIHLT_LIBDIR:$LD_LIBRARY_PATH 
+fi
diff --git a/HLT/bin/sethlt_cern.csh b/HLT/bin/sethlt_cern.csh
new file mode 100755 (executable)
index 0000000..e54ba4b
--- /dev/null
@@ -0,0 +1,25 @@
+#!/bin/csh
+###########
+# $Id$
+
+setenv ALIHLT_USEPACKAGE ALIROOT
+#setenv ALIHLT_USEPACKAGE ROOT
+#setenv ALIHLT_USEPACKAGE STANDALONE
+
+setenv ALIHLT_BASEDIR $HOME/work/
+setenv ALIHLT_TOPDIR ${ALIHLT_BASEDIR}/level3code
+setenv ALIHLT_LIBDIR ${ALIHLT_TOPDIR}/lib_${ALIHLT_USEPACKAGE}
+
+setenv ALIHLT_NOLOGGING false
+setenv ALIHLT_DOMC true
+setenv ALIHLT_HAVEASV true
+setenv ALIHLT_ALIDETECT true
+
+setenv ALIHLT_MLUCDIR ${ALIHLT_BASEDIR}/kip/MLUC
+
+setenv ALIHLT_DATADIR /data1/head
+#setenv ALIHLT_TRANSFORMFILE ${ALIHLT_DATADIR}/l3transform.config
+#setenv ALIHLT_GEOPATH ${ALIHLT_DATADIR}
+
+setenv LD_LIBRARY_PATH ${ROOTSYS}/lib\:${ALICE_ROOT}/lib/tgt_${ALICE_TARGET}\:${ALIHLT_MLUCDIR}/lib
+
diff --git a/HLT/bin/sethlt_cern.sh b/HLT/bin/sethlt_cern.sh
new file mode 100755 (executable)
index 0000000..52e3126
--- /dev/null
@@ -0,0 +1,30 @@
+#!/bin/bash
+###########
+# $Id$
+
+export ALIHLT_USEPACKAGE=ALIROOT
+#export ALIHLT_USEPACKAGE=ROOT
+#export ALIHLT_USEPACKAGE=STANDALONE
+
+export ALIHLT_BASEDIR=$HOME/work/
+export ALIHLT_TOPDIR=$ALIHLT_BASEDIR/level3code
+export ALIHLT_LIBDIR=$ALIHLT_TOPDIR/lib_$ALIHLT_USEPACKAGE
+
+export ALIHLT_NOLOGGING=true
+export ALIHLT_DOMC=true
+export ALIHLT_HAVEASV=false
+export ALIHLT_ALIDETECT=false
+
+#export ALIHLT_MLUCDIR=/usr/local/kip/MLUC
+
+#export ALIHLT_DATADIR=/mnt/local/alidata/head
+#export ALIHLT_TRANSFORMFILE=$ALIHLT_DATADIR/l3transform.config
+#export ALIHLT_GEOPATH=$ALIDATADIR
+
+
+if test -z "$LD_LIBRARY_PATH"; then
+  export LD_LIBRARY_PATH=$ALIHLT_MLUCDIR/lib:$ALIHLT_LIBDIR
+elif test -z "`echo $LD_LIBRARY_PATH | grep $ALIHLT_MLUCDIR/lib`"; 
+then
+  export LD_LIBRARY_PATH=$ALIHLT_MLUCDIR/lib:$ALIHLT_LIBDIR:$LD_LIBRARY_PATH 
+fi
diff --git a/HLT/bin/usehlt.csh b/HLT/bin/usehlt.csh
new file mode 100755 (executable)
index 0000000..d764ab6
--- /dev/null
@@ -0,0 +1,17 @@
+#!/bin/tcsh
+###########
+# $Id$
+
+if ( "a$1" == "a" )  then
+ setenv ALIHLT_USEPACKAGE ALIROOT
+else
+ setenv ALIHLT_USEPACKAGE $1
+endif
+echo HLT ALIHLT_USEPACKAGE=$ALIHLT_USEPACKAGE
+
+setenv ALIHLT_LIBDIR ${ALIHLT_TOPDIR}/lib_${ALIHLT_USEPACKAGE}
+
+#setenv ALIHLT_NOLOGGING false
+#setenv ALIHLT_DOMC true
+#setenv ALIHLT_HAVEASV true
+#setenv ALIHLT_ALIDETECT true
diff --git a/HLT/bin/usehlt.sh b/HLT/bin/usehlt.sh
new file mode 100755 (executable)
index 0000000..9328c4e
--- /dev/null
@@ -0,0 +1,17 @@
+#!/bin/bash
+###########
+# $Id$
+
+if test -z "$1"; then
+ export ALIHLT_USEPACKAGE=ALIROOT
+else
+ export ALIHLT_USEPACKAGE=$1
+fi
+echo HLT ALIHLT_USEPACKAGE=$ALIHLT_USEPACKAGE
+
+export ALIHLT_LIBDIR=$ALIHLT_TOPDIR/lib_$ALIHLT_USEPACKAGE
+
+#export ALIHLT_NOLOGGING=false
+#export ALIHLT_DOMC=true
+#export ALIHLT_HAVEASV=true
+#export ALIHLT_ALIDETECT=true
index 1f35dc7..f9ea20e 100644 (file)
@@ -1,16 +1,20 @@
-//$Id$
+// @(#) $Id$
 
 // Author: Anders Vestbo <mailto:vestbo@fi.uib.no>
-//*-- Copyright &copy ASV
+//*-- Copyright &copy ALICE HLT Group
 
 #include "AliL3StandardIncludes.h"
+
+#include "AliL3Logging.h"
 #include "AliL3ClusterFitter.h"
 #include "AliL3FitUtilities.h"
-#include "AliL3Transform.h"
 #include "AliL3DigitData.h"
 #include "AliL3ModelTrack.h"
 #include "AliL3TrackArray.h"
 #include "AliL3MemHandler.h"
+#include "AliL3HoughTrack.h"
+#include "AliL3SpacePointData.h"
+#include "AliL3Compress.h"
 
 #if GCCVERSION == 3
 using namespace std;
@@ -24,18 +28,309 @@ using namespace std;
 
 ClassImp(AliL3ClusterFitter)
 
+Int_t AliL3ClusterFitter::fBadFitError=0;
+Int_t AliL3ClusterFitter::fFitError=0;
+Int_t AliL3ClusterFitter::fResultError=0;
+Int_t AliL3ClusterFitter::fFitRangeError=0;
+
 AliL3ClusterFitter::AliL3ClusterFitter()
 {
-  fPadFitRange=2;
-  fTimeFitRange=3;
   plane=0;
   fNmaxOverlaps = 3;
   fChiSqMax=12;
+  fRowMin=-1;
+  fRowMax=-1;
+  fFitted=0;
+  fFailed=0;
+  fYInnerWidthFactor=1;
+  fZInnerWidthFactor=1;
+  fYOuterWidthFactor=1;
+  fZOuterWidthFactor=1;
+  fSeeds=0;
+  fProcessTracks=0;
+  fClusters=0;
+  fNMaxClusters=0;
+  fNClusters=0;
+}
+
+AliL3ClusterFitter::AliL3ClusterFitter(Char_t *path)
+{
+  strcpy(fPath,path);
+  plane=0;
+  fNmaxOverlaps = 3;
+  fChiSqMax=12;
+  fRowMin=-1;
+  fRowMax=-1;
+  fFitted=0;
+  fFailed=0;
+  fYInnerWidthFactor=1;
+  fZInnerWidthFactor=1;
+  fYOuterWidthFactor=1;
+  fZOuterWidthFactor=1;
+  fSeeds=0;
+  fProcessTracks=0;
+  fNMaxClusters=100000;
+  fClusters=0;
+  fNClusters=0;
 }
 
 AliL3ClusterFitter::~AliL3ClusterFitter()
 {
+  if(fSeeds)
+    delete fSeeds;
+  if(fClusters)
+    delete [] fClusters;
+}
+
+void AliL3ClusterFitter::Init(Int_t slice,Int_t patch,Int_t *rowrange,AliL3TrackArray *tracks)
+{
+  //Assuming tracklets found by the line transform
+
+  fSlice=slice;
+  fPatch=patch;
+  
+  if(rowrange[0] > AliL3Transform::GetLastRow(patch) || rowrange[1] < AliL3Transform::GetFirstRow(patch))
+    cerr<<"AliL3ClusterFitter::Init : Wrong rows "<<rowrange[0]<<" "<<rowrange[1]<<endl;
+  fRowMin=rowrange[0];
+  fRowMax=rowrange[1];
+
+  if(fRowMin < 0)
+    fRowMin = 0;
+  if(fRowMax > AliL3Transform::GetLastRow(fPatch))
+    fRowMax = AliL3Transform::GetLastRow(fPatch);
+  
+  fFitted=fFailed=0;
+  
+  Int_t ntimes = AliL3Transform::GetNTimeBins()+1;
+  Int_t npads = AliL3Transform::GetNPads(AliL3Transform::GetLastRow(fPatch))+1;//Max num of pads.
+  Int_t bounds = ntimes*npads;
+  if(fRow)
+    delete [] fRow;
+  fRow = new Digit[bounds];
+  if(fTracks)
+    delete fTracks;
+  
+  fTracks = new AliL3TrackArray("AliL3ModelTrack");
+  
+  for(Int_t i=0; i<tracks->GetNTracks(); i++)
+    {
+      AliL3HoughTrack *track = (AliL3HoughTrack*)tracks->GetCheckedTrack(i);
+      if(!track) continue;
+      AliL3ModelTrack *mtrack = (AliL3ModelTrack*)fTracks->NextTrack();
+      mtrack->Init(slice,patch);
+      mtrack->SetTgl(track->GetTgl());
+      mtrack->SetRowRange(rowrange[0],rowrange[1]);
+      for(Int_t j=fRowMin; j<=fRowMax; j++)
+       {
+         Float_t hit[3];
+         track->GetLineCrossingPoint(j,hit);
+         hit[0] += AliL3Transform::Row2X(track->GetFirstRow());
+         Float_t R = sqrt(hit[0]*hit[0] + hit[1]*hit[1]);
+         hit[2] = R*track->GetTgl();
+         Int_t se,ro;
+         AliL3Transform::Slice2Sector(slice,j,se,ro);
+         AliL3Transform::Local2Raw(hit,se,ro);
+         if(hit[1]<0 || hit[1]>=AliL3Transform::GetNPads(j) || hit[2]<0 || hit[2]>=AliL3Transform::GetNTimeBins())
+           {
+             mtrack->SetPadHit(j,-1);
+             mtrack->SetTimeHit(j,-1);
+             continue;
+           }
+         mtrack->SetPadHit(j,hit[1]);
+         mtrack->SetTimeHit(j,hit[2]);
+         mtrack->SetCrossingAngleLUT(j,fabs(track->GetPsiLine() - AliL3Transform::Pi()/2));
+         //if(mtrack->GetCrossingAngleLUT(j) > AliL3Transform::Deg2Rad(20))
+         //  cout<<"Angle "<<mtrack->GetCrossingAngleLUT(j)<<" psiline "<<track->GetPsiLine()*180/3.1415<<endl;
+         mtrack->CalculateClusterWidths(j);
+       }
+    }
+  //  cout<<"Copied "<<fTracks->GetNTracks()<<" tracks "<<endl;
+}
+
+void AliL3ClusterFitter::Init(Int_t slice,Int_t patch)
+{
+  fSlice=slice;
+  fPatch=patch;
+
+  fRowMin=AliL3Transform::GetFirstRow(patch);
+  fRowMax=AliL3Transform::GetLastRow(patch);
+  
+  fFitted=fFailed=0;
+  
+  Int_t ntimes = AliL3Transform::GetNTimeBins()+1;
+  Int_t npads = AliL3Transform::GetNPads(AliL3Transform::GetLastRow(fPatch))+1;//Max num of pads.
+  Int_t bounds = ntimes*npads;
+  if(fRow)
+    delete [] fRow;
+  fRow = new Digit[bounds];
+  if(fTracks)
+    delete fTracks;
+  fTracks = new AliL3TrackArray("AliL3ModelTrack");  
+
+}
+
 
+void AliL3ClusterFitter::LoadSeeds(Int_t *rowrange,Bool_t offline)
+{
+  
+  cout<<"Loading the seeds"<<endl;
+  Char_t fname[1024];
+  
+  if(offline)
+    sprintf(fname,"%s/offline/tracks_%d.raw",fPath,0);
+  else
+    sprintf(fname,"%s/hough/tracks_%d.raw",fPath,0);
+  
+  cout<<"AliL3ClusterFitter::LoadSeeds : Loading input tracks from "<<fname<<endl;
+  
+  AliL3MemHandler tfile;
+  tfile.SetBinaryInput(fname);
+  
+  if(fSeeds)
+    delete fSeeds;
+  fSeeds = new AliL3TrackArray("AliL3ModelTrack");
+  tfile.Binary2TrackArray(fSeeds);
+  tfile.CloseBinaryInput();
+
+  //if(!offline)
+  //fSeeds->QSort();
+  
+  Int_t clustercount=0;
+  for(Int_t i=0; i<fSeeds->GetNTracks(); i++)
+    {
+      AliL3ModelTrack *track = (AliL3ModelTrack*)fSeeds->GetCheckedTrack(i);
+      if(!track) continue;
+
+      if(!offline)
+       {
+         /*
+         if(track->GetNHits() < 10 || track->GetPt() < 0.08) 
+           {
+             fSeeds->Remove(i);
+             continue;
+           }
+         */
+       }
+      clustercount += track->GetNHits();
+      track->CalculateHelix();
+      
+      Int_t nhits = track->GetNHits();
+      UInt_t *hitids = track->GetHitNumbers();
+
+      Int_t origslice = (hitids[nhits-1]>>25)&0x7f;//Slice of innermost point
+
+      track->Init(origslice,-1);
+      Int_t slice = origslice;
+      
+      //for(Int_t j=rowrange[1]; j>=rowrange[0]; j--)
+      for(Int_t j=rowrange[0]; j<=rowrange[1]; j++)
+       {
+         
+         //Calculate the crossing point between track and padrow
+         Float_t angle = 0; //Perpendicular to padrow in local coordinates
+         AliL3Transform::Local2GlobalAngle(&angle,slice);
+         if(!track->CalculateReferencePoint(angle,AliL3Transform::Row2X(j)))
+           {
+             cerr<<"No crossing in slice "<<slice<<" padrow "<<j<<endl;
+             continue;
+             //track->Print();
+             //exit(5);
+           }
+         Float_t xyz_cross[3] = {track->GetPointX(),track->GetPointY(),track->GetPointZ()};
+         
+         Int_t sector,row;
+         AliL3Transform::Slice2Sector(slice,j,sector,row);
+         AliL3Transform::Global2Raw(xyz_cross,sector,row);
+         //cout<<"Examining slice "<<slice<<" row "<<j<<" pad "<<xyz_cross[1]<<" time "<<xyz_cross[2]<<endl;
+         if(xyz_cross[1] < 0 || xyz_cross[1] >= AliL3Transform::GetNPads(j)) //Track leaves the slice
+           {
+           newslice:
+             
+             Int_t tslice=slice;
+             Float_t lastcross=xyz_cross[1];
+             if(xyz_cross[1] > 0)
+               {
+                 if(slice == 17)
+                   slice=0;
+                 else if(slice == 35)
+                   slice = 18;
+                 else
+                   slice += 1;
+               }
+             else
+               {
+                 if(slice == 0)
+                   slice = 17;
+                 else if(slice==18)
+                   slice = 35;
+                 else
+                   slice -= 1;
+               }
+             if(slice < 0 || slice>35)
+               {
+                 cerr<<"Wrong slice "<<slice<<" on row "<<j<<endl;
+                 exit(5);
+               }
+             //cout<<"Track leaving, trying slice "<<slice<<endl;
+             angle=0;
+             AliL3Transform::Local2GlobalAngle(&angle,slice);
+             if(!track->CalculateReferencePoint(angle,AliL3Transform::Row2X(j)))
+               {
+                 cerr<<"No crossing in slice "<<slice<<" padrow "<<j<<endl;
+                 continue;
+                 //track->Print();
+                 //exit(5);
+               }
+             xyz_cross[0] = track->GetPointX();
+             xyz_cross[1] = track->GetPointY();
+             xyz_cross[2] = track->GetPointZ();
+             Int_t sector,row;
+             AliL3Transform::Slice2Sector(slice,j,sector,row);
+             AliL3Transform::Global2Raw(xyz_cross,sector,row);
+             if(xyz_cross[1] < 0 || xyz_cross[1] >= AliL3Transform::GetNPads(j)) //track is in the borderline
+               {
+                 if(xyz_cross[1] > 0 && lastcross > 0 || xyz_cross[1] < 0 && lastcross < 0)
+                   goto newslice;
+                 else
+                   {
+                     slice = tslice;//Track is on the border of two slices
+                     continue;
+                   }
+               }
+           }
+         
+         if(xyz_cross[2] < 0 || xyz_cross[2] >= AliL3Transform::GetNTimeBins())//track goes out of range
+           continue;
+         
+         if(xyz_cross[1] < 0 || xyz_cross[1] >= AliL3Transform::GetNPads(j))
+           {
+             cerr<<"Slice "<<slice<<" padrow "<<j<<" pad "<<xyz_cross[1]<<" time "<<xyz_cross[2]<<endl;
+             track->Print();
+             exit(5);
+           }
+         
+         track->SetPadHit(j,xyz_cross[1]);
+         track->SetTimeHit(j,xyz_cross[2]);
+         angle=0;
+         AliL3Transform::Local2GlobalAngle(&angle,slice);
+         Float_t crossingangle = track->GetCrossingAngle(j,slice);
+         track->SetCrossingAngleLUT(j,crossingangle);
+         
+         track->CalculateClusterWidths(j);
+         
+         track->GetClusterModel(j)->fSlice = slice;
+         
+       }
+      memset(track->GetHitNumbers(),0,159*sizeof(UInt_t));
+      track->SetNHits(0);
+    }
+  fSeeds->Compress();
+  
+  AliL3Compress *c = new AliL3Compress(-1,-1,fPath);
+  c->WriteFile(fSeeds,"tracks_before.raw");
+  delete c;
+  
+  cout<<"Loaded "<<fSeeds->GetNTracks()<<" seeds and "<<clustercount<<" clusters"<<endl;
 }
 
 void AliL3ClusterFitter::FindClusters()
@@ -56,176 +351,271 @@ void AliL3ClusterFitter::FindClusters()
 
   Int_t pad,time;
   Short_t charge;
-
+  
+  if(fRowMin < 0)
+    {
+      fRowMin = AliL3Transform::GetFirstRow(fPatch);
+      fRowMax = AliL3Transform::GetLastRow(fPatch);
+    }
   for(Int_t i=AliL3Transform::GetFirstRow(fPatch); i<=AliL3Transform::GetLastRow(fPatch); i++)
     {
+      if((Int_t)rowPt->fRow < fRowMin)
+       {
+         AliL3MemHandler::UpdateRowPointer(rowPt);
+         continue;
+       }
+      else if((Int_t)rowPt->fRow > fRowMax)
+       break;
+      else if((Int_t)rowPt->fRow != i)
+       {
+         cerr<<"AliL3ClusterFitter::FindClusters : Mismatching row numbering "<<i<<" "<<rowPt->fRow<<endl;
+         exit(5);
+       }
       fCurrentPadRow = i;
       memset((void*)fRow,0,(AliL3Transform::GetNTimeBins()+1)*(AliL3Transform::GetNPads(i)+1)*sizeof(Digit));
       digPt = (AliL3DigitData*)rowPt->fDigitData;
-      //cout<<"Loading row "<<i<<" with "<<(Int_t)rowPt->fNDigit<<" digits"<<endl;
+
       for(UInt_t j=0; j<rowPt->fNDigit; j++)
        {
          pad = digPt[j].fPad;
          time = digPt[j].fTime;
          charge = digPt[j].fCharge;
+         if(charge > 1024)
+           charge -= 1024;
          fRow[(AliL3Transform::GetNTimeBins()+1)*pad+time].fCharge = charge;
          fRow[(AliL3Transform::GetNTimeBins()+1)*pad+time].fUsed = kFALSE;
          //cout<<"Row "<<i<<" pad "<<pad<<" time "<<time<<" charge "<<charge<<endl;
        }
       
-      for(Int_t k=0; k<fTracks->GetNTracks(); k++)
+      for(Int_t it=0; it<2; it++)
        {
-         AliL3ModelTrack *track = (AliL3ModelTrack*)fTracks->GetCheckedTrack(k);
-         if(!track) continue;
-         if(track->GetPadHit(i) < 0 || track->GetTimeHit(i) < 0)
+         if(it==0)
            {
-             track->SetCluster(i,0,0,0,0,0,0);
-             continue;
+             fProcessTracks = fSeeds;
+             fSeeding = kTRUE;
+           }
+         else
+           {
+             fProcessTracks = fTracks;
+             fSeeding = kFALSE;
+           }
+         if(!fProcessTracks)
+           continue;
+         
+         for(Int_t k=0; k<fProcessTracks->GetNTracks(); k++)
+           {
+             AliL3ModelTrack *track = (AliL3ModelTrack*)fProcessTracks->GetCheckedTrack(k);
+             if(!track) continue;
+             
+             if(fSeeding)
+               if(track->GetClusterModel(i)->fSlice != fSlice) continue;
+             
+             if(track->GetPadHit(i) < 0 || track->GetPadHit(i) > AliL3Transform::GetNPads(i)-1 ||
+                track->GetTimeHit(i) < 0 || track->GetTimeHit(i) > AliL3Transform::GetNTimeBins()-1)
+               {
+                 track->SetCluster(i,0,0,0,0,0,0);
+                 continue;
+               }
+             
+             if(CheckCluster(k) == kFALSE)
+               fFailed++;
            }
-         FitClusters(track);
        }
-      FillZeros(rowPt);
+      //FillZeros(rowPt);
       AliL3MemHandler::UpdateRowPointer(rowPt);
     }
+  
+  fSeeding = kTRUE;
+  AddClusters();
+  fSeeding = kFALSE;
+  AddClusters();
+    
+  cout<<"Fitted "<<fFitted<<" clusters, failed "<<fFailed<<endl;
+  cout<<"Distribution:"<<endl;
+  cout<<"Bad fit "<<fBadFitError<<endl;
+  cout<<"Fit error "<<fFitError<<endl;
+  cout<<"Result error "<<fResultError<<endl;
+  cout<<"Fit range error "<<fFitRangeError<<endl;
+
 }
 
-void AliL3ClusterFitter::FitCluster(AliL3ModelTrack *track)
+Bool_t AliL3ClusterFitter::CheckCluster(Int_t trackindex)
 {
-  cout<<"Track had no overlaps"<<endl;
-  Int_t minpad = (Int_t)rint(track->GetPadHit(fCurrentPadRow)) - fPadFitRange;
-  Int_t maxpad = (Int_t)rint(track->GetPadHit(fCurrentPadRow)) + fPadFitRange;
-  Int_t mintime = (Int_t)rint(track->GetTimeHit(fCurrentPadRow)) - fTimeFitRange;
-  Int_t maxtime = (Int_t)rint(track->GetTimeHit(fCurrentPadRow)) + fTimeFitRange;
+  //Check if this is a single or overlapping cluster
   
-  Int_t size = FIT_PTS;
-
-  if(minpad <= 0)
-    minpad=0;
-  if(mintime<=0)
-    mintime=0;
-  if(maxpad>=AliL3Transform::GetNPads(fCurrentPadRow)-1)
-    maxpad=AliL3Transform::GetNPads(fCurrentPadRow)-1;
-  if(maxtime>=AliL3Transform::GetNTimeBins()-1)
-    maxtime=AliL3Transform::GetNTimeBins()-1;
-
-  if(plane)
-    delete [] plane;
-  plane = new DPOINT[FIT_PTS];
-  memset(plane,0,FIT_PTS*sizeof(DPOINT));
-
-  Double_t x[FIT_PTS],y[FIT_PTS],s[FIT_PTS];
+  AliL3ModelTrack *track = (AliL3ModelTrack*)fProcessTracks->GetCheckedTrack(trackindex);
   
-  //Fill the fit parameters:
-  Double_t a[FIT_MAXPAR];
-  a[2] = track->GetPadHit(fCurrentPadRow);
-  a[4] = track->GetTimeHit(fCurrentPadRow);
-  a[1] = fRow[(AliL3Transform::GetNTimeBins()+1)*((Int_t)rint(a[2])) + (Int_t)rint(a[4])].fCharge;
-  a[3] = sqrt(track->GetParSigmaY2(fCurrentPadRow))*sqrt(2);
-  a[5] = sqrt(track->GetParSigmaZ2(fCurrentPadRow))*sqrt(2);
-  a[6] = sqrt(track->GetParSigmaZ2(fCurrentPadRow))*sqrt(2);
-  
-  if(!a[1])
+  Int_t row = fCurrentPadRow;
+  
+  if(track->IsSet(row)) //A fit has already be performed on this one
+    return kTRUE;
+  
+  //Define the cluster region of this hit:
+  Int_t padr[2]={999,-1};
+  Int_t timer[2]={999,-1};
+  
+  if(!SetFitRange(track,padr,timer))
     {
-      cout<<"No charge"<<endl;
-      if(track->GetNClusters() == fCurrentPadRow - AliL3Transform::GetFirstRow(fPatch))
-       track->SetCluster(fCurrentPadRow,0,0,0,0,0,0);
-      return;
+      track->SetCluster(fCurrentPadRow,0,0,0,0,0,0);
+      
+      if(fDebug)
+       cout<<"Failed to fit cluster at row "<<row<<" pad "<<(Int_t)rint(track->GetPadHit(row))<<" time "
+           <<(Int_t)rint(track->GetTimeHit(row))<<" hitcharge "
+           <<fRow[(AliL3Transform::GetNTimeBins()+1)*(Int_t)rint(track->GetPadHit(row))+(Int_t)rint(track->GetTimeHit(row))].fCharge<<endl;
+      fFitRangeError++;
+      return kFALSE;
     }
+
+  //Check if any other track contributes to this cluster:
+  //This is done by checking if the tracks are overlapping within
+  //the range defined by the track parameters
+  for(Int_t t=trackindex+1; t<fProcessTracks->GetNTracks(); t++)
+    {
+      AliL3ModelTrack *tr = (AliL3ModelTrack*)fProcessTracks->GetCheckedTrack(t);
+      if(!tr) continue;
+      if(fSeeding)
+       if(tr->GetClusterModel(row)->fSlice != fSlice) continue;
+      Int_t xyw = (Int_t)ceil(sqrt(tr->GetParSigmaY2(row))) + 1;
+      Int_t zw = (Int_t)ceil(sqrt(tr->GetParSigmaZ2(row))) + 1;
+      if( 
+        (tr->GetPadHit(row) - xyw > padr[0] && tr->GetPadHit(row) - xyw < padr[1] &&
+         tr->GetTimeHit(row) - zw > timer[0] && tr->GetTimeHit(row) - zw < timer[1]) ||
+        
+        (tr->GetPadHit(row) + xyw > padr[0] && tr->GetPadHit(row) + xyw < padr[1] &&
+         tr->GetTimeHit(row) - zw > timer[0] && tr->GetTimeHit(row) - zw < timer[1]) ||
+        
+        (tr->GetPadHit(row) - xyw > padr[0] && tr->GetPadHit(row) - xyw < padr[1] &&
+         tr->GetTimeHit(row) + zw > timer[0] && tr->GetTimeHit(row) + zw < timer[1]) ||
+        
+        (tr->GetPadHit(row) + xyw > padr[0] && tr->GetPadHit(row) + xyw < padr[1] &&
+         tr->GetTimeHit(row) + zw > timer[0] && tr->GetTimeHit(row) + zw < timer[1]) 
+        )
+       {
+         if(SetFitRange(tr,padr,timer)) //Expand the cluster fit range
+           track->SetOverlap(row,t);    //Set overlap
+       }
+    }
+
+  if(fDebug)
+    cout<<"Fitting cluster with "<<track->GetNOverlaps(fCurrentPadRow)<<" overlaps"<<endl;
+  FitClusters(track,padr,timer);
+  return kTRUE;
+}
+
+Bool_t AliL3ClusterFitter::SetFitRange(AliL3ModelTrack *track,Int_t *padrange,Int_t *timerange)
+{
+  Int_t row = fCurrentPadRow;
+  Int_t nt = AliL3Transform::GetNTimeBins()+1;
   
-  Int_t pad_num=0;
-  Int_t time_num_max=0;
-  Int_t ndata=0;
-  Int_t charge,tot_charge=0;
+  Int_t nsearchbins=0;
+  if(row < 63)
+    nsearchbins=25;
+  else
+    nsearchbins=49;
+  Int_t padloop[49] = {0,0,0,-1,1,-1,1,-1,1,0,0,-1,1,-1,1 ,2,-2,2,-2,2,-2,2,-2,2,-2
+                      ,0,1,2,3,3,3,3,3,3,3
+                      ,2,1,0,-1,-2,-3
+                      ,-3,-3,-3,-3,-3,-3,-1,-1};
+  Int_t timeloop[49] = {0,1,-1,0,0,1,1,-1,-1,2,-2,2,2,-2,-2 ,0,0,1,1,-1,-1,2,2,-2,-2
+                       ,-3,-3,-3,-3,-2,-1,0,1,2,3
+                       ,3,3,3,3,3,3,2,1,0,-1,-2,-3,-3,-3};
+  
+  Int_t padhit = (Int_t)rint(track->GetPadHit(row));
+  Int_t timehit = (Int_t)rint(track->GetTimeHit(row));
+  Int_t padmax=-1;
+  Int_t timemax=-1;
 
-  //Fill the proper arrays:
-  for(Int_t i=minpad; i<=maxpad; i++)
+  for(Int_t index=0; index<nsearchbins; index++)
     {
-      Int_t max_charge = 0;
-      Int_t time_num=0;
-      for(Int_t j=mintime; j<=maxtime; j++)
+      if(IsMaximum(padhit + padloop[index],timehit + timeloop[index])) 
        {
-         charge = fRow[(AliL3Transform::GetNTimeBins()+1)*i + j].fCharge;
-         if(charge > max_charge)
-           {
-             max_charge = charge;
-             time_num++;
-            }
-         if(charge <= 0) continue;
-         //cout<<"Filling padrow "<<fCurrentPadRow<<" pad "<<i<<" time "<<j<<" charge "<<charge<<endl;
-         tot_charge += charge;
-         ndata++;
-         if(ndata >= size)
-           cerr<<"Too many points"<<endl;
-         plane[ndata].u = (Double_t)i;
-         plane[ndata].v = (Double_t)j;
-         x[ndata]=ndata;
-         y[ndata]=charge;
-         s[ndata]= 1 + sqrt((Double_t)charge);
+         padmax = padhit + padloop[index];
+         timemax = timehit + timeloop[index];
+         break;
        }
-      if(max_charge) //there was charge on this pad
-       pad_num++;
-      if(time_num_max < time_num)
-       time_num_max = time_num;
     }
 
-  if(pad_num <= 1 || time_num_max <=1) //too few to do fit
+  /*
+  if(IsMaximum(padhit,timehit))
+    {
+      padmax = padhit;
+      timemax = timehit;
+    }
+  */
+  //Define the cluster region of this hit:
+  //The region we look for, is centered at the local maxima
+  //and expanded around using the parametrized cluster width
+  //according to track parameters.
+  Int_t xyw = (Int_t)ceil(sqrt(track->GetParSigmaY2(row)))+1; 
+  Int_t zw = (Int_t)ceil(sqrt(track->GetParSigmaZ2(row)))+1;  
+  if(padmax>=0 && timemax>=0)
     {
-      //cout<<"To few pads for fit on row "<<fCurrentPadRow<<endl;
-      if(track->GetNClusters() == fCurrentPadRow - AliL3Transform::GetFirstRow(fPatch))
-       track->SetCluster(fCurrentPadRow,0,0,0,0,0,0);
+      if(fDebug)
+       {
+         cout<<"Expanding cluster range using expected cluster widths: "<<xyw<<" "<<zw
+             <<" and setting local maxima pad "<<padmax<<" time "<<timemax<<endl;
+         if(xyw > 10 || zw > 10)
+           track->Print();
+       }
+      
+      //Set the hit to the local maxima of the cluster.
+      //Store the maxima in the cluster model structure,
+      //-only temporary, it will be overwritten when calling SetCluster.
+      
+      track->GetClusterModel(row)->fDPad = padmax;
+      track->GetClusterModel(row)->fDTime = timemax;
 
-      return;
+      for(Int_t i=padmax-xyw; i<=padmax+xyw; i++)
+       {
+         for(Int_t j=timemax-zw; j<=timemax+zw; j++)
+           {
+             if(i<0 || i>=AliL3Transform::GetNPads(row) || j<0 || j>=AliL3Transform::GetNTimeBins()) continue;
+             if(fRow[nt*i+j].fCharge)
+               {
+                 if(i < padrange[0]) padrange[0]=i;
+                 if(i > padrange[1]) padrange[1]=i;
+                 if(j < timerange[0]) timerange[0]=j;
+                 if(j > timerange[1]) timerange[1]=j;
+               }
+           }
+       }
+      if(fDebug)
+       cout<<"New padrange "<<padrange[0]<<" "<<padrange[1]<<" "<<" time "<<timerange[0]<<" "<<timerange[1]<<endl;
+      return kTRUE;
     }
+  return kFALSE;
+}
+
+Bool_t AliL3ClusterFitter::IsMaximum(Int_t pad,Int_t time)
+{
+  if(pad<0 || pad >= AliL3Transform::GetNPads(fCurrentPadRow) ||
+     time<0 || time >= AliL3Transform::GetNTimeBins())
+    return kFALSE;
+  Int_t nt = AliL3Transform::GetNTimeBins()+1;
+  if(fRow[nt*pad+time].fUsed == kTRUE) return kFALSE; //Peak has been assigned before
+  Int_t charge = fRow[nt*pad+time].fCharge;
+  if(charge == 1023 || charge==0) return kFALSE;
   
-  Int_t npars = NUM_PARS;
-  Int_t lista[FIT_MAXPAR];
-  Double_t dev[FIT_MAXPAR],chisq_f;
-  lista[1] = 1;
-  lista[2] = 1;
-  lista[3] = 0;
-  lista[4] = 1;
-  lista[5] = 0;
-  lista[6] = 0;
-  
-  //Declare a pointer to the C fitting function
-  void (*funcs) ( double, double *, double *,double *,int );
-  funcs = f2gauss5;
-  
-  //cout<<"Doing fit with parameters "<<a[2]<<" "<<a[4]<<" "<<a[3]<<" "<<a[5]<<" "<<a[1]<<endl;
-  
-  Int_t ret = lev_marq_fit( x, y, s, ndata, a, lista, dev, npars, &chisq_f,f2gauss5);
-  if(ret)
-    cerr<<"Fit error"<<endl;
-  
-  tot_charge = (Int_t)(a[1] * a[3] * a[5]);
-  chisq_f /= (ndata - 3);
-  //  cout<<"Chisq per degree of freedom : "<<chisq_f<<endl;
-  //cout<<"pad "<<a[2]<<" time "<<a[4]<<" adc "<<a[1]<<endl;
-  //cout<<"Setting cluster on row "<<fCurrentPadRow<<" pad "<<a[2]<<" time "<<a[4]<<" charge "<<tot_charge<<endl;
-  
-  //Make sure that the cluster has not already been set before setting it:
-  if(track->GetNClusters() == fCurrentPadRow - AliL3Transform::GetFirstRow(fPatch))
-    track->SetCluster(fCurrentPadRow,a[2],a[4],tot_charge,0,0,pad_num);
+  fRow[nt*pad+time].fUsed = kTRUE;
+  return kTRUE;
+
+  //if(charge < fRow[nt*(pad-1)+(time-1)].fCharge) return kFALSE;
+  if(charge < fRow[nt*(pad)+(time-1)].fCharge) return kFALSE;
+  //if(charge < fRow[nt*(pad+1)+(time-1)].fCharge) return kFALSE;
+  if(charge < fRow[nt*(pad-1)+(time)].fCharge) return kFALSE;
+  if(charge < fRow[nt*(pad+1)+(time)].fCharge) return kFALSE;
+  //if(charge < fRow[nt*(pad-1)+(time+1)].fCharge) return kFALSE;
+  if(charge < fRow[nt*(pad)+(time+1)].fCharge) return kFALSE;
+  //if(charge < fRow[nt*(pad+1)+(time+1)].fCharge) return kFALSE;
+  fRow[nt*pad+time].fUsed = kTRUE;
+  return kTRUE;
 }
 
-void AliL3ClusterFitter::FitClusters(AliL3ModelTrack *track)
+void AliL3ClusterFitter::FitClusters(AliL3ModelTrack *track,Int_t *padrange,Int_t *timerange)
 {
   //Handle single and overlapping clusters
     
-  if(!track->IsPresent(fCurrentPadRow) && track->GetNClusters() != fCurrentPadRow - AliL3Transform::GetFirstRow(fPatch))
-    {    
-      if(!track->IsPresent(fCurrentPadRow) && 
-        track->GetNClusters() != fCurrentPadRow - AliL3Transform::GetFirstRow(fPatch) + 1)//debug
-       {
-         cerr<<"AliL3ClusterFitter::FitClusters() : Mismatching clustercount "
-             <<track->GetNClusters()<<" "<<fCurrentPadRow - AliL3Transform::GetFirstRow(fPatch) + 1<<endl;
-         exit(5);
-       }
-      return; //This cluster has been set before.
-    }
-  
-  
-  Int_t minpad,maxpad,mintime,maxtime;
+  //Check whether this cluster has been set before:
   
   Int_t size = FIT_PTS;
   Int_t max_tracks = FIT_MAXPAR/NUM_PARS;
@@ -238,17 +628,18 @@ void AliL3ClusterFitter::FitClusters(AliL3ModelTrack *track)
   
   //Check if at least one cluster is not already fitted
   Bool_t all_fitted=kTRUE;
+  
   Int_t k=-1;
   while(k < track->GetNOverlaps(fCurrentPadRow))
     {
       AliL3ModelTrack *tr=0;
       if(k==-1)
-       tr = track;
+       tr = track;
       else
-       tr = (AliL3ModelTrack*)fTracks->GetCheckedTrack(overlaps[k]);
+       tr = (AliL3ModelTrack*)fProcessTracks->GetCheckedTrack(overlaps[k]);
       k++;
       if(!tr) continue;
-      if(!tr->IsPresent(fCurrentPadRow))
+      if(!tr->IsSet(fCurrentPadRow) && !tr->IsPresent(fCurrentPadRow))//cluster has not been set and is not present
        {
          all_fitted = kFALSE;
          break;
@@ -256,10 +647,12 @@ void AliL3ClusterFitter::FitClusters(AliL3ModelTrack *track)
     }
   if(all_fitted)
     {
-      cout<<"But all the clusters were already fitted on row "<<fCurrentPadRow<<endl;
+      if(fDebug)
+       cout<<"But all the clusters were already fitted on row "<<fCurrentPadRow<<endl;
       return;
     }
   
+  //Allocate fit parameters array; this is interface to the C code
   plane = new DPOINT[FIT_PTS];
   memset(plane,0,FIT_PTS*sizeof(DPOINT));
 
@@ -270,17 +663,11 @@ void AliL3ClusterFitter::FitClusters(AliL3ModelTrack *track)
   Int_t lista[FIT_MAXPAR];
   Double_t dev[FIT_MAXPAR],chisq_f;
   
-  minpad = mintime = 999;
-  maxpad = maxtime = 0;
   Int_t fit_pars=0;
   
-  Int_t ntracks = track->GetNOverlaps(fCurrentPadRow)+1;
-  Bool_t *do_fit = new Bool_t[ntracks];
-  for(Int_t i=0; i<ntracks; i++)
-    do_fit[i]=kTRUE;
-  
   Int_t n_overlaps=0;
   k=-1;
+  
   //Fill the overlapping tracks:
   while(k < track->GetNOverlaps(fCurrentPadRow))
     {
@@ -288,50 +675,39 @@ void AliL3ClusterFitter::FitClusters(AliL3ModelTrack *track)
       if(k==-1)
        tr = track;
       else
-       tr = (AliL3ModelTrack*)fTracks->GetCheckedTrack(overlaps[k]);
+       tr = (AliL3ModelTrack*)fProcessTracks->GetCheckedTrack(overlaps[k]);
       k++;
       if(!tr) continue;
       
-      Int_t hitpad = (Int_t)rint(tr->GetPadHit(fCurrentPadRow));
-      Int_t hittime = (Int_t)rint(tr->GetTimeHit(fCurrentPadRow));
+      if(tr->IsSet(fCurrentPadRow) && !tr->IsPresent(fCurrentPadRow)) continue;//Cluster fit failed before
+      
+      //Use the local maxima as the input to the fitting routine.
+      //The local maxima is temporary stored in the cluster model:
+      Int_t hitpad = (Int_t)rint(tr->GetClusterModel(fCurrentPadRow)->fDPad);  //rint(tr->GetPadHit(fCurrentPadRow));
+      Int_t hittime = (Int_t)rint(tr->GetClusterModel(fCurrentPadRow)->fDTime); //rint(tr->GetTimeHit(fCurrentPadRow));
       Int_t charge = fRow[(AliL3Transform::GetNTimeBins()+1)*hitpad + hittime].fCharge;
-      if(!charge) //There is not charge here, so the cluster is non-existing -- remove it.
-       {
-         if(tr->GetNClusters() == fCurrentPadRow - AliL3Transform::GetFirstRow(fPatch))
-           tr->SetCluster(fCurrentPadRow,0,0,0,0,0,0);           
-         do_fit[k] = kFALSE;
-         continue;
-       }
       
-      if(k==0)
-       LocateCluster(tr,minpad,maxpad,mintime,maxtime);
-
-      if(tr->GetPadHit(fCurrentPadRow) < (Double_t)minpad || tr->GetPadHit(fCurrentPadRow) > (Double_t)maxpad ||
-        tr->GetTimeHit(fCurrentPadRow) < (Double_t)mintime || tr->GetTimeHit(fCurrentPadRow) > (Double_t)maxtime)
+      if(fDebug)
+       cout<<"Fitting track cluster, pad "<<tr->GetPadHit(fCurrentPadRow)<<" time "
+           <<tr->GetTimeHit(fCurrentPadRow)<<" charge "<<charge<<" at local maxima in pad "<<hitpad
+           <<" time "<<hittime<<" xywidth "<<sqrt(tr->GetParSigmaY2(fCurrentPadRow))
+           <<" zwidth "<<sqrt(tr->GetParSigmaZ2(fCurrentPadRow))<<endl;
+      
+      if(charge==0)
        {
-         do_fit[k] = kFALSE;//This cluster is outside the region already specified, so it will not be included in this fit.
-
-         //If this is the first: remove it, because it will not be checked again.
-         if(k==0)
-           if(tr->GetNClusters() == fCurrentPadRow - AliL3Transform::GetFirstRow(fPatch))
-             tr->SetCluster(fCurrentPadRow,0,0,0,0,0,0);                 
-         continue;
+         cerr<<"Charge still zero!"<<endl;
+         exit(5);
        }
+            
+      a[n_overlaps*NUM_PARS+2] = hitpad;
+      a[n_overlaps*NUM_PARS+4] = hittime;
       
-      
-      cout<<"Fitting track cluster, pad "<<tr->GetPadHit(fCurrentPadRow)<<" time "
-         <<tr->GetTimeHit(fCurrentPadRow)<<" charge "<<charge<<" xywidth "<<sqrt(tr->GetParSigmaY2(fCurrentPadRow))
-         <<" zwidth "<<sqrt(tr->GetParSigmaZ2(fCurrentPadRow))<<endl;
-      
-      a[n_overlaps*NUM_PARS+2] = tr->GetPadHit(fCurrentPadRow);
-      a[n_overlaps*NUM_PARS+4] = tr->GetTimeHit(fCurrentPadRow);
-      
-      if(!tr->IsPresent(fCurrentPadRow)) //Cluster is not fitted before
+      if(!tr->IsSet(fCurrentPadRow)) //Cluster is not fitted before
        {
          a[n_overlaps*NUM_PARS+1] = charge;
-         a[n_overlaps*NUM_PARS+3] = sqrt(tr->GetParSigmaY2(fCurrentPadRow))*sqrt(2);
-         a[n_overlaps*NUM_PARS+5] = sqrt(tr->GetParSigmaZ2(fCurrentPadRow))*sqrt(2);
-         a[n_overlaps*NUM_PARS+6] = sqrt(tr->GetParSigmaZ2(fCurrentPadRow))*sqrt(2);
+         a[n_overlaps*NUM_PARS+3] = sqrt(tr->GetParSigmaY2(fCurrentPadRow)) * GetYWidthFactor();
+         a[n_overlaps*NUM_PARS+5] = sqrt(tr->GetParSigmaZ2(fCurrentPadRow)) * GetZWidthFactor();
+         a[n_overlaps*NUM_PARS+6] = sqrt(tr->GetParSigmaZ2(fCurrentPadRow)) * GetZWidthFactor();
          lista[n_overlaps*NUM_PARS + 1] = 1;
          lista[n_overlaps*NUM_PARS + 2] = 1;
          lista[n_overlaps*NUM_PARS + 3] = 0;
@@ -340,8 +716,13 @@ void AliL3ClusterFitter::FitClusters(AliL3ModelTrack *track)
          lista[n_overlaps*NUM_PARS + 6] = 0;
          fit_pars             += 3;
        }
-      else
+      else  //Cluster was fitted before
        {
+         if(!tr->IsPresent(fCurrentPadRow))
+           {
+             cerr<<"AliL3ClusterFitter::FindClusters : Cluster not present; there is a bug here"<<endl;
+             exit(5);
+           }
          Int_t charge;
          Float_t xywidth,zwidth,pad,time;
          tr->GetPad(fCurrentPadRow,pad);
@@ -349,14 +730,15 @@ void AliL3ClusterFitter::FitClusters(AliL3ModelTrack *track)
          tr->GetClusterCharge(fCurrentPadRow,charge);
          xywidth = sqrt(tr->GetParSigmaY2(fCurrentPadRow));
          zwidth = sqrt(tr->GetParSigmaZ2(fCurrentPadRow));
-         cout<<"Cluster had been fitted before, pad "<<pad<<" time "<<time<<" charge "<<charge<<" width "<<xywidth<<" "<<zwidth<<endl;
+         if(fDebug)
+           cout<<"Cluster had been fitted before, pad "<<pad<<" time "<<time<<" charge "<<charge<<" width "<<xywidth<<" "<<zwidth<<endl;
          
          a[n_overlaps*NUM_PARS+2] = pad;
          a[n_overlaps*NUM_PARS+4] = time;
          a[n_overlaps*NUM_PARS+1] = charge;
-         a[n_overlaps*NUM_PARS+3] = sqrt(xywidth)*sqrt(2);
-         a[n_overlaps*NUM_PARS+5] = sqrt(zwidth)*sqrt(2);
-         a[n_overlaps*NUM_PARS+6] = sqrt(zwidth)*sqrt(2);
+         a[n_overlaps*NUM_PARS+3] = sqrt(xywidth) * GetYWidthFactor();
+         a[n_overlaps*NUM_PARS+5] = sqrt(zwidth) * GetZWidthFactor();
+         a[n_overlaps*NUM_PARS+6] = sqrt(zwidth) * GetZWidthFactor();
 
          lista[n_overlaps*NUM_PARS + 1] = 1;
          lista[n_overlaps*NUM_PARS + 2] = 0;
@@ -370,46 +752,44 @@ void AliL3ClusterFitter::FitClusters(AliL3ModelTrack *track)
     }
   
   if(n_overlaps==0) //No clusters here
-    return;
-  cout<<"Setting init searchrange; pad "<<minpad<<" "<<maxpad<<" time "<<mintime<<" "<<maxtime<<endl;
+    {
+      delete [] plane;
+      return;
+    }
 
-  if(minpad <= 0)
-    minpad=0;
-  if(mintime<=0)
-    mintime=0;
-  if(maxpad>=AliL3Transform::GetNPads(fCurrentPadRow)-1)
-    maxpad=AliL3Transform::GetNPads(fCurrentPadRow)-1;
-  if(maxtime>=AliL3Transform::GetNTimeBins()-1)
-    maxtime=AliL3Transform::GetNTimeBins()-1;
-  
   Int_t pad_num=0;
   Int_t time_num_max=0;
   Int_t ndata=0;
   Int_t tot_charge=0;
-
-  for(Int_t i=minpad; i<=maxpad; i++)
+  if(fDebug)
+    cout<<"Padrange "<<padrange[0]<<" "<<padrange[1]<<" timerange "<<timerange[0]<<" "<<timerange[1]<<endl;
+  for(Int_t i=padrange[0]; i<=padrange[1]; i++)
     {
       Int_t max_charge = 0;
       Int_t time_num=0;
-      for(Int_t j=mintime; j<=maxtime; j++)
+      for(Int_t j=timerange[0]; j<=timerange[1]; j++)
        {
          Int_t charge = fRow[(AliL3Transform::GetNTimeBins()+1)*i + j].fCharge;
          
          if(charge <= 0) continue;
 
+         time_num++;
          if(charge > max_charge)
            {
              max_charge = charge;
-             time_num++;
+             //time_num++;
            }
-         cout<<"Filling padrow "<<fCurrentPadRow<<" pad "<<i<<" time "<<j<<" charge "<<charge<<endl;
+         if(fDebug)
+           cout<<"Filling padrow "<<fCurrentPadRow<<" pad "<<i<<" time "<<j<<" charge "<<charge<<endl;
          tot_charge += charge;
          ndata++;
          if(ndata >= size)
-           cerr<<"Too many points"<<endl;
-         
-         //This digit will most likely be used:
-         fRow[(AliL3Transform::GetNTimeBins()+1)*i + j].fUsed = kTRUE;
+           {
+             cerr<<"Too many points; row "<<fCurrentPadRow<<" padrange "<<padrange[0]<<" "<<padrange[1]<<" timerange "
+                 <<timerange[0]<<" "<<timerange[1]<<endl;
+             exit(5);
+           }
+
          plane[ndata].u = (Double_t)i;
          plane[ndata].v = (Double_t)j;
          x[ndata]=ndata;
@@ -422,39 +802,35 @@ void AliL3ClusterFitter::FitClusters(AliL3ModelTrack *track)
        time_num_max = time_num;
     }
   
-  k=-1;
-  if(pad_num <= 1 || time_num_max <=1 || n_overlaps > fNmaxOverlaps) //too few to do fit
+  if(pad_num <= 1 || time_num_max <=1 || n_overlaps > fNmaxOverlaps || ndata <= fit_pars) //too few to do fit
     {
-      while(k < track->GetNOverlaps(fCurrentPadRow))
-       {
-         AliL3ModelTrack *tr=0;
-         if(k==-1)
-           tr = track;
-         else
-           tr = (AliL3ModelTrack*)fTracks->GetCheckedTrack(overlaps[k]);
-         k++;
-         if(!tr) continue;
-         if(do_fit[k] == kFALSE) continue;
-         
-         if(tr->GetNClusters() == fCurrentPadRow - AliL3Transform::GetFirstRow(fPatch))
-           tr->SetCluster(fCurrentPadRow,0,0,0,0,0,0);
-       }
-      cout<<"Too few digits or too many overlaps: "<<pad_num<<" "<<time_num_max<<" "<<n_overlaps<<endl;
+      SetClusterfitFalse(track);
+      if(fDebug)
+       cout<<"Too few digits or too many overlaps: "<<pad_num<<" "<<time_num_max<<" "<<n_overlaps<<" ndata "<<ndata<<" fit_pars "<<fit_pars<<endl;
+      delete [] plane;
       return;
     }
+
   
   Int_t npars = n_overlaps * NUM_PARS;
-  cout<<"Number of overlapping clusters "<<n_overlaps<<endl;
+  if(fDebug)
+    cout<<"Number of overlapping clusters "<<n_overlaps<<endl;
   Int_t ret = lev_marq_fit( x, y, s, ndata, a, lista, dev, npars, &chisq_f, f2gauss5 );
-  if(ret)
+  
+  if(ret<0)
     {
-      cerr<<"Fit error"<<endl;
-      exit(5);
+      SetClusterfitFalse(track);
+      fFailed++;
+      fFitError++;
+      delete [] plane;
+      return;
+      //exit(5);
     }
 
   chisq_f /= (ndata-fit_pars);
-  cout<<"Chisq "<<chisq_f<<endl;
-
+  if(fDebug)
+    cout<<"Chisq "<<chisq_f<<endl;
+  
   k=-1;
   n_overlaps=0;
   while(k < track->GetNOverlaps(fCurrentPadRow))
@@ -463,27 +839,242 @@ void AliL3ClusterFitter::FitClusters(AliL3ModelTrack *track)
       if(k==-1)
        tr = track;
       else
-       tr = (AliL3ModelTrack*)fTracks->GetCheckedTrack(overlaps[k]);
+       tr = (AliL3ModelTrack*)fProcessTracks->GetCheckedTrack(overlaps[k]);
       k++;
       if(!tr) continue;
-      if(do_fit[k] == kFALSE) continue;
-      
       if(!tr->IsPresent(fCurrentPadRow))
        {
-         if(tr->GetNClusters() != fCurrentPadRow - AliL3Transform::GetFirstRow(fPatch)) continue;//This cluster has been set before
+         if(tr->IsSet(fCurrentPadRow)) continue;//This cluster has been set before
+         
          if(chisq_f < fChiSqMax)//cluster fit is good enough
            {
              tot_charge = (Int_t)(a[n_overlaps*NUM_PARS+1] * a[n_overlaps*NUM_PARS+3] * a[n_overlaps*NUM_PARS+5]);
-             tr->SetCluster(fCurrentPadRow,a[n_overlaps*NUM_PARS+2],a[n_overlaps*NUM_PARS+4],tot_charge,0,0,pad_num);
-             cout<<"Setting cluster in pad "<<a[n_overlaps*NUM_PARS+2]<<" time "<<a[n_overlaps*NUM_PARS+4]<<" charge "<<tot_charge<<endl;
+             Float_t fpad = a[n_overlaps*NUM_PARS+2];
+             Float_t ftime = a[n_overlaps*NUM_PARS+4];
+             if(tot_charge < 0 || fpad < -1 || fpad > AliL3Transform::GetNPads(fCurrentPadRow) || 
+                ftime < -1 || ftime > AliL3Transform::GetNTimeBins())
+               {
+                 if(fDebug)
+                   cout<<"AliL3ClusterFitter::Fatal result(s) in fit; in slice "<<fSlice<<" row "<<fCurrentPadRow
+                       <<"; pad "<<fpad<<" time "<<ftime<<" charge "<<tot_charge<<" xywidth "<<a[n_overlaps*NUM_PARS+3]
+                       <<" zwidth "<<a[n_overlaps*NUM_PARS+5]<<" peakcharge "<<a[n_overlaps*NUM_PARS+1]<<endl;
+                 tr->SetCluster(fCurrentPadRow,0,0,0,0,0,0);
+                 fFailed++;
+                 fResultError++;
+                 continue;
+               }
+             
+             tr->SetCluster(fCurrentPadRow,fpad,ftime,tot_charge,0,0,pad_num);
+             if(fDebug)
+               cout<<"Setting cluster in pad "<<a[n_overlaps*NUM_PARS+2]<<" time "<<a[n_overlaps*NUM_PARS+4]<<" charge "<<tot_charge<<endl;
+             /*
+             //Set the digits to used:
+             for(Int_t i=padrange[0]; i<=padrange[1]; i++)
+             for(Int_t j=timerange[0]; j<=timerange[1]; j++)
+             fRow[(AliL3Transform::GetNTimeBins()+1)*i + j].fUsed = kTRUE;
+             */
+             fFitted++;
            }
          else //fit was too bad
-           tr->SetCluster(fCurrentPadRow,0,0,0,0,0,0);
+           {
+             if(fDebug)
+               cout<<"Cluster fit was too bad"<<endl;
+             tr->SetCluster(fCurrentPadRow,0,0,0,0,0,0);
+             fBadFitError++;
+             fFailed++;
+           }
        }
       n_overlaps++;
     }
   
   delete [] plane;
-  delete [] do_fit;
 }
 
+void AliL3ClusterFitter::SetClusterfitFalse(AliL3ModelTrack *track)
+{
+  //Cluster fit failed, so set the clusters to all the participating
+  //tracks to zero.
+  
+  Int_t i=-1;
+  Int_t *overlaps = track->GetOverlaps(fCurrentPadRow);
+  while(i < track->GetNOverlaps(fCurrentPadRow))
+    {
+      AliL3ModelTrack *tr=0;
+      if(i==-1)
+       tr = track;
+      else
+       tr = (AliL3ModelTrack*)fProcessTracks->GetCheckedTrack(overlaps[i]);
+      i++;
+      if(!tr) continue;
+      
+      tr->SetCluster(fCurrentPadRow,0,0,0,0,0,0);
+    }
+}
+
+
+void AliL3ClusterFitter::AddClusters()
+{
+  if(!fClusters)
+    {
+      fClusters = new AliL3SpacePointData[fNMaxClusters];
+      fNClusters=0;
+    }
+  
+  if(fDebug)
+    cout<<"Writing cluster in slice "<<fSlice<<" patch "<<fPatch<<endl;
+  
+  AliL3TrackArray *tracks=0;
+  if(fSeeding==kTRUE)
+    tracks = fSeeds;
+  else
+    tracks = fTracks;
+  
+  if(!tracks)
+    return;
+  
+  for(Int_t i=0; i<tracks->GetNTracks(); i++)
+    {
+      AliL3ModelTrack *tr = (AliL3ModelTrack*)tracks->GetCheckedTrack(i);
+      if(!tr) continue;
+      
+      UInt_t *hitids = tr->GetHitNumbers();
+      Int_t nhits = tr->GetNHits();
+      for(Int_t i=fRowMax; i>=fRowMin; i--)
+       {
+         if(fSeeding)
+           if(tr->GetClusterModel(i)->fSlice != fSlice) continue;
+         if(!tr->IsPresent(i)) continue;
+         fCurrentPadRow = i;
+         Float_t pad,time,xywidth,zwidth;
+         Int_t charge;
+         tr->GetPad(i,pad);
+         tr->GetTime(i,time);
+         tr->GetClusterCharge(i,charge);
+
+         if(pad < -1 || pad >= AliL3Transform::GetNPads(i) || 
+            time < -1 || time >= AliL3Transform::GetNTimeBins())
+           {
+             continue;
+             cout<<"slice "<<fSlice<<" row "<<i<<" pad "<<pad<<" time "<<time<<endl;
+             tr->Print();
+             exit(5);
+           }
+
+         tr->CalculateClusterWidths(i,kTRUE); //Parametrize errors
+         
+         tr->GetXYWidth(i,xywidth);
+         tr->GetZWidth(i,zwidth);
+         Float_t xyz[3];
+         Int_t sector,row;
+         AliL3Transform::Slice2Sector(fSlice,i,sector,row);
+         
+         AliL3Transform::Raw2Global(xyz,sector,row,pad,time);
+         
+         if(fNClusters >= fNMaxClusters)
+           {
+             cerr<<"AliL3ClusterFitter::AddClusters : Too many clusters "<<fNClusters<<endl;
+             exit(5);
+           }
+         fClusters[fNClusters].fX = xyz[0];
+         fClusters[fNClusters].fY = xyz[1];
+         fClusters[fNClusters].fZ = xyz[2];
+         fClusters[fNClusters].fCharge = charge;
+         fClusters[fNClusters].fPadRow = i;
+         Int_t pa = AliL3Transform::GetPatch(i);
+         if(xywidth==0 || zwidth==0)
+           cerr<<"AliL3ClusterFitter::AddClusters : Cluster with zero width"<<endl;
+         if(xywidth>0)
+           fClusters[fNClusters].fSigmaY2 = xywidth*pow(AliL3Transform::GetPadPitchWidth(pa),2);
+         else
+           fClusters[fNClusters].fSigmaY2 = 1;
+         if(zwidth>0)
+           fClusters[fNClusters].fSigmaZ2 = zwidth*pow(AliL3Transform::GetZWidth(),2);
+         else
+           fClusters[fNClusters].fSigmaZ2 = 1;
+         Int_t pat=fPatch;
+         if(fPatch==-1)
+           pat=0;
+         fClusters[fNClusters].fID = fNClusters + ((fSlice&0x7f)<<25)+((pat&0x7)<<22);
+         
+         if(nhits >= 159)
+           {
+             cerr<<"AliL3ClusterFitter::AddClusters : Cluster counter of out range "<<nhits<<endl;
+             exit(5);
+           }
+         hitids[nhits++] = fClusters[fNClusters].fID;
+         
+#ifdef do_mc
+         Int_t trackID[3];
+         Int_t fpad = (Int_t)rint(pad);
+         Int_t ftime = (Int_t)rint(time);
+         if(fpad < 0)
+           fpad=0;
+         if(fpad >= AliL3Transform::GetNPads(i))
+           fpad = AliL3Transform::GetNPads(i)-1;
+         if(ftime<0)
+           ftime=0;
+         if(ftime >= AliL3Transform::GetNTimeBins())
+           ftime = AliL3Transform::GetNTimeBins()-1;
+         GetTrackID(fpad,ftime,trackID);
+         fClusters[fNClusters].fTrackID[0] = trackID[0];
+         fClusters[fNClusters].fTrackID[1] = trackID[1];
+         fClusters[fNClusters].fTrackID[2] = trackID[2];
+#endif  
+         //cout<<"Setting id "<<trackID[0]<<" on pad "<<pad<<" time "<<time<<" row "<<i<<endl;
+         fNClusters++;
+       }
+      
+      //Copy back the number of assigned clusters
+      tr->SetNHits(nhits);
+    }
+}
+
+void AliL3ClusterFitter::WriteTracks()
+{
+  if(!fSeeds)
+    return;
+  
+  AliL3Compress *c = new AliL3Compress(-1,-1,fPath);
+  c->WriteFile(fSeeds,"tracks_after.raw");
+  delete c;
+  
+  Int_t clustercount=0;
+  for(Int_t i=0; i<fSeeds->GetNTracks(); i++)
+    {
+      AliL3ModelTrack *tr = (AliL3ModelTrack*)fSeeds->GetCheckedTrack(i);
+      if(!tr) continue;
+      if(tr->GetNHits()==0)
+       fSeeds->Remove(i);
+      clustercount += tr->GetNHits();
+      /*
+       if(tr->GetPt() > 1 && tr->GetNPresentClusters() < 150) 
+       tr->Print();
+      */
+    }
+  cout<<"Writing "<<clustercount<<" clusters"<<endl;
+  fSeeds->Compress();
+  AliL3MemHandler mem;
+  Char_t filename[1024];
+  sprintf(filename,"%s/fitter/tracks_0.raw",fPath);
+  mem.SetBinaryOutput(filename);
+  mem.TrackArray2Binary(fSeeds);
+  mem.CloseBinaryOutput();
+  
+}
+
+void AliL3ClusterFitter::WriteClusters()
+{
+  AliL3MemHandler mem;
+  if(fDebug)
+    cout<<"Write "<<fNClusters<<" clusters to file"<<endl;
+  Char_t filename[1024];
+  sprintf(filename,"%s/fitter/points_0_%d_%d.raw",fPath,fSlice,fPatch);
+  mem.SetBinaryOutput(filename);
+  mem.Memory2Binary(fNClusters,fClusters);
+  mem.CloseBinaryOutput();
+  mem.Free();
+  
+  delete [] fClusters;
+  fClusters=0;
+  fNClusters=0;
+}
index e7ae5b1..84711b3 100644 (file)
@@ -1,31 +1,68 @@
+// @(#) $Id$
+
 #ifndef AliL3_ClusterFitter
 #define AliL3_ClusterFitter
 
 #include "AliL3RootTypes.h"
 #include "AliL3Modeller.h"
+#include "AliL3Transform.h"
 
 class AliL3ModelTrack;
+class AliL3TrackArray;
+class AliL3SpacePointData;
 
 class AliL3ClusterFitter : public AliL3Modeller {
   
  private:
-  Int_t fPadFitRange;
-  Int_t fTimeFitRange;
   Int_t fNmaxOverlaps;
+  Int_t fRowMin;
+  Int_t fRowMax;
   Float_t fChiSqMax;
+  Float_t fYInnerWidthFactor;
+  Float_t fZInnerWidthFactor;
+  Float_t fYOuterWidthFactor;
+  Float_t fZOuterWidthFactor;
+  Int_t fFitted;
+  Int_t fFailed;
+  static Int_t fBadFitError;
+  static Int_t fFitError;
+  static Int_t fResultError;
+  static Int_t fFitRangeError;
+  Bool_t fSeeding;
+  Int_t fNMaxClusters;
+  Int_t fNClusters;
+  AliL3TrackArray *fSeeds; //!
+  AliL3TrackArray *fProcessTracks; //!
+  AliL3SpacePointData *fClusters; //!
   
-  void FitCluster(AliL3ModelTrack *track);
-  void FitClusters(AliL3ModelTrack *track);
-  
+  void FitClusters(AliL3ModelTrack *track,Int_t *padrange,Int_t *timerange);
+  Bool_t CheckCluster(Int_t trackindex);
+  Bool_t IsMaximum(Int_t pad,Int_t time);
+  Bool_t SetFitRange(AliL3ModelTrack *track,Int_t *padrange,Int_t *timerange);
+  void SetClusterfitFalse(AliL3ModelTrack *track);
+
  public:
   AliL3ClusterFitter();
+  AliL3ClusterFitter(Char_t *path);
   virtual ~AliL3ClusterFitter();
   
+  void Init(Int_t slice,Int_t patch,Int_t *rowrange,AliL3TrackArray *tracks);
+  void Init(Int_t slice,Int_t patch);
+  void LoadSeeds(Int_t *rowrange,Bool_t offline=kTRUE);
   void FindClusters();
-
-  void SetFitRange(Int_t p,Int_t t) {fPadFitRange=p; fTimeFitRange=t;}
+  void AddClusters();
+  void WriteClusters();
+  void WriteTracks();
   void SetNmaxOverlaps(Int_t i) {fNmaxOverlaps=i;}
-
+  void SetChiSqMax(Float_t f) {fChiSqMax = f;}
+  void SetInnerWidthFactor(Float_t y,Float_t z) {fYInnerWidthFactor=y; fZInnerWidthFactor=z;}
+  void SetOuterWidthFactor(Float_t y,Float_t z) {fYOuterWidthFactor=y; fZOuterWidthFactor=z;}
+  
+  Float_t GetYWidthFactor() {return fCurrentPadRow < AliL3Transform::GetLastRow(1) ? fYInnerWidthFactor : fYOuterWidthFactor;}
+  Float_t GetZWidthFactor() {return fCurrentPadRow < AliL3Transform::GetLastRow(1) ? fZInnerWidthFactor : fZOuterWidthFactor;}
+  AliL3TrackArray *GetSeeds() {return fSeeds;}
+  
+  
   ClassDef(AliL3ClusterFitter,1) 
 
 };
index 34fa554..26e2bd2 100644 (file)
@@ -1,3 +1,5 @@
+// @(#) $Id$
+
 #ifdef __CINT__
  
 #pragma link off all globals;
@@ -7,6 +9,7 @@
 #pragma link C++ class AliL3Modeller; 
 #pragma link C++ class AliL3ModelTrack; 
 #pragma link C++ class AliL3Compress; 
+#pragma link C++ class AliL3ClusterFitter; 
 #pragma link C++ class AliL3DataCompressor; 
 
 #endif
index a60fdb4..f7142b7 100644 (file)
@@ -1,23 +1,37 @@
-//$Id$
+// @(#) $Id$
 
 // Author: Anders Vestbo <mailto:vestbo$fi.uib.no>
-//*-- Copyright &copy ASV
+//*-- Copyright &copy ALICE HLT Group
 
 #include "AliL3StandardIncludes.h"
-#include <TH1.h>
-#include <TH2.h>
-#include <TRandom.h>
 
+#include "bitio.h"
+#include "AliL3RootTypes.h"
+#include "AliL3Models.h"
+#include "AliL3DigitData.h"
 #include "AliL3Logging.h"
-#include "AliL3Compress.h"
 #include "AliL3TrackArray.h"
 #include "AliL3ModelTrack.h"
 #include "AliL3Transform.h"
 #include "AliL3MemHandler.h"
+#include "AliL3DataCompressor.h"
+
+#if 0
+#ifdef use_root
+#include <TH1.h>
+#include <TH2.h>
+#include <TRandom.h>
+#endif
 #ifdef use_aliroot
 #include "AliL3FileHandler.h"
 #endif
-#include "bitio.h"
+#endif
+
+#include "AliL3Compress.h"
+
+#if GCCVERSION == 3
+using namespace std;
+#endif
 
 //_____________________________________________________________
 //
@@ -30,22 +44,18 @@ ClassImp(AliL3Compress)
 AliL3Compress::AliL3Compress()
 {
   fTracks=0;
-  SetBitNumbers(0,0,0,0);
   fSlice =0;
   fPatch=0;
-  fDigits=0;
-  fDPt=0;
   fWriteShape=kFALSE;
+  fEvent=-1;
 }
 
-AliL3Compress::AliL3Compress(Int_t slice,Int_t patch,Char_t *path,Bool_t writeshape)
+AliL3Compress::AliL3Compress(Int_t slice,Int_t patch,Char_t *path,Bool_t writeshape,Int_t event)
 {
+  fEvent=event;
   fSlice=slice;
   fPatch=patch;
-  SetBitNumbers(0,0,0,0);
   fTracks=0;
-  fDigits=0;
-  fDPt=0;
   sprintf(fPath,"%s",path);
   fWriteShape=writeshape;
 }
@@ -54,32 +64,25 @@ AliL3Compress::~AliL3Compress()
 {
   if(fTracks)
     delete fTracks;
-  if(fDigits)
-    delete [] fDigits;
-  if(fDPt)
-    delete [] fDPt;
 }
 
-void AliL3Compress::SetBitNumbers(Int_t pad,Int_t time,Int_t charge,Int_t shape)
+Bool_t AliL3Compress::WriteFile(AliL3TrackArray *tracks,Char_t *filename)
 {
-  fNumPadBits=pad;
-  fNumTimeBits=time;
-  fNumChargeBits=charge;
-  fNumShapeBits=shape;
-}
+  Char_t fname[1024];
+  if(filename)
+    sprintf(fname,"%s/comp/%s",fPath,filename);
+  else if(fEvent<0)
+    sprintf(fname,"%s/comp/tracks_m_%d_%d.raw",fPath,fSlice,fPatch);
+  else
+    sprintf(fname,"%s/comp/tracks_m_%d_%d_%d.raw",fPath,fEvent,fSlice,fPatch);
 
-void AliL3Compress::WriteFile(AliL3TrackArray *tracks)
-{
-  Char_t fname[100];
-  sprintf(fname,"%s/comp/tracks_m_%d_%d.raw",fPath,fSlice,fPatch);
   FILE *file = fopen(fname,"w");
   if(!file)
     {
       cerr<<"AliL3Compress::WriteFile : Error opening file "<<fname<<endl;
-      return;
+      return kFALSE;
     }
   Short_t ntracks = tracks->GetNTracks();
-  //cout<<"Writing "<<ntracks<<" tracks to file"<<endl;
     
   Int_t count=0;
   AliL3ClusterModel *clusters=0;
@@ -88,54 +91,65 @@ void AliL3Compress::WriteFile(AliL3TrackArray *tracks)
     {
       AliL3ModelTrack *track = (AliL3ModelTrack*)tracks->GetCheckedTrack(i);
       if(!track) continue;
-      
+
       //Do not save useless tracks or clusters:
-      if(track->GetNPresentClusters() == 0)
-       continue;
+      //if(track->GetNPresentClusters() == 0)
+      //continue;
       
       track->FillModel();
       model = track->GetModel();
       if(model->fNClusters==0) continue;
       clusters = track->GetClusters();
-      //cout<<"Writing "<<(int)model->fNClusters<<" clusters"<<endl;
       if(fwrite(model,sizeof(AliL3TrackModel),1,file)!=1) break;
-      //cout<<"Writing "<<(int)model->fNClusters<<" clusters to file"<<endl;
       if(fwrite(clusters,model->fNClusters*sizeof(AliL3ClusterModel),1,file)!=1) break;
-      //track->Print();
       count++;
       
     }
-  //cout<<"Wrote "<<count<<" tracks "<<endl;
   fclose(file);
+  return kTRUE;
 }
 
-void AliL3Compress::ReadFile(Char_t which)
+Bool_t AliL3Compress::ReadFile(Char_t which,Char_t *filename)
 {
   //Read the trackfile.
 
-  Char_t fname[100];
-  if(which == 'm')
-    sprintf(fname,"%s/comp/tracks_m_%d_%d.raw",fPath,fSlice,fPatch);
-  else if(which == 'u')
-    sprintf(fname,"%s/comp/tracks_u_%d_%d.raw",fPath,fSlice,fPatch);
+  Char_t fname[1024];
+  if(filename)
+    sprintf(fname,"%s/comp/%s",fPath,filename);
   else
     {
-      cerr<<"AliL3Compress::ReadFile() : Wrong option"<<endl;
-      return;
+      if(which == 'm')
+       {
+         if(fEvent<0)
+           sprintf(fname,"%s/comp/tracks_m_%d_%d.raw",fPath,fSlice,fPatch);
+         else
+           sprintf(fname,"%s/comp/tracks_m_%d_%d_%d.raw",fPath,fEvent,fSlice,fPatch);
+       }
+      else if(which == 'u')
+       {
+         if(fEvent<0)
+           sprintf(fname,"%s/comp/tracks_u_%d_%d.raw",fPath,fSlice,fPatch);
+         else
+           sprintf(fname,"%s/comp/tracks_u_%d_%d_%d.raw",fPath,fEvent,fSlice,fPatch);
+       }
+      else
+       {
+         cerr<<"AliL3Compress::ReadFile() : Wrong option"<<endl;
+         return kFALSE;
+       }
     }
 
   FILE *file = fopen(fname,"r");
   if(!file)
     {
       cerr<<"AliL3Compress::ReadFile : Cannot open file "<<fname<<endl;
-      return;
+      return kFALSE;
     }
 
   if(fTracks)
     delete fTracks;
   fTracks = new AliL3TrackArray("AliL3ModelTrack");
   
-  //cout<<"Reading file "<<fname<<endl;
   while(!feof(file))
     {
       AliL3ModelTrack *track = (AliL3ModelTrack*)fTracks->NextTrack();
@@ -143,33 +157,34 @@ void AliL3Compress::ReadFile(Char_t which)
       AliL3TrackModel *model = track->GetModel();
       AliL3ClusterModel *clusters = track->GetClusters();
       if(fread(model,sizeof(AliL3TrackModel),1,file)!=1) break;
-      if(fread(clusters,(model->fNClusters)*sizeof(AliL3ClusterModel),1,file)!=1) break;
+      if(fread(clusters,model->fNClusters*sizeof(AliL3ClusterModel),1,file)!=1) break;
       track->FillTrack();
     }
 
   fTracks->RemoveLast();
-  //cout<<"Read "<<fTracks->GetNTracks()<<" tracks from file"<<endl;
   fclose(file);
+  return kTRUE;
 }
 
-void AliL3Compress::CompressFile()
+Bool_t AliL3Compress::CompressFile()
 {
-  if(fNumTimeBits==0)
-    {
-      cerr<<"AliL3Compress::CompressFile() : Bitnumbers not set"<<endl;
-      return;
-    }
-  
   Char_t fname[100];
-  sprintf(fname,"%s/comp/tracks_c_%d_%d.raw",fPath,fSlice,fPatch);
+  if(fEvent<0)
+    sprintf(fname,"%s/comp/tracks_c_%d_%d.raw",fPath,fSlice,fPatch);
+  else
+    sprintf(fname,"%s/comp/tracks_c_%d_%d_%d.raw",fPath,fEvent,fSlice,fPatch);
   BIT_FILE *output = OpenOutputBitFile(fname);
   
-  sprintf(fname,"%s/comp/tracks_m_%d_%d.raw",fPath,fSlice,fPatch);
+  if(fEvent<0)
+    sprintf(fname,"%s/comp/tracks_m_%d_%d.raw",fPath,fSlice,fPatch);
+  else
+    sprintf(fname,"%s/comp/tracks_m_%d_%d_%d.raw",fPath,fEvent,fSlice,fPatch);
+  
   FILE *input = fopen(fname,"r");
   if(!input)
     {
       cerr<<"AliL3Compress::CompressFile() : Error opening file: "<<fname<<endl;
-      return;
+      return kFALSE;
     }
 
   AliL3TrackModel track;
@@ -194,6 +209,8 @@ void AliL3Compress::CompressFile()
       
       //Write track parameters:
       fwrite(&track,sizeof(AliL3TrackModel),1,output->file);
+      
+      Int_t origslice=-1,slice,clustercount=0;
       for(Int_t i=0; i<track.fNClusters; i++)
        {
          if(fread(&cluster,sizeof(AliL3ClusterModel),1,input)!=1) break;
@@ -203,43 +220,68 @@ void AliL3Compress::CompressFile()
          OutputBit(output,temp);
          if(!temp) continue;
          
+         if(cluster.fSlice<0 || cluster.fSlice>35)
+           {
+             cerr<<"AliL3DataCompress::CompressFile : Fucked up slice number :"<<cluster.fSlice<<endl;
+             exit(5);
+           }
+         
+         //Write slice number of first point
+         if(clustercount==0)
+           {
+             origslice = cluster.fSlice;
+             OutputBits(output,origslice,6); //Need 6 bits to encode slice number
+           }
+         else
+           {
+             slice = cluster.fSlice;
+             if(slice == origslice)
+               OutputBit(output,0);
+             else
+               {
+                 OutputBit(output,1);
+                 OutputBits(output,slice,6);
+                 origslice=slice;
+               }
+           }
+         
          //Write time information:
-         temp = (Int_t)cluster.fDTime;
+         temp = (Int_t)rint(cluster.fDTime);
          if(temp<0)
            OutputBit(output,0);
          else
            OutputBit(output,1);
-         power = 1<<(fNumTimeBits-1);
+         power = 1<<(AliL3DataCompressor::GetNTimeBits()-1);
          if(abs(temp)>=power)
            {
              timeo++;
              temp=power - 1;
            }
-         OutputBits(output,abs(temp),(fNumTimeBits-1));
+         OutputBits(output,abs(temp),(AliL3DataCompressor::GetNTimeBits()-1));
          
          //Write pad information:
-         temp = (Int_t)cluster.fDPad;
+         temp = (Int_t)rint(cluster.fDPad);
          if(temp<0)
            OutputBit(output,0);
          else
            OutputBit(output,1);
-         power = 1<<(fNumPadBits-1);
+         power = 1<<(AliL3DataCompressor::GetNPadBits()-1);
          if(abs(temp)>=power)
            {
              pado++;
              temp=power - 1;
            }
-         OutputBits(output,abs(temp),(fNumPadBits-1));
+         OutputBits(output,abs(temp),(AliL3DataCompressor::GetNPadBits()-1));
          
          //Write charge information:
          temp = (Int_t)cluster.fDCharge;
-         power = 1<<(fNumChargeBits);
+         power = 1<<(AliL3DataCompressor::GetNChargeBits());
          if(abs(temp)>=power)
            {
              chargeo++;
              temp=power - 1;
            }
-         OutputBits(output,abs(temp),(fNumChargeBits));
+         OutputBits(output,abs(temp),(AliL3DataCompressor::GetNChargeBits()));
          
          if(fWriteShape)
            {
@@ -249,27 +291,29 @@ void AliL3Compress::CompressFile()
                OutputBit(output,0);
              else
                OutputBit(output,1);
-             power = 1<<(fNumShapeBits-1);
+             power = 1<<(AliL3DataCompressor::GetNShapeBits()-1);
              if(abs(temp) >= power)
                {
                  shapeo++;
                  temp = power - 1;
                }
-             OutputBits(output,abs(temp),(fNumShapeBits-1));
+             OutputBits(output,abs(temp),(AliL3DataCompressor::GetNShapeBits()-1));
              
              temp = (Int_t)cluster.fDSigmaZ2;
              if(temp<0)
                OutputBit(output,0);
              else
                OutputBit(output,1);
-             power = 1<<(fNumShapeBits-1);
+             power = 1<<(AliL3DataCompressor::GetNShapeBits()-1);
              if(abs(temp) >= power)
                {
                  shapeo++;
                  temp=power - 1;
                }
-             OutputBits(output,abs(temp),(fNumShapeBits-1));
+             OutputBits(output,abs(temp),(AliL3DataCompressor::GetNShapeBits()-1));
            }
+         
+         clustercount++;
        }
     }
   
@@ -281,28 +325,29 @@ void AliL3Compress::CompressFile()
          <<"Pad "<<pado<<endl
          <<"Time "<<timeo<<endl
          <<"Charge "<<chargeo<<endl
-         <<"Shape "<<shapeo<<endl;
+         <<"Shape "<<shapeo<<endl<<endl;
     }
+  return kTRUE;
 }
 
-void AliL3Compress::ExpandFile()
+Bool_t AliL3Compress::ExpandFile()
 {
-  if(fNumTimeBits==0)
-    {
-      cerr<<"AliL3Compress::ExpandFile() : Bitnumbers not set"<<endl;
-      return;
-    }
-  
   Char_t fname[100];
-  sprintf(fname,"%s/comp/tracks_c_%d_%d.raw",fPath,fSlice,fPatch);
+  if(fEvent<0)
+    sprintf(fname,"%s/comp/tracks_c_%d_%d.raw",fPath,fSlice,fPatch);
+  else
+    sprintf(fname,"%s/comp/tracks_c_%d_%d_%d.raw",fPath,fEvent,fSlice,fPatch);
   BIT_FILE *input = OpenInputBitFile(fname);
   
-  sprintf(fname,"%s/comp/tracks_u_%d_%d.raw",fPath,fSlice,fPatch);
+  if(fEvent<0)
+    sprintf(fname,"%s/comp/tracks_u_%d_%d.raw",fPath,fSlice,fPatch);
+  else
+    sprintf(fname,"%s/comp/tracks_u_%d_%d_%d.raw",fPath,fEvent,fSlice,fPatch);
   FILE *output = fopen(fname,"w");
   if(!output)
     {
       cerr<<"AliL3Compress::ExpandFile() : Error opening file: "<<fname<<endl;
-      return;
+      return kFALSE;
     }
 
   AliL3TrackModel trackmodel;
@@ -319,7 +364,8 @@ void AliL3Compress::ExpandFile()
       fwrite(&trackmodel,sizeof(AliL3TrackModel),1,output);
 
       memset(clusters,0,AliL3Transform::GetNRows(fPatch)*sizeof(AliL3ClusterModel));
-      for(Int_t i=0; i<AliL3Transform::GetNRows(fPatch); i++)
+      Int_t origslice=-1,clustercount=0;
+      for(Int_t i=0; i<trackmodel.fNClusters; i++)
        {
          Int_t temp,sign;
          
@@ -332,39 +378,60 @@ void AliL3Compress::ExpandFile()
            }
          clusters[i].fPresent=kTRUE;
          
+         //Read slice information
+         if(clustercount==0)
+           {
+             temp = InputBits(input,6);
+             clusters[i].fSlice = temp;
+             origslice = temp;
+           }
+         else
+           {
+             temp = InputBit(input);
+             if(!temp)//no change
+               clusters[i].fSlice = origslice;
+             else
+               {
+                 temp = InputBits(input,6);//read new slice
+                 clusters[i].fSlice = temp;
+                 origslice = temp;//store new slice
+               }
+           }
+         
          //Read time information:
          sign=InputBit(input);
-         temp = InputBits(input,(fNumTimeBits-1));
+         temp = InputBits(input,(AliL3DataCompressor::GetNTimeBits()-1));
          if(!sign)
            temp*=-1;
          clusters[i].fDTime = temp;
          
          //Read pad information:
          sign=InputBit(input);
-         temp = InputBits(input,(fNumPadBits-1));
+         temp = InputBits(input,(AliL3DataCompressor::GetNPadBits()-1));
          if(!sign)
            temp*=-1;
          clusters[i].fDPad = temp;
          
          //Read charge information:
-         temp=InputBits(input,(fNumChargeBits));
+         temp=InputBits(input,(AliL3DataCompressor::GetNChargeBits()));
          clusters[i].fDCharge = temp;
          
          if(fWriteShape)
            {
              //Read shape information:
              sign = InputBit(input);
-             temp = InputBits(input,(fNumShapeBits-1));
+             temp = InputBits(input,(AliL3DataCompressor::GetNShapeBits()-1));
              if(!sign)
                temp*=-1;
              clusters[i].fDSigmaY2 = temp;
              
              sign = InputBit(input);
-             temp = InputBits(input,(fNumShapeBits-1));
+             temp = InputBits(input,(AliL3DataCompressor::GetNShapeBits()-1));
              if(!sign)
                temp*=-1;
              clusters[i].fDSigmaZ2 = temp;
            }
+         clustercount++;
        }
       count++;
       fwrite(clusters,(trackmodel.fNClusters)*sizeof(AliL3ClusterModel),1,output);
@@ -374,391 +441,58 @@ void AliL3Compress::ExpandFile()
   delete [] clusters;
   fclose(output);
   CloseInputBitFile(input);
+  return kTRUE;
 }
 
-void AliL3Compress::CreateDigitArray(Int_t maxnumber)
-{
-  fNUsed=0;
-  fNDigits = 0;
-  fMaxDigits=maxnumber;
-  if(fDigits) delete [] fDigits;
-  fDigits = new AliL3RandomDigitData[maxnumber];
-  if(fDPt) delete [] fDPt;
-  fDPt = new AliL3RandomDigitData*[maxnumber];
-}
-
-void AliL3Compress::RestoreData(Char_t which)
+void AliL3Compress::PrintCompRatio(ofstream *outfile)
 {
-  //Restore the data.
-  //which == u : restore compressed data
-  //which == m : restore uncompressed data
-  
-  if(!fWriteShape)
-    {
-      cerr<<"AliL3Compress::RestoreData : Not implemented without shape info "<<endl;
-      return;
-    }
-
-  ReadFile(which);
-  
-  CreateDigitArray(10000000);
-  
-  Float_t pad,time,sigmaY2,sigmaZ2;
-  Int_t charge,npads;
-  for(Int_t j=AliL3Transform::GetFirstRow(fPatch); j<=AliL3Transform::GetLastRow(fPatch); j++)
-    {
-      cout<<"Building clusters on row "<<j<<endl;
-      for(Int_t i=0; i<fTracks->GetNTracks(); i++)
-       {
-         AliL3ModelTrack *track = (AliL3ModelTrack*)fTracks->GetCheckedTrack(i);
-         if(!track) continue;
-         if(!track->GetPad(j,pad) || 
-            !track->GetTime(j,time) || 
-            !track->GetClusterCharge(j,charge) ||
-            !track->GetXYWidth(j,sigmaY2) || 
-            !track->GetZWidth(j,sigmaZ2))
-           continue;
-         npads = track->GetNPads(j);
-         CreateDigits(j,npads,pad,time,charge,sigmaY2,sigmaZ2);
-       }
-    }
-  
-  QSort(fDPt,0,fNDigits);
-}
-
-void AliL3Compress::PrintDigits(Int_t padrow)
-{
-  Int_t pad,time,charge,row;
-  for(Int_t i=0; i<fNDigits; i++)
-    {
-      row = fDPt[i]->fRow;
-      if(padrow > 0)
-       if(row != padrow) continue;
-      pad = fDPt[i]->fPad;
-      time = fDPt[i]->fTime;
-      charge = fDPt[i]->fCharge;
-      if(i>0 && row != fDPt[i-1]->fRow)
-       cout<<"---Padrow "<<row<<"---"<<endl;
-      cout<<"Padrow "<<row<<" Pad "<<pad<<" time "<<time<<" charge "<<charge<<endl;
-    }
-}
-
-void AliL3Compress::WriteRestoredData()
-{
-    Char_t fname[100];
-  
-  //Get the remaining raw data array:
   AliL3MemHandler *mem = new AliL3MemHandler();
-  sprintf(fname,"%s/comp/remains_%d_%d.raw",fPath,fSlice,fPatch);
-  mem->SetBinaryInput(fname);
-  UInt_t numdigits;
-  AliL3DigitRowData *origRow = mem->CompBinary2Memory(numdigits);
-  mem->CloseBinaryInput();
-  
-  //Allocate memory for the merged data:
-  UInt_t size = mem->GetAllocatedSize() + fNDigits*sizeof(AliL3DigitData);
-  cout<<"Allocating "<<size<<" bytes for merged data array "<<endl;
-  Byte_t *data = new Byte_t[size];
-  memset(data,0,size);
-  AliL3DigitRowData *tempRow = (AliL3DigitRowData*)data;
-
-  Int_t ndigits,action,charge;
-  UShort_t pad,time;
-      
-  UInt_t digit_counter;
-  Int_t row_counter=0;
-  for(Int_t i=AliL3Transform::GetFirstRow(fPatch); i<=AliL3Transform::GetLastRow(fPatch); i++)
-    {
-      tempRow->fRow = i;
-      ndigits=0;
-      AliL3DigitData *origDig = origRow->fDigitData;
-      AliL3DigitData *tempDig = tempRow->fDigitData;
-      if((Int_t)origRow->fRow != i)
-       cerr<<"AliL3Compress::WriteRestoredData() : Mismatching row numbering "<<(Int_t)origRow->fRow<<" "<<i<<endl;
-
-      //cout<<"Writing row "<<i<<" with "<<(Int_t)origRow->fNDigit<<" old digits"<<endl;
-      digit_counter=0;
-      
-      while(1)
-       {
-         while(digit_counter < origRow->fNDigit)
-           {
-             pad = origDig[digit_counter].fPad;
-             time = origDig[digit_counter].fTime;
-             charge = origDig[digit_counter].fCharge;
-             digit_counter++;
-             while( (action=ComparePoints(i,pad,time)) == 1)
-               {
-                 tempDig[ndigits].fPad = fDPt[fNUsed]->fPad;
-                 tempDig[ndigits].fTime = fDPt[fNUsed]->fTime;
-                 tempDig[ndigits].fCharge = fDPt[fNUsed]->fCharge;
-                 ndigits++;
-                 fNUsed++;
-
-               }
-             if(action == 0)
-               {
-                 tempDig[ndigits].fPad = pad;
-                 tempDig[ndigits].fTime = time;
-                 tempDig[ndigits].fCharge = charge;
-                 ndigits++;
-               }
-           }
-         
-         if(fNUsed >= fNDigits) 
-           {
-             //cerr<<"AliL3Compress::WriteRestoredData() : Array out of range : "<<fNUsed<<" "<<fNDigits<<endl;
-             break;
-           }
-         if(fDPt[fNUsed]->fRow != i) //we are on a new row
-           break;
-         tempDig[ndigits].fPad = fDPt[fNUsed]->fPad;
-         tempDig[ndigits].fTime = fDPt[fNUsed]->fTime;
-         tempDig[ndigits].fCharge = fDPt[fNUsed]->fCharge;
-         ndigits++;
-         fNUsed++;
-       }
-      //cout<<"Writing "<<ndigits<<" digits on row "<<i<<endl;
-      if(ndigits > 4)
-       {
-         row_counter++;
-       }
-      tempRow->fNDigit = ndigits;
-      Int_t size = sizeof(AliL3DigitData)*tempRow->fNDigit + sizeof(AliL3DigitRowData);
-      Byte_t *byte_pt = (Byte_t*)tempRow;
-      byte_pt += size;
-      tempRow = (AliL3DigitRowData*)byte_pt;
-      mem->UpdateRowPointer(origRow);
-    }
-  
-  if(row_counter != AliL3Transform::GetNRows(fPatch))
-    cerr<<"AliL3Compress::WriteRestoredData() : Written rows: "<<row_counter<<" total rows "<<AliL3Transform::GetNRows(fPatch)<<endl;
-  
-  mem->Free();  
-  sprintf(fname,"%s/comp/restored_%d_%d.raw",fPath,fSlice,fPatch);
-  mem->SetBinaryOutput(fname);
-  mem->Memory2CompBinary((UInt_t)AliL3Transform::GetNRows(fPatch),(AliL3DigitRowData*)data);
-  mem->CloseBinaryOutput();
-  
-  delete [] data;
-  delete mem;
-  
-}
-
-void AliL3Compress::CreateDigits(Int_t row,Int_t npads,Float_t pad,Float_t time,Int_t charge,Float_t sigmaY2,Float_t sigmaZ2)
-{
-  //Create raw data out of the cluster.
-    
-  if(npads == 1)//If there was only 1 pad, the xywidth is set to zero.
-    sigmaY2 = 0;
-  
-  if(sigmaY2 < 0 || sigmaZ2 <= 0)
+  Char_t fname[1024];
+  UInt_t remain_size=0,digit_size=0;
+  for(Int_t i=0; i<36; i++)
     {
-      cerr<<"AliL3Compress::CreateDigits() : Wrong sigmas : "<<sigmaY2<<" "<<sigmaZ2;
-      cerr<<" on row "<<row<<" pad "<<pad<<" time "<<time<<endl;
-      return;
+      if(fEvent<0)
+       sprintf(fname,"%s/comp/remains_%d_%d.raw",fPath,i,-1);
+      else
+       sprintf(fname,"%s/comp/remains_%d_%d_%d.raw",fPath,fEvent,i,-1);
+      mem->SetBinaryInput(fname);
+      remain_size += mem->GetFileSize();
+      mem->CloseBinaryInput();
+
+      sprintf(fname,"%s/binaries/digits_c8_%d_%d_%d.raw",fPath,fEvent,i,-1);
+      mem->SetBinaryInput(fname);
+      digit_size += mem->GetFileSize();
+      mem->CloseBinaryInput();
     }
   
-  TRandom *random = new TRandom();
   
-  Int_t entries=2000;
-  TH1F *hist1 = new TH1F("hist1","",AliL3Transform::GetNPads(row),0,AliL3Transform::GetNPads(row)-1);
-  TH1F *hist2 = new TH1F("hist2","",AliL3Transform::GetNTimeBins(),0,AliL3Transform::GetNTimeBins()-1);
-  TH2F *hist3 = new TH2F("hist3","",AliL3Transform::GetNPads(row),0,AliL3Transform::GetNPads(row)-1,AliL3Transform::GetNTimeBins(),0,AliL3Transform::GetNTimeBins()-1);
-
-
-  
-  //Create the distributions in pad and time:
-  for(Int_t i=0; i<entries; i++)
-    {
-      hist1->Fill(random->Gaus(pad,sqrt(sigmaY2)));
-      hist2->Fill(random->Gaus(time,sqrt(sigmaZ2)));
-    }
-    
-  //Create the cluster:
-  Int_t bin1,bin2;
-  Double_t content1,content2,dpad,dtime;
-  for(Int_t i=0; i<hist1->GetEntries(); i++)
-    {
-      bin1 = hist1->GetBin(i);
-      content1 = hist1->GetBinContent(bin1);
-      if((Int_t)content1==0) continue;
-      content1 = charge*content1/entries;
-      dpad = hist1->GetBinCenter(bin1);
-      for(Int_t j=0; j<hist2->GetEntries(); j++)
-       {
-         bin2 = hist2->GetBin(j);
-         content2 = hist2->GetBinContent(bin2);
-         if((Int_t)content2==0) continue;
-         content2 = content1*content2/entries;
-         dtime = hist2->GetBinCenter(bin2);
-         hist3->Fill(dpad,dtime,content2);
-       }
-    }
-  
-  Int_t local_dig=0;
-  //Fill it into the digit array:
-  for(Int_t i=0; i<hist3->GetNbinsX(); i++)
-    {
-      for(Int_t j=0; j<hist3->GetNbinsY(); j++)
-       {
-         bin1 = hist3->GetBin(i,j);
-         content1 = hist3->GetBinContent(bin1);
-         if((Int_t)content1 < 3) continue;
-         if(content1 >= 1024)
-           content1 = 1023;
-         if(fNDigits >= fMaxDigits)
-           {
-             cerr<<"AliL3Compress::CreateDigits() : Array index out of range : "<<fNDigits<<endl;
-             return;
-           }
-         fDigits[fNDigits].fCharge=(Int_t)content1;
-         fDigits[fNDigits].fRow = row;
-         fDigits[fNDigits].fPad = (Int_t)hist3->GetXaxis()->GetBinCenter(i);
-         fDigits[fNDigits].fTime = (Int_t)hist3->GetYaxis()->GetBinCenter(j);
-         fDPt[fNDigits] = &fDigits[fNDigits];
-         fNDigits++;
-         local_dig++;
-       }
-    }
-  //if(local_dig < 5)
-  //  cout<<"Small cluster "<<local_dig<<" pad "<<(Int_t)fDigits[fNDigits-1].fPad<<" time "<<(Int_t)fDigits[fNDigits-1].fTime<<endl;
-  
-  delete random;
-  delete hist1;
-  delete hist2;
-  delete hist3;
-}
+  if(fEvent<0)
+    sprintf(fname,"%s/comp/tracks_c_%d_%d.raw",fPath,fSlice,fPatch);
+  else
+    sprintf(fname,"%s/comp/tracks_c_%d_%d_%d.raw",fPath,fEvent,fSlice,fPatch);
 
-void AliL3Compress::PrintCompRatio(FILE *outfile)
-{
-  Char_t fname[100];
-  sprintf(fname,"%s/comp/remains_%d_%d.raw",fPath,fSlice,fPatch);
-  AliL3MemHandler *mem = new AliL3MemHandler();
-  if(!mem->SetBinaryInput(fname))
-    {
-      cerr<<"AliL3Compress::PrintCompRatio(): Error opening file: "<<fname<<endl;
-      return;
-    } 
-  UInt_t ndigits;
-  AliL3DigitRowData *rowPt = (AliL3DigitRowData*)mem->CompBinary2Memory(ndigits);
+  mem->SetBinaryInput(fname);
+  UInt_t compress_size = mem->GetFileSize();
   mem->CloseBinaryInput();
-
-  Int_t digit_counter=0;
-  for(Int_t i=AliL3Transform::GetFirstRow(fPatch); i<=AliL3Transform::GetLastRow(fPatch); i++)
-    {
-      digit_counter += rowPt->fNDigit;
-      mem->UpdateRowPointer(rowPt);
-    }
-  delete mem;
   
-  sprintf(fname,"%s/comp/tracks_c_%d_%d.raw",fPath,fSlice,fPatch);
-  FILE *file1 = fopen(fname,"r");
-  if(!file1)
+  if(digit_size==0)
     {
-      cerr<<"AliL3Compress::PrintCompRatio(): Error opening file: "<<fname<<endl;
-      return;
+      cerr<<"AliL3Compress::PrintCompRatio : Zero digit size "<<endl;
+      exit(5);
     }
-  fseek(file1,0,SEEK_END);
-  UInt_t filesize1 = (UInt_t)ftell(file1);
-  fclose(file1);
-  
-  sprintf(fname,"%s/digits_%d_%d.raw",fPath,fSlice,fPatch);
-  FILE *file2 = fopen(fname,"r");
-  if(!file2)
-    {
-      cerr<<"AliL3Compress::PrintCompRatio(): Error opening file: "<<fname<<endl;
-      return;
-    }
-  fseek(file2,0,SEEK_END);
-  UInt_t filesize2 = (UInt_t)ftell(file2);
-  fclose(file2);
   
+  Float_t compratio = (Float_t)(compress_size + remain_size)/(Float_t)digit_size;
   if(outfile)
-    fprintf(outfile,"%d %d %d %d %f\n",fPatch,filesize2,filesize1,digit_counter,(Float_t)(filesize1 + (10*digit_counter)/8)/(Float_t)(filesize2));
-  else
     {
-      cout<<"----------------------"<<endl;
-      cout<<"Original file size   : "<<filesize2<<endl;
-      cout<<"Compressed file size : "<<filesize1<<endl;
-      cout<<"Remaining digits     : "<<digit_counter<<endl;
-      cout<<"Compression ratio    : "<<(Float_t)(filesize1 + (10*digit_counter)/8)/(Float_t)(filesize2)<<endl;
+      ofstream &out = *outfile;
+      out<<compress_size<<' '<<remain_size<<' '<<digit_size<<endl;
     }
-}
 
-void AliL3Compress::QSort(AliL3RandomDigitData **a, Int_t first, Int_t last)
-{
-  
-  // Sort array of AliL3RandomDigitData pointers using a quicksort algorithm.
-  // Uses CompareDigits() to compare objects.
-  // Thanks to Root!
-  
-  static AliL3RandomDigitData *tmp;
-  static int i;           // "static" to save stack space
-  int j;
-  
-  while (last - first > 1) {
-    i = first;
-    j = last;
-    for (;;) {
-      while (++i < last && CompareDigits(a[i], a[first]) < 0)
-       ;
-      while (--j > first && CompareDigits(a[j], a[first]) > 0)
-       ;
-      if (i >= j)
-       break;
-      
-      tmp  = a[i];
-      a[i] = a[j];
-      a[j] = tmp;
-    }
-    if (j == first) {
-      ++first;
-      continue;
-    }
-    tmp = a[first];
-    a[first] = a[j];
-    a[j] = tmp;
-    if (j - first < last - (j + 1)) {
-      QSort(a, first, j);
-      first = j + 1;   // QSort(j + 1, last);
-    } else {
-      QSort(a, j + 1, last);
-      last = j;        // QSort(first, j);
-    }
-  }
-}
-
-void AliL3Compress::WriteRootFile(Char_t *newrootfile,Char_t *digitfile)
-{
-#ifdef use_aliroot
-  Char_t fname[100];
-  AliL3MemHandler *mem = new AliL3MemHandler();
-  sprintf(fname,"%s/comp/remains_%d_%d.raw",fPath,fSlice,fPatch);
-  mem->Init(fSlice,fPatch);
-  mem->SetBinaryInput(fname);
-  UInt_t ndigits;
-  AliL3DigitRowData *rowPt = (AliL3DigitRowData*)mem->CompBinary2Memory(ndigits);
-  mem->CloseBinaryInput();
-  
-  if(!digitfile)
-    sprintf(fname,"%s/digitfile.root",fPath);
-  else
-    sprintf(fname,"%s",digitfile);
-
-  AliL3FileHandler *file = new AliL3FileHandler();
-  if(!file->SetAliInput(fname))
-    {
-      cerr<<"AliL3Compress::WriteRootFile() : Error opening file: "<<fname<<endl;
-      return;
-    }
-
-  file->Init(fSlice,fPatch);
-  file->AliDigits2RootFile(rowPt,newrootfile);
-  file->CloseAliInput();
-
-  delete mem;
-  delete file;
-#endif
-  return;
+  cout<<"=========================================="<<endl;
+  cout<<"Original digits size : "<<digit_size/1000<<" kByte ( 100 % )"<<endl;
+  cout<<"Compressed file size : "<<compress_size/1000<<" kByte ( "<<(Float_t)compress_size*100/(Float_t)digit_size<<" % )"<<endl;
+  cout<<"Remainig file size   : "<<remain_size/1000<<" kByte ( "<<(Float_t)remain_size*100/(Float_t)digit_size<<" % )"<<endl;
+  cout<<"---------------------- "<<endl;
+  cout<<"Compression ratio    : "<<compratio*100<<" %"<<endl;
+  cout<<"=========================================="<<endl;
 }
index 172b4be..be67608 100644 (file)
@@ -1,52 +1,31 @@
+// @(#) $Id$
+
 #ifndef AliL3_Compress
 #define AliL3_Compress
 
-#include "AliL3RootTypes.h"
-#include "AliL3Models.h"
-#include "AliL3DigitData.h"
-
 class AliL3TrackArray;
 
 class AliL3Compress {
   
  private:
   AliL3TrackArray *fTracks; //!
-  AliL3RandomDigitData *fDigits; //!
-  AliL3RandomDigitData **fDPt; //!
-  Int_t fNDigits;
-  Int_t fNUsed;
-  Int_t fMaxDigits;
-  
-  Int_t fNumPadBits;
-  Int_t fNumTimeBits;
-  Int_t fNumChargeBits;
-  Int_t fNumShapeBits;
+
   Int_t fSlice;
   Int_t fPatch;
   Char_t fPath[100];
   Bool_t fWriteShape;
-  
-  void CreateDigitArray(Int_t maxnumber);
-  void CreateDigits(Int_t row,Int_t npads,Float_t pad,Float_t time,Int_t charge,Float_t ywidth,Float_t zwidth);
-  void QSort(AliL3RandomDigitData **a, Int_t first, Int_t last);
-  Int_t ComparePoints(Int_t row,UShort_t pad,UShort_t time);
-  Int_t CompareDigits(AliL3RandomDigitData *a,AliL3RandomDigitData *b);
+  Int_t fEvent;
 
  public:
   AliL3Compress();
-  AliL3Compress(Int_t slice,Int_t patch,Char_t *path="./",Bool_t writeshape=kFALSE);
+  AliL3Compress(Int_t slice,Int_t patch,Char_t *path="./",Bool_t writeshape=kFALSE,Int_t event=-1);
   virtual ~AliL3Compress();
   
-  void SetBitNumbers(Int_t pad,Int_t time,Int_t charge,Int_t shape);
-  void WriteFile(AliL3TrackArray *tracks);
-  void ReadFile(Char_t which);
-  void CompressFile();
-  void ExpandFile();
-  void RestoreData(Char_t which='u');
-  void WriteRestoredData();
-  void WriteRootFile(Char_t *newrootfile,Char_t *digitfile=0);
-  void PrintDigits(Int_t padrow=-1);
-  void PrintCompRatio(FILE *outfile=0);
+  Bool_t WriteFile(AliL3TrackArray *tracks,Char_t *filename=0);
+  Bool_t ReadFile(Char_t which,Char_t *filename=0);
+  Bool_t CompressFile();
+  Bool_t ExpandFile();
+  void PrintCompRatio(ofstream *outfile=0);
   
   AliL3TrackArray *GetTracks() {return fTracks;}
   
@@ -54,32 +33,4 @@ class AliL3Compress {
 
 };
 
-inline Int_t  AliL3Compress::ComparePoints(Int_t row,UShort_t pad,UShort_t time)
-{
-  if(fNUsed >= fNDigits) return 0;
-  
-  if(fDPt[fNUsed]->fRow != row) return 0;
-  
-  
-  if(fDPt[fNUsed]->fPad < pad) return 1;
-  if(fDPt[fNUsed]->fPad == pad && fDPt[fNUsed]->fTime < time) return 1;
-  
-  //if(fDPt[fNUsed]->fPad == pad && fDPt[fNUsed]->fTime == time) return 2;
-  
-  return 0;
-
-}
-
-inline Int_t AliL3Compress::CompareDigits(AliL3RandomDigitData *a,AliL3RandomDigitData *b)
-{
-  if(a->fRow < b->fRow) return -1;
-    
-  if(a->fPad==b->fPad && a->fTime == b->fTime && a->fRow == b->fRow) return 0;
-  
-  if(a->fPad<b->fPad && a->fRow == b->fRow) return -1;
-  if(a->fPad==b->fPad && a->fTime<b->fTime && a->fRow == b->fRow) return -1;
-  
-  return 1;
-}
-
 #endif
index 4da4017..372074c 100644 (file)
@@ -1,19 +1,27 @@
-//$Id$
+// @(#) $Id$
 
 // Author: Anders Vestbo <mailto:vestbo@fi.uib.no>
-//*-- Copyright &copy ASV
+//*-- Copyright &copy ALICE HLT Group
 
 #include "AliL3StandardIncludes.h"
-#include "AliL3DataCompressor.h"
-#include "AliL3FileHandler.h"
+
+#include "AliL3Logging.h"
+#include "AliL3RootTypes.h"
 #include "AliL3Transform.h"
+#include "AliL3MemHandler.h"
 #include "AliL3SpacePointData.h"
 #include "AliL3Compress.h"
 #include "AliL3TrackArray.h"
 #include "AliL3ModelTrack.h"
-#include "AliL3Modeller.h"
 #include "AliL3Benchmark.h"
+#include "AliL3ClusterFitter.h"
+
+#ifdef use_aliroot
+#include "AliL3FileHandler.h"
 
+#include <AliKalmanTrack.h>
+#include <AliTPCtracker.h>
+#include <AliTPCcluster.h>
 #include <AliTPCParamSR.h>
 #include <AliTPCDigitsArray.h>
 #include <AliTPCClustersArray.h>
 #include <AliTPC.h>
 #include <AliTPCv2.h>
 #include <AliRun.h>
+#endif
 
+#ifdef use_root
 #include <TFile.h>
 #include <TMath.h>
 #include <TDirectory.h>
 #include <TSystem.h>
+#include <TH2F.h>
+#endif
+
+#include "AliL3DataCompressor.h"
+
+#if GCCVERSION == 3
+using namespace std;
+#endif
+
 //_____________________________________________________________
 //
 //  AliL3DataCompression
 
 ClassImp(AliL3DataCompressor)
 
+Int_t AliL3DataCompressor::fNumTimeBits = 12;
+Int_t AliL3DataCompressor::fNumPadBits = 12;
+Int_t AliL3DataCompressor::fNumChargeBits = 14;
+Int_t AliL3DataCompressor::fNumShapeBits = 14;
+Float_t AliL3DataCompressor::fXYResidualStep = 0.03;
+Float_t AliL3DataCompressor::fZResidualStep = 0.05;
+Float_t AliL3DataCompressor::fXYWidthStep = 0.005;
+Float_t AliL3DataCompressor::fZWidthStep = 0.005;
+Int_t AliL3DataCompressor::fClusterCharge = 100;
+
 AliL3DataCompressor::AliL3DataCompressor()
 {
-  fMemHandler=0;
-  fMinSlice=0;
-  fMaxSlice=0;
   fBenchmark=0;
+  fInputTracks=0;
+  fKeepRemaining=kTRUE;
+  fEvent=0;
+  fWriteClusterShape=kFALSE;
+  fOutputFile=0;
+  fCompRatioFile=0;
+  memset(fClusters,0,36*6*sizeof(AliL3SpacePointData*));
 }
 
-AliL3DataCompressor::AliL3DataCompressor(Char_t *path,Int_t minslice,Int_t maxslice)
+AliL3DataCompressor::AliL3DataCompressor(Char_t *path,Bool_t keep,Bool_t writeshape)
 {
-  fMinSlice=minslice;
-  fMaxSlice=maxslice;
   strcpy(fPath,path);
-  fMemHandler = new AliL3FileHandler();
   fBenchmark = new AliL3Benchmark();
+  fInputTracks=0;
+  fKeepRemaining=keep;
+  fWriteClusterShape = writeshape;
+  fEvent=0;
+  fOutputFile=0;
+  memset(fClusters,0,36*6*sizeof(AliL3SpacePointData*));
+#ifdef use_root
+  Char_t name[1024];
+  sprintf(name,"rm -f %s/comp/*",path);//Clean the directory
+  gSystem->Exec(name);
+#endif
+  OpenOutputFile();
 }
 
 AliL3DataCompressor::~AliL3DataCompressor()
 {
-  if(fMemHandler)
-    delete fMemHandler;
+  if(fInputTracks)
+    delete fInputTracks;
   if(fBenchmark)
     delete fBenchmark;
+  if(fClusters)
+    {
+      for(Int_t i=0; i<36; i++)
+       for(Int_t j=0; j<6; j++)
+         if(fClusters[i][j])
+           delete fClusters[i][j];
+    }
+  CloseOutputFile();
 }
 
 void AliL3DataCompressor::DoBench(Char_t *fname)
@@ -68,385 +118,1016 @@ void AliL3DataCompressor::DoBench(Char_t *fname)
   fBenchmark->Analyze(fname);
 }
 
-void AliL3DataCompressor::ProcessData(Char_t *trackpath,Int_t padoverlap,Int_t timeoverlap,Int_t padsearch,Int_t timesearch)
+void AliL3DataCompressor::SetBitNumbers(Int_t pad,Int_t time,Int_t charge,Int_t shape)
+{
+  fNumPadBits = pad;
+  fNumTimeBits = time;
+  fNumChargeBits = charge;
+  fNumShapeBits = shape;
+}
+
+void AliL3DataCompressor::SetResolutions(Float_t xyresidual,Float_t zresidual,Int_t clustercharge,Float_t xywidth,Float_t zwidth)
+{
+  fXYResidualStep = xyresidual;
+  fZResidualStep = zresidual;
+  fXYWidthStep = xywidth;
+  fZWidthStep = zwidth;
+  fClusterCharge = clustercharge;
+}
+
+void AliL3DataCompressor::OpenOutputFile()
 {
-  //Find clusters based on the input tracks, and write them to file.
+#ifndef use_aliroot
+   LOG(AliL3Log::kError,"AliL3DataCompressor::OpenOutputFile","Version")
+     <<"You have to compile with use_aliroot flag in order to use this function"<<ENDLOG;
+#else
+  Char_t filename[1024];
   
-  for(Int_t slice=fMinSlice; slice<=fMaxSlice; slice++)
+  sprintf(filename,"%s/comp/comprates.txt",fPath);
+  fCompRatioFile = new ofstream(filename);
+  
+  if(fOutputFile)
+    if(fOutputFile->IsOpen())
+      fOutputFile->Close();
+
+  sprintf(filename,"%s/alirunfile.root",fPath);
+  TFile *f = TFile::Open(filename);
+  AliTPCParam *param = (AliTPCParam*)f->Get(AliL3Transform::GetParamName());
+  sprintf(filename,"%s/comp/AliTPCclusters.root",fPath);
+  fOutputFile = TFile::Open(filename,"RECREATE");
+  param->Write(param->GetTitle());
+  f->Close();
+#endif
+}
+
+void AliL3DataCompressor::CloseOutputFile()
+{
+  if(fCompRatioFile)
     {
-      for(Int_t patch=0; patch<AliL3Transform::GetNPatches(); patch++)
-       {
-         AliL3Modeller *modeller = new AliL3Modeller();
-
-         modeller->SetOverlap(padoverlap,timeoverlap);
-         modeller->SetSearchRange(padsearch,timesearch);
-         modeller->Init(slice,patch,trackpath,fPath,kTRUE,kTRUE);
-         fBenchmark->Start("Calclulate Crossing");
-         modeller->CalculateCrossingPoints();
-         fBenchmark->Stop("Calclulate Crossing");
-         fBenchmark->Start("Check for overlaps");
-         modeller->CheckForOverlaps();
-         fBenchmark->Stop("Check for overlaps");
-         fBenchmark->Start("Find clusters");
-         modeller->FindClusters();
-         fBenchmark->Stop("Find clusters");
-         modeller->WriteRemaining();
-         
-         AliL3TrackArray *tracks = modeller->GetTracks();
+      fCompRatioFile->close();
+      delete fCompRatioFile;
+    }
+  
+  if(!fOutputFile)
+    return;
+#ifdef use_root
+  if(!fOutputFile->IsOpen())
+    return;
+  fOutputFile->Close();
+#else
+  fclose(fOutputFile);
+#endif
+  fOutputFile=0;
+}
 
-         AliL3Compress *comp = new AliL3Compress(slice,patch,fPath);
+void AliL3DataCompressor::LoadData(Int_t event,Bool_t sp)
+{
+  fSinglePatch=sp;
+  fEvent=event;
+  AliL3MemHandler *clusterfile[36][6];
+  Char_t fname[1024];
+  for(Int_t s=0; s<=35; s++)
+    {
+      for(Int_t p=0; p<6; p++)
+       {
+         if(fClusters[s][p])
+           delete fClusters[s][p];
+         fClusters[s][p] = 0;
+         clusterfile[s][p] = new AliL3MemHandler();
+         if(fSinglePatch)
+           sprintf(fname,"%s/cf/points_%d_%d_%d.raw",fPath,fEvent,s,-1);
+         else
+           sprintf(fname,"%s/cf/points_%d_%d_%d.raw",fPath,fEvent,s,p);
+         clusterfile[s][p]->SetBinaryInput(fname);
          
-         comp->WriteFile(tracks);
+         fClusters[s][p] = (AliL3SpacePointData*)clusterfile[s][p]->Allocate();
+         clusterfile[s][p]->Binary2Memory(fNcl[s][p],fClusters[s][p]);
+         clusterfile[s][p]->CloseBinaryInput();
          
-         delete comp;
-         delete modeller;
+         if(fSinglePatch)
+           break;
        }
     }
   
+  sprintf(fname,"%s/cf/tracks_%d.raw",fPath,fEvent);
+  AliL3MemHandler *tfile = new AliL3MemHandler();
+  tfile->SetBinaryInput(fname);
+  
+  if(fInputTracks)
+    delete fInputTracks;
+  fInputTracks = new AliL3TrackArray();
+  tfile->Binary2TrackArray(fInputTracks);
+  tfile->CloseBinaryInput();
+  delete tfile;
 }
 
-void AliL3DataCompressor::CompressAndExpand(Int_t bitspad,Int_t bitstime,Int_t bitscharge,Int_t bitsshape)
+void AliL3DataCompressor::FillData(Int_t min_hits,Bool_t expand)
 {
-  //Read tracks/clusters from file, compress data and uncompress it. Write compression rates to file.
-  //Input parameters are number of bits to use to code the pad/time/charge/shape residuals.
   
-  Char_t filename[1024];
-  sprintf(filename,"%s/comprates.txt",fPath);
-  FILE *file = fopen(filename,"w");
-  for(Int_t slice=fMinSlice; slice<=fMaxSlice; slice++)
+  //Fill the track data into track and cluster structures, and write to file.
+  //Preparation for compressing it.
+  
+  cout<<"Filling data; "<<fInputTracks->GetNTracks()<<" tracks"<<endl;
+  AliL3TrackArray *comptracks = new AliL3TrackArray("AliL3ModelTrack");
+  fInputTracks->QSort();
+  for(Int_t i=0; i<fInputTracks->GetNTracks(); i++)
     {
-      for(Int_t patch=0; patch < AliL3Transform::GetNPatches(); patch++)
+      AliL3Track *intrack = fInputTracks->GetCheckedTrack(i);
+      if(!intrack) continue;
+
+      if(intrack->GetNHits()<min_hits) break;
+
+      intrack->CalculateHelix();
+      
+      AliL3ModelTrack *outtrack = (AliL3ModelTrack*)comptracks->NextTrack();
+      outtrack->SetNHits(intrack->GetNHits());
+      outtrack->SetRowRange(intrack->GetFirstRow(),intrack->GetLastRow());
+      outtrack->SetFirstPoint(intrack->GetFirstPointX(),intrack->GetFirstPointY(),intrack->GetFirstPointZ());
+      outtrack->SetLastPoint(intrack->GetLastPointX(),intrack->GetLastPointY(),intrack->GetLastPointZ());
+      outtrack->SetPt(intrack->GetPt());
+      outtrack->SetPsi(intrack->GetPsi());
+      outtrack->SetTgl(intrack->GetTgl());
+      outtrack->SetCharge(intrack->GetCharge());
+      outtrack->CalculateHelix();
+      Int_t nhits = intrack->GetNHits();
+      UInt_t *hitids = intrack->GetHitNumbers();
+      Int_t origslice = (hitids[nhits-1]>>25)&0x7f;
+      outtrack->Init(origslice,-1);
+      for(Int_t j=nhits-1; j>=0; j--)
        {
-         AliL3Compress *comp = new AliL3Compress(slice,patch,fPath);
-         comp->SetBitNumbers(bitspad,bitstime,bitscharge,bitsshape);
+         UInt_t id=hitids[j];
+         Int_t slice = (id>>25)&0x7f;
+         Int_t patch = (id>>22)&0x7;
+         UInt_t pos = id&0x3fffff;          
+
+         //UInt_t size;
+         AliL3SpacePointData *points = fClusters[slice][patch];//->GetDataPointer(size);
+         Float_t xyz[3] = {points[pos].fX,points[pos].fY,points[pos].fZ};
+         Int_t padrow = points[pos].fPadRow;
 
-         comp->CompressFile();
-         comp->ExpandFile();
-         comp->PrintCompRatio(file);
+         //Calculate the crossing point between track and padrow
+         Float_t angle = 0; //Perpendicular to padrow in local coordinates
+         AliL3Transform::Local2GlobalAngle(&angle,slice);
+         if(!intrack->CalculateReferencePoint(angle,AliL3Transform::Row2X(padrow)))
+           {
+             cerr<<"AliL3DataCompressor::FillData : Error in crossing point calc on slice "<<slice<<" row "<<padrow<<endl;
+             outtrack->Print(kFALSE);
+             exit(5);
+           }
+         
+         Float_t xyz_cross[3] = {intrack->GetPointX(),intrack->GetPointY(),intrack->GetPointZ()};
+         
+         Int_t sector,row;
+         AliL3Transform::Slice2Sector(slice,padrow,sector,row);
+         AliL3Transform::Global2Raw(xyz_cross,sector,row);
+         AliL3Transform::Global2Raw(xyz,sector,row);
+         
+         outtrack->SetPadHit(padrow,xyz_cross[1]);
+         outtrack->SetTimeHit(padrow,xyz_cross[2]);
+
+         if(fWriteClusterShape)
+           {
+             Float_t angle = intrack->GetCrossingAngle(padrow,slice);
+             outtrack->SetCrossingAngleLUT(padrow,angle);
+             outtrack->CalculateClusterWidths(padrow,kTRUE);
+             Int_t patch = AliL3Transform::GetPatch(padrow);
+             Float_t sigmaY2 = points[pos].fSigmaY2 / pow(AliL3Transform::GetPadPitchWidth(patch),2);
+             Float_t sigmaZ2 = points[pos].fSigmaZ2 / pow(AliL3Transform::GetZWidth(),2);
+             outtrack->SetCluster(padrow,xyz[1],xyz[2],points[pos].fCharge,sigmaY2,sigmaZ2,3);
+           }
+         else
+           outtrack->SetCluster(padrow,xyz[1],xyz[2],points[pos].fCharge,0,0,3);
          
-         delete comp;
+         //IMPORTANT: Set the slice in which cluster is, you need it in AliL3ModelTrack::FillTrack!
+         outtrack->GetClusterModel(padrow)->fSlice=slice;
+         points[pos].fCharge = 0;//Mark this cluster as used.
        }
+      if(!expand)
+       outtrack->SetNClusters(AliL3Transform::GetNRows(-1));
     }
-  fclose(file);
+  
+  if(expand)
+    ExpandTrackData(comptracks);
+  
+  cout<<"Writing "<<comptracks->GetNTracks()<<" tracks to file"<<endl;
+  AliL3Compress *comp = new AliL3Compress(-1,-1,fPath,fWriteClusterShape,fEvent);
+  comp->WriteFile(comptracks);
+  delete comp;
+  delete comptracks;
+  
 }
 
-void AliL3DataCompressor::WriteRemainingDigits()
+void AliL3DataCompressor::ExpandTrackData(AliL3TrackArray *tracks)
 {
-  //Write the remaining digits resulting from ProcessData to a rootfile
-  //which serves as an input to the offline cluster finder.
-  
-  Char_t filename[1024];
-  sprintf(filename,"rm %s/comp/remains.root",fPath);
-  gSystem->Exec(filename);
-  sprintf(filename,"%s/comp/remains.root",fPath);
+  //Loop over tracks and try to assign unused clusters.
+  //Only clusters which are closer than the max. residual are taken.
   
-  cout<<"AliL3DataCompressor::WriteRemainingDigits : Removing old file : "<<filename<<endl;
-  for(Int_t slice=fMinSlice; slice<=fMaxSlice; slice++)
+  cout<<"Expanding "<<tracks->GetNTracks()<<" tracks"<<endl;
+  for(Int_t i=0; i<tracks->GetNTracks(); i++)
     {
-      for(Int_t patch=0; patch<AliL3Transform::GetNPatches(); patch++)
+      AliL3ModelTrack *track = (AliL3ModelTrack*)tracks->GetCheckedTrack(i);
+      if(!track) continue;
+      if(track->GetNHits() == AliL3Transform::GetNRows()) continue;
+      
+      Int_t nhits = track->GetNHits();
+      //cout<<"Expanding track with "<<nhits<<" clusters"<<endl;
+      
+      Int_t last_slice=-1;
+      for(Int_t padrow=AliL3Transform::GetNRows()-1; padrow>=0; padrow--)
        {
-         AliL3Compress *comp = new AliL3Compress(slice,patch,fPath);
-         comp->WriteRootFile(filename);
-         delete comp;
+         if(track->IsPresent(padrow))
+           {
+             last_slice = track->GetClusterModel(padrow)->fSlice;
+             continue;
+           }
+         
+         if(last_slice < 0) //the outer cluster is missing, so skip it - it will be written anyhow.
+           continue;
+         
+         //Check the slice of the next padrow:
+         Int_t next_padrow = padrow-1;
+         Int_t next_slice = -1;
+         while(next_padrow >=0)
+           {
+             if(track->IsPresent(next_padrow))
+               {
+                 next_slice = track->GetClusterModel(next_padrow)->fSlice;
+                 break;
+               }
+             next_padrow--;
+           }
+         if(next_slice>=0)
+           if(next_slice != last_slice)//The track crosses a slice boundary here
+             continue;
+         
+         //UInt_t size;
+         AliL3SpacePointData *points = fClusters[last_slice][0];//->GetDataPointer(size);
+         
+         Float_t angle = 0;
+         AliL3Transform::Local2GlobalAngle(&angle,last_slice);
+         if(!track->CalculateReferencePoint(angle,AliL3Transform::Row2X(padrow)))
+           continue;
+         Float_t xyz_cross[3] = {track->GetPointX(),track->GetPointY(),track->GetPointZ()};
+         AliL3Transform::Global2Local(xyz_cross,last_slice,kTRUE);
+         Float_t mindist = 123456789;
+         AliL3SpacePointData *closest=0;
+         for(UInt_t j=0; j<fNcl[last_slice][0]; j++)
+           {
+             if(points[j].fCharge == 0) continue;// || points[j].fPadRow != padrow) continue;
+             if(points[j].fPadRow < padrow) continue;
+             if(points[j].fPadRow > padrow) break;
+             Float_t xyz[3] = {points[j].fX,points[j].fY,points[j].fZ};
+             AliL3Transform::Global2Local(xyz,last_slice,kTRUE);
+             
+             //Check for overflow:
+             Int_t temp = (Int_t)rint((xyz_cross[1]-xyz[1])/GetXYResidualStep());
+             if( abs(temp) > 1<<(GetNPadBits()-1))
+               continue;
+             
+             temp = (Int_t)rint((xyz_cross[2]-xyz[2])/GetZResidualStep());
+             if( abs(temp) > 1<<(GetNTimeBits()-1))
+               continue;
+             
+             Float_t dist = sqrt( pow(xyz_cross[1]-xyz[1],2) + pow(xyz_cross[2]-xyz[2],2) );
+             if(dist < mindist)
+               {
+                 closest = &points[j];
+                 mindist = dist;
+               }
+           }
+         if(closest) //there was a cluster assigned
+           {
+             Int_t sector,row;
+             Float_t xyz[3] = {closest->fX,closest->fY,closest->fZ};
+             AliL3Transform::Slice2Sector(last_slice,padrow,sector,row);
+             AliL3Transform::Local2Raw(xyz_cross,sector,row);
+             AliL3Transform::Global2Raw(xyz,sector,row);
+             
+             track->SetPadHit(padrow,xyz_cross[1]);
+             track->SetTimeHit(padrow,xyz_cross[2]);
+             
+             if(fWriteClusterShape)
+               {
+                 Float_t angle = track->GetCrossingAngle(padrow,last_slice);
+                 track->SetCrossingAngleLUT(padrow,angle);
+                 track->CalculateClusterWidths(padrow,kTRUE);
+                 Int_t patch = AliL3Transform::GetPatch(padrow);
+                 Float_t sigmaY2 = closest->fSigmaY2 / pow(AliL3Transform::GetPadPitchWidth(patch),2);
+                 Float_t sigmaZ2 = closest->fSigmaZ2 / pow(AliL3Transform::GetZWidth(),2);
+                 track->SetCluster(padrow,xyz[1],xyz[2],closest->fCharge,sigmaY2,sigmaZ2,3);
+               }
+             else
+               track->SetCluster(padrow,xyz[1],xyz[2],closest->fCharge,0,0,3);
+             nhits++;
+             
+             //IMPORTANT: Set the slice in which cluster is, you need it in AliL3ModelTrack::FillTrack!
+             track->GetClusterModel(padrow)->fSlice=last_slice;
+             closest->fCharge = 0;//Mark this cluster as used.
+           }
        }
+      track->SetNClusters(AliL3Transform::GetNRows());
+      //cout<<"Track was assigned "<<nhits<<" clusters"<<endl;
     }
   
 }
 
-void AliL3DataCompressor::FindOfflineClusters(Bool_t remains)
+void AliL3DataCompressor::WriteRemaining(Bool_t select)
 {
-  //Code taken from macro AliTPCFindClusters.
-  //remains = kTRUE : Find remaining clusters after comression
-  //remains = kFALSE : Find offline clusters before compression.
+  //Write remaining clusters (not assigned to any tracks) to file
 
-  Char_t fname[1024];
-  if(!remains)
-    sprintf(fname,"%s/AliTPCclusters.root",fPath);
-  else
-    sprintf(fname,"%s/comp/AliTPCclusters_remains.root",fPath);
   
-  TFile *out=TFile::Open(fname,"RECREATE");
-    
-  sprintf(fname,"%s/alirunfile.root",fPath);
-  TFile *in = TFile::Open(fname);
+  if(!fKeepRemaining)
+    return;
   
-  if (!(gAlice=(AliRun*)in->Get("gAlice"))) 
+  if(select)
+    SelectRemainingClusters();
+  
+  Char_t filename[1024];
+  
+  if(!fSinglePatch)
     {
-      cerr<<"AliL3DataCompressor::FindOfflineClusters : gAlice have not been found on file "<<fname<<endl;
+      cerr<<"AliL3Compressor::WriteRemaining : You have to modify this function when not running singlepatch"<<endl;
       return;
-   }
-  
-  AliTPC *TPC = (AliTPC*)gAlice->GetDetector("TPC"); 
-  Int_t ver = TPC->IsVersion(); 
-  cerr<<"TPC version "<<ver<<" has been found !\n";
-  
-  AliTPCParamSR *dig=(AliTPCParamSR *)in->Get("75x40_100x60");
-  if(dig){
-    cerr<<"2 pad-length geom hits with 3 pad-lengths geom digits\n";
-    delete dig;
-    dig = new AliTPCParamSR();
-  }
-  else
+    }
+
+  cout<<"Writing remaining clusters "<<endl;
+  Int_t nrows = AliL3Transform::GetNRows();
+  Int_t *npoints = new Int_t[nrows];
+  for(Int_t i=0; i<=35; i++)
     {
-      dig=(AliTPCParamSR *)gDirectory->Get("75x40_100x60_150x60");
+      for(Int_t patch=0; patch < 1; patch++)
+       {
+         sprintf(filename,"%s/comp/remains_%d_%d_%d.raw",fPath,fEvent,i,-1);
+         FILE *outfile = fopen(filename,"w");
+         if(!outfile)
+           {
+             cerr<<"AliL3DataCompressor::WriteRemaining : Cannot open file "<<filename<<endl;
+             exit(5);
+           }
+         //UInt_t dummy;
+         AliL3SpacePointData *points = fClusters[i][patch];//->GetDataPointer(dummy);
+         
+         memset(npoints,0,nrows*sizeof(Int_t));
+         
+         for(UInt_t j=0; j<fNcl[i][patch]; j++)
+           {
+             if(points[j].fCharge == 0) continue; //has been used
+             npoints[points[j].fPadRow]++;
+           }
+         Int_t size =0;
+         Byte_t *data = 0;
+         AliL3RemainingRow *tempPt=0;
+         
+         Int_t last_row = -2;
+         Int_t localcounter=0;
+         
+         for(UInt_t j=0; j<fNcl[i][patch]; j++)
+           {
+             if(points[j].fCharge == 0) continue; //has been used
+             
+             Int_t padrow = points[j].fPadRow;
+             if(padrow != last_row)
+               {
+                 if(last_row != -2)
+                   {
+                     if(!tempPt)
+                       {
+                         cerr<<"AliL3DataCompressor::WriteRemaining : Zero row pointer "<<endl;
+                         exit(5);
+                       }
+                     if(localcounter != tempPt->fNClusters)
+                       {
+                         cerr<<"AliL3DataCompressor::WriteRemaining : Mismatching clustercounter "<<localcounter<<" "
+                             <<(Int_t)tempPt->fNClusters<<endl;
+                         exit(5);
+                       }
+                     //cout<<"Writing row "<<(int)tempPt->fPadRow<<" with "<<(int)tempPt->fNClusters<<" clusters"<<endl;
+                     fwrite(tempPt,size,1,outfile);
+                   }
+                 if(data)
+                   delete [] data;
+                 size = sizeof(AliL3RemainingRow) + npoints[padrow]*sizeof(AliL3RemainingCluster);
+                 data = new Byte_t[size];
+                 tempPt = (AliL3RemainingRow*)data;
+                 
+                 localcounter=0;
+                 tempPt->fPadRow = padrow;
+                 tempPt->fNClusters = npoints[padrow];
+                 last_row = padrow;
+               }
+             if(localcounter >= npoints[padrow])
+               {
+                 cerr<<"AliL3DataCompressor::WriteRemaining : Cluster counter out of range: "
+                     <<localcounter<<" "<<npoints[padrow]<<endl;
+                 exit(5);
+               }
+             
+             Float_t xyz[3] = {points[j].fX,points[j].fY,points[j].fZ};
+             AliL3Transform::Global2Local(xyz,i,kTRUE);
+             
+             tempPt->fClusters[localcounter].fY = xyz[1];
+             tempPt->fClusters[localcounter].fZ = xyz[2];
+             tempPt->fClusters[localcounter].fCharge = points[j].fCharge;
+             tempPt->fClusters[localcounter].fSigmaY2 = points[j].fSigmaY2;
+             tempPt->fClusters[localcounter].fSigmaZ2 = points[j].fSigmaZ2;
+             localcounter++;
+           }
+         //Write the last row:
+         //cout<<"Writing row "<<(int)tempPt->fPadRow<<" with "<<(int)tempPt->fNClusters<<" clusters"<<endl;
+         fwrite(tempPt,size,1,outfile);
+         if(data)
+           delete [] data;
+         fclose(outfile);
+       }
     }
-  if (!dig) {cerr<<"TPC parameters have not been found !\n"; return;}
-  
-  if(!remains)
-    sprintf(fname,"%s/digitfile.root",fPath);
-  else
-    sprintf(fname,"%s/comp/remains.root",fPath);
-  TFile *dfile = TFile::Open(fname);
-  
-  cerr<<"Looking for clusters...\n";
-  AliTPCv2 tpc; 
-  tpc.SetParam(dig); 
-  dfile->cd();  
-  
-  tpc.Digits2Clusters(out,0); //event 0
+  delete [] npoints;
+}
+
+void AliL3DataCompressor::SelectRemainingClusters()
+{
+  //Select which remaining clusters to write in addition to the compressed data.
+
+  cout<<"Cleaning up clusters"<<endl;
+  Int_t nrows = AliL3Transform::GetNRows();
+  Int_t gap=(Int_t)(0.125*nrows), shift=(Int_t)(0.5*gap);
   
+  for(Int_t slice=0; slice<36; slice++)
+    {
+      //UInt_t dummy;
+      AliL3SpacePointData *points = fClusters[slice][0];//->GetDataPointer(dummy);
+      for(UInt_t i=0; i<fNcl[slice][0]; i++)
+       {
+         if(points[i].fCharge == 0) continue; //Already removed
+         Int_t padrow = (Int_t)points[i].fPadRow;
+         
+         Float_t xyz[3] = {points[i].fX,points[i].fY,points[i].fZ};
+         Int_t sector,row;
+         AliL3Transform::Slice2Sector(slice,padrow,sector,row);
+         AliL3Transform::Global2Raw(xyz,sector,row);
+         
+         if(padrow >= nrows-1-gap-shift) continue;
+         //if(padrow >= nrows-1-shift) continue;
+
+         //Save the clusters at the borders:
+         if(xyz[1] < 3 || xyz[1] >= AliL3Transform::GetNPads(padrow)-4)
+           continue;
+
+         //Save clusters on padrows used for offline seeding:
+         if(padrow == nrows - 1 || padrow == nrows - 1 - gap ||                 //First seeding
+            padrow == nrows - 1 - shift || padrow == nrows - 1 - gap - shift)   //Second seeding
+           continue;
+         
+         //Cluster did not meet any of the above criteria, so disregard it:
+         points[i].fCharge = 0;
+       }
+    }
   
-  delete gAlice; gAlice=0;
-  out->Close();
-  in->Close();
 }
 
+void AliL3DataCompressor::CompressAndExpand()
+{
+  //Read tracks/clusters from file, compress data and uncompress it. Write compression rates to file.
+  cout<<"Compressing and expanding data"<<endl;
+  AliL3Compress *comp = new AliL3Compress(-1,-1,fPath,fWriteClusterShape,fEvent);
+  comp->CompressFile();
+  comp->ExpandFile();
+  comp->PrintCompRatio(fCompRatioFile);
+  delete comp;
+}
+
+
 void AliL3DataCompressor::RestoreData()
 {
   //Restore the uncompressed data together with the remaining clusters,
   //and write to a final cluster file which serves as an input to the
-  //final offline tracker. 
+  //final offline tracker.
   
-  Char_t filename[1024];
+#ifndef use_aliroot
+   LOG(AliL3Log::kError,"AliL3DataCompressor::RestoreData","Version")
+     <<"You have to compile with use_aliroot flag in order to use this function"<<ENDLOG;
+#else
+
+  cout<<"Restoring data"<<endl;
+  
+  const Int_t maxpoints=500000;
+  TempCluster **clusters = new TempCluster*[36];
+  Int_t *ncl = new Int_t[36];
+  for(Int_t i=0; i<36; i++)
+    {
+      ncl[i]=0;
+      clusters[i] = new TempCluster[maxpoints];
+    }
+  
+  ReadUncompressedData(clusters,ncl,maxpoints);
   
-  sprintf(filename,"%s/comp/AliTPCclusters_remains.root",fPath);
-  if(!fMemHandler->SetAliInput(filename))
-    cerr<<"AliL3DataCompressor::RestoreData : Problems opening "<<filename<<endl;
+  if(fKeepRemaining)
+    ReadRemaining(clusters,ncl,maxpoints);
   
+  Char_t filename[1024];
   sprintf(filename,"%s/digitfile.root",fPath);
   TFile *rootfile = TFile::Open(filename);
   rootfile->cd();
   AliTPCParam *param = (AliTPCParam*)rootfile->Get(AliL3Transform::GetParamName());
+
   AliTPCDigitsArray *darray = new AliTPCDigitsArray();
   darray->Setup(param);
   darray->SetClass("AliSimDigits");
-  sprintf(filename,"TreeD_%s_0",AliL3Transform::GetParamName());
+  sprintf(filename,"TreeD_%s_%d",AliL3Transform::GetParamName(),fEvent);
   Bool_t ok = darray->ConnectTree(filename);
   if(!ok)
     {
       cerr<<"AliL3DataCompressor::RestoreData : Problems connecting tree"<<endl;
       return;
     }
+
+  fOutputFile->cd();
+    
+  AliTPCClustersArray *carray = new AliTPCClustersArray();
+  carray->Setup(param);
+  carray->SetClusterType("AliTPCcluster");
+  carray->MakeTree();
   
-  TDirectory *savedir = gDirectory;
-  
-  //Create new file for storing the final clusters:
-  sprintf(filename,"%s/comp/AliTPCclusters.root",fPath);
-  TFile *clusterfile = TFile::Open(filename,"RECREATE");
-  clusterfile->cd();
-  param->Write(param->GetTitle());
-  
-  AliTPCClustersArray carray;
-  carray.Setup(param);
-  carray.SetClusterType("AliTPCcluster");
-  carray.MakeTree();
-  
-  //Now start the loop:
-  for(Int_t slice=fMinSlice; slice<=fMaxSlice; slice++)
+  Int_t totcounter=0;
+  for(Int_t slice=0; slice<=35; slice++)
     {
-      for(Int_t patch=0; patch < AliL3Transform::GetNPatches(); patch++)
+      TempCluster **clPt = new TempCluster*[maxpoints];
+      cout<<"Sorting "<<ncl[slice]<<" clusters in slice "<<slice<<endl;
+      for(Int_t i=0; i<ncl[slice]; i++)
+       clPt[i] = &clusters[slice][i];
+      
+      QSort(clPt,0,ncl[slice]);
+      
+      //cout<<"padrow "<<clPt[i]->padrow<<" pad "<<clPt[i]->pad<<" time "<<clPt[i]->time<<endl;
+
+      Int_t falseid=0;
+      Int_t counter=0;
+      for(Int_t padrow=AliL3Transform::GetFirstRow(-1); padrow<=AliL3Transform::GetLastRow(-1); padrow++)
        {
-         //Get the remaining clusters:
-         Int_t nclusters = FindRemaining(slice,patch);
-         UInt_t size=0;
-         AliL3SpacePointData *points = (AliL3SpacePointData*)fMemHandler->GetDataPointer(size);
-         Int_t counter=0;
-         cout<<"Found "<<nclusters<<" clusters in slice "<<slice<<" patch "<<patch<<endl;
-         
-         //Get the uncompressed data:
-         AliL3Compress *comp = new AliL3Compress(slice,patch,fPath);
-         comp->ReadFile('u');
-
-         AliL3TrackArray *tracks = comp->GetTracks();
-         Short_t *used = new Short_t[tracks->GetNTracks()];
-                 
-         for(Int_t padrow=AliL3Transform::GetFirstRow(patch); padrow<=AliL3Transform::GetLastRow(patch); padrow++)
+         Int_t sec,row;
+         AliL3Transform::Slice2Sector(slice,padrow,sec,row);
+         AliTPCClustersRow *clrow=carray->CreateRow(sec,row);
+         AliSimDigits *digits = (AliSimDigits*)darray->LoadRow(sec,row);
+         digits->ExpandBuffer();
+         digits->ExpandTrackBuffer();
+         Int_t patch = AliL3Transform::GetPatch(padrow);
+         while(counter < ncl[slice] && clPt[counter]->padrow == padrow)
            {
-             Int_t sec,row;
-             AliL3Transform::Slice2Sector(slice,padrow,sec,row);
-             AliTPCClustersRow *clrow=carray.CreateRow(sec,row);
-             AliSimDigits *digits = (AliSimDigits*)darray->LoadRow(sec,row);
+             Float_t temp[3];
+             AliL3Transform::Raw2Local(temp,sec,row,clPt[counter]->pad,clPt[counter]->time);
+             
+             AliTPCcluster *c = new AliTPCcluster();
+             c->SetY(temp[1]);
+             c->SetZ(temp[2]);
+             c->SetQ(clPt[counter]->charge);
+             
+             c->SetSigmaY2(clPt[counter]->sigmaY2*pow(AliL3Transform::GetPadPitchWidth(patch),2));
+             c->SetSigmaZ2(clPt[counter]->sigmaZ2*pow(AliL3Transform::GetZWidth(),2));
+             Int_t pad = TMath::Nint(clPt[counter]->pad);
+             Int_t time = TMath::Nint(clPt[counter]->time);
              
-             Float_t pad,time,xywidth,zwidth;
-             Int_t charge;
+             if(pad < 0)
+               pad=0;
+             if(pad >= AliL3Transform::GetNPads(padrow))
+               pad = AliL3Transform::GetNPads(padrow)-1;
+             if(time < 0 || time >= AliL3Transform::GetNTimeBins())
+               cerr<<"row "<<padrow<<" pad "<<pad<<" time "<<time<<endl;
              
-             //Get the remaining clusters:
-             memset(used,0,tracks->GetNTracks()*sizeof(Short_t));
-             while(counter < nclusters && points[counter].fPadRow == padrow)
+             for(Int_t lab=0; lab<3; lab++)
                {
-                 Float_t temp[3] = {points[counter].fX,points[counter].fY,points[counter].fZ};
-                 AliL3Transform::Local2Raw(temp,sec,row);
-                 Int_t tpad,ttime;
-                 tpad = TMath::Nint(temp[1]);
-                 ttime = TMath::Nint(temp[2]);
-                 
-                 //Get the track data, if the order is such:
-                 for(Int_t i=0; i<tracks->GetNTracks(); i++)
+                 Int_t label = digits->GetTrackIDFast(time,pad,lab);
+                 if(label > 1)
+                   c->SetLabel(label-2,lab);
+                 else if(label==0)
+                   c->SetLabel(-2,lab);
+                 else
+                   c->SetLabel(-1,lab);
+                 if(lab==0 && c->GetLabel(0) < 0)
                    {
-                     if(used[i] == 1) continue;
-                     AliL3ModelTrack *track = (AliL3ModelTrack*)tracks->GetCheckedTrack(i);
-                     if(!track) continue;
-                     if(!track->IsPresent(padrow)) continue;
-                     track->GetPad(padrow,pad);
-                     track->GetTime(padrow,time);
-                     track->GetClusterCharge(padrow,charge);
-
-                     Float_t xyz[3];
-                     AliL3Transform::Raw2Local(xyz,sec,row,pad,time);
-                     
-                     if(TMath::Nint(pad) > tpad) continue;
-                     if(TMath::Nint(pad) == tpad &&
-                        TMath::Nint(time) > ttime) continue;
-                     
-                     used[i]=1;
-
-                     track->GetXYWidth(padrow,xywidth);
-                     track->GetZWidth(padrow,zwidth);
-                     
-                     Int_t trpad,trtime;
-                     trpad = TMath::Nint(pad);
-                     trtime = TMath::Nint(time);
-                     if(trpad < 0 || trpad >= AliL3Transform::GetNPads(padrow) ||
-                        trtime < 0 || trtime >= AliL3Transform::GetNTimeBins())
-                       {
-                         cerr<<"AliL3DataCompressor::RestoreData : Wrong pad "<<trpad<<" or time "<<trtime<<endl;
-                         track->Print();
-                         return;
-                       }
-                     
-                     xywidth = (xywidth+1./12)*pow(AliL3Transform::GetPadPitchWidth(patch),2);
-                     zwidth = (zwidth+1./12)*pow(AliL3Transform::GetZWidth(),2);
-                     
-                     AliTPCcluster *c = new AliTPCcluster();
-                     c->SetY(xyz[1]);
-                     c->SetZ(xyz[2]);
-                     c->SetSigmaY2(xywidth);
-                     c->SetSigmaZ2(zwidth);
-                     c->SetQ(charge);
-                     
-                     
-                     c->SetLabel(digits->GetTrackID(trtime,trpad,0),0);
-                     c->SetLabel(digits->GetTrackID(trtime,trpad,1),1);
-                     c->SetLabel(digits->GetTrackID(trtime,trpad,2),2);
-                     
-                     clrow->InsertCluster(c);
-                     delete c;
+                     falseid++;
+                     //AliL3Transform::Local2Global(temp,slice);
+                     //cout<<"slice "<<slice<<" padrow "<<padrow<<" y "<<temp[1]<<" z "<<temp[2]<<" label "<<c->GetLabel(0)<<endl;
                    }
-                                 
-                 AliTPCcluster *c = new AliTPCcluster();
-                 c->SetY(points[counter].fY);
-                 c->SetZ(points[counter].fZ);
-                 c->SetQ(points[counter].fCharge);
-                 
-                 xywidth = points[counter].fXYErr * points[counter].fXYErr;
-                 zwidth = points[counter].fZErr * points[counter].fZErr;
-                 c->SetSigmaY2(xywidth);
-                 c->SetSigmaZ2(zwidth);
-                 
-                 c->SetLabel(digits->GetTrackID(ttime,tpad,0),0);
-                 c->SetLabel(digits->GetTrackID(ttime,tpad,1),1);
-                 c->SetLabel(digits->GetTrackID(ttime,tpad,2),2);
-                 
-                 clrow->InsertCluster(c);
-                 delete c;
-                 counter++;
                }
+             //cout<<"row "<<padrow<<" pad "<<clPt[counter]->pad<<" time "<<clPt[counter]->time<<" sigmaY2 "<<c->GetSigmaY2()<<" sigmaZ2 "<<c->GetSigmaZ2()<<endl;
+             clrow->InsertCluster(c);
+             delete c;
+             counter++;
+             totcounter++;
+           }
+         carray->StoreRow(sec,row);
+         carray->ClearRow(sec,row);
+         darray->ClearRow(sec,row);
+       }
+      //cerr<<"Slice "<<slice<<" nclusters "<<counter<<" falseones "<<falseid<<endl;
+      if(counter != ncl[slice])
+       cerr<<"AliLDataCompressor::RestoreData : Mismatching cluster count :"<<counter<<" "<<ncl[slice]<<endl;
+      delete [] clPt;
+    }
+
+  cout<<"Writing "<<totcounter<<" clusters to rootfile "<<endl;
+
+  sprintf(filename,"TreeC_TPC_%d",fEvent);
+  carray->GetTree()->SetName(filename);
+  carray->GetTree()->Write();
+  delete carray;
+  delete darray;
+  rootfile->Close();
+  
+  for(Int_t i=0; i<36; i++)
+    delete [] clusters[i];
+  delete [] clusters;
+  delete [] ncl;
+#endif
+}
+
+void AliL3DataCompressor::ReadUncompressedData(TempCluster **clusters,Int_t *ncl,const Int_t maxpoints)
+{
+
+  cout<<"Reading uncompressed tracks "<<endl;
+  AliL3Compress *comp = new AliL3Compress(-1,-1,fPath,fWriteClusterShape,fEvent);
+  
+  if(!comp->ReadFile('u'))
+    return;
+  
+  AliL3TrackArray *tracks = comp->GetTracks();
+  
+  Int_t charge;
+  Float_t pad,time,sigmaY2,sigmaZ2;
+  for(Int_t i=0; i<tracks->GetNTracks(); i++)
+    {
+      AliL3ModelTrack *track = (AliL3ModelTrack*)tracks->GetCheckedTrack(i);
+      if(!track) continue;
+      for(Int_t padrow=0; padrow < AliL3Transform::GetNRows(-1); padrow++)
+       {
+         if(!track->IsPresent(padrow)) continue;
+         track->GetPad(padrow,pad);
+         track->GetTime(padrow,time);
+         track->GetClusterCharge(padrow,charge);
+         track->GetXYWidth(padrow,sigmaY2);
+         track->GetZWidth(padrow,sigmaZ2);
+         Int_t slice = track->GetClusterModel(padrow)->fSlice;
+         /*
+           if(pad < -1 || pad > AliL3Transform::GetNPads(padrow) || time < -1 || time > AliL3Transform::GetNTimeBins())
+           {
+           cerr<<"AliL3DataCompressor::ReadUncompressData : Wrong pad "<<pad<<" or time "<<time<<" on row "<<padrow<<" track index "<<i<<endl;
+           track->Print();
+           exit(5);
+           }
+         */
+         if(ncl[slice] >= maxpoints)
+           {
+             cerr<<"AliL3DataCompressor::ReadUncompressedData : Too many clusters"<<endl;
+             exit(5);
+           }
+         clusters[slice][ncl[slice]].pad = pad;
+         clusters[slice][ncl[slice]].time = time;
+         clusters[slice][ncl[slice]].charge = charge;
+         clusters[slice][ncl[slice]].sigmaY2 = sigmaY2;
+         clusters[slice][ncl[slice]].sigmaZ2 = sigmaZ2;
+         clusters[slice][ncl[slice]].padrow = padrow;
+         //cout<<"row "<<padrow<<" pad "<<pad<<" time "<<time<<" charge "<<charge<<" sigmas "<<sigmaY2<<" "<<sigmaZ2<<endl;
+         ncl[slice]++;
+       }
+    }
+
+  delete comp;
+}
+
+void AliL3DataCompressor::ReadRemaining(TempCluster **clusters,Int_t *ncl,const Int_t maxpoints)
+{
+  
+  Char_t filename[1024];
+  cout<<"Reading remaining clusters "<<endl;
+  AliL3MemHandler mem;
+  
+  for(Int_t slice=0; slice<=35; slice++)
+    {
+      for(Int_t p=0; p<1; p++)
+       {
+         sprintf(filename,"%s/comp/remains_%d_%d_%d.raw",fPath,fEvent,slice,-1);
+         
+         mem.SetBinaryInput(filename);
+         AliL3RemainingRow *tempPt = (AliL3RemainingRow*)mem.Allocate();
+         
+         Int_t nrows=0;
+         FILE *infile = mem.GetFilePointer();
+         while(!feof(infile))
+           {
+             Byte_t *dPt = (Byte_t*)tempPt;
+             if(fread(tempPt,sizeof(AliL3RemainingRow),1,infile)!=1) break;
              
-             //Fill the remaining tracks:
-             for(Int_t i=0; i<tracks->GetNTracks(); i++)
+             dPt += sizeof(AliL3RemainingRow);
+             
+             Int_t size = sizeof(AliL3RemainingCluster)*tempPt->fNClusters;
+             
+             fread(dPt,size,1,infile);
+             dPt += size;
+             tempPt = (AliL3RemainingRow*)dPt;
+             nrows++;
+           }
+         
+         mem.CloseBinaryInput();
+         UInt_t dummy;
+         tempPt = (AliL3RemainingRow*)mem.GetDataPointer(dummy);
+         
+         for(Int_t i=0; i<nrows; i++)
+           {
+             AliL3RemainingCluster *points = tempPt->fClusters;
+             Int_t padrow = (Int_t)tempPt->fPadRow;
+             Int_t patch = AliL3Transform::GetPatch(padrow);
+             Int_t sector,row;
+             AliL3Transform::Slice2Sector(slice,padrow,sector,row);
+             //cout<<"Loading slice "<<slice<<" row "<<padrow<<" with "<<(Int_t)tempPt->fNClusters<<" clusters "<<endl;
+             for(Int_t j=0; j<tempPt->fNClusters; j++)
                {
-                 if(used[i] == 1) continue;
-                 AliL3ModelTrack *track = (AliL3ModelTrack*)tracks->GetCheckedTrack(i);
-                 if(!track) continue;
-                 if(!track->IsPresent(padrow)) continue;
-                 track->GetPad(padrow,pad);
-                 track->GetTime(padrow,time);
-                 track->GetClusterCharge(padrow,charge);
-                 
-                 Float_t xyz[3];
-                 AliL3Transform::Raw2Local(xyz,sec,row,pad,time);
                  
-                 used[i]=1;
+                 Float_t xyz[3] = {AliL3Transform::Row2X(padrow),points[j].fY,points[j].fZ};
                  
-                 track->GetXYWidth(padrow,xywidth);
-                 track->GetZWidth(padrow,zwidth);
+                 AliL3Transform::Local2Raw(xyz,sector,row);
                  
-                 Int_t trpad,trtime;
-                 trpad = TMath::Nint(pad);
-                 trtime = TMath::Nint(time);
-                 if(trpad < 0 || trpad >= AliL3Transform::GetNPads(padrow) ||
-                    trtime < 0 || trtime >= AliL3Transform::GetNTimeBins())
+                 if(ncl[slice] >= maxpoints)
                    {
-                     cerr<<"AliL3DataCompressor::RestoreData : Wrong pad "<<trpad<<" or time "<<trtime<<endl;
-                     track->Print();
-                     return;
+                     cerr<<"AliL3DataCompressor::ReadRemaining : Too many clusters"<<endl;
+                     exit(5);
                    }
-                 
-                 xywidth = (xywidth+1./12)*pow(AliL3Transform::GetPadPitchWidth(patch),2);
-                 zwidth = (zwidth+1./12)*pow(AliL3Transform::GetZWidth(),2);
-                 
-                 AliTPCcluster *c = new AliTPCcluster();
-                 c->SetY(xyz[1]);
-                 c->SetZ(xyz[2]);
-                 c->SetSigmaY2(xywidth);
-                 c->SetSigmaZ2(zwidth);
-                 c->SetQ(charge);
-                 
-                 c->SetLabel(digits->GetTrackID(trtime,trpad,0),0);
-                 c->SetLabel(digits->GetTrackID(trtime,trpad,1),1);
-                 c->SetLabel(digits->GetTrackID(trtime,trpad,2),2);
-                 
-                 clrow->InsertCluster(c);
-                 delete c;
-               }
-             
-             carray.StoreRow(sec,row);
-             carray.ClearRow(sec,row);
-             darray->ClearRow(sec,row);
-             for(Int_t tr=0; tr<tracks->GetNTracks(); tr++)
-               {
-                 AliL3ModelTrack *track = (AliL3ModelTrack*)tracks->GetCheckedTrack(tr);
-                 if(!track) continue;
-                 if(track->IsPresent(padrow) && used[tr]==0)
-                   cerr<<"AliL3DataCompressor::RestoreData : Track "<<tr<<" in sector "<<sec<<" row "<<row<<" was not used"<<endl;
+                 //cout<<"slice "<<slice<<" padrow "<<padrow<<" pad "<<xyz[1]<<" time "<<xyz[2]<<endl;
+                 clusters[slice][ncl[slice]].pad = xyz[1];
+                 clusters[slice][ncl[slice]].time = xyz[2];
+                 clusters[slice][ncl[slice]].charge = points[j].fCharge;
+                 clusters[slice][ncl[slice]].sigmaY2 = points[j].fSigmaY2/pow(AliL3Transform::GetPadPitchWidth(patch),2);
+                 clusters[slice][ncl[slice]].sigmaZ2 = points[j].fSigmaZ2/pow(AliL3Transform::GetZWidth(),2);
+                 clusters[slice][ncl[slice]].padrow = padrow;
+                 ncl[slice]++;
                }
+             Byte_t *dPt = (Byte_t*)tempPt;
+             Int_t size = sizeof(AliL3RemainingRow) + tempPt->fNClusters*sizeof(AliL3RemainingCluster);
+             dPt += size;
+             tempPt = (AliL3RemainingRow*)dPt;
            }
-         delete [] used;
-         delete comp;
-         fMemHandler->Free();
-         if(nclusters != counter)
-           cerr<<"AliL3DataCompressor::RestoreData : Mismatching counters : "<<nclusters<<" "<<counter<<endl;
+         
+         mem.Free();
        }
     }
+}
+
+void AliL3DataCompressor::QSort(TempCluster **a, Int_t first, Int_t last)
+{
+  static TempCluster *tmp;
+   static int i;           // "static" to save stack space
+   int j;
+
+   while (last - first > 1) {
+      i = first;
+      j = last;
+      for (;;) {
+       while (++i < last && Compare(a[i], a[first]) < 0)
+         ;
+       while (--j > first && Compare(a[j], a[first]) > 0)
+         ;
+         if (i >= j)
+            break;
+
+         tmp  = a[i];
+         a[i] = a[j];
+         a[j] = tmp;
+      }
+      if (j == first) {
+         ++first;
+         continue;
+      }
+      tmp = a[first];
+      a[first] = a[j];
+      a[j] = tmp;
+      if (j - first < last - (j + 1)) {
+         QSort(a, first, j);
+         first = j + 1;   // QSort(j + 1, last);
+      } else {
+         QSort(a, j + 1, last);
+         last = j;        // QSort(first, j);
+      }
+   }
+}
+
+Int_t AliL3DataCompressor::Compare(TempCluster *a,TempCluster *b)
+{
+  /*
+  if(a->padrow < 0 || a->padrow > AliL3Transform::GetNRows(-1) ||
+     b->padrow < 0 || b->padrow > AliL3Transform::GetNRows(-1))
+    {
+      cerr<<"AliL3Compressor::Compare : Wrong padrows "<<a->padrow<<" "<<b->padrow<<endl;
+      exit(5);
+    }
+  else if(a->pad < 0 || a->pad > AliL3Transform::GetNPads(a->padrow) || 
+         b->pad < 0 || b->pad > AliL3Transform::GetNPads(b->padrow))
+    {
+      cerr<<"AliL3Compressor::Compare : Wrong pads "<<a->pad<<" "<<b->pad<<endl;
+      exit(5);
+    }
+  else if(a->time < 0 || a->time > AliL3Transform::GetNTimeBins() || 
+         b->time < 0 || b->time > AliL3Transform::GetNTimeBins())
+    {
+      cerr<<"AliL3Compressor::Compare : Wrong timebins "<<a->time<<" "<<b->time<<endl;
+      exit(5);
+    }
+  */
+  if(a->padrow < b->padrow) return -1;
+  if(a->padrow > b->padrow) return 1;
+
+  if(rint(a->pad) == rint(b->pad) && rint(a->time) == rint(b->time)) return 0;
   
-  //Write the tree to file:
-  sprintf(filename,"TreeC_TPC_%d",0);
-  carray.GetTree()->SetName(filename);
-  carray.GetTree()->Write();
-  savedir->cd();
-  delete darray;
-  rootfile->Close();
-  //  clusterfile->Close();
+  if(rint(a->pad) < rint(b->pad)) return -1;
+  if(rint(a->pad) == rint(b->pad) && rint(a->time) < rint(b->time)) return -1;
   
+  return 1;
 }
 
-Int_t AliL3DataCompressor::FindRemaining(Int_t slice,Int_t patch)
+void AliL3DataCompressor::LoadOfflineData(Int_t event)
 {
-  fMemHandler->Init(slice,patch);
-  UInt_t npoints=0;
-  if(!fMemHandler->AliPoints2Memory(npoints))
-    cerr<<"AliL3DataCompressor::FindRemaining : Problems loading clusters "<<endl;
+  //Take offline reconstructed tracks as an input.
+  //In this case, no remaining clusters are written.
   
-  return (Int_t)npoints;
-}
+#ifndef use_aliroot
+   LOG(AliL3Log::kError,"AliL3DataCompressor::LoadOfflineData","Version")
+     <<"You have to compile with use_aliroot flag in order to use this function"<<ENDLOG;
+#else
+
+  char filename[1024];
+  
+  AliKalmanTrack::SetConvConst(1000/0.299792458/AliL3Transform::GetSolenoidField());
+  sprintf(filename,"%s/offline/AliTPCclusters.root",fPath);
+
+  TFile *in = TFile::Open(filename);
+  AliTPCParam *param=(AliTPCParam*)in->Get("75x40_100x60_150x60");
+  
+  AliTPCtracker *tracker = new AliTPCtracker(param);
+  tracker->SetEventNumber(event);
+  tracker->LoadClusters();
+  
+  const Int_t MAX=20000;
+  Int_t nentr=0,i=0; TObjArray tarray(MAX);
+  sprintf(filename,"%s/offline/AliTPCtracks.root",fPath);
+  TFile *tf=TFile::Open(filename);
+  
+  char tname[100]; sprintf(tname,"TreeT_TPC_%d",event);
+  TTree *tracktree=(TTree*)tf->Get(tname);
+  
+  TBranch *tbranch=tracktree->GetBranch("tracks");
+  nentr=(Int_t)tracktree->GetEntries();
+  AliTPCtrack *iotrack=0;
+
+  for (i=0; i<nentr; i++) {
+    iotrack=new AliTPCtrack;
+    tbranch->SetAddress(&iotrack);
+    tracktree->GetEvent(i);
+    tarray.AddLast(iotrack);
+  }   
+  delete tracktree; 
+  tf->Close();
+  
+  AliL3TrackArray *comptracks = new AliL3TrackArray("AliL3ModelTrack");
+  cout<<"Loaded "<<nentr<<" offline tracks"<<endl;
+  Int_t slice,padrow;
+  Int_t totcounter=0;
+  for(i=0; i<nentr; i++)
+    {
+      
+      AliTPCtrack *track=(AliTPCtrack*)tarray.UncheckedAt(i);
+      Int_t nhits = track->GetNumberOfClusters();
+      Int_t idx = track->GetClusterIndex(nhits-1);
+      Int_t sec=(idx&0xff000000)>>24, row=(idx&0x00ff0000)>>16;
+      
+      if(sec >= 18)
+       sec += 18;
+      
+      AliL3Transform::Sector2Slice(slice,padrow,sec,row);
+      Double_t par[5],xk=AliL3Transform::Row2X(padrow);
+      track->PropagateTo(xk);
+      track->GetExternalParameters(xk,par);
+      Double_t psi = TMath::ASin(par[2]) + track->GetAlpha();
+      if (psi<-TMath::Pi()) psi+=2*TMath::Pi();
+      if (psi>=TMath::Pi()) psi-=2*TMath::Pi();
+      Float_t pt_1=TMath::Abs(par[4]);
+      Int_t charge = 1;
+      if(par[4] > 0)
+       charge=-1;
+
+      Float_t first[3];
+      AliCluster *fcl = tracker->GetCluster(idx);
+      first[0] = xk;
+      first[1] = fcl->GetY();
+      first[2] = fcl->GetZ();
+
+      AliL3Transform::Local2Global(first,slice);
+      
+      AliL3ModelTrack *outtrack = (AliL3ModelTrack*)comptracks->NextTrack();
+      outtrack->SetNHits(nhits);
+      outtrack->SetFirstPoint(first[0],first[1],first[2]);
+      outtrack->SetPt(1/pt_1);
+      outtrack->SetPsi(psi);
+      outtrack->SetTgl(par[3]);
+      outtrack->SetCharge(charge);
+      outtrack->CalculateHelix();
+      outtrack->Init(0,-1);
 
+      //for(int j=0; j<nhits; j++)
+      for(int j=nhits-1; j>=0; j--)
+       {
+         Int_t index = track->GetClusterIndex(j);
+         
+         Float_t xyz[3];
+         Int_t clustercharge =0;
+         
+         AliTPCcluster *cluster = (AliTPCcluster*)tracker->GetCluster(index);
+         xyz[1] = cluster->GetY();
+         xyz[2] = cluster->GetZ();
+         clustercharge = (Int_t)cluster->GetQ();
+         
+         cluster->SetQ(-clustercharge);//Set as used
+         
+         sec=(index&0xff000000)>>24; row=(index&0x00ff0000)>>16;
+         
+         //This we do because the sector numbering of course are different internally
+         //in the fucked up AliTPCtracker class. 
+         if(sec >= 18)
+           sec += 18;
+         
+         if(xyz[2] < 0)
+           sec += 18;
+
+         //cout<<"sector "<<sec<<" row "<<row<<endl;
+         if(!AliL3Transform::Sector2Slice(slice,padrow,sec,row))
+           exit(5);
+         xyz[0] = AliL3Transform::Row2X(padrow);
+         
+         //cout<<"Hit in slice "<<slice<<" padrow "<<padrow<<" y "<<cluster->GetY()<<" z "<<cluster->GetZ()<<endl;
+         AliL3Transform::Local2Raw(xyz,sec,row);
+         //cout<<"slice "<<slice<<" padrow "<<padrow<<" pad "<<xyz[1]<<" time "<<xyz[2]<<endl;
+         
+         if(xyz[1] < -1 || xyz[1] > AliL3Transform::GetNPads(padrow) ||
+            xyz[2] < -1 || xyz[2] > AliL3Transform::GetNTimeBins())
+           {
+             cerr<<"AliL3DataCompressor::FillOfflineData : Wrong time "<<xyz[2]<<" in slice "
+                 <<slice<<" padrow "<<padrow<<endl;
+             cout<<"sector "<<sec<<" row "<<row<<endl;
+             //cout<<"Hit in slice "<<slice<<" padrow "<<padrow<<" y "<<cluster->GetY()<<" z "<<cluster->GetZ()<<endl;
+             cout<<"Track hit "<<xyz[0]<<" "<<xyz[1]<<" "<<xyz[2]<<endl;
+             exit(5);
+           }
+         
+         Float_t angle = 0;
+         AliL3Transform::Local2GlobalAngle(&angle,slice);
+         if(!outtrack->CalculateReferencePoint(angle,AliL3Transform::Row2X(padrow)))
+           {
+             cerr<<"AliL3DataCompressor::FillOfflineData : Error in crossing point calc on slice "
+                 <<slice<<" row "<<padrow<<endl;
+             exit(5);
+           }
+         Float_t xyz_cross[3] = {outtrack->GetPointX(),outtrack->GetPointY(),outtrack->GetPointZ()};
+         AliL3Transform::Global2Raw(xyz_cross,sec,row);
+         /*
+           if(fabs(xyz_cross[1] - xyz[1]) > 10 ||
+           fabs(xyz_cross[2] - xyz[2]) > 10)
+           {
+           cout<<"AliL3DataCompressor::FillOfflineData : Wrong crossing slice "<<slice<<" padrow "
+           <<padrow<<" pad "<<xyz[1]<<" padhit "<<xyz_cross[1]<<" time "<<xyz[2]<<" timehit "<<xyz_cross[2]<<endl;
+           outtrack->Print();
+           exit(5);
+           }
+         */
+         //cout<<" crossing "<<xyz_cross[0]<<" "<<xyz_cross[1]<<" "<<xyz_cross[2]<<endl;
+         outtrack->SetPadHit(padrow,xyz_cross[1]);
+         outtrack->SetTimeHit(padrow,xyz_cross[2]);
+         
+         if(fWriteClusterShape)
+           {
+             Float_t angle = outtrack->GetCrossingAngle(padrow,slice);
+             outtrack->SetCrossingAngleLUT(padrow,angle);
+             outtrack->CalculateClusterWidths(padrow,kTRUE);
+             Int_t patch = AliL3Transform::GetPatch(padrow);
+             Float_t sigmaY2 = cluster->GetSigmaY2() / pow(AliL3Transform::GetPadPitchWidth(patch),2);
+             Float_t sigmaZ2 = cluster->GetSigmaZ2() / pow(AliL3Transform::GetZWidth(),2);
+             outtrack->SetCluster(padrow,xyz[1],xyz[2],clustercharge,sigmaY2,sigmaZ2,3);
+           }
+         else
+           outtrack->SetCluster(padrow,xyz[1],xyz[2],clustercharge,0,0,3);
+         totcounter++;
+         outtrack->GetClusterModel(padrow)->fSlice = slice;
+       }
+      /*
+      int label = track->GetLabel();
+      if(label == 10019 || label==6281 || label== 5326 || label==3054 || label==1366 || label==1005)
+       outtrack->Print();
+      */
+    }
+  
+  tracker->UnloadClusters();
+  
+  cout<<"AliL3DataCompressor::FillOfflineData : Wrote "<<totcounter<<" clusters"<<endl;
+  //Write tracks to file
+  AliL3Compress *comp = new AliL3Compress(-1,-1,fPath,fWriteClusterShape,fEvent);
+  comp->WriteFile(comptracks);
+  delete comp;
+  delete comptracks;
+  delete tracker;
+#endif
+}
index 162b1a8..c149078 100644 (file)
@@ -1,33 +1,92 @@
+// @(#) $Id$
+
 #ifndef AliL3_DataCompressor
 #define AliL3_DataCompressor
 
-#include "AliL3RootTypes.h"
-
-class AliL3MemHandler;
+class AliL3SpacePointData;
 class AliL3Benchmark;
+class AliL3TrackArray;
+class AliL3Track;
+
+#ifdef use_root
+class TH2F;
+class TFile;
+#endif
+
+struct TempCluster {
+  Float_t pad;
+  Float_t time;
+  Float_t sigmaY2;
+  Float_t sigmaZ2;
+  Int_t charge;
+  Int_t padrow;
+};
 
 class AliL3DataCompressor {
   
  private:
-  AliL3MemHandler *fMemHandler;  //!
   AliL3Benchmark *fBenchmark;    //!
-  Int_t fMinSlice;
-  Int_t fMaxSlice;
-  Char_t fPath[1024]; //!
+  AliL3TrackArray *fInputTracks; //!
+  AliL3SpacePointData *fClusters[36][6]; //!
+  ofstream *fCompRatioFile;      //!
+#ifdef use_root
+  TFile *fOutputFile;            //!
+#else
+  FILE *fOutputFile;
+#endif
+  Char_t fPath[1024];            //!
+  
+  UInt_t fNcl[36][6];
+  Bool_t fKeepRemaining;
+  Bool_t fWriteClusterShape;
+  Int_t fEvent;
+  Bool_t fSinglePatch;
+  
+  static Int_t fNumPadBits;
+  static Int_t fNumTimeBits;
+  static Int_t fNumChargeBits;
+  static Int_t fNumShapeBits;
   
-  Int_t FindRemaining(Int_t slice,Int_t patch);
+  static Float_t fXYResidualStep;
+  static Float_t fZResidualStep;
+  static Float_t fXYWidthStep;
+  static Float_t fZWidthStep;
+  static Int_t fClusterCharge;
+  
+  void SelectRemainingClusters();
+  void ExpandTrackData(AliL3TrackArray *tracks);
+  void ReadUncompressedData(TempCluster **clusters,Int_t *ncl,const Int_t maxpoints);
+  void ReadRemaining(TempCluster **clusters,Int_t *ncl,const Int_t maxpoints);
+  void QSort(TempCluster **a, Int_t first, Int_t last);
+  Int_t Compare(TempCluster *a,TempCluster *b);
+  void OpenOutputFile();
+  void CloseOutputFile();
 
  public:
   AliL3DataCompressor();
-  AliL3DataCompressor(Char_t *path,Int_t minslice,Int_t maxslice);
+  AliL3DataCompressor(Char_t *path,Bool_t keep,Bool_t writeshape);
   virtual ~AliL3DataCompressor();
   
-  void ProcessData(Char_t *trackpath,Int_t padoverlap,Int_t timeoverlap,Int_t padsearch,Int_t timesearch);
-  void CompressAndExpand(Int_t bitspad,Int_t bitstime,Int_t bitscharge,Int_t bitsshape);
-  void WriteRemainingDigits();
-  void FindOfflineClusters(Bool_t remains);
+  void LoadData(Int_t event,Bool_t sp=kTRUE);
+  void FillData(Int_t minhits,Bool_t expand);
+  void LoadOfflineData(Int_t event);
+  void CompressAndExpand();
+  void WriteRemaining(Bool_t select);
   void RestoreData();
   void DoBench(Char_t *fname="benchmark");
+  
+  void SetBitNumbers(Int_t pad,Int_t time,Int_t charge,Int_t shape);
+  void SetResolutions(Float_t xyresidual,Float_t zresidual,Int_t clustercharge,Float_t xywidth=0.005,Float_t zwidth=0.005);
+  
+  static const Int_t GetNPadBits() {return fNumPadBits;}
+  static const Int_t GetNTimeBits() {return fNumTimeBits;}
+  static const Int_t GetNChargeBits() {return fNumChargeBits;}
+  static const Int_t GetNShapeBits() {return fNumShapeBits;}
+  static const Float_t GetXYResidualStep() {return fXYResidualStep;}
+  static const Float_t GetZResidualStep() {return fZResidualStep;}
+  static const Float_t GetXYWidthStep() {return fXYWidthStep;}
+  static const Float_t GetZWidthStep() {return fZWidthStep;}
+  static const Int_t GetClusterCharge() {return fClusterCharge;}
 
   ClassDef(AliL3DataCompressor,1) 
 
index 4db6851..335b033 100644 (file)
@@ -1,9 +1,20 @@
+// @(#) $Id$
+
 #ifndef AliL3FitUtilities
 #define AliL3FitUtilities
 
-void   f2gauss5( double, double *, double *,double *,int );
+//This we do because this file is read both with c and c++ compiler, 
+//and extern "C" is needed only in case of c++.
+#ifdef __cplusplus
+extern "C" 
+#endif
+void f2gauss5( double, double *, double *,double *,int );
+
+#ifdef __cplusplus 
+extern "C" 
+#endif
 int lev_marq_fit( double x[], double y[], double sig[], int NPT, double a[], int ia[], double dev[], int MA,
-                  double *chisq_p, void (*funcs)(double, double [], double *, double [], int) );
+                 double *chisq_p, void (*funcs)(double, double [], double *, double [], int) );
 
 #define max(x, y) (((x) > (y)) ? (x) : (y))
 #define min(x, y) (((x) < (y)) ? (x) : (y))
index 5fcee4d..45914cc 100644 (file)
@@ -1,13 +1,14 @@
-//$Id$
+// @(#) $Id$
 
 // Author: Anders Vestbo <mailto:vestbo$fi.uib.no>
-//*-- Copyright &copy ASV
+//*-- Copyright &copy ALICE HLT Group
 
 #include "AliL3StandardIncludes.h"
 
 #include "AliL3Logging.h"
 #include "AliL3ModelTrack.h"
 #include "AliL3Transform.h"
+#include "AliL3DataCompressor.h"
 
 #if GCCVERSION == 3
 using namespace std;
@@ -20,16 +21,19 @@ using namespace std;
 
 ClassImp(AliL3ModelTrack)
 
-AliL3ModelTrack::AliL3ModelTrack()
+AliL3ModelTrack::AliL3ModelTrack() 
 {
   fNClusters = 0;
   fClusters = 0;
   fOverlap = 0;
   fPad=0;
   fTime=0;
+  fNoverlaps=0;
   fClusterCharge=0;
   fTrackModel=0;
-  fLabel=0;
+  fCrossingAngle=0;
+  fParSigmaY2=0;
+  fParSigmaZ2=0;
 }
 
 
@@ -41,71 +45,164 @@ AliL3ModelTrack::~AliL3ModelTrack()
     delete [] fPad;
   if(fTime)
     delete [] fTime;
-  if(fOverlap)
-    delete [] fOverlap;
+  if(fCrossingAngle)
+    delete [] fCrossingAngle;
+  if(fParSigmaY2)
+    delete [] fParSigmaY2;
+  if(fParSigmaZ2)
+    delete [] fParSigmaZ2;
   if(fTrackModel)
     delete fTrackModel;
+  if(fNoverlaps)
+    delete [] fNoverlaps;
+  if(fOverlap)
+    {
+      for(Int_t i=0; i<AliL3Transform::GetNRows(fPatch); i++)
+       delete [] fOverlap[i];
+      delete [] fOverlap;
+    }
+
 }
 
 void AliL3ModelTrack::Init(Int_t slice,Int_t patch)
 {
-  fNClusters = 0;
-  fSlice=slice;
+  fNClusters=AliL3Transform::GetNRows(patch);//is not incremented in setcluster anymore
+  //fSlice=slice;
   fPatch=patch;
   Int_t nrows = AliL3Transform::GetNRows(fPatch);
   fClusters = new AliL3ClusterModel[nrows];
   fPad = new Float_t[nrows];
   fTime = new Float_t[nrows];
+  fCrossingAngle = new Float_t[nrows];
+  fParSigmaY2 = new Float_t[nrows];
+  fParSigmaZ2 = new Float_t[nrows];
   fTrackModel = new AliL3TrackModel;
-  fOverlap = new Int_t[nrows];
-
+  
+  fOverlap = new Int_t*[nrows];
+  fNoverlaps = new Int_t[nrows];
+  fMaxOverlaps = 5;
+  
+  memset(fNoverlaps,0,nrows*sizeof(Int_t));
   memset(fClusters,0,nrows*sizeof(AliL3ClusterModel));
   memset(fPad,0,nrows*sizeof(Float_t));
   memset(fTime,0,nrows*sizeof(Float_t));
+  memset(fCrossingAngle,0,nrows*sizeof(Float_t));
+  memset(fParSigmaY2,0,nrows*sizeof(Float_t));
+  memset(fParSigmaZ2,0,nrows*sizeof(Float_t));
   memset(fTrackModel,0,sizeof(AliL3TrackModel));
   for(Int_t i=0; i<nrows; i++)
-    fOverlap[i]=-1;
+    {
+      fOverlap[i] = new Int_t[fMaxOverlaps];
+      for(Int_t j=0; j<fMaxOverlaps; j++)
+       fOverlap[i][j]=-1;
+      fClusters[i].fSlice = -1;
+    }
 
-  fClusterCharge = 100;
-  
-  // 100 micrometers:
-  fXYResidualQ = 0.01/AliL3Transform::GetPadPitchWidth(patch);
-  fZResidualQ = 0.01/AliL3Transform::GetPadPitchWidth(patch);
-  
-  fXYWidthQ = 0.005/AliL3Transform::GetPadPitchWidth(patch);
-  fZWidthQ = 0.005/AliL3Transform::GetPadPitchWidth(patch);
 }
 
-
-void AliL3ModelTrack::SetCluster(Int_t row,Float_t fpad,Float_t ftime,Float_t charge,Float_t sigmaY2,Float_t sigmaZ2,Int_t npads)
+void AliL3ModelTrack::CalculateClusterWidths(Int_t row,Bool_t parametrize)
 {
-  Int_t index = row - AliL3Transform::GetFirstRow(fPatch);
-  if(index != fNClusters)
-    cout<<"AliL3ModelTrack::SetCluster() : Mismatch ; index: "<<index<<" nclusters "<<fNClusters<<endl;
+  //Cluster widths
   
+  Float_t xyz[3];
+  Int_t sr,lr;
+  Int_t index = row - AliL3Transform::GetFirstRow(fPatch);
   if(index < 0 || index > AliL3Transform::GetNRows(fPatch))
     {
-      cerr<<"AliL3ModelTrack::SetCluster() : Wrong index: "<<index<<" row "<<row<<endl;
+      cerr<<"AliL3ModelTrack::CalculcateClusterWidths : Wrond index "<<index<<" row "<<row<<endl;
       return;
     }
+  Int_t patch = AliL3Transform::GetPatch(row);
+  AliL3Transform::Slice2Sector(0,row,sr,lr);
+  AliL3Transform::Raw2Local(xyz,sr,lr,GetPadHit(row),GetTimeHit(row));
+  fParSigmaY2[index] = AliL3Transform::GetParSigmaY2(row,xyz[2],GetCrossingAngleLUT(row));
+  fParSigmaZ2[index] = AliL3Transform::GetParSigmaZ2(row,xyz[2],GetTgl());
+  
+  if(parametrize)
+    {
+      fParSigmaY2[index] = (fParSigmaY2[index] + (1./12)*pow(AliL3Transform::GetPadPitchWidth(patch),2) );
+      fParSigmaY2[index] *= 0.108;
+      if(patch<2)
+       fParSigmaY2[index] *= 2.07;
+     
+      fParSigmaZ2[index] = (fParSigmaZ2[index] + (1./12)*pow(AliL3Transform::GetZWidth(),2) );
+      fParSigmaZ2[index] *= 0.169;
+      if(patch<2)
+       fParSigmaZ2[index] *= 1.77;
+    }
+  
+  //convert to raw coordinates:
+  fParSigmaY2[index] /= pow(AliL3Transform::GetPadPitchWidth(patch),2);
+  fParSigmaZ2[index] /= pow(AliL3Transform::GetZWidth(),2);
+}
+
+void AliL3ModelTrack::SetCluster(Int_t row,Float_t fpad,Float_t ftime,Float_t charge,
+                                Float_t sigmaY2,Float_t sigmaZ2,Int_t npads)
+{
   AliL3ClusterModel *cl = GetClusterModel(row);
   
-  //Do not save the cluster if there were no charge found, or only 1 pad is present.
-  //In the latter case it is most probably noise.
+  //First bit: Cluster is present or not
+  //Second bit: Cluster was set, meaning an fit attempt was done (if true)
+  
+  cl->fPresent |= 0x2; //set second bit to true, because a fit attempt has been made
+  
+  Int_t patch = AliL3Transform::GetPatch(row);
   if(!charge || npads == 1)
-    cl->fPresent = kFALSE;
+    {
+      cl->fPresent &= ~0x1; //set first bit to false
+    }
   else
     {
-      cl->fPresent = kTRUE;
-      cl->fDTime = (ftime - GetTimeHit(row))/fXYResidualQ;
-      cl->fDPad = (fpad - GetPadHit(row))/fZResidualQ;
-      cl->fDCharge = charge;// - fClusterCharge;
-      cl->fDSigmaY2 = (sigmaY2 - GetParSigmaY2(row))/fXYWidthQ;
-      cl->fDSigmaZ2 = (sigmaZ2 - GetParSigmaZ2(row))/fZWidthQ;
+      cl->fPresent|=0x1;//set first bit to true
+      cl->fDTime = (ftime - GetTimeHit(row))/(AliL3DataCompressor::GetZResidualStep()/AliL3Transform::GetZWidth());   
+      cl->fDPad = (fpad - GetPadHit(row))/(AliL3DataCompressor::GetXYResidualStep()/AliL3Transform::GetPadPitchWidth(patch));
+      cl->fDCharge = charge;// - AliL3DataCompressor::GetClusterCharge();
+      //cl->fSlice = fSlice;
+      if(sigmaY2==0 && sigmaZ2==0)
+       {
+         cl->fDSigmaY2=0;//if width is zero, shape is not supposed to be written
+         cl->fDSigmaZ2=0;
+       }
+      else
+       {
+         cl->fDSigmaY2 = (sigmaY2 - GetParSigmaY2(row))/(AliL3DataCompressor::GetXYWidthStep()/pow(AliL3Transform::GetPadPitchWidth(patch),2));
+         cl->fDSigmaZ2 = (sigmaZ2 - GetParSigmaZ2(row))/(AliL3DataCompressor::GetZWidthStep()/pow(AliL3Transform::GetZWidth(),2));
+       }
       cl->fNPads = npads;
     }
   
-  fNClusters++;
+  //fNClusters++;
+}
+
+void AliL3ModelTrack::Set(AliL3Track *tpt)
+{
+  AliL3ModelTrack *tr = (AliL3ModelTrack*)tpt;
+  SetRowRange(tr->GetFirstRow(),tr->GetLastRow());
+  SetPhi0(tr->GetPhi0());
+  SetKappa(tr->GetKappa());
+  SetFirstPoint(tr->GetFirstPointX(),tr->GetFirstPointY(),tr->GetFirstPointZ());
+  SetLastPoint(tr->GetLastPointX(),tr->GetLastPointY(),tr->GetLastPointZ());
+  SetPt(tr->GetPt());
+  SetPsi(tr->GetPsi());
+  SetTgl(tr->GetTgl());
+  SetCharge(tr->GetCharge());
+  
+  if(fClusters)
+    {
+      cerr<<"AliL3ModelTrack::Set : Init has already been called for this object!"<<endl;
+      return;
+    }
+
+  //Init(tr->fSlice,tr->fPatch);
+  Init(0,tr->fPatch);
+  memcpy(fClusters,tr->fClusters,AliL3Transform::GetNRows(fPatch)*sizeof(AliL3ClusterModel));
+  memcpy(fPad,tr->fPad,AliL3Transform::GetNRows(fPatch)*sizeof(Float_t));
+  memcpy(fTime,tr->fTime,AliL3Transform::GetNRows(fPatch)*sizeof(Float_t));
+  memcpy(fParSigmaY2,tr->fParSigmaY2,AliL3Transform::GetNRows(fPatch)*sizeof(Float_t));
+  memcpy(fParSigmaZ2,tr->fParSigmaZ2,AliL3Transform::GetNRows(fPatch)*sizeof(Float_t));
+  memcpy(fCrossingAngle,tr->fCrossingAngle,AliL3Transform::GetNRows(fPatch)*sizeof(Float_t));
+  memcpy(fTrackModel,tr->fTrackModel,sizeof(AliL3TrackModel));
+
 }
 
 Int_t AliL3ModelTrack::GetNPresentClusters()
@@ -117,11 +214,9 @@ Int_t AliL3ModelTrack::GetNPresentClusters()
   Int_t count=0;
 
   for(Int_t i=AliL3Transform::GetFirstRow(fPatch); i<=AliL3Transform::GetLastRow(fPatch); i++)
-    {
-      AliL3ClusterModel *cl = GetClusterModel(i);
-      if(cl->fPresent)
-       count++;
-    }
+    if(IsPresent(i))
+      count++;
+
   return count;
 }
 
@@ -129,21 +224,26 @@ void AliL3ModelTrack::FillModel()
 {
   //Fill the track structure
   
+  if(fNClusters != AliL3Transform::GetNRows(fPatch))
+    {
+      cout<<"AliL3ModelTrack::FillModel : fNClusters != nrows; beware, this could be caused by a bug!!!"<<endl;
+      fNClusters = AliL3Transform::GetNRows(fPatch);
+    }
+
   if(!fTrackModel)
     {
       cerr<<"AliL3ModelTrack::FillModel() : No trackmodel "<<endl;
       return;
     }
   fTrackModel->fKappa = GetKappa();
+
   fTrackModel->fFirstPointX = GetFirstPointX();
   fTrackModel->fFirstPointY = GetFirstPointY();
   fTrackModel->fFirstPointZ = GetFirstPointZ();
   fTrackModel->fTgl = GetTgl();
   fTrackModel->fPsi = GetPsi();
   fTrackModel->fLength = (Short_t)GetLength();
-  fTrackModel->fClusterCharge = fClusterCharge;
   fTrackModel->fNClusters = fNClusters;
-
 }
 
 void AliL3ModelTrack::FillTrack()
@@ -161,27 +261,60 @@ void AliL3ModelTrack::FillTrack()
   SetTgl(fTrackModel->fTgl);
   SetPsi(fTrackModel->fPsi);
   SetLength(fTrackModel->fLength);
-  fClusterCharge=fTrackModel->fClusterCharge;
   fNClusters = fTrackModel->fNClusters;
-  SetPt((BFACT*AliL3Transform::GetBField())/fabs(GetKappa()));
-  
+  SetPt((AliL3Transform::GetBFact()*AliL3Transform::GetBField())/fabs(GetKappa()));
+    
   CalculateHelix();
-  
-  Float_t hit[3];
-  Int_t sector,row;
+
   for(Int_t i=AliL3Transform::GetFirstRow(fPatch); i<=AliL3Transform::GetLastRow(fPatch); i++)
     {
       AliL3ClusterModel *cl = GetClusterModel(i);
       if(!cl) continue;
-      GetCrossingPoint(i,hit);
-      AliL3Transform::Slice2Sector(fSlice,i,sector,row);
-      AliL3Transform::Local2Raw(hit,sector,row);
+
+      if(cl->fSlice == -1)
+       {
+         SetPadHit(i,-1);
+         SetTimeHit(i,-1);
+         continue;
+       }
+      if(cl->fSlice < 0 || cl->fSlice > 35)
+       {
+         cerr<<"AliL3ModelTrack::FillTrack : Slice out of range "<<cl->fSlice<<" on row "<<i<<endl;
+         exit(5);
+       }
+      
+      Float_t angle = 0;
+      
+      AliL3Transform::Local2GlobalAngle(&angle,cl->fSlice);
+      if(!CalculateReferencePoint(angle,AliL3Transform::Row2X(i)))
+       {
+         if(IsPresent(i))
+           {
+             cerr<<"AliL3ModelTrack::FillTrack : Track does not cross slice "<<cl->fSlice<<" row "<<i<<" Points "
+                 <<GetPointX()<<" "<<GetPointY()<<" "<<GetPointZ()<<endl;
+             Print();
+             exit(5);
+           }
+         SetPadHit(i,-1);
+         SetTimeHit(i,-1);
+         continue;
+       }
+      Float_t hit[3] = {GetPointX(),GetPointY(),GetPointZ()};
+      Int_t sector,row;
+      AliL3Transform::Slice2Sector(cl->fSlice,i,sector,row);
+      AliL3Transform::Global2Raw(hit,sector,row);
+
       SetPadHit(i,hit[1]);
       SetTimeHit(i,hit[2]);
+
+      Float_t crossingangle = GetCrossingAngle(i,cl->fSlice);
+      
+      SetCrossingAngleLUT(i,crossingangle);
+      CalculateClusterWidths(i,kTRUE);
+      
     }
 }
 
-
 void AliL3ModelTrack::SetPadHit(Int_t row,Float_t pad)
 {
   Int_t index = row-AliL3Transform::GetFirstRow(fPatch);
@@ -191,7 +324,6 @@ void AliL3ModelTrack::SetPadHit(Int_t row,Float_t pad)
       return;
     }
   fPad[index]=pad;
-  
 }
 
 void AliL3ModelTrack::SetTimeHit(Int_t row,Float_t time)
@@ -205,21 +337,40 @@ void AliL3ModelTrack::SetTimeHit(Int_t row,Float_t time)
   fTime[index]=time;
 }
 
+void AliL3ModelTrack::SetCrossingAngleLUT(Int_t row,Float_t angle)
+{
+  Int_t index = row-AliL3Transform::GetFirstRow(fPatch);
+  if(index < 0 || index > AliL3Transform::GetNRows(fPatch))
+    {
+      cerr<<"AliL3ModelTrack::SetCrossingAngle() : Wrong index: "<<index<<endl;
+      return;
+    }
+  fCrossingAngle[index]=angle;
+}
+
 void AliL3ModelTrack::SetOverlap(Int_t row,Int_t id)
 {
+
   Int_t index = row-AliL3Transform::GetFirstRow(fPatch);
   if(index < 0 || index > AliL3Transform::GetNRows(fPatch))
     {
       cerr<<"AliL3ModelTrack::SetOverlap() : Wrong index: "<<index<<endl;
       return;
     }
-  fOverlap[index]=id;
+  if(fNoverlaps[index] >= fMaxOverlaps) return;
+  fOverlap[index][fNoverlaps[index]++] = id;
 }
 
 Bool_t AliL3ModelTrack::IsPresent(Int_t row)
 {
   AliL3ClusterModel *cl = GetClusterModel(row);
-  return (Bool_t)cl->fPresent;
+  return (Bool_t)(cl->fPresent & 0x1);
+}
+
+Bool_t AliL3ModelTrack::IsSet(Int_t row)
+{
+  AliL3ClusterModel *cl = GetClusterModel(row);
+  return (Bool_t)(cl->fPresent & 0x2);
 }
 
 Int_t AliL3ModelTrack::GetNPads(Int_t row)
@@ -230,73 +381,82 @@ Int_t AliL3ModelTrack::GetNPads(Int_t row)
 
 Bool_t AliL3ModelTrack::GetPad(Int_t row,Float_t &pad)
 {
-  //(ftime - GetTimeHit(fNClusters))/fXYResidualQ;
-  //(fpad - GetPadHit(fNClusters))/fZResidualQ;
+  //(ftime - GetTimeHit(fNClusters))/AliL3DataCompressor::GetXYResidualStep();
+  //(fpad - GetPadHit(fNClusters))/AliL3DataCompressor::GetZResidualStep();
 
   AliL3ClusterModel *cl = GetClusterModel(row);
-  pad = cl->fDPad*fXYResidualQ + GetPadHit(row);
-
-  return (Bool_t)cl->fPresent;
+  Int_t patch = AliL3Transform::GetPatch(row);
+  pad = cl->fDPad*(AliL3DataCompressor::GetXYResidualStep()/AliL3Transform::GetPadPitchWidth(patch)) + GetPadHit(row);
+  
+  return IsPresent(row);
 }
 
 Bool_t AliL3ModelTrack::GetTime(Int_t row,Float_t &time)
 {
   AliL3ClusterModel *cl = GetClusterModel(row);
-  time = cl->fDTime*fZResidualQ + GetTimeHit(row);
-
-  return (Bool_t)cl->fPresent;
+  time = cl->fDTime*(AliL3DataCompressor::GetZResidualStep()/AliL3Transform::GetZWidth()) + GetTimeHit(row);
+  
+  return IsPresent(row);
 }
 
 Bool_t AliL3ModelTrack::GetClusterCharge(Int_t row,Int_t &charge)
 {
   AliL3ClusterModel *cl = GetClusterModel(row);
-  charge = (Int_t)cl->fDCharge;// + fClusterCharge;
+  charge = (Int_t)cl->fDCharge;// + AliL3DataCompressor::GetClusterCharge();
   
-  return (Bool_t)cl->fPresent;
+  return IsPresent(row);
 }
 
 Bool_t AliL3ModelTrack::GetXYWidth(Int_t row,Float_t &width)
 {
+  //cl->fDSigmaY2 = (sigmaY2 - GetParSigmaY2(row))/AliL3DataCompressor::GetXYWidthStep();
   AliL3ClusterModel *cl = GetClusterModel(row);
-  width = cl->fDSigmaY2*fXYWidthQ + GetParSigmaY2(row);
+  Int_t patch = AliL3Transform::GetPatch(row);
+  width = cl->fDSigmaY2*(AliL3DataCompressor::GetXYWidthStep()/pow(AliL3Transform::GetPadPitchWidth(patch),2)) + GetParSigmaY2(row);
 
-  return (Bool_t)cl->fPresent;
+  return IsPresent(row);
 }
 
 Bool_t AliL3ModelTrack::GetZWidth(Int_t row,Float_t &width)
 {
   AliL3ClusterModel *cl = GetClusterModel(row);
-  width = cl->fDSigmaZ2*fZWidthQ + GetParSigmaZ2(row);
+  width = cl->fDSigmaZ2*(AliL3DataCompressor::GetZWidthStep()/pow(AliL3Transform::GetZWidth(),2)) + GetParSigmaZ2(row);
 
-  return (Bool_t)cl->fPresent;
+  return IsPresent(row);
 }
 
 Bool_t AliL3ModelTrack::GetPadResidual(Int_t row,Float_t &res)
 {
   AliL3ClusterModel *cl = GetClusterModel(row);
   res = cl->fDPad;
-  return cl->fPresent;
+  return IsPresent(row);
 }
 
 Bool_t AliL3ModelTrack::GetTimeResidual(Int_t row,Float_t &res)
 {
   AliL3ClusterModel *cl = GetClusterModel(row);
   res = cl->fDTime;
-  return cl->fPresent;
+  return IsPresent(row);
 }
 
 Bool_t AliL3ModelTrack::GetXYWidthResidual(Int_t row,Float_t &res)
 {
   AliL3ClusterModel *cl = GetClusterModel(row);
   res = cl->fDSigmaY2;
-  return cl->fPresent;
+  return IsPresent(row);
 }
 
 Bool_t AliL3ModelTrack::GetZWidthResidual(Int_t row,Float_t &res)
 {
   AliL3ClusterModel *cl = GetClusterModel(row);
   res = cl->fDSigmaZ2;
-  return cl->fPresent;
+  return IsPresent(row);
+}
+
+Int_t AliL3ModelTrack::GetSlice(Int_t row)
+{
+  AliL3ClusterModel *cl = GetClusterModel(row);
+  return cl->fSlice;
 }
 
 Float_t AliL3ModelTrack::GetPadHit(Int_t row)
@@ -321,11 +481,55 @@ Float_t AliL3ModelTrack::GetTimeHit(Int_t row)
   return fTime[index];
 }
 
-Int_t AliL3ModelTrack::GetOverlap(Int_t row)
+Float_t AliL3ModelTrack::GetCrossingAngleLUT(Int_t row)
 {
   Int_t index = row-AliL3Transform::GetFirstRow(fPatch);
   if(index < 0 || index > AliL3Transform::GetNRows(fPatch))
     {
+      cerr<<"AliL3ModelTrack::GetCrossingAngleLUT() : Wrong index: "<<index<<" row "<<row<<endl;
+      return 0;
+    }
+  return fCrossingAngle[index];
+}
+
+Float_t AliL3ModelTrack::GetParSigmaY2(Int_t row)
+{
+  Int_t index = row-AliL3Transform::GetFirstRow(fPatch);
+  if(index < 0 || index > AliL3Transform::GetNRows(fPatch))
+    {
+      cerr<<"AliL3ModelTrack::GetParSigmaY2() : Wrong index: "<<index<<" row "<<row<<endl;
+      return 0;
+    }
+  return fParSigmaY2[index];
+}
+
+Float_t AliL3ModelTrack::GetParSigmaZ2(Int_t row)
+{
+  Int_t index = row-AliL3Transform::GetFirstRow(fPatch);
+  if(index < 0 || index > AliL3Transform::GetNRows(fPatch))
+    {
+      cerr<<"AliL3ModelTrack::GetParSigmaZ2() : Wrong index: "<<index<<" row "<<row<<endl;
+      return 0;
+    }
+  return fParSigmaZ2[index];
+}
+
+Int_t AliL3ModelTrack::GetNOverlaps(Int_t row)
+{
+  Int_t index = row - AliL3Transform::GetFirstRow(fPatch);
+  if(index < 0 || index > AliL3Transform::GetNRows(fPatch))
+    {
+      cerr<<"AliL3ModelTrack::GetOverlap() : Wrong index: "<<index<<endl;
+      return 0;
+    }
+  return fNoverlaps[index];
+}
+
+Int_t *AliL3ModelTrack::GetOverlaps(Int_t row)
+{
+  Int_t index = row - AliL3Transform::GetFirstRow(fPatch);
+  if(index < 0 || index > AliL3Transform::GetNRows(fPatch))
+    {
       cerr<<"AliL3ModelTrack::GetOverlap() : Wrong index: "<<index<<endl;
       return 0;
     }
@@ -344,99 +548,64 @@ AliL3ClusterModel *AliL3ModelTrack::GetClusterModel(Int_t row)
   return &fClusters[index];
 }
 
-void AliL3ModelTrack::Print()
+void AliL3ModelTrack::Print(Bool_t everything)
 {
   //Print info
 
-  cout<<"----Slice "<<fSlice<<" Patch "<<fPatch<<"----"<<endl;
   cout<<"First point "<<GetFirstPointX()<<" "<<GetFirstPointY()<<" "<<GetFirstPointZ()<<endl;
   cout<<"Last point "<<GetLastPointX()<<" "<<GetLastPointY()<<" "<<GetLastPointZ()<<endl;
   cout<<"Pt "<<GetPt()<<" kappa "<<GetKappa()<<" tgl "<<GetTgl()<<" psi "<<GetPsi()<<" charge "<<GetCharge()<<endl;
   cout<<"Center "<<GetCenterX()<<" "<<GetCenterY()<<endl<<endl;
+  if(!everything)
+    return;
   cout<<"NHits "<<GetNClusters()<<endl;
-  cout<<"Clusters:"<<endl;
 
+  cout<<"Clusters:"<<endl;
+  Int_t origslice=-1,counter=0;
+  Float_t fpad,ftime;
   for(Int_t i=AliL3Transform::GetFirstRow(fPatch); i<=AliL3Transform::GetLastRow(fPatch); i++)
     {
       AliL3ClusterModel *cl = GetClusterModel(i);
       
-      if(!cl->fPresent)
-       cout<<i<<" Empty"<<" Padcrossing "<<GetPadHit(i)<<" Timecrossing "<<GetTimeHit(i)<<" ";
+      if(!IsPresent(i))
+       cout<<i<<" Empty"<<" Slice "<<cl->fSlice<<" Padcrossing "<<GetPadHit(i)<<" Timecrossing "<<GetTimeHit(i)<<" ";
       else
        {
-         cout<<i<<" Dpad "<<cl->fDPad<<" Dtime "<<cl->fDTime<<" Dcharge "<<cl->fDCharge;
-         cout<<" DsigmaY2 "<<cl->fDSigmaY2<<" DsigmaZ2 "<<cl->fDSigmaZ2;
-         cout<<" Padcrossing "<<GetPadHit(i)<<" Timecrossing "<<GetTimeHit(i)<<" ";
-         cout<<"Number of pads "<<GetNPads(i)<<" Overlapping index "<<GetOverlap(i);
+         GetPad(i,fpad);
+         GetTime(i,ftime);
+         if(counter==0)
+           origslice=cl->fSlice;
+         else if(cl->fSlice != origslice)
+           cout<<"Change in slice "<<cl->fSlice<<" "<<origslice<<endl;
+         cout<<i<<" Slice "<<cl->fSlice<<" Dpad "<<cl->fDPad<<" Dtime "<<cl->fDTime<<" Dcharge "<<cl->fDCharge;
+         cout<<" sigmaY2 "<<GetParSigmaY2(i)<<" sigmaZ2 "<<GetParSigmaZ2(i);
+         cout<<" Pad "<<fpad<<" padhit "<<GetPadHit(i)<<" Time "<<ftime<<" timehit "<<GetTimeHit(i)<<" ";
+         cout<<"Number of pads "<<GetNPads(i)<<" Overlaps "<<GetNOverlaps(i);
+         counter++;
        }
       cout<<endl;
     }
 }
 
-Double_t AliL3ModelTrack::GetParSigmaY2(Int_t row)
+void AliL3ModelTrack::SetClusterLabel(Int_t row,Int_t *trackID)
 {
-  //Calculate the expected cluster width, based on the track parameters and drift distance.
-
-  Float_t pad,time;
-  if(!GetTime(row,time) || !GetPad(row,pad))
-    return -1;
-  
-  Float_t xyz[3];
-  Int_t sector,padrow;
-  AliL3Transform::Slice2Sector(fSlice,row,sector,padrow);
-  AliL3Transform::Raw2Local(xyz,sector,padrow,pad,time);
-  
-  //Calculate the drift length:
-  Double_t drift;
-  if(xyz[2] > 0)
-    drift = AliL3Transform::GetZLength() - xyz[2];
-  else
-    drift = AliL3Transform::GetZLength() + xyz[2];
-  
-  Double_t prf = AliL3Transform::GetPRFSigma(fPatch);
-  Double_t diffT = AliL3Transform::GetDiffT();
-  Double_t padlength = AliL3Transform::GetPadLength(row);
-  Double_t anode = AliL3Transform::GetAnodeWireSpacing();
-  Double_t beta = GetCrossingAngle(row);
-  
-  Double_t sigmaY2 = prf*prf + diffT*diffT*drift + padlength*padlength*tan(beta)*tan(beta)/12 + anode*anode*pow( tan(beta)-0.15, 2)/12;
-  
-  //Convert back to raw coordinates.
-  sigmaY2 = sigmaY2/pow(AliL3Transform::GetPadPitchWidth(fPatch),2);
-  return sigmaY2;
+#ifdef do_mc
+  AliL3ClusterModel *cl = GetClusterModel(row);
+  cl->fTrackID[0] = trackID[0];
+  cl->fTrackID[1] = trackID[1];
+  cl->fTrackID[2] = trackID[2];
+#endif
+  return;
 }
 
-Double_t AliL3ModelTrack::GetParSigmaZ2(Int_t row)
+void AliL3ModelTrack::GetClusterLabel(Int_t row,Int_t *trackID)
 {
-  //Calculate the expected cluster width, based on the track parameters and drift distance.
-  
-  Float_t pad,time;
-  if(!GetTime(row,time) || !GetPad(row,pad))
-    return -1;
-  
-  Float_t xyz[3];
-  Int_t sector,padrow;
-  AliL3Transform::Slice2Sector(fSlice,row,sector,padrow);
-  AliL3Transform::Raw2Local(xyz,sector,padrow,pad,time);
-  
-  //Calculate the drift length:
-  Double_t drift;
-  if(xyz[2] > 0)
-    drift = AliL3Transform::GetZLength() - xyz[2];
-  else
-    drift = AliL3Transform::GetZLength() + xyz[2];
-  
-  Double_t sigma0 = AliL3Transform::GetTimeSigma();
-  Double_t diffL = AliL3Transform::GetDiffL();
-  Double_t padlength = AliL3Transform::GetPadLength(row);
-  Double_t tanl = GetTgl();
-  
-  Double_t sigmaZ2 = sigma0*sigma0 + diffL*diffL*drift + padlength*padlength * tanl*tanl/12;
-  
-  //Convert back to raw coodinates:
-  sigmaZ2 = sigmaZ2/pow(AliL3Transform::GetZWidth(),2);
-  
-  return sigmaZ2;
-  
+#ifdef do_mc
+  AliL3ClusterModel *cl = GetClusterModel(row);
+  trackID[0] = cl->fTrackID[0];
+  trackID[1] = cl->fTrackID[1];
+  trackID[2] = cl->fTrackID[2];
+#endif
+  return;
 }
 
index c8228f6..40c42fb 100644 (file)
@@ -1,3 +1,5 @@
+// @(#) $Id$
+
 #ifndef AliL3Model_Track
 #define AliL3Model_Track
 
@@ -12,17 +14,14 @@ class AliL3ModelTrack : public AliL3Track {
   AliL3ClusterModel *fClusters; //!
   AliL3TrackModel *fTrackModel; //!
   Short_t fNClusters;
-  Int_t *fOverlap; //!
-  Float_t fXYResidualQ; //Quantization steps.
-  Float_t fZResidualQ;
-  Float_t fXYResolution;
-  Float_t fZResolution;
-  Float_t fXYWidthQ;
-  Float_t fZWidthQ;
-  Int_t fSlice;
+  Int_t fMaxOverlaps;
+  Int_t *fNoverlaps; //!
+  Int_t **fOverlap; //!
+  Float_t *fParSigmaY2;    //!
+  Float_t *fParSigmaZ2;    //!
+  Float_t *fCrossingAngle; //!
   Int_t fPatch;
-  Int_t fLabel;
-  
+
   //Crossing points with padrows
   Float_t *fPad; //!
   Float_t *fTime; //!
@@ -32,27 +31,36 @@ class AliL3ModelTrack : public AliL3Track {
   virtual ~AliL3ModelTrack();
   
   void Init(Int_t slice,Int_t patch);
+  void CalculateClusterWidths(Int_t row,Bool_t parametrize=kFALSE);
   void SetCluster(Int_t row,Float_t dpad,Float_t dtime,Float_t charge,Float_t sigmaY2,Float_t sigmaZ2,Int_t npads);
   void FillModel();
   void FillTrack();
-  void Print();
-  
+  void Print(Bool_t everything=kTRUE);
+  void Set(AliL3Track *tpt);
+
   void SetPadHit(Int_t row,Float_t f);
   void SetTimeHit(Int_t row,Float_t f);
+  void SetCrossingAngleLUT(Int_t row,Float_t angle);
   void SetOverlap(Int_t row,Int_t id);
-  void SetXYResolution(Float_t f) {fXYResolution=f;}
-  void SetZResolution(Float_t f) {fZResolution=f;}
-  void SetLabel(Int_t i) {fLabel = i;}
+  void SetClusterLabel(Int_t row,Int_t *trackID);
+  void SetNClusters(Int_t i) {fNClusters = i;}
+  
   Int_t GetNPresentClusters();
   Bool_t IsPresent(Int_t row);
+  Bool_t IsSet(Int_t row);
   
   AliL3ClusterModel *GetClusters() {return fClusters;}
   AliL3TrackModel *GetModel() {return fTrackModel;}
   AliL3ClusterModel *GetClusterModel(Int_t row);
-  Int_t GetOverlap(Int_t row);
+  Int_t *GetOverlaps(Int_t row);
+  Int_t GetNOverlaps(Int_t row);
   Int_t GetNPads(Int_t row);
+  Int_t GetSlice(Int_t row);
   Float_t GetPadHit(Int_t row);
   Float_t GetTimeHit(Int_t row);
+  Float_t GetCrossingAngleLUT(Int_t row);
+  Float_t GetParSigmaY2(Int_t row);
+  Float_t GetParSigmaZ2(Int_t row);
   Bool_t GetPad(Int_t row,Float_t &pad);
   Bool_t GetTime(Int_t row,Float_t &time);
   Bool_t GetClusterCharge(Int_t row,Int_t &charge);
@@ -63,11 +71,8 @@ class AliL3ModelTrack : public AliL3Track {
   Bool_t GetXYWidthResidual(Int_t row,Float_t &res);
   Bool_t GetZWidthResidual(Int_t row,Float_t &res);
   Int_t GetNClusters() {return fNClusters;}
-  Int_t GetLabel() {return fLabel;}
-
-  Double_t GetParSigmaY2(Int_t row);
-  Double_t GetParSigmaZ2(Int_t row);
-  
+  void GetClusterLabel(Int_t row,Int_t *trackID);
+    
   ClassDef(AliL3ModelTrack,1)
 
 };
index b0e1ed4..f4553ab 100644 (file)
@@ -1,19 +1,22 @@
-//$Id$
+// @(#) $Id$
 
 // Author: Anders Vestbo <mailto:vestbo@fi.uib.no>
-//*-- Copyright &copy ASV
+//*-- Copyright &copy ALICE HLT Group
 
 #include "AliL3StandardIncludes.h"
 
+#include "AliL3Logging.h"
 #include "AliL3Modeller.h"
 #include "AliL3MemHandler.h"
-#ifdef use_aliroot
-#include "AliL3FileHandler.h"
-#endif
 #include "AliL3TrackArray.h"
 #include "AliL3ModelTrack.h"
 #include "AliL3DigitData.h"
 #include "AliL3Transform.h"
+#include "AliL3SpacePointData.h"
+
+#ifdef use_aliroot
+#include "AliL3FileHandler.h"
+#endif
 
 #if GCCVERSION == 3
 using namespace std;
@@ -35,10 +38,13 @@ AliL3Modeller::AliL3Modeller()
 {
   fMemHandler=0;
   fTracks=0;
+  fRow=0;
   fTrackThreshold=0;
   SetOverlap();
   SetTrackThreshold();
   SetSearchRange();
+  SetMaxClusterRange(0,0);
+  fDebug=kFALSE;
 }
 
 
@@ -48,12 +54,15 @@ AliL3Modeller::~AliL3Modeller()
     delete fMemHandler;
   if(fTracks)
     delete fTracks;
+  if(fRow)
+    delete [] fRow;
 }
 
 void AliL3Modeller::Init(Int_t slice,Int_t patch,Char_t *trackdata,Char_t *path,Bool_t houghtracks,Bool_t binary)
 {
   fSlice = slice;
   fPatch = patch;
+  fHoughTracks=houghtracks;
 
   sprintf(fPath,"%s",path);
   
@@ -61,8 +70,11 @@ void AliL3Modeller::Init(Int_t slice,Int_t patch,Char_t *trackdata,Char_t *path,
   
   Char_t fname[100];
   AliL3MemHandler *file = new AliL3MemHandler();
-  //sprintf(fname,"%s/tracks_tr_%d_0.raw",trackdata,fSlice); //output tracks from the tracker (no merging)
-  sprintf(fname,"%s/tracks_ho_%d.raw",trackdata,fSlice);
+  if(!houghtracks)
+    sprintf(fname,"%s/tracks_tr_%d_0.raw",trackdata,fSlice); //output tracks from the tracker (no merging)
+  else 
+    sprintf(fname,"%s/tracks_ho_%d.raw",trackdata,fSlice);
+  //sprintf(fname,"%s/tracks_ho_%d_%d.raw",trackdata,fSlice,fPatch);
   if(!file->SetBinaryInput(fname))
     {
       cerr<<"AliL3Modeller::Init : Error opening trackfile: "<<fname<<endl;
@@ -72,7 +84,6 @@ void AliL3Modeller::Init(Int_t slice,Int_t patch,Char_t *trackdata,Char_t *path,
   file->CloseBinaryInput();
   delete file;
   
-
   if(!houghtracks)
     fTracks->QSort();
   
@@ -89,6 +100,12 @@ void AliL3Modeller::Init(Int_t slice,Int_t patch,Char_t *trackdata,Char_t *path,
       track->CalculateHelix();
     }    
   
+  Int_t ntimes = AliL3Transform::GetNTimeBins()+1;
+  Int_t npads = AliL3Transform::GetNPads(AliL3Transform::GetLastRow(fPatch))+1;//Max num of pads.
+  Int_t bounds = ntimes*npads;
+  fRow = new Digit[bounds];
+  
+  
   UInt_t ndigits=0;
   AliL3DigitRowData *digits=0;
 #ifdef use_aliroot
@@ -98,7 +115,7 @@ void AliL3Modeller::Init(Int_t slice,Int_t patch,Char_t *trackdata,Char_t *path,
     {
       sprintf(fname,"%s/digitfile.root",fPath);
       fMemHandler->SetAliInput(fname);
-      digits = fMemHandler->AliDigits2Memory(ndigits);
+      digits = fMemHandler->AliAltroDigits2Memory(ndigits);
     }
   else
     {
@@ -135,7 +152,8 @@ void AliL3Modeller::Init(Int_t slice,Int_t patch,Char_t *trackdata,Char_t *path,
 
 void AliL3Modeller::FindClusters()
 {
-  cout<<"AliL3Modeller::FindClusters : Processing slice "<<fSlice<<" patch "<<fPatch<<endl;
+  if(fDebug)
+    cout<<"AliL3Modeller::FindClusters : Processing slice "<<fSlice<<" patch "<<fPatch<<endl;
   if(!fTracks)
     {
       cerr<<"AliL3Modeller::Process : No tracks"<<endl;
@@ -150,20 +168,20 @@ void AliL3Modeller::FindClusters()
   AliL3DigitRowData *rowPt = fRowData;
   AliL3DigitData *digPt=0;
 
-  Int_t ntimes = AliL3Transform::GetNTimeBins()+1;
-  Int_t npads = AliL3Transform::GetNPads(AliL3Transform::GetLastRow(fPatch))+1;//Max num of pads.
-  Int_t bounds = ntimes*npads;
-  Digit *row = new Digit[bounds];
-  
-  Int_t seq_charge;
-  Int_t pad,time,index;
+  Int_t pad,time;
   Short_t charge;
   Cluster cluster;
-
+  ClusterRegion region[200];
+  
   for(Int_t i=AliL3Transform::GetFirstRow(fPatch); i<=AliL3Transform::GetLastRow(fPatch); i++)
     {
+      if(i != (Int_t)rowPt->fRow)
+       {
+         cerr<<"AliL3Modeller::FindClusters : Mismatching rownumbering "<<i<<" "<<rowPt->fRow<<endl;
+         return;
+       }
       fCurrentPadRow = i;
-      memset((void*)row,0,ntimes*npads*sizeof(Digit));
+      memset((void*)fRow,0,(AliL3Transform::GetNTimeBins()+1)*(AliL3Transform::GetNPads(i)+1)*sizeof(Digit));
       digPt = (AliL3DigitData*)rowPt->fDigitData;
       //cout<<"Loading row "<<i<<" with "<<(Int_t)rowPt->fNDigit<<" digits"<<endl;
       for(UInt_t j=0; j<rowPt->fNDigit; j++)
@@ -171,8 +189,8 @@ void AliL3Modeller::FindClusters()
          pad = digPt[j].fPad;
          time = digPt[j].fTime;
          charge = digPt[j].fCharge;
-         row[ntimes*pad+time].fCharge = charge;
-         row[ntimes*pad+time].fUsed = kFALSE;
+         fRow[(AliL3Transform::GetNTimeBins()+1)*pad + time].fCharge = charge;
+         fRow[(AliL3Transform::GetNTimeBins()+1)*pad + time].fUsed = kFALSE;
          //cout<<"Row "<<i<<" pad "<<pad<<" time "<<time<<" charge "<<charge<<endl;
        }
       
@@ -181,86 +199,40 @@ void AliL3Modeller::FindClusters()
          AliL3ModelTrack *track = (AliL3ModelTrack*)fTracks->GetCheckedTrack(k);
          if(!track) continue;
          
-         if(track->GetPadHit(i)<0 || track->GetTimeHit(i)<0 || track->GetOverlap(i)>=0)
+         if(track->GetPadHit(i)<0 || track->GetTimeHit(i)<0 || track->GetNOverlaps(i)>0)//track->GetOverlap(i)>=0)
            {
-             track->SetCluster(i,0,0,0,0,0,0); //The track has left the patch.
+             //cout<<"Track "<<k<<" is empty on row "<<i<<" "<<track->GetPadHit(i)<<" "<<track->GetTimeHit(i)<<endl;
+             track->SetCluster(i,0,0,0,0,0,0); //The track has left the patch, or it is overlapping
              continue;
            }
          
-         Int_t hitpad = (Int_t)rint(track->GetPadHit(i));
-         Int_t hittime = (Int_t)rint(track->GetTimeHit(i));
-
-         if(!CheckCluster(row,hitpad,hittime)) //Not a good cluster.
+         Int_t minpad,mintime,maxpad,maxtime;
+         minpad = mintime = 999;
+         maxpad = maxtime = 0;
+         
+         memset(&cluster,0,sizeof(Cluster));
+         LocateCluster(track,region,minpad,maxpad);//,mintime,maxtime);
+         if(maxpad - minpad + 1 > fMaxPads ||  // maxtime - mintime + 1 > fMaxTimebins ||
+            maxpad - minpad < 1)               //  || maxtime - mintime < 1)
            {
-             track->SetCluster(i,0,0,0,0,0,0); 
+             //cout<<"Cluster not found on row "<<i<<" maxpad "<<maxpad<<" minpad "<<minpad<<" maxtime "<<maxtime<<" mintime "<<mintime
+             //  <<" padhit "<<track->GetPadHit(i)<<" timehit "<<track->GetTimeHit(i)<<endl;
+               
+             track->SetCluster(i,0,0,0,0,0,0);
              continue;
            }
-
-         //cout<<"Checking track on row "<<i<<" with pad "<<hitpad<<" time "<<hittime<<endl;
-         pad = hitpad;
-         time = hittime;
-
-         Int_t padsign=-1;
-         Int_t timesign=-1;
          
-         memset(&cluster,0,sizeof(Cluster));
-         //cout<<"Processing padrow "<<i<<" with hittime "<<hittime<<" hitpad "<<hitpad<<" charge "<<row[ntimes*pad + time].fCharge<<" index "<<ntimes*pad + time<<endl;
          Int_t npads=0;
-         Int_t last_mean = hittime;
-         while(1)//Process this padrow
+         for(pad=minpad; pad<=maxpad; pad++)
            {
-             if(pad < 0 || pad >= AliL3Transform::GetNPads(i)) 
-               {
-                 //cout<<"Pad = "<<pad<<" on row "<<i<<endl;
-                 FillCluster(track,&cluster,i,npads);
-                 break;
-               }
-             seq_charge=0;
-             timesign=-1;
-             time = hittime;
-             
-             while(1) //Process sequence on this pad:
+             Int_t ntimes=0;
+             for(time=region[pad].mintime; time<=region[pad].maxtime; time++)
                {
-                 if(time < 0 || time >= AliL3Transform::GetNTimeBins()) 
-                   break;
-               
-                 index = ntimes*pad + time;
-                 if(index < 0 || index >= bounds)
-                   {
-                     cerr<<"AliL3Modeller::FindClusters : Index out of range : "<<index
-                       <<" on row "<<i<<" pad "<<pad<<" time "<<time<<endl;
-                     break;
-                   }
-                 
-                 charge = row[index].fCharge;
-                 
-                 if(charge==0) //Empty timebin, so try and expand the search within the limits on this pad
-                   {
-                     if(seq_charge==0 && abs(time-hittime) <= fTimeSearch)//No sequence yet, keep looking
-                       {
-                         if(timesign==-1)
-                           time--;
-                         else
-                           time++;
-                         continue;
-                       }
-                     else if(timesign==-1) //Switch search direction
-                       {
-                         time = hittime + 1;
-                         timesign = 1;
-                         continue;
-                       }
-                     else //ok, boundary reached, this pad is done.
-                       break;
-                   }
-                 
-                 if(row[ntimes*pad+time].fUsed==kTRUE) //Don't use digits several times. This leads to mult. rec.tracks.
-                   {
-                     time += timesign;
-                     continue;
-                   }
-                 
-                 seq_charge += charge;
+                 charge = fRow[(AliL3Transform::GetNTimeBins()+1)*pad+time].fCharge;
+                 if(!charge) continue;
+                 if(fRow[(AliL3Transform::GetNTimeBins()+1)*pad+time].fUsed == kTRUE)
+                   continue;
+                 ntimes++;
                  
                  //Update the cluster parameters with this timebin
                  cluster.fTime += time*charge;
@@ -268,52 +240,19 @@ void AliL3Modeller::FindClusters()
                  cluster.fCharge += charge;
                  cluster.fSigmaY2 += pad*pad*charge;
                  cluster.fSigmaZ2 += time*time*charge;
-                 
-                 row[ntimes*pad+time].fUsed = kTRUE;
-                 time += timesign;
-               }
-             
-             //Always compare with the current mean in time of the cluster under construction.
-             if(cluster.fCharge)
-               last_mean = (Int_t)rint((Float_t)(cluster.fTime/cluster.fCharge));
-             
-             if(seq_charge)//There was something on this pad, so keep looking on the neighbouring pad
-               {
-                 pad += padsign;
-                 npads++;
-               }
-             else
-               {
-                 if(cluster.fCharge==0 && abs(pad-hitpad) <= fPadSearch && pad > 0)
-                   {
-                     if(padsign==-1)
-                       pad--;
-                     else
-                       pad++;
-                     continue;
-                   }
-                 else if(padsign==-1)
-                   {
-                     pad = hitpad + 1;
-                     padsign = 1;
-                     continue;
-                   }
-                 else
-                   {
-                     FillCluster(track,&cluster,i,npads);
-                     break;
-                   }
+                 fRow[(AliL3Transform::GetNTimeBins()+1)*pad+time].fUsed = kTRUE;
                }
+             if(ntimes)
+               npads++;
            }
-         //cout<<"done"<<endl;
+         FillCluster(track,&cluster,i,npads);
        }
-      FillZeros(rowPt,row);
+      FillZeros(rowPt);
       fMemHandler->UpdateRowPointer(rowPt);
     }
-  delete [] row;
   //cout<<"done processing"<<endl;
   
-  
+
   //Debug:
   for(Int_t i=0; i<fTracks->GetNTracks(); i++)
     {
@@ -325,108 +264,162 @@ void AliL3Modeller::FindClusters()
   
 }
 
-Bool_t AliL3Modeller::CheckCluster(Digit *row,Int_t hitpad,Int_t hittime)
+
+void AliL3Modeller::LocateCluster(AliL3ModelTrack *track,ClusterRegion *region,Int_t &padmin,Int_t &padmax)
 {
-  Int_t ntimes = AliL3Transform::GetNTimeBins()+1;
-  Bool_t seq_was_falling=kFALSE;
-  Int_t last_seq_charge=0;
-  Int_t cluster_charge=0;
-  Int_t time,pad,charge,padsign=-1,timesign=-1;
-  time = hittime;
-  pad = hitpad;
-  Int_t npads=0;
-  //cout<<"Checking cluster "<<hitpad<<" hittime "<<hittime<<endl;
+  //Set the cluster range
+  //This method searches for _all_ nonzeros timebins which are neigbours.
+  //This makes it rather impractical when dealing with high occupancy,
+  //because then you might have very large "cluster" areas from low
+  //pt electrons/noise. 
+  
+  Int_t row=fCurrentPadRow,charge,prtmin=0,prtmax=999;
+  Int_t hitpad = (Int_t)rint(track->GetPadHit(row));
+  Int_t hittime = (Int_t)rint(track->GetTimeHit(row));
+  Int_t tmin = hittime;
+  Int_t tmax = tmin;
+    
+  Int_t clustercharge=0;
+  Int_t pad=hitpad;
+  Bool_t pm = kTRUE;
+  Int_t npads=0,middlemax=tmax,middlemin=tmin;
   while(1)
     {
-      Bool_t last_was_falling=kFALSE;
-      Int_t last_charge=0;
-      Int_t seq_charge=0;
+      Bool_t padpr=kFALSE;
+      Int_t time = hittime;
+      Bool_t tm = kTRUE;
+      if(pad < 0)
+       {
+         padmin = 0;
+         pad = hitpad+1;
+         pm = kFALSE;
+         prtmin = middlemin;
+         prtmax = middlemax;
+         continue;
+       }
+      else if(pad >= AliL3Transform::GetNPads(row))
+       {
+         padmax = AliL3Transform::GetNPads(row)-1;
+         break;
+       }
+      
+      tmin = 999;
+      tmax = 0;
+      //if(row==0)
+      //cout<<"Starting to look in pad "<<pad<<" time "<<time<<endl;
       while(1)
        {
-         
-         charge = row[(ntimes*pad+time)].fCharge;
-         //cout<<"Charge "<<charge<<" on pad "<<pad<<" time "<<time<<endl;
-         if(charge==0)
+         if(time < 0)
            {
-             if(seq_charge==0 && abs(time-hittime) <= fTimeSearch)
+             time = hittime+1;
+             tm = kFALSE;
+           }
+         else if(time >= AliL3Transform::GetNTimeBins())
+           {
+             //timemax = AliL3Transform::GetNTimeBins()-1;
+             break;
+           }
+         charge = fRow[(AliL3Transform::GetNTimeBins()+1)*pad+time].fCharge;
+         //if(row==0)
+         //cout<<"charge "<<charge<<" at pad "<<pad<<" time "<<time<<endl;
+         if(charge>0)
+           {
+             clustercharge+=charge;
+             padpr = kTRUE;
+             if(time < tmin)
+               tmin = time;
+             if(time > tmax)
+               tmax = time;
+             if(tm)
+               time--;
+             else
+               time++;
+           }
+         else
+           {
+             if(tm)
                {
-                 if(timesign==-1)
+                 //if(abs(time - hittime) < fTimeSearch && padpr == kFALSE)//Keep looking
+                 if(time > prtmin && npads!=0)
                    time--;
                  else
-                   time++;
-                 continue;
-               }
-             else if(timesign==-1)
-               {
-                 last_charge = row[(ntimes*hitpad+hittime)].fCharge;
-                 time = hittime+1;
-                 timesign=1;
-                 if(last_charge < row[(ntimes*hitpad+(hittime-1))].fCharge)
-                   last_was_falling=kTRUE;
-                 else
-                   last_was_falling=kFALSE;
-                 continue;
+                   {
+                     time = hittime+1;
+                     tm=kFALSE;
+                   }
                }
+             //else if(abs(time-hittime) < fTimeSearch && padpr == kFALSE)//Keep looking
+             else if(time < prtmax && npads != 0)
+               time++;
              else
                break;
            }
-
-         if(charge > last_charge)
-           {
-             if(last_was_falling) //This is a overlapping cluster.
-               return kFALSE;
-           }
-         else
-           last_was_falling = kTRUE;
-
-         cluster_charge+=charge;
-         seq_charge += charge;
-         last_charge = charge;
-         time += timesign;
        }
+      if(npads==0)
+       {
+         middlemax = tmax;
+         middlemin = tmin;
+       }
+      //      if(row==0)
+      //cout<<"tmax "<<tmax<<" tmin "<<tmin<<" prtmin "<<prtmin<<" ptrmax "<<prtmax<<endl;
       
-      if(seq_charge)
+      if(padpr && tmax >= prtmin && tmin <= prtmax)//Sequence is overlapping with the previous
        {
-         pad += padsign;
+         //if(row==0)
+         //cout<<"Incrementing pad "<<endl;
          npads++;
+         
+         region[pad].mintime=tmin;
+         region[pad].maxtime=tmax;
+         
+         /*
+         if(tmin < timemin)
+           timemin=tmin;
+         if(tmax > timemax)
+           timemax=tmax;
+         */
+         if(pad < padmin)
+           padmin = pad;
+         if(pad > padmax)
+           padmax = pad;
+         if(pm)
+           pad--;
+         else
+           pad++;
+         
+         prtmin = tmin;
+         prtmax = tmax;
        }
       else
        {
-         if(cluster_charge==0 && abs(pad-hitpad)<=fPadSearch && pad > 0)
+         if(pm)
            {
-             if(padsign==-1)
+             if(abs(pad-hitpad)<fPadSearch && clustercharge == 0)
                pad--;
              else
-               pad++;
-             continue;
+               {
+                 //if(row==0)
+                 //cout<<"Setting new pad "<<hitpad+1<<endl;
+                 pad = hitpad+1;
+                 pm = kFALSE;
+                 prtmin = middlemin;
+                 prtmax = middlemax;
+                 continue;
+               }
            }
-         else if(padsign==-1)
+         else 
            {
-             pad = hitpad+1;
-             padsign = 1;
-             seq_was_falling=kFALSE;
-             continue;
+             if(abs(pad-hitpad)<fPadSearch && clustercharge==0)
+               pad++;
+             else
+               break;
            }
-         else
-           break;
        }
-      
-      if(seq_charge > last_seq_charge)
-       {
-         if(seq_was_falling)
-           return kFALSE;
-         else
-           seq_was_falling=kTRUE;
-       }
-      last_seq_charge = seq_charge;
     }
   
-  if(npads < 2 || npads > 8)
-    return kFALSE;
-  else
-    return kTRUE;
 }
 
+
 void AliL3Modeller::FillCluster(AliL3ModelTrack *track,Cluster *cluster,Int_t row,Int_t npads)
 {
   if(cluster->fCharge==0)
@@ -440,20 +433,34 @@ void AliL3Modeller::FillCluster(AliL3ModelTrack *track,Cluster *cluster,Int_t ro
   Float_t sigmaY2,sigmaZ2;
   CalcClusterWidth(cluster,sigmaY2,sigmaZ2);
   track->SetCluster(row,fpad,ftime,fcharge,sigmaY2,sigmaZ2,npads);
+#ifdef do_mc
+  Int_t trackID[3];
+  GetTrackID((Int_t)rint(fpad),(Int_t)rint(ftime),trackID);
+  track->SetClusterLabel(row,trackID);
+#endif
 }
 
-void AliL3Modeller::FillZeros(AliL3DigitRowData *rowPt,Digit *row)
+
+
+void AliL3Modeller::FillZeros(AliL3DigitRowData *rowPt,Bool_t reversesign)
 {
   //Fill zero where data has been used.
-  
-  Int_t ntimes = AliL3Transform::GetNTimeBins()+1;
+
   AliL3DigitData *digPt = (AliL3DigitData*)rowPt->fDigitData;
   for(UInt_t j=0; j<rowPt->fNDigit; j++)
     {
       Int_t pad = digPt[j].fPad;
       Int_t time = digPt[j].fTime;
-      if(row[ntimes*pad+time].fUsed==kTRUE)
-       digPt[j].fCharge = 0;
+      if(fRow[(AliL3Transform::GetNTimeBins()+1)*pad+time].fUsed==kTRUE)
+       {
+         if(reversesign)
+           {
+             if(digPt[j].fCharge < 1024)
+               digPt[j].fCharge += 1024;
+           }
+         else
+           digPt[j].fCharge = 0;
+       }
     }
 }
 
@@ -520,6 +527,7 @@ void AliL3Modeller::WriteRemaining()
   Char_t fname[100];
   AliL3MemHandler *mem = new AliL3MemHandler();
   sprintf(fname,"%s/comp/remains_%d_%d.raw",fPath,fSlice,fPatch);
+  mem->Init(fSlice,fPatch);
   mem->SetBinaryOutput(fname);
   mem->Memory2CompBinary((UInt_t)AliL3Transform::GetNRows(fPatch),(AliL3DigitRowData*)data);
   mem->CloseBinaryOutput();
@@ -527,10 +535,33 @@ void AliL3Modeller::WriteRemaining()
   delete [] data;
 }
 
+void AliL3Modeller::RemoveBadTracks()
+{
+  //Remove tracsk which should not be included in the compression scheme.
+
+  for(Int_t i=0; i<fTracks->GetNTracks(); i++)
+    {
+      AliL3ModelTrack *track = (AliL3ModelTrack*)fTracks->GetCheckedTrack(i);
+      if(!track) continue;
+
+      if(track->GetPt() < 0.08)
+       {
+         fTracks->Remove(i);
+         continue;
+       }
+
+      if(!fHoughTracks)
+       if(track->GetNHits() < fTrackThreshold)
+         fTracks->Remove(i);
+    }
+  fTracks->Compress();
+  
+}
 
 void AliL3Modeller::CalculateCrossingPoints()
 {
-  //cout<<"Calculating crossing points on "<<fTracks->GetNTracks()<<" tracks"<<endl;
+  if(fDebug)
+    cout<<"Calculating crossing points on "<<fTracks->GetNTracks()<<" tracks"<<endl;
   if(!fTracks)
     {
       cerr<<"AliL3Modeller::CalculateCrossingPoints(): No tracks"<<endl;
@@ -549,11 +580,11 @@ void AliL3Modeller::CalculateCrossingPoints()
          if(!track->GetCrossingPoint(i,hit)) 
            {
              //cerr<<"AliL3Modeller::CalculateCrossingPoints : Track "<<j<<" does not intersect row "<<i<<" :"<<endl<<
-             //" pt "<<track->GetPt()<<
-             //" tgl "<<track->GetTgl()<<" psi "<<track->GetPsi()<<" charge "<<track->GetCharge()<<endl;
-               //"Center "<<track->GetCenterX()<<" "<<track->GetCenterY()<<endl<<endl<<
-               //"--------"<<endl;
-             fTracks->Remove(j);
+             //        " pt "<<track->GetPt()<<
+             //        " tgl "<<track->GetTgl()<<" psi "<<track->GetPsi()<<" charge "<<track->GetCharge()<<endl;
+             //fTracks->Remove(j);
+             track->SetPadHit(i,-1);
+             track->SetTimeHit(i,-1);
              continue;
            }
          //cout<<"X "<<hit[0]<<" Y "<<hit[1]<<" Z "<<hit[2]<<" tgl "<<track->GetTgl()<<endl;
@@ -568,10 +599,13 @@ void AliL3Modeller::CalculateCrossingPoints()
              track->SetTimeHit(i,-1);
              continue;
            }
-         
-         
+
          track->SetPadHit(i,hit[1]);
          track->SetTimeHit(i,hit[2]);
+         track->CalculateClusterWidths(i);
+
+         Double_t beta = track->GetCrossingAngle(i);
+         track->SetCrossingAngleLUT(i,beta);
          
          //if(hit[1]<0 || hit[2]>445)
          //if(hit[2]<0 || hit[2]>445)
@@ -580,41 +614,55 @@ void AliL3Modeller::CalculateCrossingPoints()
        }
     }
   fTracks->Compress();
-  //cout<<"And there are "<<fTracks->GetNTracks()<<" tracks remaining"<<endl;
+  if(fDebug)
+    cout<<"And there are "<<fTracks->GetNTracks()<<" tracks remaining"<<endl;
 }
 
-void AliL3Modeller::CheckForOverlaps()
+void AliL3Modeller::CheckForOverlaps(Float_t dangle,Int_t *rowrange)
 {
   //Flag the tracks that overlap
   
-  //cout<<"Checking for overlaps...";
+  if(fDebug)
+    cout<<"Checking for overlaps on "<<fTracks->GetNTracks()<<endl;
   Int_t counter=0;
-  for(Int_t i=0; i<fTracks->GetNTracks(); i++)
+  
+  for(Int_t k=AliL3Transform::GetFirstRow(fPatch); k<=AliL3Transform::GetLastRow(fPatch); k++)
     {
-      AliL3ModelTrack *track1 = (AliL3ModelTrack*)fTracks->GetCheckedTrack(i);
-      if(!track1) continue;
-      for(Int_t j=i+1; j<fTracks->GetNTracks(); j++)
+      if(rowrange)
        {
-         AliL3ModelTrack *track2 = (AliL3ModelTrack*)fTracks->GetCheckedTrack(j);
-         if(!track2) continue;
-         for(Int_t k=AliL3Transform::GetFirstRow(fPatch); k<=AliL3Transform::GetLastRow(fPatch); k++)
+         if(k < rowrange[0]) continue;
+         if(k > rowrange[1]) break;
+       }
+      for(Int_t i=0; i<fTracks->GetNTracks(); i++)
+       {
+         AliL3ModelTrack *track1 = (AliL3ModelTrack*)fTracks->GetCheckedTrack(i);
+         if(!track1) continue;
+         if(track1->GetPadHit(k)<0 || track1->GetTimeHit(k)<0) continue;
+         
+         for(Int_t j=i+1; j<fTracks->GetNTracks(); j++)
            {
-             if(track1->GetPadHit(k)<0 || track1->GetTimeHit(k)<0 ||
-                track2->GetPadHit(k)<0 || track2->GetTimeHit(k)<0)
-               continue;
-             
-             if(track1->GetOverlap(k)>=0 || track2->GetOverlap(k)>=0) continue;
+             AliL3ModelTrack *track2 = (AliL3ModelTrack*)fTracks->GetCheckedTrack(j);
+             if(!track2) continue;
+             if(track2->GetPadHit(k)<0 || track2->GetTimeHit(k)<0) continue;
              
              if(abs((Int_t)rint(track1->GetPadHit(k))-(Int_t)rint(track2->GetPadHit(k))) <= fPadOverlap &&
                 abs((Int_t)rint(track1->GetTimeHit(k))-(Int_t)rint(track2->GetTimeHit(k))) <= fTimeOverlap)
                {
-                 track2->SetOverlap(k,i);
-                 //track1->SetOverlap(k,j);
+                 if(dangle>0 && fabs(track1->GetCrossingAngleLUT(k) - track2->GetCrossingAngleLUT(k)) < dangle)
+                   fTracks->Remove(j);
+                 
+                 //cout<<"row "<<k<<" "<<i<<" "<<j<<" "<<track1->GetPadHit(k)<<" "<<track2->GetPadHit(k)<<" "<<fabs(track1->GetCrossingAngleLUT(k) - track2->GetCrossingAngleLUT(k))<<endl;
+
+                 else
+                   track1->SetOverlap(k,j);
                  counter++;
                }
            }
        }
     }
+  fTracks->Compress();
+  if(fDebug)
+    cout<<"and there are "<<fTracks->GetNTracks()<<" track left"<<endl;
   //cout<<"found "<<counter<<" done"<<endl;
 }
 
@@ -650,7 +698,8 @@ void AliL3Modeller::CalcClusterWidth(Cluster *cl,Float_t &sigmaY2,Float_t &sigma
   
 
   
-  /*Constants added by offline
+  /*
+    Constants added by offline
     if(s2 != 0)
     {
     sigmaZ2 = sigmaZ2*0.169;
@@ -660,3 +709,38 @@ void AliL3Modeller::CalcClusterWidth(Cluster *cl,Float_t &sigmaY2,Float_t &sigma
   */
 }
 
+void AliL3Modeller::GetTrackID(Int_t pad,Int_t time,Int_t *trackID)
+{
+#ifdef do_mc
+  AliL3DigitRowData *rowPt = (AliL3DigitRowData*)fRowData;
+  
+  trackID[0]=trackID[1]=trackID[2]=-2;
+  
+  for(Int_t i=AliL3Transform::GetFirstRow(fPatch); i<=AliL3Transform::GetLastRow(fPatch); i++)
+    {
+      if(rowPt->fRow < (UInt_t)fCurrentPadRow)
+       {
+         AliL3MemHandler::UpdateRowPointer(rowPt);
+         continue;
+       }
+      AliL3DigitData *digPt = (AliL3DigitData*)rowPt->fDigitData;
+      for(UInt_t j=0; j<rowPt->fNDigit; j++)
+       {
+         Int_t cpad = digPt[j].fPad;
+         Int_t ctime = digPt[j].fTime;
+         if(cpad != pad) continue;
+         if(ctime != time) continue;
+         //if(cpad != pad && ctime != ctime) continue;
+         //cout<<"Reading row "<<fCurrentRow<<" pad "<<cpad<<" time "<<ctime<<" trackID "<<digPt[j].fTrackID[0]<<endl;
+         trackID[0] = digPt[j].fTrackID[0];
+         trackID[1] = digPt[j].fTrackID[1];
+         trackID[2] = digPt[j].fTrackID[2];
+         break;
+         //cout<<"Reading trackID "<<trackID[0]<<endl;
+       }
+      break;
+    }
+#endif
+  return;
+}
+
index c650671..89f16bb 100644 (file)
@@ -1,3 +1,5 @@
+// @(#) $Id$
+
 #ifndef AliL3_Modeller
 #define AliL3_Modeller
 
@@ -22,49 +24,75 @@ struct Digit {
   Bool_t fUsed;
 };
 
+struct ClusterRegion {
+  Int_t mintime;
+  Int_t maxtime;
+};
+
 class AliL3Modeller {
   
  private:
+  Bool_t fHoughTracks;
+  Bool_t CheckCluster(Int_t hitpad,Int_t hittime);
+  Float_t fPadOverlap;
+  Float_t fTimeOverlap;
+  Int_t fTrackThreshold; //minimum weigth track need in order to be included.(=Nhits/weight)
+  AliL3MemHandler *fMemHandler; //!
+
+  void CalcClusterWidth(Cluster *cl,Float_t &sigmaY2,Float_t &sigmaZ2);
+  
+ protected:
   
   AliL3TrackArray *fTracks; //!
-  AliL3MemHandler *fMemHandler; //!
   AliL3DigitRowData *fRowData;//!
-  
+  Digit *fRow; //!
+  Char_t fPath[1024];
+
+  Bool_t fDebug;
   Int_t fNClusters;
   Int_t fMaxClusters;
   Int_t fCurrentPadRow;
-  
-  Float_t fPadOverlap;
-  Float_t fTimeOverlap;
+  Int_t fMaxPads;
+  Int_t fMaxTimebins;
   Int_t fPadSearch;
   Int_t fTimeSearch;
-  Int_t fTrackThreshold; //minimum weigth track need in order to be included.(=Nhits/weight)
+  Int_t fInnerPadSearch;
+  Int_t fInnerTimeSearch;
+  Int_t fOuterPadSearch;
+  Int_t fOuterTimeSearch;
   
   Int_t fSlice;
   Int_t fPatch;
-  Char_t fPath[100];
-
+  
   void FillCluster(AliL3ModelTrack *track,Cluster *cluster,Int_t row,Int_t npads);
-  void CalcClusterWidth(Cluster *cl,Float_t &sigmaY2,Float_t &sigmaZ2);
-  void FillZeros(AliL3DigitRowData *digPt,Digit *row);
-  Bool_t CheckCluster(Digit *row,Int_t hitpad,Int_t hittime);
+  void FillZeros(AliL3DigitRowData *digPt,Bool_t reversesign=kFALSE);
+  void LocateCluster(AliL3ModelTrack *track,ClusterRegion *region,Int_t &padmin,Int_t &padmax);
+  void GetTrackID(Int_t pad,Int_t time,Int_t *trackID);
   
  public:
   
   AliL3Modeller();
   virtual ~AliL3Modeller();
   
+  virtual void FindClusters();
   void Init(Int_t slice,Int_t patch,Char_t *trackdata,Char_t *path,Bool_t houghtracks,Bool_t binary=kTRUE);
-  void FindClusters();
-  void CheckForOverlaps();
+  void CheckForOverlaps(Float_t dangle=-1,Int_t *rowrange=0);
   void CalculateCrossingPoints();
+  void RemoveBadTracks();
   void WriteRemaining();
   
   void SetInputData(AliL3DigitRowData *digits) {fRowData = digits;}
   void SetTrackThreshold(Int_t i=0) {fTrackThreshold=i;}
   void SetOverlap(Int_t p=6,Int_t t=8) {fPadOverlap=p;fTimeOverlap=t;}
   void SetSearchRange(Int_t p=1,Int_t t=2) {fPadSearch=p;fTimeSearch=t;}
-
+  void SetInnerSearchRange(Int_t p,Int_t t) {fInnerPadSearch=p; fInnerTimeSearch=t;}
+  void SetOuterSearchRange(Int_t p,Int_t t) {fOuterPadSearch=p; fOuterTimeSearch=t;}
+  void SetMaxClusterRange(Int_t p,Int_t t) {fMaxPads=p; fMaxTimebins=t;}
+  void Debug() {fDebug=kTRUE;}
+  virtual void SetFitRange(Int_t p,Int_t t) {return;}
+  virtual void SetNmaxOverlaps(Int_t i) {return;}
+  virtual void SetChiSqMax(Float_t f) {return;}
+  
   AliL3TrackArray *GetTracks() {return fTracks;}
     
   ClassDef(AliL3Modeller,1) //Modeller class
index 64a0b5b..235bffb 100644 (file)
@@ -1,3 +1,5 @@
+// @(#) $Id$
+
 #ifndef AliL3Models_H
 #define AliL3Models_H
 
@@ -6,19 +8,36 @@
 const Int_t MaxNClusters = 32;
 
 struct AliL3ClusterModel {
-  Bool_t fPresent;
+  Byte_t fPresent;
   Float_t fDTime;
   Float_t fDPad;
   Float_t fDCharge;
   Float_t fDSigmaY2;
   Float_t fDSigmaZ2;
   UInt_t fNPads;
+  Short_t fSlice;
 #ifdef do_mc
   Int_t fTrackID[3];
 #endif
 };
 typedef struct AliL3ClusterModel AliL3ClusterModel;
 
+struct AliL3RemainingCluster {
+  Float_t fY;
+  Float_t fZ;
+  UShort_t fCharge;
+  Float_t fSigmaY2;
+  Float_t fSigmaZ2;
+};
+typedef struct AliL3RemainingCluster AliL3RemainingCluster;
+
+struct AliL3RemainingRow {
+  Byte_t fPadRow;
+  UShort_t fNClusters;
+  AliL3RemainingCluster fClusters[0];
+};
+typedef struct AliL3RemainingRow AliL3RemainingRow;
+
 struct AliL3TrackModel {
   Float_t fKappa;
   Float_t fFirstPointX;
@@ -27,8 +46,7 @@ struct AliL3TrackModel {
   Float_t fTgl;
   Float_t fPsi;
   Short_t fLength;
-  Short_t fClusterCharge;
-  Char_t fNClusters;
+  Short_t fNClusters;
 };
 typedef struct AliL3TrackModel AliL3TrackModel;
 
index f462cd2..c349de0 100644 (file)
 #$Id$
-###########################
-# Makefile for HLT code.  #
-#                         #
-# Author: Anders Vestbo   #                    
-# changes by C. Loizides  #
-###########################
+################################
+# Makefile for HLT Comp code.  #
+#                              #
+# Author: Anders Vestbo        #                    
+#         Constantin Loizides  #
+################################
 
+MODNAME = AliL3Comp
 
-ifndef TOPDIR
-TOPDIR = $(shell pwd)/..
+ifndef ALIHLT_TOPDIR
+ALIHLT_TOPDIR = $(shell pwd)/..
 endif
 
-include $(TOPDIR)/Makefile.conf
+include $(ALIHLT_TOPDIR)/Makefile.conf
 
-DEFSTR = -Dno_root
-OBJDIR = lib_alone
-INCLUDES = -I$(TOPDIR)/hough -I$(TOPDIR)/src -I$(TOPDIR)/comp -I$(TOPDIR)/misc
+SRCS =  AliL3Modeller.cxx AliL3ModelTrack.cxx AliL3ClusterFitter.cxx \
+        AliL3Compress.cxx AliL3DataCompressor.cxx 
 
-ifeq ($(USEPACKAGE),ROOT) 
-INCLUDES = -I$(ROOTSYS)/include -I$(TOPDIR)/hough -I$(TOPDIR)/src -I$(TOPDIR)/comp
-DEFSTR = -Duse_root
-OBJDIR = lib_ROOT
-endif
-
-ifeq ($(USEPACKAGE),ALIROOT)
-INCLUDES = -I$(ROOTSYS)/include -I$(TOPDIR)/hough -I$(TOPDIR)/src -I$(TOPDIR)/comp -I$(ALICE_ROOT)/include/ -I$(ALICE_ROOT)/TPC -I$(ALICE_ROOT)/CONTAINERS -I$(ALICE_ROOT)/STEER
-DEFSTR = -Duse_aliroot -Duse_root
-OBJDIR = lib
-endif
-
-ifdef DO_MC
-DEFSTR += -Ddo_mc
-endif
-
-ifndef NOLOGGING
-DEFSTR += -Duse_logging
-endif
-
-DEFSTR += $(EXTRADEF)
-
-ifdef MLUCDIR
-INCLUDES += -I$(MLUCDIR)/include
-else
-INCLUDES += -I/prog/alice/level3/kip/MLUC/include
-endif
-
-SRCS =  AliL3Modeller.cxx AliL3ModelTrack.cxx 
-
-DICT  = AliL3CompCint-$(USEPACKAGE).cxx
-DICTH = AliL3CompCint-$(USEPACKAGE).h
-DICTO = $(OBJDIR)/AliL3CompCint-$(USEPACKAGE).o
+ADD_C_OBJS = $(OBJDIR)/bitio.o $(OBJDIR)/errhand.o $(OBJDIR)/AliL3FitUtilities.o
 
-ifeq ($(USEPACKAGE),ROOT)
-SRCS += AliL3Compress.cxx 
-HDRS = $(SRCS:.cxx=.h) bitio.h errhand.h AliL3CompLinkDef.h
-OBJS = $(patsubst %.cxx,$(OBJDIR)/%.o,$(SRCS)) $(OBJDIR)/bitio.o $(OBJDIR)/errhand.o $(DICTO)
+ifeq ($(ALIHLT_USEPACKAGE),ROOT)
+HDRS = $(SRCS:.cxx=.h) $(MODNAME)LinkDef.h
+OBJS = $(patsubst %.cxx,$(OBJDIR)/%.o,$(SRCS)) $(ADD_C_OBJS) $(DICTO)
 endif
 
-ifeq ($(USEPACKAGE),ALIROOT)
-SRCS += AliL3Compress.cxx AliL3DataCompressor.cxx 
-HDRS = $(SRCS:.cxx=.h) bitio.h errhand.h AliL3CompLinkDef.h
-OBJS = $(patsubst %.cxx,$(OBJDIR)/%.o,$(SRCS)) $(OBJDIR)/bitio.o $(OBJDIR)/errhand.o $(DICTO)
+ifeq ($(ALIHLT_USEPACKAGE),ALIROOT)
+HDRS = $(SRCS:.cxx=.h) $(MODNAME)LinkDef.h
+OBJS = $(patsubst %.cxx,$(OBJDIR)/%.o,$(SRCS)) $(ADD_C_OBJS) $(DICTO)
 endif
 
-ifeq ($(OBJDIR),lib_alone)
-HDRS = $(SRCS:.cxx=.h) bitio.h errhand.h
-OBJS = $(patsubst %.cxx,$(OBJDIR)/%.o,$(SRCS)) $(OBJDIR)/bitio.o $(OBJDIR)/errhand.o
+ifeq ($(ALIHLT_USEPACKAGE),STANDALONE)
+OBJS = $(patsubst %.cxx,$(OBJDIR)/%.o,$(SRCS)) $(ADD_C_OBJS)
 endif
 
+include $(ALIHLT_TOPDIR)/Makefile.rules
 
-LEVELSO = $(LIBDIR)/libAliL3Comp.so
-
-all : $(OBJDIR) $(LIBDIR) $(LEVELSO)
-
-$(LEVELSO) : $(OBJS)
-       $(LD) $(SOFLAGS) $(LDFLAGS) $^ -o $@
-
-$(DICT) : $(HDRS)
-       @echo "Generating dictionary..."
-       @rootcint -f $(DICT) -c $(INCLUDES) -DGCCVERSION=$(GCCVERSION) -include AliL3StandardIncludes.h $(HDRS)
-
-$(OBJDIR)/%.o : %.cxx 
-       $(CXX) $(CXXFLAGS) $(DEFSTR) -c $(INCLUDES) -o $@ $<
-
-$(OBJDIR) : 
-       test ! -e $(OBJDIR) && mkdir -p $(OBJDIR)
-
-$(LIBDIR) :
-       test ! -e $(LIBDIR) && mkdir -p $(LIBDIR)
 
-$(OBJDIR)/bitio.o : bitio.c
+$(OBJDIR)/bitio.o: bitio.c
        $(CXX) -c -o $(OBJDIR)/bitio.o bitio.c
 
-$(OBJDIR)/errhand.o : errhand.c
+$(OBJDIR)/errhand.o: errhand.c
        $(CXX) -c -o $(OBJDIR)/errhand.o errhand.c
 
-clean :
-       rm -f $(OBJDIR)/*.o
-       rm -f $(LIBDIR)/libAliL3Comp.so
-       rm -f $(DICT) $(DICTH)
-so :
-       rm -f $(LIBDIR)/libAliL3Comp.so
+$(OBJDIR)/AliL3FitUtilities.o: AliL3FitUtilities.c
+       $(CXX) -c -o $(OBJDIR)/AliL3FitUtilities.o AliL3FitUtilities.c
index 6f75afa..5563794 100644 (file)
@@ -1,3 +1,5 @@
+// @(#) $Id$
+
 /************************** Start of BITIO.H *************************/
 
 #ifndef _BITIO_H
@@ -14,16 +16,32 @@ typedef struct bit_file {
 
 //#ifdef __STDC__
 
+//The following we do because this file is read both by
+//C and C++ compiler.
+#ifdef __cplusplus
+extern "C" BIT_FILE     *OpenInputBitFile( char *name );
+extern "C" BIT_FILE     *OpenOutputBitFile( char *name );
+extern "C" void          OutputBit( BIT_FILE *bit_file, int bit );
+extern "C" void          OutputBits( BIT_FILE *bit_file,
+                                    unsigned long code, int count );
+extern "C" int           InputBit( BIT_FILE *bit_file );
+extern "C" unsigned long InputBits( BIT_FILE *bit_file, int bit_count );
+extern "C" void          CloseInputBitFile( BIT_FILE *bit_file );
+extern "C" void          CloseOutputBitFile( BIT_FILE *bit_file );
+extern "C" void          FilePrintBinary( FILE *file, unsigned int code, int bits );
+#else
 BIT_FILE     *OpenInputBitFile( char *name );
 BIT_FILE     *OpenOutputBitFile( char *name );
 void          OutputBit( BIT_FILE *bit_file, int bit );
 void          OutputBits( BIT_FILE *bit_file,
-                          unsigned long code, int count );
+                         unsigned long code, int count );
 int           InputBit( BIT_FILE *bit_file );
 unsigned long InputBits( BIT_FILE *bit_file, int bit_count );
 void          CloseInputBitFile( BIT_FILE *bit_file );
 void          CloseOutputBitFile( BIT_FILE *bit_file );
 void          FilePrintBinary( FILE *file, unsigned int code, int bits );
+#endif
+
 /*
 #else   
 
index 20ab238..b176809 100644 (file)
@@ -1,3 +1,5 @@
+// @(#) $Id$
+
 /************************* Start of ERRHAND.H ************************/
 
 #ifndef _ERRHAND_H
diff --git a/HLT/doc/README b/HLT/doc/README
new file mode 100644 (file)
index 0000000..892bc6a
--- /dev/null
@@ -0,0 +1,68 @@
+#
+#$Id$
+#
+
+ALICE High Level Trigger
+-------------------------
+
+After checking out the code, you should see the following
+in the toplevel directory:
+
+bin ............ small scripts to set env or to compile
+exa ............ sample macros showing how to use the code  
+kalman ......... (not usable at the moment)
+Makefile.conf .. checks environment for ALIHLT_* variables
+misc ........... lib AliL3Misc (different helper classes)
+sim ............ (not usable at the moment)
+trigger ........ (not usable at the moment)
+comp ........... lib AliL3Comp (compression and deconvolution)
+doc ............ hopefully contains information
+hough .......... lib AliL3Hough (different hough transforms)
+Makefile ....... main makefile (use make libs to compile all libs)
+Makefile.rules . most of the rules for all libs
+programs ....... sample programs showing how to use the code
+src ............ main lib AliL3Src (transformer, tracker and clusterer)
+
+The compilation is controlled by the following variables:
+
+$ALIHLT_USEPACKAGE --> HLT package to compile  
+ = ALIROOT    (to use galice root files)
+ = ROOT       (to use root features)
+ = STANDALONE (to be independant of root)
+
+$ALIHLT_BASEDIR --> base directory, e.g. $HOME/work/hlt 
+$ALIHLT_TOPDIR  --> directory of top makefile, e.g. $ALIHLT_BASEDIR/code
+$ALIHLT_LIBDIR  --> directory where libs will be placed,
+                  e.g. $ALIHLT_TOPDIR/lib_$ALIHLT_USEPACKAGE
+
+$ALIHLT_MLUCDIR --> directory of MLUC include and lib sub-directories,
+                    e.g. switch of by setting ALIHLT_NOLOGGING="true"  
+
+Compiliation flags:
+
+$ALIHLT_NOLOGGING (false) --> use HLT logger classes (requires MLUC lib)
+$ALIHLT_DOMC (true)       --> store Monte Carlo ids (for ALIROOT package)
+$ALIHLT_HAVEASV (true)    --> have patched ALITPC class for fast digit I/O
+$ALIHLT_ALIDETECT (true)  --> detect ALIROOT version using cvs
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!                                      !
+! Have a look at bin/sethlt_cern.[c]sh !
+! for a sample configuration script.   !
+!                                      !
+! After setting the environment,       !
+! do `make libs` in $ALIHLT_TOPDIR     !
+! to compile the shared HLT libs.      !
+!                                      !
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+Note, using ROOT THtml class, you can generate html 
+documentation (see http://root.cern.ch for an HOWTO).
+
+----------------------------------------------------
+Further Information:
+http://web.kip.uni-heidelberg.de/Hardwinf/L3/
+http://www.ikf.physik.uni-frankfurt.de/~loizides/
+http://www.fi.uib.no/~vestbo/
+----------------------------------------------------
+C. Loizides, loizides@ikf.uni-frankfurt.de
diff --git a/HLT/exa/Eval.C b/HLT/exa/Eval.C
deleted file mode 100644 (file)
index 3c0f25b..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-// $Id$
-
-void Eval(char *rootfile="")
-{
-  AliL3Logger l;
-//  l.UnSet(AliL3Logger::kDebug);
-//  l.UnSet(AliL3Logger::kAll);
-  l.Set(AliL3Logger::kError);
-  l.UseStdout();
-  //l.UseStream();
-    
-  int slice[2] = {0,35};
-  e = new AliL3Evaluate(rootfile,slice);
-  e->SetupSlow("tracks.raw",".");
-  //e->SetupFast("tracks.raw","/nfs/david/subatom/alice/data/V3.04/fast/clusters/hg_8k_v0_s1-3_e0_cl.root",".");
-  
-  TNtuple *ntuppel = (TNtuple*)e->EvaluatePoints();
-  file = new TFile("CFeval_nodeconv.root","RECREATE");
-  file->cd();
-  ntuppel->Write();
-  file->Close();
-  delete file;
-}
-
-void plotPt(char *rootfile)
-{
-  gStyle->SetStatColor(10);
-  gStyle->SetOptStat(0);
-  gStyle->SetOptFit(1100);  
-  
-  c = new TCanvas("c","",2);
-  SetCanvasOptions(c);
-  
-  f1 = new TFile(rootfile);
-
-  hist = new TH1F("hist","",50,-10,10);
-  SetTH1Options(hist);
-  fNtuppel->Draw("(pt_found-pt_gen)/pt_gen*100>>hist","nHits>30");
-  hist->GetXaxis()->SetTitle("%");
-  hist->GetYaxis()->SetTitle("Counts");
-
-  float rms = hist->GetRMS();
-  printf("Rms value : %f\n",rms);
-  
-  TF1 *f = new TF1("f","gaus",-rms,rms);
-  hist->Fit("f","R");
-}
-
-void plot(char *rootfile)
-{
-  gStyle->SetStatColor(10);
-  gStyle->SetOptStat(1);
-  gStyle->SetOptFit(1);
-  
-  file = new TFile(rootfile);
-  hist = new TH1F("hist","",100,-0.6,0.6);
-  SetTH1Options(hist);
-  
-  can = new TCanvas("can","Residuals",900,600);
-  can->Divide(2);
-  SetCanvasOptions(can);
-  can->cd(1);
-  //ntuppel->Draw("residual_trans>>hist","zHit < 50 && padrow > 55");//beta < 10*4.1515/180");
-  ntuppel->Draw("resy>>hist","ptgen > 1.0");
-  
-  float rms = hist->GetRMS();
-  printf("Rms value : %f\n",rms);
-  
-  TF1 *f = new TF1("f","gaus",-rms,rms);
-  hist->Fit("f","R");
-    
-  hist->GetXaxis()->SetTitle("#delta_{T} [cm]");
-  hist->GetYaxis()->SetTitle("Counts");
-  
-  f2 = new TFile("results_fast_oldparams.root");
-  hist2 = new TH1F("hist2","",100,-0.6,0.6);
-  SetTH1Options(hist2);
-  can->cd(2);
-  ntuppel_fast->Draw("residual_trans>>hist2","nHits>100 && pt>1.0 && padrow > 0 && zHit < 50");//dipangle < 20*3.1415/180");
-  
-  can->Update();
-}
-
-
diff --git a/HLT/exa/MakePileup.C b/HLT/exa/MakePileup.C
new file mode 100644 (file)
index 0000000..d9d61ae
--- /dev/null
@@ -0,0 +1,412 @@
+//$Id$
+
+/**
+  Macro for making pileup events in pp. Remember to have the MC
+  optione switched on and that the resulting digit files will 
+  not be RLE so use the PileUp option when tracking.
+
+  Compile and run it by:
+  root>.L MakePileup.C++
+  root>MakePileup(path,triggerevent);
+  
+  Remember to have a "digitfile" link to the root 
+  file containing the pp events in "path". 
+
+  Authors: Roland Bramm & Anders Vestbo & Constantin Loizides
+*/
+
+#ifndef __CINT__
+#include "AliL3Logger.h"
+#include "AliL3FileHandler.h"
+#include "AliL3DigitData.h"
+#include "AliL3Transform.h"
+#include <TNtuple.h>
+#include <TRandom.h>
+#include <TSystem.h>
+#include <stdio.h>
+#include <iostream.h>
+#include <time.h>
+
+void QSort(void **dPt,Int_t first,Int_t last);
+Int_t CompareDigits(void *dPt1,void *dPt2);
+#endif
+
+/* Nice script I am using for the generation of pileup events:
+
+--------------------------------------------------------
+#!/bin/bash
+
+from=$1
+to=$2
+
+dir=/tmp/pp
+
+mkdir -p $dir
+ln -s -f /data1/AliRoot/PythiaPP_1000Events_TPConly_ev0-375_digits.root $dir/digitfile.root
+cd ~/l3/level3code/exa
+
+for i in `seq $from $to`; do 
+ echo $i;
+ pdir="pileup-100-$i";
+
+ aliroot -b runMakePileup.C\(\"$dir\",0,375,\"$pdir\",101\);
+done
+--------------------------------------------------------
+
+  Path should point to the path in which there is a link to the root digitsfile.
+  Startev and Endev mark the beginning and ending of valid event numbers in that file.
+  Pileupdir is the directory in which the binary pileuped data will be written
+  Npiles specifies the number of pileups wanted.
+  TriggerEvent specifies the triggerevent in the linear mode or if -1 is given the random mode.
+  Good_tpc_ev_filename is the rootfile name where the offline good-tracks are stored (see fill.C)
+*/
+
+void MakePileup(Char_t *path,Int_t startev,Int_t endev,Char_t *pileupdir="pileup",Int_t npiles=25,Int_t triggerevent=-1,Char_t *good_tpc_ev_filename=0)
+{
+  Int_t ntotalev=endev-startev+1;
+
+  if(ntotalev<npiles){
+    cerr << "Total number of events in root file must be at least equal to the number of pp events to be piledup." <<endl;
+    return;
+  }
+  if(npiles<1 || npiles % 2 != 1 ){
+    cerr << "npiles must be at least one and a odd number." <<endl;
+    return;
+  }
+
+  Int_t const minTriggerEvents=5;
+  //Int_t RefOffset[25] = {30,60,90,120,150,180,210,240,270,300,330,360,-30,-60,-90,-120,-150,-180,-210,-240,-270,-300,-330,-360,-390};
+  Int_t tshift=30*25/npiles;
+  Int_t *Offset=new Int_t[npiles];
+  Offset[0]=0;
+  for(Int_t i=1;i<=(npiles-1)/2;i++)
+    Offset[i] = i*tshift;
+  for(Int_t i=1;i<=(npiles-1)/2;i++)
+    Offset[i+(npiles-1)/2] = -i*tshift;
+
+  Int_t *EventNumbers=new Int_t[npiles];
+  if(triggerevent<0){
+    Int_t evdiff=endev-startev;
+    time_t t;
+    Int_t iseed = (abs((12*1000+1)*time(&t)))%900000000;
+    TRandom *rand=new TRandom(iseed);
+
+    while(triggerevent<0){
+      Double_t dummy=evdiff*rand->Rndm();
+
+      if(good_tpc_ev_filename){
+       TFile goodfile=TFile(good_tpc_ev_filename,"READ");
+       if(!goodfile.IsOpen()){
+         cerr << "Could not open good tpc tracks file "<<good_tpc_ev_filename<<endl;
+         return;
+       }
+       Char_t gooddummy[1000];
+       sprintf(gooddummy,"good-pptracks-%d",(Int_t)dummy+startev);
+       TNtuple *ngtuppel = (TNtuple*)goodfile.Get(gooddummy);
+       if(!ngtuppel) continue;
+       Int_t ngoodevents=(Int_t)ngtuppel->GetEntries();
+       if(ngoodevents>=minTriggerEvents) triggerevent=(Int_t)dummy+startev;
+       goodfile.Close();
+      } else
+       triggerevent=(Int_t)dummy+startev;
+    } //found a trigger event
+    for(Int_t i=1;i<npiles;i++){
+      Int_t ev=triggerevent;
+      while(ev==triggerevent){
+       Double_t dummy=evdiff*rand->Rndm()+startev;
+       ev=(Int_t)dummy;
+      }
+      EventNumbers[i]=ev;
+    }
+    delete rand;
+  } else {
+    Int_t ev=startev;
+    for(Int_t i=1;i<npiles;i++){
+      if(ev==triggerevent) ev++;
+      EventNumbers[i]=ev;
+      ev++;
+    }
+  }
+  EventNumbers[0]=triggerevent;
+  cout << "Events: ";for(Int_t i=0;i<npiles;i++) cout << EventNumbers[i] << " "; cout << endl;
+  cout << "Offsets: ";for(Int_t i=0;i<npiles;i++) cout << Offset[i] << " ";cout << endl;
+
+  /////////////
+  //exit(1);
+  /////////////
+            
+  UInt_t size;
+  Int_t patch = -1; //All of slice.
+
+  Int_t NEvents = npiles; //for compatibility with old version
+  AliL3FileHandler **hand=new AliL3FileHandler*[NEvents];
+  AliL3DigitRowData **data=new AliL3DigitRowData*[NEvents];
+  AliL3DigitData **rowData=new AliL3DigitData*[NEvents];
+  AliL3DigitData *test;
+  Char_t Carry[1024];
+  Int_t DigitsTot = 0;
+  Int_t tot_dig=0;
+  Int_t MeVDigit;
+  Int_t DigitsPerRow = 0;
+  Byte_t *NData;
+
+  const Int_t maxdigits=50000;
+  AliL3DigitData *temp[maxdigits];
+  AliL3DigitData *temp2[maxdigits];
+  
+  //Create 1 filehander per event:
+  sprintf(Carry,"%s/digitfile.root",path);
+  for(Int_t event=0; event<NEvents; event++)
+    {
+      hand[event] = new AliL3FileHandler();
+      if(!hand[event]->SetAliInput(Carry))
+       cerr<<" Error opening file :"<<Carry<<endl;
+    }
+  
+  //Looping over slices and the over events
+  for(Int_t slice=0 ; slice<36 ; slice++){
+    cout<<"\nLoading slice "<<slice<<" "<<endl;
+    for(Int_t event = 0; event < NEvents ; event++){
+      Int_t eventno=EventNumbers[event];
+      hand[event]->Init(slice,patch);  //give merge option to FileHandler
+      data[event] = hand[event]->AliAltroDigits2Memory(size,eventno,kTRUE);
+      cout << "."<<flush;
+    }
+    cout<<" done"<<endl;
+
+    //Find out how many digits to allocate per patch
+    DigitsTot=0;
+    Int_t sign = slice < 18 ? -1 : 1;
+    for(Int_t row = 0 ; row < AliL3Transform::GetNRows(patch) ; row++){
+      for(Int_t event = 0; event < NEvents ; event++){
+       rowData[event] = (AliL3DigitData *)data[event]->fDigitData;
+       for(UInt_t dig=0; dig<data[event]->fNDigit; dig++)
+         {
+           Int_t time = rowData[event][dig].fTime + sign*Offset[event];
+           if(time < AliL3Transform::GetNTimeBins() && time >= 0)
+             DigitsTot++;
+         }
+
+       hand[event]->UpdateRowPointer(data[event]);
+      }
+    }
+
+    //cout << "Try to allocate : " << DigitsTot << endl;
+    Int_t AllDigitsSize = sizeof(AliL3DigitData) * DigitsTot + sizeof(AliL3DigitRowData) * AliL3Transform::GetNRows(patch);
+    NData = new Byte_t[AllDigitsSize];
+    memset(NData,0,AllDigitsSize);
+    AliL3DigitRowData *AllRowData = (AliL3DigitRowData*)NData;
+    //cout << "Allocated " << endl;
+    
+    //Reset the data pointers, because they changed when doing UpdateRowPointer.
+    for(Int_t event=0; event<NEvents; event++)
+      data[event] = (AliL3DigitRowData*)hand[event]->GetDataPointer(size);
+
+    //Pileup the event    
+    tot_dig=0;
+    for(Int_t row = 0 ; row < AliL3Transform::GetNRows(patch) ; row++){
+      DigitsPerRow = 0;
+      for(Int_t event = 0; event < NEvents ; event++){
+       rowData[event] = (AliL3DigitData *)data[event]->fDigitData;
+       for(UInt_t dig=0; dig<data[event]->fNDigit; dig++)
+         {
+           Int_t time = rowData[event][dig].fTime + sign*Offset[event];
+           if(time < AliL3Transform::GetNTimeBins() && time >= 0)
+             DigitsPerRow++;
+         }
+      }
+      //cout << "Found : " << DigitsPerRow << " in all Events, Row :" << row << endl;
+
+      //Copy the digits to a temporary storage, 
+      //because we have to sort them before storing them :
+      MeVDigit = 0;
+      for(Int_t event = 0; event < NEvents ; event++){
+       rowData[event] = (AliL3DigitData *)data[event]->fDigitData;
+       for(UInt_t digit = 0; digit < data[event]->fNDigit ; digit++){
+
+         Int_t time = rowData[event][digit].fTime + sign*Offset[event];
+         if(time >= AliL3Transform::GetNTimeBins() || time < 0)
+           continue;
+         
+         temp[MeVDigit] = &rowData[event][digit];
+         temp[MeVDigit]->fTime = temp[MeVDigit]->fTime + sign*Offset[event];
+         //cout << MeVDigit << " : " << digit << endl;
+         MeVDigit++;
+       }
+       hand[event]->UpdateRowPointer(data[event]);
+      }
+
+      //Sort the digits:
+      QSort((void**)temp,0,MeVDigit);
+
+      //Now, loop and check for overlaps:
+      Int_t final_count=0;
+      for(Int_t c=0; c<MeVDigit; c++)
+       {
+
+         if(final_count>0 && temp[c]->fTime == temp[c-1]->fTime && temp[c]->fPad == temp[c-1]->fPad)
+           {
+             //this one is overlapping with the previous one:
+             temp2[final_count-1]->fCharge += temp[c]->fCharge;
+             if(temp2[final_count-1]->fCharge>=1024)
+               temp2[final_count-1]->fCharge=1023; //Saturation
+             
+             Int_t testev=( (temp[c]->fTrackID[0])>>22 ) & 0x3ff;
+             if( testev == triggerevent) 
+               {
+                 //This digit comes from trigger event, so store the mcid
+                 temp2[final_count-1]->fTrackID[0] = temp[c]->fTrackID[0];
+                 temp2[final_count-1]->fTrackID[1] = temp[c]->fTrackID[1];
+                 temp2[final_count-1]->fTrackID[2] = temp[c]->fTrackID[2];
+               }
+           }
+         else
+           {
+             temp2[final_count] = temp[c];
+             final_count++;
+           }
+       }
+
+      tot_dig+=final_count;
+      AllRowData->fRow = row;
+      AllRowData->fNDigit = final_count;
+      test = (AliL3DigitData *) AllRowData->fDigitData;
+
+      //and copy them to the new event:
+      for(Int_t c=0; c<final_count; c++)
+       {
+         test[c].fCharge = temp2[c]->fCharge;
+         test[c].fPad = temp2[c]->fPad;
+         test[c].fTime = temp2[c]->fTime;
+
+
+         Int_t testev=( (temp2[c]->fTrackID[0])>>22 ) & 0x3ff;
+
+         //Save the MCID
+         //Only store the mc corresponding to the trigger event:
+         if ( testev == triggerevent)
+           {
+             test[c].fTrackID[0] = ( (temp2[c]->fTrackID[0]) & 0x3fffff ) - 128;
+             test[c].fTrackID[1] = ( (temp2[c]->fTrackID[1]) & 0x3fffff ) - 128;
+             test[c].fTrackID[2] = ( (temp2[c]->fTrackID[2]) & 0x3fffff ) - 128;
+           }
+         else //Digit not corresponding to the triggerevent, so mark it as noise.
+           {
+             test[c].fTrackID[0]=-1;
+             test[c].fTrackID[1]=-1;
+             test[c].fTrackID[2]=-1;
+           }
+         if(c>0 && test[c].fTime == test[c-1].fTime && test[c].fPad == test[c-1].fPad)
+           cerr<<"Overlap at row "<<row<<" pad "<<(int)test[c].fPad<<" time "<<(int)test[c].fTime<<endl;
+         //cout<<"Copying back, pad "<<(int)test[c].fPad<<" time "<<(int)test[c].fTime<<" charge "<<(int)test[c].fCharge<<endl;
+       }
+      
+      if(MeVDigit!=DigitsPerRow)
+       cerr<<endl<<"Error: "<<MeVDigit<<" "<<DigitsPerRow<<endl;
+      if(final_count > MeVDigit)
+       cerr<<"Error; final_count "<<final_count<<" MeVDigit "<<MeVDigit<<endl;
+
+      Byte_t *tmp = (Byte_t *)AllRowData;
+      Int_t UpdateSize = sizeof(AliL3DigitRowData) + sizeof(AliL3DigitData)*final_count;
+      tmp += UpdateSize;
+      AllRowData = (AliL3DigitRowData *) tmp; 
+    }//end looping over row
+
+    if(tot_dig>DigitsTot)
+      cerr<<endl<<"Mismatching digitcount "<<tot_dig<<" "<<DigitsTot<<endl;
+
+    //cout << "Clearing data structures. " << endl;
+    for(Int_t event = 0; event < NEvents ; event++)
+      {
+       data[event]=0;
+       hand[event]->Free();
+       hand[event]->FreeDigitsTree();
+      }
+    
+    AliL3FileHandler *Out = new AliL3FileHandler();
+    AllRowData = (AliL3DigitRowData*)NData;
+    if(slice==0){
+      if(pileupdir[0]=='/')
+       sprintf(Carry,"mkdir -p %s/",pileupdir);
+      else
+       sprintf(Carry,"mkdir -p %s/%s/",path,pileupdir);
+      gSystem->Exec(Carry);
+    }
+    if(pileupdir[0]=='/')
+      sprintf(Carry,"%s/digits_%d_%d_%d.raw",pileupdir,triggerevent,slice,patch);
+    else 
+      sprintf(Carry,"%s/%s/digits_%d_%d_%d.raw",path,pileupdir,triggerevent,slice,patch);
+
+
+    if(!Out->SetBinaryOutput(Carry))
+      {
+       cerr<<"Cannot open file: "<<Carry<<endl;
+       return;
+      }
+    cout << "Writing to file: " << Carry <<endl;
+    Out->Memory2Binary(AliL3Transform::GetNRows(patch),AllRowData);
+    Out->CloseBinaryOutput();
+    delete Out;
+    delete [] NData;
+  }
+  
+  for(Int_t event = 0; event < NEvents ; event++)
+    delete hand[event];
+
+  delete[] hand;
+  delete[] rowData;
+  delete[] data;
+}
+
+void QSort(void **dPt,Int_t first,Int_t last)
+{
+  //General sorting routine. only sorting the pointers.
+  AliL3DigitData **a = (AliL3DigitData**)dPt;
+  
+  AliL3DigitData *tmp;
+  int i; 
+  int j;
+  
+  while (last - first > 1) {
+    i = first;
+    j = last;
+    for (;;) {
+      while (++i < last && CompareDigits((void*)a[i], (void*)a[first]) < 0)
+       ;
+      while (--j > first && CompareDigits((void*)a[j], (void*)a[first]) > 0)
+       ;
+      if (i >= j)
+       break;
+
+      tmp  = a[i];
+      a[i] = a[j];
+      a[j] = tmp;
+    }
+    if (j == first) {
+      ++first;
+      continue;
+    }
+    tmp = a[first];
+    a[first] = a[j];
+    a[j] = tmp;
+    if (j - first < last - (j + 1)) {
+      QSort((void**)a, first, j);
+      first = j + 1;   // QSort(j + 1, last);
+    } else {
+      QSort((void**)a, j + 1, last);
+      last = j;        // QSort(first, j);
+    }
+  }
+}
+
+Int_t CompareDigits(void *dPt1,void *dPt2)
+{
+  AliL3DigitData *a = (AliL3DigitData*)dPt1;
+  AliL3DigitData *b = (AliL3DigitData*)dPt2;
+  if(a->fPad==b->fPad && a->fTime == b->fTime) return 0;
+  
+  if(a->fPad<b->fPad) return -1;
+  if(a->fPad==b->fPad && a->fTime<b->fTime) return -1;
+  
+  return 1;
+}
diff --git a/HLT/exa/MakePythia.C b/HLT/exa/MakePythia.C
new file mode 100644 (file)
index 0000000..02929c6
--- /dev/null
@@ -0,0 +1,139 @@
+//$Id$
+
+/* A little macro filling a root 
+   tree with PYTHIA6 events. Same 
+   as generate_PYTHIA.C */
+
+typedef struct 
+{
+  Int_t    no;
+  Int_t    part;
+  Int_t    total;
+  Int_t    npart;
+  Int_t    nenergy;
+  Int_t    nhard;
+  Float_t  b; 
+  Float_t  phi;
+} THeader;
+
+UInt_t makeSeed(int mode=0) 
+{
+  switch (mode) {
+  case 1: 
+    {
+      TDatime date;
+      return date.GetDate();
+    }
+  case 2:
+    {
+      TDatime date;
+      UInt_t  seed1 = (date.GetDate() / 1000000 * 100 + 
+                      date.GetTime() / 1000000);
+      UInt_t  seed2 = (date.GetTime() % 10000);
+      TRanMar ranmar(seed1, seed2);
+      Int_t   eat = (date.GetDate() - 19980101 + seed2 +
+                    gSystem->GetPid()); 
+      for (Int_t i = 0; i < (eat + 250000) ; i++) 
+       ranmar.Rndm();
+      return 2 * Int_t(ranmar.Rndm() * (TMath::Power(2,30) - 1)) + 1;
+    }
+  case 3:
+    {
+      TDatime date;
+      UInt_t  seed1 = (date.GetDate() / 1000000 * 100 + 
+                      date.GetTime() / 1000000 + gSystem->GetPid());
+      TRandom rand(seed1);
+      return Int_t(rand.Rndm() * (TMath::Power(2,30) - 1)) + 1;
+    }
+
+    break;
+  }
+  return 0;
+}
+
+Int_t MakePythia(Int_t nEvents=10,Char_t *rfile="pythia6.root")
+{
+   gSystem->Load("$ROOTSYS/lib/libPythia6.so");
+   gSystem->Load("$ROOTSYS/lib/libEG.so");                   // Root Event Generator interface
+   gSystem->Load("$ROOTSYS/lib/libEGPythia6.so");            // Root interface to Pythia6
+   //gDebug=1;
+
+   TStopwatch*   stopWatch = new TStopwatch();
+   TPythia6* pythia6       = new TPythia6();
+   TClonesArray* particles = new TClonesArray("TParticle");
+   THeader header;
+
+   Char_t filename[1024];
+   sprintf(filename,"%s",rfile);
+
+   TFile* file = new TFile(filename,"RECREATE");
+   file->SetCompressionLevel(1);
+   TTree* tree = new TTree("pythia","pythia events");
+   tree->Branch("particles",&particles);
+   //tree->Branch("header",&header, "no/I:part:total:npart:nenergy:nhard:b/F:phi");
+
+   stopWatch->Start();
+
+   //      select Pythia min. bias model, taken from AliPythia.C
+   pythia6->SetMSEL(0);
+   pythia6->SetMSUB(92,1);      // single diffraction AB-->XB
+   pythia6->SetMSUB(93,1);      // single diffraction AB-->AX
+   pythia6->SetMSUB(94,1);      // double diffraction
+   pythia6->SetMSUB(95,1);      // low pt production
+   pythia6->SetMSTP(81,1);      // multiple interactions switched on
+   pythia6->SetMSTP(82,3);      // model with varying impact param. & a single Gaussian
+   pythia6->SetPARP(82,3.47);   // set value pT_0  for turn-off of the cross section of
+   // multiple interaction at a reference energy = 14000 GeV
+   pythia6->SetPARP(89,14000.); // reference energy for the above parameter
+   pythia6->SetPARP(90,0.174);  // set exponent for energy dependence of pT_0
+
+   // set fragmentation on (default)
+   pythia6->SetMSTP(111,1);
+  
+   // don't smear the primary vertex
+   pythia6->SetMSTP(151,0);
+
+   //pythia6->SetMSTP(61,0);
+   //pythia6->SetMSTP(64,0);
+
+   pythia6->SetMRPY(1,makeSeed(3));
+   pythia6->Initialize("cms","p","p",5500);
+   //pythia6->Initialize("cms","p","p",1800);
+
+   stopWatch->Stop();
+   stopWatch->Print();
+
+   Int_t i;
+   for (i = 0; i < nEvents; i++) {
+     stopWatch->Start();
+     cout << "Event # " << i << " ... " << flush;
+
+     pythia6->GenerateEvent();
+
+     header.no    = i;
+     header.total = pythia6->ImportParticles(particles,"All");
+     header.part  = 0;
+
+     header.npart    = 0;
+     header.nenergy  = 0;
+     header.nhard    = 0;
+
+     header.b     = 0;
+     header.phi   = 0;
+
+     //particles->Print();
+     //pythia6->Pylist(1);
+
+     tree->Fill();
+     
+     cout << "done (" << header.total << " particles) " << flush;
+     stopWatch->Stop();
+     stopWatch->Print();
+   }
+
+   file->Write();
+   file->Close();
+
+  return 0;
+}
+
diff --git a/HLT/exa/PlotPythiaEvent.C b/HLT/exa/PlotPythiaEvent.C
new file mode 100644 (file)
index 0000000..c783cca
--- /dev/null
@@ -0,0 +1,202 @@
+void PlotPythiaEvent(char* path="/data1/AliRoot/pp/pythia/14000")
+{
+  //gSystem->Load("$ROOTSYS/lib/libEG.so");                   // Root Event Generator interface
+
+  TH1F *hVr = new TH1F("hVr","Secondary vertex distribution (r direction)",100,0,100);
+  TH1F *hVr2 = new TH1F("hVr2","Secondary vertex distribution near primary vertex",100,0,50);
+  
+  TH1F *hVz = new TH1F("hVz","Secondary vertex distribution",100,-100,100);
+  TH1F *hVz10 = new TH1F("hVz10","Secondary vertex distribution",10,-10,10);
+  TH1F *hVz20 = new TH1F("hVz20","Secondary vertex distribution",200,-20,20);
+  TH1F *hVz30 = new TH1F("hVz30","Secondary vertex distribution",300,-30,30);
+  TH1F *hVz40 = new TH1F("hVz40","Secondary vertex distribution",400,-40,40);
+  TH1F *hVz50 = new TH1F("hVz50","Secondary vertex distribution",500,-50,50);
+  TH1F *hVz60 = new TH1F("hVz60","Secondary vertex distribution",600,-60,60);
+  TH1F *hVz70 = new TH1F("hVz70","Secondary vertex distribution",700,-70,70);
+  TH1F *hVz80 = new TH1F("hVz80","Secondary vertex distribution",800,-80,80);
+  TH1F *hVz90 = new TH1F("hVz90","Secondary vertex distribution",900,-90,90);
+  TH1F *hVz100 = new TH1F("hVz100","Secondary vertex distribution",100,-100,100);
+
+  TH1F *hPt = new TH1F("hPt","Transversal momentum",50,0,10);
+  TH1F *hPt10 = new TH1F("hPt10","Transversal momentum for particles within the vertex cut",50,0,10);
+  TH1F *hPt20 = new TH1F("hPt20","Transversal momentum for particles within the vertex cut",50,0,10);
+  TH1F *hPt30 = new TH1F("hPt30","Transversal momentum for particles within the vertex cut",50,0,10);
+  TH1F *hPt40 = new TH1F("hPt40","Transversal momentum for particles within the vertex cut",50,0,10);
+  TH1F *hPt50 = new TH1F("hPt50","Transversal momentum for particles within the vertex cut",50,0,10);
+  TH1F *hPt60 = new TH1F("hPt60","Transversal momentum for particles within the vertex cut",50,0,10);
+  TH1F *hPt70 = new TH1F("hPt70","Transversal momentum for particles within the vertex cut",50,0,10);
+  TH1F *hPt80 = new TH1F("hPt80","Transversal momentum for particles within the vertex cut",50,0,10);
+  TH1F *hPt90 = new TH1F("hPt90","Transversal momentum for particles within the vertex cut",50,0,10);
+  TH1F *hPt100 = new TH1F("hPt100","Transversal momentum for particles within the vertex cut",50,0,10);
+
+/*TH1F *hPt3 = new TH1F("hPt3","Transversal momentum for particles outside the vertex cut",100,0,10);
+  hPt3->SetXTitle("GeV/c");
+  hPt3->SetYTitle("N");
+
+  TH1F *hPt4 = new TH1F("hPt4","hPt2/hPt",100,0,10);
+  hPt4->SetXTitle("GeV/c");
+  hPt4->SetYTitle("N");
+
+  TH1F *hPt5 = new TH1F("hPt5","hPt3/hPt",100,0,10);
+  hPt5->SetXTitle("GeV/c");
+  hPt5->SetYTitle("N");*/
+
+  Char_t fname[256];
+  Int_t nFiles = 4;
+  for (Int_t iFile = 0; iFile < nFiles; iFile++) {
+
+    sprintf(fname,"%s/pythia6_%d.root",path,iFile);
+    TFile *f = new TFile(fname);
+    cout << "Opened file " << fname << endl;
+
+    TClonesArray* arr = new TClonesArray("TParticle");
+
+    TTree *tree = (TTree *) f->Get("pythia");
+    tree->GetBranch("particles")->SetAddress(&arr);
+    Int_t nEntries = tree->GetEntries();
+    
+    TParticle *p;
+    TParticle d1;
+    //TParticle d2;
+
+    for (Int_t i = 0; i < nEntries; i++) {
+      tree->GetEvent(i);
+      TClonesArray &part = *arr;
+      Int_t nPart = part.GetEntriesFast();
+      for (Int_t iPart = 0; iPart < nPart; iPart++) {
+       p = (TParticle*)part[iPart];
+       if (p->GetPdgCode()==3122){
+         
+          Int_t mother = p->GetFirstMother();
+
+         Int_t fdaughter = p->GetFirstDaughter();
+         Int_t ldaughter = p->GetLastDaughter();
+          d1 = (TParticle*)part[fdaughter-1];
+          //if (!d1) continue;
+          d2 = (TParticle*)part[ldaughter-1];
+         //cout << fdaughter << " " << ldaughter << endl;
+         //cout << d1->GetPdgCode() << " " << d2->GetPdgCode() << endl;
+
+         Double_t vx = d2->Vx();
+         Double_t vy = d2->Vy();
+         Double_t vz = d2->Vz();
+         Double_t vt = TMath::Sqrt((vx*vx)+(vy*vy));
+         Double_t vr = TMath::Sqrt((vx*vx)+(vy*vy)+(vz*vz));
+         Double_t pt = p->Pt();
+
+         hVr->Fill(vr);
+         if (vr < 10) hVr2->Fill(vr);
+         hVz->Fill(vz);
+         hPt->Fill(pt);
+         if (TMath::Abs(vz) < 10) 
+           {
+             hVz10->Fill(vz);
+             hPt10->Fill(pt);
+           }
+         if (TMath::Abs(vz) < 20)
+           {
+             hVz20->Fill(vz);
+             hPt20->Fill(pt);
+           }
+         if (TMath::Abs(vz) < 30)
+           {
+             hVz30->Fill(vz);
+             hPt30->Fill(pt);
+           }
+         if (TMath::Abs(vz) < 40)
+           {
+             hVz40->Fill(vz);
+             hPt40->Fill(pt);
+           }
+         if (TMath::Abs(vz) < 50)
+           {
+             hVz50->Fill(vz);
+             hPt50->Fill(pt);
+           }
+         if (TMath::Abs(vz) < 60)
+           {
+             hVz60->Fill(vz);
+             hPt60->Fill(pt);
+           }
+         if (TMath::Abs(vz) < 70)
+           {
+             hVz70->Fill(vz);
+             hPt70->Fill(pt);
+           }
+         if (TMath::Abs(vz) < 80)
+           {
+             hVz80->Fill(vz);
+             hPt80->Fill(pt);
+           }
+         if (TMath::Abs(vz) < 90)
+           {
+             hVz90->Fill(vz);
+             hPt90->Fill(pt);
+           }
+         if (TMath::Abs(vz) < 100)
+           {
+             hVz100->Fill(vz);
+             hPt100->Fill(pt);
+           }
+
+       }
+       
+      }
+      
+    }
+    
+  }
+  
+  //TCanvas *c = new TCanvas("c","c",50,50,600,800);
+  //c->Divide(1,2);
+  //c->cd(1);
+  //gPad->SetLogy();
+  //hVz->Draw();
+  //hPt->Draw();
+  //c->cd(2);
+  //gPad->SetLogy();
+  //hVz2->Draw();
+  //hPt3->Draw();
+
+  //hPt4->Divide(hPt2,hPt);
+  //hPt5->Divide(hPt3,hPt);
+  //TCanvas *c2 = new TCanvas("c2","c2",50,50,600,800);
+  //c2->Divide(1,2);
+  //c2->cd(1);
+  //hPt4->Draw();
+  //c2->cd(2);
+  //hPt5->Draw();
+
+  TFile *outfile = new TFile("/tmp/results.root","recreate");
+  hVr->Write();
+  hVr2->Write();
+
+  hVz->Write();
+  hVz10->Write();
+  hVz20->Write();
+  hVz30->Write();
+  hVz40->Write();
+  hVz50->Write();
+  hVz60->Write();
+  hVz70->Write();
+  hVz80->Write();
+  hVz90->Write();
+  hVz100->Write();
+
+  hPt->Write(); 
+  hPt10->Write();
+  hPt20->Write();
+  hPt30->Write();
+  hPt40->Write();
+  hPt50->Write();
+  hPt60->Write();
+  hPt70->Write();
+  hPt80->Write();
+  hPt90->Write();
+  hPt100->Write();
+
+  outfile->Close();
+  f->Close();
+
+}
+
diff --git a/HLT/exa/SetTrackingParameters_1000bf02.C b/HLT/exa/SetTrackingParameters_1000bf02.C
new file mode 100644 (file)
index 0000000..0a68f59
--- /dev/null
@@ -0,0 +1,32 @@
+void SetTrackingParameters(AliLevel3 *tracker)
+{
+  Int_t phi_segments,eta_segments,trackletlength,tracklength;
+  Int_t rowscopetracklet,rowscopetrack;
+  Double_t min_pt_fit,maxangle,goodDist,hitChi2Cut,xyerror,zerror;
+  Double_t goodHitChi2,trackChi2Cut,maxphi,maxeta;
+  
+  phi_segments = 50;//50;
+  eta_segments = 100;//100;
+  trackletlength = 3;
+  tracklength = 10;
+  rowscopetracklet = 2;
+  rowscopetrack = 4;
+  min_pt_fit = 0;
+  maxangle = 0.1745;
+  goodDist = 5;
+  maxphi = 0.1;
+  maxeta = 0.1;
+  hitChi2Cut = 100;
+  goodHitChi2 = 5;
+  trackChi2Cut = 50;
+      
+  xyerror = -1;
+  zerror =  -1;
+  
+  tracker->SetClusterFinderParam(xyerror,zerror,kTRUE);
+  tracker->SetTrackerParam(phi_segments,eta_segments,trackletlength,tracklength,
+                          rowscopetracklet,rowscopetrack,
+                          min_pt_fit,maxangle,goodDist,hitChi2Cut,
+                          goodHitChi2,trackChi2Cut,50,maxphi,maxeta,kTRUE);
+  
+}
diff --git a/HLT/exa/SetTrackingParameters_1000bf04.C b/HLT/exa/SetTrackingParameters_1000bf04.C
new file mode 100644 (file)
index 0000000..0a68f59
--- /dev/null
@@ -0,0 +1,32 @@
+void SetTrackingParameters(AliLevel3 *tracker)
+{
+  Int_t phi_segments,eta_segments,trackletlength,tracklength;
+  Int_t rowscopetracklet,rowscopetrack;
+  Double_t min_pt_fit,maxangle,goodDist,hitChi2Cut,xyerror,zerror;
+  Double_t goodHitChi2,trackChi2Cut,maxphi,maxeta;
+  
+  phi_segments = 50;//50;
+  eta_segments = 100;//100;
+  trackletlength = 3;
+  tracklength = 10;
+  rowscopetracklet = 2;
+  rowscopetrack = 4;
+  min_pt_fit = 0;
+  maxangle = 0.1745;
+  goodDist = 5;
+  maxphi = 0.1;
+  maxeta = 0.1;
+  hitChi2Cut = 100;
+  goodHitChi2 = 5;
+  trackChi2Cut = 50;
+      
+  xyerror = -1;
+  zerror =  -1;
+  
+  tracker->SetClusterFinderParam(xyerror,zerror,kTRUE);
+  tracker->SetTrackerParam(phi_segments,eta_segments,trackletlength,tracklength,
+                          rowscopetracklet,rowscopetrack,
+                          min_pt_fit,maxangle,goodDist,hitChi2Cut,
+                          goodHitChi2,trackChi2Cut,50,maxphi,maxeta,kTRUE);
+  
+}
diff --git a/HLT/exa/SetTrackingParameters_2000bf02.C b/HLT/exa/SetTrackingParameters_2000bf02.C
new file mode 100644 (file)
index 0000000..5675395
--- /dev/null
@@ -0,0 +1,32 @@
+void SetTrackingParameters(AliLevel3 *tracker)
+{
+  Int_t phi_segments,eta_segments,trackletlength,tracklength;
+  Int_t rowscopetracklet,rowscopetrack;
+  Double_t min_pt_fit,maxangle,goodDist,hitChi2Cut,xyerror,zerror;
+  Double_t goodHitChi2,trackChi2Cut,maxphi,maxeta;
+  
+  phi_segments = 50;//50;
+  eta_segments = 100;//100;
+  trackletlength = 3;
+  tracklength = 10;
+  rowscopetracklet = 2;
+  rowscopetrack = 4;
+  min_pt_fit = 0;
+  maxangle = 0.1745; //AliL3Transform::Deg2Rad(10);
+  goodDist = 5;
+  maxphi = 0.1;
+  maxeta = 0.1;
+  hitChi2Cut = 30;
+  goodHitChi2 = 5;
+  trackChi2Cut = 20;
+      //94.1
+  xyerror = -1;
+  zerror =  -1;
+  
+  tracker->SetClusterFinderParam(xyerror,zerror,kTRUE);
+  tracker->SetTrackerParam(phi_segments,eta_segments,trackletlength,tracklength,
+                          rowscopetracklet,rowscopetrack,
+                          min_pt_fit,maxangle,goodDist,hitChi2Cut,
+                          goodHitChi2,trackChi2Cut,50,maxphi,maxeta,kTRUE);
+  
+}
diff --git a/HLT/exa/SetTrackingParameters_2000bf04.C b/HLT/exa/SetTrackingParameters_2000bf04.C
new file mode 100644 (file)
index 0000000..1cdc5f9
--- /dev/null
@@ -0,0 +1,32 @@
+void SetTrackingParameters(AliLevel3 *tracker)
+{
+  Int_t phi_segments,eta_segments,trackletlength,tracklength;
+  Int_t rowscopetracklet,rowscopetrack;
+  Double_t min_pt_fit,maxangle,goodDist,hitChi2Cut,xyerror,zerror;
+  Double_t goodHitChi2,trackChi2Cut,maxphi,maxeta;
+  
+  phi_segments = 50;//50;
+  eta_segments = 100;//100;
+  trackletlength = 3;
+  tracklength = 10;
+  rowscopetracklet = 2;
+  rowscopetrack = 5;
+  min_pt_fit = 0;
+  maxangle = 0.1745; //AliL3Transform::Deg2Rad(10);
+  goodDist = 5;
+  maxphi = 0.1;
+  maxeta = 0.1;
+  hitChi2Cut = 30;
+  goodHitChi2 = 5;
+  trackChi2Cut = 20;
+      //90.3
+  xyerror = -1;
+  zerror =  -1;
+  
+  tracker->SetClusterFinderParam(xyerror,zerror,kTRUE);
+  tracker->SetTrackerParam(phi_segments,eta_segments,trackletlength,tracklength,
+                          rowscopetracklet,rowscopetrack,
+                          min_pt_fit,maxangle,goodDist,hitChi2Cut,
+                          goodHitChi2,trackChi2Cut,50,maxphi,maxeta,kTRUE);
+  
+}
diff --git a/HLT/exa/SetTrackingParameters_4000bf02.C b/HLT/exa/SetTrackingParameters_4000bf02.C
new file mode 100644 (file)
index 0000000..5a6b133
--- /dev/null
@@ -0,0 +1,32 @@
+void SetTrackingParameters(AliLevel3 *tracker)
+{
+  Int_t phi_segments,eta_segments,trackletlength,tracklength;
+  Int_t rowscopetracklet,rowscopetrack;
+  Double_t min_pt_fit,maxangle,goodDist,hitChi2Cut,xyerror,zerror;
+  Double_t goodHitChi2,trackChi2Cut,maxphi,maxeta;
+  
+  phi_segments = 50;//50;
+  eta_segments = 100;//100;
+  trackletlength = 3;
+  tracklength = 10;
+  rowscopetracklet = 2;
+  rowscopetrack = 10;
+  min_pt_fit = 0;
+  maxangle = 0.1745; //AliL3Transform::Deg2Rad(10);
+  goodDist = 5;
+  maxphi = 0.1;
+  maxeta = 0.1;
+  hitChi2Cut = 20;
+  goodHitChi2 = 5;
+  trackChi2Cut = 10;
+      //88.3
+  xyerror = -1;
+  zerror =  -1;
+  
+  tracker->SetClusterFinderParam(xyerror,zerror,kTRUE);
+  tracker->SetTrackerParam(phi_segments,eta_segments,trackletlength,tracklength,
+                          rowscopetracklet,rowscopetrack,
+                          min_pt_fit,maxangle,goodDist,hitChi2Cut,
+                          goodHitChi2,trackChi2Cut,50,maxphi,maxeta,kTRUE);
+  
+}
diff --git a/HLT/exa/SetTrackingParameters_4000bf04.C b/HLT/exa/SetTrackingParameters_4000bf04.C
new file mode 100644 (file)
index 0000000..ff39f11
--- /dev/null
@@ -0,0 +1,32 @@
+void SetTrackingParameters(AliLevel3 *tracker)
+{
+  Int_t phi_segments,eta_segments,trackletlength,tracklength;
+  Int_t rowscopetracklet,rowscopetrack;
+  Double_t min_pt_fit,maxangle,goodDist,hitChi2Cut,xyerror,zerror;
+  Double_t goodHitChi2,trackChi2Cut,maxphi,maxeta;
+  
+  phi_segments = 50;//50;
+  eta_segments = 100;//100;
+  trackletlength = 3;
+  tracklength = 10;
+  rowscopetracklet = 2;
+  rowscopetrack = 10;
+  min_pt_fit = 0;
+  maxangle = 0.1745; //AliL3Transform::Deg2Rad(10);
+  goodDist = 5;
+  maxphi = 0.1;
+  maxeta = 0.1;
+  hitChi2Cut = 20;
+  goodHitChi2 = 5;
+  trackChi2Cut = 10;
+      //77.8
+  xyerror = -1;
+  zerror =  -1;
+  
+  tracker->SetClusterFinderParam(xyerror,zerror,kTRUE);
+  tracker->SetTrackerParam(phi_segments,eta_segments,trackletlength,tracklength,
+                          rowscopetracklet,rowscopetrack,
+                          min_pt_fit,maxangle,goodDist,hitChi2Cut,
+                          goodHitChi2,trackChi2Cut,50,maxphi,maxeta,kTRUE);
+  
+}
diff --git a/HLT/exa/SetTrackingParameters_8000bf02.C b/HLT/exa/SetTrackingParameters_8000bf02.C
new file mode 100644 (file)
index 0000000..0112d78
--- /dev/null
@@ -0,0 +1,32 @@
+void SetTrackingParameters(AliLevel3 *tracker)
+{
+  Int_t phi_segments,eta_segments,trackletlength,tracklength;
+  Int_t rowscopetracklet,rowscopetrack;
+  Double_t min_pt_fit,maxangle,goodDist,hitChi2Cut,xyerror,zerror;
+  Double_t goodHitChi2,trackChi2Cut,maxphi,maxeta;
+  
+  phi_segments = 50;//50;
+  eta_segments = 100;//100;
+  trackletlength = 3;
+  tracklength = 10;
+  rowscopetracklet = 3;
+  rowscopetrack = 15;
+  min_pt_fit = 0;
+  maxangle = 0.1745; //AliL3Transform::Deg2Rad(10);
+  goodDist = 5;
+  maxphi = 0.1;
+  maxeta = 0.1;
+  hitChi2Cut = 10;
+  goodHitChi2 = 5;
+  trackChi2Cut = 5;
+      //63.3
+  xyerror = -1;
+  zerror =  -1;
+  
+  tracker->SetClusterFinderParam(xyerror,zerror,kTRUE);
+  tracker->SetTrackerParam(phi_segments,eta_segments,trackletlength,tracklength,
+                          rowscopetracklet,rowscopetrack,
+                          min_pt_fit,maxangle,goodDist,hitChi2Cut,
+                          goodHitChi2,trackChi2Cut,50,maxphi,maxeta,kTRUE);
+  
+}
diff --git a/HLT/exa/SetTrackingParameters_8000bf04.C b/HLT/exa/SetTrackingParameters_8000bf04.C
new file mode 100644 (file)
index 0000000..2cd1f84
--- /dev/null
@@ -0,0 +1,32 @@
+void SetTrackingParameters(AliLevel3 *tracker)
+{
+  Int_t phi_segments,eta_segments,trackletlength,tracklength;
+  Int_t rowscopetracklet,rowscopetrack;
+  Double_t min_pt_fit,maxangle,goodDist,hitChi2Cut,xyerror,zerror;
+  Double_t goodHitChi2,trackChi2Cut,maxphi,maxeta;
+  
+  phi_segments = 50;//50;
+  eta_segments = 100;//100;
+  trackletlength = 3;
+  tracklength = 10;
+  rowscopetracklet = 2;
+  rowscopetrack = 15;
+  min_pt_fit = 0;
+  maxangle = 0.1745; //AliL3Transform::Deg2Rad(10);
+  goodDist = 5;
+  maxphi = 0.1;
+  maxeta = 0.1;
+  hitChi2Cut = 15;
+  goodHitChi2 = 5;
+  trackChi2Cut = 5;
+      //47.6
+  xyerror = -1;
+  zerror =  -1;
+  
+  tracker->SetClusterFinderParam(xyerror,zerror,kTRUE);
+  tracker->SetTrackerParam(phi_segments,eta_segments,trackletlength,tracklength,
+                          rowscopetracklet,rowscopetrack,
+                          min_pt_fit,maxangle,goodDist,hitChi2Cut,
+                          goodHitChi2,trackChi2Cut,50,maxphi,maxeta,kTRUE);
+  
+}
diff --git a/HLT/exa/SetTrackingParameters_pp.C b/HLT/exa/SetTrackingParameters_pp.C
new file mode 100644 (file)
index 0000000..fddc3fc
--- /dev/null
@@ -0,0 +1,32 @@
+void SetTrackingParameters(AliLevel3 *tracker)
+{
+  Int_t phi_segments,eta_segments,trackletlength,tracklength;
+  Int_t rowscopetracklet,rowscopetrack;
+  Double_t min_pt_fit,maxangle,goodDist,hitChi2Cut,xyerror,zerror;
+  Double_t goodHitChi2,trackChi2Cut,maxphi,maxeta;
+  
+  phi_segments = 50;//50;
+  eta_segments = 100;//100;
+  trackletlength = 3;
+  tracklength = 10;
+  rowscopetracklet = 2;
+  rowscopetrack = 2;
+  min_pt_fit = 0;
+  maxangle = 0.1745; //AliL3Transform::Deg2Rad(10);
+  goodDist = 5;
+  maxphi = 0.1;
+  maxeta = 0.1;
+  hitChi2Cut = 100;
+  goodHitChi2 = 5;
+  trackChi2Cut = 50;
+      
+  xyerror = -1;
+  zerror =  -1;
+  
+  tracker->SetClusterFinderParam(xyerror,zerror,kTRUE);
+  tracker->SetTrackerParam(phi_segments,eta_segments,trackletlength,tracklength,
+                          rowscopetracklet,rowscopetrack,
+                          min_pt_fit,maxangle,goodDist,hitChi2Cut,
+                          goodHitChi2,trackChi2Cut,50,maxphi,maxeta,kTRUE);
+  
+}
index 957a014..3bf7321 100644 (file)
@@ -4,30 +4,33 @@
    Macro for converting AliRoot digits into L3 RawData. 
    Binary creates for each patch its own file. 
    Singlepatch uses one file per slice (sp=kTRUE). 
+   Run with ALIROOT (not root)
 */
 
-binary(char* in,int first, int last,char *path=".",Bool_t sp=kFALSE){
+binary(Char_t* inpath,Char_t *outpath,Int_t first,Int_t last,Int_t event,Bool_t sp=kFALSE){
+
+  AliL3Transform::Init(inpath,kTRUE);
 
-  AliL3Transform::Init(path);
-  
   if(sp) {
-    singlepatch(in,first,last,path);
+    singlepatch(inpath,outpath,first,last,event);
     return;
   }
 
-  char name[256];
+  Char_t name[256];
   const Int_t npatch = 6;
-  
+  Bool_t altrodigits=kFALSE;
+
+  sprintf(name,"%s/digitfile.root",inpath);
   AliL3FileHandler *fFileHandler = new AliL3FileHandler(); 
-  fFileHandler->SetAliInput(in);
+  fFileHandler->SetAliInput(name);
 
-  for(int slice=first; slice<=last; slice++){
-    for(int patch=0;patch<npatch;patch++){
-      cerr<<"reading slice: "<<slice<<" patch: "<<patch<<" and storing to: "<<path<<"/digits_"<<slice<<"_"<<patch<<".raw"<<endl;
+  for(Int_t slice=first; slice<=last; slice++){
+    for(Int_t patch=0;patch<npatch;patch++){
+      cerr<<"reading slice: "<<slice<<" patch: "<<patch<<" and storing to: "<<outpath<<"/digits_"<<slice<<"_"<<patch<<".raw"<<endl;
       fFileHandler->Init(slice,patch);      
-      sprintf(name,"%s/digits_%d_%d.raw",path,slice,patch);
+      sprintf(name,"%s/digits_%d_%d_%d.raw",outpath,event,slice,patch);
       fFileHandler->SetBinaryOutput(name);
-      fFileHandler->AliDigits2CompBinary();
+      fFileHandler->AliDigits2CompBinary(event,altrodigits);
       fFileHandler->CloseBinaryOutput();      
       fFileHandler->Free();
       cerr<<" done"<<endl;
@@ -36,7 +39,7 @@ binary(char* in,int first, int last,char *path=".",Bool_t sp=kFALSE){
   fFileHandler->CloseAliInput();
 }
 
-void write2rootfile(char *in,int first,int last,char *path)
+void write2rootfile(Char_t *in,Int_t first,Int_t last,Char_t *path)
 {
   //Write new rootfile, using data from the binary files. 
 
@@ -49,9 +52,9 @@ void write2rootfile(char *in,int first,int last,char *path)
       cout<<"Delete file "<<filename<<endl;
       return;
     }
-  for(int slice=first; slice<=last; slice++)
+  for(Int_t slice=first; slice<=last; slice++)
     {
-      for(int patch=0; patch<=5; patch++)
+      for(Int_t patch=0; patch<=5; patch++)
        {
          c = new AliL3Compress(slice,patch,path);
          c->WriteRootFile(filename,in);
@@ -61,29 +64,24 @@ void write2rootfile(char *in,int first,int last,char *path)
   
 }
  
-void singlepatch(char* in,int first=0, int last=0,char *path=".",int event=0)
+void singlepatch(Char_t* inpath,Char_t *outpath,Int_t first=0, Int_t last=0,Int_t event=0)
 {
-  AliL3Logger l;
-  //l.UnSet(AliL3Logger::kDebug);
-  //l.UnSet(AliL3Logger::kAll);
-  //l.Set(AliL3Logger::kInformational);
-  l.UseStderr();
-  //l.UseStream();
-  
-  char name[256];
+   
+  Char_t name[256];
   AliL3FileHandler *fFileHandler = new AliL3FileHandler(); 
-  fFileHandler->SetAliInput(in);
-
-  Int_t srow[2] = {0,175};
-  int patch=0;
-  for(int slice=first; slice<=last; slice++)
+  sprintf(name,"%s/digitfile.root",inpath);
+  fFileHandler->SetAliInput(name);
+  
+  Bool_t altrodigits=kFALSE;
+  Int_t patch=-1;
+  for(Int_t slice=first; slice<=last; slice++)
     {
       cerr<<"reading slice: "<<slice;
       fFileHandler->Free();
-      fFileHandler->Init(slice,patch,srow);
-      sprintf(name,"%s/digits_%d_%d.raw",path,slice,patch);
+      fFileHandler->Init(slice,patch);
+      sprintf(name,"%s/digits_%d_%d_%d.raw",outpath,event,slice,patch);
       fFileHandler->SetBinaryOutput(name);
-      fFileHandler->AliDigits2CompBinary(event);
+      fFileHandler->AliDigits2CompBinary(event,altrodigits);
       fFileHandler->CloseBinaryOutput();      
       cerr<<" done"<<endl;
     }
@@ -92,12 +90,5 @@ void singlepatch(char* in,int first=0, int last=0,char *path=".",int event=0)
 }
 
 void make_init_file(Char_t *f,Char_t *path="./"){
-  AliL3Logger l;
-  //l.UnSet(AliL3Logger::kDebug);
-  //l.UnSet(AliL3Logger::kAll);
-  //l.Set(AliL3Logger::kInformational);
-  l.UseStderr();
-  //l.UseStream();
-
   AliL3Transform::MakeInitFile(f,path);
 }
index 2daa8d8..2c277d8 100644 (file)
@@ -5,27 +5,42 @@
    Uses the AliL3Display class. 
 */
 
-void display(int minslice,int maxslice,char *file="tracks.raw",char *path="./",char *gfile="$(LEVEL3)/GEO/alice.geom")
+void display(Int_t minslice,Int_t maxslice,Char_t *file="tracks.raw",Char_t *path="./",Char_t *gfile="$(ALIGEOPATH)/alice.geom")
 {
-  AliL3Logger l;
-  //l.UnSet(AliL3Logger::kDebug);
-  //l.UnSet(AliL3Logger::kAll);
-  //l.Set(AliL3Logger::kInformational);
-  //l.UseStdout();
-  l.UseStream();
+  gStyle->SetOptStat(0);
+  Int_t slice[2] = {minslice,maxslice};
+
+  AliL3Display *a = new AliL3Display(slice,gfile);
+  //a->Setup(file,path);
+  a->Setup(file,path,0,kTRUE);
+  
+  
+  /* Choose one of the following */
+  a->DisplayAll();
+  //a->DisplayTracks();
+  //a->DisplayClusters();
+
+  //a->DisplayClusterRow(1,151,file,"colz");
+}
 
+
+void display_cl(Int_t ev=0,Char_t *path="./",Char_t *gfile="$(LEVEL3)/GEO/alice.geom")
+{
   gStyle->SetOptStat(0);
-  int slice[2] = {minslice,maxslice};
+  Int_t slice[2] = {0,35};
 
-  a = new AliL3Display(slice,gfile);
-  a->Setup(file,path);
-  //a->Setup("/prog/alice/data/Rawdata/1_patch/pp/recon_6/tracks.raw","/prog/alice/data/Rawdata/1_patch/pp/recon_6/");
+  Char_t file[1024];
+  sprintf(file,"%s/tracks_%d.raw",path,ev);
 
+  a = new AliL3Display(slice,gfile);
+  //a->Setup(file,path);
+  a->Setup(file,path,ev,kTRUE);
+  
+  
+  /* Choose one of the following */
   a->DisplayAll();
   //a->DisplayTracks();
   //a->DisplayClusters();
 
   //a->DisplayClusterRow(1,151,file,"colz");
 }
-
-
diff --git a/HLT/exa/eval.C b/HLT/exa/eval.C
deleted file mode 100644 (file)
index b8225b7..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-// $Id$
-
-void eval(char *inFile)
-{
-  // Connect the Root Galice file containing Geometry, Kine and Hits
-
-  file = new TFile(inFile);
-  
-  gAlice = (AliRun*)file->Get("gAlice");
-  if (gAlice) printf("AliRun object found on file\n");
-  if (!gAlice) gAlice = new AliRun("gAlice","Alice test program");
-  
-  gAlice->GetEvent(0);
-  AliTPC *TPC = (AliTPC*)gAlice->GetDetector("TPC");      
-  
-  AliTPCParam *param = (AliTPCParam*)file->Get("75x40_100x60");
-  
-  TFile *nfile = new TFile("/prog/alice/data/exact_clusters.root","RECREATE");
-  nfile->cd();
-
-  //setup AliTPCClustersArray
-  AliTPCClustersArray * arr=new AliTPCClustersArray;
-  arr->SetClusterType("AliComplexCluster");
-  arr->Setup(param);
-  TPC->SetParam(param);
-  arr->MakeTree();
-
-  TPC->SetClustersArray(arr); 
-  TPC->Hits2ExactClustersSector(1);
-  TPC->Hits2ExactClustersSector(37);
-    
-
-  //write results
-  char treeName[100];
-  sprintf(treeName,"TreeCExact_%s",param->GetTitle());
-  TPC->GetClustersArray()->GetTree()->Write(treeName);
-  param->Write(param->GetTitle());
-  file->Close();
-  nfile->Close();
-  
-  return;
-}
-
-void calc(char *rootfile,char *digitsfile,char *cfile)
-{
-
-  int slice[2] = {1,1};
-  a = new AliL3Evaluate(rootfile,digitsfile,slice);
-  a->SetupSlow("tracks.raw","./");
-  ntuppel = (TNtuple*)a->EvaluatePoints(cfile);
-
-  f = new TFile("results.root","RECREATE");
-  f->cd();
-  ntuppel->Write();
-  f->Close();
-
-}
-
-void plot(char *file)
-{
-  gStyle->SetOptFit(0110);
-  f = new TFile(file);
-  
-  TCanvas *c1 = new TCanvas("c1","",2);
-  TH1F *hist = new TH1F("hist","",100,-2,2);
-  
-  ntuppel->Draw("resy>>hist","pt>1");
-
-  float rms = hist->GetRMS();
-  hist->SetXTitle("#delta_{T} [cm]");
-
-  TF1 *f1 = new TF1("f1","gaus",-rms,rms);
-  hist->Fit("f1","R");
-
-}
diff --git a/HLT/exa/fill_pp.C b/HLT/exa/fill_pp.C
new file mode 100644 (file)
index 0000000..557d0f4
--- /dev/null
@@ -0,0 +1,594 @@
+// $Id$
+
+
+/**
+   fill_pp -> store track info in ntuple root file
+   fill_good_tracks_pp -> store good track info in ntuple root file
+   print_pp -> print selected events from ntuple root file
+   plot_pp -> plot parts of selected events from ntuple root file
+   eval_pp -> simple evaluation of impact parameter cut effects
+   Author: C. Loizides
+*/
+
+
+/* ---fill_pp---
+   Fill ntuple with relevant pp event data 
+   from the tracks files:
+
+   Ev is the event number to use
+   Path gives the path where you find the digit files (and possibly also l3transform.config)
+   Rfile gives the root file where the information will be added
+   Saveev will be Ev unless you specify something else (useful for storing the trigger event of pilup events)
+*/
+
+void fill_pp(Int_t ev=0,Char_t *path="./",Char_t *rfile="pptracks.root",Int_t saveev=-1)
+{
+  AliL3Logger l;
+  l.Set(AliL3Logger::kAll);
+  l.UseStdout();
+  //l.UseStream();
+
+  if(getenv("TRANSFORMCONFIGPATH")){
+    AliL3Transform::Init(getenv("TRANSFORMCONFIGPATH"));
+  } else AliL3Transform::Init(path);
+
+  TNtuple *ntuppel = new TNtuple("ntuppel","pptracks","pt:phi:eta:xvert:yvert:zvert:imp:nhits:px:py:pz:event:mc");
+  Float_t meas[13];  
+
+  TFile file(rfile,"UPDATE");
+  Char_t name[1024];
+
+  AliL3Evaluate *eval=new AliL3Evaluate(path,63,63);
+  eval->LoadData(ev,-1);
+  eval->AssignIDs();
+
+  AliL3TrackArray *a=eval->GetTracks();
+  a->Compress();
+
+  AliL3Track t;
+  Float_t phi,pt,eta;
+  Int_t id;
+  Int_t nhits;
+
+  AliL3Vertex vertex;
+  Double_t xc,yc,zc,impact;
+
+  Int_t ntracks=a.GetNTracks();
+  for(Int_t i=0;i<ntracks;i++){
+    t.Set(a.GetTrack(i));
+
+    t.CalculateHelix();
+    t.GetClosestPoint(&vertex,xc,yc,zc);
+
+    nhits=t.GetNHits();
+    if(nhits<63) continue;
+    pt=t.GetPt();
+    eta=t.GetPseudoRapidity();
+    phi=t.GetPsi();
+    id=t.GetMCid();
+
+    //impact=TMath::fabs(zc);
+    impact=TMath::Sqrt(xc*xc+yc*yc+zc*zc);
+
+    meas[0]=pt;
+    meas[1]=phi;
+    meas[2]=eta;
+    meas[3]=xc;
+    meas[4]=yc;   
+    meas[5]=zc;
+    meas[6]=impact;   
+    meas[7]=nhits;
+    meas[8]=t.GetPx();
+    meas[9]=t.GetPy();
+    meas[10]=t.GetPz();
+    meas[11]=ev;
+    meas[12]=id;
+
+    ntuppel->Fill(meas);
+
+    cout << i << ": pt " << pt << " " << phi << " " << eta << " " << id << " nhits " << nhits << " impact " << impact << endl;
+
+    //if(id!=-1) cout << "mc " << id << " " << t.GetCenterX() << " " << t.GetCenterY() << " " << t.GetRadius() << " fst point " << t.GetFirstPointX() << " " << t.GetFirstPointY() << " " << t.GetFirstPointZ() << " tgl " << t.GetTgl() << endl;
+  } 
+
+  if(saveev==-1) saveev=ev;
+  sprintf(name,"pptracks-%d",saveev);
+  ntuppel->Write(name);
+  file.Close();
+
+  delete ntuppel;
+  delete eval;
+}
+
+/*--fill_good_tracks_pp--
+
+  Fill good tracks taken from offline into ntuple root file for later evaluation.
+
+  Evs is the event to start with
+  Eve is the last event to process
+  Path gives the path where the offline good_particles_tpc files are
+  Rfile specifies the recreated root file where the ntuples will be stored
+*/
+
+void fill_good_tracks_pp(Int_t evs=0,Int_t eve=100,Char_t *path="./",Char_t *rfile="pp-good-tracks.root")
+{
+  TFile file(rfile,"RECREATE");
+  if(!file.IsOpen()) return;
+
+  Float_t meas[10];  
+  Char_t name[1024];
+
+  for(Int_t i=evs;i<eve;i++){
+    TNtuple *ntuppel = new TNtuple("ntuppel-goodtracks","good-pptracks","mc:pdg:px:py:pz:xvert:yvert:zvert:nhits:sector");
+
+    sprintf(name,"%s/good_tracks_tpc_%d",path,i);
+    FILE *f=fopen(name,"r");
+    cout << "Event " << i << " " << name << endl;
+
+    while(!feof(f)){
+      Int_t mc,pdg,nhits,sector;
+      Float_t px,py,pz,xv,yv,zv;
+      fscanf(f,"%d %d %f %f %f %f %f %f %d %d\n",&mc,&pdg,&px,&py,&pz,&xv,&yv,&zv,&nhits,&sector);
+      
+      if(nhits<63) continue;
+      if((px==0)&&(py==0)&&(pz==0)) continue;
+      if((xv==0)&&(yv==0)&&(zv==0)) continue;
+
+      //cout << mc << " " << pdg << " " << px << " " << py << " " << pz << " " << xv << " " << yv << " " << zv << " " << nhits << " " << sector << endl;
+
+      meas[0]=mc;      
+      meas[1]=pdg;      
+      meas[2]=px;      
+      meas[3]=py;      
+      meas[4]=pz;      
+      meas[5]=xv;      
+      meas[6]=yv;      
+      meas[7]=zv;      
+      meas[8]=nhits;      
+      meas[9]=sector;      
+      
+      ntuppel->Fill(meas);
+    }
+    fclose(f);
+    sprintf(name,"good-pptracks-%d",i);
+    ntuppel->Write(name);
+    delete ntuppel;
+  }
+
+  file.Close();
+}
+
+/* ---print_pp---
+   Looping over event reading root file containing ntuples 
+   and printing wanted information:
+
+   Pfile specifies the root file created with fill_pp
+   Evi gives the first event to print
+   Eve the last event to print
+*/
+
+void print_pp(Char_t *pfile, Int_t evi=0, Int_t eve=-1)
+{
+  TFile file1=TFile(pfile,"READ");
+
+  if(!file1.IsOpen()) return;
+
+  //"pt:phi:eta:xvert:yvert:zvert:imp:nhits:px:py:pz:event:mc")
+  Float_t pt1,phi1,eta1,xvert1,yvert1,zvert1,imp1,nhits1,px1,py1,pz1,event1,mc1; //pileup
+  Float_t pt2,phi2,eta2,xvert2,yvert2,zvert2,imp2,nhits2,px2,py2,pz2,event2,mc2; //pp
+
+  Int_t nent1;
+  Char_t dummy[1024];
+  if(eve==-1) eve=evi;
+
+  for(Int_t i=evi;i<=eve;i++){ //loop over pileup-events
+    sprintf(dummy,"pptracks-%d",i);
+    TNtuple *ntuppel1 = (TNtuple*)file1.Get(dummy);
+    ntuppel1->SetBranchAddress("pt",&pt1);
+    ntuppel1->SetBranchAddress("phi",&phi1);
+    ntuppel1->SetBranchAddress("eta",&eta1);
+    ntuppel1->SetBranchAddress("xvert",&xvert1);
+    ntuppel1->SetBranchAddress("yvert",&yvert1);
+    ntuppel1->SetBranchAddress("zvert",&zvert1);
+    ntuppel1->SetBranchAddress("imp",&imp1);
+    ntuppel1->SetBranchAddress("px",&px1);
+    ntuppel1->SetBranchAddress("py",&py1);
+    ntuppel1->SetBranchAddress("pz",&pz1);
+    ntuppel1->SetBranchAddress("event",&event1);
+    ntuppel1->SetBranchAddress("mc",&mc1);
+
+    nent1=ntuppel1->GetEntries();
+    cout << "Event: " << i << " " << nent1 << " tracks" << endl;
+    for(Int_t j=0;j<nent1;j++){
+      ntuppel1->GetEvent(j);
+
+      Float_t bt=TMath::Sqrt(xvert1*xvert1+yvert1*yvert1);
+      Float_t bz=TMath::fabs(zvert1);
+
+      if(mc1!=-1)
+      cout << j << ": " << event1 << " " << pt1 << " " << phi1 << " " << eta1 << " mc " << mc1 << " bt " << bt << " bz " << bz << endl;
+
+    }//pp track loop
+  }//pileup loop
+
+  file1.Close();
+}
+
+/* ---plot_pp---
+   Plot some variables from the ntuples (currently impact parameter
+   but easily changeable.
+
+   Pfile is the root file containing the ntuples.
+   Evi and Eve are start and end event number to process
+*/
+
+void plot_pp(Char_t *pfile, Int_t evi=0, Int_t eve=100)
+{
+  TH1F *hist1=new TH1F("h1","test",100,0,1000);
+
+  TFile file1=TFile(pfile,"READ");
+
+  if(!file1.IsOpen()) return;
+
+  //"pt:phi:eta:xvert:yvert:zvert:imp:nhits:px:py:pz:event:mc")
+  Float_t pt1,phi1,eta1,xvert1,yvert1,zvert1,imp1,nhits1,px1,py1,pz1,event1,mc1; //pileup
+  Float_t pt2,phi2,eta2,xvert2,yvert2,zvert2,imp2,nhits2,px2,py2,pz2,event2,mc2; //pp
+
+  Int_t nent1;
+  Char_t dummy[1024];
+
+  for(Int_t i=evi;i<eve;i++){ //loop over pileup-events
+    sprintf(dummy,"pptracks-%d",i);
+    TNtuple *ntuppel1 = (TNtuple*)file1.Get(dummy);
+    if(!ntuppel1){
+      cerr << "Error getting ntuple from " << dummy<<endl;
+      continue;
+    } 
+    ntuppel1->SetBranchAddress("pt",&pt1);
+    ntuppel1->SetBranchAddress("phi",&phi1);
+    ntuppel1->SetBranchAddress("eta",&eta1);
+    ntuppel1->SetBranchAddress("xvert",&xvert1);
+    ntuppel1->SetBranchAddress("yvert",&yvert1);
+    ntuppel1->SetBranchAddress("zvert",&zvert1);
+    ntuppel1->SetBranchAddress("imp",&imp1);
+    ntuppel1->SetBranchAddress("px",&px1);
+    ntuppel1->SetBranchAddress("py",&py1);
+    ntuppel1->SetBranchAddress("pz",&pz1);
+    ntuppel1->SetBranchAddress("event",&event1);
+    ntuppel1->SetBranchAddress("mc",&mc1);
+
+    nent1=ntuppel1->GetEntries();
+    cout << "Event: " << i << " " << nent1 << " tracks" << endl;
+    for(Int_t j=0;j<nent1;j++){
+      ntuppel1->GetEvent(j);
+
+      if(TMath::fabs(eta1)>0.9) continue;
+      if(pt1<0.1) continue;
+
+      Float_t bt=TMath::Sqrt(xvert1*xvert1+yvert1*yvert1);
+      Float_t bz=TMath::fabs(zvert1);
+      hist1->Fill(bz,1);
+    }//pp track loop
+  }//pileup loop
+
+  file1.Close();
+
+  hist1->Sumw2();
+  hist1->Draw("e1p");
+}
+
+/* ---eval_pp---
+   Little macro to play with pp pileup evaluation and do some
+   counting. See real trigger macro trigger.C instead.
+
+   Ev is the event number
+   Path is the path to the track arrays.
+*/
+
+void eval_pp(Int_t ev=0,Char_t *path="./")
+{
+  AliL3Logger l;
+  l.Set(AliL3Logger::kAll);
+  l.UseStdout();
+  //l.UseStream();
+
+  AliL3Evaluate *eval=new AliL3Evaluate(path,63,63);
+  eval->LoadData(ev,-1);
+  eval->AssignIDs();
+
+  AliL3TrackArray *a=eval->GetTracks();
+
+  AliL3Track t;
+  Float_t phi,pt,tgl,eta;
+  Int_t id;
+  Int_t nhits;
+  Int_t abspos=0,pos=0,absneg=0,neg=0;
+  //assume vertex around zero
+  AliL3Vertex vertex;
+  Double_t xc,yc,zc,impact;
+
+  Int_t nents=0;
+  Int_t ntracks=a.GetNTracks();
+  for(Int_t i=0;i<ntracks;i++){
+    t.Set(a.GetTrack(i));
+
+    t.CalculateHelix();
+    t.GetClosestPoint(&vertex,xc,yc,zc);
+
+    nhits=t.GetNHits();
+    if(nhits<63) continue;
+    pt=t.GetPt();
+    tgl=t.GetTgl();
+    phi=100;
+    id=t.GetMCid();
+    cout << id << endl;
+    if(t.GetPy()!=0) phi=TMath::ATan(t.GetPy()/t.GetPx());
+
+    //impact=TMath::fabs(zc);
+    impact=TMath::Sqrt(xc*xc+yc*yc+zc*zc);
+
+    cout << i << ": pt " << pt << " " << phi << " " << tgl << " " << id << " nhits " << nhits << " impact " << impact << endl;
+
+    if(id<0) absneg++;
+    else abspos++;
+    nents++;
+    if(impact>10) continue;
+    if(id<0) neg++;
+    else pos++;
+  } 
+
+  cout << "Result: " << nents << " " << abspos << " " << absneg << endl;
+  cout << "After cut: " << pos << " " << neg << endl;
+}
+
+void simple_eff_pp(Char_t *pfile, Char_t *reffile, Int_t evi=0, Int_t eve=100,Int_t cut=-1)
+{
+  //"pt:phi:eta:xvert:yvert:zvert:imp:nhits:px:py:pz:event:mc")
+  Float_t pt1,phi1,eta1,xvert1,yvert1,zvert1,imp1,nhits1,px1,py1,pz1,event1,mc1; //pileup
+  Float_t pt2,phi2,eta2,xvert2,yvert2,zvert2,imp2,nhits2,px2,py2,pz2,event2,mc2; //pp
+
+  Int_t countgoodevents=0;
+  Int_t nent1,nent2;
+  Char_t dummy[1024];
+
+  Int_t tnorm;
+  Int_t fnorm;
+  Int_t pnorm;
+  Int_t tcounts=0;
+  Int_t fcounts=0;
+  Int_t pcounts=0;
+  Float_t fmean=0;
+  Float_t pmean=0;
+
+  TFile file1=TFile(pfile,"READ");
+  TFile file2=TFile(reffile,"READ");
+  if(!file1.IsOpen() || !file2.IsOpen()) return;
+
+  for(Int_t i=evi;i<eve;i++){ //loop over pileup-events
+    sprintf(dummy,"pptracks-%d",i);
+    TNtuple *ntuppel1 = (TNtuple*)file1.Get(dummy);
+    ntuppel1->SetBranchAddress("pt",&pt1);
+    ntuppel1->SetBranchAddress("phi",&phi1);
+    ntuppel1->SetBranchAddress("eta",&eta1);
+    ntuppel1->SetBranchAddress("xvert",&xvert1);
+    ntuppel1->SetBranchAddress("yvert",&yvert1);
+    ntuppel1->SetBranchAddress("zvert",&zvert1);
+    ntuppel1->SetBranchAddress("imp",&imp1);
+    ntuppel1->SetBranchAddress("px",&px1);
+    ntuppel1->SetBranchAddress("py",&py1);
+    ntuppel1->SetBranchAddress("pz",&pz1);
+    ntuppel1->SetBranchAddress("event",&event1);
+    ntuppel1->SetBranchAddress("mc",&mc1);
+
+    tnorm=0;
+    fnorm=0;
+    pnorm=0;
+    nent1=ntuppel1->GetEntries();
+    for(Int_t j=0;j<nent1;j++){
+      ntuppel1->GetEvent(j);
+
+      if(j==0){ //get info of triggered event from file2
+       
+       sprintf(dummy,"good-pptracks-%d",event1);
+       TNtuple *ntuppel2 = (TNtuple*)file2.Get(dummy);
+       Float_t nhits2,pdg2,sector2;
+       if(ntuppel2){
+         ntuppel2->SetBranchAddress("mc",&mc2);
+         ntuppel2->SetBranchAddress("pdg",&pdg2);
+         ntuppel2->SetBranchAddress("px",&px2);
+         ntuppel2->SetBranchAddress("py",&py2);
+         ntuppel2->SetBranchAddress("pz",&pz2);
+         ntuppel2->SetBranchAddress("xvert",&xvert2);
+         ntuppel2->SetBranchAddress("yvert",&yvert2);
+         ntuppel2->SetBranchAddress("zvert",&zvert2);
+         ntuppel2->SetBranchAddress("nhits",&nhits2);
+         ntuppel2->SetBranchAddress("sector",&sector2);
+         nent2=ntuppel2->GetEntries();
+         for(Int_t k=0;k<nent2;k++){
+           ntuppel2->GetEvent(k);
+           if(mc2<0)continue; //dont count fake tracks
+           //if(TMath::fabs(zvert2)>30) continue;
+           pt2=TMath::Sqrt(px2*px2+py2*py2);
+           if(nhits2<63) continue;
+           if(pt2<0.1) continue;
+           if((px2==0)&&(py2==0)&&(pz2==0)) continue;
+           Float_t p=TMath::Sqrt(px2*px2+py2*py2+pz2*pz2);
+           eta2=0.5*TMath::log((p+pz2)/(p-pz2));
+           if(TMath::fabs(eta2)>0.9) continue;
+           tnorm++;
+         }
+       } else {
+         sprintf(dummy,"pptracks-%d",event1);
+         TNtuple *ntuppel2 = (TNtuple*)file2.Get(dummy);
+         if(ntuppel2){
+           ntuppel2->SetBranchAddress("pt",&pt2);
+           ntuppel2->SetBranchAddress("phi",&phi2);
+           ntuppel2->SetBranchAddress("eta",&eta2);
+           ntuppel2->SetBranchAddress("xvert",&xvert2);
+           ntuppel2->SetBranchAddress("yvert",&yvert2);
+           ntuppel2->SetBranchAddress("zvert",&zvert2);
+           ntuppel2->SetBranchAddress("imp",&imp2);
+           ntuppel2->SetBranchAddress("px",&px2);
+           ntuppel2->SetBranchAddress("py",&py2);
+           ntuppel2->SetBranchAddress("pz",&pz2);
+           ntuppel2->SetBranchAddress("event",&event2);
+           ntuppel2->SetBranchAddress("mc",&mc2);
+
+           nent2=ntuppel2->GetEntries();
+           for(Int_t k=0;k<nent2;k++){
+             ntuppel2->GetEvent(k);
+             if(mc2<0)continue; //dont count fake tracks
+             if(pt2<0.1) continue;
+             //if(TMath::fabs(zvert2)>30) continue;
+             if(TMath::fabs(eta2)>0.9) continue;
+             tnorm++;
+           }
+         }
+       }
+      }
+      if(tnorm==0){
+       tnorm=0;
+       break; //triggered event has to have one track at least
+      }
+      
+      if(pt1<0.1) continue;
+      if(TMath::fabs(eta1>0.9)) continue;
+
+      if(mc1<-1) continue; //dont count fake tracks
+      else if(mc1==-1) fnorm++; //count tracks from pileup
+      else {
+       if((cut>0)&&(zvert1>cut)) continue;
+       pnorm++; //count real tracks
+      }
+    }//pp track loop
+
+    if(tnorm==0) continue; //break from above
+    if(pnorm>tnorm) pnorm=tnorm; //prob. multiple found tracks
+    countgoodevents++; //for normalization
+    fcounts+=fnorm;
+    pcounts+=pnorm;
+    tcounts+=tnorm;
+    pmean+=(Float_t)pnorm/(Float_t)tnorm;
+    fmean+=(Float_t)fnorm/(Float_t)tnorm;
+ &