Index: trunk/Mars/mimage/ImageLinkDef.h
===================================================================
--- trunk/Mars/mimage/ImageLinkDef.h	(revision 17831)
+++ trunk/Mars/mimage/ImageLinkDef.h	(revision 17832)
@@ -6,4 +6,5 @@
 
 #pragma link C++ class MImgCleanStd+;
+#pragma link C++ class MImgCleanTime+;
 #pragma link C++ class MImgCleanSimple+;
 
Index: trunk/Mars/mimage/MImgCleanTime.cc
===================================================================
--- trunk/Mars/mimage/MImgCleanTime.cc	(revision 17832)
+++ trunk/Mars/mimage/MImgCleanTime.cc	(revision 17832)
@@ -0,0 +1,239 @@
+/* ======================================================================== *\
+!
+! *
+! * 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/2014 <mailto:tbretz@phys.ethz.ch>
+!
+!   Copyright: MAGIC Software Development, 2014
+!
+!
+\* ======================================================================== */
+
+/////////////////////////////////////////////////////////////////////////////
+//
+//  MImgCleanTime
+//
+//  Input Containers:
+//   MGeomCam
+//   MSignalCam
+//
+//  Output Containers:
+//   MSignalCam
+//
+/////////////////////////////////////////////////////////////////////////////
+#include "MImgCleanTime.h"
+
+#include <TEnv.h>
+
+#include "MLog.h"
+#include "MLogManip.h"
+
+#include "MParList.h"
+
+#include "MGeomPix.h"
+#include "MGeomCam.h"
+
+#include "MSignalPix.h"
+#include "MSignalCam.h"
+
+ClassImp(MImgCleanTime);
+
+using namespace std;
+
+// --------------------------------------------------------------------------
+//
+// Default constructor. Here you can specify the cleaning method and levels. 
+// If you don't specify them the 'common standard' values 3.0 and 2.5 (sigma
+// above mean) are used.
+// Here you can also specify how many rings around the core pixels you want 
+// to analyze (with the fixed lvl2). The default value for "rings" is 1.
+//
+MImgCleanTime::MImgCleanTime(const char *name, const char *title)
+    : fCam(0), fEvt(0), fMinCount(0), fMinSize(25), fDeltaT(2.5*17.5*0.1111),
+    fNameSignalCam("MSignalCam")
+{
+    fName  = name  ? name  : "MImgCleanTime";
+    fTitle = title ? title : "Task to perform image cleaning";
+}
+
+// --------------------------------------------------------------------------
+//
+//  Check if MEvtHeader exists in the Parameter list already.
+//  if not create one and add them to the list
+//
+Int_t MImgCleanTime::PreProcess (MParList *pList)
+{
+    fCam = (MGeomCam*)pList->FindObject("MGeomCam");
+    if (!fCam)
+    {
+        *fLog << err << "MGeomCam not found (no geometry information available)... aborting." << endl;
+        return kFALSE;
+    }
+    fEvt = (MSignalCam*)pList->FindObject(fNameSignalCam, "MSignalCam");
+    if (!fEvt)
+    {
+        *fLog << err << fNameSignalCam << " [MSignalCam] not found... aborting." << endl;
+        return kFALSE;
+    }
+
+    return kTRUE;
+}
+
+Island MImgCleanTime::CalcIsland(MSignalPix &pix1, int idx1)
+{
+    pix1.SetIdxIsland(idx1);
+
+    const Float_t tm0 = pix1.GetArrivalTime();
+
+    Island island(pix1.GetNumPhotons(), tm0);
+
+    const MGeom &gpix1 = (*fCam)[idx1];
+    for (UInt_t i=0; i<gpix1.GetNumNeighbors(); i++)
+    {
+        const int n = gpix1.GetNeighbor(i);
+
+        MSignalPix &pix2 = (*fEvt)[n];
+
+        const Int_t idx2 = pix2.GetIdxIsland();
+        if (idx2>=0)
+        {
+            if (idx1==idx2)
+                continue;
+
+            // The entries are sorted naturally, therefore
+            // there is no need to check the whole array
+            const auto it = fContacts.rbegin();
+            if (it==fContacts.rend() ||
+                (it->first!=idx1 && it->second!=idx2))
+                fContacts.emplace_back(idx1, idx2);
+
+            continue;
+        }
+
+        const Float_t tm1 = pix2.GetArrivalTime();
+        if (fabs(tm0-tm1)<fDeltaT) // FIXME: Scale with distance?
+            island += CalcIsland(pix2, idx2);
+    }
+
+    return island;
+}
+
+// --------------------------------------------------------------------------
+//
+// Cleans the image.
+//
+Int_t MImgCleanTime::Process()
+{
+    // The assumption is that all pixels contain valid data
+    const UInt_t npix = fEvt->GetNumPixels();
+    for (UInt_t i=0; i<npix; i++)
+    {
+        MSignalPix &pix = (*fEvt)[i];
+        pix.SetPixelUnused();
+        pix.SetPixelCore(kFALSE);
+        pix.SetIdxIsland(-1);
+    }
+
+    // Contains the id of the island for each pixel
+    fIslands.clear();
+    fContacts.clear();
+
+    // Start with island idx==0
+    UShort_t idx = 0;
+    for (UInt_t i=0; i<1440; i++)
+    {
+        MSignalPix &pix = (*fEvt)[i];
+
+        // The following might be much more efficient and faster
+        // if we omit small counted and sized islands already,
+        // but what is the disadvantage?
+        if (pix.GetIdxIsland()<0)
+            fIslands.emplace_back(CalcIsland(pix, idx++));
+    }
+
+    fLut.resize(fIslands.size());
+    for (UInt_t i=0; i<fLut.size(); i++)
+        fLut[i] = i;
+
+    // Unify touching islands if their arrival time ranges overlap
+    for (auto it=fContacts.begin(); it!=fContacts.end(); it++)
+    {
+        const uint16_t &idx1 = fLut[it->first];
+        const uint16_t &idx2 = fLut[it->second];
+        if (idx1==idx2)
+            continue;
+
+        // FIXME: Put a limit on count? Put a limit on size?
+        if ((fIslands[idx1].min<fIslands[idx2].min || fIslands[idx1].min>fIslands[idx2].max) &&
+            (fIslands[idx1].max<fIslands[idx2].min || fIslands[idx1].max>fIslands[idx2].max) &&
+            (fIslands[idx2].min<fIslands[idx1].min || fIslands[idx2].min>fIslands[idx1].max) &&
+            (fIslands[idx2].max<fIslands[idx1].min || fIslands[idx2].max>fIslands[idx1].max))
+            continue;
+
+        // Combine both islands
+        fIslands[idx1] += fIslands[idx2];
+
+        // Remove idx2 from the list
+        for (auto is=fLut.begin(); is!=fLut.end(); is++)
+            if (*is==idx2)
+                *is=idx1;
+
+        // Erase entry form contact list
+        fContacts.erase(it);
+
+        // Start over again
+        it = fContacts.begin();
+    }
+
+    for (UInt_t i=0; i<1440; i++)
+    {
+        MSignalPix &pix = (*fEvt)[i];
+
+        // At the end every pixel has an island assigned
+        const Short_t ii = pix.GetIdxIsland();
+
+        const Island &island = fIslands[fLut[ii]];
+
+        if (island.count>fMinCount && island.size>fMinSize)
+            pix.SetPixelUsed();
+    }
+
+    return kTRUE;
+}
+
+// --------------------------------------------------------------------------
+//
+Int_t MImgCleanTime::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
+{
+    Bool_t rc = kFALSE;
+    if (IsEnvDefined(env, prefix, "MinSize", print))
+    {
+        rc = kTRUE;
+        SetMinSize(GetEnvValue(env, prefix, "MinSize", fMinSize));
+    }
+    if (IsEnvDefined(env, prefix, "MinCount", print))
+    {
+        rc = kTRUE;
+        SetMinSize(GetEnvValue(env, prefix, "MinCount", (Int_t)fMinCount));
+    }
+    if (IsEnvDefined(env, prefix, "DeltaT", print))
+    {
+        rc = kTRUE;
+        SetMinSize(GetEnvValue(env, prefix, "DeltaT", fDeltaT));
+    }
+
+    return rc;
+}
Index: trunk/Mars/mimage/MImgCleanTime.h
===================================================================
--- trunk/Mars/mimage/MImgCleanTime.h	(revision 17832)
+++ trunk/Mars/mimage/MImgCleanTime.h	(revision 17832)
@@ -0,0 +1,78 @@
+#ifndef MARS_MImgCleanTime
+#define MARS_MImgCleanTime
+
+#include <stdint.h>
+#include <list>
+#include <vector>
+
+#ifndef MARS_MTask
+#include "MTask.h"
+#endif
+
+class MGeomCam;
+class MSignalPix;
+class MSignalCam;
+
+struct Island
+{
+    uint16_t count;
+    float size;
+    float min;
+    float max;
+
+    Island() : count(0) { }
+    Island(float sz, float tm) : count(1), size(sz), min(tm), max(tm) { }
+
+    void operator+=(const Island &i)
+    {
+        count += i.count;
+        size += i.size;
+        if (i.min<min)
+            min = i.min;
+        if (i.max>max)
+            max = i.max;
+    }
+};
+
+class MImgCleanTime : public MTask
+{
+public:
+    const MGeomCam   *fCam;  //!
+          MSignalCam *fEvt;  //!
+
+    UInt_t  fMinCount;
+    Float_t fMinSize;
+    Float_t fDeltaT;
+
+    TString fNameSignalCam;  // name of the 'MSignalCam' container
+
+    std::vector<float>    fSignal;
+    std::vector<float>    fTime;
+    std::vector<int16_t>  fIsland;
+    std::vector<Island>   fIslands;
+    std::list<std::pair<uint16_t, uint16_t>> fContacts;
+    std::vector<uint16_t> fLut;
+
+    Island CalcIsland(MSignalPix &, int);
+
+    // MParContainer
+    Int_t ReadEnv(const TEnv &env, TString prefix, Bool_t print);
+
+    Int_t PreProcess(MParList *pList);
+    Int_t Process();
+
+public:
+    MImgCleanTime(const char *name=NULL, const char *title=NULL);
+
+    //void Print(Option_t *o="") const;
+
+    void SetMinCount(UInt_t sz)  { fMinCount=sz; }
+    void SetMinSize(Float_t lvl) { fMinSize=lvl; }
+    void SetDeltaT(Float_t dt)   { fDeltaT=dt; }
+
+    void SetNameSignalCam(const char *name) { fNameSignalCam = name; }
+
+    ClassDef(MImgCleanTime, 0) // task doing the image cleaning
+}; 
+
+#endif
Index: trunk/Mars/mimage/Makefile
===================================================================
--- trunk/Mars/mimage/Makefile	(revision 17831)
+++ trunk/Mars/mimage/Makefile	(revision 17832)
@@ -27,4 +27,5 @@
 
 SRCFILES = MImgCleanStd.cc \
+           MImgCleanTime.cc \
            MImgCleanSimple.cc \
            MHillas.cc \
