Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Observational data on old plots #29

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open

Observational data on old plots #29

wants to merge 17 commits into from

Conversation

GeorgySk
Copy link
Owner

Now we also plot observational data on old plots of velocities vs magnitude and velocities clouds diagrams

observational_clouds_paths = dict(
u=os.path.join(base_dir, u_observational_clouds_path),
v=os.path.join(base_dir, v_observational_clouds_path),
w=os.path.join(base_dir, w_observational_clouds_path))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

но ведь эти вещи можно передавать сверху, что облегчит сигнатуру и уберёт значения по умолчанию, которые не стоит использовать для путей, потому что у всех они разные, а при изменении никто не обратит внимание на функцию на самом дне

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

сверху - это откуда именно? из функции draw модуля plots.service в месте вызова?

Copy link
Collaborator

@lycantropos lycantropos Sep 24, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ага, в месте вызова, этой функции будет без разницы, откуда именно её вызывают, лишь бы передали словарь с путями

v_observational_bins_df = pd.read_csv(observational_bins_paths['v'],
delimiter=' ',
skipinitialspace=True,
header=None)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DRY, что нам мешает использовать partial?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

запилил

w_observational_clouds_df = pd.read_csv(observational_clouds_paths['w'],
delimiter=' ',
skipinitialspace=True,
header=None)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

6 раз (!)

вместо того, чтобы делать простой Copy-Paste внутри проекта без изменения логики с инициализацией объекта (что уже само говорит о нарушении DRY-принципа) ничто нам не стоит потратить некоторое время на вынос в отдельную функцию (если это всё ещё не функция) или на фиксирование значений у уже имеющейся, если часть не изменяется

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

и мы в очередной раз пройдём путь, когда все эти префиксы u, v, w – суть проекции данных, логика которых изменяется только на префикс

в этом прелесть физики, в наличии всевозможных инвариантов, и мы должны использовать эту фичу, а не копипастить

y_line_obs=v_observational_bins_df[1],
yerr_obs=v_observational_bins_df[2],
x_scatter_obs=v_observational_clouds_df[0],
y_scatter_obs=v_observational_clouds_df[1])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

эти вызовы отличаются лишь префиксом u/v/w, если исходную функцию обобщить и все эти *_vs_mag_bins. df, SAMPLE TEXT считывать сверху, а сюда просто их передавать по одному, мы уменьшим объём как минимум втрое

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

и это нужно сделать, потому что дальше кода будет ещё больше, нас всего 2ое, не хочется потом тратить пару недель на простой рефакторинг, который легче всего сделать, пока мы (ну я не в счёт) в контексте задачи, которую этот код должен выполнять

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

этот подход с написанием общей функции и передачей в неё проекций значительно упростит следующее:

  • чтение кода, ведь его объём уменьшится, а всё самое интересное (I/O операции) будет происходить наверху, а не на самом дне, не забываем, что современные программисты несмотря на заблуждения масс бОльшую часть времени
  • тестирование, которое было бы неплохо начать писать уже сейчас, ведь это увеличивает количество участников до 3, притом он всегда онлайн, отвечает в считанные секунды, говорит фактами, и чем проще – тем он лучше, потому что мы можем себе позволить пропустить незначительный edge-case'ы, но наши use-case'ы он должен покрывать, ТАКЖЕ написание unit-тестов облегчится за счёт того, что всё I/O в таком подходе уползает наружу, а не происходит в самом низу, что само по себе есть причина многих бед, надо по возможности оперировать с чистыми функциями, может показаться, что я этого начитался/насмотрелся и теперь бездумно это проповедую, но так оно и есть + я немного писал тестов и это становится тем очевиднее, чем больше их напишешь, поэтому я так против мутирования Star объектов.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Для наглядности рассмотрим пример:
есть функция, которая мутирует state одного Star-объекта:

def set_coordinates(star: Star,
                    coordinates: Tuple[int, int, int]) -> None:
    # `if` здесь чтобы добавить логики
    if not star.coordinates:
        star.coordinates = coordinates

код максимально краток, при этом аналогичный тест

...generating star object and new coordinates...
old_coordinates = star.coordinates

set_coordinates(star, new_coordinates)

assert (not old_coordinates and star.coordinates == new_coordinates or
        star.coordinates == old_coordinates)

не отличается ясностью. Мы оперируем не в терминах звёзд, а в терминах их внутренностей, и из этого теста можно подумать, что Star – абстракция, которая «заточила» в себе бедные объекты и нам приходится их освобождать (создавать old_coordinates), чтобы работать наконец с самими объектами, этот подход противоречит самой сути абстракции и ООП, когда ты должен скрывать реализацию и просто обмениваться сообщениями а-ля

...generating star object and new coordinates...

new_star = update_coordinates(star, new_coordinates)

assert (not star.coordinates and new_star.coordinates == new_coordinates or 
        new_star.coordinates == star.coordinates)

т. е. в данном тесте coordinates уже спокойно может быть как полем, так и property (напомню, что основная суть property в том, что мы предоставляем динамический getter (и опционально setter/deleter) для объектов, и в отсутствие setter/deleter, пользователь не может напрямую изменить поле объекта, т. е. оно становится read-only, а если ко всем полям относиться read-only, то возникает очевидная возможность мемоизации (с которой нужно быть осторожным, но «we are adults here», советую это выступление посмотреть с самого начала), мы абстрагируемся от реализации Star.coordinates и работаем с ним путём общения с объектом вроде

"эй, star, что ты мне скажешь насчёт coordinates?"

а не как с продуктом в корзине, который нужно достать и посмотреть самому и так каждый раз... СНОВА И СНОВА

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

в рассмотренном примере первый тест будет некорректным, если например

  • coordinates принадлежит мутируемому типу (например list или numpy.array)
  • внутри set_coordinates произойдёт мутация coordinates в духе C-style:
for coordinate in new_coordinates:
    star.coordinates.append(coordinate)

тогда old_coordinates уже будет удовлетворять не первому условию assert'a (coordinates были пусты и перестали быть пустыми, наполнившись новыми координатами)

not old_coordinates and star.coordinates == new_coordinates

а второму (координаты были не пусты и не наполнились)

star.coordinates == old_coordinates

и самое ужасное здесь, что код содержит логическую ошибку, а тесты проходят!

w=[star.w_velocity
for star in velocity_vs_magnitude_clouds['w']])

for key in ('u', 'v', 'w'):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

разве я не писал про ту утилиту для прохождения по одинаковым ключам словарей?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

тем более что опять нужно всё это превратить в функцию для одной проекции и работать с ней, а сверху просто передавать их одну за другой, так будет «чище»

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

хотел было глянуть, но подумал, что раз я решил избавиться от пост-процессинга, то сначала и избавлюсь от него. иначе, возможно, сейчас бы зря переписывал этот модуль.

avg_velocities[key],
velocities_std[key]) = zip(*sorted(zip(bins_avg_magnitudes[key],
avg_velocities[key],
velocities_std[key])))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

это ещё зачем?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

если нужна сортировка, её стоит делать отдельно от draw_subplot

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

остаток от кассандры. она перемешивала всё. графики непоследовательно строились. надо будет ветку с фиксом сделать, где удалю эти сортировки

@GeorgySk GeorgySk changed the base branch from sloan_cones to master September 29, 2017 19:55
@GeorgySk
Copy link
Owner Author

GeorgySk commented Oct 9, 2017

Тут продолжим, когда ветку с пандас в мастер смержим

@GeorgySk GeorgySk self-assigned this Oct 30, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants