HyperLEDA / db-app

Backend for HyperLeda astronomical database of extragalactic objects
https://hyperleda.github.io/db-app/
MIT License
0 stars 0 forks source link

Метод старта кросс-идентификации #194

Open Kraysent opened 2 weeks ago

Kraysent commented 2 weeks ago

В рамках дискуссии https://github.com/orgs/HyperLEDA/discussions/171 обсуждали проведение кросс-идентификации и её API.

Сошлись на том, что после загрузки таблицы будет вызываться метод POST /api/v1/admin/table/process, который будет стартовать кросс-идентификацию. Тело запроса будет иметь вид:

{
    "table_id": 12345,
    "cross_identification": { // это поле можно не передавать, тогда будут значения по умолчанию
        "inner_radius_arcsec": 1.5,
        "outer_radius_arcsec": 5
    }
}

Если ничего не передано, метод сам выберет нужные параметры кросс-идентификации (пока что просто возьмёт параметры по умолчанию) и начнёт обработку с ними.

В рамках задачи нужно воспользоваться функцией кросс-идентификации: https://github.com/HyperLEDA/db-app/blob/0692788774d18b701ceef5a1730ba89d4f4d2dd3/app/domain/usecases/cross_identify_use_case.py, начать кросс-идентификацию и записать её результаты в таблицу.

Несколько моментов на проработку:

Kraysent commented 2 weeks ago

Пока что процесс кросс-идентификации будет выглядеть так:

  1. С нулевого уровня вытащить BATCH_SIZE объектов из заданной таблицы. Вытаскивание будет делаться с ORDER BY hyperleda_internal_id OFFSET x LIMIT BATCH_SIZE.
  2. Вытащить метаданные загружаемой таблицы.
  3. Сделать алгоритм, по которому выделяются столбцы для кросс-идентификации - имя, прямое восхождение и склонение.
  4. Сформировать набор объектов для кросс-идентификации
  5. Запустить алгоритм кросс-идентификации для каждого объекта
  6. Записать результат в таблицу.
  7. Повторить для каждого батча

Здесь нет учёта возможных коллизий объектов одного набора данных между собой. Это нужно отдельно продумать и обсудить - текущая реализация предполагает загрузку всего каталога в память, что нереализуемо для больших каталогов.

Пока что реализую без этого в качестве proof of concept.

Kraysent commented 2 weeks ago

Алгоритм выделения столбцов кросс-идентификации

Проблема

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

Столбцы в себе могут содержать ucd в разных видах (pos.eq.ra или pos.eq.ra;meta.main) или даже простираться на несколько столбцов, аггрегация которых будет проводиться в соответствии с тем, что написано в поле format.

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

Предполагаемое решение

Класс-абстракция, который будет на вход получать информацию о столбцах, а по запросу отдавать функцию преобразования столбцов в данные. То есть интерфейс класса будет в каком-то таком виде:

class QuantityConverter(abc.ABC):
    @abc.abstractmethod
    def get_converter(self) -> Callable[[list[Iterable]], Iterable]: ...

@dataclass
class RightAscensionFormat:
    pass

class RightAscensionConverter(QuantityConverter):
    def __init__(self, columns_info: list[ColumnDescription], format_data: RightAscensionFormat): ...

    def get_converter(self) -> Callable[[list[Iterable]], Iterable]: ...

Соответственно для получения конвертаторов нужно будет из переданного пользователем списка столбцов собирать список колонок, которые относятся к данной величине, раскладывать их по конструкторам и собирать список объектов QuantityConverter. Далее для кросс-идентификации будут собираться только конвертеры для прямого восхождения, склонения и имени. Для переноса на 1-й уровень будут собираться все остальные конвертеры. При этом эта абстракция не требует зависимости от ucd напрямую, что будет полезно при обработке каталога фотометрии (в нём, скорее всего, одному ucd будет соответствовать множество таблиц).