KBMOD Documentation

This notebook demonstrates the basics of the kbmod image processing and searching python API

Before importing, make sure to run
source setup.bash
in the root directory, and that you are using the python3 kernel.
Import everything with:


In [1]:
from kbmodpy import kbmod as kb
import numpy
path = "../data/demo/"

Object Types

There are currently 5 classes exposed to the python interface
psf
layered_image
image_stack
stack_search
trajectory

psf

A psf kernel, for convolution and adding artificial sources to images
Initializes to a gaussian given the width in pixels


In [2]:
p = kb.psf(1.0)

In [3]:
p.get_array()


---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-3-babbadbc1282> in <module>()
----> 1 p.get_array()

AttributeError: 'kbmod.psf' object has no attribute 'get_array'

There are several methods that get information about its properties


In [4]:
p.get_dim() # dimension of kernel width and height
p.get_radius() # distance from center of kernel to edge
p.get_size() # total number of pixels in the kernel
p.get_sum() # total sum of all pixels in the kernel, should be close to 1.0


Out[4]:
0.975315511226654

The entire kernel can be printed out (note: prints to the console, not the notebook)


In [5]:
p.print_psf()

layered_image

Stores the science, mask, and variance image for a single image. The "layered" means it contains all of them together.
It can be initialized 2 ways:
A. Generate a new image from scratch


In [2]:
im = kb.layered_image("image2", 100, 100, 5.0, 25.0, 0.0)
# name, width, height, background_noise_sigma, variance, capture_time

B. Load a file


In [7]:
im = kb.layered_image(path+"CORR40535777.fits")

Artificial objects can easily be added into a layered_image


In [8]:
im.add_object(20.0, 35.0, 2500.0, p)
# x, y, flux, psf

The image pixels can be retrieved as a 2D numpy array


In [9]:
pixels = im.science()
pixels


Out[9]:
array([[  2.28166199e+01,   6.30420532e+01,   1.63110748e+02, ...,
          7.00930725e+02,   7.09400024e+02,   7.12992859e+02],
       [  5.68100052e+01,   5.66378860e+01,   5.64662590e+01, ...,
          4.21070099e+01,   4.24052353e+01,   4.27034683e+01],
       [  7.16959906e+00,   5.70686722e+00,  -7.47076273e-01, ...,
          4.78974731e+02,   4.69988556e+02,   4.66543457e+02],
       ..., 
       [  2.35906372e+03,   2.31805493e+03,   2.26477246e+03, ...,
          2.29155615e+03,   2.36493823e+03,   2.33169312e+03],
       [  2.37056982e+03,   2.30898706e+03,   2.28240771e+03, ...,
          2.34917578e+03,   2.27273486e+03,   2.30295142e+03],
       [  2.31421606e+03,   2.29851660e+03,   2.37822192e+03, ...,
          2.27155884e+03,   2.27939673e+03,   2.27193042e+03]], dtype=float32)

The image can mask itself by providing a bitmask of flags (note: masked pixels are set to -9999.9 so they can be distinguished later from 0.0 pixles)


In [3]:
flags = ~0
flag_exceptions = [32,39]
# mask all of pixels with flags except those with specifed combiniations
im.apply_mask_flags( flags, flag_exceptions )

The image can be convolved with a psf kernel


In [26]:
im.convolve(p)
# note: This function is called interally by stack_search and doesn't need to be
# used directy. It is only exposed because it happens to be a fast 
# implementation of a generally useful function

The image at any point can be saved to a file


In [27]:
im.save_layers(path+"/out/") # file will use original name

Get properties


In [28]:
im.get_width()
im.get_height()
im.get_time()
im.get_ppi() # pixels per image, width*height


Out[28]:
8388608

image_stack

A collection of layered_images. Used to apply operations to a group of images.


In [13]:
count = 10
imlist = [ kb.layered_image("img"+str(n), 50, 50, 10.0, 5.0, n/count) for n in range(count) ]
stack = kb.image_stack( imlist )
# this creates a stack with 10 50x50 images, and times ranging from 0 to 1

A shortcut is provided to initialize a stack automatically from a list of files


In [30]:
import os
files = os.listdir(path)
files = [path+f for f in files if '.fits' in f]
files.sort()
files


Out[30]:
['../data/demo/CORR40535777.fits',
 '../data/demo/CORR40535787.fits',
 '../data/demo/CORR40535797.fits',
 '../data/demo/CORR40535807.fits',
 '../data/demo/CORR40535817.fits']

In [31]:
stack = kb.image_stack(files)

A master mask can be generated and applied to the stack


In [32]:
stack.apply_master_mask( int('100111', 2), 2 ) # flags, threshold
stack.save_master_mask("mask.fits")

Manually set the times the images in the stack were taken


In [15]:
stack.set_times( [0,2,3,4.5,5,6,7,10,11,14] )

Most features of the layered_image can be used on the whole stack


In [16]:
stack.apply_mask_flags(flags, flag_exceptions)
stack.convolve(p)
stack.get_width()
stack.get_height()
stack.get_ppi()
stack.get_images() # retrieves list of layered_images back from the stack
stack.get_times()


Out[16]:
[0.0, 2.0, 3.0, 4.5, 5.0, 6.0, 7.0, 10.0, 11.0, 14.0]

stack_search

Searches a stack of images for a given psf


In [11]:
search = kb.stack_search( stack, p )

To save psi and images, a directory with "psi" and "phi" folders must be specified.


In [12]:
search.save_psi_phi("/home/kbmod-usr/cuda-workspace/kbmod/search/output")

Launch a search


In [69]:
search.gpu(10, 10, 0.0, 1.0, 20.0, 50.0)
# angle_steps, velocity_steps, min_angle, max_angle, min_velocity, max_velocity

Save the results to a files
note: format is {x, y, xv, yv, likelihood, flux}


In [55]:
search.save_results(path+"results.txt", 0.05) 
# path, fraction of total results to save in file

Trajectories can be retrieved directly from search without writing and reading to file.
However, this is not recommended for a large number of trajectories, as it is not returned as a numpy array, but as a list of the trajectory objects described below


In [51]:
top_results = search.get_results(0, 100)
# start, count

trajectory

A simple container with properties representing an object and its path


In [52]:
best = top_results[0]

In [57]:
# these numbers are wild because mask flags and search parameters above were chosen randomly
best.flux 
best.lh
best.x
best.y
best.x_v
best.y_v


Out[57]:
2.8951690196990967

tests/test_search.py shows a simple example of how to generate a set of images, add an artificial source, and recover it with search


In [ ]: