RAPID

RAPID (Real-time Automated Photometric IDentification) can classify multiband photometric light curves into several different transient classes. It uses a deep recurrent neural network to produce time-varying classifications.

_images/classification_vs_time.gif

Installation

Using pip

The easiest and preferred way to install DASH (to ensure the latest stable version) is using pip:

pip install astrorapid --upgrade

From Source

Alternatively, the source code can be downloaded from GitHub by running the following command:

git clone https://github.com/daniel-muthukrishna/astrorapid.git

Dependencies

Using pip to install astrorapid will automatically install the mandatory dependencies: numpy, tensorflow, keras, astropy, pandas, extinction, and scikit-learn.

If you wish to plot your classifications or train your own classifier with your data you will need matplotlib and scipy as well. These can be installed with

pip install matplotlib
pip install scipy

Platforms

RAPID can be run on both Python 2 and Python 3 distributions. It is also cross-platform, working on Mac, Windows, and Linux distributions. If you have any issues, please submit an issue at https://github.com/daniel-muthukrishna/astrorapid/issues.

Usage

Classify Light curves

Use the following example code:

from astrorapid.classify import Classify

# Each light curve should be a tuple in this form. Look at the example code for an example of the input format.
light_curve_info1 = (mjd, flux, fluxerr, passband, photflag, ra, dec, objid, redshift, mwebv)
light_curve_list = [light_curve_info1,]
contextual_info_list = [{'hosttype': value},]  # Only use this parameter if you have trained your own classifer with specific meta data. Otherwise set to None.

# Classify Light curves
classification = Classify(known_redshift=True)
predictions = classification.get_predictions(light_curve_list, contextual_info_list)
print(predictions)

# Plot light curve and classification vs time of the light curves at the specified indexes
classification.plot_light_curves_and_classifications(indexes_to_plot=(0,1,4,6))
classification.plot_classification_animation(indexes_to_plot=(0,1,4,6))

Train your own classifier with your own data

You’ll simply need to run the function astrorapid.custom_classifier.create_custom_classifier() to get started with training your own classifier. An example is shown below.

from astrorapid.custom_classifier import create_custom_classifier

script_dir = os.path.dirname(os.path.abspath(__file__))

create_custom_classifier(get_data_func=astrorapid.get_training_data.get_data_from_snana_fits,
                         data_dir=os.path.join(script_dir, '..', 'data/ZTF_20190512'),
                         class_nums=(1, 2, 12, 14, 3, 13, 41, 43, 51, 60, 61, 62, 63, 64, 70),
                         class_name_map={1: 'SNIa-norm', 2: 'SNII', 12: 'SNII', 14: 'SNII', 3: 'SNIbc', 13: 'SNIbc', 41: 'SNIa-91bg', 43: 'SNIa-x', 51: 'Kilonova', 60: 'SLSN-I', 61: 'PISN', 62: 'ILOT', 63: 'CART', 64: 'TDE', 70: 'AGN'},
                         reread_data=False,
                         contextual_info=('redshift', 'some_contextual_info1'),
                         passbands=('g', 'r'),
                         retrain_network=False,
                         train_epochs=100,
                         zcut=0.5,
                         bcut=True,
                         ignore_classes=(61, 62, 64, 70),
                         nprocesses=None,
                         nchunks=10000,
                         otherchange='',
                         training_set_dir='data/training_set_files',
                         save_dir='data/saved_light_curves',
                         fig_dir='data/training_set_files/Figures'),
                         plot=True
                         )

You’ll need to write your own function get_data_func to read your data and use the astrorapid preprocessing tools. Use the skeleton function here astrorapid.get_custom_data.get_custom_data(), or as rewritten below.

def get_custom_data(class_num, data_dir, save_dir, passbands, known_redshift, nprocesses, redo):
    """
    Get data from custom data files.
    You will need to write this function with the following skeleton function:

    Parameters
    ----------
    class_num : int
        Class number. E.g. SNIa is 1. See helpers.py for lookup table.
        E.g. class_num = 1
    data_dir : str
        Directory where data is stored
        E.g. data_dir='data/ZTF_20190512/'
    save_dir : str
        Directory to save processed data
        E.g. save_dir='data/saved_light_curves/'
    passbands : tuple
        Passbands to use.
        E.g. passbands=('g', 'r')
    known_redshift : bool
        Whether to correct the light curves for cosmological time dilation using redshift.
    nprocesses : int or None
        Number of processes to use
    redo : bool
        Whether to redo reading the data and saving the processed data.


    Returns
    -------
    light_curves : dict of astropy.table.Table objects
        e.g light_curves['objid1'] =
            passband   time       flux     fluxErr   photflag
              str1   float32    float32    float32    int32
            -------- -------- ----------- ---------- --------
                   g -46.8942  -48.926975  42.277767        0
                   g -43.9352  -105.35379   72.97575        0
                   g -35.9161  -46.264206    99.9172        0
                   g -28.9377  -28.978344  42.417065        0
                   g -25.9787  109.886566   46.03949        0
                   g -15.0399    -80.2485   80.38155        0
                   g -12.0218    93.51743  113.21529        0
                   g  -6.9585   248.88364 108.606865        0
                   g  -4.0411   341.41498  47.765404        0
                   g      0.0    501.7441   45.37485     6144
                 ...      ...         ...        ...      ...
                   r  40.9147   194.32494  57.836903     4096
                   r  59.9162    67.59185   45.66463     4096
                   r  62.8976    80.85155  44.356197     4096
                   r  65.8974   28.174305   44.75049     4096
                   r  71.8966  -18.790287 108.049774     4096
                   r  74.9297  -3.1707647  125.15057     4096
                   r  77.9341 -11.0205965 125.784676     4096
                   r  80.8576   129.65466   69.99305     4096
                   r  88.8922  -14.259436  52.917866     4096
                   r 103.8734   27.178356 115.537704     4096

    """

    # If the data has already been run and processed load it. Otherwise read it and save it
    save_lc_filepath = os.path.join(save_dir, f"lc_classnum_{class_num}.pickle")
    if os.path.exists(save_lc_filepath) and not redo:
        with open(save_lc_filepath, "rb") as fp:  # Unpickling
            light_curves = pickle.load(fp)
    else:
        light_curves = {}
        # Read in data from data_dir and get the mjd, flux, fluxerr, passband, photflag as 1D numpy arrays for
        # each light curve. Get the ra, dec, objid, redshift, mwebv, model_num, peak_mjd as floats or strings.
        # Set whether you'd like to train a model with a known redshift or not. Set known_redshift as a boolean.

        # Enter your own data-reading code here that gets the mjds, fluxes, fluxerrs, passbands, photflags,
        # ras, decs, objids, redshifts, mwebvs, model_nums, peak_mjds for all the light curves from the data_dir

        # Once you have the required data information for each light curve, pass it into InputLightCurve with
        # something like the following code:
        for i, objid in enumerate(objids):
            inputlightcurve = InputLightCurve(mjds[i], fluxes[i], fluxerrs[i], passbands[i], photflags[i],
                                              ras[i], decs[i], objids[i], redshifts[i], mwebvs[i],
                                              known_redshift=known_redshift,
                                              training_set_parameters={'class_number': int(class_num),
                                                                       'peakmjd': peakmjds[i]},
                                              other_meta_data={'some_contextual_info1': value})
            light_curves[objid] = inputlightcurve.preprocess_light_curve()

        # If you think that reading the data is too slow, you may want to replace the for loop above with
        # multiprocessing. See the example function in get_training_data.py if you need help doing this.

        # Next, we save it:
        with open(save_lc_filepath, "wb") as fp:  # Pickling
            pickle.dump(light_curves, fp)

    return light_curves

Example

Example script classifying an example supernova light curve.

from astrorapid.classify import Classify

# Light curve information. It may be easier if this is read from a file and later manipulated into this format.
mjd = [57433.4816, 57436.4815, 57439.4817, 57451.4604, 57454.4397, 57459.3963, 57462.418 , 57465.4385, 57468.3768, 57473.3606, 57487.3364, 57490.3341, 57493.3154, 57496.3352, 57505.3144, 57513.2542, 57532.2717, 57536.2531, 57543.2545, 57546.2703, 57551.2115, 57555.2669, 57558.2769, 57561.1899, 57573.2133,57433.5019, 57436.4609, 57439.4587, 57444.4357, 57459.4189, 57468.3142, 57476.355 , 57479.3568, 57487.3586, 57490.3562, 57493.3352, 57496.2949, 57505.3557, 57509.2932, 57513.2934, 57518.2735, 57521.2739, 57536.2321, 57539.2115, 57543.2301, 57551.1701, 57555.2107, 57558.191 , 57573.1923, 57576.1749, 57586.1854]
flux = [2.0357230e+00, -2.0382695e+00,  1.0084588e+02,  5.5482742e+01,  1.4867026e+01, -6.5136810e+01,  1.6740545e+01, -5.7269131e+01,  1.0649184e+02,  1.5505235e+02,  3.2445984e+02,  2.8735449e+02,  2.0898877e+02,  2.8958893e+02,  1.9793906e+02, -1.3370536e+01, -3.9001358e+01,  7.4040916e+01, -1.7343750e+00,  2.7844931e+01,  6.0861992e+01,  4.2057487e+01,  7.1565346e+01, -2.6085690e-01, -6.8435440e+01, 17.573107  ,   41.445435  , -110.72664   ,  111.328964  ,  -63.48336   ,  352.44907   ,  199.59058   ,  429.83075   ,  338.5255    ,  409.94604   ,  389.71262   ,  195.63905   ,  267.13318   ,  123.92461   ,  200.3431    ,  106.994514  ,  142.96387   ,   56.491238  ,   55.17521   ,   97.556946  ,  -29.263103  ,  142.57687   ,  -20.85057   ,   -0.67210346,   63.353024  ,  -40.02601]
fluxerr = [42.784702,  43.83665 ,  99.98704 ,  45.26248 ,  43.040398,  44.00679 ,  41.856007,  49.354336, 105.86439 , 114.0044  ,  45.697918,  44.15781 ,  60.574158,  93.08788 ,  66.04482 ,  44.26264 ,  91.525085,  42.768955,  43.228336,  44.178196,  62.15593 , 109.270035, 174.49638 ,  72.6023  ,  48.021034, 44.86118 ,  48.659588, 100.97703 , 148.94061 ,  44.98218 , 139.11194 ,  71.4585  ,  47.766987,  45.77923 ,  45.610615,  60.50458 , 105.11658 ,  71.41217 ,  43.945534,  45.154167,  43.84058 ,  52.93122 ,  44.722775,  44.250145,  43.95989 ,  68.101326, 127.122025, 124.1893  ,  49.952255,  54.50728 , 114.91599]
passband = ['g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r']
photflag = [0,    0,    0,    0,    0,    0,    0,    0,    0,    0, 4096, 4096,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, 0,    0,    0,    0,    0,    0,    0,    0,    0, 4096, 6144, 4096, 4096, 4096, 0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, 0,    0,    0,    0]
objid = 'transient_1'
ra = 3.75464531293933
dec = 0.205076187109334
redshift = 0.233557
mwebv = 0.0228761

light_curve_info1 = (mjd, flux, fluxerr, passband, photflag, ra, dec, objid, redshift, mwebv)

# Classification
light_curve_list = [light_curve_info1,]  # Add more light curves to be classified to this list.

classification = Classify(known_redshift=True)
predictions = classification.get_predictions(light_curve_list)
print(predictions)

# Plot classifications vs time
classification.plot_light_curves_and_classifications()
classification.plot_classification_animation()

API

RAPID has a few important classes and methods.

Classify light curves

  • astrorapid.classify.Classify - Setup light curve classification
  • astrorapid.classify.Classify.get_predictions() - Classify light curves!

Plot classifications

  • astrorapid.classify.Classify.plot_light_curves_and_classifications() - Plot light curves and classifications
  • astrorapid.classify.Classify.plot_classification_animation() - Plot animation of light curves and classifications

Train your own classifier

  • astrorapid.get_custom_data.get_custom_data() - Read custom data files and save preprocessed light curves.
  • astrorapid.custom_classifier.create_custom_classifier() - Run preprocessing and train neural network classification model.

The full documentation of useful classes and methods can be found below.

Full Documentation









Support

If you are having issues, please let us know by submitting a GitHub issue at https://github.com/daniel-muthukrishna/astrorapid/issues

License

The project is licensed under the MIT license.

Citation

You can cite the following paper for this work: https://ui.adsabs.harvard.edu/abs/2019arXiv190400014M/abstract

Author

Daniel Muthukrishna http://www.danielmuthukrishna.com