Добро пожаловать в Engee
Движение звезд
Цель: Использовать все полученные знания в ходе практического проекта.
Вводное видео
Транскрипция видео
Можно много узнать о звездах по их электромагнитному излучению, даже о тех, которые располагаются в сотнях тысяч световых лет от нас. Используя дифракционную решетку, можно расщепить поток света на световые пучки с разной частотой колебаний подобно тому, как капли воды преломляют солнечный свет, образуя радугу. Измеряя яркость светового потока на каждой отдельной частоте, или длине волны, мы собираем спектр каждой звезды. Сейчас перед вами спектр HD94028, он принадлежит не очень яркой звезде в созвездии Льва.
Обратите внимание на самую большую впадину в спектре, появление которого означает, что на длине волны около 650 нанометров от звезды приходит не так уж много света. Эта особенность присуща многим звездам, поскольку водород, который является основным компонентом большинства звезд, поглощает те световые волны, длина волны которых составляет в точности 656.28 нанометров.
Однако, как вы узнаете в ходе этого проекта, эта впадина спектра HD94028, называемая также H-альфа, располагается на уровне значения, немного превышающего 656.28 нанометров. Причина этого явления в том, что данная звезда удаляется от Земли. Тот же эффект, из-за которого звук сирен кажется выше, когда машина приближается к вам, и ниже, когда она удаляется, спектр звезды испытывает синее смещение, то есть смещение в сторону более коротких волн если источник приближается к нам. В обратном случае, если движется происходит с удалением от вас, мы видим красное смещение – смещение в сторону более длинных волн. Мы предлагаем в этом проекте воспользоваться возможностями Julia, чтобы найти расположение впадины H-линии звезды HD94028 и сравнить ее с известной длиной волны поглощения водорода, чтобы определить, с какой скоростью эта звезда движется относительно Земли. Производя точные спектральные измерения на протяжении некоторого времени, астрономы могут наблюдать легкие колебания этого значения, показывающие присутствие планет вокруг звезды.
Часть 1: Относительное движение звезды
using CSV, DataFrames
cd(@__DIR__);
default(fmt = :png); # Все графики должны иметь формат PNG
spectra = CSV.read("starData.csv", DataFrame, header=0)[:,1:7];
starnames = CSV.read("starnames.csv", DataFrame, header=0)[!, 1]
lambdaStart = 630.02;
lambdaDelta = 0.14;
nObs = size(spectra,1)
Задача 1
Матрица spectra содержит спектры, измеренные в некотором диапазоне длин волн . Вам дана начальная длина волны (), шаг измерений () и количество измерений nObs.
Создайте переменную lambdaEnd (), в которой будет содержаться значение яркости спектра на последней зарегистрированной длине волны. Можно рассчитать lambdaEnd по формуле .
Затем используйте полученное значение lambdaEnd, чтобы создать вектор lambda (), содержащий диапазон значений от до с шагом .
Подсказка
Для расчета выражения для lambdaEnd нужны только операторы + и *.
Оператор (:) позволит создать диапазон значений с фиксированным шагом.
Решение
lambdaEnd = lambdaStart + (nObs - 1)*lambdaDelta;
lambda = lambdaStart:lambdaDelta:lambdaEnd;
Задача 2 (и 7)
Каждый столбец матрицы spectra содержит спектр отдельной звезды. Шестой столбец соответствует спектру звезды HD 94028.
spectra и создайте переменную s, хранящую все его значения. Вспомните правило индексации: [строка, столбец].
Подсказка
Получите все элементы шестого столбца, использовав двоеточие (:) в качестве первого индекса и число 6 в качестве второго индекса.
Решение
s = spectra[:,6];
Задача 3
s) по всему диапазону длин волн (lambda). Установите, чтобы маркеры были небольшими точками (m=:o, ms=1), соединенными сплошной линией. Отключим легенду графика аргументом legend = false.
Добавьте подписи на осях: Длина волны на ось X и Яркость на ось Y.
Подсказка
Используйте команду plot с аргументами lambda и s. Вы можете добавить подписи на осях при помощи аргументов xlabel="label" и ylabel="label" или при помощи функций-модификаторов xlabel!("label") и ylabel!("label").
Решение
plot(lambda, s, m=:o, ms=1, legend = false)
Задача 4
Вспомните, как мы использовали функцию findmin для получения минимального значения и его индекса в массиве. Этот индекс соответствует положению линии H-альфа, ().
sHa и idx, содержащие минимальное значение вектора s и тот индекс, где оно встречается в векторе.
Затем найдите длину волны для линии H-альфа, соответствующую найденному минимуму, получив ее из вектора lambda по индексу idx. Сохраните результат в переменную lambdaHa ().
Подсказка
Вызовите функцию findmin с двумя выходными переменными: sHa,idx = ...
Затем используйте idx в качестве индекса для получения значения из вектора lambda.
Решение
(sHa, idx) = findmin(s);
lambdaHa = lambda[idx]
Задача 5
Два значения (lambdaHa,sHa) характеризуют положение линии H-альфа.
[lambdaHa], y = [sHa] в виде красного квадрата ("c=:red,m=:square") и размером маркера ("ms") равным 5.
Подсказка
Используйте функцию plot! чтобы добавить точку ([lambdaHa], [sHa]) на уже созданный график.
В конце строки аргументов добавьте аргумент ms, который задаст нужный размер маркера на графике.
Решение
plot!([lambdaHa], [sHa], c=:red, m=:square, ms=5)
Задача 6
Как вы уже могли убедиться, H-альфа линия звезды HD94028 находится в области 656.62 нм, что характеризует наблюдаемую волну как более длинную, чем волна с периодом 656.28 нм.
Используя значение длины волны линии H-альфа этой звезды, можно рассчитать коэффициент красного смещения (имеющий отношение к тангенциальной скорости движения звезды относительно Земли), используя формулу . После этого можно рассчитать саму скорость, умножив коэффициент смещения (z) на скорость света в вакууме (299792.458 км/с).
z, а скорость – в переменную с названием speed.
Подсказка
Рассчитайте значение z по формуле lambdaHa/656.28 − 1. Для расчета скорости найдите произведение переменной z на скорость света 299792.458.
Решение
z = lambdaHa/656.28 - 1
speed = z*299792.458
Задача 7
Вы создали скрипт для расчета красного смещения звезды. Теперь вы можете с легкостью изменить код, чтобы провести те же расчеты для любой другой звезды из матрицы spectra.
spectra вместо шестой.Подсказка
Замените код в строке s = spectra[:,6] чтобы он помещал второй столбец в матрицу s, вместо шестого.
Решение
s = spectra[:,2]
Часть 2: Относительное движение всех звезд в созвездии
В прошлой части упражнения вы рассчитали скорость приближения или удаления одной звезды по отношению к Земле (в км/ч). В этой части проекта вы рассчитаете ту же скорость для всех звезд в целом созвездии. В конце вы получите график, подобный тому, который представлен на иллюстрации ниже.
Задача 1
В приведенном ниже скрипте реализован алгоритм получения спектра второй звезды из матрицы spectra и вычисление скорости ее движения (в км/ч) относительно Земли.
sHa,idx = findmin(spectra[:,2]);
lambdaHa = lambda[idx];
z = lambdaHa/656.28 - 1;
speed = z*299792.458;
А как бы вы рассчитали скорость всех описанных звезд?
Многократное выполнение одного и того же кода можно осуществить при помощи цикла for, но векторные операции (над массивами) всегда работают быстрее, чем операции над отдельными числами.
- Удалите
[:,2], чтобы рассчитать скорость сразу всех звезд в созвездии. - Добавьте в команду
findminвторой аргументdims = 1, чтобы найти минимум каждого отдельного спектра (а не всей матрицы). - Вектор индексов сейчас вычислен для двумерной матрицы. Его нужно преобразовать в одномерный вектор командой: распаковать из особого формата для декартовых координат и в каждом случае из двух координат оставить только первую:
idx = first.(Tuple.(idx)). - Вычитание единицы нужно сделать поэлементным (
.-).
sHa,idx = findmin(spectra[:,2])
#
lambdaHa = lambda[idx];
z = lambdaHa/656.28 - 1;
speed = z*299792.458
Подсказка
Чтобы векторизовать этот код, вам нужно изменить первые две строки, заменив
sHa,idx = findmin(spectra[:,2])наsHa,idx = findmin(Matrix(spectra), dims = 1)- Вторую строку
#наidx = first.(Tuple.(idx)) - Строку
z = lambdaHa/656.28 - 1наz = lambdaHa/656.28 .- 1
Решение
sHa,idx = findmin(Matrix(spectra), dims = 1)
idx = first.(Tuple.(idx))
lambdaHa = lambda[idx];
z = lambdaHa/656.28 .- 1
speed = z*299792.458
Задача 2 (3, 4)
Как можно заметить, переменная speed теперь является матрицей. Положительное значение элемента в ней означает, что звезда удаляется от нас (красное смещение спектра), а отрицательное значение означает, что звезда приближается к нам (синее смещение).
В паре следующих задач вы нарисуете графики спектров всех изучаемых нами звезд, применяя к ним разные стили в зависимости от характера смещения спектра звезды: красное или синее. Здесь удобно использовать цикл for, чтобы обрабатывать данные обо всех звездах по очереди.
for с переменной-счетчиком v. Цикл должен проходить по всем столбцам матрицы spectra (с 1 по 7).
Внутри тела цикла поместите столбец под номером v матрицы spectra в переменную s.
Подсказка
Создайте цикл for при помощи строки for v = 1:7.
Тело цикла должно состоять из одной строки: s = spectra[:,v]
Не забудьте дописать слово end после окончания тела цикла.
Решение
for v = 1:7
s = spectra[:,v]
end
Задача 3
Условный блок if позволит провести различие между красным и синим смещением спектров. В первую очередь, нанесем на график спектры с синим смещением при помощи пунктирных линий.
Добавьте блок if в тело цикла for. Пусть он проверяет выражение speed(v), и если значение меньше или равно 0, то должен выполниться код, который рисует график s относительно lambda при помощи пунктирной линии (ls=:dash). После end добавьте команду plot!(legend=false).
До начала цикла создайте пустой график plot(), а все дополнения делайте через функцию-модификатор plot!. В конце ячейки поместите команду plot!(legend=false).
Подсказка
Команда вывода графиков должна выглядеть так: plot!(lambda,s,ls=:dash).
Решение
plot()
for v = 1:7
s = spectra[:,v]
if speed[v] <= 0
plot!(lambda, s, ls=:dash)
end
end
plot!(legend=false)
Задача 4
Выведите на графике спектры звезд с красным смещением при помощи толстой линии.
Добавьте слово else к имеющейся конструкции. Если значение speed[v] больше 0, должен быть создан график s по lambda с толщиной линии 3 (lw=3).
Подсказка
Добавьте слово else между if и end.
Установите свойство lw у функции plot! равным 3.
Не забудьте добавить plot!(legend=false) в конец ячейки.
Решение
plot()
for v = 1:7
s = spectra[:,v]
if speed[v] <= 0
plot!(lambda, s, ls=:dash)
else
plot!(lambda, s, lw=3)
end
end
plot!(legend=false)
Задача 5
Удалите строку plot!(legend=false). Затем задайте правильные подписи всем спектрам на графике, добавьте аргумент label в каждый вызов функции plot!, взяв подпись из массива starnames по индексу v.
Добавьте название графика: title!("Спектры звезд").
Подсказка
Добавьте аргументы label=starnames[v] к каждому вызову функции plot!.
Решение
plot()
for v = 1:7
s = spectra[:,v]
if speed[v] <= 0
plot!(lambda, s, ls=:dash, label=starnames[v])
else
plot!(lambda, s, lw=3, label=starnames[v])
end
end
title!("Спектры звёзд")
Задача 6
Для интерпретации графика вы можете изучить, какая линия нарисована каким стилем, а затем узнать по легенде, как называется соответствующая звезда. Но сможете ли вы определить названия звезд с красным смещением без использования цикла for?
Вспомните, как мы использовали бинарные индексы, чтобы найти элементы массива, которые соответствуют какому-нибудь условию: c = b(a < 6)
movaway, содержащую те элементы из вектора starnames, для которых speed больше 0.
Поскольку переменная speed является матрицей, приведите результат сравнения speed .> 0 к одномерному векторному типу при помощи функции vec, ее результат используйте в качестве индекса.
Подсказка
Нужные элементы вектора speed вы можете найти при помощи логической команды: speed .> 0.
Вывод этого сравнения используйте как индекс для вектора starnames после преобразования vec(speed .> 0).
Решение
moveaway = starnames[vec(speed .> 0)]
Задача 7*
Как и множество других функций, вывод графика можно осуществить как "поштучно", так и для всей матрицы сразу.
Команда plot(A) создает по одному графику для каждого столбца матрицы A.
Так что если вам не нужно рисовать разные графики для звезд с синим и с красным смещением, то можно обойтись и без цикла for.
Попробуйте выполнить следующую команду и пронаблюдайте ее результат!
plot(lambda, Matrix(spectra), label=starnames)