Penetrasi sinyal dalam numpy

8

Masalahnya terdiri dalam pemodelan propagasi sinyal (mis. Cahaya atau suara dll) melalui serangkaian hambatan, seperti pada gambar di bawah ini. Sinyal tidak dapat melewati permukaan bawah (medan), tetapi dapat melintasi rintangan. Saya ingin menghitung jumlah rintangan yang dilalui.

masukkan deskripsi gambar di sini

Medan dan hambatan ada dalam array numpy 2D (x, y, z). Inilah yang saya lakukan:

output = numpy.zeros(terrain.shape)

obstacles = terrain + obstacle_heights


for i in xrange (obstacles.shape[0]):
    for j in xrange (obstacles.shape[1]):

        mask = obstacles[i,j] > terrain[i,j:]
        output[i,j:][mask] +=1

Hasilnya akan menjadi seperti [0, 0, 0, 1, 1, 1, 2, 3, 4, 4, 4 ...]per baris.

Metode ini berfungsi dengan baik (asalkan lembah di terisi diisi dengan menggunakan numpy.maximum.accumulate). Sekarang, apakah mungkin untuk mempercepatnya dengan menggunakan solusi vektor?

Zoran
sumber
1
Pertanyaan menarik. Bisakah Anda menjelaskan lebih detail solusi mana yang Anda cari dan data input mana? Saya pikir Anda sedang mencari pembuatan garis (sebagai lapisan linestring) yang mewakili sinyal tetapi, dalam hal ini, perlu juga menentukan arah selain format sumber.
mgri
Saya tertarik pada keduanya, akustik dan redaman ringan (mis. Kabut asap, asap). Demi kesederhanaan, sinyal bergerak paralel ke medan (vertikal) dan paralel ke medan jaringan (horizontal). Dengan "sinyal" yang saya maksud hanya iterator sederhana di atas matriks numpy.
Zoran
1
Dan bagaimana dengan tinggi sinyal?
dmh126
Tinggi sinyal berubah-ubah: katakanlah 1,7 meter untuk tinggi manusia ... Maka Anda dapat menaikkan (sementara) medan untuk nilai itu `mask = rintangan [i, j]> medan [i, j:] + 1,7` <dalam kode saya Saya menggunakan ukuran sudut yang diperoleh dengan membagi ketinggian dengan jarak dari sumber - tetapi itu tidak relevan di sini, menurut saya (?)>
Zoran
Tentunya dimungkinkan untuk melakukan vektorisasi, FFT dapat di vektorisasi ( jakevdp.github.io/blog/2013/08/28/understanding-the-fft ). Saya berjuang untuk memahami apa yang rintangan.shape [0] dan rintangan.shape [1] mewakili.
John Powell

Jawaban:

1

Seperti komentar di atas, Anda mungkin bisa membuat vektor operasi untuk menghapus loop dan membuatnya lebih efisien.

Namun, jika Anda mempertimbangkan masalah dengan cara yang sedikit berbeda - yaitu dari thresholding - Anda dapat memanfaatkan alat dari ndimage yang cerdik untuk menghitung hambatan:

Pertama, ambangkan data terrain Anda dengan tinggi sinyal Anda untuk mendapatkan array boolean di mana sinyal bisa berada, terlepas dari asalnya.

signal_reach = terrain < signal_height

Kemudian Anda dapat menggunakan ndimage.labelmetode ini untuk mengelompokkan wilayah diskrit:

from scipy import ndimage
signal_regions, region_count = ndimage.label(signal_reach)

Setelah ini selesai, dapatkan ID wilayah yang cocok dengan sel asal sinyal Anda. Dalam kasus Anda itu akan menjadi kolom pertama.

import numpy as np
origin_labels = np.unique(signal_regions[:, 0]) # or whatever indexes meet the start of the signal
# ndimage lables are greater than 1, 0 is an unlabeled region
origin_labels = origin_lables[origin_lables > 0]

Sekarang ambang muncul di mana sinyal mencegat rintangan terrain +, dan kali ini memfilter wilayah di luar atau area yang diminati menggunakan numpy.isin.

area_of_interest = np.isin(signal_regions, origin_labels)
signal_intercepted = (obstacles >= signal_height) & area_of_interest

Dan putaran terakhir ndimage.labelmemberi Anda hitungan hambatan yang dicegat, karena kami telah menyaring area yang terhalang oleh medan:

obstacles_hit, obstacle_count = ndimage.label(signal_intercepted)

Ada sedikit lebih banyak kode di sini, tetapi ada dua keuntungan besar:

  • Tidak untuk loop berarti kode harus cukup cepat,
  • Dan untuk tujuan perhitungan, asal sinyal bisa di atau banyak sel, di mana saja di raster medan.
om_henners
sumber
1
Ini terlihat seperti pendekatan yang menjanjikan! Saya akan mengujinya pada bulan Januari dan menandainya sebagai slution jika berhasil.
Zoran