// $id: treesum.h,v 1.15 2002/10/29 22:01:19 ewalkup Exp $

/*
Copyright 2002-2005 Mary K. Kuhner, Peter Beerli, and Joseph Felsenstein

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/

/* Authors: Peter Beerli, Mary Kuhner, Jon Yamato and Joseph Felsenstein */


#ifndef TREESUM_H
#define TREESUM_H

#include <fstream>
#include <iostream>                     // debug function include
#include <map>
#include <string>
#include <vector>

#include "vectorx.h"
#include "intervaldata.h"               // for IntervalData member
#include "stringx.h"                    // debug function include
#include "forceparam.h"                 // for STATIONARIES

// #include "tree.h" in .cpp for generalized access to trees in
//     TreeSummary::Summarize(), RecTreeSummary::Summarize, and
//     TreeSummary::SummarizeTree();

//------------------------------------------------------------------------------------

class Tree;
class ForceSummary;
class Registry;
class Summary;

//------------------------------------------------------------------------------------

typedef std::map<force_type, Summary *> Summap;
typedef std::map<force_type, Summary *>::iterator Sumiter;
typedef std::map<force_type, Summary *>::const_iterator Sumconst_iter;

//------------------------------------------------------------------------------------

struct StickSummary
{
    DoubleVec2d freqs;                  // dim by number of joints/stairs by xpart
    DoubleVec1d lengths;                // dim by number of joints/stairs
    DoubleVec2d lnfreqs;                // dim by number of joints/stairs by xpart
};

//------------------------------------------------------------------------------------

/*********************************************************************
Class TreeSummary.
Summarizes the information from a single tree or run of identical
trees for the use of the maximizer.  There is a polymorphic form of
TreeSummary for recombinant trees and there will need to be
a more drastically polymorphic form for trees with growth.

Written by Jim Sloan, revised by Mary Kuhner
   added debug printers Jon Yamato 2001/04/23
   added AdjustSummary Mary Kuhner 2001/07/05
   massively refactored Mary Kuhner 2002/04/18 (and hey, it's snowing today!)
   ChainSummary moved to own file Mary Kuhner 2002/04/19
   ChainSummary refactored out of existence by Mary again, 2004/08/01
   adding Stick summarization and struct Jon 2007/03/19
   adding EpochSummary Mary 2010/09/16
**********************************************************************/

class TreeSummary
{
  private:
    TreeSummary & operator=(const TreeSummary & src);     // undefined

  protected:

    // speed optimization caches
    Summary * m_coalsummary;
    Summary * m_migsummary;
    Summary * m_recsummary;
    Summary * m_growsummary;
    Summary * m_diseasesummary;
    Summary * m_epochsummary;
    Summary * m_divmigsummary;

    IntervalData m_intervalData;        // the actual stored stuff; we own this
    Summap       m_summaries;           // helper objects for interpreting m_intervalData
    long         m_nCopies;             // number of identical trees

    StickSummary m_stickData;           // the stored stick stuff, we own this

    void Compress();                    // reduce storage space, if possible
    void CacheSummaries();              // cache summary locations

  public:

    TreeSummary();  // used only to prototype
    TreeSummary(const TreeSummary & src);
    virtual TreeSummary * Clone() const;
    virtual              ~TreeSummary();

    virtual void Summarize(const Tree & tree);

#ifdef STATIONARIES
    virtual void DumpStationariesData(const Tree & tree, const ForceParameters & fp) const;
#endif // STATIONARIES

    void AddCopy() { ++m_nCopies; };
    long GetNCopies() const { return m_nCopies; };

    std::map<force_type, DoubleVec1d> InspectSummary() const;
    virtual void AdjustSummary(const std::map<force_type, DoubleVec1d> & counts, long region);

    Summary *      GetSummary(force_type type);
    Summary const* GetSummary(force_type type) const;
    void           AddSummary(force_type type, Summary * sum);

    // Read and instantiate TreeSummary objs
    void ReadInTreeSummary  ( std::ifstream & in );
    void ReadInSummary      ( force_type type, string & tag, std::ifstream & in );
    void ReadInIntervals    ( string & tag, std::ifstream & in );

    // Write the short summary files
    // (Writing whole intervals in tree/intervaldata.cpp)
    void WriteTreeSummary ( std::ofstream & out );
    void WriteShorts      ( std::ofstream & out, DoubleVec1d & shortpoint,
                            DoubleVec1d & shortwait, LongVec2d & shortpick ) const;

    IntervalData& GetIntervalData() { return m_intervalData; };

    // speed optimized routines which duplicate GetSummary for
    // the given force, but much more quickly.

    Summary const* GetCoalSummary() const { return m_coalsummary; };
    Summary const* GetMigSummary() const { return m_migsummary; };
    Summary const* GetDiseaseSummary() const { return m_diseasesummary; };
    Summary const* GetRecSummary() const { return m_recsummary; };
    Summary const* GetGrowSummary() const { return m_growsummary; };
    Summary const* GetEpochSummary() const { return m_epochsummary; };
    Summary const* GetDivMigSummary() const { return m_divmigsummary; };

    void SetStickSummary(const DoubleVec2d & freqs,
                         const DoubleVec1d & lengths,
                         const DoubleVec2d & lnfreqs)
    {
        m_stickData.freqs = freqs;
        m_stickData.lengths = lengths;
        m_stickData.lnfreqs = lnfreqs;
    };

    const StickSummary & GetStickSummary() const { return m_stickData; };

    // debug functions
    void PrintIntervalData() const;
    void PrintStickSummaryToFile(std::ofstream & of) const;
};

//------------------------------------------------------------------------------------

class RecTreeSummary : public TreeSummary
{
  protected:
    // more speed optimization, dim: partforce X partition X recs_in_part
    vector<vector<vector<Interval*> > > m_recsbypart;
    bool m_diseasepresent;

  public:
    RecTreeSummary();
    RecTreeSummary(const RecTreeSummary & src);
    virtual TreeSummary * Clone() const;
    virtual              ~RecTreeSummary()  {};

    virtual void Summarize(const Tree & tree);

    void AddRecToRecsByPart(const LongVec1d & membership, Interval* newrec);
    const vector<vector<vector<Interval*> > > & GetRecsByPart() const;

};

#endif // TREESUM_H

//____________________________________________________________________________________
