28 Mart 2018 Çarşamba

3 - Açık Cezeri Kütüphanesi (tek boyutlu sinyaller nasıl üretilir)

    Bu yazımızda Açık Cezeri Kütüphanesi (OCL) kullanılarak, tek boyutlu sinyallerin üretilmesi ve onlar üzerinde geçekleştirilen sinyal işleme uygulamalarından bahsedeceğiz. Eğer 1. ve 2. derslerimizde önerilenleri tamamıyla uygulamış iseniz bugünkü yazımızda kodlayacağımız komutlar sorunsuz bir şekilde çalışacaktır.

    OCL'de tek boyutlu bir sinyal (1 boyutlu dizi, one dimensional array) üretmenin birden fazla yolu bulunmaktadır. Geleneksel olarak, Java dilinde bir boyutlu dizi:

double[] dizi=new double[n];  n sıfırdan farklı tamsayı

şeklinde üretilir. Varsayılan olarak dizi değişkeninin tüm elemanlarına sıfır değeri atanmaktadır. Bir dizideki elemanları 0 değil de istediğimiz bir sayı ile mesela 1 ile doldurmak istersek döngü kullanmamız gerekir. n=100 olduğunu kabul edersek mesela:

for (int i=0;i<100;i++){
   dizi[i]=1;
}

Diğer taraftan Matlab ve Python gibi dillerde bir boyutlu dizi yapmak için

Matlab  ==>  dizi=ones(100,1);
Python  ==>  import numpy as np
                      dizi=np.ones(100)

dememiz kâfidir. Görüldüğü gibi dilin dahili yapısında vektörizasyon kabiliyeti bulunmaktadır ve bu yüzden kullanıcı for döngüleriyle uğraşmadan doğrudan problemin çözümü üzerine odaklanabilmektedir. Java 8, 9 ve 10 da yapılan bir dizi iyileştirmeler özellikle de stream apisi Java kod geliştiricilerine kod tasarrufu sağlayarak ekstra kolaylıklar sağlamaktadır. Ancak Matlab, R ve Python dilleri geliştirilme süreçlerinde vektörizasyon temelinde tasarlandıkları için Java'da söz konusu işlemleri yapabilmek adına üçüncü parti kütüphaneleri geliştirilmiştir. Bu bağlamda java tabanlı geliştirilen matrix kütüphanelerine örnek olarak JAMA, JBLAS, COMMONS MATH, COLT ve EJML gösterilebilir. Her birinin kendi ekseninde üstünlükleri zayıflıkları mevcut olmakla birlikte, kullanıcı ve geliştirici perspektifinden olaya bakacak olursak ilgili apileri öğrenmek ve uzmanlaşmanın maliyetinin yüksek olduğu görülecektir. OCL de aynen zikredilen kütüphaneler gibi Java dilinde geliştirilen alana has bir dil olarak yorumlanabilir ve önceki api ler gibi matris tabanlı işlemleri kolaylaştırmak adına geliştirilmiştir. OCL'de kullanılan metod isimleri genelde Matlab'de aşina olduğumuz isimlere benzetilmeye çalışmakla birlikte yüzde yüz aynı yapıda değildir. Örneğin 100 elemanlı ve değerleri bir olan bir diziyi OCL'de yapmanız için



main metodunun veya main metodundan çağrılan başka bir metodun içerisinde CMatrix sınıfından bir nesne yapmanız gerekmektedir. CMatrix sınıfının constructor metodları bilerek private tanımlanmıştır. Bunun sebebi olarak üretilecek nesne üzerinde daha fazla hakimiyet kurma isteği ve çeşitli güvenlik nedenleri sayılabilir. Yani daha açık söylemek gerekirse,

CMatrix cm=new CMatrix();

geleneksel nesne üretme tekniği çalışmamaktadır. Bunun yerine CMatrix sınıfında public static erişim belirleyicisi özelliğine sahip getInstance  (yani sınıfın bir örneğini ver veya yap) metodları overload edilmiştir. Yukarıdaki kod bloğunda görüldüğü gibi CMatrix sınıfının altı kırmızı ile çizilmiştir, bunun nedeni properties den add jar ile eklediğimiz OCL kütüphanelerini henüz import etmediğimizden kaynaklanmaktadır. Bunun için sol tarafta beliren sarı baloncuğa tıklayıp ilgili sınıfı (yani CMatrix) "add import cezeri.matrix.CMatrix" seçerek kodumuza dâhil ediyoruz.


CMatrix sınıfı fluent interface (akıcı arayüz) veya method chaining (metot zincirlenmesi) olarak ta bilinen bir tasarım kipi kullandığı için getInstance() metodundan sonra "." bırakıp ones metodunu çağırıyoruz. ones metodunun kullanımı Matlab'e benzemektedir. ones metodunun tek parametre versiyonunu kullandığınızda örneğin .ones(100) deseydik 100x100 2 boyutlu bir matris üretecek idi. Bunun yerine .ones(100,1) kullandık. Bu komut ile OCL'nin 100 satır ve bir sütun dan meydana gelen bir matris üretmesini istiyoruz. buna aynı zamanda column matrix yani sütun matrisi de denmektedir. Satır matrisi üretmek istiyorsak ".ones(1,100)" demeli idik. Ayrıca üretilen matrisin içeriğini output penceresinde görüntülemek için ".println()" komutunu çağırdık. Sonuç aşağıdaki gibi olacaktır.



Tüm elemanları "0" olan bir matris yapmak için de ".zeros" komutu kullanılır. Elemanlarının değeri sıfır olan matris üretmenin diğer bir yolu getInstance metodunu kullanmaktır. Bunun için

CMatrix cm=CMatrix.getInstance(100,1);  kullanılabilirdi.

SORU: 100 elemanlı, değerleri 3.14 yani PI sayısı olan bir sütun matrisini OCL'de gerçekleyiniz.

CEVAP:

CMatrix cm=CMatrix.getInstance(100,1,Math.PI);

veya

CMatrix cm=CMatrix.getInstance(100,1).addScalar(Math.PI);

veya

CMatrix cm=CMatrix.getInstance().zeros(100,1).addScalar(Math.PI);

veya

CMatrix cm=CMatrix.getInstance().ones(100,1).multiplyScalar(Math.PI);

aynı sonucu geri döndürecektir.

Yukarıdaki örnekte bir matrise herhangi bir sayıyı eklemek istersek "addScalar" komutunu, sayıyla çarpmak içinse "multiplyScalar" metodunu kullanabiliriz.

Bazen de dizinin elemanlarını bir seri gibi doldurmak isteyebiliriz. Mesela ardışık sayılardan meydana gelen bir sütun matrisi yapmak için

CMatrix cm=CMatrix.getInstance().vector(0,1,255);

yukarıdaki komut çalıştırıldığında 0,1,2,3...255 serisini bir sütun matrisi yani 256x1 olan matrise yazar. vector komutunun ilk parametresi başlangıç değerini, ortadaki parametre artım miktarı (incr) ve son parametre ise bitiş değerini simgeler. Dikkat edilmesi gereken önemli bir nokta, üretilen sütun matrisine başlangıç ve bitiş değerleri dâhil edilmektedir. vector komutunu daha çok artım miktarı belirgin olan problemlerde kullanıyoruz. Örneğin istersek 0 ile 255 arasında 0.001 artımla değeri yükselen bir seri de üretebilirdik bu durumda 255001 adet artan seri değerleri üretilirdi. Diğer taraftan, bazı problemlerde artım değerinden ziyade, matris boyutu önemli olabilir. Mesela, 0..255 arasına 999 adet sayıyı lineer (eşit arttırımlı) yerleştirmek istersek "linspace" komutunu kullanmamız gerekecektir.

CMatrix cm=CMatrix.getInstance().linspace(0, 255, 99);

yukarıdaki komutun sonuna println ekleyip ekrana bastığımızda toplamda 99 satırdan meydana gelen sütun matrisinin elemanlarının başlangıç değeri olarak 0'dan başladığını ancak bitiş değerini yazmadığını görürüz. Bunun nedeni son değer eklendiğinde satır sayısı 100 olacaktır. Ancak özellikle 99 satır olması gerektiğini söylediğimiz için son değer seriye eklenmez.

vector ve linspace komutları daha çok matematiksel fonskiyonların (polynomial and complex) yazılmasında y=f(x) benzetimi için x eksenini temsil etmede kullanılmaktadır.

SORU: 0..720 arasında sinüs değerini hesaplayan kodu OCL ile gerçekleyiniz.

CEVAP:

CMatrix cm=CMatrix.getInstance().vector(0, 1, 720).sin().plot();

yukarıdaki kod bloğu çalıştırıldığında aşağıdakine benzer bir grafik üretecektir.



Plot ekranı dikkatlice incelendiğinde bir şeylerin yanlış gittiği kolaylıkla anlaşılabilir çünkü sinüs fonksiyonu teorik olarak 0..360 arasında tam bir periyot yapması gerekirken şekilden de anlaşılacağı gibi çok yüksek frekansta değişim göstermektedir. Bunun nedeni, sin metodu varsayılan olarak (by default) radian türünde değerler alır. Bunun için sin metodundan önce toRadians() veya multiplyScalar(Math.PI/180) yazmamız gerekir. Doğru çalışan kod ve plot ekranı aşağıda gösterilmiştir.

CMatrix cm=CMatrix.getInstance().vector(0,1,720).toRadians().sin().plot();

veya

CMatrix cm=CMatrix.getInstance().vector(0,1,720).multiplyScalar(Math.PI/180).sin().plot();



Şimdilik tek boyutlu sinyallerle ilgili anlatacaklarımız bu kadar. Açık Cezeri Kütüphanesine katkıda bulunmak ve yazı dizilerini daha kaliteli yapmak için kanalımıza abone olmayı ve yorum yazmayı unutmayınız. Herkese iyi kodlamalar.

Bu dersin videosuna   https://www.youtube.com/watch?v=ebzcySaeGOI   linkinden ulaşabilirsiniz.


Hiç yorum yok:

Yorum Gönder