Index: /trunk/MagicSoft/Mars/Changelog
===================================================================
--- /trunk/MagicSoft/Mars/Changelog	(revision 8396)
+++ /trunk/MagicSoft/Mars/Changelog	(revision 8397)
@@ -19,4 +19,13 @@
                                                  -*-*- END OF LINE -*-*-
 
+ 2007/04/12 Thomas Bretz
+
+   * mmovie/MMoviePrepare.[h,cc], mmovie/MMovieData.[h,cc],
+     mmovie/MMovieWrite.[h,cc], mmovie/Makefile, mmovie/MovieLinkDef.h,
+     movie/MovieIncl.h:
+     - added
+
+
+
  2007/04/11 Thomas Bretz
 
Index: /trunk/MagicSoft/Mars/mmovie/MMovieData.cc
===================================================================
--- /trunk/MagicSoft/Mars/mmovie/MMovieData.cc	(revision 8397)
+++ /trunk/MagicSoft/Mars/mmovie/MMovieData.cc	(revision 8397)
@@ -0,0 +1,101 @@
+/* ======================================================================== *\
+!
+! *
+! * This file is part of MARS, the MAGIC Analysis and Reconstruction
+! * Software. It is distributed to you in the hope that it can be a useful
+! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
+! * It is distributed WITHOUT ANY WARRANTY.
+! *
+! * Permission to use, copy, modify and distribute this software and its
+! * documentation for any purpose is hereby granted without fee,
+! * provided that the above copyright notice appear in all copies and
+! * that both that copyright notice and this permission notice appear
+! * in supporting documentation. It is provided "as is" without express
+! * or implied warranty.
+! *
+!
+!
+!   Author(s): Thomas Bretz, 04/2007 <mailto:tbretz@astro.uni-wuerzburg.de>
+!
+!   Copyright: MAGIC Software Development, 2000-2007
+!
+!
+\* ======================================================================== */
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// MMovieData
+//
+/////////////////////////////////////////////////////////////////////////////
+#include "MMovieData.h"
+
+#include <TSpline.h>
+
+ClassImp(MMovieData);
+
+using namespace std;
+
+class MSpline3 : public TSpline3
+{
+public:
+   MSpline3(const char *title,
+            const TGraph *g, const char *opt=0,
+            Double_t valbeg=0, Double_t valend=0)
+        : TSpline3(title, g, opt, valbeg, valend)
+   {
+   }
+
+   Double_t GetXmin() const { return fXmin; }     // Minimum value of abscissa
+   Double_t GetXmax() const { return fXmax; }     // Maximum value of abscissa
+};
+
+// --------------------------------------------------------------------------
+//
+// Creates a MSignalPix object for each pixel in the event
+//
+MMovieData::MMovieData(const char *name, const char *title)
+{
+    fName  = name  ? name  : "MMovieData";
+    fTitle = title ? title : "Storage container for movie data";
+
+    fSplines.SetOwner();
+}
+
+// --------------------------------------------------------------------------
+//
+// Reset, deletes all stored splines
+//
+void MMovieData::Reset()
+{
+    fSplines.Delete();
+}
+
+// --------------------------------------------------------------------------
+//
+// Add a new TSpline3 from a TGraph
+//
+void MMovieData::Add(const TGraph &g)
+{
+    TSpline *sp = new MSpline3(g.GetName(), &g, "b2 e2");
+    fSplines.Add(sp);
+}
+
+// --------------------------------------------------------------------------
+//
+// Check whether tm would extra- or interpolate. kTRUE means tm will
+// be interpolated.
+//
+Bool_t MMovieData::CheckRange(Int_t idx, Double_t tm) const
+{
+    const MSpline3 &sp = (*this)[idx];
+    return tm>=sp.GetXmin() && tm<=sp.GetXmax();
+}
+
+// --------------------------------------------------------------------------
+//
+// Return the value of the idx-th spline at x=tm
+//
+Double_t MMovieData::Eval(Int_t idx, Double_t tm) const
+{
+    return (*this)[idx].Eval(tm);
+}
Index: /trunk/MagicSoft/Mars/mmovie/MMovieData.h
===================================================================
--- /trunk/MagicSoft/Mars/mmovie/MMovieData.h	(revision 8397)
+++ /trunk/MagicSoft/Mars/mmovie/MMovieData.h	(revision 8397)
@@ -0,0 +1,53 @@
+#ifndef MARS_MMovieData
+#define MARS_MMovieData
+
+#ifndef MARS_MParContainer
+#include "MParContainer.h"
+#endif
+
+#ifndef MARS_MCamEvent
+#include "MCamEvent.h"
+#endif
+
+#ifndef ROOT_TObjArray
+#include <TObjArray.h>
+#endif
+
+class TGraph;
+class MSpline3;
+
+class MMovieData : public MParContainer, public MCamEvent
+{
+private:
+    TObjArray fSplines;
+
+    Float_t fMax;
+    UInt_t  fNumSlices;
+
+    //TSpline *operator[](int i) { return (TSpline*)fSplines[i]; }
+    MSpline3 &operator[](int i) const { return *(MSpline3*)fSplines[i]; }
+
+    Bool_t GetPixelContent(Double_t &val, Int_t idx, const MGeomCam &cam, Int_t type=0) const { return kFALSE; }
+    void   DrawPixelContent(Int_t num) const { }
+
+public:
+    MMovieData(const char *name=NULL, const char *title=NULL);
+    ~MMovieData() { }
+
+    void Reset();
+    void Add(const TGraph &g);
+
+    void SetMax(Float_t mx) { fMax = mx; }
+    Float_t GetMax() const { return fMax; }
+
+    void SetNumSlices(UInt_t n) { fNumSlices=n; }
+    UInt_t GetNumSlices() const { return fNumSlices; }
+
+    Bool_t CheckRange(Int_t idx, Double_t tm) const;
+    Double_t Eval(Int_t idx, Double_t tm) const;
+    Double_t CheckedEval(Int_t idx, Double_t tm) const { return CheckRange(idx, tm) ? Eval(idx, tm) : 0; }
+
+    ClassDef(MMovieData, 1) // Storage container for movie data
+};
+
+#endif
Index: /trunk/MagicSoft/Mars/mmovie/MMoviePrepare.cc
===================================================================
--- /trunk/MagicSoft/Mars/mmovie/MMoviePrepare.cc	(revision 8397)
+++ /trunk/MagicSoft/Mars/mmovie/MMoviePrepare.cc	(revision 8397)
@@ -0,0 +1,281 @@
+/* ======================================================================== *\
+!
+! *
+! * This file is part of MARS, the MAGIC Analysis and Reconstruction
+! * Software. It is distributed to you in the hope that it can be a useful
+! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
+! * It is distributed WITHOUT ANY WARRANTY.
+! *
+! * Permission to use, copy, modify and distribute this software and its
+! * documentation for any purpose is hereby granted without fee,
+! * provided that the above copyright notice appear in all copies and
+! * that both that copyright notice and this permission notice appear
+! * in supporting documentation. It is provided "as is" without express
+! * or implied warranty.
+! *
+!
+!
+!   Author(s): Thomas Bretz  4/2007 <mailto:tbretz@astro.uni-wuerzburg.de>
+!
+!   Copyright: MAGIC Software Development, 2000-2007
+!
+!
+\* ======================================================================== */
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// MMoviePrepare
+//
+// Prepare the splines for displaying of a movie. The data is shifted by
+// the calculated time offset from MCalibrationRelTimeCam. It is
+// flat-fielded by multiplication with the calibration factor from
+// MCalibrateData divided by the median of the calibration factors of the
+// pixels with area index 0 (for MAGIC: inner pixels).
+//
+// The splines are initialized for the first slice given to the last
+// slice given (included).
+//
+// By default (MJCalibrateSignal.cc) the same slices than for the hi-gain
+// extraction range are used. To overwrite this behaviour use
+//
+//    MMoviewPrepare.FirstSlice: 10
+//    MMoviewPrepare.LastSlice:  50
+//
+// The maximum y-value set as knot is stored together with the splines
+// in MMovieData
+//
+// Input:
+//   MGeomCam
+//   MPedestalSubtractedEvt
+//   MCalibrateData
+//   MCalibrationRelTimeCam
+//   MRawRunHeader
+//
+// Output:
+//   MMovieData
+//
+/////////////////////////////////////////////////////////////////////////////
+#include "MMoviePrepare.h"
+
+#include <TGraph.h>
+
+#include "MLog.h"
+#include "MLogManip.h"
+
+#include "MString.h"
+
+#include "MParList.h"
+#include "MTaskList.h"
+
+#include "MGeomCam.h"
+#include "MGeomPix.h"
+
+#include "MCalibrationRelTimeCam.h"
+#include "MCalibrationRelTimePix.h"
+
+#include "MExtractor.h"
+#include "MMovieData.h"
+#include "MRawRunHeader.h"
+#include "MCalibrateData.h"
+//#include "MExtractedSignalCam.h"
+#include "MPedestalSubtractedEvt.h"
+
+ClassImp(MMoviePrepare);
+
+using namespace std;
+
+// --------------------------------------------------------------------------
+//
+// Default constructor. Initialize fData with default rule "MMcEvt.fEnergy"
+//
+MMoviePrepare::MMoviePrepare(const char *name, const char *title)
+    : fFirstSlice(2), fLastSlice(12)
+{
+    fName  = name  ? name  : "MMoviePrepare";
+    fTitle = title ? title : "Task to calculate a MParameterD";
+}
+
+// --------------------------------------------------------------------------
+//
+// Set moview range from extractor
+//
+void MMoviePrepare::SetRangeFromExtractor(const MExtractor &ext)
+{
+    fFirstSlice = ext.GetHiGainFirst();
+    fLastSlice  = ext.GetHiGainLast();
+}
+
+// --------------------------------------------------------------------------
+//
+// Input:
+//   MGeomCam
+//   MPedestalSubtractedEvt
+//   MCalibrateData
+//   MCalibrationRelTimeCam
+//   MRawRunHeader
+//
+// Output:
+//   MMovieData
+//
+Int_t MMoviePrepare::PreProcess(MParList *plist)
+{
+    fCam = (MGeomCam*)plist->FindObject("MGeomCam");
+    if (!fCam)
+    {
+        *fLog << err << "MGeomCam not found ... aborting." << endl;
+        return kFALSE;
+    }
+    fEvt = (MPedestalSubtractedEvt*)plist->FindObject("MPedestalSubtractedEvt");
+    if (!fEvt)
+    {
+        *fLog << err << "MPedestalSubtractedEvt not found ... aborting." << endl;
+        return kFALSE;
+    }
+    fCal = (MCalibrateData*)plist->FindTaskListWithTask("MCalibrateData")->FindTask("MCalibrateData");
+    if (!fCal)
+    {
+        *fLog << err << "MCalibrateData not found ... aborting." << endl;
+        return kFALSE;
+    }
+    fRel = (MCalibrationRelTimeCam*)plist->FindObject("MCalibrationRelTimeCam");
+    if (!fRel)
+    {
+        *fLog << err << "MCalibrationRelTimeCam not found ... aborting." << endl;
+        return kFALSE;
+    }
+    fRun = (MRawRunHeader*)plist->FindObject("MRawRunHeader");
+    if (!fRun)
+    {
+        *fLog << err << "MRawRunHeader not found ... aborting." << endl;
+        return kFALSE;
+    }
+
+    fOut = (MMovieData*)plist->FindCreateObj("MMovieData");
+    if (!fOut)
+        return kFALSE;
+
+    return kTRUE;
+}
+
+/*
+Bool_t MMoviePrepare::ReInit(MParList *plist)
+{
+    MExtractedSignalCam *cam = (MExtractedSignalCam*)plist->FindObject("MExtractedSignalCam");
+    if (!cam)
+    {
+        *fLog << err << "MExtractedSignalCam not found ... aborting." << endl;
+        return kFALSE;
+    }
+    fSlope = cam->GetNumUsedHiGainFADCSlices();
+
+    cout << "---> " << fSlope << " <---" << endl;
+
+    return kTRUE;
+}
+*/
+
+// --------------------------------------------------------------------------
+//
+// Return the median of the calibration constants of all pixels
+// with area index 0
+//
+Double_t MMoviePrepare::GetMedianCalibConst() const
+{
+    const MArrayF &calco = fCal->GetCalibConsts();
+
+    Int_t n = fCam->GetNumPixWithArea(0);
+
+    MArrayF calco0(n);
+
+    for (UInt_t i=0; i<fCam->GetNumPixels(); i++)
+        if ((*fCam)[i].GetAidx()==0)
+            calco0[--n] = calco[i];
+
+    return TMath::Median(calco0.GetSize(), calco0.GetArray());
+}
+
+// --------------------------------------------------------------------------
+//
+// Get value from fData and set it to fEnergy. SetReadyToSave for fEnergy.
+// Return kCONTINUE if value is NaN (Not a Number)
+//
+Int_t MMoviePrepare::Process()
+{
+    if (fLastSlice>=fEvt->GetNumSamples())
+    {
+        fLastSlice = fEvt->GetNumSamples()-1;
+        *fLog << inf << "Cannot go beyond last slice... set last=" << fLastSlice << "." << endl;
+    }
+
+    // ---------------- Setup ------------------
+    const UInt_t  width = fLastSlice-fFirstSlice+1;     // [slices] width of window shown
+    const Float_t freq = fRun->GetFreqSampling()/1000.; // [GHz] Sampling frequency
+    const Float_t len  = width/freq;                    // [ns]  length of data stream in data-time
+
+    // ---------------- Prepare data ------------------
+
+    fOut->Reset();
+
+    // For invalid calib constants we can use the sector average
+    const MArrayF &calco = fCal->GetCalibConsts();
+    const UShort_t npix  = fEvt->GetNumPixels();
+    const Double_t slope = 1./GetMedianCalibConst();
+
+    TGraph g(width);
+
+    Float_t max = 0;
+    for (UShort_t p=0; p<npix; p++)
+    {
+        const MCalibrationRelTimePix &tpix = (MCalibrationRelTimePix&)(*fRel)[p];
+
+        const Float_t  offset = tpix.GetTimeOffset();
+        const Float_t  cal    = calco[p];
+        const Float_t *ptr    = fEvt->GetSamples(p)+fFirstSlice;
+        const Float_t  scale  = cal*slope*fCam->GetPixRatio(p);
+
+        for (UInt_t s=0; s<width; s++)
+        {
+            const Double_t x = (s-offset)/freq;
+            const Double_t y = ptr[s]*scale;
+
+            g.SetPoint(s, x, y);
+
+            // Check for maximum in the visible time range only
+            if (x>0 && x<len && y>max)
+                max=y;
+        }
+
+        g.SetName(MString::Format("%d", p));
+        fOut->Add(g);
+    }
+
+    fOut->SetMax(max);
+    fOut->SetNumSlices(width);
+
+    return kTRUE;
+}
+
+// --------------------------------------------------------------------------
+//
+// Check for corresponding entries in resource file and setup
+//
+// Example:
+//   MMoviewPrepare.FirstSlice: 10
+//   MMoviewPrepare.LastSlice:  50
+//
+Int_t MMoviePrepare::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
+{
+    Bool_t rc = kFALSE;
+    if (IsEnvDefined(env, prefix, "FirstSlice", print))
+    {
+        rc = kTRUE;
+        fFirstSlice = GetEnvValue(env, prefix, "FirstSlice", (Int_t)fFirstSlice);
+    }
+    if (IsEnvDefined(env, prefix, "LastSlice", print))
+    {
+        rc = kTRUE;
+        fLastSlice = GetEnvValue(env, prefix, "LastSlice", (Int_t)fLastSlice);
+    }
+
+    return rc;
+}
Index: /trunk/MagicSoft/Mars/mmovie/MMoviePrepare.h
===================================================================
--- /trunk/MagicSoft/Mars/mmovie/MMoviePrepare.h	(revision 8397)
+++ /trunk/MagicSoft/Mars/mmovie/MMoviePrepare.h	(revision 8397)
@@ -0,0 +1,55 @@
+#ifndef MARS_MMoviePrepare
+#define MARS_MMoviePrepare
+
+#ifndef MARS_MTask
+#include "MTask.h"
+#endif
+
+class MGeomCam;
+class MExtractor;
+class MMovieData;
+class MSignalCam;
+class MRawEvtHeader;
+class MRawRunHeader;
+class MCalibrateData;
+class MCalibrationRelTimeCam;
+class MPedestalSubtractedEvt;
+
+class MMoviePrepare : public MTask
+{
+private:
+    MPedestalSubtractedEvt *fEvt;    //! Slices with pedestal subtracted
+    MCalibrateData         *fCal;    //! Calibration constants signal
+    MCalibrationRelTimeCam *fRel;    //! Calibration constants time
+    MRawRunHeader          *fRun;    //! Run Header (sampling frequency)
+    MGeomCam               *fCam;    //! Pixel size
+//    MCalibConstCam         *fCal;
+
+    MMovieData             *fOut;    //! Prepared output container
+
+    UInt_t fFirstSlice;
+    UInt_t fLastSlice;
+
+    //Float_t fSlope;
+
+    // MTask
+    Int_t  PreProcess(MParList *plist);
+    //Bool_t ReInit(MParList *plist);
+    Int_t  Process();
+
+    // MParContainer
+    Int_t ReadEnv(const TEnv &env, TString prefix, Bool_t print);
+
+    // MMoviePrepare
+    Double_t GetMedianCalibConst() const;
+
+public:
+    MMoviePrepare(const char *name=NULL, const char *title=NULL);
+
+    void SetRangeFromExtractor(const MExtractor &ext);
+
+    ClassDef(MMoviePrepare, 0) // Task to prepare a movie
+};
+
+#endif
+
Index: /trunk/MagicSoft/Mars/mmovie/MMovieWrite.cc
===================================================================
--- /trunk/MagicSoft/Mars/mmovie/MMovieWrite.cc	(revision 8397)
+++ /trunk/MagicSoft/Mars/mmovie/MMovieWrite.cc	(revision 8397)
@@ -0,0 +1,842 @@
+/* ======================================================================== *\
+!
+! *
+! * This file is part of MARS, the MAGIC Analysis and Reconstruction
+! * Software. It is distributed to you in the hope that it can be a useful
+! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
+! * It is distributed WITHOUT ANY WARRANTY.
+! *
+! * Permission to use, copy, modify and distribute this software and its
+! * documentation for any purpose is hereby granted without fee,
+! * provided that the above copyright notice appear in all copies and
+! * that both that copyright notice and this permission notice appear
+! * in supporting documentation. It is provided "as is" without express
+! * or implied warranty.
+! *
+!
+!
+!   Author(s): Thomas Bretz  4/2007 <mailto:tbretz@astro.uni-wuerzburg.de>
+!
+!   Copyright: MAGIC Software Development, 2000-2007
+!
+!
+\* ======================================================================== */
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// MMovieWrite
+//
+// The intention of this class is to encode movies prepard by the
+// MMoviePrepare task.
+//
+// For writing the movies the images are converted to ppm and piped through
+// ppm2y4m to mpeg2enc. The output format is a mpeg2 movie and should
+// be within the specifications of mpeg2 for DVD. Its size is 720x480,
+// which is a good compromise between resolution and file size. The frame
+// rate is fixed to 24fps.
+//
+// By changing the setup you can control the output:
+//
+//    NumEvents: To make sure the file size doesn't get too large
+//     (300 evts are roughly 80MB with the default seetings) you can set
+//     a maximum number of events. If this number of events has been encoded
+//     the eventloop is stopped.
+//
+//    TargetLength: The length (in seconds) each even will be encoded to.
+//     For example with the default Target Length of 5s and the fixed frame
+//     rate of 24fps each event will be encoded into 24f/s*5s +1f = 121frames
+//     equally distributed between the beginning of the first and the end of
+//     the last frame.
+//
+//    Threshold: The default threshold is 2. At 2 times median pedestal rms
+//     of the pixles with area index 0 (for MAGIC: inner pixels) the color
+//     palette will change from yellow to red and isolated pixels between
+//     the median rms and 2 times the median of the rms will be removed from
+//     the image. To switch off this behaviour you can set a threshold
+//     below one.
+//
+//    Filename: The output filename of the movie. If it doesn't end with ".mpg"
+//     the suffix is added.
+//
+//  The interpolation of the frames is done using a TSpline3. If the spline
+//  would extrapolate the contents is set to zero. Unsuitable pixels are
+//  interpolated frame by frame using the surrounding suitable pixels.
+//
+//
+// Input:
+//   - MGeomCam
+//   - MRawRunHeader
+//   - MRawEvtHeader
+//   - MSignalCam
+//   - MBadPixelsCam
+//   - MPedestalFundamental [MPedestalCam]
+//   - MMovieData
+//
+/////////////////////////////////////////////////////////////////////////////
+#include "MMovieWrite.h"
+
+#include <errno.h>
+
+#include <TF1.h>
+#include <TStyle.h>
+#include <TColor.h>
+#include <TCanvas.h>
+#include <TSystem.h>
+#include <TASImage.h>
+#include <TStopwatch.h>
+
+#include "MParList.h"
+#include "MTaskList.h"
+
+#include "MGeomCam.h"
+#include "MGeomPix.h"
+
+#include "MPedestalCam.h"
+#include "MPedestalPix.h"
+
+#include "MH.h"
+#include "MHCamera.h"
+#include "MMovieData.h"
+#include "MSignalCam.h"
+#include "MRawEvtHeader.h"
+#include "MRawRunHeader.h"
+#include "MBadPixelsCam.h"
+#include "MBadPixelsPix.h"
+#include "MCalibrateData.h"
+
+#include "MLog.h"
+#include "MLogManip.h"
+
+ClassImp(MMovieWrite);
+
+using namespace std;
+
+// --------------------------------------------------------------------------
+//
+// Default constructor.
+//
+MMovieWrite::MMovieWrite(const char *name, const char *title)
+    : fPipe(0), fTargetLength(5), fThreshold(2), fNumEvents(1000), fFilename("movie.mpg")
+{
+    fName  = name  ? name  : "MMovieWrite";
+    fTitle = title ? title : "Task to encode a movie";
+}
+
+// --------------------------------------------------------------------------
+//
+// Close pipe if still open
+//
+MMovieWrite::~MMovieWrite()
+{
+    if (fPipe)
+        gSystem->ClosePipe(fPipe);
+}
+
+// --------------------------------------------------------------------------
+//
+// Check the pipe for errors. In case of error print an error message.
+// return kFALSE in case of error, kTRUE in case of success.
+//
+Bool_t MMovieWrite::CheckPipe()
+{
+    if (!ferror(fPipe))
+        return kTRUE;
+
+    *fLog << err << "Error in pipe: " << strerror(errno) << endl;
+    return kFALSE;
+}
+
+// --------------------------------------------------------------------------
+//
+// Open pipe for encoding the movie
+//
+Bool_t MMovieWrite::OpenPipe()
+{
+    //    name = "ppmtoy4m -B -S 420mpeg2 -v 0 | yuvplay";
+    //    name = Form("ppmtoy4m -B -S 420jpeg -v 0 -F %d:%d | yuv2lav -v 0 -o output%03d.avi", TMath::Nint()  TMath::Nint(fTargetLength*1000))
+    //    name = "ppmtoy4m -B -F 3:1 -S 420jpeg -v 0 | yuv2lav -v 0 -o output.avi";
+
+    TString name;
+    name  = "ppmtoy4m -B -F 24:1 -S 420jpeg -v 0 | ";
+    name += "mpeg2enc -v 0 -F 2 -I 0 -M 2 -o ";
+    name += fFilename;
+    if (!fFilename.EndsWith(".mpg"))
+        name += ".mpg";
+
+    const Int_t n = TMath::Nint(fTargetLength*24)+1;
+
+    name += " -f 9 -E 40 -r 0 -K kvcd ";
+    name += Form("-g %d -G %d", n, n);
+
+    // For higher resolution add "--no-constraints"
+
+    fPipe = gSystem->OpenPipe(name, "w");
+    if (fPipe)
+        return kTRUE;
+
+    *fLog << err;
+    *fLog << "Pipe: " << name << endl;
+    *fLog << "Couldn't open pipe... aborting." << endl;
+    CheckPipe();
+    return kFALSE;
+
+    //  1: 37M name += "-f 9 -E 40 -H -4 1 -2 1 --dualprime-mpeg2";
+    //  2: 42M name += "-f 9";
+    //  3: 37M name += "-f 9 -E 40 -4 1 -2 1 --dualprime-mpeg2";
+    //  4: 37M name += "-f 9 -E 40 -4 1 -2 1";
+    //  5: 37M name += "-f 9 -E 40 -4 4 -2 4";           // 640x400   3 frames/slice
+    //  6: 11M name += "-f 3 -E 40 -b 750";              // 640x400   3 frames/slice
+
+    //  7: 28M name += "-f 9 -E 40 -G 50";               // 640x400   3 frames/slice
+    //  8: 24M name += "-f 9 -E 40 -G 500";              // 640x400   3 frames/slice
+
+    //  9: 17M name += "-f 9 -E 40 -G 2400";             // 640x400  24 frames/slice
+    // 10: 19M name += "-f 9 -E 40 -G 1120";             // 720x480   3 frames/slice
+    // 20: 33M name += "-f 9 -E 40 -g 28 -G 28";         // 720x480   3 frames/slice
+    //     57M name += "-f 9 -E 40 -g 28 -G 28 -q 4";    // 720x480   3 frames/slice
+
+    //     30M name += "-f 9 -E  40 -g 84 -G 84 -r  0";          // 720x480   3 frames/slice
+    //     31M name += "-f 9 -E  40 -g 56 -G 56 -r  0";          // 720x480   3 frames/slice
+    //     34M name += "-f 9 -E  40 -g 28 -G 28 -r  0";          // 720x480   3 frames/slice
+    // 24: 24M name += "-f 9 -E  40 -g 28 -G 28 -r  0 -K kvcd";  // 720x480   3 frames/slice
+    // 25: 24M name += "-f 9 -E -40 -g 28 -G 28 -r  0 -K kvcd";  // 720x480   3 frames/slice
+    // 26: 26M name += "-f 9 -E   0 -g 28 -G 28 -r  0 -K kvcd";  // 720x480   3 frames/slice
+    //     34M name += "-f 9 -E  40 -g 28 -G 28 -r  2";          // 720x480   3 frames/slice
+    //     33M name += "-f 9 -E  40 -g 28 -G 28 -r 32";          // 720x480   3 frames/slice
+
+    // name += "-f 9 -E 40 -g 121 -G 121 -r 0 -K kvcd";  // 720x480 5s  24 frames/slice
+
+    // 11: 56M name += "-f 9 -E 40 -g 217 -G 217";       // 720x480  24 frames/slice
+    // 18: 59M name += "-f 9 -E 40 -G 250";              // 720x480  24 frames/slice
+    //     62M name += "-f 9 -E 40 -G 184";              // 720x480  24 frames/slice
+
+    // 12: --- name += "-f 9 -E 40 -G 500 -q 31";        // 720x480  3frames/slice
+    // 13: 49M name += "-f 9 -E 40 -G 500 -q 4";         // 720x480  3frames/slice
+    // 14: 21M name += "-f 9 -E 40 -G 500 -q 4 -b 1500"; // 720x480  3frames/slice
+
+    // 15: 57M name += "-f 9 -E 40 -G 500 --no-constraints"; // 1280 864  3frames/slice
+
+    // 16: >80 name += "-f 9 -E 40 -G 217 --no-constraints -b 3000"; // 1280 864  24frames/slice
+    // 17: >50 name += "-f 9 -E 40 -G 682 -b 3000 --no-constraints"; // 1280 864  24frames/slice
+}
+
+// --------------------------------------------------------------------------
+//
+// Search for:
+//   - MGeomCam
+//   - MRawRunHeader
+//   - MRawEvtHeader
+//   - MSignalCam
+//   - MBadPixelsCam
+//   - MPedestalFundamental [MPedestalCam]
+//   - MMovieData
+//
+// Open a pipe to write the images to. Can be either a player or
+// an encoder.
+//
+Int_t MMovieWrite::PreProcess(MParList *plist)
+{
+    fCam = (MGeomCam*)plist->FindObject("MGeomCam");
+    if (!fCam)
+    {
+        *fLog << err << "MGeomCam not found ... aborting." << endl;
+        return kFALSE;
+    }
+    fRun = (MRawRunHeader*)plist->FindObject("MRawRunHeader");
+    if (!fRun)
+    {
+        *fLog << err << "MRawRunHeader not found ... aborting." << endl;
+        return kFALSE;
+    }
+    fHead = (MRawEvtHeader*)plist->FindObject("MRawEvtHeader");
+    if (!fHead)
+    {
+        *fLog << err << "MRawEvtHeader not found ... aborting." << endl;
+        return kFALSE;
+    }
+    fSig = (MSignalCam*)plist->FindObject("MSignalCam");
+    if (!fSig)
+    {
+        *fLog << err << "MSignalCam not found ... aborting." << endl;
+        return kFALSE;
+    }
+    fBad = (MBadPixelsCam*)plist->FindObject("MBadPixelsCam");
+    if (!fBad)
+    {
+        *fLog << err << "MBadPixelsCam not found ... aborting." << endl;
+        return kFALSE;
+    }
+    fPed = (MPedestalCam*)plist->FindObject("MPedestalFundamental", "MPedestalCam");
+    if (!fPed)
+    {
+        *fLog << err << "MPedestalFundamental [MPedestalCam] not found ... aborting." << endl;
+        return kFALSE;
+    }
+    fIn = (MMovieData*)plist->FindObject("MMovieData");
+    if (!fIn)
+    {
+        *fLog << err << "MMovieData not found... aborting." << endl;
+        return kFALSE;
+    }
+
+    return OpenPipe();
+}
+
+TStopwatch clockT, clock1, clock2, clock3;
+
+// --------------------------------------------------------------------------
+//
+// Close pipe if still open
+//
+Int_t MMovieWrite::PostProcess()
+{
+    if (fPipe)
+    {
+        gSystem->ClosePipe(fPipe);
+        fPipe=0;
+    }
+
+    *fLog << all << endl;
+    *fLog << "Snap: " << flush;
+    clock1.Print();
+    *fLog << "Writ: " << flush;
+    clock2.Print();
+    *fLog << "Prep: " << flush;
+    clock3.Print();
+    *fLog << "Totl: " << flush;
+    clockT.Print();
+    *fLog << endl;
+
+    return kTRUE;
+}
+
+// --------------------------------------------------------------------------
+//
+// Produce a 99 color palette made such, that everything below one
+// pedestal rms is white, everything up to two pedestal rms is yellow
+// and everything above gets colors.
+//
+void MMovieWrite::SetPalette(Double_t rms, const TH1 &h) const
+{
+    const Double_t min = h.GetMinimum();
+    const Double_t max = h.GetMaximum();
+
+    const Double_t f = (fThreshold*rms-min)/(max-min);
+    const Double_t w = 1-f;
+
+    // --- Produce the nice colored palette ---
+
+    //             min      th*rms                 max
+    double s[6] = {0.0, f/2,  f,   f+w/4, f+3*w/5, 1.0 };
+
+    double r[6] = {1.0, 1.0,  1.0, 0.85,  0.1,     0.0 };
+    double g[6] = {1.0, 1.0,  1.0, 0.0,   0.1,     0.0 };
+    double b[6] = {0.9, 0.55, 0.4, 0.0,   0.7,     0.1 };
+
+    TArrayI col(99);
+    gStyle->CreateGradientColorTable(6, s, r, g, b, col.GetSize());
+
+    // --- Overwrite the 'underflow' bin with white ---
+
+    for (int i=0; i<col.GetSize(); i++)
+        col[i] = gStyle->GetColorPalette(i);
+
+    col[0] = TColor::GetColor(0xff, 0xff, 0xff);
+
+    // --- Set Plette ---
+
+    gStyle->SetPalette(col.GetSize(), col.GetArray());
+}
+
+/*
+// --------------------------------------------------------------------------
+//
+// Do a snapshot from the pad via TASImage::FromPad and write the
+// image to the pipe.
+// return kFALSE in case of error, kTRUE in case of success.
+//
+Bool_t MMovieWrite::WriteImage(TVirtualPad &pad)
+{
+    clock1.Start(kFALSE);
+    TASImage img;
+    img.FromPad(&pad);
+    clock1.Stop();
+
+    clock2.Start(kFALSE);
+    const Bool_t rc = WriteImage(img);
+    clock2.Stop();
+
+    return rc;
+}
+
+#include <TVirtualPS.h>
+Bool_t MMovieWrite::WriteImage(TVirtualPad &pad)
+{
+    TVirtualPS *psave = gVirtualPS;
+
+    clock1.Start(kFALSE);
+    TImage dump("", 114);
+    dump.SetBit(BIT(11));
+    pad.Paint();
+    TASImage *itmp = (TASImage*)dump.GetStream();
+    clock1.Stop();
+
+    clock2.Start(kFALSE);
+    const Bool_t rc = WriteImage(*itmp);
+    clock2.Stop();
+
+    gVirtualPS = psave;
+
+    return rc;
+}
+*/
+
+// --------------------------------------------------------------------------
+//
+// Update the part of the idst image with the contents of the pad.
+//
+// It is a lot faster not to rerender the parts of the image which don't
+// change anyhow, because rerendering the camera is by far the slowest.
+//
+void MMovieWrite::UpdateImage(TASImage &idst, TVirtualPad &pad)
+{
+    // Get image from pad
+    TASImage isrc;
+    isrc.FromPad(&pad);
+
+    // Get position and width of destination- and source-image
+    const UInt_t wsrc = isrc.GetWidth();    // width  of image
+    const UInt_t hsrc = isrc.GetHeight();   // height of image
+
+    const UInt_t usrc = pad.UtoPixel(1)*4;  // width  of pad (argb)
+    //const UInt_t vsrc = pad.VtoPixel(0);    // height of pad
+
+    const UInt_t xsrc = pad.UtoAbsPixel(0); // offset of pad in canvas
+    const UInt_t ysrc = pad.VtoAbsPixel(1); // offset of pad in canvas
+
+    const UInt_t wdst = idst.GetWidth();
+    //const UInt_t hdst = idst.GetHeight();
+
+    // Update destination image with source image
+    const UInt_t size = wsrc*hsrc;
+
+    UInt_t *psrc = isrc.GetArgbArray();
+    UInt_t *pdst = idst.GetArgbArray();
+
+    UInt_t *src = psrc + ysrc*wsrc+xsrc;
+    UInt_t *dst = pdst + ysrc*wdst+xsrc;
+
+    while (src<psrc+size)
+    {
+        memcpy(dst, src, usrc);
+
+        src += wsrc;
+        dst += wdst;
+    }
+}
+
+// --------------------------------------------------------------------------
+//
+// Write the image as ppm (raw/P6) to the pipe.
+// return kFALSE in case of error, kTRUE in case of success.
+//
+Bool_t MMovieWrite::WriteImage(TASImage &img)
+{
+    // Write image header
+    fprintf(fPipe, "P6 %d %d 255\n", img.GetWidth(), img.GetHeight());
+    if (!CheckPipe())
+        return kFALSE;
+
+    // Write image data (remove alpha channel from argb data)
+    UInt_t *argb = img.GetArgbArray();
+    for (UInt_t *ptr=argb; ptr<argb+img.GetWidth()*img.GetHeight(); ptr++)
+        fwrite(ptr, 1, 3, fPipe);
+
+    return CheckPipe();
+}
+
+// --------------------------------------------------------------------------
+//
+// Update TASImage with changing parts of the image and write image to pipe.
+// return kFALSE in case of error, kTRUE in case of success.
+//
+Bool_t MMovieWrite::WriteImage(TASImage &img, TVirtualPad &pad)
+{
+    clock1.Start(kFALSE);
+    UpdateImage(img, pad);
+    clock1.Stop();
+
+    clock2.Start(kFALSE);
+    const Bool_t rc = WriteImage(img);
+    clock2.Stop();
+
+    return rc;
+}
+
+// --------------------------------------------------------------------------
+//
+// Do a simple interpolation of the surrounding suitable pixels for all
+// unsuitable pixels.
+//
+void MMovieWrite::TreatBadPixels(TH1 &h) const
+{
+    const UShort_t entries = fCam->GetNumPixels();
+
+    //
+    // Loop over all pixels
+    //
+    for (UShort_t i=0; i<entries; i++)
+    {
+        //
+        // Check whether pixel with idx i is blind
+        //
+        if (!(*fBad)[i].IsUnsuitable())
+            continue;
+
+        const MGeomPix &gpix = (*fCam)[i];
+
+        Int_t    num = 0;
+        Double_t sum = 0;
+
+        //
+        // Loop over all its neighbors
+        //
+        Int_t n = gpix.GetNumNeighbors();
+        while (n--)
+        {
+            const UShort_t nidx = gpix.GetNeighbor(n);
+
+            //
+            // Do not use blind neighbors
+            //
+            if ((*fBad)[nidx].IsUnsuitable())
+                continue;
+
+            sum += h.GetBinContent(nidx+1);
+            num++;
+        }
+
+        h.SetBinContent(i+1, sum/num);
+    }
+}
+
+// --------------------------------------------------------------------------
+//
+// Do a simple interpolation of the surrounding suitable pixels for all
+// unsuitable pixels.
+//
+void MMovieWrite::Clean(TH1 &h, Double_t rms) const
+{
+    if (fThreshold<1)
+        return;
+
+    const UShort_t entries = fCam->GetNumPixels();
+
+    //
+    // Loop over all pixels
+    //
+    for (UShort_t i=0; i<entries; i++)
+    {
+        Double_t val = h.GetBinContent(i+1);
+        if (val<rms || val>fThreshold*rms)
+            continue;
+
+        const MGeomPix &gpix = (*fCam)[i];
+
+        //
+        // Loop over all its neighbors
+        //
+        Int_t n = gpix.GetNumNeighbors();
+        while (n)
+        {
+            const UShort_t nidx = gpix.GetNeighbor(n-1);
+            if (h.GetBinContent(nidx+1)>=rms)
+                break;
+            n--;
+        }
+
+        if (n==0)
+            h.SetBinContent(i+1, 0);
+    }
+}
+
+// --------------------------------------------------------------------------
+//
+// Return the median of the pedestal rms of all pixels with area index 0
+//
+Double_t MMovieWrite::GetMedianPedestalRms() const
+{
+    Int_t n = fCam->GetNumPixWithAidx(0);
+
+    MArrayF rms(n);
+
+    for (UInt_t i=0; i<fCam->GetNumPixels(); i++)
+        if ((*fCam)[i].GetAidx()==0)
+            rms[--n] = (*fPed)[i].GetPedestalRms();
+
+    return TMath::Median(rms.GetSize(), rms.GetArray());
+}
+
+// --------------------------------------------------------------------------
+//
+Bool_t MMovieWrite::Process(TH1 &h, TVirtualPad &c)
+{
+    // ---------------- Setup ------------------
+
+    const Float_t freq   = fRun->GetFreqSampling()/1000.; // [GHz] Sampling frequency
+    const UInt_t  slices = fIn->GetNumSlices();
+    const Float_t len    = slices/freq;                   // [ns]  length of data stream in data-time
+    //const Float_t len    = (slices-2)/freq;               // [ns]  length of data stream in data-time
+
+    const Double_t rms = GetMedianPedestalRms();
+
+    h.SetMinimum(fIn->GetMax()-(fIn->GetMax()-rms)*99/98); // rms0
+    h.SetMaximum(fIn->GetMax());
+
+    // -----------------------------------------
+
+    // Produce starting image from canvas
+    TASImage img;
+    img.FromPad(&c);
+
+    // Set new adapted palette for further rendering
+    SetPalette(rms, h);
+
+    // Get the pad containing the camera with the movie
+    TVirtualPad &pad = *c.GetPad(1)->GetPad(1);
+
+    // Calculate number of frames
+    const Int_t numframes = TMath::Nint(fTargetLength*24);
+
+    // Get number of pixels in camera
+    const Int_t npix = fCam->GetNumPixels();
+
+    // Loop over all frames+1 (upper edge)
+    for (Int_t i=0; i<=numframes; i++)
+    {
+        // Calculate corresponding time
+        const Float_t t = len*i/numframes;// + 0.5/freq;  // Process from slice beg+0.5 to end-1.5
+
+        // Calculate histogram contents by spline interpolation
+        for (UShort_t p=0; p<npix; p++)
+        {
+            const Double_t y = (*fBad)[p].IsUnsuitable() ? 0 : fIn->CheckedEval(p, t);
+            h.SetBinContent(p+1, y);
+        }
+
+        // Interpolate unsuitable pixels
+        TreatBadPixels(h);
+
+        // Clean single pixels
+        Clean(h, rms);
+
+        // Set new name to be displayed
+        h.SetName(Form("%d: %.2f/%.1fns", i+1, t*freq, t));
+
+        // Update existing image with new data and encode into pipe
+        if (!WriteImage(img, pad))
+            return kFALSE;
+    }
+
+    cout << setw(3) << GetNumExecutions() << ": " << Form("%6.2f", (float)numframes/(slices-2)) << " f/sl " << slices << " " << numframes+1 << endl;
+
+    return kTRUE;
+}
+
+// --------------------------------------------------------------------------
+//
+Int_t MMovieWrite::Process()
+{
+    clockT.Start(kFALSE);
+
+    clock3.Start(kFALSE);
+
+    // ---------------- Prepare display ------------------
+
+    Bool_t batch = gROOT->IsBatch();
+    gROOT->SetBatch();
+
+    TCanvas c;
+    //c.Iconify();
+    c.SetBorderMode(0);
+    c.SetFrameBorderMode(0);
+    c.SetFillColor(kWhite);
+    //c.SetCanvasSize(640, 400);
+    c.SetCanvasSize(720, 480);
+    //c.SetCanvasSize(960, 640);
+    //c.SetCanvasSize(1024, 688);
+    //c.SetCanvasSize(1152, 768);
+    //c.SetCanvasSize(1280, 864);
+
+    MH::SetPalette("pretty");
+
+    c.cd();
+    TPad p1("Pad2", "", 0.7, 0.66, 0.99, 0.99);
+    p1.SetNumber(2);
+    p1.SetBorderMode(0);
+    p1.SetFrameBorderMode(0);
+    p1.SetFillColor(kWhite);
+    p1.Draw();
+    p1.cd();
+
+    MHCamera hsig(*fCam, "Signal", "Calibrated Signal");
+    hsig.SetYTitle("S [phe]");
+    hsig.SetCamContent(*fSig, 99);
+    hsig.SetMinimum(0);
+    //hsig.SetContour(99);
+    hsig.Draw("nopal");
+
+    c.cd();
+    TPad p2("Pad3", "", 0.7, 0.33, 0.99, 0.65);
+    p2.SetNumber(3);
+    p2.SetBorderMode(0);
+    p2.SetFrameBorderMode(0);
+    p2.SetFillColor(kWhite);
+    p2.Draw();
+    p2.cd();
+
+    MHCamera htime(*fCam, "ArrivalTime", "Calibrated Arrival Time");
+    htime.SetYTitle("T [au]");
+    htime.SetCamContent(*fSig, 8);
+    htime.Draw("nopal");
+
+    c.cd();
+    TPad p3("Pad4", "", 0.7, 0.00, 0.99, 0.32);
+    p3.SetNumber(4);
+    p3.SetBorderMode(0);
+    p3.SetFrameBorderMode(0);
+    p3.SetFillColor(kWhite);
+    p3.Draw();
+    p3.cd();
+/*
+    TH1F htpro("TimeProj", "", slices, 0, len);
+    for (UInt_t i=0; i<htime.GetNumPixels(); i++)
+        if(htime.IsUsed(i))
+            htpro.Fill((htime.GetBinContent(i+1)-first)/freq, hsig.GetBinContent(i+1));
+    htpro.SetMinimum(0);
+    htpro.SetMaximum(100);
+    htpro.SetLineColor(kBlue);
+    htpro.Draw();
+
+    TF1 fgaus("f1", "gaus");
+    const Double_t m = (htpro.GetMaximumBin()-0.5)*len/slices;
+    fgaus.SetParameter(0, htpro.GetMaximum());
+    fgaus.SetParameter(1, m);
+    fgaus.SetParameter(2, 1.0);
+    fgaus.SetParLimits(1, m-3, m+3);
+    fgaus.SetParLimits(2, 0, 3);
+    fgaus.SetLineWidth(1);
+    fgaus.SetLineColor(kMagenta);
+    htpro.Fit(&fgaus, "NI", "", m-3, m+3);
+    fgaus.Draw("same");
+
+    g.SetMarkerStyle(kFullDotMedium);
+    g.Draw("PL");
+    //g.SetMinimum(0);
+    //g.SetMaximum(100);
+    //g.Draw("APL");
+
+    p3.Update();
+    p3.cd(1);
+    gPad->Update();
+  */
+    c.cd();
+    TPad p0("MainPad", "", 0.01, 0.01, 0.69, 0.99);
+    p0.SetNumber(1);
+    p0.SetBorderMode(0);
+    p0.SetFrameBorderMode(0);
+    p0.SetFillColor(kWhite);
+    p0.Draw();
+    p0.cd();
+ /*
+    cout << "Max=" << hsig.GetMaximum() << "/" << fIn->GetMax() << "   ";
+    cout << hsig.GetMaximum()/fIn->GetMax() << endl;
+    Float_t rms0 = fPed->GetAveragedRmsPerArea(*fCam, 0, fBad)[0];
+    Float_t rms1 = fPed->GetAveragedRmsPerArea(*fCam, 1, fBad)[0];
+    cout << "RMS="<<rms0<<"/"<<rms1<<endl;
+
+    rms0 = GetMedianPedestalRms();
+
+    cout << "MED=" << rms0 << endl;
+  */
+    MHCamera h(*fCam);
+    h.SetTitle(Form("%d: Run #%d,  Evt %d", GetNumExecutions()+1,
+                    fRun->GetRunNumber(), fHead->GetDAQEvtNumber()));
+    h.SetAllUsed();
+    h.SetYTitle("V [au]");
+    h.SetContour(99);
+
+    h.Draw("nopal");
+
+    // ---------------- Show data ------------------
+    gStyle->SetOptStat(1000000001);
+/*                     
+    p0.Modified();
+    p1.Modified();
+    p2.Modified();
+
+    p0.GetPad(1)->Modified();
+    p1.GetPad(1)->Modified();
+    p2.GetPad(1)->Modified();
+
+    c.Update();
+ */
+
+    // ---------------- Show data ------------------
+
+    clock3.Stop();
+
+    // Switch off automatical adding to directory (SetName would do)
+    const Bool_t add = TH1::AddDirectoryStatus();
+    TH1::AddDirectory(kFALSE);
+
+    const Bool_t rc = Process(h, c);
+
+    // restore previous state
+    TH1::AddDirectory(add);
+
+    clockT.Stop();
+
+    gROOT->SetBatch(batch);
+
+    if (!rc)
+        return kERROR;
+
+    return fNumEvents<=0 || GetNumExecutions()<fNumEvents;
+}
+
+// --------------------------------------------------------------------------
+//
+// Check for corresponding entries in resource file and setup
+//
+// Example:
+//   MMoviewPrepare.TargetLength: 5 <seconds>
+//   MMoviewPrepare.NumEvents: 500
+//   MMoviewPrepare.Threshold: 2 <rms>
+//   MMoviewPrepare.Filename: movie.mpg
+//
+Int_t MMovieWrite::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
+{
+    Bool_t rc = kFALSE;
+    if (IsEnvDefined(env, prefix, "NumEvents", print))
+    {
+        fNumEvents = GetEnvValue(env, prefix, "NumEvents", (Int_t)fNumEvents);
+        rc = kTRUE;
+    }
+    if (IsEnvDefined(env, prefix, "TargetLength", print))
+    {
+        fTargetLength = GetEnvValue(env, prefix, "TargetLength", fTargetLength);
+        rc = kTRUE;
+    }
+    if (IsEnvDefined(env, prefix, "Threshold", print))
+    {
+        fThreshold = GetEnvValue(env, prefix, "Threshold", fThreshold);
+        rc = kTRUE;
+    }
+    if (IsEnvDefined(env, prefix, "Filename", print))
+    {
+        fFilename = GetEnvValue(env, prefix, "Filename", fFilename);
+        rc = kTRUE;
+    }
+    return rc;
+}
Index: /trunk/MagicSoft/Mars/mmovie/MMovieWrite.h
===================================================================
--- /trunk/MagicSoft/Mars/mmovie/MMovieWrite.h	(revision 8397)
+++ /trunk/MagicSoft/Mars/mmovie/MMovieWrite.h	(revision 8397)
@@ -0,0 +1,78 @@
+#ifndef MARS_MMovieWrite
+#define MARS_MMovieWrite
+
+#ifndef MARS_MTask
+#include "MTask.h"
+#endif
+
+class TH1;
+class TASImage;
+
+class MGeomCam;
+class MMovieData;
+class MSignalCam;
+class MPedestalCam;
+class MRawEvtHeader;
+class MRawRunHeader;
+class MBadPixelsCam;
+
+class MMovieWrite : public MTask
+{
+private:
+    MRawRunHeader *fRun;   //! Header with run number and sampling frequency
+    MRawEvtHeader *fHead;  //! Header with event number
+    MGeomCam      *fCam;   //! Camera geometry necessary for the histograms
+    MSignalCam    *fSig;   //! Input signal to display cleaned and uncleaned event
+    MBadPixelsCam *fBad;   //! Information about bad pixels
+    MPedestalCam  *fPed;   //! Fundamental pedestal for palette and cleaning
+
+    MMovieData    *fIn;    //! Input data with splines for all pixels
+
+    FILE          *fPipe;  //! Ouput pipe to player or encoder
+
+    Float_t fTargetLength; // [s] Target length for stream of one event (+1 frame)
+    Float_t fThreshold;    // Threshold for cleaning
+    UInt_t  fNumEvents;    // Maximum number of events to encode
+
+    TString fFilename;     // name of output file
+
+    // MTask
+    Int_t PreProcess(MParList *plist);
+    Int_t Process();
+    Int_t PostProcess();
+
+    // MParContainer
+    Int_t ReadEnv(const TEnv &env, TString prefix, Bool_t print);
+
+    // MMovieWrite
+    Bool_t OpenPipe();
+    Bool_t CheckPipe();
+
+    Double_t GetMedianPedestalRms() const;
+
+    void Clean(TH1 &h, Double_t rms) const;
+    void TreatBadPixels(TH1 &h) const;
+
+    void SetPalette(Double_t rms, const TH1 &h) const;
+
+    void UpdateImage(TASImage &img, TVirtualPad &pad);
+
+    Bool_t WriteImage(TASImage &img);
+    Bool_t WriteImage(TASImage &img, TVirtualPad &pad);
+    //Bool_t WriteImage(TVirtualPad &pad);
+
+    Bool_t Process(TH1 &h, TVirtualPad &c);
+
+public:
+    MMovieWrite(const char *name=NULL, const char *title=NULL);
+    ~MMovieWrite();
+
+    void SetFilename(const char *f) { fFilename = f; }
+    void SetNumEvents(Int_t n) { fNumEvents = n; }
+    void SetThreshold(Float_t f) { fThreshold = f; }
+    void SetTargetLength(Float_t l) { fTargetLength = l; }
+
+    ClassDef(MMovieWrite, 0) // Task to encode a movie
+};
+
+#endif
Index: /trunk/MagicSoft/Mars/mmovie/Makefile
===================================================================
--- /trunk/MagicSoft/Mars/mmovie/Makefile	(revision 8397)
+++ /trunk/MagicSoft/Mars/mmovie/Makefile	(revision 8397)
@@ -0,0 +1,38 @@
+##################################################################
+#
+#   subdirectory makefile
+# 
+#   for the MARS software
+#
+##################################################################
+include ../Makefile.conf.$(OSTYPE)
+include ../Makefile.conf.general
+
+#------------------------------------------------------------------------------
+
+#
+# Handling name of the Root Dictionary Files
+#
+CINT  = Movie
+
+#
+#  connect the include files defined in the config.mk file
+#
+INCLUDES = -I. -I../mbase -I../mraw -I../mgeom -I../mhbase -I../mgui \
+           -I../mcalib -I../msignal -I../mbadpixels -I../mpedestal   \
+           -I../mhist
+
+SRCFILES = MMoviePrepare.cc \
+           MMovieData.cc \
+           MMovieWrite.cc
+
+############################################################
+
+all:  $(OBJS)
+
+include ../Makefile.rules
+
+clean:	rmcint rmobjs rmcore rmlib
+
+mrproper:	clean rmbak
+
Index: /trunk/MagicSoft/Mars/mmovie/MovieIncl.h
===================================================================
--- /trunk/MagicSoft/Mars/mmovie/MovieIncl.h	(revision 8397)
+++ /trunk/MagicSoft/Mars/mmovie/MovieIncl.h	(revision 8397)
@@ -0,0 +1,3 @@
+#ifndef __CINT__
+
+#endif // __CINT__
Index: /trunk/MagicSoft/Mars/mmovie/MovieLinkDef.h
===================================================================
--- /trunk/MagicSoft/Mars/mmovie/MovieLinkDef.h	(revision 8397)
+++ /trunk/MagicSoft/Mars/mmovie/MovieLinkDef.h	(revision 8397)
@@ -0,0 +1,11 @@
+#ifdef __CINT__
+
+#pragma link off all globals;
+#pragma link off all classes;
+#pragma link off all functions;
+
+#pragma link C++ class MMovieWrite+;
+#pragma link C++ class MMoviePrepare+;
+#pragma link C++ class MMovieData+;
+
+#endif
