Google Summer of Code 2018 final evaluation report

Link to GitHub repository: https://github.com/BoostGSoC18/geometry

The work is present under the following branches:


The goal of this project was to implement the direct and inverse geodesic algorithms in the Boost Geometry library. These methods were proposed by Charles Karney in his paper in 2011.

In a previous blog post, the inaccuracy of the existing methods was discussed, which provided inconsistent results for nearly antipodal points. To monitor the progress, a weekly report was provided through GitHub, which summarized the work done. Finally, benchmarks were performed against existing methods in Boost Geometry. The performance metric used was execution time and accuracy.

Additional material, such as utility scripts …

Using variadic templates with lambda expressions in C++ for constrained optimization

Constrained optimization problems are encountered in numerous domains, such as protein folding, Magnetic Resonance Image reconstruction, and radiation therapy. In this problem, we are given with an objective function which is to be minimized or maximized with respect to constraints on some variables. The constraints can either be soft constraints or hard constraints, which can be specified by boolean operators, such as equality, relational, and conditional operators.

This post provides insight on how to model constraints using lambda expressions, and how to pass a varying number of constraints to a function using variadic templates. Before moving on with the C++ implementation, it will be helpful to review how variadic functions are used in C and how they differ from the …

Inaccuracy in Boost Geometry geodesic algorithms for nearly antipodal points

Nearly antipodal points or antipodes refer to the most geographically distant points on a sphere, that is, the points are diametrically opposite to each other. If a line is drawn between these two points, it passes through the center of the sphere and forms its diameter.

Computing the great circle distance between these two points is often a corner case for most geodesic computations, and the distance is either overestimated or underestimated. In case of Vincenty's formulae, the solution fails to converge, or provides inaccurate results. This can have major implications in applications which rely on accurate results, such as flight navigation systems. The software can handle this either by doing an error analysis check and providing specific values through …

Parallel tile fetching and CPU-and-memory statistics

The hips package now supports parallel tile fetching. The user can achieve this either using the urllib or aiohttp package.

In case of aiohttp, the fetched tile data is coupled with HipsTileMeta to create a HipsTile object. This ensures there is no misalignment of tile data, otherwise, tiles could get swapped during the drawing period.

async def fetch_tile_aiohttp(url: str, meta: HipsTileMeta, session, timeout: float) -> HipsTile:
    """Fetch a HiPS tile asynchronously using aiohttp."""
    async with session.get(url, timeout=timeout) as response:
        raw_data = await response.read()
        return HipsTile(meta, raw_data)

We also limit the amount of simultaneously open connections using aiohttp.TCPConnector class. The returned object is passed to aiohttp.ClientSession's __init__ method. This procedure …

Google Summer of Code 2017 final evaluation report

Link to GitHub repository: http://github.com/hipspy/hips

In addition to the main hips repository, I also maintained my personal HIPS-to-Py repository on GitHub. This contains Jupyter notebooks which showcase the functionality in hips and numerous related Python scripts. The Wiki page contains a short description on hips. It also contains links to resource documents and telcon notes, which are hosted on Google Docs.

List of Pull Requests

Work related with HiPS tile drawing

Fixing tile distortion issue in hips package

As documented in the tile distortion issue section, the previous technique for drawing HiPS tiles brings some astrometry offsets for distorted tiles.

An example of such distortions can be viewed at this link (uncheck "Activate deformations reduction algorithm" to view the astrometry offsets): http://cds.unistra.fr/~boch/AL/test-reduce-deformations2.html

To overcome this issue, the parent tile is divided into four children tiles if it meets the following two criteria:

  • One edge is greater than 300 pixels when projected
  • Or, the ratio of smaller diagonal on larger diagonal is smaller than 0.7 and one of the diagonal is greater than 150 pixels when projected

For handling these checks, a function is_tile_distorted is introduced:

def is_tile …

RGB tile drawing in hips package

The hips package now supports RGB tile drawing. To make this possible, the output image dimensions had to be altered according to the following configuration:

The output image shape is two dimensional for grayscale, and three dimensional for color images:

  • shape = (height, width) for FITS images with one grayscale channel
  • shape = (height, width, 3) for JPG images with three RGB channels
  • shape = (height, width, 4) for PNG images with four RGBA channels

In addition to this, in-case of JPG and PNG format, the tiles are flipped in the vertical direction, which leads to incorrect tile drawing using the previous technique. The figure below is taken from the hips paper, figure 6, which shows the inverted tiles.

HiPS inverted tiles figure

To overcome this, the …

Parameterized testing using Pytest

Pytest provides a feature for parameterized testing in Python. The built-in pytest.mark.parametrize decorator enables parametrization of arguments for a test function. This allows the user to compare the values for input and output.

Here is a typical example which shows its usage:

get_hips_order_for_resolution_pars = [
    dict(tile_width=512, resolution=0.01232, resolution_res=0.06395791924665553, order=4),
    dict(tile_width=256, resolution=0.0016022, resolution_res=0.003997369952915971, order=8),
    dict(tile_width=128, resolution=0.00009032, resolution_res=0.00012491781102862408, order=13),

@pytest.mark.parametrize('pars', get_hips_order_for_resolution_pars)
def test_get_hips_order_for_resolution(pars):
    hips_order = _get_hips_order_for_resolution(pars['tile_width'], pars['resolution'])
    assert …

Creating custom decorators in Python 3.6

In the hips package, often data has to be fetched from remote servers, especially HiPS tiles. One way to cut back on the queries was by introducing the hips-extra repository. This contains HiPS tiles from various HiPS surveys. This allows us to quickly fetch tiles from local storage, which makes the testing process less time-consuming.

As hips-extra repository does not come with the standard hips package, user has to manually clone it. The availability of the package is checked using an environment variable. This can be set using:

$export HIPS_EXTRA=\path\to\hips-extra

In Python, the path can be retrieved using the os module: os.environ['HIPS_EXTRA']. Now, what if the user does not have …

HiPS tile drawing

One of the major part of the hips package is being able to draw HiPS tiles onto a larger sky image. This involves using projective transformation for computing and drawing a HiPS tile at the correct location. The discussion below is for the tile containing the galactic center pixel values. To achieve this, several steps are involved.

Computing boundaries of a HiPS tile

A tile is defined by four corners, hips uses the astropy_healpix.HEALPix.boundaries_skycoord function which returns the angle (\(\theta\) and \(\phi\)) in radians wrapped inside astropy.coordinates.SkyCoord class. This contains the four corners of a HiPS tile in the order (North, West, South, East). A snippet which computes the corners of a HiPS tile …

Type annotations in Python 3.6 and using Mypy as a static type checker

The main goal of type annotations is to open up Python code for static analysis. It makes it easier to debug and maintain code because each type is explicitly stated. It also makes the code review process simpler as the parameters and return types can be inferred from the function header. These changes were introduced in PEP 484.

In this regards, static type checking is the most important. It allows support for off-line third-party type checkers, such as Mypy, which will be introduced in a later section.

Purpose of annotations

The typing module in Python 3.6 contains many definitions that are useful in statically typed code. For instance, the Any type is used by default for every argument and …

An overview of Hierarchical Progressive Surveys (HiPS) and the HEALPix framework

The Hierarchical Progressive Surveys (HiPS) is a scheme for describing astronomical images and provides a solution for managing large amounts of data. Underneath, HiPS utilizes the HEALPix framework for mapping a sphere (in this case, part of a sky) and transforms it into HiPS tiles and HiPS pixels which contain the astronomical data. The HiPS scheme emphasizes on usability, and abstracts the scientific details to reach a wider audience. This can be further built upon for statistical analysis of large datasets. A brief overview of HEALPix is given below before moving onto the working of HiPS.

Introduction to HEALPix

HEALPix, an acronym of 'Hierarchical Equal Area isoLatitude Pixelization of a sphere', is a framework for discretizing high resolution data. It …

A comparison of response times using URLLib, GRequests, and asyncio

For the HiPS client multiple tiles have to be fetched for time efficiency. To achieve this, we create a separate thread for each outgoing request. Thus, requests are sent concurrently. A comparison is done utilizing Python's threading library. The elapsed time is calculated using the time module. For fetching the tiles urllib, grequests, aiohttp, and asyncio packages are used. The HiPS survey chosen for this comparison is alasky.u-strasbg.fr.

For fetching 10 tiles, it takes the following time (in seconds):

Elapsed Time URLLib (without concurrency): 3.5430831909179688
Elapsed Time URLLib (with concurrency): 0.388397216796875
Elapsed Time URLLib (with aiohttp): 0.3900480270385742
Elapsed Time GRequests: 1.6238431930541992

Similarly, for fetching 100 tiles, it takes:

Elapsed Time URLLib (without concurrency): 37 …

My First Article

Hello World!

This blog will be extensively used for posting GSoC updates, apart from other technical ramblings.