yoppa.org


immediate bitwave

芸大 - 情報編集(Web) 2013

Processingによるネットワーク情報のビジュアライズ 2

最終課題の提出方法

最終課題は以下の方法で制作・提出してください。

最終課題テーマ「芸大のネットワーク情報をビジュアライズ」

配布したJSONデータを利用して、芸大のネットワーク情報をビジュアライズ(可視化)してください。この授業ではProcessingを視覚化のツールとして使用しましたが、その他のツールや自分で独自にプログラミングしても構いません。ただし、最終的にWebブラウザで閲覧できる形式にしてください。

提出期限: 2013年7月31日

提出方法: 作成したプログラム一式をZip圧縮して、以下のメールアドレスに送付してください。

  • tadokoro+geidai13[at]gmail.com …※ [at]を@に変換

今回も芸大のネットワークの状況をビジュアライズ(視覚化)する手法について、サンプルをみながら解説していきます。

サンプルファイルのダウンロード

Processingのソースコードは下記のリンクからダウンロードしてください。

ネットワーク情報を、時間軸でプロット

まず初めに、これまでは取得した値をそのまま大きさや形、色にしていたものを、時間の経過による変化がわかるようプロットしてみましょう。Processingでは、draw()関数の中でbackground()を呼びだすのをやめると、過去の描画がそのまま残ります。この原理を利用して、簡単にプロットしていくことが可能です。

JSONArray values;

void setup() {

  size(800, 600);
  frameRate(30);
  values = loadJSONArray("packets.json");
  noStroke();
  background(0);
}

void draw() {
  int num = frameCount % values.size();
  JSONObject packet = values.getJSONObject(num);
  int year = packet.getInt("year"); 
  int month = packet.getInt("month"); 
  int day = packet.getInt("day"); 
  int hour = packet.getInt("hour"); 
  int min = packet.getInt("min"); 
  int InOctets = packet.getInt("InOctets");
  int OutOctets = packet.getInt("OutOctets");
  fill(0);
  rect(0, 0, width, 60);
  fill(255);
  text(year + "/" + month + "/" + day + ", " + hour + ":" + min, 20, 30);
  text("InOctets: " + InOctets + ", " + "OutOctets: " + OutOctets, 20, 50);

  float barWidth = map(num, 0, values.size(), 0, width);
  fill(127);
  noStroke();
  rect(0, 0, barWidth, 5);

  float x = map(num, 0, values.size(), 0, width);
  float iy = map(InOctets, 0, 100000000, height, 0);
  float oy = map(OutOctets, 0, 100000000, height, 0);

  fill(0, 127, 255, 127);
  ellipse(x, iy, 4, 4);

  fill(255, 127, 0, 127);
  ellipse(x, oy, 4, 4);

  if (num >= values.size()-1) {
    fill(0);
    rect(0, 0, width, height);
  }
}

geidai_net01

一つ前の時点での値を記録しておくことで、点ではなく2点間を結んだ線を描くことが可能です。これを連ねていくことで、線によるグラフになります。

JSONArray values;
float lastX, lastInY, lastOutY;

void setup() {
  size(800, 600);
  frameRate(30);
  values = loadJSONArray("packets.json");
  smooth();
  background(0);
}

void draw() {
  int num = frameCount % values.size();
  JSONObject packet = values.getJSONObject(num);
  int year = packet.getInt("year"); 
  int month = packet.getInt("month"); 
  int day = packet.getInt("day"); 
  int hour = packet.getInt("hour"); 
  int min = packet.getInt("min"); 
  int InOctets = packet.getInt("InOctets");
  int OutOctets = packet.getInt("OutOctets");

  noStroke();
  fill(0);
  rect(0, 0, width, 60);
  fill(255);
  text(year + "/" + month + "/" + day + ", " + hour + ":" + min, 20, 30);
  text("InOctets: " + InOctets + ", " + "OutOctets: " + OutOctets, 20, 50);

  float barWidth = map(num, 0, values.size(), 0, width);
  fill(127);
  noStroke();
  rect(0, 0, barWidth, 5);

  float x = map(num, 0, values.size(), 0, width);
  float iy = map(InOctets, 0, 100000000, height, 0);
  float oy = map(OutOctets, 0, 100000000, height, 0);

  if (num > 0 && num < values.size()-1) {
    stroke(0, 127, 255, 180);
    line(x, iy, lastX, lastInY);

    stroke(255, 127, 0, 180);
    line(x, oy, lastX, lastOutY);
  }

  lastX = x;
  lastInY = iy;
  lastOutY = oy;

  if (num >= values.size()-1) {
    fill(0);
    noStroke();
    rect(0, 0, width, height);
  }
}

geidai_net02

時間変化を円状に変形

では、この時間変化のプロットをすこし工夫して、円環状にデータが並んでいくようにしてみましょう。車に搭載された「タコグラフ(運行記録計)」のように、少しずつ回転させながら値をプロットしていっていると考えるとシンプルに実現可能です。

JSONArray values;

void setup() {

  size(800, 600);
  frameRate(30);
  values = loadJSONArray("packets.json");
  noStroke();
  background(0);
}

void draw() {
  int num = frameCount % values.size();
  JSONObject packet = values.getJSONObject(num);
  int year = packet.getInt("year"); 
  int month = packet.getInt("month"); 
  int day = packet.getInt("day"); 
  int hour = packet.getInt("hour"); 
  int min = packet.getInt("min"); 
  int InOctets = packet.getInt("InOctets");
  int OutOctets = packet.getInt("OutOctets");
  fill(0);
  noStroke();
  rect(0, 0, width, 60);
  fill(255);
  text(year + "/" + month + "/" + day + ", " + hour + ":" + min, 20, 30);
  text("InOctets: " + InOctets + ", " + "OutOctets: " + OutOctets, 20, 50);

  float barWidth = map(num, 0, values.size(), 0, width);
  fill(127);
  noStroke();
  rect(0, 0, barWidth, 5);

  float rot = map(num, 0, values.size(), 0, 2.0*PI);
  float iy = map(InOctets, 0, 100000000, 0, -height);
  float oy = map(OutOctets, 0, 100000000, 0, -height);

  pushMatrix();
  translate(width/2, height/2);
  rotate(rot);
  strokeWeight(0.25);
  stroke(255, 127, 31);
  line(0, 0, 0, oy);

  stroke(31, 127, 255);
  line(0, 0, 0, iy);

  popMatrix();

  if (num >= values.size()-1) {
    fill(0);
    rect(0, 0, width, height);
  }
}

geidai_net03

入力パケットと出力パケットの数を合計したものを1本の棒にして、円環状に記録していくと、さらに面白い結果になりました。

JSONArray values;

void setup() {

  size(800, 600);
  frameRate(30);
  values = loadJSONArray("packets.json");
  noStroke();
  background(0);
}

void draw() {
  int num = frameCount % values.size();
  JSONObject packet = values.getJSONObject(num);
  int year = packet.getInt("year"); 
  int month = packet.getInt("month"); 
  int day = packet.getInt("day"); 
  int hour = packet.getInt("hour"); 
  int min = packet.getInt("min"); 
  int InOctets = packet.getInt("InOctets");
  int OutOctets = packet.getInt("OutOctets");
  fill(0);
  noStroke();
  rect(0, 0, width, 60);
  fill(255);
  text(year + "/" + month + "/" + day + ", " + hour + ":" + min, 20, 30);
  text("InOctets: " + InOctets + ", " + "OutOctets: " + OutOctets, 20, 50);

  float barWidth = map(num, 0, values.size(), 0, width);
  fill(127);
  noStroke();
  rect(0, 0, barWidth, 5);

  float rot = map(num, 0, values.size(), 0, 2.0*PI);
  float iy = map(InOctets, 0, 100000000, 0, -height/2);
  float oy = map(OutOctets, 0, 100000000, 0, -height/2);

  pushMatrix();
  translate(width/2, height/2);
  rotate(rot);
  strokeWeight(0.25);
  stroke(255, 127, 31);
  line(0, 0, 0, oy);

  stroke(31, 127, 255);
  line(0, oy, 0, oy+iy);

  popMatrix();

  if (num >= values.size()-1) {
    fill(0);
    rect(0, 0, width, height);
  }
}

geidai_net04