MINOS Offline Calibration Framework

Warning: this document is obsolete although it still has some useful information. Specifically:-


Please see the Calibrator chapter of the User Manual for up to date information.

Summary

In this document we describe the structure and usage of the MINOS offline calibration framework.  The calibration framework includes the portions of the offline framework devoted to accessing the database tables containing the calibration constants, applying these constants to the raw charge and time measurements, and storing these calibrated quantities for use in reconstruction and analysis.  We will also describe a procedure for updating the calibration databases with new constants.  However, a description of the procedure for obtaining new constants is beyond the scope of this document, and will be described elsewhere once these procedures have been fully developed.

 

  Calibration Stages

The calibration of the charge measurement proceeds through a sequence of stages, necessitated by the fact that certain aspects of the calibration can be carried out prior to reconstruction, while other aspects require knowledge of the 3D position of the hit in the detector.  Ultimately, we desire a transformation of the raw adc value to a normalized measurement in units of MIPs (the response to a normally incident, minimum ionizing particle, corrected for channel to channel gain and QE differences, attenuation in the strip and clear fiber, and corrected for time variations in response).  Below, we show the sequence of steps taken in the charge calibration, and the name used in the offline for a calibrated quantity at a particular processing stage:

 

 

Charge: Pre-Reconstruction

 

The pre-reconstruction calibrations operate on CandDigits, and store the calibrated quantities as items on the strip end ID alt list of that CandDigit, as described later.

 

·         Correction of non-linearity and time drift:                                                  : SigLin

·         Correction for strip-strip response differences:                                        : SigCor

·         Conversion of ADC to PEs                                                                          : SigPE                               

 

Charge: Post-Reconstruction

 

The post-reconstruction calibrations operate on CandStrips.  The calibrated quantities are stored as arrays (maps)

 

·         Correction for attenuation along strip and clear fiber                              : SigMap

·         Conversion to MIPs                                                                                      : SigMIP

·         Conversion of MIPs to shower energy                                   

 

 

Time: Pre-Reconstruction

 

·         subtraction of a timing offset and multiplication by a scale factor        : Time

 

Time: Post-Reconstruction

 

·         correction for pulse height-dependent ‘time-walk’

·         correction  for propagation delays in the cable and strip.                       :

 

 

In the charge calibration sequence, raw adcs are used to obtain SigLin, which is used in the calculation of SigCor.  SigCor in turn is used to determine SigMap.  Finally, SigMIP is calculated from SigMAP.  SigPE is not in the direct calibration chain to SigMIP, and is calculated from raw adcs.

 

Calibration Database Tables

The calibration constants are stored in a set of tables, each associated with a specific calibration stage.  For a general description of MINOS database usage, refer to the offline framework documentation.  Here, we assume a general working knowledge of database usage.  Below, we proceed through the calibration chain for charge and time measurements, indicating the conversion which takes place at each step, and the structure of the associated calibration table.

 

Non-Linearity

The correction for non-linearity uses a two column table of raw adc and associated PIN values. To linearize a given adc measurement, the table entries bounding this adc value are interpolated, and the linearized PIN value equivalent to the  raw adc measurement is obtained.   The light injection system is used to obtain the table entries – a description of this process is beyond the scope of this document.   The linearized PIN value is then multiplied by a scale factor which results in SigLin, the calibrated quantity resulting from these operations, having a value roughly equal to the raw adc value for small pulse heights.  In this way, SigLin, and all calibrated quantities derived from SigLin,  can be treated in all respects like a linearized version of raw adc counts. The non-linearity database table is called CalNonLinearity, and contains columns shown in the table below.

 

 

CalNonLinearity Table     

 

Column Name
Description

SEQNO

Sequence Number for validity context association

TASK

 

SEIDKEY

Index key for this entry – based on the strip end ID

STRIPENDID

Strip end ID

DATALEN

# of constants in non-linearity table (default = 40)

CONST1

Raw ADC value 1

CONST2         

PIN value 1

CONST3         

Raw ADC value 2

CONST4         

PIN value 2

CONST5         

Raw ADC value 3

CONST6         

PIN value 3

CONST7         

Raw ADC value 4

CONST8         

PIN value 4

CONST9         

.

CONST10        

.

CONST11         

.

CONST12         

.

CONST13         

.

CONST14         

 

CONST15         

 

CONST16         

 

CONST17         

 

CONST18         

 

CONST19         

 

CONST20        

 

CONST21          

 

CONST22         

 

CONST23         

 

CONST24

 

CONST25

 

CONST26

 

CONST27

 

CONST28

 

CONST29

 

CONST30

 

CONST31

 

CONST32

 

CONST33

 

CONST34

 

CONST35

 

CONST36

 

CONST37

 

CONST38

 

CONST39

 

CONST40

 

 

The table containing the scale factors required to convert PIN output of the non-linearity correction back to adc counts is called CalPINtoADC:

 

CalPINtoADC Table

 

Column Name

Description

SEQNO

Sequence Number for validity context association

SEIDKEY

Index key for this entry – based on the strip end ID

STRIPENDID

Strip end ID

SCALE

Scale factor for converting from PIN to ADC

 

 

 

 

Time Point Correction

In the time point correction, we multiply the linearized response by the ratio of the response to a fixed LI pulse observed at a reference time, to the response at the time of data taking.  The following tables are associated with this calibration.  The time drift-corrected, linearized charge measurement is called SigLin in the offline.

 

CalGainDrift Table

 

 

Column Name

Description

SEQNO

Sequence number for validity context association

SEIDKEY

Index key based on strip end ID

STRIPENDID

Strip end ID

SCALECORR

Time drift correction factor for this strip end and validity context

SCALELOW

Unused

SCALEHI

Unused

 

 

 

Strip-Strip relative normalization (SigCor)

The next step in the calibration chain is to apply a scale factor of order 1 associated with each strip end, which results in identical average response for each strip end.  These scale factors are obtained using muon pulse height distributions.   This scale factor is contained in a data base table which also includes the parameters of a double exponential fit to the position dependent response of each strip to muons.  These muon response fits are identical in form to the mapper fits described later, and can be substituted for mapper fits in correcting for the position dependent response if desired.

 

The muon calibration parameters are contained in CalMuonCalibration, as shown below.

 

CalMuonCalibration Table

 

Column Name

Description

SEQNO

Sequence number for validity context association

SEIDKEY

Index key based on strip end ID

STRIPENDID

Strip end ID

CHI2

Goodness of fit of the double exponential fit to the muon data used

C0

Overall strip to strip normalization factor

C0ERR

Error in overall strip to strip normalization factor

C1

Fit parameter multiplying first exponential

C1ERR

Error in C1

LAMBDA1

‘long’ attenuation length

LAMBDA1ERR

Error in l1

C2

Fit parameter multiplying second exponential

C2ERR

Error in C2

LAMBDA2

‘short’ attenuation length

LAMBDA2ERR

Error in l2

 

 

 

 

The strip-to-strip normalization is obtained by dividing SigLin by C0.  The resulting quantity is referred to as SigCor in the offline.  This completes the main stream pre-reconstruction calibration of charge.  In addition, the conversion of raw adc to photoelectrons is performed, and the resulting quantities stored in the strip end ID alt list.   This calibration uses constants contained in the table CalADCtoPE.

 

CalADCtoPE

 

Column Name

Description

SEQNO

Sequence number for validity context association

SEIDKEY

Index key based on strip end ID

STRIPENDID

Strip end ID

GAIN

ADC/PE

GAINERR

Error in ADC/PE conversion constant

WIDTH1PE

Width of the 1 PE peak

 

 


 

Time Calibration

In the pre-reconstruction time calibration we apply timing offsets, (and potentially, scale factors) to the raw times.  The timing offsets are contained in the database table CalTimeCalibration, shown below.

 

CalTimeCalibration

 

Column Name

Description

SEQNO

Sequence number for validity context association

SEIDKEY

Index key based on strip end ID

STRIPENDID

Strip end ID

SCALE

Channel –dependent scale factor correction (currently set to unity)

OFFSET

T0

SLEWCONST1

General time walk parameterization constant

SLEWCONST2

General time walk parameterization constant

SLEWCONST3

General time walk parameterization constant

SLEWCONST4

General time walk parameterization constant

 

 

The calibrated time values are obtained by dividing the raw time by the scale factor, and subtracting the offset.  Prior to this operation, a global scale factor is applied to convert raw tdc values to times (in units of seconds)  as part of the process of constructing CandDigits.  Following the pre-reconstruction time calibration, code contained in AlgDigitList determines the start time of the snarl, and subtracts this common start time from all times contained in the snarl CandDigits.  Following reconstruction, further corrections are made to the measured times - we subtract the propagation delay down the strip and clear fiber, and subtract the time walk correction, obtained using a parameterization based on the raw adc signal and the SLEWCONST parameters in the database table.  Although the preceding describes the default action of the software, it is possible to disable the pre-reconstruction time calibrations. This is done by setting the parameter CalTimeMode to zero in the job control file by adding the following job control statements:

 

AlgFactory &af  = AlgFactory::GetInstance();               

AlgHandle ah  = af.GetAlgHandle("AlgDigit", "default");    

AlgConfig &ac = ah.GetAlgConfig();                         

ac.UnLockValues();                                         

ac.Set("CalTimeMode",    0);                               

ac.LockValues();            

 

 

 


 

Post-Reconstruction Calibrations – Mapper Corrections

Following event reconstruction, we know the true 3 dimensional position of each CandStrip which has been associated with either a track or shower.  For the CandTrack and CandShower members, we apply a post-reconstruction stage to the calibration chain.  First, we use the mapper data to correct for the signal attenuation along the strip and clear fiber.  The table CalMapperFits contains the parameters of a double exponential fit to the mapper data for each strip end.  The format of the CalMapperFits table is shown below:

 

Column Header

Description

SEQNO

Sequence number for validity context association

SEIDKEY

Index key based on strip end ID

STRIPENDID

Strip end ID

TESTID

Test ID

STRIPNUM

Strip number (1-28)

STRIPEND

Strip end (1-2)

NORM

Overall normalization factor for parameterization

NPOINTS

# points used in the mapper fit

C1

Fit parameter multiplying first exponential

C1ERR

Error in C1

LAMBDA1

‘long’ attenuation length

LAMBDA1ERR

Error in l1

C2

Fit parameter multiplying second exponential

C2ERR

Error in C2

LAMBDA2

‘short’ attenuation length

LAMBDA2ERR

Error in l2

 

 

MIP calibration

The final stage of the strip level charge reconstruction is the conversion of the mapper-corrected charge (SigMap) into MIP units.  The relevant scale factor is stored in CalMIPCalibration, shown below.

 

Column Name

Description

SEQNO

Sequence number for validity context association

SEIDKEY

Index key based on strip end ID

STRIPENDID

Strip end ID

SCALE

ADC/MIP conversion

 

 

 

 

 

 

   The MIP value corresponding to a given SigMap signal is given by:   MIP = SigMap/SCALE.

 

      


Calibration Framework Classes

In this section, we describe the calibration classes associated with the MINOS offline framework, as well as the code in other portions of the framework which initiates the pre and post – reconstruction calibrations. 

 

The initial pre-reconstruction calibrations are performed at the time of the formation of the CandDigits.  Since we have not yet de-multiplexed the event at that time, we must store the results of calibrations for each of the possible strip end alternatives associated with a given CandDigit.  Therefore, the most logical place to store these calibrated quantities is on the strip end ID alternative list itself.  To hold these calibrated signal values, each strip end alternative of a CandDigit has an associated item list with the following member variables:

                                                                         

PlexSEIdAltLItem Member Variables

 

  PlexStripEndId    fStripEndId;  // which strip-end                     

  PlexPixelSpotId   fPixelSpotId; // which pixel-spot                    

  Float_t           fWeight;      // stored demux weight                 

  Float_t           fPE;          // ADC value converted to photoelectrons

  Float_t           fSigLin;      // correct for time depend & linearity by LI

  Float_t           fSigCorr;     // correct for strip-to-strip variations

  Double_t        fTime;        // timestamp, corrected for offsets and  scale      

 

The members of interest to us here are the latter four, which hold the pre-reconstruction calibrated quantities described in previous sections.   At the time of the construction of a CandDigit, in AlgDigit::RunAlg, all possible  strip end alternatives for the CandDigit under construction are determined, and the alt list built, initially through a call to PlexHandle::GetSEIdAltL from RunAlg.  One of the arguments of this call is a pointer to the singleton instance of the pre-reconstruction calibration driver class, called DigitCalibrator.  PlexHandle::GetSEIdAltL consists simply of a call to Plexus::GetSEIdAltL, which in turn contains a loop over all strip end alternatives.  For each SEId a call to PlexSEIdAltL::AddStripEndId is made, which adds a new item to the alt list of this CandDigit.  The first action of AddStripEndId is a call to the CalibStripEnd(seid,spot,adc,time) member of DigitCalibrator, which returns a PlexSEIdAltLItem holding the calibrated quantities.   The input parameters include the raw charge and time quantities, and the strip end Id. 

 

The CalibStripEnd function results in calls to the Calibrate method of each of the classes associated with the pre-reconstruction calibrated quantities held in the alt list item.  The Calibrate member of the given calibration class constructs an index key from the strip end id provided in the function call and uses this to get a database table row in each of the tables needed for its particular calibration.  The table row will contain the necessary calibration constants for the strip end being calibrated, and appropriate to the validity context in which the job is currently running.  Access to a given database is made through an associated DBI class, the basic structure of which is defined in the MINOS offline db documentation.  The names of these interface classes are the same as the names of the database tables described in previous sections.  Each of these DBI classes includes a member function called by Calibrate, which accepts an ‘uncalibrated’ input quantity, uses the calibration constants obtained from the table, and returns the calibrated quantity.  Calibrate, having received this calibrated quantity from the DBI interface,  passes it up the chain to the CalibStripEnd function, where it becomes part of the PlexSEIdAltLItem being build for this strip end.  The complete call chain associated with the pre-reconstruction calibration, starting in AlgDigit, is shown in the figure below.

 

 

 

 

 

 


 

 

 

 


 

The final stages of calibration of the charge and time measurements require that the 3D position of a hit be known, and take place after a track or shower has been fully reconstructed.  As CandStrips can be members of multiple track or shower objects, and calibrations performed at this time depend upon the 3 dimensional position of the hit, and therefore membership in a particular 3D object, there is an inherent ambiguity in associating these final calibrated quantities with CandStrips.  Instead, each CandEvent holds maps of SigMap and SigMIP values, with strip end IDs used as keys to look up values in these maps.  SigMap is obtained by applying the mapper or muon-based corrections to the attenuation of the strip and cable, and a path length correction, to SigCorr.  SigMIP  is given by scaling SigMap, minus the path length corrections, to units of MIPs.  These maps are filled in AlgEvent::Calibrate, which is called from AlgEventSR::RunAlg as the last step in the construction of an event.  In AlgEvent::Calibrate, we loop over event objects in priority order, starting with the primary track, followed by the secondary tracks if any, then the primary shower, and finally secondary showers. For each of these objects, we loop over member CandStrips and obtain the SigMap and SigMIP values through calls to a post-reconstruction calibration driver routine, StripCalibrator, storing these calibrated charge values in the CandEvent maps, indexed by the strip end Ids associated with the CandStrip members.  As we work through the tracks and showers in the event, looping over their CandStrip members, a check is made that a given strip end Id has not already been encountered in a higher priority object.  If this is the case, the map entry is NOT updated.   When a map entry IS updated (ie a new CandStrip is encountered), a call is made to StripCalibrator::GetSigMapped and to StripCalibrator::GetSigMIP.  These in turn call the Calibrate methods of the calibration classes associated with the Map and MIP calibrations.  In an identical fashion to the pre-reconstruction calibrations, the Calibrate functions construct an index key from the strip end id provided in the function call and use this to get a database table row in each of the tables needed for the particular calibration being performed.  Access to a given database is again  made through an associated DBI class.  The full post-reconstruction charge calibration chain, starting at AlgEventSR::RunAlg, is shown below. 

 

 

 

 

 

 

 

 

 

We turn now to the post-reconstruction time calibration.  After reconstruction, we can correct times for the propagation delays in the strip and cable.  The time walk calibration is also performed at this point, in future updates to this software it is likely that the timewalk correction will be moved to the pre-reconstruction stage.  Since the times resulting from these corrections are primarily of interest for track hits, these corrected times are stored in a map associated with the CandTrack, indexed by plane.  Following the formation of a track in CandTrackSR::RunAlg, a call to AlgTrack::SetUVZT(CandTrackHandle *) is  made which computes the U, V, and Z positions of the track in each plane, and more relevant here, the times for each plane/strip end, corrected for propagation delays. These quantities are stored in maps associated with the CandTrack, as described above.   At the present time, these corrections do not entail access to the calibration database, and the correction is carried out within SetUVZT itself.  However, given that these corrections involve the use of the effective speed of light in the strip and cable, which should be considered a calibration constant, it is expected this code will be modified in the future to make proper use of the calibration databases.

 

Access to Calibrated Quantities from Offline Framework Code

As described above, the quantities PE, SigLin, SigCorr, and the T0-corrected times for a given CandDigit are stored on the alt list associated with the CandDigit for each strip end alternative.  Access to the charge quantities is made through calls to:

 

 CandDigitHandle::GetCharge(CalDigitType::CalDigitType_t),

 

 and access to the time measurement through 

 

CandDigitHandle::GetTime(CalTimeType::CalTimeType_t).

 

 The function parameter determines the type of quantity returned.  Possible CalDigitTypes include:

 

CalDigitType:: kNone     :    Returns raw adc

CalDigitType:: kPE         :    Returns  PEs

CalDigitType:: kSigLin   :   Returns SigLin

CalDigitType:: kSigCorr :   Returns SigCorr

 

Possible CandTimeType values include:

 

CalTimeType::kNone    :   Returns raw time

CalTimeType::kT0        :   Returns T0 corrected time.

 

Higher level objects such as CandStrips, CandClusters, etc, have associated GetCharge and GetTime members which act in a manner analogous to the CandDigitHandle members, usually providing the value for the desired quantity summed over the object if a charge-related quantity is desired, or the earliest time in the object if a time is desired.  The detailed behavior of these functions is described in the reconstruction class documentation. 

 

The calibrated quantities obtained in the post-reconstruction phase are accessed through member functions of the higher level objects (tracks or events) holding these quantities in maps.  The charge-related quantities SigMap and SigMIP are held in CandEvents, and are access through one the following:

 

Float_t CandEventHandle::GetCharge(CalStripType::CalStripType_t)

     

Float_t CandEventHandle::GetStripCharge(CandStripHandle *, CalStripType::CalStripType_t, StripEnd::StripEnd_t )                

 

where CalStripType::CalStripType_t is one of  the following

 

CalStripType::kSigMapped          : Returns SigMap

CalStripType::kMIP                     :  Returns MIPs

CalStripType::kGeV                     :  Returns energy in GeV – presently hardwired for 45 MIPs/GeV

 

 

A call to GetCharge returns the requested quantity summed over the event (ie summed overall all map entries).  The call the GetStripCharge returns the requested quantity for a given strip end.

 

The propagation delay-corrected times are accessed though the GetT member of CandTrackHandle, which has the form:

 

Float_t CandTrackHandle::GetT(Int_t plane,StripEnd::StripEnd_t)

 

 

 

 

 

 

 

      

Adding Calibration Constants to the Database    

We assume here that the user has developed a set of calibration constants which he/she would like to add to the calibration db tables, and employ in subsequent analyses.  It is possible to write to the db tables directly from an offline job, using the DBO interface – this capability is documented elsewhere.  However, it is often simper to write a small standalone program which runs as a script under loon, reading in your constants and their associated plane/strip location in the detector from some file you provide, and writing out a text file which can be loaded into the db via mysql. Of course, to do this you need to know the table format for the table you are interested in – all tables likely to be of interest to the user are described in previous sections.   As a further aid to the user, we include in Appendix 1 a root script which can be used  to build ALL the calibration db tables, and load them with default values.  If a users desires that only a subset of the tables be constructed and loaded with use-supplied constants, it is a simple matter to strip out everything in this script but that associated with the desired tables, and add some simple code to read in your calibration constants/plane-strip values.  The only other action the user will need to take is to verify that the detector type and sequence number, defined at the start of this script via the following statements

 

Int_t SeqNo =; 200000000 // for far detector

DetectorType::Detector_t det = DetectorType::kFar; // or kNear or kCaldet

 

 are set properly.  (ie, referring to the script,  if the calibration constants are for the far detector,  ‘det’ should be set to DetectorType::kFar, and the sequence number set to a unique value for the db table in the range 200000000 – 299999999.  Near detector context occupies the sequence number range 300000000-399999999, and caldet context the range 40000000-499999999).  The set of sequence numbers currently in use can be determined by examining the validity context table associated with a given calibration table.      

 

Having modified this script for your particular needs, the user should execute the script from the Loon prompt, via the commands ‘ .x minos.C’, followed by   ‘.x iterateSEId.C++’ .  If all goes well, this should result in two files being written, -  a validity context text file, and a text file containing your constants.  To load these constants into your  database, run mysql, and enter the following commands from the mysql prompt:

 

 

USE OFFLINE;

 

LOAD DATA LOCAL INFILE 'myvalidityfile' INTO TABLE tablenameVLD IGNORE 1

LINES;

 

LOAD DATA LOCAL INFILE 'myfile' INTO TABLE tablename IGNORE 1 LINES;

 

 

Where  tablename is the name of the db table,  documented in previous sections. After loading executing these mysql commands the new calibration constants are available

Appendix 1:  Root Script for Building Default Calibration Databases

 

#include "UgliGeometry/UgliGeomHandle.h"

#include <fstream.h>

 

void iterateSEId() {

  // ________________________________________

   // loop over all the strips in the chosen detector 

  // ---------------------------------------

 

 

  // establish validity context

  // -------------------------

    Int_t SeqNo =200000000;  // for far detector

    DetectorType::Detector_t det = DetectorType::kFar; // or kNear

 

 

  //    Int_t SeqNo = 400000000;  // for caldet detector

  //   DetectorType::Detector_t det = DetectorType::kCalDet; // or kNear

 

 

 

  SimFlag::SimFlag_t simflag = SimFlag::kData;  // or kReroot

 

  // time:  time used for detector config

  // time1/3:  validity time interval for constants

 

  VldTimeStamp time(2002,12,1,0,0,0);

 

  char timestamp1[21];

  sprintf(timestamp1,"'2000-01-01 00:00:00'");

  char timestamp2[21];

  sprintf(timestamp2,"'2010-01-01 00:00:00'");

  char timestamp3[21];

  sprintf(timestamp3,"'2001-11-07 00:00:00'");

 

  int mode=0;

  int aggnum=-1;

 

 

/* Gain tables

   ------------------------------------ */

 

  ofstream GainTable("GainTable.far");

  GainTable << "# SeqNo  \t SEIDkey  \t SEID  \t Gain \t GainErr \t Width1PE" << endl;

 

  ofstream GainTableValidity("GainTableValidity.far");

  GainTableValidity << "# SeqNo \t TimeStart \t TimeEnd \t DetMask \t SimMask \t Mode \t AggrNo \t CreationTime \t InsertTime" << endl;

 

   GainTableValidity << SeqNo << '\t' << timestamp1 << '\t' << timestamp2 << '\t' <<(Int_t) det << '\t' << (Int_t) simflag << '\t' << mode << '\t' << aggnum << '\t' <<  timestamp3 << '\t' << timestamp3 << endl;

  /* Gain tables */

 

 

/* PINResponse table

   ------------------------------------- */

 

  ofstream PINResponseTable("PINResponseTable.far");

  PINResponseTable << "# SeqNo  \t PINIDkey \t PINID  \t Constant" << endl;

 

  ofstream PINResponseValidity("PINResponseValidity.far");

  PINResponseValidity << "# SeqNo \t TimeStart \t TimeEnd \t DetMask \t SimMask \t Mode \t AggrNo \t CreationTime \t InsertTime" << endl;

 

   PINResponseValidity << SeqNo << '\t' << timestamp1 << '\t' << timestamp2 << '\t' <<(Int_t) det << '\t' << (Int_t) simflag << '\t' << mode << '\t' << aggnum << '\t' <<  timestamp3 << '\t' << timestamp3 << endl;

 

/* time drift tables

   -------------------------------------*/

 

  ofstream GainDriftTable("GainDriftTable.far");

  GainDriftTable << "# SeqNo  \t SEIDkey \t SEID  \t ScaleCorr  \t ScaleLow \t ScaleHi" << endl;

 

  ofstream GainDriftTableValidity("GainDriftTableValidity.far");

  GainDriftTableValidity << "# SeqNo \t TimeStart \t TimeEnd \t DetMask \t SimMask \t Mode \t AggrNo \t CreationTime \t InsertTime" << endl;

 

   GainDriftTableValidity << SeqNo << '\t' << timestamp1 << '\t' << timestamp2 << '\t' <<(Int_t) det << '\t' << (Int_t) simflag << '\t' << mode << '\t' << aggnum << '\t' <<  timestamp3 << '\t' << timestamp3 << endl;

 

/*  Time Drift Master table

  ------------------------------------- */

 

  ofstream GainDriftMasterTable("GainDriftMasterTable.far");

  GainDriftMasterTable << "# SeqNo  \t SEIDkey \t SEID  \t HighPIN \t HighPINErr \t LowPIN \t LowPINErr \t ADC \t ADCErr" << endl;

 

  ofstream GainDriftMasterValidity("GainDriftMasterValidity.far");

  GainDriftMasterValidity << "# SeqNo \t TimeStart \t TimeEnd \t DetMask \t SimMask \t Mode \t AggrNo \t CreationTime \t InsertTime" << endl;

 

   GainDriftMasterValidity << SeqNo << '\t' << timestamp1 << '\t' << timestamp2 << '\t' <<(Int_t) det << '\t' << (Int_t) simflag << '\t' << mode << '\t' << aggnum << '\t' <<  timestamp3 << '\t' << timestamp3 << endl;

 

/* PINtoADC table

  -------------------------------------*/

 

  ofstream PINtoADCTable("PINtoADCTable.far");

  PINtoADCTable << "# SeqNo  \t SEIDkey \t SEID  \t Scale" << endl;

 

  ofstream PINtoADCValidity("PINtoADCValidity.far");

  PINtoADCValidity << "# SeqNo \t TimeStart \t TimeEnd \t DetMask \t SimMask \t Mode \t AggrNo \t CreationTime \t InsertTime" << endl;

 

   PINtoADCValidity << SeqNo << '\t' << timestamp1 << '\t' << timestamp2 << '\t' <<(Int_t) det << '\t' << (Int_t) simflag << '\t' << mode << '\t' << aggnum << '\t' <<  timestamp3 << '\t' << timestamp3 << endl;

 

 

/* non-linearity table 

 --------------------------------------*/

 

  ofstream NonLinTable("NonLinearityTable.far");

  NonLinTable << "# SeqNo  \t Mode \t SEIDkey \t SEID  \t DataLen \t Data[40] "  << endl;

 

  ofstream NonLinTableValidity("NonLinearityValidity.far");

  NonLinTableValidity << "# SeqNo \t TimeStart \t TimeEnd \t DetMask \t SimMask \t Mode \t AggrNo \t CreationTime \t InsertTime" << endl;

 

 

   NonLinTableValidity << SeqNo << '\t' << timestamp1 << '\t' << timestamp2 << '\t' <<(Int_t) det << '\t' << (Int_t) simflag << '\t' << mode << '\t' << aggnum << '\t' <<  timestamp3 << '\t' << timestamp3 << endl;

 

 

/* mapper fits

   ------------------------------------*/

 

  ofstream MapperFitsTable("MapperFitsTable.far");

  MapperFitsTable << "# SeqNo  \t SEIDkey \t SEID  \t TestID \t StripNum \t StripEnd \t Chi2 \t NPoints \t C1 \t C1Err \t Lambda1 \t Lambda1Err \t C2 \t C2Err \t Lambda2 \t lambda2Err "  << endl;

 

  ofstream MapperFitsValidity("MapperFitsValidity.far");

  MapperFitsValidity << "# SeqNo \t TimeStart \t TimeEnd \t DetMask \t SimMask \t Mode \t AggrNo \t CreationTime \t InsertTime" << endl;

 

 

   MapperFitsValidity << SeqNo << '\t' << timestamp1 << '\t' << timestamp2 << '\t' <<(Int_t) det << '\t' << (Int_t) simflag << '\t' << mode << '\t' << aggnum << '\t' <<  timestamp3 << '\t' << timestamp3 << endl;

 

/* muon fits

  ---------------------------------------*/

 

  ofstream MuonFitsTable("MuonFitsTable.far");

  MuonFitsTable << "# SeqNo  \t SEIDkey \t SEID   Chi2 \t C0 \t C0Err \t C1 \t C1Err \t Lambda1 \t Lambda1Err \t C2 \t C2Err \t Lambda2 \t lambda2Err "  << endl;

 

  ofstream MuonFitsValidity("MuonFitsValidity.far");

  MuonFitsValidity << "# SeqNo \t TimeStart \t TimeEnd \t DetMask \t SimMask \t Mode \t AggrNo \t CreationTime \t InsertTime" << endl;

 

 

   MuonFitsValidity << SeqNo << '\t' << timestamp1 << '\t' << timestamp2 << '\t' <<(Int_t) det << '\t' << (Int_t) simflag << '\t' << mode << '\t' << aggnum << '\t' <<  timestamp3 << '\t' << timestamp3 << endl;

 

/* time

  --------------------------------------*/

 

  ofstream TimeCalibrationTable("TimeCalibrationTable.far");

  TimeCalibrationTable << "# SeqNo  \t SEIDkey \t SEID   Chi2 \t Scale \t Offset  "  << endl;

 

  ofstream TimeCalibrationValidity("TimeCalibrationValidity.far");

  TimeCalibrationValidity << "# SeqNo \t TimeStart \t TimeEnd \t DetMask \t SimMask \t Mode \t AggrNo \t CreationTime \t InsertTime" << endl;

 

 

  TimeCalibrationValidity << SeqNo << '\t' << timestamp1 << '\t' << timestamp2 << '\t' <<(Int_t) det << '\t' << (Int_t) simflag << '\t' << mode << '\t' << aggnum << '\t' <<  timestamp3 << '\t' << timestamp3 << endl;

 

 

 /* MIPs

    ---------------------------------*/

 

  ofstream MIPCalibrationTable("MIPCalibrationTable.far");

  MIPCalibrationTable << "# SeqNo  \t SEIDkey \t SEID \t  Scale  "  << endl;

 

  ofstream MIPCalibrationValidity("MIPCalibrationValidity.far");

  MIPCalibrationValidity << "# SeqNo \t TimeStart \t TimeEnd \t DetMask \t SimMask \t Mode \t AggrNo \t CreationTime \t InsertTime" << endl;

 

 

  MIPCalibrationValidity << SeqNo << '\t' << timestamp1 << '\t' << timestamp2 << '\t' <<(Int_t) det << '\t' << (Int_t) simflag << '\t' << mode << '\t' << aggnum << '\t' <<  timestamp3 << '\t' << timestamp3 << endl;

 

 

  cout << " UgliLoanPool::SetAlwaysUseDbi" << endl;

 

 

   // create the appropriate context for reading in the detector geometry/plex

  //  ----------------------------------------------------

 

   VldContext vldc(det,simflag,time);

 

  // decide now whether we have two-sided or one-sided readout

   // -------------------------------------------------------

 

   StripEnd::StripEnd_t one_sided[] = { StripEnd::kWest };

   StripEnd::StripEnd_t two_sided[] = { StripEnd::kEast,

                                        StripEnd::kWest };

   StripEnd::StripEnd_t *side_list = two_sided;

   int nsides = 2;

   if (det==DetectorType::kNear) { side_list = one_sided; nsides = 1; }

   UgliGeomHandle ugh(vldc);

 

   // quick-and-dirty way of finding last plane known to the geometry

   // what's just upstream of waaaay downstream.

   PlexPlaneId lastid = ugh.GetPlaneIdFromZ(1.0*Munits::km);

 

   int last = lastid.GetPlane();

 

   for (int ipln=0; ipln <= last; ipln++) {   // note: "<=" not "<"

      PlexPlaneId plnid(det,ipln,false);

      // skip planes that don't have an strips

      PlaneCoverage::PlaneCoverage_t cover = plnid.GetPlaneCoverage();

   

      if (cover == PlaneCoverage::kNoActive ||

          cover == PlaneCoverage::kUnknown)    continue;

 

      // get a handle for the plane and ask it how many strips it has

      // ------------------------------------------------------------

         UgliScintPlnHandle usph = ugh.GetScintPlnHandle(plnid);

         int nstrips = usph.NumberOfStrips();

         for (int istrip=0; istrip < nstrips; istrip++) {

                  

           for (int indx_side=0; indx_side<nsides; indx_side++) {

            

             PlexStripEndId oneend(plnid,istrip,side_list[indx_side]);

            

             // what the heck, check that the geometry isn't screwed up

             UgliStripHandle ush = ugh.GetStripHandle(oneend);

             if (!ush.IsValid()) cout << "invalid handle?" << endl;

          

 

             //  Get strip end ID, and generated encoded version

             //  -----------------------------------------------

 

             Int_t SEID = oneend.GetEncoded();

            

             Int_t SEIDkey = oneend.BuildPlnStripEndKey();

            

 

 

             // Now write the table entry files

             // --------------------------------

 

             GainTable  <<  SeqNo << '\t'

                        << SEIDkey << '\t'

                        << SEID << '\t'

                        << 60.0 << '\t'

                        << 0 << '\t'

                        << 30.0 << endl;

            

             //--------------------------------

             GainDriftTable  <<  SeqNo << '\t'

                             << SEIDkey  << '\t'

                             << SEID << '\t'

                             << 1.0 << '\t'

                             << 1.0  << '\t'

                             << 1.0 << endl;

 

             //--------------------------------

             GainDriftMasterTable  <<  SeqNo << '\t'

                                   << SEIDkey << '\t'

                                   << SEID << '\t'

                                   << 1000. << '\t'

                                   << 5. << '\t'

                                   << 1000. << '\t'

                                   << 5. << '\t'

                                   << 1000. << '\t'

                                   << 5. << << endl;

 

             //--------------------------------

             PINtoADCTable  <<  SeqNo << '\t'

                            << SEIDkey << '\t'

                            << SEID << '\t'

                            << 1.0 << endl;

 

             //-------------------------------

             NonLinTable  <<  SeqNo << '\t'

                          <<  0 << '\t'

                          <<  SEIDkey  << '\t' 

                          <<  SEID  << '\t'

                          << 40 << '\t';

             int j;

             for (j=0;j<20;j++) NonLinTable <<  10+j*1000.0 << '\t'

                                            << 10+j*1000.0 << '\t';

             NonLinTable  << endl;

 

             //------------------------------

             MapperFitsTable  << SeqNo  << '\t'

                              << SEIDkey << '\t'

                              << SEID << '\t'

                              << -1 << '\t'

                              << (int) oneend.GetStrip() << '\t'

                              << indx_side   << '\t'

                              << 1.0 << '\t' << 80  << '\t'

                              << 1.0 << '\t' << 0.0 << '\t'

                              << 2.0 << '\t' << 0.0 << '\t'

                              << 1.0 << '\t' << 0.0 << '\t'

                              << 8.0 << '\t' << 0.0 << endl;

 

             //-------------------------------

             MuonFitsTable << SeqNo  << '\t'

                           << SEIDkey  << '\t'

                           << SEID << '\t' 

                           << 1.0 << '\t'

                           << 1.0 << '\t' << 0.0 << '\t'

                           << 1.0 << '\t' << 0.0 << '\t'

                           << 2.0 << '\t' << 0.0 << '\t'

                           << 1.0 << '\t' << 0.0 << '\t'

                           << 8.0 << '\t' << 0.0 << endl;

 

             //--------------------------------

             TimeCalibrationTable << SeqNo  << '\t'

                                  << SEIDkey  << '\t'

                                  << SEID << '\t' 

                                  << 1.0 << '\t'

                                  << 0.0 << '\t'

                                  << 0 << '\t'

                                  << 0 << '\t'

                                  << 0 << '\t'

                                  << 0 << endl;

 

             //--------------------------------

             MIPCalibrationTable << SeqNo  << '\t'

                                 << SEIDkey  << '\t'

                                 << SEID << '\t' 

                                 << 1.0 << endl ;

 

           } // loop over legal ends

          

         } // loop over strips in plane

        

   } // loop over planes

}