Changeset 6977


Ignore:
Timestamp:
04/25/05 15:30:46 (20 years ago)
Author:
tbretz
Message:
*** empty log message ***
Location:
trunk/MagicSoft/Mars
Files:
1 added
28 edited

Legend:

Unmodified
Added
Removed
  • trunk/MagicSoft/Mars/ganymed.cc

    r6949 r6977  
    6666    gLog << "   --outf=filename           Filename for output file (eg. status display)" << endl;
    6767    gLog << "   --sum[=filename]          Enable writing of summary file (events after cut0)" << endl;
    68     gLog << "   --res[=filename]          Enable writing of result file (surviving events)" << endl;
     68//    gLog << "   --res[=filename]          Enable writing of result file (surviving events)" << endl;
     69    gLog << "   --skip-res                Disable writing of result events" << endl;
    6970    gLog << "   --write-only              Only write output files. No histograms filled." << endl;
    7071    gLog << "   --print-ds                Print Dataset information" << endl;
     
    130131    const Bool_t  kWriteSummary  = arg.HasOnlyAndRemove("--sum");
    131132    const TString kNameSummary   = arg.GetStringAndRemove("--sum=");
    132     const Bool_t  kWriteResult   = arg.HasOnlyAndRemove("--res");
    133     const TString kNameResult    = arg.GetStringAndRemove("--res=");
     133    const Bool_t  kSkipResult    = arg.HasOnlyAndRemove("--skip-res");
     134//    const Bool_t  kWriteResult   = arg.HasOnlyAndRemove("--res");
     135//    const TString kNameResult    = arg.GetStringAndRemove("--res=");
    134136
    135137    if (kWobbleModeOn && kWobbleModeOff)
     
    237239    job.SetNameOutFile(kOutfile);
    238240    job.SetNameSummaryFile(kNameSummary);
    239     job.SetNameResultFile(kNameResult);
     241    //job.SetNameResultFile(kNameResult);
    240242    job.EnableWriteOnly(kWriteOnly);
    241243    job.EnableWobbleMode(iswobble);
    242244    job.EnableFullDisplay(kFullDisplay);
    243245    job.EnableMonteCarloMode(kIsMc);
     246    job.EnableStorageOfResult(!kSkipResult);
    244247    if (kWriteSummary) // Don't change flag set in SetNameSummaryFile
    245248        job.EnableStorageOfSummary();
    246     if (kWriteResult)  // Don't change flag set in SetNameSummaryFile
    247         job.EnableStorageOfResult();
     249    //if (kWriteResult)  // Don't change flag set in SetNameSummaryFile
     250    //    job.EnableStorageOfResult();
    248251
    249252    if (!job.ProcessFile(seq))
  • trunk/MagicSoft/Mars/mhflux/MHAlpha.cc

    r6958 r6977  
    8484    fPointPos(0), fTimeEffOn(0), fTime(0),
    8585    fSkipHistTime(kFALSE), fSkipHistTheta(kFALSE), fSkipHistEnergy(kFALSE),
    86     fNumTimeBins(10), fMatrix(0)
     86    fForceUsingSize(kFALSE), fNumTimeBins(10), fMatrix(0)
     87
    8788{
    8889    //
     
    9596    fHAlpha.SetTitle("Alpha");
    9697    fHAlpha.SetXTitle("\\Theta [deg]");
    97     fHAlpha.SetYTitle("E_{est} [GeV]");
     98    //fHAlpha.SetYTitle("E_{est} [GeV]");
    9899    fHAlpha.SetZTitle("|\\alpha| [\\circ]");
    99100    fHAlpha.SetDirectory(NULL);
     
    108109
    109110
    110     //fHEnergy.SetName("Energy");
     111    fHEnergy.SetName("Excess");
    111112    //fHEnergy.SetTitle(" N_{exc} vs. E_{est} ");
    112113    //fHEnergy.SetXTitle("E_{est} [GeV]");
     
    256257
    257258    fHillas = 0;
    258     /*
    259     if (fSizeMin>=0 || fSizeMax>=0)
    260     {
    261         fHillas = (MHillas*)pl->FindObject("MHillas");
    262         if (!fHillas)
    263         {
    264             *fLog << warn << "Size cut set, but MHillas not found... abort." << endl;
    265             return kFALSE;
    266         }
    267     }
    268     */
    269     fEnergy = (MParameterD*)pl->FindObject("MEnergyEst", "MParameterD");
     259    fEnergy = fForceUsingSize ? 0 : (MParameterD*)pl->FindObject("MEnergyEst", "MParameterD");
    270260    if (!fEnergy)
    271     { /*
    272         if (fEnergyMin>=0 || fEnergyMax>=0)
    273         {
    274             *fLog << warn << "Energy cut set, but MEnergyEst not found... abort." << endl;
    275             return kFALSE;
    276         } */
    277 
     261    {
    278262        *fLog << warn << "MEnergyEst [MParameterD] not found... " << flush;
    279263
     
    285269            *fLog << "ignored." << endl;
    286270
    287         fHEnergy.SetName("ExcessSize");
    288271        fHEnergy.SetTitle(" N_{exc} vs. Size ");
    289         fHEnergy.SetXTitle("Size [\\gamma]");
     272        fHEnergy.SetXTitle("Size [phe]");
     273        fHAlpha.SetYTitle("Size [phe]");
    290274    }
    291275    else
    292276    {
    293         fHEnergy.SetName("ExcessEnergy");
    294277        fHEnergy.SetTitle(" N_{exc} vs. E_{est} ");
    295278        fHEnergy.SetXTitle("E_{est} [GeV]");
     279        fHAlpha.SetYTitle("E_{est} [GeV]");
    296280    }
    297281
     
    325309    binse.SetEdges(fOffData ? *fOffData : fHAlpha, 'y');
    326310    binsa.SetEdges(fOffData ? *fOffData : fHAlpha, 'z');
    327 
    328311    if (!fOffData)
    329312    {
     
    336319            binse.SetEdges(1, 10, 100000);
    337320        else
    338             binse.SetEdges(*pl, "BinningEnergyEst");
     321            if (fEnergy)
     322                binse.SetEdges(*pl, "BinningEnergyEst");
     323            else
     324                binse.SetEdges(*pl, "BinningSize");
    339325
    340326        binsa.SetEdges(*pl, "BinningAlpha");
     327    }
     328    else
     329    {
     330        fHEnergy.SetTitle(fOffData->GetTitle());
     331        fHEnergy.SetXTitle(fOffData->GetYaxis()->GetTitle());
     332        fHAlpha.SetYTitle(fOffData->GetYaxis()->GetTitle());
    341333    }
    342334
     
    946938        rc = kTRUE;
    947939    }
     940    if (IsEnvDefined(env, prefix, "ForceUsingSize", print))
     941    {
     942        fForceUsingSize = GetEnvValue(env, prefix, "ForceUsingSize", fForceUsingSize);
     943        rc = kTRUE;
     944    }
    948945    return rc;
    949946}
  • trunk/MagicSoft/Mars/mhflux/MHAlpha.h

    r6958 r6977  
    106106    Bool_t fSkipHistTheta;
    107107    Bool_t fSkipHistEnergy;
     108    Bool_t fForceUsingSize;
    108109
    109110    UShort_t fNumTimeBins;      // Number of time bins to fill together
     
    141142    void SetOffData(const MHAlpha &h)
    142143    {
    143         fOffData = &h.fHAlpha;
     144        fOffData        = &h.fHAlpha;
     145        fForceUsingSize =  h.fForceUsingSize;
     146        fNumTimeBins    =  h.fNumTimeBins;
    144147    }
    145148    void SetNumTimeBins(UShort_t n) { fNumTimeBins = n; }
     
    161164    void SkipHistTheta(Bool_t b=kTRUE)  { fSkipHistTheta=b; }
    162165    void SkipHistEnergy(Bool_t b=kTRUE) { fSkipHistEnergy=b; }
     166    void ForceUsingSize(Bool_t b=kTRUE) { fForceUsingSize=b; }
    163167
    164168    void DrawAll(); //*MENU*
  • trunk/MagicSoft/Mars/mhist/MHCamEvent.cc

    r6855 r6977  
    210210// Return fSum for "sum" and fRms for "rms"
    211211//
    212 TH1 *MHCamEvent::GetHistByName(const TString name)
     212TH1 *MHCamEvent::GetHistByName(const TString name) const
    213213{
    214214    return fSum;
  • trunk/MagicSoft/Mars/mhist/MHCamEvent.h

    r6855 r6977  
    4343    void SetType(Int_t type) { fType = type; }
    4444
    45     TH1 *GetHistByName(const TString name="");
     45    TH1 *GetHistByName(const TString name="") const;
    4646
    4747    void Paint(Option_t *o="");
  • trunk/MagicSoft/Mars/mhist/MHCamEventRot.h

    r5159 r6977  
    5151    Bool_t Fill(const MParContainer *par, const Stat_t w=1);
    5252
    53     TH1 *GetHistByName(const TString name) { return &fHist; }
     53    TH1 *GetHistByName(const TString name) const { return const_cast<TH2D*>(&fHist); }
    5454
    5555    void SetNameTime(const char *name) { fNameTime=name; }
  • trunk/MagicSoft/Mars/mhist/MHEvent.h

    r6855 r6977  
    4343    EventType_t fType;
    4444
    45     TH1 *GetHistByName(const TString name) { return (TH1*)fHist; }
     45    TH1 *GetHistByName(const TString name) const { return (TH1*)fHist; }
    4646
    4747    Bool_t SetupFill(const MParList *plist);
  • trunk/MagicSoft/Mars/mhist/MHStarMap.h

    r3580 r6977  
    4545    void SetMm2Deg(Float_t mmdeg);
    4646
    47     TH1 *GetHistByName(const TString name) { return (TH1*)fStarMap; }
     47    TH1 *GetHistByName(const TString name) const { return (TH1*)fStarMap; }
    4848
    4949    TH2F *GetHist() { return fStarMap; }
  • trunk/MagicSoft/Mars/mhist/MHTriggerLvl0.cc

    r2563 r6977  
    167167}
    168168
    169 TH1 *MHTriggerLvl0::GetHistByName(const TString name)
     169TH1 *MHTriggerLvl0::GetHistByName(const TString name) const
    170170{
    171171    return fSum;
  • trunk/MagicSoft/Mars/mhist/MHTriggerLvl0.h

    r2550 r6977  
    3232    void SetThreshold(Double_t t) { fThreshold = t; }
    3333
    34     TH1 *GetHistByName(const TString name="");
     34    TH1 *GetHistByName(const TString name="") const;
    3535
    3636    void Draw(Option_t * ="");
  • trunk/MagicSoft/Mars/mhistmc/MHMcTriggerLvl2.cc

    r2953 r6977  
    360360//  so remember to cast the returned object if you want to work with it.
    361361//
    362 TH1 *MHMcTriggerLvl2::GetHistByName(const TString name)
     362TH1 *MHMcTriggerLvl2::GetHistByName(const TString name) const
    363363{
    364364 
  • trunk/MagicSoft/Mars/mhistmc/MHMcTriggerLvl2.h

    r2953 r6977  
    4848    Bool_t Fill(const MParContainer *par, const Stat_t w=1);
    4949
    50     TH1 *GetHistByName(const TString name);
     50    TH1 *GetHistByName(const TString name) const;
    5151
    5252    TH1F *GetHistLutPseudoSize() const { return fHistLutPseudoSize; }
  • trunk/MagicSoft/Mars/mhvstime/MHPixVsTime.cc

    r4891 r6977  
    206206// Return histogram of TGraph
    207207//
    208 TH1 *MHPixVsTime::GetHistByName(const TString name)
     208TH1 *MHPixVsTime::GetHistByName(const TString name) const
    209209{
    210210    return fGraph->GetHistogram();
  • trunk/MagicSoft/Mars/mhvstime/MHPixVsTime.h

    r4891 r6977  
    5252    void SetTitle(const char *title);
    5353
    54     TH1 *GetHistByName(const TString name="");
     54    TH1 *GetHistByName(const TString name="") const;
    5555    TGraph *GetGraph() { return fGraph; }
    5656
  • trunk/MagicSoft/Mars/mhvstime/MHSectorVsTime.cc

    r4893 r6977  
    231231// Return fHistogram from TGraph
    232232//
    233 TH1 *MHSectorVsTime::GetHistByName(const TString name)
     233TH1 *MHSectorVsTime::GetHistByName(const TString name) const
    234234{
    235235    return fGraph->GetHistogram();
  • trunk/MagicSoft/Mars/mhvstime/MHSectorVsTime.h

    r4891 r6977  
    6464    void SetAreaIndex(const TArrayI &a)  { fAreaIndex=a; }
    6565
    66     TH1 *GetHistByName(const TString name="");
     66    TH1 *GetHistByName(const TString name="") const;
    6767    //TGraph *GetGraph() { return fGraph; }
    6868
  • trunk/MagicSoft/Mars/mimage/MHHillas.cc

    r6961 r6977  
    386386}
    387387
    388 TH1 *MHHillas::GetHistByName(const TString name)
     388TH1 *MHHillas::GetHistByName(const TString name) const
    389389{
    390390    if (name.Contains("Width", TString::kIgnoreCase))
  • trunk/MagicSoft/Mars/mimage/MHHillas.h

    r4700 r6977  
    4343    Bool_t Fill(const MParContainer *par, const Stat_t w=1);
    4444
    45     TH1 *GetHistByName(const TString name);
     45    TH1 *GetHistByName(const TString name) const;
     46    TObject *FindObject(const TObject *obj) const { return 0; }
     47    TObject *FindObject(const char *name) const
     48    {
     49        return (TObject*)GetHistByName(name);
     50    }
    4651
    4752    TH1F *GetHistLength() { return fLength; }
  • trunk/MagicSoft/Mars/mimage/MHHillasExt.cc

    r6961 r6977  
    294294}
    295295
    296 TH1 *MHHillasExt::GetHistByName(const TString name)
     296TH1 *MHHillasExt::GetHistByName(const TString name) const
    297297{
    298298    if (name.Contains("Asym", TString::kIgnoreCase))
    299         return &fHAsym;
    300     if (name.Contains("M3Long", TString::kIgnoreCase))
    301         return &fHM3Long;
    302     if (name.Contains("M3Trans", TString::kIgnoreCase))
    303         return &fHM3Trans;
     299        return const_cast<TH1F*>(&fHAsym);
     300    if (name.Contains("M3L", TString::kIgnoreCase))
     301        return const_cast<TH1F*>(&fHM3Long);
     302    if (name.Contains("M3T", TString::kIgnoreCase))
     303        return const_cast<TH1F*>(&fHM3Trans);
    304304    if (name.Contains("MaxDist", TString::kIgnoreCase))
    305         return &fHMaxDist;
     305        return const_cast<TH1F*>(&fHMaxDist);
    306306
    307307    return NULL;
  • trunk/MagicSoft/Mars/mimage/MHHillasExt.h

    r3682 r6977  
    3737    Bool_t Fill(const MParContainer *par, const Stat_t w=1);
    3838
    39     TH1 *GetHistByName(const TString name);
     39    TH1 *GetHistByName(const TString name) const;
     40    TObject *FindObject(const TObject *obj) const { return 0; }
     41    TObject *FindObject(const char *name) const
     42    {
     43        return (TObject*)GetHistByName(name);
     44    }
    4045
    4146    void Draw(Option_t *opt=NULL);
  • trunk/MagicSoft/Mars/mimage/MHHillasSrc.cc

    r6961 r6977  
    293293}
    294294
    295 TH1 *MHHillasSrc::GetHistByName(const TString name)
     295TH1 *MHHillasSrc::GetHistByName(const TString name) const
    296296{
    297297    if (name.Contains("Alpha", TString::kIgnoreCase))
  • trunk/MagicSoft/Mars/mimage/MHHillasSrc.h

    r4817 r6977  
    3232    Bool_t Fill(const MParContainer *par, const Stat_t w=1);
    3333
    34     TH1 *GetHistByName(const TString name);
     34    TH1 *GetHistByName(const TString name) const;
     35    TObject *FindObject(const TObject *obj) const { return 0; }
     36    TObject *FindObject(const char *name) const
     37    {
     38        return (TObject*)GetHistByName(name);
     39    }
    3540
    3641    TH1F *GetHistAlpha()         { return fAlpha; }
  • trunk/MagicSoft/Mars/mimage/MHImagePar.cc

    r6961 r6977  
    297297}
    298298
    299 TH1 *MHImagePar::GetHistByName(const TString name)
     299TH1 *MHImagePar::GetHistByName(const TString name) const
    300300{
    301301    if (name.Contains("SatHi", TString::kIgnoreCase))
    302         return &fHistSatHi;
     302        return const_cast<TH1F*>(&fHistSatHi);
    303303    if (name.Contains("SatLo", TString::kIgnoreCase))
    304         return &fHistSatLo;
     304        return const_cast<TH1F*>(&fHistSatLo);
    305305    if (name.Contains("Islands", TString::kIgnoreCase))
    306         return &fHistIslands;
     306        return const_cast<TH1F*>(&fHistIslands);
    307307
    308308    return NULL;
  • trunk/MagicSoft/Mars/mimage/MHImagePar.h

    r6489 r6977  
    3333    Bool_t Fill(const MParContainer *par, const Stat_t w=1);
    3434
    35     TH1 *GetHistByName(const TString name);
     35    TH1 *GetHistByName(const TString name) const;
     36    TObject *FindObject(const TObject *obj) const { return 0; }
     37    TObject *FindObject(const char *name) const
     38    {
     39        return (TObject*)GetHistByName(name);
     40    }
    3641
    3742    TH1F &GetHistSatHi()   { return fHistSatHi; }
  • trunk/MagicSoft/Mars/mimage/MHNewImagePar.cc

    r6961 r6977  
    367367}
    368368
    369 TH1 *MHNewImagePar::GetHistByName(const TString name)
     369TH1 *MHNewImagePar::GetHistByName(const TString name) const
    370370{
    371371    if (name.Contains("Leakage1", TString::kIgnoreCase))
    372         return &fHistLeakage1;
     372        return const_cast<TH1F*>(&fHistLeakage1);
    373373    if (name.Contains("Leakage2", TString::kIgnoreCase))
    374         return &fHistLeakage2;
     374        return const_cast<TH1F*>(&fHistLeakage2);
     375    if (name.Contains("Conc1", TString::kIgnoreCase)) // must be first!
     376        return const_cast<TH1F*>(&fHistConc1);
    375377    if (name.Contains("Conc", TString::kIgnoreCase))
    376         return &fHistConc;
    377     if (name.Contains("Conc1", TString::kIgnoreCase))
    378         return &fHistConc1;
     378        return const_cast<TH1F*>(&fHistConc);
    379379    if (name.Contains("UsedPix", TString::kIgnoreCase))
    380         return &fHistUsedPix;
     380        return const_cast<TH1F*>(&fHistUsedPix);
    381381    if (name.Contains("CorePix", TString::kIgnoreCase))
    382         return &fHistCorePix;
     382        return const_cast<TH1F*>(&fHistCorePix);
    383383    if (name.Contains("UsedArea", TString::kIgnoreCase))
    384         return &fHistUsedArea;
     384        return const_cast<TH1F*>(&fHistUsedArea);
    385385    if (name.Contains("CoreArea", TString::kIgnoreCase))
    386         return &fHistCoreArea;
     386        return const_cast<TH1F*>(&fHistCoreArea);
    387387
    388388    return NULL;
  • trunk/MagicSoft/Mars/mimage/MHNewImagePar.h

    r6869 r6977  
    3535    Bool_t Fill(const MParContainer *par, const Stat_t w=1);
    3636
    37     TH1 *GetHistByName(const TString name);
     37    TH1 *GetHistByName(const TString name) const;
     38    TObject *FindObject(const TObject *obj) const { return 0; }
     39    TObject *FindObject(const char *name) const
     40    {
     41        return (TObject*)GetHistByName(name);
     42    }
    3843
    3944    TH1F &GetHistLeakage1()  { return fHistLeakage1; }
  • trunk/MagicSoft/Mars/mjobs/MJCalibrateSignal.cc

    r6968 r6977  
    652652    evt8.EnableSqrtVariance();
    653653  */
    654     MFillH fill0(&evt0, "MPedestalFundamental",    "FillPedFLG");
     654    MFillH fill0(&evt0, "MPedestalFundamental",       "FillPedFLG");
    655655    MFillH fill1(&evt1, "MPedestalFromExtractorRndm", "FillPedRmsFLG");
    656     MFillH fill2(&evt2, "MExtractedSignalCam",     "FillExtracted");
     656    MFillH fill2(&evt2, "MExtractedSignalCam",        "FillExtracted");
    657657    // MFillH fill3(&evt3, "MPedPhotFundamental",  "FillPedPhot");
    658     MFillH fill4(&evt4, "MPedPhotFromExtractorRndm", "FillPedRMS");
    659     MFillH fill5(&evt5, "MSignalCam",              "FillInterpolated");
    660     MFillH fill6(&evt6, "MBadPixelsCam",           "FillUnsuitable");
    661     MFillH fill7(&evt7, "MSignalCam",              "FillTimes");
    662     MFillH fill8(&evt8, "MCalibConstCam",          "FillConv");
    663     MFillH fill9(&evt9, "MSignalCam",              "FillPulse");
     658    MFillH fill4(&evt4, "MPedPhotFromExtractorRndm",  "FillPedRMS");
     659    MFillH fill5(&evt5, "MSignalCam",                 "FillInterpolated");
     660    MFillH fill6(&evt6, "MBadPixelsCam",              "FillUnsuitable");
     661    MFillH fill7(&evt7, "MSignalCam",                 "FillTimes");
     662    MFillH fill8(&evt8, "MCalibConstCam",             "FillConv");
     663    MFillH fill9(&evt9, "MSignalCam",                 "FillPulse");
    664664
    665665    MTaskEnv fillflorian("FinalFantasy");
  • trunk/MagicSoft/Mars/sponde.cc

    r6960 r6977  
    5252    gLog << " Operation Mode:" << endl;
    5353    gLog << "   --refill                  Refill the excess histogram from result file" << endl;
    54     gLog << "                             (usefull to change the binning)" << endl << endl;
     54    gLog << "                             (usefull to change the binning)" << endl;
     55    gLog << "   --accurate                Fill original energy/theta distribution from data" << endl;
     56    gLog << "                             (do not weight the histogram)" << endl;
     57    gLog << "   --raw-mc                  Use the mc sample as it is" << endl << endl;
    5558    gLog << " Options:" << endl;
    5659    gLog.Usage();
     
    104107    gLog.Setup(arg);
    105108
    106     const TString kConfig       = arg.GetStringAndRemove("--config=", "sponde.rc");
    107 
    108     const Bool_t  kPrintSeq     = arg.HasOnlyAndRemove("--print-ds");
    109     const Bool_t  kPrintFiles   = arg.HasOnlyAndRemove("--print-files");
    110     const Bool_t  kDebugMem     = arg.HasOnlyAndRemove("--debug-mem");
     109    const TString kConfig       =  arg.GetStringAndRemove("--config=", "sponde.rc");
     110
     111    const Bool_t  kPrintSeq     =  arg.HasOnlyAndRemove("--print-ds");
     112    const Bool_t  kPrintFiles   =  arg.HasOnlyAndRemove("--print-files");
     113    const Bool_t  kDebugMem     =  arg.HasOnlyAndRemove("--debug-mem");
    111114    Int_t  kDebugEnv = arg.HasOnlyAndRemove("--debug-env") ? 1 : 0;
    112115    kDebugEnv = arg.GetIntAndRemove("--debug-env=", kDebugEnv);
    113116
    114     const Bool_t  kQuit          = arg.HasOnlyAndRemove("-q");
    115     const Bool_t  kBatch         = arg.HasOnlyAndRemove("-b");
    116     const Bool_t  kOverwrite     = arg.HasOnlyAndRemove("-f");
    117 
    118     const Bool_t  kRefill        = arg.HasOnlyAndRemove("--refill");
     117    const Bool_t  kQuit          =  arg.HasOnlyAndRemove("-q");
     118    const Bool_t  kBatch         =  arg.HasOnlyAndRemove("-b");
     119    const Bool_t  kOverwrite     =  arg.HasOnlyAndRemove("-f");
     120
     121    const Bool_t  kRefill        =  arg.HasOnlyAndRemove("--refill");
     122    const Bool_t  kSimple        = !arg.HasOnlyAndRemove("--accurate");
     123    const Bool_t  kRawMc         =  arg.HasOnlyAndRemove("--raw-mc");
    119124
    120125    if (arg.GetNumOptions()>0)
     
    207212    job.SetPathOut(kOutfile);
    208213    job.SetPathIn(kInfile);
     214
    209215    job.EnableRefilling(kRefill);
     216    job.EnableSimpleMode(kSimple);
     217    job.EnableRawMc(kRawMc);
    210218
    211219    if (!job.Process(seq))
Note: See TracChangeset for help on using the changeset viewer.