RSS

Visualisasi dengan Processing

Pada post ini saya akan memperkenalkan processing. Processing adalah bahasa pemrograman yang digunakan untuk membuat visualisasi dalam bentuk gambar statis dan/atau animasi. Secara bahasa pemrograman, Processing memiliki sintaks yang mirip dengan Java.

logo

Instalasi

Masuk ke halaman Download di situs processing dan pilih file sesuai dengan sistem operasi yang Anda gunakan.

download

Ekstrak file zip ke direktori manapun yang dikehendaki.

Getting Started

Buka folder hasil ekstraksi dan jalankan processing.exe

processing

Gambar di atas adalah tampilan awal dari processing ketika baru dijalankan. Pada text editor, ketikkan kode berikut untuk menginisialisasi visualisasi baru lalu klik tombol Rum (yang gambar segitiga) atau lewat menu Sketch > Run atau dengan shortcut Ctrl+R.

void setup() {
  size(500, 400);
}

void draw() {
  background(0,0,255);
}

Seharusnya keluar window baru dengan warna latar belakang biru. Kode di atas merupakan kode paling dasar pada Processing. fungsi setup() dijalankan sekali pada waktu program mulai berjalan di awal sedangkan fungsi draw() dipanggil berulang kali dalam satu detik. Berapa kali fungsi draw() dipanggil bisa dikontrol dengan fungsi frameRate() di mana nilai standarnya adalah 60 fps.

Contoh: Bacteria random walk

Untuk contoh yang sedikit lebih rumit dibanding hanya background kosong, kita akan membuat animasi bakteri yang berjalan secara acak.
Pertama, kita buat kelas baru untuk menyimpan data posisi bakteri. Jangan lupa fungsi constructor untuk menginisialisasi posisi awal bakteri.

class Bactery {
  int x;
  int y;
  float angle;
  
  Bactery() {
    x = int(random(width));
    y = int(random(height));
    angle = 2*PI*random(1);
  }
  
  Bactery(int x, int y) {
    this.x = x;
    this.y = y;
    angle = 0;
  }
}

Kemudian kita tambahkan fungsi display() untuk menggambar bakteri, dimana kita sederhanakan bentuk bakteri menjadi sebuah segi empat.

void display() {
    stroke(0);
    fill(0);
    
    if(random(1) < 0.2)
      angle = 2*PI*random(1);
      
    int x1 = bactWidth;
    int y1 = 0;
    
    int x2 = bactWidth;
    int y2 = bactHeight;
    
    int x3 = 0;
    int y3 = bactHeight;
    
    // Apply the rotation
    int nx1 = int( x1*cos(angle) - y1*sin(angle) +x);
    int ny1 = int( x1*sin(angle) + y1*cos(angle) +y);
    
    int nx2 = int( x2*cos(angle) - y2*sin(angle) +x);
    int ny2 = int( x2*sin(angle) + y2*cos(angle) +y);
    
    int nx3 = int( x3*cos(angle) - y3*sin(angle) +x);
    int ny3 = int( x3*sin(angle) + y3*cos(angle) +y);
    
    quad(x, y, nx1, ny1, nx2, ny2, nx3, ny3);
  }

Tambahkan pula fungsi step() untuk meng-update posisi bakteri pada setiap frame.

void step() {
    int moveX = int(random(11)) - 5;
    int moveY = int(random(11)) - 5;
    
    x += moveX;
    y += moveY;
  }

Instansiasi objek bakteri di awal, kemudian kita panggil kedua fungsi diatas pada setiap frame.

void setup() {
  size(500, 400);
  
  bacteria = new Bactery[numBact];
  for(int i=0; i<numBact; i++) {
    bacteria[i] = new Bactery();
  }
}

void draw() {
  background(255,255,255);
  
  for(int i=0; i<numBact; i++) {
    bacteria[i].step();
    bacteria[i].display();
  }
}

Jangan lupa untuk menambahkan variabel-variabel global yang dipakai.

Bactery[] bacteria;
int numBact = 200;
int bactWidth = 2;
int bactHeight = 10;

Contoh tampilan ketika dijalankan: bakteri yang jumlahnya banyak menggeliat sepanjang waktu.

bakteri

Processing on the Web

dengan menggunakan processing.js, program processing Anda akan secara ajaib dan otomatis bisa ditampilkan pada halaman web dengan memanfaatkan teknologi HTML5. Cukup dengan membuat sebuah halaman html kosong, import processingjs, dan tambahkan canvas ke dalamnya.

<script src="https://raw.github.com/processing-js/processing-js/v1.4.8/processing.min.js"></script>
<canvas data-processing-sources="bacterium.pde"></canvas>

Karena wordpress.com tidak bisa pakai iframe, maka animasinya bisa dilihat pada link berikut: http://mitbal.com/bacterium.html

Seperti biasa kode lengkap bisa dilihat di repository github: https://github.com/mitbal/pro-bacterium

Demikian, semoga berguna. Sampai ketemu pada contoh-contoh visualisasi lainnya.
Salam.

 
Leave a comment

Posted by on August 8, 2014 in Programming

 

Tags: ,

Baseline Wander Removal dengan Wavelet

Pada post kali ini, kita akan melakukan proses menghilangkan baseline wander (baseline wander removal) pada sinyal EKG dengan menggunakan transformasi wavelet seperti yang ditulis oleh Sargolzaei et al pada paper dengan judul “A new robust wavelet based algorithm for baseline wandering cancellation in ECG signals“.

Latar belakang
Elektrokardiogram (EKG) adalah pembacaan sinyal elektrik jantung dengan cara menempelkan elektroda ke posisi tertentu pada tubuh dan kemudian membaca nilai perbedaan potensial listrik alias tegangan yang dihasilkan. Dari pembacaan ini kita bisa mencari tahu mengenai kondisi jantung. Akan tetapi, sinyal yang baru dibaca ini tidak lepas dari noise sehingga bisa mengganggu proses diagnosis. Sumber noise ini berasal dari berbagai macam, seperti elektroda dari elektroda itu sendiri atau jika tubuh bergerak ketika dilakukan pengukuran. Salah satu kondisi noise yang sering menyerang adalah situasi yang disebut baseline wander. Baseline wander terjadi apabila sinyal EKG tidak lurus pada sumbu x, malah naik turun. Contoh bisa dilihat di gambar 1.

bwr

Contoh sinyal yang terkena baseline wander dan hasilnya setelah dihilangkan. Gambar diambil tanpa izin dari paper yang dirujuk di atas.

Baseline wander removal (BWR) adalah salah satu tahap preprocessing pada sinyal EKG untuk menghilangkan baseline drift ini. Ada beberapa teknik yang bisa dipakai, seperti melakukan filtering. Pada post ini, kita akan mengimplementasikan salah satu teknik yang memanfaatkan transformasi wavelet. Penjelasan dasar mengenai wavelet salah satunya bisa dilihat di http://users.rowan.edu/~polikar/WAVELETS/WTtutorial.html. Kelebihan dari teknik ini adalah kita tidak perlu menentukan parameter seperti ketika menggunakan high pass filter (frequency cut-off) sehingga metode kita bekerja secara non-supervised.

Sinyal EKG yang sudah bersih dari noise semacam ini kemudian bisa digunakan untuk berbagai macam kegunaan. Untuk pembahasan mengenai kegunaan sinyal EKG untuk mengenali tipe detak arrhythmia atau diagnosis tahapan tidur, bisa merujuk ke paper ini dan ini.

Algoritma
Berikut adalah tahapan dalam algoritma ini. Pertama, kita lakukan dekomposisi kepada sinyal asli dengan transformasi wavelet. Dalam hal ini kita memilih Daubechies orde 4 sebagai fungsi basisnya. Sinyal didekomposisi menjadi bagian frekuensi rendah/aproksimasi dan frekuensi tinggi/detail. Kemudian kita hitung nilai energi pada sinyal frekuensi tinggi. Kita cari kondisi dimana nilai energi pada level dekomposisi tersebut lebih rendah dari pada nilai pada level dekomposisi sebelumnya dan sesudahnya (alias lokal minima). Setelah kita temukan level tersebut, kita rekonstruksi sinyal aproksimasi dari level ini dengan membuang nilai pada sinyal frekuensi tinggi (atau dijadikan 0 semua). Sinyal hasil rekonstruksi ini kita sebut dengan baseline. Untuk menghilangkan baseline wander pada sinyal asli, maka kita kurangkan sinyal asli dengan sinyal baseline.

level

Gambar atas: plot nilai energi pada sinyal detail pada berbagai level dekomposisi. Tanda panah menunjukkan level ketika nilainya adalah lokal minima. Gambar bawah: Sinyal asli, baseline, dan sinyal asli yang sudah dikurang baseline. Lagi-lagi diambil dari paper rujukan di atas.

 

Implementasi
Pertama, kita implementasi metode konvolusi antara dua sinyal.

def conv(x, h):
    """ Perform the convolution operation between two input signals. The output signal length
    is the sum of the lenght of both input signal minus 1."""
    length = len(x) + len(h) - 1
    y = [0]*length

    for i in xrange(len(y)):
        for j in xrange(len(h)):
            if i-j >= 0 and i-j < len(x):
                y[i] += h[j] * x[i-j]

    return y

Lalu kita implementasi metode dekomposisi wavelet dan jangan lupa deklarasi koefisien basis fungsi yang dipakai. Dalam kasus ini adalah Daubechies dengan 4 koefisien. Dekomposisi dilakukan dengan cara mengkonvolusi sinyal asli dengan koefisien low pass and high pass. Sinyal keluaran dari proses ini kemudian di-downsampling menjadi setengahnya dengan cara hanya mengambil nilai pada posisi ganjil atau genap saja. Hal ini dilakukan berulang terhadap sinyal keluaran low pass (atau disebut aproksimasi) sebanyak parameter level.

c0 = (1+sqrt(3))/(4*sqrt(2))
c1 = (3+sqrt(3))/(4*sqrt(2))
c2 = (3-sqrt(3))/(4*sqrt(2))
c3 = (1-sqrt(3))/(4*sqrt(2))

def db4_dec(x, level):
""" Perform the wavelet decomposition to signal x with Daubechies order 4 basis function as many as specified level"""

    # Decomposition coefficient for low pass and high pass
    lpk = [c0, c1, c2, c3]
    hpk = [c3, -c2, c1, -c0]

    result = [[]]*(level+1)
    x_temp = x[:]
    for i in xrange(level):
        lp = conv(x_temp, lpk)
        hp = conv(x_temp, hpk)

        # Downsample both output by half
        lp_ds=[0]*(len(lp)/2)
        hp_ds=[0]*(len(hp)/2)
        for j in xrange(len(lp_ds)):
            lp_ds[j] = lp[2*j+1]
            hp_ds[j] = hp[2*j+1]

        result[level-i] = hp_ds
        x_temp = lp_ds[:]

    result[0] = lp_ds
    return result

Fungsi rekontruksi digunakan untuk mencari baseline dari sinyal asal. Rekonstruksi bekerja dengan melakukan konvolusi dengan koefisien rekonstruksi pada kedua sinyal low pass dan high pass, melakukan upsampling dengan menyelipkan 0 di setiap nilai pada sinyal dan kemudian masing-masing posisi pada sinyal saling dijumlahkan.

def db4_rec(signals, level):
    """ Perform reconstruction from a set of decomposed low pass and high pass signals as deep as specified level"""

    # Reconstruction coefficient
    lpk = [c3, c2, c1, c0]
    hpk = [-c0, c1, -c2, c3]

    cp_sig = signals[:]
    for i in xrange(level):
        lp = cp_sig[0]
        hp = cp_sig[1]

        # Verify new length
        length = 0
        if len(lp) > len(hp):
            length = 2*len(hp)
        else:
            length = 2*len(lp)

        # Upsampling by 2
        lpu = [0]*(length+1)
        hpu = [0]*(length+1)
        index = 0
        for j in xrange(length+1):
            if j%2 != 0:
                lpu[j] = lp[index]
                hpu[j] = hp[index]
                index += 1

        # Convolve with reconstruction coefficient
        lpc = conv(lpu, lpk)
        hpc = conv(hpu, hpk)

        # Truncate the convolved output by the length of filter kernel minus 1 at both end of the signal
        lpt = lpc[3:-3]
        hpt = hpc[3:-3]

        # Add both signals
        org = [0]*len(lpt)
        for j in xrange(len(org)):
            org[j] = lpt[j] + hpt[j]

        if len(cp_sig) > 2:
            cp_sig = [org]+cp_sig[2:]
        else:
            cp_sig = [org]

    return cp_sig[0]

Method calcEnergy menghitung nilai energi dari sebuah sinyal berdasarkan definisinya yaitu jumlahan kuadrat sinyal di tiap titik

def calcEnergy(x):
    """ Calculate the energy of a signal which is the sum of square of each points in the signal."""
    total = 0
    for i in x:
        total += i*i
    return total

Kemudian method bwr berikut adalah implementasi dari algoritma yang dijabarkan di atas.

def bwr(raw):
    """ Perform the baseline wander removal process against signal raw. The output of this method is signal with correct baseline
    and its baseline """
    en0 = 0
    en1 = 0
    en2 = 0
    n = 0

    curlp = raw[:]
    num_dec = 0
    last_lp = []
    while True:
        print 'Iterasi ke' + str(num_dec+1)
        print len(curlp)

        # Decompose 1 level
        [lp, hp] = db4_dec(curlp,1)

        # Shift and calculate the energy of detail/high pass coefficient
        en0 = en1
        en1 = en2
        en2 = calcEnergy(hp)
        print en2

        # Check if we are in the local minimum of energy function of high-pass signal
        if en0 > en1 and en1 < en2:
            last_lp = curlp
            break

        curlp = lp[:]
        num_dec = num_dec+1

    # Reconstruct the baseline from this level low pass signal up to the original length
    base = last_lp[:]
    for i in xrange(num_dec):
        base = db4_rec([base,[0]*len(base)], 1)

    # Correct the original signal by subtract it with its baseline
    ecg_out = [0]*len(raw)
    for i in xrange(len(raw)):
        ecg_out[i] =  raw[i] - base[i]

    return (base, ecg_out)

Contoh
Untuk contoh kita ambil data dari situs Physionet khususnya MIT-BIH Arrhythmia database. Data diambil dari salah satu record pasien dengan kode nomor 101. Sinyal EKG diambil sepanjang 1 menit. Sinyal EKG yang diambil berasal dari lead II dan V5.

Contoh kode untuk memanggil modul dan fungsi yang sudah dibuat di atas adalah sebagai berikut

import bwr
import matplotlib.pyplot as plt

# Read input csv file from physionet
f = open('samples1.csv', 'r')
lines = f.readlines()
f.close()

# Discard the first two lines because of header. Takes either column 1 or 2 from each lines (different signal lead)
signal = [0]*(len(lines)-2)
for i in xrange(len(signal)):
	signal[i] = float(lines[i+2].split(',')[1])

# Call the BWR method
(baseline, ecg_out) = bwr.bwr(signal)

plt.subplot(2,1,1)
plt.plot(signal, 'b-')
plt.plot(baseline, 'r-')

plt.subplot(2,1,2)
plt.plot(ecg_out, 'b-')
plt.show()

Berikut contoh pertama. Garis merah pada plot merupakan baseline dari sinyal EKG.

samples1

Berikut adalah contoh kedua.

samples2

Contoh berikut diambil dari lead V5.

samples3

Kode lengkap dan sampel sinyal dapat dilihat di: https://github.com/mitbal/py-bwr

Semoga berguna. Salam.

 
2 Comments

Posted by on July 8, 2014 in Programming, Python, Research

 

Tags: , , , , ,

UPGMA

Pada post kali ini kita akan mengimplementasi algoritma UPGMA atau Unweighted Pair Group Method with Arithmetic Mean untuk melakukan clustering.

Algoritma
UPGMA bekerja dengan prinsip yang sederhana. Pada setiap iterasi, pilih pasangan point dengan point, atau point dengan cluster, atau cluster dengan cluster, yang memiliki jarak yang terpendek. Gabung kedua pasangan ini kedalam satu cluster. Hal ini dilakukan terus menerus hingga jumlah cluster berkurang menjadi jumlah yang diinginkan. Untuk menghitung jarak antar datapoint, kita bisa menggunakan berbagai kriteria jarak. Pada implementasi ini, kita menggunakan euclidean distance untuk menghitung jarak. Sedangkan untuk menghitung jarak antar cluster, kita hitung dengan cara merata-ratakan jarak antar semua pasang point dari cluster pertama ke cluster kedua, atau dengan kata lain:

\frac{1}{|A|.|B|} \sum_{x \in A} \sum_{y \in B} d(x,y)

Teknik UPGMA ini bisa digolongkan kepada teknik hierarchical clustering karena kita bisa melihat hirarki sebuah cluster yang dibentuk dari cluster-cluster lain yang lebih kecil.

Implementasi
Kita implementasikan UPGMA dalam bahasa Python. Pertama, kita butuh struktur data untuk menyimpan point yang terdapat pada sebuah cluster.

class Node:
    def __init__(self, p):
        self.points = p
        self.right = None
        self.left = None

Fungsi UPGMA menerima dua parameter. Parameter pertama adalah set yang berisi datapoints sebanyak n dengan masing-masing point memiliki dimensi d. Parameter kedua adalah jumlah cluster yang kita inginkan.

def upgma(points, k):
    """ Cluster based on distance matrix dist using Unweighted Pair Group Method with Arithmetic Mean algorithm up to k cluster"""

    # Initialize each cluster with one point
    nodes = []
    n = len(points)
    for i in xrange(n):
        node = Node([points[i]])
        nodes = nodes + [node]

    # Iterate until the number of clusters is k
    nc = n
    while nc > k:
        # Calculate the pairwise distance of each cluster, while searching for pair with least distance
        c1 = 0; c2 = 0; i1 = 0; i2 = 0;
        sdis = 9999999999
        for i in xrange(nc):
            for j in xrange(i+1, nc):
                dis = euclidistance(nodes[i], nodes[j])
                if dis < sdis:
                    sdis = dis
                    c1 = nodes[i]; c2 = nodes[j];
                    i1 = i; i2 = j;
        # Merge these two nodes into one new node
        node = Node(c1.points + c2.points)
        node.left = c1; node.right = c2;
        
        #Remove the previous nodes, and add the new node
        new_nodes = []
        for i in xrange(nc):
            if i != i1 and i != i2:
                new_nodes = new_nodes + [nodes[i]]
        new_nodes = new_nodes + [node]
        nodes = new_nodes[:]
        nc = nc - 1

    return nodes

Kemudian terakhir, kita definisikan fungsi jarak yang kita pakai. Selain jarak euclidean, kita bisa yang digunakan kriteria jarak lainnya seperti Manhattan distance atau Chebyshev distance.

import math

def euclidistance(c1, c2):
    """ Calculate the distance between two cluster """
    dist = .0
    n1 = len(c1.points)
    n2 = len(c2.points)
    for i in xrange(n1):
        for j in xrange(n2):
            p1 = c1.points[i]
            p2 = c2.points[j]
            dim = len(p1)
            d = 0
            for k in xrange(dim):
                d = d + (p1[k]-p2[k])**2
            d = math.sqrt(d)
            dist = dist + d
    dist = dist / (n1*n2)
    return dist

Contoh
Untuk contoh pertama kita pakai dataset sintesis yang dihasilkan oleh dua buah distribusi normal multidimensi.

import upgma
import random
import matplotlib.pyplot as plt
import math

# Example 1
datapoints = [(random.normalvariate(2.5, 1.0), random.normalvariate(1.5,1.0)) for i in xrange(100)] + \
				[(random.normalvariate(-1, 0.5), random.normalvariate(3,0.5)) for i in xrange(100)]

# Plot datapoints before clustering
plt.plot([x for (x,y) in datapoints], [y for (x,y) in datapoints], 'k^')
plt.show()

# Cluster the data
nodes = upgma.upgma(datapoints, 2)
plt.plot([x[0] for x in nodes[0].points], [x[1] for x in nodes[0].points], 'b*')
plt.plot([x[0] for x in nodes[1].points], [x[1] for x in nodes[1].points], 'ro')
plt.show()

dan berikut keluaran hasil clustering jika kita pilih 2 sebagai jumlah cluster.
nocluster1cluster1

Contoh kedua kita ambil dataset old faithful geyser (http://www.stat.cmu.edu/~larry/all-of-statistics/=data/faithful.dat).

f = open('faithful.dat.txt', 'r')
lines = f.readlines()
f.close()

datapoints = []
for line in lines:
	tokens = line.split()
	datapoints += [(float(tokens[1]), float(tokens[2]))]

Karena fitur kedua berbeda skalanya dengan fitur pertama (puluhan berbanding dengan satuan), kita lakukan normalisasi z-score pada tiap masing-masing fitur dengan cara mengurangi dengan mean distribusi dan kemudian dibagi dengan standar deviasi.

avg1 = sum([x for (x,y) in datapoints])
avg2 = sum([y for (x,y) in datapoints])
centered_datapoints = map(lambda (x,y): (x-avg1, y-avg2), datapoints)
std1 = math.sqrt(sum(map(lambda x: x*x, [x for (x,y) in centered_datapoints])))
std2 = math.sqrt(sum(map(lambda x: x*x, [y for (x,y) in centered_datapoints])))
normalized_datapoints = map(lambda (x,y): (x/std1, y/std2), centered_datapoints)

Hasil clustering-nya adalah sebagai berikut.

# Before clustering
plt.plot([x for (x,y) in normalized_datapoints], [y for (x,y) in normalized_datapoints], 'k^')
plt.show()

# Cluster the data
nodes = upgma.upgma(normalized_datapoints, 2)
plt.plot([x[0] for x in nodes[0].points], [x[1] for x in nodes[0].points], 'b*')
plt.plot([x[0] for x in nodes[1].points], [x[1] for x in nodes[1].points], 'ro')
plt.show()

nocluster2cluster2

Kode lengkap dapat dilihat di: https://github.com/mitbal/py-upgma

Semoga berguna. Salam.

 
Leave a comment

Posted by on June 11, 2014 in Machine Learning, Programming, Python

 

Tags: , , , ,

Pengalaman kuliah di swedia

Pada post kali ini, saya hendak membagi sedikit pengalaman saya dan hal-hal menarik yang saya temui setelah kurang lebih selama 7 bulan atau 28 purnama melanjutkan kuliah tingkat Master untuk program Machine Learning di KTH Royal Institute of Technology di Stockholm, Swedia.

Latar belakang

Semua itu bermula dan diawali dengan saya mendaftarkan diri kuliah di universitas di Swedia pada awal Januari 2013. Pendaftaran dilakukan di satu tempat terpadu, yaitu university admission (https://www.universityadmissions.se/intl/start) dengan membayar biaya pendaftaran sekitar 900 SEK. Untuk biaya kuliah dan biaya hidup, saya mendaftar ke beasiswa Swedish Institute (http://studyinsweden.se/scholarship/swedish-institute-study-scholarships/)

universityadmission

si scholarship

Setelah pengumuman penerimaan universitas lewat website, datanglah paket, kotak merah, dari KTH yang isinya kurang lebih kalendar, buku petunjuk mahasiswa baru, dan flash disk berisi video profil KTH.

kotakmerahkth.

Seminggu setelah pengumuman universitas, keluarlah pengumuman untuk beasiswa, dan Alhamdulillah nama saya keluar sebagai salah satu penerima dari Indonesia, bersama 14 teman saya lainnya.

Berangkatlah saya ke Swedia pada tanggal 15 Agustus 2013, di penghujung, akhir musim panas.

Tujuhbelasan

Karena saya berangkat sebelum tanggal 17 Agustus, maka saya merasakan tujuhbelasan di negeri orang. Melihat bendera merah putih berkibar di negeri orang adalah pengalaman yang cukup berkesan.

merahputih

Di kota Vienna ternyata ada bendera merah putih juga yang berkibar. Namun, ternyata itu adalah bendera kota Vienna itu sendiri.

benderavienna

Perkuliahan

kthdaridepan

Beban kuliah saya adalah 120 ECTS (European Credit Transfer and Accumulation System). Jika dibagi kedalam 2 tahun, maka saya harus menyelesaikan 60 credit untuk tahun pertama, 30 credit untuk semester 3, dan 30 credit sisanya untuk thesis.

Kuliah di dalam setahun dibagi menjadi 2 semester. Masing-masing semester dibagi lagi menjadi 2 period dimana masing-masing period kurang lebih berjalan selama 2 bulan. Dalam 1 period normalnya mengambil 2 mata kuliah yang masing-masing bebannya 7.5 credit walaupun hal ini bergantung dari mata kuliah dan program masing-masing.

Hal menarik lainnya adalah ujian akhir bisa berlangsung hingga 5 jam. Tak jarang mahasiswa membawa botol air minum dan makanan ringan agar bisa bertahan duduk mengerjakan soal selama itu. Selain itu ujian biasanya bisa diulang, dengan jarak sekitar 1 bulan setelah ujian sebelumnya berakhir, istilahnya reexam (walaupun saya belum pernah coba).

Yang menarik lagi, sistem perkuliahan di KTH menganut academic quarter, atau kuliah dimulai 15 menit dari waktu yang ditetapkan. Dan setiap satu jam sekali akan ada istirahat sekitar 15 menit. Hal ini sangat membantu apalagi kalau jadwal kuliahnya panjang langsung 4 jam. Bisa teler kalau tidak ada istirahat.

Perpustakaan

Setelah mendaftar ke kantor pajak Swedia (skatteverket) dan memiliki personnummer, maka kita bisa mendaftar dan meminjam buku dari perpustakaan Stockholm. Buku dapat dipinjam dari perpus manapun dan juga dapat dikembalikan ke perpus mana saja yang kita mau. Perpustakaan di Stockholm sendiri jumlahnya banyak, hampir tiap kommun memiliki perpus tersendiri. Namun yang terbesar tentunya adalah Perpus publik Stockholm atau Stockholm Stadsbiblioteket.

perpus

Kartu

Orang Swedia suka kartu. Total saya punya 13 kartu baru sejak datang ke Swedia.

kartu

Transportasi

Transportasi di Stockholm sangat bagus, dimana jumlah angkutan yang tersedia banyak dan memiliki jadwal yang tepat. Rute transportasi juga menjangkau hingga daerah-daerah terjarang di Stockholm. Namun kualitas yang bagus itu harus dibayar dengan harga tiket yang tidak murah. Satu kali naik sarana transportasi untuk zona yang sama harganya sekitar 36 SEK dan harga tiket bulanan untuk pelajar adalah 560 SEK atau hampir 1 juta rupiah.

kereta

Masjid

Ada masjid di Stockholm yang terletak di daerah Medborgarplatsen. Bisa dijangkau dengan menggunakan tunnelbana jalur hijau berhenti di Medborgarplatsen atau menggunakan bis nomor 59 arah Norra Hammarbyhamen. Khutbah jum’at biasanya menggunakan bahasa Arab, yang kemudian diterjemahkan ke bahasa Swedia.

masjid

Pos

Disini Swedia tidak ada lagi kantor pos. Sebagai gantinya, tersedialah banyak kotak surat di semua penghujung kota dimana masyarakat tinggal memasukkan surat kedalamnya yang kemudian akan diambil dan diantarkan oleh petugas setiap waktu tertentu. Perangko sendiri bisa dibeli di toko minimarket seperti Seven-Eleven dan pressbyran atau supermarket seperti ICA dan Co-op.

kotakpos

Stockholm

Kota Stockholm sendiri adalah kota yang sangat indah dan nyaman untuk dihuni. Berikut sedikit cuplikan kondisi Stockholm dari berbagai waktu dan tempat.

halloween

lampuwinter

3seasons

collage stockholm

Internet

Internetnya juga cukup kencang disini.

speedtest

Yak, demikian yang bisa saya utarakan pada post kali ini. Post berikutnya akan kembali membahas mengenai Machine Learning dan kerabatnya (kalau saya enggak malas). Untuk penutup, tinggal di luar negeri tidaklah mudah namun sangat layak untuk diperjuangkan. Hal yang diperoleh tidak hanya dalam bentuk ilmu yang didapat di kelas saja namun juga dari pengalaman bagaimana ketika kita berhadapan dan merasakan semua hal yang sebelumnya belum pernah ditemui. Hal ini bisa dalam bentuk pergaulan dengan orang-orang yang lebih beragam lagi latar belakangnya dibanding yang ditemui dari tempat asal namun juga kondisi geografis dan lingkungan yang bisa sangat berbeda dan membuat takjub walau padahal sebenarnya kita masih tinggal di planet yang sama.

Salam.

 
3 Comments

Posted by on April 8, 2014 in Other

 

Tags: , , , ,

Transformasi Gambar Buta Warna

Pada post kali ini, kita akan menyimulasikan gambar yang kira-kira dilihat oleh mereka yang memiliki kekurangan penglihatan dalam hal membedakan warna atau buta warna dengan mengikuti metode yang diajukan oleh paper dengan judul Digital Video Colourmaps for Checking the Legibility of Display by Dichromats oleh Vienot et al. Hal ini tentunya akan berguna jika kita akan mendesain website atau papan pengumuman atau poster sehingga semua karya kita bisa dinikmati oleh semua orang.

Latar belakang

Pada retina di mata, manusia memiliki 2 jenis sel, yaitu sel batang (rod cell) dan sel kerucut (cone cell). Sel batang berguna untuk mengetahui tingkat kecerahan cahaya (brightness) dan berfungsi dengan baik ketika pencahayaan kurang seperti pada malam hari. Sedangkan sel kerucut bekerja ketika terdapat pencahayaan yang cukup dan berfungsi untuk membedakan warna. Terdapat tiga jenis sel kerucut yang masing-masing memiliki tingkat kesensitifan yang berbeda terhadap panjang gelombang warna, sel kerucut merah, hijau, dan biru. Persentase komposisinya kurang lebih 65% merah, 33% hijau, dan 2% biru.

Makhluk hidup yang memiliki 3 jenis sel kerucut dengan sensitivitas berbeda disebut trichromats. Beberapa hewan karnivora seperti anjing hanya memiliki dua jenis sel kerucut, alias dichromats. Sedangkan burung dan beberapa jenis ikan memiliki 4 jenis sel kerucut yang berbeda sehingga bisa disebut tetrachromats.

Buta warna sendiri adalah kondisi ketika manusia kekurangan satu jenis sel kerucut. Buta warna diperkirakan menimpa 8% dari populasi laki-laki di seluruh dunia. Ada dua jenis buta warna yang akan disimulasikan pada post ini, protan dan deutan. Protan terjadi karena mata hanya memiliki sel kerucut hijau dan biru sedangkan Deutan terjadi ketika mata hanya memiliki sel kerucut merah dan biru.

Implementasi

Berikut kode dalam Matlab.

function [ pim, dim ] = MakeDichromatIms( im )
%This function transform the input image into two different images how they
%perceived by dichromats people (protan and deutan)

    im = double(im);

    % Normalize transform the original RGB value
    im1 = (im/255).^(2.2);
    R = im1(:, :, 1);
    G = im1(:, :, 2);
    B = im1(:, :, 3);

    % Protan transform
    pR = 0.992052*R + 0.003974;
    pG = 0.992052*G + 0.003974;
    pB = 0.992052*B + 0.003974;

    % Deutan transform
    dR = 0.957237*R + 0.0213814;
    dG = 0.957237*G + 0.0213814;
    dB = 0.957237*B + 0.0213814;

    % Transformation matrix from RGB to LMS
    M = [17.8824 43.5161 4.11935;
         3.45565 27.1554 3.86714;
         0.0299566 0.184309 1.46709];

    % Protan projection
    P = [0 2.02344 -2.52581; 0 1 0; 0 0 1];

    % Deutan projection
    D = [1 0 0; 0.494207 0 1.24827; 0 0 1];

    % Precompute the transformation matrix before loop to speed things up
    Tp = inv(M)*P*M;
    Td = inv(M)*D*M;

    % Allocate the output image
    pim = zeros(size(im));
    dim = zeros(size(im));

    % Apply the transformation for each pixel
    for ii=1:size(im, 1)
       for jj=1:size(im, 2)
           protan = Tp*([pR(ii,jj) pG(ii,jj) pB(ii,jj)]');
           deutan = Td*([dR(ii,jj) dG(ii,jj) dB(ii,jj)]');

           pim(ii, jj, 1) = protan(1); pim(ii, jj, 2) = protan(2); pim(ii, jj, 3) = protan(3);
           dim(ii, jj, 1) = deutan(1); dim(ii, jj, 2) = deutan(2); dim(ii, jj, 3) = deutan(3);
       end
    end

    % Reverse the initial transform
    pim = 255*(pim.^(1/2.2));
    dim = 255*(dim.^(1/2.2));
end

–Edit–
Berikut implementasi yang memanfaatkan perkalian matrix di Matlab sehingga waktu eksekusinya 10x lebih cepat dibanding kode di atas.

function [ pim, dim ] = MakeDichromatIms2( im )
%This function transform the input image into two different images how they
%perceived by dichromats people (protan and deutan) faster using matrix
%operation in Matlab

    im = double(im);
    
    % Normalize transform the original RGB value
    im1 = (im/255).^(2.2);
    R = im1(:, :, 1);
    G = im1(:, :, 2);
    B = im1(:, :, 3);
    
    % Protan transform
    pR = 0.992052*R + 0.003974;
    pG = 0.992052*G + 0.003974;
    pB = 0.992052*B + 0.003974;
    
    % Deutan transform
    dR = 0.957237*R + 0.0213814;
    dG = 0.957237*G + 0.0213814;
    dB = 0.957237*B + 0.0213814;
    
    % Transformation matrix from RGB to LMS
    M = [17.8824 43.5161 4.11935; 
         3.45565 27.1554 3.86714; 
         0.0299566 0.184309 1.46709];
    
    % Protan projection
    P = [0 2.02344 -2.52581; 0 1 0; 0 0 1];
    
    % Deutan projection
    D = [1 0 0; 0.494207 0 1.24827; 0 0 1];

    % Precompute the transformation matrix before loop to speed things up
    Tp = inv(M)*P*M;
    Td = inv(M)*D*M;
    
    % Apply the transformation using matrix operation
    PP = Tp * [pR(:)'; pG(:)'; pB(:)'];
    DD = Td * [dR(:)'; dG(:)'; dB(:)'];
    
    % Reverse the initial transform
    PP = 255*(PP.^(1/2.2));
    DD = 255*(DD.^(1/2.2));
    
    % Reshape the computed vector back
    pim = zeros(size(im));
    pim(:,:, 1) = reshape(PP(1, :), size(R));
    pim(:,:, 2) = reshape(PP(2, :), size(G));
    pim(:,:, 3) = reshape(PP(3, :), size(B));
    
    dim = zeros(size(im));
    dim(:,:, 1) = reshape(DD(1, :), size(R));
    dim(:,:, 2) = reshape(DD(2, :), size(G));
    dim(:,:, 3) = reshape(DD(3, :), size(B));
end

Contoh keluaran dari program.

firetruck

flowers

Semoga berguna. Salam

 
Leave a comment

Posted by on April 1, 2014 in Image, Programming

 

Tags: , , ,

Essay discovery of computer

Pada post kali ini, saya akan membagi tulisan saya dalam essay 4 halaman yang berjudul discovery of computer. Tulisan ini membahas sedikit mengenai perjalanan bagaimana komputer dahulu pertama dikonsepsikan hingga bisa direalisasikan menjadi sekarang. Tentunya tulisan ini bukan sejarah komprehensif melainkan ingin memberikan sedikit sudut pandang dengan kaitannya terhadap bagaimana science berperan dalam perkembangannya.

Salam,

essay_thumb

 
Leave a comment

Posted by on March 4, 2014 in Writing

 

Tags: ,

Menghitung jumlah kata di abstrak

Oke, venue publikasi tempat Anda akan mengirimkan paper conference atau jurnal Anda mengisyaratkan batasan maksimal kata untuk abstrak, misalnya 200 kata. Jadi, apa yang harus dilakukan untuk menghitung jumlah kata di abstrak yang sudah Anda tulis, misalkan di Latex jika Anda tidak memiliki Microsoft Word?

Untungnya, ada utilitas wordcount dari commandline Linux untuk mengerjakan fungsi tersebut

wc -w

Misalkan abstrak sudah ditulis di file dengan nama abstrak.txt maka jumlah kata bisa dihitung dengan

cat abstrak.txt | wc -w

atau

wc -w abstrak.txt

Contoh, misalkan kita punya abstrak yang isinya kurang lebih begini

Intrauterine growth restriction (IUGR) is one of many fetal abnormalities which has high contribution on maternal mortality rate and perinatal mortality rate in Indonesia. The impact of IUGR can be reduced if only the symptoms are detected earlier and the correct treatment is applied. However, fetal growth detection and monitoring process in Indonesia is obstructed as the number of physicians is very limited and USG tools are expensive. Prototype of fetal growth telehealth system was initiated to answer some of this problem. This system consists of mobile component which is developed using Android operating system and server component which is developed using Django. The main feature of this system is automatic fetal head parameter detection and its ability to operate in the limited internet access environment. Experiment result shows that the implemented system with Randomized Hough Transform (RHT) achieve delta ellipse average of 79.564, delta Head Circumference (HC) average of 1.29 cm, and delta Biparietal Diameter (BPD) average of 0.25 cm.

Maka jumlah kata yang dihitung adalah
jumlahkata

Salam. Semoga berguna.

 
Leave a comment

Posted by on February 13, 2014 in paper

 

Tags: ,

 
Follow

Get every new post delivered to your Inbox.