この連載の第 1 回では、Processing がデータを視覚化するためのいかに強力な言語および環境であるかを具体的に紹介しました。今回の記事でも引き続き Processing の詳細を探ります。まずは Processing のユーザー対話機能を概説することから始めます。
Processing は簡単にデータを視覚化できるようにしているだけでなく、マウスおよびキーボードからのユーザー入力もサポートします。Processing がユーザー入力のサポートを可能にしている手段は、ユーザーが入力したことを Processing プログラムに通知する、一連の関数とコールバックです。
Processing には、キーが押されたこと、またはリリースされたことを Processing アプリケーションに通知するためのキーボード関数がいくつか用意されています。さらに、ユーザーが特殊文字を使用できる場合には、その入力を詳しく構文解析することも可能です。
キー押下イベントがあったことを伝えるには、keyPressed 関数を使用します。この関数をアプリケーションに定義すると、キー押下イベントが発生するたびに、この関数が呼び出されます。ユーザーが押した実際のキーを識別するには、このコールバック関数の中で key という特殊な変数を使用します。同じように、キーがリリースされた場合のイベントも keyReleased 関数を使用することで捕捉することができます。どちらの関数も同じ情報を提供しますが、アクションをトリガーするタイミングは自由に定義できるようになっています。
リスト 1 に、keyPressed 関数と keyReleased 関数を記載します。いずれの関数の中でも、プログラムがユーザーによる 2 つのタイプのキー・ストロークを解析します。2 つのタイプとは、ASCII 文字と非 ASCII 文字 (矢印キーなど) のことで、前者はコード化されませんが、後者の場合はコード化が必要です。コード化された文字に対しては、Processing は key 変数を CODED トークンに設定することによって、keyCode というもう 1 つの特殊な変数を調べるように指示します。したがって、key が CODED でなければ、key 変数にキー・ストロークが含まれるということです。一方、key が CODEDに設定されている場合は、keyCode 変数に実際の文字 (UP、DOWN、LEFT、RIGHT、ALT、CONTROL、または SHIFT) が含まれます。
リスト 1.
keyPressed および keyReleased コールバック
void keyPressed()
{
if (key == CODED) {
if (keyCode == DOWN) println("Key pressed: Down arrow");
if (keyCode == SHIFT) println("Key pressed: Shift key");
} else {
println("Key pressed: " + key );
}
}
void keyReleased()
{
if (key == CODED) {
if (keyCode == DOWN) println("Key released: Down arrow");
if (keyCode == SHIFT) println("Key released: Shift key");
} else {
println("Key released: " + key );
}
}
|
Processing 関数の中で使用できる特殊な変数には、keyPressed という変数もあります。keyPressed 関数はブール値を返して、押されているキーがあること (true)、またはどのキーも押されていないこと (false) を示します。この変数を使用することで、Processing アプリケーション内 (通常のコールバック構造の外部) で発生したキー・イベントを管理することができます。
マウス・イベントはキーボード・イベントと同様の構造に従いますが、キーボード・イベントとは異なり、発生する可能性のあるさまざまなマウス・ベースのイベントをサポートするために、複数の関数があります。マウス・イベントに定義できる基本的なコールバックは、以下の 4 つです。
mousePressedmouseReleasedmouseMovedmouseDragged
mousePressed コールバック関数は、ユーザーがマウス・ボタンを押下すると呼び出されます。どのマウス・ボタンが押下されたのかは、このコールバック関数に含まれる mouseButton 変数 (LEFT、CENTER、RIGHT) によって特定することができます。そしてマウス・ボタンがリリースされると、mouseReleased コールバック関数が呼び出されます。mousePressed と mouseReleased を組み合わせたコールバック関数 mouseClicked を使用することもできます。mouseMoved 関数は、マウス・ボタンが押下されていない状態でマウスが動かされると呼び出されます。最後の mouseDragged 関数は、マウス・ボタンが押下された状態でマウスが動かされると呼び出されます。
マウス・イベントにも、数々の特殊な変数を使用することができます。まず、mouseX および mouseY 変数にはマウスの現在の位置が取り込まれます。マウスが移動する前の位置を (前のフレームから) 取り込むには、pmouseX 変数と pmouseY 変数を使用します。また、マウス・ボタンが現在クリックされているかどうかを検出するには、Processing アプリケーション内で mouseClicked 変数を使用することができます。この変数を mouseButton と組み合わせれば、現在クリックされているボタンを特定することもできます。リスト 2 に、マウス・イベントのコールバックと特殊変数を記載します。
リスト 2. 基本的なマウス・イベント・コールバックのデモ
int curx, cury;
void setup() {
size(100, 100);
curx = cury = 0;
}
void mousePressed() {
println( "Mouse Pressed at " + mouseX + " " + mouseY );
if (mousePressed && (mouseButton == LEFT)) {
curx = mouseX;
cury = mouseY;
}
}
void mouseReleased() {
println( "Mouse Released at " + mouseX + " " + mouseY );
}
void mouseMoved() {
println( "Mouse moved, now at " + mouseX + " " + mouseY );
}
void mouseDragged() {
println( "Mouse moved from " + curx + " " + cury +
" to " + mouseX + " " + mouseY );
}
|
以上で説明したマウス・イベントとキーボード・イベントの関数が、UI を作成する際の基礎となります。オブジェクトをディスプレイ・ウィンドウに配置した後、マウス・イベント関数を使用して、マウス・ボタンが押されたかどうかを判断することができます。つまり、マウス・ボタンが押されたときに、オブジェクトの領域内にあるピクセルがマウスのカーソルであったかどうかを識別できるということです。
Processing では、オブジェクト指向プログラミング (OOP: Object-Oriented Programming) の手法を利用して、アプリケーションの開発を単純化し、さらにアプリケーションを保守しやすくすることができます。Processing 自体はオブジェクト指向ですが、オブジェクトの概念を無視したアプリケーションを開発することも可能です。けれども、OOP には情報の非表示、モジュール性、そしてカプセル化という利点があるため、OOP を使用することには重要な意味があります。
Processing は他のオブジェクト指向の言語と同じく、Class の概念を使用してオブジェクト・テンプレートを定義します。クラスから定義されたオブジェクトが保持するのは、データとそのデータに対して実行できる操作の一式です。これを説明するため、まずは単純なクラスを開発するところから始めます。その後、この例を展開させて、開発したクラスに複数のオブジェクトを組み込みます。
Processing でのクラスは、データとそのデータに適用される関数 (またはメソッド) の一式を定義します。この例で引用するデータは、2 次元空間の座標 (x、y) と直径によって、中心と大きさが指定される円のデータです。この円は、x 座標と y 座標、そして直径として 1 を指定して初期化することができますが、この場合を単に「円が指定されている」と言うことにします。円を初期化するための情報は、init 関数を使用して指定します。新たに描画される円は、前に描画された円よりも大きい円になります。直径がゼロより大きければ (円が指定されているオブジェクトであることを意味します)、その直径を増分して円のサイズを大きくします。直径を増分するのは、spread 関数です。そして最後に、show 関数が円をディスプレイ・ウィンドウに描画します。直径がゼロより大きい限り (つまり、有効な円である限り)、ellipse 関数を使用して円を作成し続け、円が特定の大きさになった時点で直径をゼロに設定し、円を取り消します。このサンプル・クラスは、リスト 3 のとおりです。
リスト 3. 新たに描画される円が前に描画された円よりも大きくなる、円 (ドロップ) のサンプル・クラス
class Drop {
int x, y; // Coordinate (center of circle)
int diameter; // Diameter of circle (unused == 0).
void init( int ix, int iy ) {
x = ix;
y = iy;
diameter = 1;
}
void spread() {
if (diameter > 0) diameter += 1;
}
void show() {
if (diameter > 0) {
ellipse( x, y, diameter, diameter );
if (diameter > 500) diameter = 0;
}
}
}
|
今度は、この Drop クラスを使用して、ユーザー入力を用いたグラフィックを作成する方法を見てみましょう。リスト 4 に、Drop クラスを使用したアプリケーションを記載します。最初のステップは、ドロップの配列 (drops という名前の配列) を作成することです。配列を作成した後には、いくつかの定義が続きます (ドロップの数と、現在対象としているドロップの (drops 配列における) インデックス)。setup 関数では、ディスプレイ・ウィンドウを作成して drops 配列を初期化します (すべての直径がゼロに設定されます。つまり円が指定されていません)。ドロップのコア機能はこのクラス自体の中に含まれるため (リスト 3 の spread 関数と show 関数を参照)、draw 関数はかなり単純な内容になっています。最後に UI 部分を追加して、ユーザーがドロップの開始位置を定義できるようにします。具体的には、mousePressed コールバック関数がマウスの現在の位置の情報を使ってドロップを初期化した後 (これで、ドロップには直径が設定され、使用されることになります)、現在対象としているドロップを表すインデックスをインクリメントするという内容です。
リスト 4. 複数のユーザー定義ドロップを作成するアプリケーション
Drop[] drops;
int numDrops = 30;
int curDrop = 0;
void setup() {
size(400, 400);
ellipseMode(CENTER);
smooth();
drops = new Drop[numDrops];
for (int i = 0 ; i < numDrops ; i++) {
drops[i] = new Drop();
drops[i].diameter = 0;
}
}
void draw() {
background(0);
for (int i = 0 ; i < numDrops ; i++) {
drops[i].spread();
drops[i].show();
}
}
void mousePressed() {
drops[curDrop].init( mouseX, mouseY );
if (++curDrop == numDrops) curDrop = 0;
}
|
図 1 に、リスト 3 とリスト 4 によるアプリケーションの出力を示します。ご覧のように、マウスが何度もクリックされたことによって、大きさの異なるドロップがいくつも描画されています。
図 1. リスト 3 および 4 によるアプリケーションのディスプレイ・ウィンドウ
Processing には、画像処理に役立つ興味深い機能が用意されています。このセクションでは、画像のフィルター、合成、そしてピクセルを使ったユーザー定義の画像処理のサポートについて詳しく説明します。
Processing は、filter 関数を介して、あらかじめ用意されている画像処理機能を提供します。この filter 関数は、フィルターのモードを直接ディスプレイ・ウィンドウに適用する関数です。リスト 5 に、フィルターを使用した単純な Processing アプリケーションを示します。図 2 に示すさまざまなタイプの出力は、このアプリケーションに関連する出力で、リスト 5 では BLUR のフィルターを適用しているだけですが、図 2 にはその他にも適用できるフィルターを指定したときの画像が (対応するコードと一緒に) 示されていることに注意してください。
filter 関数はディスプレイ・ウィンドウの表示内容に直接作用するため、この関数を使用するときに指定する必要があるのは、フィルターのモード (適用するフィルターのタイプ) と画質 (つまり、フィルターのモードに対する引数) だけです。リスト 5 は、画像を保管するためのデータ型である PImage 型の変数を宣言するところから始まっています。これに続き、setup 関数の中で特定の画像を PImage データ型の変数 (img1) にロードします。画像がロードされた時点で、画像のサイズが既知となるため、その画像のサイズを使ってウィンドウのサイズを設定します (PImage インスタンスの width および height 属性を使用)。続く draw 関数の中で、image 関数を呼び出して画像を表示します。image 関数は画像の左上隅の x 座標と y 座標を指定して、画像をディスプレイ・ウィンドウに表示するように要求します (画像の幅と高さを指定することも可能です)。そして最後に、フィルターを指定して適用するという流れです。この例では、BLUR モードを指定していますが、図 2 には他のフィルターを指定したときの画像も示してあるので、オリジナルの画像と比べてみてください。
※訳注: 上記段落の原文の最後にある「(also provided in Figure 5 below)」は、誤りであり、訳出すると読者が混乱すると思われるので訳出していません。
リスト 5. 単純なフィルター・アプリケーション
PImage img1;
void setup() {
img1 = loadImage("alaska1.png");
size(img1.width, img1.height);
smooth();
}
void draw() {
image(img1, 0, 0);
filter(BLUR, 2);
}
|
図 2 に示されているように、Processing には、画像を操作するアプリケーションで一般的に使われている画像処理の操作があらかじめ用意されていますが、ピクセル単位で画像を操作することもできます。
図 2. フィルター操作の例
上記に示されていないフィルターの種類には、以下のものがあります。
OPAQUE— アルファ・チャネルを不透明に設定します。ERODE— 指定された画質パラメーターに応じて明るい部分を縮小します。DILATE— 指定された画質パラメーターに応じて明るい部分を拡大します。
フィルターのその他のモードについては、「参考文献」セクションを参照してください。
Processing では画像を合成することができます。合成は、各画像 (または必要な場合には画像の部分的領域) のピクセルごとに行われます。この機能は、Adobe® Illustrator® や Photoshop® で使用されている機能を真似たものです。
リスト 6 に、ADD を指定して 2 つの画像を合成する操作を示します (図 3 を参照)。このリストでは、loadImage 関数によって 2 つの画像をロードした後、ADD モードを使用して img2 を img1 に合成しています。blend 関数を呼び出す場合、対象となる合成先の画像 (img1) に対して合成する画像 (img2) を最初に指定します。その後に続ける 4 つのパラメーターは、合成する画像 (img2) の x 座標、y 座標、幅、高さです。さらに、合成先の画像 (img1) の左上隅の x 座標、y 座標、幅、高さのパラメーターを続けます。そして最後に定義するのが、モード・パラメーターです。この例で要求している ADD による合成では、dest_img_pixel += src_img_pixel*factor (ただし、dest_img_pixel の値が 255 を超えた場合は、dest_img_pixel の値は 255 とする) という操作を実行しています。
リスト 6. 画像の合成
void setup() {
size(237, 178);
smooth();
}
void draw() {
PImage img1 = loadImage("alaska1.png");
PImage img2 = loadImage("alaska2.png");
img1.blend( img2, 0, 0, 237, 178, 0, 0, 237, 178, ADD );
image(img1, 0, 0);
}
|
この他にも、BLEND (dest_img_pixel の値は上限なし)、SUBTRACT、DARKEST (dest_img_pixel と src_img_pixel*factor のうち、暗い方の色を採用)、LIGHTEST (dest_img_pixel と src_img_pixel*factor のうち、明るい方の色を採用)、MULTIPLY (画像が暗くなります) をはじめ、数々の操作を行うことができます。「参考文献」セクションに合成のモードに関するリンクを記載してあります。
図 3. 合成操作の結果の画像
最後に紹介する画像処理の方法は、よりマニュアルでの操作に近い手法です。このモードでは、ピクセルごとに個別の操作をすることができます。ディスプレイ・ウィンドウは、color 型からなる 1 次元の配列で構成されているため、(リスト 7 に示されているように、background 関数を使用して) 画像を表示した後 、loadPixels 関数を使用することによって、pixels 配列に含まれるディスプレイ・ウィンドウのピクセルにアクセスすることができます。loadPixels 関数はディスプレイ・ウィンドウを pixels 配列内にロードする一方、updatePixels 関数は pixels 配列を基にディスプレイ・ウィンドウを更新します。
リスト 7. ピクセル・マップを使った画像の操作
void setup() {
size(237, 178);
smooth();
}
void draw() {
PImage img = loadImage("alaska2.png");
background(img);
loadPixels();
for (int i = 0 ; i < img.width*img.height ; i++) {
color p = pixels[i];
float r = red(p)/2;
float g = green(p);
float b = blue(p);
pixels[i] = color(r, g, b);
}
updatePixels();
}
|
ディスプレイ・ウィンドウは pixels 配列の中にありますが、これを操作するにはさまざまな手段を使うことができます。リスト 7 に示されているのは、最初に各ピクセルから color 型 (変数 p) を作成し、それを使って表示を変更する方法です。この変数は、red、green、blue 関数を使用することによって、さらに RGB それぞれの値に分解することができます。上記の例では、ディスプレイ・ウィンドウに表示された画像の赤の要素の値を半分にしてから、color 関数を使ってピクセルを再ロードしています。これは、RGB それぞれの色を取得して、ピクセルを再構成する関数です。図 4 に、リスト 7 を実行する前と実行した後の画像を示します。
図 4. pixels 配列を使用したマニュアルでの画像操作
このセクションでは、Processing (具体的には OOP (Object Oriented Programming: オブジェクト指向プログラミング)) の機能のいくつかを実演するアプリケーションを紹介します。このサンプル・アプリケーションは、数値最適化および機械学習の分野で使用されるアプリケーションです。
粒子群とは、自然から発想を得た最適化手法です。この手法では、探索空間のなかで見つかった最適解 (粒子自体の最適解と大域的最適解の両方) に従って移動する解候補 (粒子) の集団を使用します。単純ながらも、探索空間の興味深い視覚表現を提供する粒子群最適化 (PSO: Particle Swarm Optimization) は、データを視覚化するための言語 (詳細は「参考文献」を参照) で探索する際に使用するには最適な手法となります。粒子群は、2 次元空間を移動して大域的最適解を探索するからです。
PSO の Processing 実装は、2 つのクラスからなります。その 1 つは個々の粒子を実装する Particle というクラスです。Particle クラスでは、PSO に従い、各粒子はその現在の位置、現在の速度、現在の適応度、最大適応度、および粒子の最適解を維持します (リスト 8 を参照)。Particle クラスが PSO をサポートするために提供する数々のメソッドには、コンストラクター (探索空間に粒子を不規則に配置)、適応度を計算する関数 (この例に示す calculateFitness 関数では、sombrero 関数に基づいて計算を行っており、z が適応度を表しています)、update 関数 (粒子をその現在の速度ベクトルに基づいて移動するための関数)、そして show 関数 (粒子を探索空間に表示するための関数) があります。さらに、粒子の要素 (適応度、x 位置、y 位置) をユーザーに公開する 3 つのヘルパー関数もあります。
リスト 8. PSO の
Particle クラス
class Particle {
float locX, locY;
float velX = 0.0, velY = 0.0;
float fitness = 0.0;
float bestFitness = -10.0;
float pbestX = 0.0, pbestY = 0.0; // Best particle solution
float vMax = 10.0; // Max velocity
float dt = 0.1; // Used to constrain changes to each particle
Particle() {
locX = random( dimension );
locY = random( dimension );
}
void calculateFitness() {
// Clip the particles
if ((locX < 0) || (locX > dimension) ||
(locY < 0) || (locY > dimension)) fitness = 0;
else {
// Calculate fitness based on the sombrero function.
float x = locX - (dimension / 2);
float y = locY - (dimension / 2);
float r = sqrt( (x*x) + (y*y) );
fitness = (sin(r)/r);
}
// Maintain the best particle solution
if (fitness > bestFitness) {
pbestX = locX; pbestY = locY;
bestFitness = fitness;
}
}
void update( float gbestX, float gbestY, float c1, float c2 ) {
// Calculate particle.x velocity and new location
velX = velX + (c1 * random(1) * (gbestX - locX)) +
(c2 * random(1) * (pbestX - locX));
if (velX > vMax) velX = vMax;
if (velX < -vMax) velX = -vMax;
locX = locX + velX*dt;
// Calculate particle.y velocity and new location
velY = velY + (c1 * random(1) * (gbestY - locY)) +
(c2 * random(1) * (pbestY - locY));
if (velY > vMax) velY = vMax;
if (velY < -vMax) velY = -vMax;
locY = locY + velY*dt;
}
void show() {
point( (int)locX, (int)locY);
}
float pFitness() {
return fitness;
}
float xLocation() {
return locX;
}
float yLocation() {
return locY;
}
}
|
もう 1 つのクラスは、粒子群を対象とした Swarm というクラスです (リスト 9 を参照)。このクラスは、Particles の配列 (粒子群コンストラクターで作成され、初期化されたもの)、現在の大域的最適解 (x 座標と y 座標)、そして 2 つの学習因数で構成された配列を保持します。学習因数は、粒子の移動 (探索) の中心が自己最適解 (c2) または大域的最適解 (c1) のどちらに置かれているのかの評価基準となります。因数のそれぞれが、最適解が粒子に及ぼす影響を示します。
run メソッドは、PSO シミュレーションにおける 1 つのステップを実行します。まず、このメソッドは粒子群に含まれる粒子ごとの適応度を計算し、それから大域的最適解を見つけます。そしてこの情報を指定して update 関数を呼び出して粒子を移動した後、show 関数を呼び出して、粒子群に含まれる各粒子の移動結果を表示します。
リスト 9. PSO の Swarm クラス
class Swarm {
float gbestX = 0.0, gbestY = 0.0; // Global best solution
float c1 = 0.1, c2 = 2.0; // Learning factors
Particle swarm[];
Swarm() {
swarm = new Particle[numParticles];
for (int i = 0 ; i < numParticles ; i++) {
swarm[i] = new Particle();
}
}
void run() {
// Calculate each particle's fitness
for (int i = 0 ; i < numParticles ; i++) {
swarm[i].calculateFitness();
}
findGlobalBest();
// Update each particle and display it.
for (int i = 0 ; i < numParticles ; i++) {
swarm[i].update( gbestX, gbestY, c1, c2 );
swarm[i].show();
}
}
void findGlobalBest() {
float fitness = -10.0;
for (int i = 0 ; i < numParticles ; i++) {
if (swarm[i].pFitness() > fitness) {
gbestX = swarm[i].xLocation(); gbestY = swarm[i].yLocation();
fitness = swarm[i].pFitness();
}
}
}
void showGlobalBest() {
println("Best Particle Result: " + gbestX + " " + gbestY);
}
}
|
リスト 10 に記載するのは、上記で定義したクラスを使用したユーザー・アプリケーションです。このアプリケーションは、粒子の数、ディスプレイ・ウィンドウのサイズ (dimension)、そして粒子群自体など、PSO で構成可能な項目のいくつかを定義しています。setup 関数がウィンドウおよび色を準備すると、draw 関数が粒子群を呼び出して、大域的最適解を 10 回の繰り返しごとに出力します。このシミュレーションでは sombrero 関数を使って最適化を行うため、最適条件がディスプレイの中心となります。
リスト 10. PSO を駆動するアプリケーション
// Particle Swarm Optimization
int numParticles = 200;
int iteration = 0;
float dimension = 500;
Swarm mySwarm = new Swarm();
void setup() {
background(255);
fill(0);
size( int(dimension), int(dimension));
smooth();
}
void draw() {
background(255); // remove for trails
mySwarm.run();
if ((iteration++ % 10) == 0) mySwarm.showGlobalBest();
}
|
以下に記載する 2 つの図に、Processing で実行した PSO シミュレーションの出力を示します。図 5 には、PSO の時間的推移を示しています。その後の図 6 に示す PSO の軌跡が、最適条件に至るまでの粒子の経路を明らかにします。
図 5. PSO シミュレーションの時間的推移
図 6 に示す軌跡からは、粒子の経路が中央の最適解に集まってきている様子が明らかに見て取れます。一部の経路はループしていることがわかりますが、これは、粒子が自己の最適解に群がってから、大域的最適解へと移動していることを示しています。
図 6. PSO シミュレーションの軌跡
連載の第 1 回で説明したように、Processing コードは Java 言語に変換されてから実行されます。そのため、Processing アプリケーションを Java アプレットや Java アプリケーションに変換するのは簡単です。この変換を行うには、Processing 開発環境 (PDE) で「File (ファイル)」をクリックしてから、「Export (エクスポート)」をクリックしてアプレットをエクスポートするか、「Export Application (アプリケーションのエクスポート)」をクリックして Java アプリケーションをエクスポートします。すると、sketchbook ディレクトリーにコードと、この操作に関連するファイルが生成されます。リスト 11 には、エクスポートされたアプレット (applet サブディレクトリー)、エクスポートされたアプリケーション (この特定ターゲットの 3 つの application ディレクトリー)、そしてソース自体 (pso.pde) が示されています。
リスト 11. エクスポート後の Processing の sketchbook サブディレクトリー
mtj@ubuntu:~/sketchbook/pso$ ls applet application.linux application.macosx application.windows pso.pde |
applet サブディレクトリー内にオリジナルの処理ソース、変換後の Java ソース、JAR ファイル、およびサンプル index.html ファイルが置かれているので、変換結果を確認することができます。
連載 2 回目の記事では、マウスおよびキーボード・イベントというコンテキストで UI について説明した後、Processing の OOP 手法、そして数々の追加 Processing アプリケーションについて探りました。最終回となる次回の記事では、Processing の3 次元機能を取り上げ、ネットワークを使用して収集したデータを視覚化するアプリケーションを作成します。
学ぶために
- Processing の詳細、最新バージョンのダウンロード、そして興味深いサンプルとチュートリアルを見つけるには、Processing.org にアクセスしてください。独自のアプリケーションを開発したら、ぜひ OpenProcessing.org でそのアプリケーションを共有してください。
- filter 関数のモードおよび blend 関数のオプションについて読んでください。
- PSO は、粒子群を使って最適化問題を解決するという、比較的新しい最適化手法です。PSO や、シロアリ群や蟻コロニーなどの他の最適化手法について学ぶには、SwarmIntelligence.org にアクセスしてください。
- developerWorks podcasts ではソフトウェア開発者のための興味深いインタビューや議論を聞くことができます。
- developerWorks の Technical events and webcasts で最新情報を入手してください。
- Twitter で developerWorks をフォローしてください。
- 世界中で近日中に予定されている IBM オープンソース開発者を対象とした会議、見本市、ウェブキャストやその他のイベントをチェックしてください。
- オープンソース技術を使用して開発し、IBM の製品と併用するときに役立つ広範囲のハウツー情報、ツール、およびプロジェクト・アップデートについては、developerWorks Open source ゾーンを参照してください。
- 無料の developerWorks On demand demos で、IBM およびオープンソースの技術と製品機能を調べて試してみてください。
製品や技術を入手するために
- IBM ソフトウェアの試用版を使用して、次のオープンソース開発プロジェクトを革新してください。ダウンロード、あるいは DVD で入手できます。
- IBM 製品の評価版をダウンロードするか、あるいは IBM SOA Sandbox のオンライン試用版で、DB2®、Lotus®、Rational®、Tivoli®、および WebSphere® などが提供するアプリケーション開発ツールやミドルウェア製品を試してみてください。
議論するために
- developerWorks blogs から developerWorks コミュニティーに加わってください。
- developerWorks コミュニティーに参加してください。ここでは他の developerWorks ユーザーとのつながりを持てる他、開発者が主導するブログ、フォーラム、グループ、ウィキを調べることができます。

M. Tim Jones は組み込みファームウェアのアーキテクトであり、『Artificial Intelligence: A Systems Approach』、『GNU/Linux Application Programming』、『AI Application Programming』、それに『BSD Sockets Programming from a Multilanguage Perspective』の著者でもあります。技術的な経歴は静止軌道衛星用のカーネル開発から、組み込みシステム・アーキテクチャーやネットワーク・プロトコル開発まで、広範にわたっています。また、コロラド州ロングモン所在の Emulex Corp. のシニア・エンジニアでもあります。