// that format.
//
// #include <AliLog.h> // ALILOG_H
-#include "AliFMDDebug.h" // Better debug macros
+#include "AliFMDDebug.h" // Better debug macros
#include <AliLoader.h> // ALILOADER_H
-#include <AliAltroBuffer.h> // ALIALTROBUFFER_H
+#include <AliAltroBufferV3.h> // ALIALTROBUFFER_H
#include "AliFMD.h" // ALIFMD_H
#include "AliFMDParameters.h" // ALIFMDPARAMETERS_H
#include "AliFMDDigit.h" // ALIFMDDIGIT_H
#include "AliFMDAltroMapping.h" // ALIFMDALTROMAPPING_H
// #include "AliFMDAltroIO.h" // ALIFMDALTROWRITER_H
#include <TArrayI.h> // ROOT_TArrayI
+#include <TArrayF.h> // ROOT_TArrayI
+#include <TArrayC.h> // ROOT_TArrayI
#include <TClonesArray.h> // ROOT_TClonesArray
+#include <TTree.h>
// #include <fstream>
#include "AliDAQ.h"
return;
}
- TClonesArray* digits = new TClonesArray("AliFMDDigit", 1000);
fFMD->SetTreeAddress();
- TBranch* digitBranch = digitTree->GetBranch(fFMD->GetName());
- if (!digitBranch) {
- AliError(Form("no branch for %s", fFMD->GetName()));
- return;
- }
- digitBranch->SetAddress(&digits);
+ TClonesArray* digits = fFMD->Digits();
+ // new TClonesArray("AliFMDDigit", 1000);
+ // TBranch* digitBranch = digitTree->GetBranch(fFMD->GetName());
+ // if (!digitBranch) {
+ // AliError(Form("no branch for %s", fFMD->GetName()));
+ // return;
+ // }
+ // digitBranch->SetAddress(&digits);
Int_t nEvents = Int_t(digitTree->GetEntries());
AliFMDDebug(5, ("Got a total of %5d events from tree", nEvents));
WriteDigits(digits);
}
loader->UnloadDigits();
+ //delete digits;
}
#if 1
//____________________________________________________________________
-void
+Long_t
AliFMDRawWriter::WriteDigits(TClonesArray* digits)
{
// WRite an array of digits to disk file
Int_t nDigits = digits->GetEntries();
- if (nDigits < 1) return;
+ if (nDigits < 1) return 0;
AliFMDDebug(5, ("Got a total of %5d digits from tree", nDigits));
AliFMDParameters* pars = AliFMDParameters::Instance();
// Which channel number in the ALTRO channel we're at
UShort_t nWords = 0;
UShort_t preSamples = 0;
-
- // How many times the ALTRO Samples one VA1_ALICE channel
- Int_t sampleRate = 1;
+ UShort_t sampleRate = 0;
// A buffer to hold 1 ALTRO channel - Normally, one ALTRO channel
// holds 128 VA1_ALICE channels, sampled at a rate of `sampleRate'
TArrayI data(pars->GetChannelsPerAltro() * 8);
+ TArrayF peds(pars->GetChannelsPerAltro() * 8);
+ TArrayF noise(pars->GetChannelsPerAltro() * 8);
// The Altro buffer
- AliAltroBuffer* altro = 0;
-
+ AliAltroBufferV3* altro = 0;
+
+ Int_t totalWords = 0;
+ Int_t nCounts = 0;
+ Long_t nBits = 0;
+
// Loop over the digits in the event. Note, that we assume the
// the digits are in order in the branch. If they were not, we'd
// have to cache all channels before we could write the data to
Char_t ring = digit->Ring();
UShort_t sector = digit->Sector();
UShort_t strip = digit->Strip();
- UInt_t ddl;
- UInt_t addr;
+ UShort_t ddl, addr, time;
+
+ AliFMDDebug(15, ("Processing digit # %5d FMD%d%c[%2d,%3d]",
+ i, det, ring, sector, strip));
+ threshold = pars->GetZeroSuppression(det, ring, sector, strip);
+ sampleRate = pars->GetSampleRate(det, ring, sector, strip);
+ preSamples = pars->GetPreSamples(det, ring, sector, strip);
+
if (det != oldDet) {
AliFMDDebug(5, ("Got new detector: %d (was %d)", det, oldDet));
oldDet = det;
}
- AliFMDDebug(10, ("Processing digit # %5d FMD%d%c[%2d,%3d]",
- i, det, ring, sector, strip));
- threshold = pars->GetZeroSuppression(det, ring, sector, strip);
- if (!pars->Detector2Hardware(det, ring, sector, strip, ddl, addr)) {
- AliError(Form("Failed to get hardware address for FMD%d%c[%2d,%3d]",
- det, ring, sector, strip));
- continue;
- }
- preSamples = pars->GetPreSamples(det, ring, sector, strip);
+ AliFMDDebug(15, ("Sample rate is %d", sampleRate));
- AliFMDDebug(10, ("FMD%d%c[%2d,%3d]-> ddl: 0x%x addr: 0x%x",
- det, ring, sector, strip, ddl, addr));
- if (addr != prevaddr) {
- // Flush a channel to output
- AliFMDDebug(15, ("Now hardware address 0x%x from FMD%d%c[%2d,%3d] "
- "(board 0x%x, chip 0x%x, channel 0x%x), flushing old "
- "channel at 0x%x with %d words",
- addr, det, ring, sector, strip,
- (addr >> 7), (addr >> 4) & 0x7, addr & 0xf,
- prevaddr, nWords));
- if (altro) altro->WriteChannel(prevaddr,nWords,data.fArray,threshold);
- nWords = preSamples;
- prevaddr = addr;
- for (size_t j = 0; j < nWords; j++) data[j] = digit->Count(0);
- }
- if (ddl != prevddl) {
- AliFMDDebug(5, ("FMD: New DDL, was %d, now %d", prevddl, ddl));
- // If an altro exists, delete the object, flushing the data to
- // disk, and closing the file.
- if (altro) {
- // When the first argument is false, we write the real
- // header.
- AliFMDDebug(15, ("Closing output"));
- altro->Flush();
- altro->WriteDataHeader(kFALSE, kFALSE);
- delete altro;
- altro = 0;
+ for (UShort_t j = 0; j < sampleRate; j++) {
+ if (!pars->Detector2Hardware(det,ring,sector,strip,j,ddl,addr,time)){
+ AliError(Form("Failed to get hardware address for FMD%d%c[%2d,%3d]-%d",
+ det, ring, sector, strip, j));
+ continue;
}
- prevddl = ddl;
- // Need to open a new DDL!
- TString filename(AliDAQ::DdlFileName(fFMD->GetName(), ddl));
- AliFMDDebug(5, ("New altro buffer with DDL file %s", filename.Data()));
- // Create a new altro buffer - a `1' as the second argument
- // means `write mode'
- altro = new AliAltroBuffer(filename.Data());
- altro->SetMapping(pars->GetAltroMap());
- // Write a dummy (first argument is true) header to the DDL
- // file - later on, when we close the file, we write the real
- // header
- altro->WriteDataHeader(kTRUE, kFALSE);
- }
- // Store the counts of the ADC in the channel buffer
- sampleRate = pars->GetSampleRate(det, ring, sector, strip);
- for (int s = 0; s < sampleRate; s++) {
- data[nWords] = digit->Count(s);
+ AliFMDDebug(10, ("FMD%d%c[%2d,%3d]-%d-> 0x%x/0x%x/%04d",
+ det, ring, sector, strip, j, ddl, addr, time));
+ if (addr != prevaddr) {
+ // Flush a channel to output
+ AliFMDDebug(5, ("Now hardware address 0x%x from FMD%d%c[%2d,%3d]-%d"
+ "(b: 0x%02x, a: 0x%01x, c: 0x%02x, t: %04d), "
+ "flushing old channel at 0x%x with %d words",
+ addr, det, ring, sector, strip, j,
+ (addr >> 7), (addr >> 4) & 0x7, addr & 0xf,
+ time, prevaddr, nWords));
+ totalWords += nWords;
+ ZeroSuppress(data.fArray, nWords, peds.fArray, noise.fArray, threshold);
+ if (altro)
+ /*nBits+=*/altro->WriteChannel(prevaddr,nWords,data.fArray,threshold);
+ data.Reset(-1);
+ peds.Reset(0);
+ noise.Reset(0);
+ nWords = 0;
+ prevaddr = addr;
+ }
+ if (ddl != prevddl) {
+ AliFMDDebug(10, ("FMD: New DDL, was %d, now %d", prevddl, ddl));
+ // If an altro exists, delete the object, flushing the data to
+ // disk, and closing the file.
+ if (altro) {
+ // When the first argument is false, we write the real
+ // header.
+ AliFMDDebug(15, ("Closing output"));
+ /* nBits += */ altro->Flush();
+ /* nBits += */ altro->WriteDataHeader(kFALSE, kFALSE);
+ delete altro;
+ altro = 0;
+ }
+ prevddl = ddl;
+ // Need to open a new DDL!
+ TString filename(AliDAQ::DdlFileName(fFMD ? fFMD->GetName() : "FMD", ddl));
+ AliFMDDebug(5, ("New altro buffer with DDL file %s", filename.Data()));
+ // Create a new altro buffer - a `1' as the second argument
+ // means `write mode'
+ altro = new AliAltroBufferV3(filename.Data());
+ altro->SetMapping(pars->GetAltroMap());
+ // Write a dummy (first argument is true) header to the DDL
+ // file - later on, when we close the file, we write the real
+ // header
+ altro->WriteDataHeader(kTRUE, kFALSE);
+ }
+
+ // Get the pedestal value
+ peds[time] = pars->GetPedestal(det, ring, sector, strip);
+ noise[time] = pars->GetPedestalWidth(det, ring, sector, strip);
+
+ // Store the counts of the ADC in the channel buffer
+ AliFMDDebug(15, ("Storing FMD%d%c[%02d,%03d]-%d in timebin %d (%d)",
+ det, ring, sector, strip, j, time, preSamples));
+ data[time] = digit->Count(j);
nWords++;
+ nCounts++;
+ if (time == preSamples) {
+ AliFMDDebug(15, ("Filling in %4d for %d presamples",
+ data[time], preSamples));
+ for (int k = 0; k < preSamples; k++) {
+ peds[k] = peds[time];
+ noise[k] = noise[time];
+ data[k] = data[time];
+ }
+ nWords += preSamples;
+ }
}
}
// Finally, we need to close the final ALTRO buffer if it wasn't
// already
if (altro) {
- if (nWords > 0) altro->WriteChannel(prevaddr,nWords,data.fArray,threshold);
- altro->Flush();
- altro->WriteDataHeader(kFALSE, kFALSE);
+ ZeroSuppress(data.fArray, nWords, peds.fArray, noise.fArray, threshold);
+ if (nWords > 0)
+ /* nBits += */ altro->WriteChannel(prevaddr,nWords,data.fArray,threshold);
+ /* nBits += */ altro->Flush();
+ /* nBits += */ altro->WriteDataHeader(kFALSE, kFALSE);
delete altro;
}
+ AliFMDDebug(5, ("Wrote a total of %d words in %ld bytes for %d counts",
+ nWords, nBits / 8, nCounts));
+ return nBits;
}
+//____________________________________________________________________
+void
+AliFMDRawWriter::ZeroSuppress(Int_t*& data, Int_t nWords,
+ const Float_t* peds,
+ const Float_t* noise, UShort_t threshold) const
+{
+ // Simulate the ALTRO zero-suppression filter. The data passed in
+ // the first array is modified, such that all suppressed channels
+ // are set to some value below threshold.
+ //
+ // If threshold == 0 zero suppression is considered disabled, and no
+ // action is taken.
+ if (threshold <= 0) return;
+
+ // const Short_t width = 3;
+ // If fPedSubtract is false, compare data-(ped+f*noise), if true
+ // always modify data by -(ped+f*noise), and force negative values
+ // to zero.
+ Bool_t pedSubtract = AliFMDParameters::Instance()->IsZSPedSubtract();
+ UShort_t pre = AliFMDParameters::Instance()->GetZSPreSamples();
+ UShort_t post = AliFMDParameters::Instance()->GetZSPostSamples();
+ Float_t factor = AliFMDParameters::Instance()->GetPedestalFactor();
+
+ TArrayC mask(nWords+1);
+ for (Short_t i = 0; i < nWords; i++) {
+ Float_t val = data[i] - peds[i] - factor * noise[i];
+ if (val < 0.5) val = 0;
+ if (pedSubtract) data[i] = Int_t(val) & 0x3FF;
+
+ mask[i] = (val > threshold ? 1 : 0);
+ AliFMDDebug(10, ("Comparing sample %d %d-%f-%f*%f=%f to %d -> %s",
+ i, data[i], peds[i], factor, noise[i], val, threshold,
+ (mask[i] ? "above" : "below")));
+ }
+
+ for (Short_t i = 0; i < nWords; i++) {
+ if (mask[i]) { // Signal above, so do nothing
+ AliFMDDebug(10, ("Sample %d, above", i));
+ if (i < nWords-1 && !mask[i+1]) {
+ // After a valid sample. Increase the pointer to the next
+ // possible data, thereby skipping over the post-samples
+ AliFMDDebug(10, ("At sample %d, next is below, skipping %d to %d",
+ i, post, i+post));
+ i += post;
+ }
+ continue;
+ }
+
+ Short_t lookahead = TMath::Min(Short_t(nWords), Short_t(i+pre));
+ AliFMDDebug(10, ("Sample %d, below, look to %d", i, lookahead));
+ if (mask[lookahead] && pre > 0) {
+ AliFMDDebug(10, ("Sample %d is a pre-sample to %d", i, lookahead));
+ // We're in a presample, so don't modify the data, and increase
+ // counter by the number of pre-samples
+ i += pre-1;
+ continue;
+ }
+
+ // This sample must be surpressed
+ data[i] = threshold - 1;
+ }
+}
+
#else
//____________________________________________________________________
void
AliFMDRawWriter::WriteDigits(TClonesArray* digits)
{
+ //
+ // Write digits to file
+ //
Int_t nDigits = digits->GetEntries();
if (nDigits < 1) return;
//
// EOF
//
+