Index: trunk/MagicSoft/Mars/mfileio/MRead.h
===================================================================
--- trunk/MagicSoft/Mars/mfileio/MRead.h	(revision 4601)
+++ trunk/MagicSoft/Mars/mfileio/MRead.h	(revision 4694)
@@ -17,6 +17,7 @@
     MRead() : fSelector(NULL) {}
 
-    virtual UInt_t GetEntries() = 0;
-    virtual Bool_t Rewind();
+    virtual UInt_t  GetEntries() = 0;
+    virtual TString GetFileName() const = 0;
+    virtual Bool_t  Rewind();
 
     void SetSelector(MFilter *f) { fSelector = f; }
Index: trunk/MagicSoft/Mars/mfileio/MReadMarsFile.cc
===================================================================
--- trunk/MagicSoft/Mars/mfileio/MReadMarsFile.cc	(revision 4601)
+++ trunk/MagicSoft/Mars/mfileio/MReadMarsFile.cc	(revision 4694)
@@ -191,5 +191,5 @@
     if (!tlist)
     {
-        *fLog << err << dbginf << "ERROR - Task List not found in Parameter List." << endl;
+        *fLog << err << dbginf << "ERROR - MTaskList not found in Parameter List." << endl;
         return kFALSE;
     }
Index: trunk/MagicSoft/Mars/mfileio/MWriteAsciiFile.cc
===================================================================
--- trunk/MagicSoft/Mars/mfileio/MWriteAsciiFile.cc	(revision 4601)
+++ trunk/MagicSoft/Mars/mfileio/MWriteAsciiFile.cc	(revision 4694)
@@ -188,5 +188,5 @@
 // a warning message is print.
 //
-Bool_t MWriteAsciiFile::CheckAndWrite() const
+Bool_t MWriteAsciiFile::CheckAndWrite()
 {
     Bool_t written = kFALSE;
Index: trunk/MagicSoft/Mars/mfileio/MWriteAsciiFile.h
===================================================================
--- trunk/MagicSoft/Mars/mfileio/MWriteAsciiFile.h	(revision 4601)
+++ trunk/MagicSoft/Mars/mfileio/MWriteAsciiFile.h	(revision 4694)
@@ -21,5 +21,5 @@
     TObjArray fAutoDel; //! List of object to be deleted in the destructor
 
-    virtual Bool_t CheckAndWrite() const;
+    virtual Bool_t CheckAndWrite();
     virtual Bool_t IsFileOpen() const;
     virtual Bool_t GetContainer(MParList *pList);
Index: trunk/MagicSoft/Mars/mfileio/MWriteFile.h
===================================================================
--- trunk/MagicSoft/Mars/mfileio/MWriteFile.h	(revision 4601)
+++ trunk/MagicSoft/Mars/mfileio/MWriteFile.h	(revision 4694)
@@ -8,12 +8,14 @@
 class MWriteFile : public MTask
 {
+protected:
+    Bool_t ReInit(MParList *pList);
+
 private:
     Int_t PreProcess(MParList *pList);
     Int_t Process();
     Int_t PostProcess();
-    Bool_t ReInit(MParList *pList);
 
     virtual Bool_t      IsFileOpen() const = 0;
-    virtual Bool_t      CheckAndWrite() const = 0;
+    virtual Bool_t      CheckAndWrite() = 0;
     virtual Bool_t      GetContainer(MParList *pList) = 0;
     virtual const char *GetFileName() const = 0;
Index: trunk/MagicSoft/Mars/mfileio/MWriteRootFile.cc
===================================================================
--- trunk/MagicSoft/Mars/mfileio/MWriteRootFile.cc	(revision 4601)
+++ trunk/MagicSoft/Mars/mfileio/MWriteRootFile.cc	(revision 4694)
@@ -18,5 +18,5 @@
 !   Author(s): Thomas Bretz, 6/2001 <mailto:tbretz@astro.uni-wuerzburg.de>
 !
-!   Copyright: MAGIC Software Development, 2000-2003
+!   Copyright: MAGIC Software Development, 2000-2004
 !
 !
@@ -24,13 +24,17 @@
 
 /////////////////////////////////////////////////////////////////////////////
-//                                                                         //
-// MWriteRootFile                                                          //
-//                                                                         //
-// This is a writer to store several containers to a root file.            //
-// The containers are added with AddContainer.                             //
-// To understand how it works, see base class MWriteFile                   //
-//                                                                         //
-// Warning: Checkout the Warning in MTaskList.                             //
-//                                                                         //
+//
+// MWriteRootFile
+//
+// This is a writer to store several containers to a root file.
+// The containers are added with AddContainer.
+// To understand how it works, see base class MWriteFile
+//
+// Warning: Look at the Warning in MTaskList.
+//
+// There is a special mode of operation which opens a new file for each new
+// file read by the reading task (opening the new file is initiated by
+// ReInit()) For more details se the corresponding constructor.
+//
 /////////////////////////////////////////////////////////////////////////////
 #include "MWriteRootFile.h"
@@ -40,8 +44,10 @@
 #include <TFile.h>
 #include <TTree.h>
+#include <TRegexp.h>
 
 #include "MLog.h"
 #include "MLogManip.h"
 
+#include "MRead.h"
 #include "MParList.h"
 
@@ -51,6 +57,25 @@
 using namespace std;
 
-static const TString gsDefName  = "MWriteRootFile";
-static const TString gsDefTitle = "Task which writes a root-output file";
+const TString MWriteRootFile::gsDefName  = "MWriteRootFile";
+const TString MWriteRootFile::gsDefTitle = "Task which writes a root-output file";
+
+void MWriteRootFile::Init(const char *name, const char *title)
+{
+    fName  = name  ? name  : gsDefName.Data();
+    fTitle = title ? title : gsDefTitle.Data();
+
+    //
+    // Set the Arrays the owner of its entries. This means, that the
+    // destructor of the arrays will delete all its entries.
+    //
+    fBranches.SetOwner();
+
+    //
+    // Believing the root user guide, TTree instanced are owned by the
+    // directory (file) in which they are. This means we don't have to
+    // care about their destruction.
+    //
+    //fTrees.SetOwner();
+}
 
 // --------------------------------------------------------------------------
@@ -61,8 +86,41 @@
 MWriteRootFile::MWriteRootFile() : fOut(NULL)
 {
-    fName  = gsDefName;
-    fTitle = gsDefTitle;
-
+    Init();
+
+    //
+    // Set the Arrays the owner of its entries. This means, that the
+    // destructor of the arrays will delete all its entries.
+    //
     fBranches.SetOwner();
+}
+
+// --------------------------------------------------------------------------
+//
+// Use this constructor to run in a special mode.
+//
+// In this mode for each input file a new output file is written. This
+// happens in ReInit.
+//
+// comp:        Compression Level (see TFile, TBranch)
+// rule:        Rule to create output file name (see GetNewFileName())
+// overwrite:   Allow newly created file to overwrite old files ("RECREATE")
+// ftitle:      File title stored in the file (see TFile)
+// name, title: Name and title of this object
+//
+MWriteRootFile::MWriteRootFile(const Int_t comp,
+                               const char *rule,
+                               const Bool_t overwrite,
+                               const char *ftitle,
+                               const char *name,
+                               const char *title) : fSplitRule(rule)
+{
+    Init(name, title);
+
+    //
+    // Open a TFile in dummy mode! This is necessary to be able to create
+    // the trees and branches, which are then (in ReInit) moved to
+    // a valid file. (Stupid workaround - but does a good job)
+    //
+    fOut = new TFile("/dev/null", overwrite?"RECREATE":"NEW", ftitle, comp);
 }
 
@@ -81,19 +139,14 @@
                                const char *title)
 {
-    fName  = name  ? name  : gsDefName.Data();
-    fTitle = title ? title : gsDefTitle.Data();
-
-    //
-    // Set the Arrays the owner of its entries. This means, that the
-    // destructor of the arrays will delete all its entries.
-    //
-    fBranches.SetOwner();
-
-    //
-    // Believing the root user guide, TTree instanced are owned by the
-    // directory (file) in which they are. This means we don't have to
-    // care about their destruction.
-    //
-    //fTrees.SetOwner();
+    Init(name, title);
+
+    //
+    // If no name is given we open the TFile in some kind of dummy mode...
+    //
+    if (!fname)
+    {
+        fOut = new TFile("/dev/null", "READ", ftitle, comp);
+        return;
+    }
 
     TString str(fname);
@@ -112,5 +165,5 @@
 // properly.
 //
-MWriteRootFile::~MWriteRootFile()
+void MWriteRootFile::Close()
 {
     //
@@ -130,4 +183,5 @@
     //
     delete fOut;
+    fOut = 0;
 
     //
@@ -139,4 +193,13 @@
 
     *fLog << inf << "Output File closed and object deleted." << endl;
+}
+
+// --------------------------------------------------------------------------
+//
+// call Close()
+//
+MWriteRootFile::~MWriteRootFile()
+{
+    Close();
 }
 
@@ -350,4 +413,13 @@
             *fLog << inf << "Branch '" << cname << "' already existing... updating." << endl;
             branch->SetAddress(entry->GetAddress());
+
+            if (!fSplitRule.IsNull())
+            {
+                *fLog << warn << endl;
+                *fLog << "WARNING:   You are updating an existing branch.  For this" << endl;
+                *fLog << "     case file-splitting mode is not allowed... disabled!" << endl;
+                *fLog << endl;
+                fSplitRule = "";
+            }
         }
         else
@@ -365,4 +437,5 @@
 
             branch = tree->Branch(branchname, cont->ClassName(), entry->GetAddress());
+
             //
             // If the branch couldn't be created we have a problem.
@@ -376,4 +449,13 @@
 
             *fLog << "done." << endl;
+
+            if (!tree->TestBit(kIsNewTree) && !fSplitRule.IsNull())
+            {
+                *fLog << warn << endl;
+                *fLog << "WARNING:   You  have  created  a new branch  in  an existing tree." << endl;
+                *fLog << "     For this case file-splitting mode is not allowed... disabled!" << endl;
+                *fLog << endl;
+                fSplitRule= "";
+            }
         }
 
@@ -384,4 +466,5 @@
         entry->SetBranch(branch);
     }
+
     return kTRUE;
 }
@@ -401,5 +484,5 @@
 // has the write flag, all containers in this tree are filled!
 //
-Bool_t MWriteRootFile::CheckAndWrite() const
+Bool_t MWriteRootFile::CheckAndWrite()
 {
     TObject *obj;
@@ -438,8 +521,9 @@
     // Loop over all tree entries
     //
-    TIter NextTree(&fTrees);
-    while ((obj=NextTree()))
-    {
-        TTree *t = (TTree*)obj;
+    const Int_t n = fTrees.GetEntriesFast();
+
+    for (int idx=0; idx<n; idx++)
+    {
+        TTree *t = (TTree*)fTrees[idx];
 
         //
@@ -455,4 +539,5 @@
         //
         t->ResetBit(kFillTree);
+
         if (!t->Fill())
         {
@@ -461,4 +546,20 @@
         }
     }
+
+    //
+    // For more information see TTree:ChangeFile()
+    //
+    TTree *t0 = (TTree*)fTrees[0];
+    if (!t0 || fOut==t0->GetCurrentFile())
+        return kTRUE;
+
+    *fLog << warn << endl;
+    *fLog << "WARNING - MWriteRootFile:   Root's  TTree/TFile   has  opened   a  new  file" << endl;
+    *fLog << "  automatically.  You can change this behaviour using TTree::SetMaxTreeSize." << endl;
+    *fLog << "  You won't be able to read splitted  files  correctly with MReadMarsFile if" << endl;
+    *fLog << "  they have more than one entry in 'RunHeaders' or you try to read more than" << endl;
+    *fLog << "  one of such sequences at once." << endl;
+    *fLog << endl;
+
     return kTRUE;
 }
@@ -466,9 +567,198 @@
 // --------------------------------------------------------------------------
 //
+// Open a new file with the ame fname. Move all trees and branches from the
+// old file to the new file.
+//
+Bool_t MWriteRootFile::ChangeFile(const char *fname)
+{
+    //
+    // The following code is more or less a copy of TTree::ChangeFile
+    //
+    const Int_t   compr = fOut->GetCompressionLevel();
+    const TString title = fOut->GetTitle();
+
+    *fLog << inf << "MWriteRootFile - Open new file " << fname << " (Title=" << title << ", Compression=" << compr << ")" << endl;
+
+    // Open new file with old setup
+    TFile *newfile = TFile::Open(fname, "RECREATE", title, compr);
+    if (!newfile)
+    {
+        *fLog << err << "ERROR - Cannot open new file " << fname << endl;
+        return kFALSE;
+    }
+
+    // Print statistics of old file
+    const TString n = GetFileName();
+    if (!n.IsNull() && n!=TString("/dev/null"))
+        Print();
+
+    if (fOut->IsOpen())
+        fOut->Write();
+
+    // Move all trees from the old file to the new file
+    TObject *obj=0;
+    while ((obj = fOut->GetList()->First()))
+    {
+        // Remove obj from old file (otherwise deleting
+        // the old file will delete the objs)
+        fOut->GetList()->Remove(obj);
+
+        // If this is not a tree do nothing.
+        if (!obj->InheritsFrom("TTree"))
+            continue;
+
+        // process all trees in the old file
+        TTree *t = (TTree*)obj;
+
+        // reset and move to new file (this is done implicitly for all branches)
+        t->Reset();
+        t->SetDirectory(newfile);
+    }
+
+    // Close/delete the old file (keys already written above)
+    delete fOut;
+
+    // Replace current with new file
+    fOut = newfile;
+
+    // Change current directory to new file
+    gFile = fOut;
+
+    return kTRUE;
+}
+
+// --------------------------------------------------------------------------
+//
+// A rule looks like:
+//   "outputpath{s/source/destination}"
+//
+// outpath:                the output path into which the files are written
+// {s/source/destination}  a substitution rule for the filename
+//   while source can be a regular expression everything which matches this
+//   regular expression (see TRegexp) will be replaced by destination.
+//   Warning: The algorithm is recursive you may create endless loops!
+//
+// Example:
+//   inputfile: /data/MAGIC/Period016/rootdata/20040621_23210_D_Mkn421_E.root
+//   rule:      /outpath/{s/_D_/_Y_}
+//   outfile:   /outpath/20040621_23210_Y_Mkn421_E.root
+//
+// If you need more difficult rules please send me an eMail...
+//
+TString MWriteRootFile::GetNewFileName(const char *inname) const
+{
+    // Remove the path from the filename
+    TString fname(inname);
+    if (fname.Last('/')>=0)
+        fname.Remove(0, fname.Last('/')+1);
+
+    // Make a copy of the rule
+    TString rule(fSplitRule);
+
+    // [characte class], ^ do not, [^{}] do not match { and }, [^{}]+ match at least not one { or }
+    const TRegexp subst0("{s/[^{}/]+/[^{}/]+}");
+
+    TString path;
+    Bool_t first = kTRUE;
+
+    Ssiz_t idx=0;
+    while (1)
+    {
+        // Find a substitution exprsssion
+        Ssiz_t len = 0;
+        idx = subst0.Index(rule, &len);
+        if (idx<0)
+            break;
+
+        // If the first substitution expression is found in the rule
+        // determin the path from everything before
+        if (first)
+        {
+            path=rule(0, idx);
+            first = kFALSE;
+        }
+
+        // Extract a substitution expression
+        TString expr = rule(idx, len);
+        rule.Remove(idx, len);
+
+        expr.Remove(0,3);
+        expr.Remove(expr.Length()-1);
+
+        // In all cases this is well defined (see Regexp)
+        const Ssiz_t pos = expr.First('/');
+
+        // Split substitution rule into source and destination
+        const TString src  = expr(0, pos);
+        const TString dest = expr(pos+1, expr.Length());
+
+        // Replace source by destination
+        const TRegexp regexp(src);
+        while (1)
+        {
+            TString sub = fname(idx+dest.Length());
+            idx = regexp.Index(fname, &len);
+            if (idx<0)
+                break;
+
+            fname.Replace(idx, len, dest);
+        }
+    }
+
+    // Check if we have a trailing '/'
+    if (!path.IsNull() && path[path.Length()-1]!='/')
+        path.Append("/");
+
+    // Create full qualified pathname
+    path += fname;
+    return path;
+}
+
+// --------------------------------------------------------------------------
+//
+// ReInit. If file splitting is not allowed call MWriteFile::ReInit.
+//
+// In other cases get MRead from the TaskList (splitting is switched of if
+// this is impossible).
+//
+// Convert the input- into a new output file-name.
+//
+// Open a new file, change all trees to the new file (calling ChangeFile()),
+// and close the old one.
+//
+// Call MWriteFile::ReInit()
+//
+Bool_t MWriteRootFile::ReInit(MParList *pList)
+{
+    if (fSplitRule.IsNull())
+        return MWriteFile::ReInit(pList);
+
+    MRead *read = (MRead*)pList->FindTask("MRead");
+    if (!read)
+    {
+        *fLog << warn;
+        *fLog << "WARNING: No Task 'MRead' found in the tasklist.  This task is" << endl;
+        *fLog << "  necessary  to  get  the filename.  Without  a filename file" << endl;
+        *fLog << "  file splitting is not allowed... disabled!" << endl;
+        *fLog << endl;
+        fSplitRule = "";
+        return kTRUE;
+    }
+
+    const TString fname = GetNewFileName(read->GetFileName());
+    if (!ChangeFile(fname))
+        return kFALSE;
+
+    return MWriteFile::ReInit(pList);
+}
+
+// --------------------------------------------------------------------------
+//
 // return open state of the root file.
 //
 Bool_t MWriteRootFile::IsFileOpen() const
 {
-    return fOut->IsOpen();
+    const char *n = fOut->GetName();
+    return n==0 || *n==0 ? kTRUE : fOut->IsOpen();
 }
 
@@ -479,5 +769,6 @@
 const char *MWriteRootFile::GetFileName() const
 {
-    return fOut->GetName();
+    const char *n = fOut->GetName();
+    return n==0 || *n==0 ? "<dummy>" : n;
 }
 
Index: trunk/MagicSoft/Mars/mfileio/MWriteRootFile.h
===================================================================
--- trunk/MagicSoft/Mars/mfileio/MWriteRootFile.h	(revision 4601)
+++ trunk/MagicSoft/Mars/mfileio/MWriteRootFile.h	(revision 4694)
@@ -7,4 +7,7 @@
 #ifndef ROOT_TObjArray
 #include <TObjArray.h>
+#endif
+#ifndef ROOT_TArrayL
+#include <TArrayL.h>
 #endif
 
@@ -68,21 +71,17 @@
 {
 private:
-    TFile *fOut;
+    static const TString gsDefName;
+    static const TString gsDefTitle;
 
-    TObjArray fBranches;
-    TObjArray fTrees;     //!
+    TFile *fOut;             // Current file
 
-    //UInt_t fNumEvents; //! Number of events written in a run
+    TObjArray fBranches;     // List of Branch setup (MRootFileBranch)
+    TObjArray fTrees;        //! List of trees
 
-    Bool_t      CheckAndWrite() const;
-    Bool_t      IsFileOpen() const;
-    Bool_t      GetContainer(MParList *pList);
-    const char *GetFileName() const;
-
-    void StreamPrimitive(ofstream &out) const;
-    //Bool_t ReInit(MParList *pList);
+    TString fSplitRule;      // file splitting allowed if rule existing (done in ReInit)
 
     enum {
         kFillTree  = BIT(14),
+        // Be carefull these bits are already in use!
         // TBranch::kAutoDelete = BIT(15)
         // TBranchElement::kDeleteObject = BIT(16)
@@ -90,18 +89,40 @@
     };
 
+    // File handling
+    void    Close();
+    TString GetNewFileName(const char *fname) const;
+    Bool_t  ChangeFile(const char *fname);
+
+    // MWrite
+    Bool_t      CheckAndWrite();
+    Bool_t      IsFileOpen() const;
+    Bool_t      GetContainer(MParList *pList);
+    const char *GetFileName() const;
+
+    // MTask
+    Bool_t ReInit(MParList *pList);
+    void   StreamPrimitive(ofstream &out) const;
+
+    // Constructor
+    void Init(const char *name=0, const char *title=0);
+
 public:
     MWriteRootFile();
+    MWriteRootFile(const Int_t comp,
+                   const char *rule,
+                   const Bool_t overwrite=kTRUE,
+                   const char *ftitle="Untitled",
+                   const char *name=NULL,
+                   const char *title=NULL);
     MWriteRootFile(const char *fname,
                    const Option_t *opt="RECREATE",
                    const char *ftitle="Untitled",
-                   const Int_t comp=9,
+                   const Int_t comp=2,
                    const char *name=NULL,
                    const char *title=NULL);
     ~MWriteRootFile();
 
-
     void AddContainer(const char *cname,   const char *tname=NULL, Bool_t must=kTRUE);
     void AddContainer(MParContainer *cont, const char *tname=NULL, Bool_t must=kTRUE);
-
 
     void Print(Option_t *t=NULL) const;
