2013-06-14 2 views
5

私はTeafiles.netと呼ばれるオープンソースの.Netライブラリに出くわしました.Thafiles.netは時系列のストレージと検索を処理します。独自の製品である茶葉は、そのような時系列をグラフ化することができます。私は茶店の製品がオープンソースであろうと有料であろうと、ソースコードとして利用可能かどうか疑問です。私は、現在のチャートビューに表示されるデータポイントのみを読み込むことができ、同様のソリューションを実装する方法について興味を持っています。Teafilesとteahouse charting libraryのアーキテクチャは?

私は似たような実装しているよと、誰もが同様の技術に遭遇または有料茶屋ライセンスは、ソースコードで使用可能であるかどうかを知っているかどうかを疑問に思いました。

答えて

3

私は現在、ZedGraphライブラリに基づいて傾向分析ソリューションを開発しています、と私は、データベースから来る大量のデータをキャッシュするTeaFilesを使用しています。

私は技術の種類は、茶屋ソリューション後ろに立って正確に何を知りません。しかし、私はTeaFileから来る大量のデータから2つの日付の間にあるポイントのセットを表示するための手法も使用しました。

ZedGraphライブラリは、の自動を実行するオブジェクトを持っています。 SetBoundsメソッドを使用して、表示する日付の範囲と表示するポイントの最大量を選択できます。通常は、ビューの実際の幅に対応します。

FilteredPointList(original source code)は、XYデータを含む二重の二つの配列を使用します。このクラスをTeaFilePointListに適合させることは、TをDateTimeとdoubleプロパティを含む構造体とみなして、TeaFileオブジェクトで配列を置き換えることによって簡単に行うことができます。

実装は最適ではありませんが、私はこの方法で始めました。私はTeaFileのMemoryMappedFile機能を含むようにこのコードを後で更新するかもしれません。この方法ではるかに速くなります。

public class TeaFilePointList : IPointList 
{ 
    TeaFile<point> tf; 

    private int _maxPts = -1; 
    private int _minBoundIndex = -1; 
    private int _maxBoundIndex = -1; 

    struct point 
    { 
     public TeaTime.Time x; 
     public double y; 
    } 

    public TeaFilePointList(DateTime[] x, double[] y) 
    { 
     tf = TeaFile<point>.Create(Path.GetRandomFileName() + ".tea"); 
     for (var i = 0; i < x.Length; i++) 
      tf.Write(new point() { x = x[i], y = y[i] }); 
    } 

    public void SetBounds(double min, double max, int maxPts) 
    { 
     _maxPts = maxPts; 

     // find the index of the start and end of the bounded range 

     var xmin = (DateTime)new XDate(min); 
     var xmax = (DateTime)new XDate(max); 

     int first = tf.BinarySearch(xmin, item => (DateTime)item.x); 
     int last = tf.BinarySearch(xmax, item => (DateTime)item.x); 

     // Make sure the bounded indices are legitimate 
     // if BinarySearch() doesn't find the value, it returns the bitwise 
     // complement of the index of the 1st element larger than the sought value 

     if (first < 0) 
     { 
      if (first == -1) 
       first = 0; 
      else 
       first = ~(first + 1); 
     } 

     if (last < 0) 
      last = ~last; 

     _minBoundIndex = first; 
     _maxBoundIndex = last; 
    } 

    public int Count 
    { 
     get 
     { 
      int arraySize = (int)tf.Count; 

      // Is the filter active? 
      if (_minBoundIndex >= 0 && _maxBoundIndex >= 0 && _maxPts > 0) 
      { 
       // get the number of points within the filter bounds 
       int boundSize = _maxBoundIndex - _minBoundIndex + 1; 

       // limit the point count to the filter bounds 
       if (boundSize < arraySize) 
        arraySize = boundSize; 

       // limit the point count to the declared max points 
       if (arraySize > _maxPts) 
        arraySize = _maxPts; 
      } 

      return arraySize; 
     } 
    } 

    public PointPair this[int index] 
    { 
     get 
     { 
      if (_minBoundIndex >= 0 && _maxBoundIndex >= 0 && _maxPts >= 0) 
      { 
       // get number of points in bounded range 
       int nPts = _maxBoundIndex - _minBoundIndex + 1; 

       if (nPts > _maxPts) 
       { 
        // if we're skipping points, then calculate the new index 
        index = _minBoundIndex + (int)((double)index * (double)nPts/(double)_maxPts); 
       } 
       else 
       { 
        // otherwise, index is just offset by the start of the bounded range 
        index += _minBoundIndex; 
       } 
      } 

      double xVal, yVal; 
      if (index >= 0 && index < tf.Count) 
       xVal = new XDate(tf.Items[index].x); 
      else 
       xVal = PointPair.Missing; 

      if (index >= 0 && index < tf.Count) 
       yVal = tf.Items[index].y; 
      else 
       yVal = PointPair.Missing; 

      return new PointPair(xVal, yVal, PointPair.Missing, null); 
     } 
    } 

    public object Clone() 
    { 
     throw new NotImplementedException(); // I'm lazy... 
    } 

    public void Close() 
    { 
     tf.Close(); 
     tf.Dispose(); 
     File.Delete(tf.Name); 
    } 
} 

最も困難な部分は、DateTimeを使用してレコードをすばやく検索するためのTeaFileのBinarySearchを実装することでした。私は逆コンパイラを使用してArray.BinarySearchの実装を見て、私は以下の拡張子を書いた:ZedGraphがニーズに合わない場合は

public static int BinarySearch<T, U>(this TeaFile<T> tf, U target, Func<T, U> indexer) where T : struct 
{ 
    var lo = 0; 
    var hi = (int)tf.Count - 1; 
    var comp = Comparer<U>.Default; 

    while(lo <= hi) 
    { 
     var median = lo + (hi - lo >> 1); 
     var num = comp.Compare(indexer(tf.Items[median]), target); 
     if (num == 0) 
      return median; 
     if (num < 0) 
      lo = median + 1; 
     else 
      hi = median - 1; 
    } 

    return ~lo; 
} 

を、少なくとも、あなたのアイデアを得ました。 FilteredPointListクラスで使用されるデシメーションアルゴリズムはかなり優れており、ニーズに合わせて別の方法で調整できます。

+3

Laurentありがとう、私は似たようなソリューションで終わった。 TeaHouse製品の一部としてソースコードが利用できないということは、私には間に合わなかった。私は自分のバイナリファイル構造を使用して終了し、それをプロのチャートソリューション(SciChart)に供給するようにしました。そのようにして私はほとんどのソースコードを管理しています。 –

関連する問題