]>
Commit | Line | Data |
---|---|---|
5990c064 | 1 | /************************************************************************** |
2 | * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * | |
3 | * * | |
4 | * Author: The ALICE Off-line Project. * | |
5 | * Contributors are mentioned in the code where appropriate. * | |
6 | * * | |
7 | * Permission to use, copy, modify and distribute this software and its * | |
8 | * documentation strictly for non-commercial purposes is hereby granted * | |
9 | * without fee, provided that the above copyright notice appears in all * | |
10 | * copies and that both the copyright notice and this permission notice * | |
11 | * appear in the supporting documentation. The authors make no claims * | |
12 | * about the suitability of this software for any purpose. It is * | |
13 | * provided "as is" without express or implied warranty. * | |
14 | **************************************************************************/ | |
15 | ||
88cb7938 | 16 | /* $Id$ */ |
5990c064 | 17 | |
18 | /////////////////////////////////////////////////////////////////////////////// | |
19 | // // | |
20 | // TRD raw data conversion class // | |
21 | // // | |
22 | /////////////////////////////////////////////////////////////////////////////// | |
23 | ||
a2cb5b3d | 24 | #include <Riostream.h> |
090026bf | 25 | #include <TMath.h> |
5990c064 | 26 | |
2745a409 | 27 | #include "AliDAQ.h" |
28 | #include "AliRawDataHeader.h" | |
29 | #include "AliRawReader.h" | |
30 | #include "AliLog.h" | |
31 | ||
5990c064 | 32 | #include "AliTRDrawData.h" |
33 | #include "AliTRDdigitsManager.h" | |
bd0f8685 | 34 | #include "AliTRDgeometry.h" |
5990c064 | 35 | #include "AliTRDdataArrayI.h" |
b864d801 | 36 | #include "AliTRDRawStream.h" |
50378239 | 37 | |
3551db50 | 38 | #include "AliTRDcalibDB.h" |
08f92f14 | 39 | #include "AliFstream.h" |
5990c064 | 40 | |
41 | ClassImp(AliTRDrawData) | |
42 | ||
43 | //_____________________________________________________________________________ | |
2cb20be6 | 44 | AliTRDrawData::AliTRDrawData() |
45 | :TObject() | |
bd63bf88 | 46 | ,fRawVersion(2) // Default Raw Data version set here |
8c703901 | 47 | ,fGeo(0) |
48 | ,fNumberOfDDLs(0) | |
5990c064 | 49 | { |
b864d801 | 50 | // |
51 | // Default constructor | |
52 | // | |
5990c064 | 53 | |
5990c064 | 54 | } |
55 | ||
8c703901 | 56 | //_____________________________________________________________________________ |
57 | AliTRDrawData::AliTRDrawData(const AliTRDrawData &r) | |
58 | :TObject(r) | |
bd63bf88 | 59 | ,fRawVersion(2) // Default Raw Data version set here |
8c703901 | 60 | ,fGeo(0) |
61 | ,fNumberOfDDLs(0) | |
62 | { | |
63 | // | |
64 | // Copy constructor | |
65 | // | |
66 | ||
67 | } | |
68 | ||
5990c064 | 69 | //_____________________________________________________________________________ |
70 | AliTRDrawData::~AliTRDrawData() | |
71 | { | |
72 | // | |
73 | // Destructor | |
74 | // | |
75 | ||
5990c064 | 76 | } |
77 | ||
5990c064 | 78 | //_____________________________________________________________________________ |
8c703901 | 79 | Bool_t AliTRDrawData::SetRawVersion(Int_t v) |
5990c064 | 80 | { |
8c703901 | 81 | // |
7925de54 | 82 | // Set the raw data version (Currently only version 0, 1 and 2 are available) |
8c703901 | 83 | // |
84 | ||
7925de54 | 85 | if ( (v >= 0) && (v <= 2) ) { |
8c703901 | 86 | fRawVersion = v; |
87 | return kTRUE; | |
88 | } | |
89 | ||
90 | return kFALSE; | |
91 | ||
92 | } | |
93 | ||
94 | //_____________________________________________________________________________ | |
95 | Bool_t AliTRDrawData::Digits2Raw(TTree *digitsTree, TTree *tracks ) | |
96 | { | |
97 | // | |
98 | // Initialize necessary parameters and call one | |
99 | // of the raw data simulator selected by SetRawVersion. | |
100 | // | |
101 | // Currently tracklet output is not spported yet and it | |
102 | // will be supported in higher version simulator. | |
103 | // | |
104 | ||
105 | fNumberOfDDLs = AliDAQ::NumberOfDdls("TRD"); | |
106 | ||
107 | AliTRDdigitsManager* digitsManager = new AliTRDdigitsManager(); | |
108 | ||
109 | if (!digitsManager->ReadDigits(digitsTree)) { | |
110 | delete digitsManager; | |
111 | return kFALSE; | |
112 | } | |
113 | ||
114 | if (tracks != NULL) { | |
115 | delete digitsManager; | |
7925de54 | 116 | AliError("Tracklet input is not supported yet."); |
8c703901 | 117 | return kFALSE; |
118 | } | |
119 | ||
120 | fGeo = new AliTRDgeometry(); | |
121 | ||
f162af62 | 122 | if (!AliTRDcalibDB::Instance()) { |
7925de54 | 123 | AliError("Could not get calibration object"); |
8c703901 | 124 | delete fGeo; |
125 | delete digitsManager; | |
126 | return kFALSE; | |
127 | } | |
128 | ||
129 | Int_t retval = kTRUE; | |
130 | ||
131 | // Call appropriate Raw Simulator | |
50378239 | 132 | if ( fRawVersion > 0 && fRawVersion <= 2 ) retval = Digits2Raw(digitsManager); |
7925de54 | 133 | else { |
134 | retval = kFALSE; | |
135 | AliWarning(Form("Unsupported raw version (fRawVersion=%d).",fRawVersion)); | |
8c703901 | 136 | } |
137 | ||
138 | // Cleanup | |
139 | delete fGeo; | |
140 | delete digitsManager; | |
141 | ||
142 | return retval; | |
143 | ||
144 | } | |
145 | ||
146 | //_____________________________________________________________________________ | |
50378239 | 147 | Bool_t AliTRDrawData::Digits2Raw(AliTRDdigitsManager *digitsManager) |
8c703901 | 148 | { |
149 | // | |
7925de54 | 150 | // Raw data simulator for all versions > 0. This is prepared for real data. |
8c703901 | 151 | // This version simulate only raw data with ADC data and not with tracklet. |
8c703901 | 152 | // |
153 | ||
7925de54 | 154 | const Int_t kMaxHcWords = (fGeo->TBmax()/3)*fGeo->ADCmax()*fGeo->MCMmax()*fGeo->ROBmaxC1()/2 + 100 + 20; |
8c703901 | 155 | |
156 | // Buffer to temporary store half chamber data | |
157 | UInt_t *hc_buffer = new UInt_t[kMaxHcWords]; | |
158 | ||
159 | // sect is same as iDDL, so I use only sect here. | |
160 | for (Int_t sect = 0; sect < fGeo->Nsect(); sect++) { | |
161 | ||
162 | char name[1024]; | |
163 | sprintf(name,"TRD_%d.ddl",sect + AliTRDRawStream::kDDLOffset); | |
164 | ||
08f92f14 | 165 | AliFstream* of = new AliFstream(name); |
8c703901 | 166 | |
167 | // Write a dummy data header | |
168 | AliRawDataHeader header; // the event header | |
08f92f14 | 169 | UInt_t hpos = of->Tellp(); |
170 | of->WriteBuffer((char *) (& header), sizeof(header)); | |
8c703901 | 171 | |
172 | // Reset payload byte size (payload does not include header). | |
173 | Int_t npayloadbyte = 0; | |
174 | ||
7925de54 | 175 | // GTU common data header (5x4 bytes per super module, shows link mask) |
8c703901 | 176 | for( Int_t cham = 0; cham < fGeo->Ncham(); cham++ ) { |
777fe13b | 177 | UInt_t GtuCdh = (UInt_t)(0xe << 28); |
7925de54 | 178 | for( Int_t plan = 0; plan < fGeo->Nplan(); plan++) { |
179 | Int_t iDet = fGeo->GetDetector(plan, cham, sect); | |
180 | // If chamber status is ok, we assume that the optical link is also OK. | |
181 | // This is shown in the GTU link mask. | |
f162af62 | 182 | if ( AliTRDcalibDB::Instance()->GetChamberStatus(iDet) ) |
7925de54 | 183 | GtuCdh = GtuCdh | (3 << (2*plan)); |
184 | } | |
08f92f14 | 185 | of->WriteBuffer((char *) (& GtuCdh), sizeof(GtuCdh)); |
8c703901 | 186 | npayloadbyte += 4; |
187 | } | |
188 | ||
189 | // Prepare chamber data | |
190 | for( Int_t cham = 0; cham < fGeo->Ncham(); cham++) { | |
191 | for( Int_t plan = 0; plan < fGeo->Nplan(); plan++) { | |
192 | ||
193 | Int_t iDet = fGeo->GetDetector(plan,cham,sect); | |
194 | ||
195 | // Get the digits array | |
196 | AliTRDdataArrayI *digits = digitsManager->GetDigits(iDet); | |
197 | digits->Expand(); | |
198 | ||
7925de54 | 199 | Int_t hcwords = 0; |
8c703901 | 200 | |
201 | // Process A side of the chamber | |
7925de54 | 202 | if ( fRawVersion >= 1 && fRawVersion <= 2 ) hcwords = ProduceHcDataV1andV2(digits,0,iDet,hc_buffer,kMaxHcWords); |
08f92f14 | 203 | of->WriteBuffer((char *) hc_buffer, hcwords*4); |
8c703901 | 204 | npayloadbyte += hcwords*4; |
205 | ||
206 | // Process B side of the chamber | |
7925de54 | 207 | if ( fRawVersion >= 1 && fRawVersion <= 2 ) hcwords = ProduceHcDataV1andV2(digits,1,iDet,hc_buffer,kMaxHcWords); |
08f92f14 | 208 | of->WriteBuffer((char *) hc_buffer, hcwords*4); |
8c703901 | 209 | npayloadbyte += hcwords*4; |
210 | ||
211 | } | |
212 | } | |
213 | ||
214 | // Complete header | |
08f92f14 | 215 | header.fSize = UInt_t(of->Tellp()) - hpos; |
8c703901 | 216 | header.SetAttribute(0); // Valid data |
08f92f14 | 217 | of->Seekp(hpos); // Rewind to header position |
218 | of->WriteBuffer((char *) (& header), sizeof(header)); | |
8c703901 | 219 | delete of; |
8c703901 | 220 | } |
221 | ||
222 | delete hc_buffer; | |
223 | return kTRUE; | |
224 | ||
225 | } | |
226 | ||
227 | //_____________________________________________________________________________ | |
7925de54 | 228 | Int_t AliTRDrawData::ProduceHcDataV1andV2(AliTRDdataArrayI *digits, Int_t side |
229 | , Int_t det, UInt_t *buf, Int_t maxSize) | |
8c703901 | 230 | { |
7925de54 | 231 | // |
232 | // This function simulates: 1) SM-I commissiong data Oct. 06 (fRawVersion == 1). | |
233 | // 2) Full Raw Production Version (fRawVersion == 2) | |
8c703901 | 234 | // |
235 | // Produce half chamber data (= an ORI data) for the given chamber (det) and side (side) | |
236 | // where | |
7925de54 | 237 | // |
8c703901 | 238 | // side=0 means A side with ROB positions 0, 2, 4, 6. |
239 | // side=1 means B side with ROB positions 1, 3, 5, 7. | |
240 | // | |
241 | // Chamber type (C0 orC1) is determined by "det" automatically. | |
242 | // Appropriate size of buffer (*buf) must be prepared prior to calling this function. | |
243 | // Pointer to the buffer and its size must be given to "buf" and "maxSize". | |
244 | // Return value is the number of valid data filled in the buffer in unit of 32 bits | |
245 | // UInt_t words. | |
246 | // If buffer size if too small, the data is truncated with the buffer size however | |
247 | // the function will finish without crash (this behaviour is similar to the MCM). | |
248 | // | |
249 | ||
250 | Int_t nw = 0; // Number of written words | |
251 | Int_t of = 0; // Number of overflowed words | |
252 | Int_t plan = fGeo->GetPlane( det ); // Plane | |
253 | Int_t cham = fGeo->GetChamber( det ); // Chamber | |
254 | Int_t sect = fGeo->GetSector( det ); // Sector (=iDDL) | |
f162af62 | 255 | Int_t nRow = fGeo->GetRowMax( plan, cham, sect ); |
256 | Int_t nCol = fGeo->GetColMax( plan ); | |
257 | const Int_t nTBin = AliTRDcalibDB::Instance()->GetNumberOfTimeBins(); | |
8c703901 | 258 | Int_t kCtype = 0; // Chamber type (0:C0, 1:C1) |
259 | Int_t iEv = 0xA; // Event ID. Now fixed to 10, how do I get event id? | |
260 | UInt_t x = 0; // General used number | |
261 | ||
262 | // Check the nCol and nRow. | |
263 | if ((nCol == 144) && | |
264 | (nRow == 16 || nRow == 12)) { | |
265 | kCtype = (nRow-12) / 4; | |
266 | } | |
267 | else { | |
7925de54 | 268 | AliError(Form("This type of chamber is not supported (nRow=%d, nCol=%d)." |
8c703901 | 269 | ,nRow,nCol)); |
270 | return 0; | |
271 | } | |
272 | ||
273 | AliDebug(1,Form("Producing raw data for sect=%d plan=%d cham=%d side=%d" | |
274 | ,sect,plan,cham,side)); | |
275 | ||
276 | // Tracklet should be processed here but not implemented yet | |
277 | ||
278 | // Write end of tracklet marker | |
279 | if (nw < maxSize) { | |
bd63bf88 | 280 | buf[nw++] = kEndoftrackletmarker; |
8c703901 | 281 | } |
282 | else { | |
283 | of++; | |
284 | } | |
285 | ||
286 | // Half Chamber header | |
7925de54 | 287 | if ( fRawVersion == 1 ) { |
288 | // Now it is the same version as used in SM-I commissioning. | |
289 | Int_t dcs = det+100; // DCS Serial (in simulation, it is meaningless | |
290 | x = (dcs<<20) | (sect<<15) | (plan<<12) | (cham<<9) | (side<<8) | 1; | |
291 | if (nw < maxSize) { | |
292 | buf[nw++] = x; | |
293 | } | |
294 | else { | |
295 | of++; | |
296 | } | |
297 | } | |
298 | else if ( fRawVersion == 2 ) { | |
bd63bf88 | 299 | // h[0] (there are 3 HC header) |
7925de54 | 300 | Int_t minorv = 0; // The minor version number |
301 | Int_t add = 1; // The number of additional header words to follow | |
302 | x = (1<<31) | (fRawVersion<<24) | (minorv<<17) | (add<<14) | (sect<<9) | (plan<<6) | (cham<<3) | (side<<2) | 1; | |
303 | if (nw < maxSize) { | |
304 | buf[nw++] = x; | |
305 | } | |
306 | else { | |
307 | of++; | |
308 | } | |
309 | // h[1] | |
310 | Int_t bc_ctr = 99; // bunch crossing counter. Here it is set to 99 always for no reason | |
311 | Int_t pt_ctr = 15; // pretrigger counter. Here it is set to 15 always for no reason | |
312 | Int_t pt_phase = 11; // pretrigger phase. Here it is set to 11 always for no reason | |
313 | x = (bc_ctr<<16) | (pt_ctr<<12) | (pt_phase<<8) | ((nTBin-1)<<2) | 1; | |
314 | if (nw < maxSize) { | |
315 | buf[nw++] = x; | |
316 | } | |
317 | else { | |
318 | of++; | |
319 | } | |
bd63bf88 | 320 | // h[2] |
321 | Int_t ped_setup = 1; // Pedestal filter setup (0:1). Here it is always 1 for no reason | |
322 | Int_t gain_setup = 1; // Gain filter setup (0:1). Here it is always 1 for no reason | |
323 | Int_t tail_setup = 1; // Tail filter setup (0:1). Here it is always 1 for no reason | |
324 | Int_t xt_setup = 0; // Cross talk filter setup (0:1). Here it is always 0 for no reason | |
325 | Int_t nonlin_setup = 0; // Nonlinearity filter setup (0:1). Here it is always 0 for no reason | |
326 | Int_t bypass_setup = 0; // Filter bypass (for raw data) setup (0:1). Here it is always 0 for no reason | |
327 | Int_t common_additive = 10; // Digital filter common additive (0:63). Here it is always 10 for no reason | |
328 | x = (ped_setup<<31) | (gain_setup<<30) | (tail_setup<<29) | (xt_setup<<28) | (nonlin_setup<<27) | |
329 | | (bypass_setup<<26) | (common_additive<<20) | 1; | |
330 | if (nw < maxSize) { | |
331 | buf[nw++] = x; | |
332 | } | |
333 | else { | |
334 | of++; | |
335 | } | |
8c703901 | 336 | } |
337 | ||
338 | // Scan for ROB and MCM | |
339 | for (Int_t iRobRow = 0; iRobRow < (kCtype + 3); iRobRow++ ) { | |
340 | Int_t iRob = iRobRow * 2 + side; | |
7925de54 | 341 | for (Int_t iMcm = 0; iMcm < fGeo->MCMmax(); iMcm++ ) { |
8c703901 | 342 | Int_t padrow = iRobRow * 4 + iMcm / 4; |
343 | ||
344 | // MCM header | |
7925de54 | 345 | x = ((iRob * fGeo->MCMmax() + iMcm) << 24) | ((iEv % 0x100000) << 4) | 0xC; |
8c703901 | 346 | if (nw < maxSize) { |
347 | buf[nw++] = x; | |
348 | } | |
349 | else { | |
350 | of++; | |
351 | } | |
352 | ||
353 | // ADC data | |
354 | for (Int_t iAdc = 0; iAdc < 21; iAdc++ ) { | |
bd63bf88 | 355 | Int_t padcol = fGeo->GetPadColFromADC(iRob, iMcm, iAdc); |
7925de54 | 356 | UInt_t aa = !(iAdc & 1) + 2; |
8c703901 | 357 | UInt_t *a = new UInt_t[nTBin+2]; |
358 | // 3 timebins are packed into one 32 bits word | |
359 | for (Int_t iT = 0; iT < nTBin; iT+=3) { | |
7925de54 | 360 | if ((padcol >= 0) && (padcol < nCol)) { |
361 | a[iT ] = ((iT ) < nTBin ) ? digits->GetDataUnchecked(padrow,padcol,iT ) : 0; | |
362 | a[iT+1] = ((iT + 1) < nTBin ) ? digits->GetDataUnchecked(padrow,padcol,iT + 1) : 0; | |
363 | a[iT+2] = ((iT + 2) < nTBin ) ? digits->GetDataUnchecked(padrow,padcol,iT + 2) : 0; | |
364 | } | |
365 | else { | |
366 | a[iT] = a[iT+1] = a[iT+2] = 0; // This happenes at the edge of chamber (should be pedestal! How?) | |
8c703901 | 367 | } |
7925de54 | 368 | x = (a[iT+2] << 22) | (a[iT+1] << 12) | (a[iT] << 2) | aa; |
369 | if (nw < maxSize) { | |
370 | buf[nw++] = x; | |
8c703901 | 371 | } |
7925de54 | 372 | else { |
373 | of++; | |
8c703901 | 374 | } |
7925de54 | 375 | } |
8c703901 | 376 | // Diagnostics |
377 | Float_t avg = 0; | |
378 | Float_t rms = 0; | |
379 | for (Int_t iT = 0; iT < nTBin; iT++) { | |
380 | avg += (Float_t) (a[iT]); | |
381 | } | |
382 | avg /= (Float_t) nTBin; | |
383 | for (Int_t iT = 0; iT < nTBin; iT++) { | |
384 | rms += ((Float_t) (a[iT]) - avg) * ((Float_t) (a[iT]) - avg); | |
385 | } | |
386 | rms = TMath::Sqrt(rms / (Float_t) nTBin); | |
387 | if (rms > 1.7) { | |
7925de54 | 388 | AliDebug(2,Form("Large RMS (>1.7) (ROB,MCM,ADC)=(%02d,%02d,%02d), avg=%03.1f, rms=%03.1f" |
389 | ,iRob,iMcm,iAdc,avg,rms)); | |
8c703901 | 390 | } |
391 | delete a; | |
392 | } | |
393 | } | |
394 | } | |
395 | ||
396 | // Write end of raw data marker | |
397 | if (nw < maxSize) { | |
bd63bf88 | 398 | buf[nw++] = kEndofrawdatamarker; |
8c703901 | 399 | } |
400 | else { | |
401 | of++; | |
402 | } | |
403 | if (of != 0) { | |
404 | AliWarning("Buffer overflow. Data is truncated. Please increase buffer size and recompile."); | |
405 | } | |
406 | ||
407 | return nw; | |
5990c064 | 408 | |
409 | } | |
410 | ||
411 | //_____________________________________________________________________________ | |
7925de54 | 412 | AliTRDdigitsManager *AliTRDrawData::Raw2Digits(AliRawReader *rawReader) |
5990c064 | 413 | { |
b864d801 | 414 | // |
50378239 | 415 | // Vx of the raw data reading |
b864d801 | 416 | // |
5990c064 | 417 | |
2cb20be6 | 418 | AliTRDdataArrayI *digits = 0; |
419 | AliTRDdataArrayI *track0 = 0; | |
420 | AliTRDdataArrayI *track1 = 0; | |
421 | AliTRDdataArrayI *track2 = 0; | |
5990c064 | 422 | |
5990c064 | 423 | // Create the digits manager |
b864d801 | 424 | AliTRDdigitsManager* digitsManager = new AliTRDdigitsManager(); |
b864d801 | 425 | digitsManager->CreateArrays(); |
5990c064 | 426 | |
3551db50 | 427 | AliTRDRawStream input(rawReader); |
50378239 | 428 | input.SetRawVersion( fRawVersion ); |
429 | input.Init(); | |
5990c064 | 430 | |
b864d801 | 431 | // Loop through the digits |
50378239 | 432 | Int_t lastdet = -1; |
433 | Int_t det = 0; | |
434 | Int_t it = 0; | |
435 | while (input.Next()) | |
436 | { | |
437 | ||
438 | det = input.GetDet(); | |
439 | ||
440 | if (det != lastdet) | |
441 | { | |
442 | ||
443 | lastdet = det; | |
444 | ||
445 | if (digits) digits->Compress(1,0); | |
446 | if (track0) track0->Compress(1,0); | |
447 | if (track1) track1->Compress(1,0); | |
448 | if (track2) track2->Compress(1,0); | |
449 | ||
450 | // Add a container for the digits of this detector | |
451 | digits = digitsManager->GetDigits(det); | |
452 | track0 = digitsManager->GetDictionary(det,0); | |
453 | track1 = digitsManager->GetDictionary(det,1); | |
454 | track2 = digitsManager->GetDictionary(det,2); | |
455 | ||
456 | // Allocate memory space for the digits buffer | |
457 | if (digits->GetNtime() == 0) | |
458 | { | |
459 | digits->Allocate(input.GetMaxRow(),input.GetMaxCol(), input.GetNumberOfTimeBins()); | |
460 | track0->Allocate(input.GetMaxRow(),input.GetMaxCol(), input.GetNumberOfTimeBins()); | |
461 | track1->Allocate(input.GetMaxRow(),input.GetMaxCol(), input.GetNumberOfTimeBins()); | |
462 | track2->Allocate(input.GetMaxRow(),input.GetMaxCol(), input.GetNumberOfTimeBins()); | |
463 | } | |
464 | } | |
465 | ||
466 | for (it = 0; it < 3; it++) | |
467 | { | |
468 | if ( input.GetTimeBin() + it < input.GetNumberOfTimeBins() ) | |
469 | { | |
470 | digits->SetDataUnchecked(input.GetRow(), input.GetCol(), | |
471 | input.GetTimeBin() + it, input.GetSignals()[it]); | |
472 | track0->SetDataUnchecked(input.GetRow(), input.GetCol(), | |
473 | input.GetTimeBin() + it, 0); | |
474 | track1->SetDataUnchecked(input.GetRow(), input.GetCol(), | |
475 | input.GetTimeBin() + it, 0); | |
476 | track2->SetDataUnchecked(input.GetRow(), input.GetCol(), | |
477 | input.GetTimeBin() + it, 0); | |
2cb20be6 | 478 | |
50378239 | 479 | } |
480 | } | |
5990c064 | 481 | } |
482 | ||
b864d801 | 483 | if (digits) digits->Compress(1,0); |
928e9fae | 484 | if (track0) track0->Compress(1,0); |
485 | if (track1) track1->Compress(1,0); | |
486 | if (track2) track2->Compress(1,0); | |
b864d801 | 487 | |
7925de54 | 488 | return digitsManager; |
489 | ||
490 | } |