Безпосередньо порівняйте зсуви пікселів між двома спектрами - і отримайте правдоподібні помилки


9

У мене є два спектри одного і того ж астрономічного об’єкта. Основне питання полягає в наступному: Як я можу обчислити відносний зсув між цими спектрами і отримати точну помилку на цьому зсуві?

Ще кілька деталей, якщо ти все ще зі мною. Кожен спектр буде масивом зі значенням x (довжина хвилі), значенням y (потік) та помилкою. Зсув довжини хвилі буде нижчим пікселем. Припустимо, що пікселі регулярно розташовані між собою і що буде лише один зсув довжини хвилі, застосований до всього спектру. Тож кінцева відповідь буде приблизно такою: 0,35 +/- 0,25 пікселів.

Два спектри будуть безліччю безхарактерного континууму, що визначається деякими досить складними характеристиками поглинання (опускання), які не моделюються легко (і не є періодичними). Я хотів би знайти метод, який безпосередньо порівнює два спектри.

Перший інстинкт кожного - це зробити перехресну кореляцію, але при зміні субпікселів вам доведеться інтерполювати між спектрами (спочатку згладжуючи?) - також помилки здаються неприємними, щоб виправитись.

Мій сучасний підхід полягає в згладжуванні даних шляхом з'єднання з гауссовим ядром, потім спланування згладженого результату та порівняння двох сплайнованих спектрів - але я не вірю цьому (особливо помилкам).

Хтось знає про спосіб зробити це правильно?

Ось коротка програма пітона, яка створить два іграшкових спектри, зміщені на 0,4 пікселя (виписані у toy1.ascii та toy2.ascii), з якими можна грати. Хоча ця модель іграшки використовує просту гауссову функцію, припустимо, що фактичні дані не можуть відповідати простої моделі.

import numpy as np
import random as ra
import scipy.signal as ss
arraysize = 1000
fluxlevel = 100.0
noise = 2.0
signal_std = 15.0
signal_depth = 40.0
gaussian = lambda x: np.exp(-(mu-x)**2/ (2 * signal_std))
mu = 500.1
np.savetxt('toy1.ascii', zip(np.arange(arraysize), np.array([ra.normalvariate(fluxlevel, noise) for x in range(arraysize)] - gaussian(np.arange(arraysize)) * signal_depth), np.ones(arraysize) * noise))
mu = 500.5
np.savetxt('toy2.ascii', zip(np.arange(arraysize), np.array([ra.normalvariate(fluxlevel, noise) for x in range(arraysize)] - gaussian(np.arange(arraysize)) * signal_depth), np.ones(arraysize) * noise))

Якщо я правильно розумію, проблема звучить аналогічно реєстрації зображень, за винятком того, що у вас є лише лінійний зсув пікселя в одній осі. Може, спробувати стандартні методи реєстрації зображень, такі як фазова кореляція?
Пол Р

Якщо у вас є чиста затримка одного сигналу (тобто зсув параметра довжини хвилі, про який ви говорите), ви, можливо, зможете використовувати властивість перетворення Фур'є, яка перетворює затримку часу в лінійне зміщення фази в частотній області. Це може спрацювати, якщо обидва зразки не будуть пошкоджені різними шумами вимірювань або перешкодами.
Джейсон Р.

1
Ця тема може бути корисною
Джим Клей

1
У вас є фактичні дані для тестування? Значення шуму, яке ви подали, є занадто великим, щоб перехресне співвідношення було точним на вибірці. Це те , що він знаходить з декількома пробігами шуму 2.0 і 0.7 (зміщення = 1000.7 на осі х сюжетів в), наприклад: i.stack.imgur.com/UK5JD.png
ендоліти

Відповіді:


5

Я думаю, що використання перехресної кореляції та інтерполяції піку спрацювало б добре. Як описано в „ Чи не є марним проведення вибірки до перехресної кореляції? , інтерполяція або прискорене моделювання перед перехресним співвідношенням насправді не отримує більше інформації. Інформація про пік субпроби міститься у вибірках навколо неї. Вам просто потрібно витягти його з мінімальною помилкою. Я зібрав тут кілька записок .

Найпростіший метод квадратичної / параболічної інтерполяції, який у мене є приклад пітон тут . Нібито точно, якщо ваш спектр базується на гауссовому вікні або якщо пік трапляється саме на середину між зразками, але в іншому випадку є деяка помилка . Тож у вашому випадку ви, мабуть, хочете використати щось краще.

Ось перелік більш складних, але більш точних оцінок. "З вищезазначених методів другий оцінювач Квін має найменшу помилку RMS."

Я не знаю математики, але в цій роботі йдеться про те, що їх параболічна інтерполяція має теоретичну точність у 5% від ширини відро для FFT.

Використання FFT-інтерполяції на крос-кореляційному виході не має помилок упередження , тому це найкраще, якщо ви хочете по-справжньому гарної точності. Якщо вам потрібно врівноважити точність та швидкість обчислення, рекомендується зробити деяку інтерполяцію FFT, а потім виконати її за допомогою одного з інших оцінювачів, щоб отримати «досить хороший» результат.

Це просто використовує параболічне прилягання, але воно виводить правильне значення для зміщення, якщо шум низький:

def parabolic_polyfit(f, x, n):
    a, b, c = polyfit(arange(x-n//2, x+n//2+1), f[x-n//2:x+n//2+1], 2)
    xv = -0.5 * b/a
    yv = a * xv**2 + b * xv + c

    return (xv, yv)

arraysize = 1001
fluxlevel = 100.0
noise = 0.3 # 2.0 is too noisy for sub-sample accuracy
signal_std = 15.0
signal_depth = 40.0
gaussian = lambda x: np.exp(-(mu-x)**2/ (2 * signal_std))
mu = 500.1
a_flux = np.array([ra.normalvariate(fluxlevel, noise) for x in range(arraysize)] - gaussian(np.arange(arraysize)) * signal_depth)
mu = 500.8
b_flux = np.array([ra.normalvariate(fluxlevel, noise) for x in range(arraysize)] - gaussian(np.arange(arraysize)) * signal_depth)

a_flux -= np.mean(a_flux)
b_flux -= np.mean(b_flux)

corr = ss.fftconvolve(b_flux, a_flux[::-1])

peak = np.argmax(corr)
px, py = parabolic_polyfit(corr, peak, 13)

px = px - (len(a_flux) - 1)
print px

введіть тут опис зображення введіть тут опис зображення

Шум у вашій вибірці дає результати, які змінюються більш ніж на цілий зразок, тому я зменшив його. Встановлення кривої з використанням більшої кількості точок піку допомагає дещо підтягнути оцінку, але я не впевнений, що це статистично достовірно, і це насправді погіршує оцінку для ситуації з меншим рівнем шуму.

З шумом = 0,2 та 3-кратним приладом, він дає такі значення, як 0,398 та 0,402 для зміщення = 0,4.

З шумом = 2,0 і 13-кратне прилягання, він дає такі значення, як 0,156 і 0,595 для зміщення = 0,4.


Я намагаюся вирішити цю точну проблему для реєстрації зображень. Мені потрібна точність пікселів (0,1, мабуть, буде досить хорошою), але головне не потребує упередженості, тому методи інтерполяції не працюють. Чи є для цього хороші (і реалізовані в python?) Методи? Метод нульової прокладки буде працювати, але це занадто дорого, щоб бути практичним.
кефлавич

@kelavich: Ви перевірили всі методи інтерполяції та виявили неприйнятні упередження? Рекомендований підхід - це комбінація деякої нульової прокладки з подальшою інтерполяцією з низькою помилкою. Я не знаю жодного іншого методу, але, думаю, це забезпечить вам велику точність.
ендоліт

Так, я виявив неприйнятне зміщення у лінійній інтерполяції та другого порядку. Я спробував FFT з нульовим накладенням, але в результаті переважає високочастотний дзвінок ... будь-який шанс, ви можете додати приклад з нульовим накладенням?
кефлавич
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.