Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

IRSA Tutorials

Strategies to Efficiently Work with NEOWISE Single-exposure Source Table in Parquet

An executed version of this notebook can be seen on IRSA’s website.

This notebook discusses strategies for working with the Apache Parquet version of the NEOWISE Single-exposure Source Table and provides the basic code needed for each approach. This is a very large catalog -- 11 years and 42 terabytes in total with 145 columns and 200 billion rows. Most of the work shown in this notebook is how to efficiently deal with so much data.

Learning Goals:

1. Introduction

The NEOWISE Single-exposure Source Table comprises 11 years of data. Each year on its own would be considered “large” compared to astronomy catalogs produced contemporaneously, so working with the full dataset requires extra consideration. In this Parquet version, each year is stored as an independent Parquet dataset. This tutorial shows how to combine them and work with all years as one. The data are partitioned by HEALPix (Górski et al., 2005) order k=5. HEALPix is a tessellation of the sky, so partitioning the dataset this way makes it especially efficient for spatial queries. In addition, the access methods shown below are expected to perform well when parallelized.

The terms “partition”, “filter”, and “slice” all relate to subsets of data. In this notebook we’ll use them with definitions that overlap but are not identical, as follows. A “partition” includes all data observed in a single HEALPix pixel. This data is grouped together in the Parquet files. A “filter” is a set of criteria defined by the user and applied when reading data so that only the desired rows are loaded. We’ll use it exclusively to refer to a PyArrow filter. The criteria can include partitions and/or any other column in the dataset. A “slice” is a generic subset of data. There are a few ways to obtain a slice; one is by applying a filter.

This notebook is expected to require about 2 CPUs and 50G RAM and to complete in about 10 minutes. These estimates are based on testing in science platform environments. Your numbers will vary based on many factors including compute power, bandwidth, and physical distance from the data. The required RAM and runtime can be reduced by limiting the number of NEOWISE years loaded.

1.1 When to use the Parquet version

IRSA provides large catalogs in file formats (e.g., Parquet) primarily to support use cases that require bulk access. The Parquet version of the NEOWISE Source Table, coupled with the methods demonstrated in this tutorial, are expected to be the most efficient option for large-ish use cases like classifying, clustering, or building light curves for many objects. In general, the efficiency will increase with the number of rows required from each slice because the slice only needs to be searched once regardless of the number of rows that are actually loaded. In addition, this access route tends to perform well when parallelized. Note that these use cases (including this notebook) are often too large for a laptop and may perform poorly and/or crash if attempted.

For small-ish use cases like searching for a handful of objects, other access routes like PyVO and TAP queries will be faster.

Consider using this tutorial if either of the following is true:

The basic process is:

  1. Load the catalog metadata as a PyArrow dataset.

  2. Decide how to slice the dataset (e.g., by year, partition, and/or file) depending on your use case.

  3. Iterate and/or parallelize over the slices. For each slice:

    1. Use the PyArrow dataset to load data of interest, applying row filters during the read.

    2. Process the data as you like (e.g., cluster, classify, etc.).

    3. Write your results to disk and/or return them for further processing.

  4. (Optional) Concatenate your results and continue processing.

This notebook covers steps 1 through 3.1 and indicates where to insert your own code to proceed with 3.2. Here we iterate over slices, but the same code can be parallelized using any multi-processing framework. A fully-worked example is shown in the light curve notebook linked below.

1.3 See also

2. Imports

3. Setup

3.1 Define variables and helper functions

Choose which NEOWISE years to include. Expect the notebook to require about 4G RAM and 1 minute of runtime per year.

Column and partition variables:

Paths:

Some representative partitions and files (see dataset stats in the Appendix for how we determine these values):

Convenience function for displaying a table size:

3.2 Load NEOWISE metadata as a pyarrow dataset

The metadata contains column names, schema, and row-group statistics for every file in the dataset. Later, we will use this pyarrow dataset object to slice and query the catalog in several different ways.

neowise_ds is a UnionDataset. All methods demonstrated for pyarrow datasets in the AllWISE demo notebook can be used with neowise_ds and will be applied to all years as if they were a single dataset. In addition, a separate Dataset for each year is stored in the list attribute neowise_ds.children (== year_datasets, loaded above), and the same methods can be applied to them individually.

4. Example: Slice by partition

This example shows how to load data from each partition separately. The actual “slicing” is done by applying a filter to the pyarrow dataset neowise_ds. Constructing filters was discussed in the AllWISE notebook linked above.

pixel_tbl is a (pyarrow) Table containing all NEOWISE sources with an ra/dec falling within HEALPix order 5 pixel pix. Use pixel_tbl.to_pandas() to convert the table to a pandas dataframe.

How big are the partitions? (see Appendix for details)

Often only a few columns are needed for processing, so most partitions will fit comfortably in memory. (The recommended maximum for an in-memory table/dataframe is typically 1GB, but there is no strict upper limit -- performance will depend on the compute resources available.)

However, beware that the largest partitions are quite large:

5. Example: Slice by file

If you don’t need data for all years at the same time, you may want to load individual files. Generally, there is 1 file per partition per year, but a few partitions are as large as 6+ files per year. Most of the files are about 0.3GB (compressed on disk) but about 1% are > 1GB. Thus it should be reasonable to load at least a subset of columns for every row in a file.

The actual “slicing” here is done by using neowise_ds to access a dataset Fragment (frag in the code below) which represents a single file.

This can be combined with the previous example to iterate over the files in a single partition (left as an exercise for the reader).

How big are the files?

6. Example: Slice by year

If you want to handle the years independently you can work with the per-year datasets. We actually created these “slices” in the Setup section with year_datasets, and that same list is now accessible in neowise_ds.children used below. Any of the techniques shown in this notebook or those listed under “See also” can also be applied to the per-year datasets.

Appendix

A.1 Considerations when extending to specific use cases

Because the catalog is so large, you will need to carefully consider your specific problem and determine how to slice and filter the data most efficiently. There is no one right answer; it will depend on the use case.

A.1.1 Filtering

Filter out as much data as possible as early as possible. Ideas to consider are:

  1. With the Parquet file format, you can apply filters during the read to avoid loading rows that you don’t need.

    • Pandas (not demonstrated here) supports basic filters.

    • PyArrow (demonstrated here) also supports complex filters which allow you to compare values between columns and/or construct new columns on the fly (e.g., subtracting magnitude columns to construct a new color column, as done in the AllWISE notebook).

  2. Queries (i.e., loading data by applying filters) will be much more efficient when they include a filter on the partitioning column (‘healpix_k5’; demonstrated above).

    • Notice both that this is essentially equivalent to slicing by partition and that you can filter for more than one partition at a time.

    • This is highly recommended even if your use case doesn’t explicitly care about it. Exceptions include situations where you’re working with individual files and when it’s impractical or counterproductive for the science.

  3. You should also include filters specific to your use case if possible.

  4. Exceptions: Sometimes it’s not easy to write a dataset filter for the query. A cone search is a common example. In principal it could be written as a PyArrow dataset filter, but in practice the correct formula is much too complicated. In this case, it’s easier to write dataset filters for broad RA and Dec limits and then do the actual cone search using astropy. This approach is still quite performant (see the NEOWISE light curves notebook).

A.1.2 Slicing

Slice the dataset in some way(s), then iterate and/or parallelize over the slices. Ideas to consider are:

  1. Choose your slices so that you can:

    • Run your processing code on one slice independently. For example, if your code must see all the data for some target object (RA and Dec) at the same time, you may slice the dataset by partition, but don’t slice it by year.

    • Load all data in the slice into memory at once (after applying your filters during the read). This notebook shows how to determine how big a slice of data is in order to guide this decision.

  2. By default, slice by partition. If this is too much data, you may also want to slice by year and/or file.

  3. If you have enough memory to load more than one slice simultaneously, parallelize over the slices to speed up your code.

A.2 Inspect dataset stats

When deciding how to slice and filter the dataset, it can be useful to understand dataset statistics like partition and file sizes.

A.2.1 Dataset statistics per file

A.2.2 Dataset statistics per partition


About this notebook

Updated: 2025-03-07

Contact: the IRSA Helpdesk with questions or reporting problems.

References
  1. Gorski, K. M., Hivon, E., Banday, A. J., Wandelt, B. D., Hansen, F. K., Reinecke, M., & Bartelmann, M. (2005). HEALPix: A Framework for High‐Resolution Discretization and Fast Analysis of Data Distributed on the Sphere. The Astrophysical Journal, 622(2), 759–771. 10.1086/427976