In Japanese

また、run()で実行したときのログとりなのですが、libecsのなかに、 Loggerクラスなどそれらしきクラスがあることを確認しており、 Pythonスクリプトで書いたときと似た感覚でログを採取することが できるのだろうと考えていますが、それのクラスをどのように使うと ログが採取できるのかがよく分かっていません。libemc, libecsでの ロガーの使い方について教えていただくことはできますか?

上記に関してですが、いろいろな方法があります。 libemc を介してシミュレーションを実行する場合でしたら、 libemc の Simulator クラスの API を使うのがもっとも適切な方法と思われます。

  1. libemc::Simulator::createLogger() でログを取りたいプロパティを指示する。
  2. libemc::Simulator::setLoggerPolicy() で必要があれば、ロギングの際のポリシーを設定する。
    • ポリシーとは:
      • ロギング中にディスク領域を使い果たしてしまったときにどのような行動を取るか
      • ログの最大サイズ
      • ログを行う最小のステップ幅
      • ログを行う最小の時間幅 を指定するものです。
  3. シミュレーションを実行する。
  4. libemc::Simulator::getLogger() でログのデータを取得する。戻り値は boost::shared_ptr<libecs::DataPointVector>。

以下 libecs::DataPointVector の説明です。

  • DataPointVector は DataPoint もしくは LongDataPoint のシーケンスを表現しています。LongDataPoint には DataPoint の情報に加え、その時点での最小値、最大値、平均値が格納されています (これは設計上問題視されており、次期 E-Cell で解消されるそうです)。どちらが使われるかは、ログ取得にどの関数を用いたかによって異なります (これも設計上ひどいです。申し訳ありません…)。
  • DataPoint を格納するのか、LongDataPoint を格納するのかはコンストラクタのパラメータにより動的に決定されます。
  • どちらが格納されているのかは、!DataPointVector::getElementSize() で知ることができます。
    • 戻り値が sizeof(DataPoint) であれば DataPoint、sizeofLongDataPoint) であれば LongDataPoint となります。
    • !DataPointVector::getPointSize() という関数があり、これを使うこともできますが、全くおすすめできません。
  • DataPoint が格納されている DataPointVector から値を取り出すには !DataPointVector::asShort(size_t pos)で、LongDataPoint の場合は、!DataPointVector::asLong(size_t pos) を用います。
    • short だの long だのという名前がついていますが、これは C++ の同名の型とはまったく関係ありません。
    • また、引数の型が DataPointVectorIterator となっていますが、これはイテレータでもなんでもなく、ただの size_t 型です。(落胆しないでください。)
  • 以下コード例です。
    #include <iostream>
    #include <libecs/DataPoint.hpp>
    #include <libecs/DataPointVector.hpp>
    using namespace libecs;
    
    void print_log(DataPointVectorSharedPtr dpv)
    {
        if (dpv->getElementSize() == sizeof(DataPoint)) {
            for (DataPointVectorIterator i = dpv->begin(); i < dpv->end(); ++i) {
                const DataPoint& dp = dpv->asShort(i);
                std::cout << "time=" << dp.getTime() << ", value=" << dp.getValue()
                          << std::endl;
            }
        } else if (dpv->getElementSize() == sizeof(LongDataPoint)) {
            for (DataPointVectorIterator i = dpv->begin(); i < dpv->end(); ++i) {
                const LongDataPoint& dp = dpv->asLong(i);
                std::cout << "time=" << dp.getTime() << ", value=" << dp.getValue()
                          << ", min=" << dp.getMin() << ", max=" << dp.getMax()
                          << ", avg=" << dp.getAvg() << std::endl;
            }
        } else {
            std::cout << "Something went wrong! Please report bugs at http://sf.net/projects/ecell . Thank you for your cooperation." << std::endl;
        }
    }