Gaia DR3 Full Sky Map — pobieranie, walidacja i wizualizacja całej Drogi Mlecznej

Przez kilka dni budowałem lokalny pipeline do pobrania i przetworzenia pełnego datasetu Gaia DR3. Celem było:

  • pobranie całej tabeli gaia_source
  • konwersja do Parquet
  • walidacja integralności danych
  • przygotowanie szybkich wizualizacji całego nieba oraz Dużego Obłoku Magellana

Projekt został wykonany lokalnie w Pythonie + Jupyter Notebook z użyciem Parquet, Polars, DuckDB i Plotly.

Stack technologiczny

Środowisko

  • Python 3.10 + 3.11
  • Jupyter Notebook
  • Ubuntu Server
  • Szybki dysk SSD NVMe

Biblioteki

  • Astroquery
  • Astropy
  • PyArrow
  • Polars
  • DuckDB
  • Pandas
  • Plotly
  • Matplotlib

Dwie metody pobierania Gaia DR3

Pobieranie przez SQL ESA TAP

  • logowanie do ESA Gaia Archive
  • pobieranie batchami po 100 000 rekordów
  • checkpointy
  • retry logic
  • zapis do Parquet

Pobierane były tylko wybrane kolumny:

  • source_id
  • ra
  • dec
  • l
  • b
  • parallax
  • pmra
  • pmdec
  • phot_g_mean_mag
  • phot_bp_mean_mag
  • phot_rp_mean_mag
  • ruwe

Cechy kodu crawlera:

  • możliwość wznawiania pobierania
  • wykładnicze opóźnienie ponownych prób
  • logowanie nieudanych batchy / paczek danych
  • automatyczny zapis checkpointów
  • konwersję float64 -> float32
  • batching do parquetów

Problem SQL

SQL okazał się zbyt wolny dla pełnego datasetu.

Pobranie około 500 milionów rekordów trwało około 3 dni — i to tylko dla ograniczonego zestawu parametrów. Pobranie jednego batchu 100 000 rekordów i konwersja do parquetu trwała 15 sekund w dni wolne, oraz 50-60 sekund w dni pracujące.

To było zbyt wolne dla pełnego Gaia DR3.

Pobieranie bezpośrednio z CDN ESA

Finalnie przeszedłem na oficjalny CDN Gaia DR3.

https://cdn.gea.esac.esa.int/?prefix=Gaia/gdr3/gaia_source/

To okazało się znacznie szybsze i stabilniejsze.

Jest to równocześnie rekomendowana metoda pobierania całego datasetu przez ESA.


Pipeline CDN -> Parquet

Crawler wykonywał:

  1. Pobranie oficjalnego _MD5SUM.txt
  2. Parsowanie listy plików
  3. Pobieranie wszystkich .csv.gz
  4. Walidację MD5
  5. Odczyt ECSV
  6. Konwersję Arrow -> Parquet
  7. Kompresję ZSTD
  8. Checkpointing
  9. Cleanup

Kod zawierał:

  • mechanizm ponownych prób
  • walidacja sum kontrolnych MD5
  • możliwość wznawiania sesji pobierania
  • automatyczne checkpointy
  • obsługę nulli
  • silnik pyarrow
  • kompresję ZSTD

Podczas budowy pipeline konieczne było utworzenie oddzielnego środowiska Conda specjalnie do pobierania danych z CDN Gaia DR3.

starsze wersje Astropy nie obsługują poprawnie:

  • read_ecsv()
  • engine=pyarrow

dla dużych plików Gaia DR3 ECSV.

Dopiero:

  • Python 3.11
  • Astropy 7+
  • nowy PyArrow

pozwalały stabilnie odczytywać ogromne pliki .csv.gz bezpośrednio jako ECSV.

Pipeline korzystał z:

read_ecsv(
csv_path,
engine="pyarrow",
null_values=["null"]
)

Pobranie jednej paczki 500 000 rekordów, walidacja i zapis do parquet z wszystkimi kolumnami trwało około 60 sekund.


Walidacja integralności danych


Wynik walidacji

Liczba plików

  • znaleziono: 3386
  • oczekiwano: 3386
  • brakujących: 0

Rozmiar

  • około 600.61 GB parquetów

Liczba rekordów

  • rows: 1,811,709,771
  • expected: 1,811,709,771
  • difference: 0

Duplikaty

  • duplicates: 0

Unikalne source_id

  • unique_source_ids: 1,811,709,771
============================================================
FILE COUNT
============================================================
FOUND:      3,386
EXPECTED:   3,386
MISSING:    0
============================================================
TOTAL SIZE
============================================================
600.61 GB
============================================================
FULL DATASET VALIDATION
============================================================
ROWS:               1,811,709,771
EXPECTED:           1,811,709,771
ROW DIFFERENCE:     0
UNIQUE SOURCE_ID:   1,811,709,771
DUPLICATES:         0

RA RANGE:           0.0000 -> 360.0000
DEC RANGE:          -89.9929 -> 89.9901
L RANGE:            0.0000 -> 360.0000
B RANGE:            -89.9937 -> 89.9880

SOURCE_ID NULLS:    0
RA NULLS:           0
DEC NULLS:          0
PARALLAX NULLS:     343,964,953
============================================================
VALIDATION COMPLETE
============================================================
============================================================

Sprawdzono również pokrycie nieba RA, DEC, L, B, NULLS i PARALLAX NULLS. Liczba rekordów bez paralaksy odpowiada zbiorowi rekordów dwu-parametrowych co stwierdza się również poniżej.


Zgodność z oficjalnym datasetem ESA

============================================================
RUNNING SCIENTIFIC VALIDATION
============================================================
============================================================
OFFICIAL ESA VS LOCAL DATASET
============================================================
total_sources                      LOCAL: 1,811,709,771    ESA: 1,811,709,771    DIFF: 0    100.00%    OK
sources_with_g                     LOCAL: 1,806,254,432    ESA: 1,806,254,432    DIFF: 0    100.00%    OK
sources_with_bp                    LOCAL: 1,542,033,472    ESA: 1,542,033,472    DIFF: 0    100.00%    OK
sources_with_rp                    LOCAL: 1,554,997,939    ESA: 1,554,997,939    DIFF: 0    100.00%    OK
sources_with_full_astrometry       LOCAL: 1,467,744,818    ESA: 1,467,744,818    DIFF: 0    100.00%    OK
five_parameter_sources             LOCAL: 585,416,709    ESA: 585,416,709    DIFF: 0    100.00%    OK
six_parameter_sources              LOCAL: 882,328,109    ESA: 882,328,109    DIFF: 0    100.00%    OK
two_parameter_sources              LOCAL: 343,964,953    ESA: 343,964,953    DIFF: 0    100.00%    OK
============================================================
VALIDATION COMPLETE
============================================================

 # sources in Gaia DR3
   Total number of sources1,811,709,771
 Gaia Early Data Release 3
   Number of sources with full astrometry1,467,744,818
         Number of 5-parameter sources585,416,709
         Number of 6-parameter sources882,328,109
   Number of 2-parameter sources343,964,953
   Gaia-CRF sources1,614,173
   Sources with mean G magnitude1,806,254,432
   Sources with mean GBP-band photometry1,542,033,472
   Sources with mean GRP-band photometry1,554,997,939
Źródło: https://www.cosmos.esa.int/web/gaia/dr3

Walidacja kolumn posługując się plikiem referencyjnym.

============================================================
GAIA SCHEMA VALIDATION
============================================================
FILES FOUND: 3,386
============================================================
LOADING REFERENCE SCHEMA
============================================================
REFERENCE FILE:
GaiaSource_000000-003111.parquet

COLUMNS: 152

============================================================
VALIDATION RESULTS
============================================================
VALID FILES: 3,386
INVALID FILES: 0
============================================================
REFERENCE SCHEMA
============================================================
000  solution_id                               int64
001  designation                               string
002  source_id                                 int64
003  random_index                              int64
004  ref_epoch                                 double
005  ra                                        double
006  ra_error                                  float
007  dec                                       double
008  dec_error                                 float
009  parallax                                  double
010  parallax_error                            float
011  parallax_over_error                       float
012  pm                                        float
013  pmra                                      double
014  pmra_error                                float
015  pmdec                                     double
016  pmdec_error                               float
017  ra_dec_corr                               float
018  ra_parallax_corr                          float
019  ra_pmra_corr                              float
020  ra_pmdec_corr                             float
021  dec_parallax_corr                         float
022  dec_pmra_corr                             float
023  dec_pmdec_corr                            float
024  parallax_pmra_corr                        float
025  parallax_pmdec_corr                       float
026  pmra_pmdec_corr                           float
027  astrometric_n_obs_al                      int16
028  astrometric_n_obs_ac                      int16
029  astrometric_n_good_obs_al                 int16
030  astrometric_n_bad_obs_al                  int16
031  astrometric_gof_al                        float
032  astrometric_chi2_al                       float
033  astrometric_excess_noise                  float
034  astrometric_excess_noise_sig              float
035  astrometric_params_solved                 int8
036  astrometric_primary_flag                  bool
037  nu_eff_used_in_astrometry                 float
038  pseudocolour                              float
039  pseudocolour_error                        float
040  ra_pseudocolour_corr                      float
041  dec_pseudocolour_corr                     float
042  parallax_pseudocolour_corr                float
043  pmra_pseudocolour_corr                    float
044  pmdec_pseudocolour_corr                   float
045  astrometric_matched_transits              int16
046  visibility_periods_used                   int16
047  astrometric_sigma5d_max                   float
048  matched_transits                          int16
049  new_matched_transits                      int16
050  matched_transits_removed                  int16
051  ipd_gof_harmonic_amplitude                float
052  ipd_gof_harmonic_phase                    float
053  ipd_frac_multi_peak                       int8
054  ipd_frac_odd_win                          int8
055  ruwe                                      float
056  scan_direction_strength_k1                float
057  scan_direction_strength_k2                float
058  scan_direction_strength_k3                float
059  scan_direction_strength_k4                float
060  scan_direction_mean_k1                    float
061  scan_direction_mean_k2                    float
062  scan_direction_mean_k3                    float
063  scan_direction_mean_k4                    float
064  duplicated_source                         bool
065  phot_g_n_obs                              int16
066  phot_g_mean_flux                          double
067  phot_g_mean_flux_error                    float
068  phot_g_mean_flux_over_error               float
069  phot_g_mean_mag                           float
070  phot_bp_n_obs                             int16
071  phot_bp_mean_flux                         double
072  phot_bp_mean_flux_error                   float
073  phot_bp_mean_flux_over_error              float
074  phot_bp_mean_mag                          float
075  phot_rp_n_obs                             int16
076  phot_rp_mean_flux                         double
077  phot_rp_mean_flux_error                   float
078  phot_rp_mean_flux_over_error              float
079  phot_rp_mean_mag                          float
080  phot_bp_rp_excess_factor                  float
081  phot_bp_n_contaminated_transits           int16
082  phot_bp_n_blended_transits                int16
083  phot_rp_n_contaminated_transits           int16
084  phot_rp_n_blended_transits                int16
085  phot_proc_mode                            int8
086  bp_rp                                     float
087  bp_g                                      float
088  g_rp                                      float
089  radial_velocity                           float
090  radial_velocity_error                     float
091  rv_method_used                            int8
092  rv_nb_transits                            int16
093  rv_nb_deblended_transits                  int16
094  rv_visibility_periods_used                int16
095  rv_expected_sig_to_noise                  float
096  rv_renormalised_gof                       float
097  rv_chisq_pvalue                           float
098  rv_time_duration                          float
099  rv_amplitude_robust                       float
100  rv_template_teff                          float
101  rv_template_logg                          float
102  rv_template_fe_h                          float
103  rv_atm_param_origin                       int16
104  vbroad                                    float
105  vbroad_error                              float
106  vbroad_nb_transits                        int16
107  grvs_mag                                  float
108  grvs_mag_error                            float
109  grvs_mag_nb_transits                      int16
110  rvs_spec_sig_to_noise                     float
111  phot_variable_flag                        string
112  l                                         double
113  b                                         double
114  ecl_lon                                   double
115  ecl_lat                                   double
116  in_qso_candidates                         bool
117  in_galaxy_candidates                      bool
118  non_single_star                           int16
119  has_xp_continuous                         bool
120  has_xp_sampled                            bool
121  has_rvs                                   bool
122  has_epoch_photometry                      bool
123  has_epoch_rv                              bool
124  has_mcmc_gspphot                          bool
125  has_mcmc_msc                              bool
126  in_andromeda_survey                       bool
127  classprob_dsc_combmod_quasar              float
128  classprob_dsc_combmod_galaxy              float
129  classprob_dsc_combmod_star                float
130  teff_gspphot                              float
131  teff_gspphot_lower                        float
132  teff_gspphot_upper                        float
133  logg_gspphot                              float
134  logg_gspphot_lower                        float
135  logg_gspphot_upper                        float
136  mh_gspphot                                float
137  mh_gspphot_lower                          float
138  mh_gspphot_upper                          float
139  distance_gspphot                          float
140  distance_gspphot_lower                    float
141  distance_gspphot_upper                    float
142  azero_gspphot                             float
143  azero_gspphot_lower                       float
144  azero_gspphot_upper                       float
145  ag_gspphot                                float
146  ag_gspphot_lower                          float
147  ag_gspphot_upper                          float
148  ebpminrp_gspphot                          float
149  ebpminrp_gspphot_lower                    float
150  ebpminrp_gspphot_upper                    float
151  libname_gspphot                           string
============================================================
DONE
============================================================

Wizualizacje Drogi Mlecznej

Podstawowe wizualizacje były wykonywane w:

  • Matplotlib
  • Plotly

1. Czarno biały obraz nieba

Mapa jasności Drogi Mlecznej.

Widoczny:

  • płaszczyzna galaktyki
  • centralne zgrubienie galaktyki
  • ciemne pasma pyłu międzygwiazdowego
  • Wielki Obłok Magellana
  • Mały Obłok Magellana

2. Obraz z naturalnymi kolorami z sensorów.

Naturalne kolory gwiazd na podstawie indeksu:

  • BP – RP

Wizualizacja pokazuje:

  • niebieskie młode gwiazdy (widoczne wyraźnie w obłokach Magellana)
  • czerwone chłodne gwiazdy
  • pył międzygwiazdowy
  • strukturę dysku galaktycznego

3. Wizualizacja fałszywymi kolorami.

Sztuczne kolory dla lepszego podkreślenia struktur.

Pozwala lepiej zobaczyć:

  • zagęszczenia gwiazd
  • gradienty
  • obłoki pyłu

Large Magellanic Cloud (LMC)

Selekcja gwiazd dla LMC

Najpierw zostały wybrane gwiazdy znajdujące się w obszarze Large Magellanic Cloud.

Filtr współrzędnych:

WHERE

l BETWEEN 265 AND 295

AND

b BETWEEN -45 AND -20

Dodatkowo zastosowano filtry jakości:

  • brak nulli
  • limit jasności
  • poprawne proper motion
  • ograniczenie paralaksy

Przykład:

phot_g_mean_mag < 20
AND parallax < 0.3

Sampling danych

Do renderowania używany był sampling:

MAX_POINTS = 1_500_000

Pozwalało to skrócić obliczenia oraz zachować strukturę LMC przy zachowaniu płynności wykresu.

W finalnym renderze zostało załadowanych:

  • 8252 gwiazd

Lokalny układ współrzędnych

Współrzędne zostały przeliczone względem środka LMC:

LMC_L = 280.47
LMC_B = -32.89

Następnie utworzono lokalny układ:

x = (df["l"] - LMC_L)
y = (df["b"] - LMC_B)

Dzięki temu wykres był wycentrowany na obłoku Magellana.

Proper Motion i rekonstrukcja 3D

Do stworzenia pseudo-głębi wykorzystane zostały:

  • pozycje gwiazd
  • proper motion RA
  • proper motion DEC

Następnie zastosowano PCA:

pca = PCA(n_components=3)
components = pca.fit_transform(
motion_features
)

Trzeci komponent PCA został użyty jako:

  • pseudo depth
  • kinematic depth

czyli przybliżona głębokość struktury LMC.

Podstawowe wizualizacje są równocześnie optyczną walidacją datasetu.


Format danych

Finalny dataset został zapisany jako:

  • Apache Parquet
  • kompresja ZSTD
  • partycjonowane pliki (optymalny rozmiar około 200 MB)

To pozwala na:

  • szybkie filtrowanie
  • pracę z DuckDB
  • pracę z Polars
  • analizę bez ładowania całego datasetu do RAM

Wydajność ściągania

SQL ESA

  • ~500 mln rekordów
  • około 3 dni
  • tylko wybrane kolumny

CDN ESA

  • pełne Gaia DR3
  • wszystkie rekordy
  • wszystkie parametry
  • około 3 dni

CDN okazał się zdecydowanie lepszym rozwiązaniem dla pełnego mirroru Gaia DR3. Gaia TAP SQL natomiast jest opcją dla użytkowników bez stacji roboczych do wybiórczego ściągania danych do analizy.


Wnioski

  • Parquet + Polars + DuckDB daje ogromną wydajność
  • Gaia DR3 można trzymać lokalnie
  • walidacja MD5 jest konieczna przy ściąganiu za pomocą crawlera z cdn
  • CDN ESA jest dużo szybszy od TAP SQL przy ściąganiu dużej ilości danych
  • Plotly i matplotlib jest wystarczający do podstawowych interaktywnych map nieba
  • sampling jest konieczny przy miliardach rekordów

Następne kroki

Możliwe dalsze rozwinięcia:

  • 3D mapa Drogi Mlecznej
  • mapa pyłu galaktycznego
  • clustering gwiazd (UMAP)
  • spiral arm reconstruction
  • Wykresy HR

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *