LATEST ENTRIES
CATEGORIES
ARCHIVES
SPONSORED LINK
MOBILE
qrcode
LINKS
PROFILE
OTHERS

09
--
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
--
>>
<<
--

Agata's Blog

MATLABやPythonとともにD3.jsを使ってデータ解析とデータビジュアライゼーションに挑戦する某エンジニアのBlog
<< 【D3.js】 フォースレイアウトの作成例 | main | 【D3.js】 リサージュ曲線 (Lissajous curve) を描画する >>
D3.js でギブス現象を見る
0
    JUGEMテーマ:JavaScript

    今回は、プルダウンメニューで選択した数値によって変化するグラフを作成します。とはいっても、ただの練習のためだけのプログラムを書いても面白くないので、フーリエ変換 (Fourier transform) のギブス現象 (Gibbs phenomenon) が発生する様子を D3.js を使って可視化してみます。

    ギブス現象というのは、周期関数のフーリエ級数において、元の周期関数の不連続点付近でフーリエ級数の m 次部分和が大きく振動する現象のことを指します。

    言葉で書いてもなかなか分かりにくい現象なので、実際の例で見てみましょう。簡単のために元信号 f(x) を次のような x = π で不連続点を持つ矩形信号とします。


    この関数をフーリエ級数展開すると、次式のようになります。

    ではいよいよ、D3.js を使ってこのフーリエ級数展開の m 次部分和を描画してみます。加えて今回は、m の数値をプルダウンメニューから選択できるようにしてみます。こうすることで、m の値を増やすと次第に不連続点 (x = π) 周辺で振動が発生するギブス現象を可視化することができます。

    サンプルページ



    まず準備として、html ファイルに以下を追加します。ここでは D3.js で描画するグラフの線として、幅2ピクセルのオレンジ色の線を指定しています。また、プルダウンメニューとして m = 1 〜 100 まで選択可能としました。
     

    <style>
      .line{
        fill: none;
        stroke: orange;
        stroke-width: 2px;
      }
    </style>

    (中略)

    <p>
    m = <select id="listbox">
      <option value="1">1</option>
      <option value="2">2</option>
      <option value="3">3</option>
      <option value="4">4</option>
      <option value="5">5</option>
      <option value="10">10</option>
      <option value="20">20</option>
      <option value="50">50</option>
      <option value="100">100</option>
    </select>
    </p>
    <svg id="MyGraph"></svg>


    ここで、対象となるプルダウンメニューを特定できるよう、id = "listbox" として ID を設定しています。

    次に、プルダウンメニューで選択された m の値を取得して、フーリエ級数展開の m 次部分和を描画する D3.js プログラムを以下に示します。44 行目でまず html 内のプルダウン要素を選択しています。そのうえで、47 行目でこのプルダウンメニュー選択の更新を検知して、グラフを更新しています。具体的には、プルダウンにより選択された m の値を 49, 59 行目で取得しています。そのうえで 56 行目以降で定義する update() 関数でフーリエ級数展開の m 次部分和を計算し、70 行目以降で定義する updateLine() 関数でグラフを更新しています。

    // X,Y軸を表示できるようにグラフの周囲にマージンを確保する
    var margin = {top: 40, right: 40, bottom: 80, left: 80};
    var width = 800 - margin.left - margin.right;
    var height = 500 - margin.top - margin.bottom;
    
    // SVGの表示領域を生成
    var svg = d3.select("#MyGraph")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform", "translate(" + margin.left + ", " + margin.top + ")");
    
    var dx = 2.0*Math.PI/800.0;
    var x = d3.range(0,2.0*Math.PI,dx);
    var y = d3.range(0,x.length);
    
    // 時間軸のスケール関数を生成
    var x_scale = d3.scale.linear()
      .domain([0, 2.0*Math.PI])
      .range([0, width]);
        
    // 縦軸のスケール関数を生成
    var y_scale = d3.scale.linear()
      .domain([-2,2])
      .range([height, 0]);  
      
    // データごとに折れ線グラフを描画するための関数
    var line = d3.svg.line()
      .x(function(d, i){ return x_scale(x[i]);})
      .y(function(d, i) { return y_scale(y[i]);})
      .interpolate("linear");
    
    var polyline = svg.append('path')
      .attr("class", "line")
      .attr('stroke', 'black')
      .attr('stroke-width', '1')
      .attr('fill', 'transparent');
    
    // 初期値として m = 1 のグラフを描画
    update(1);
    updateLine();
    
    // 対象となる html 内のプルダウン要素を選択 
    var select = document.getElementById( 'listbox' );
    
    // プルダウンメニューが更新されるとグラフを更新する
    select.onchange = function(){
      // プルダウンで選択されているoption要素を取得する
      var selectedItem = this.options[ this.selectedIndex ];
      var value = selectedItem.value;
      update(value);
      updateLine();
    }
    
    // フーリエ級数展開の m 次部分和を計算する
    function update(k){
      for (var i = 0; i < k; i++){
        for (var j = 0; j < x.length; j++){
          if (i == 0){
            y[j] = (4/Math.PI)*(1/(2*(i+1)-1))*Math.sin((2*(i+1)-1)*x[j]);
          }
          else{
            y[j] = y[j] + (4/Math.PI)*(1/(2*(i+1)-1))*Math.sin((2*(i+1)-1)*x[j]);
          }
        }
      }
    }
    
    // グラフを更新する
    function updateLine(){
      polyline
        .transition()
        .duration(300)
        .attr('d', line(y));
    }
    
    // X軸を描画
    svg.append("g")
      .attr("class", "axis")
      .attr("transform", "translate(0," + height/2 + ")")
      .call(d3.svg
        .axis()
        .scale(x_scale)
        .orient("bottom")
      );
      
    // Y軸を描画
    svg.append("g")
      .attr("class", "axis")
      .call(d3.svg
        .axis()
        .scale(y_scale)
        .orient("left")
      );
      
    

     
    このエントリーをはてなブックマークに追加
    | アニメーション | 07:51 | comments(0) | - | - |
    スポンサーリンク