/**
 * \class BDSwicDevice
 *
 * \ingroup BeamDataUtil
 *
 * \brief Base class for data from SWIC scanner devices.
 *
 * This class is a RawBeamSwicData object which applies pedestals,
 * channel masks, and anything else needed to make the per-channel
 * data more regular.  It provides the base class for more specific
 * devices such as BDHadMuMon and BDProfMon.
 *
 * \note Due to different channel numbering conventions between
 * hardware is important to distinguish between a "channel number" and
 * a data array "index number".  Channel numbering is specific to the
 * device.  See BDHadMuMon and BDProfMon classes.  Array "index
 * numbers" ALWAYS count from 0.  Data is ALWAYS accessed via an
 * index.  Never use a channel number to access that channels data,
 * use the index.  The sub classes provide an Index() method that
 * converts their native numbering scheme into an index.
 *
 * \author (last to touch it) $Author: bishai $
 *
 * \version $Revision: 1.7 $
 *
 * \date $Date: 2005/08/22 15:40:44 $
 *
 * Contact: bv@bnl.gov
 *
 * Created on: Fri Apr 15 11:52:50 2005
 *
 * $Id: BDSwicDevice.h,v 1.7 2005/08/22 15:40:44 bishai Exp $
 *
 */

#ifndef BDSWICDEVICE_H
#define BDSWICDEVICE_H

#include <RawData/RawBeamSwicData.h>

class BDSwicDevice : public RawBeamSwicData 
{
public:

    /// General type of monitor, see GetMonitorType()
    enum MonitorType {
        kUnknown = 0,
        kProfile,               ///< on of many SEM profile monitor
        kHadron,                ///< the hadron monitor
        kMuon,                  ///< one of muon monitor 1, 2 or 3.
        kWire                   ///< real SWIC.
    };

    /** \brief Default constructor.
     *
     * Constructed this way, this object will not be valid until
     * SetData() is called.  
     */

    BDSwicDevice();
    
    /** \brief Construct a BDSwicDevice with an initial RawBeamData object.
     *
     * The RawBeamData object should be from SWIC scanner data.
     */
    BDSwicDevice(const RawBeamData& swic_data);

    virtual ~BDSwicDevice();

    /** \brief Set the RawBeamData from a swic scanner device.
     *
     * If subclasses override this, they should still pass the data to
     * the parent class.
     */
    virtual void SetData(const RawBeamData& swic_data);

    /** \brief Set the per channel pedestals to use.
     *
     * \return a boolean which will be false if vector is wrong size.
     *
     * This should be an array of 96 channels worth of pedestals.  A
     * copy is made of the vector.
     *
     * \note It is assumed the pedestals are in millivolts not Munits!!!
     */
    bool SetPeds(const std::vector<double>& peds);

    /** \brief Mask off any bad channels.
     *
     * \return a boolean which will be false if vector is wrong size.
     *
     * This should be an array of 96 channels worth of masks.  The
     * mask is multiplied to the channel so a 0 means don't use the
     * channel, 1 means use it at normal strenght.  A copy is made of
     * the vector.
     *
     * Sub classes can override this in order to zero out channels
     * that are always missing but the mask should still be passed to
     * the base class for storage and use.  The subclass should only
     * zero a channel and not otherwise modify since the mask can hold
     * per-channel scaling information.
     */
    virtual bool SetMask(const std::vector<double>& mask);


    /** \brief Set the per channel noise to use.
     *
     * \return a boolean which will be false if vector is wrong size.
     *
     * This should be an array of 96 channels worth of pedestal RMS.  A
     * copy is made of the vector.
     *
     * \note It is assumed that noise is in millivolts not Munits!!!
     */
    bool SetNoise(const std::vector<double>& noise);
    
    /** \brief Set an overall scale.
     *
     * This allows an overall scale to be set by the user which will
     * be multiplied to the pedestal subtracted data.  It can be
     * useful if one wants to normalize the data to proton intensity
     * as measured by, say, a toroid.  Default is 1.0.  It is external
     * (in addition) to any calibrations.
     */
    void SetScale(double scale);

    /** \brief Set millivolt per ADC count correction.
     *
     * This allows a linear correction to convert from raw ADC counts
     * to millivolts.  Default is -0.30518 mV/ADC.
     */
    void SetMvPerADC(double mvperadc);

    /** \brief Set multiplicative gain correction.
     */
    void SetGainCorrection(double gain);

    /** \brief Set capacitance of integrating capacitor for GetCharge().
     *
     * If this goes unset all charge returned will be zero.
     *
     * units are Munits
     */
    void SetCapacitance(double cap);

    /** \brief Get a channel's voltage with all corrections applied.
     *
     * Units are in Munits (not mV!) and indexing is SWIC level
     * indexing with "index" ranging from 0-95, inclusive.  A zero is
     * returned if a bad index is passed.
     */
    virtual double GetVoltage(int index) const;

    /** \brief Get a channel's corrected charge in Munits (not pC!).
     */
    double GetCharge(int index) const;

    /** \brief Get the total voltage.
     *
     * Units are in Munits.  This just returns the sum of the above
     * over all unmasked channels.
     */
    double GetTotalVoltage();

    /** \brief Get the total charge.
     *
     * Units are in Munits (not pC!).  This just returns the sum of
     * the above over all unmasked channels.
     */
    double GetTotalCharge();

    /** Get general type of monitor as an enum. */
    MonitorType GetMonitorType() { return fType; }

    /** \brief Get the channel noise.
     *
     * Units are in mV.  This just returns the noise on a given
     * channel. Noise is defined as the RMS of the pedestal distribution.
     */
    
    double GetNoise(int index) const;

 private:

    std::vector<double> fPeds, fMask, fNoise;
    double fMvPerADC, fScale, fGain, fCap;
    std::vector<int> fData;	// cache

    MonitorType fType;

    void UpdateType();
};				// end of class BDSwicDevice

#endif  // BDSWICDEVICE_H

