The last couple of days I’ve spent a fair amount of time trying organising a number of diversity-related things for our upcoming collaboration meeting, and doing more admin than I can pretend to have enjoyed, so today’s note’s going to be a fairly short one, covering some work I did while helping a student using Bilby, the LSC’s new inference library (named, pleasingly, after an animal).

This post is unashamedly technical. Sorry.

Injecting numerical relativity signals with Bilby

All that bilby requires in order to produce a time-domain signal is a function which ingests a time (or an array of times), and returns a dictionary with the amplitude timeseries of the two gravitational wave polarisations for the signal.

Since NR data is distributed as discrete samples in a text file we’ll need to interpolate between the individual times in the file.

Normally these files contain the timestamps in the first column, and then the plus and cross polarisation amplitudes in the second and third columns, normally scaled in geometrised units.

The function below assumes the conversion to SI units has already been done, however, and that the waveforms are scaled correctly for injection.

def nr_injection(time, datafile):
    """
    This function produces the amplitude for a given 
    NR-derived signal at any given time for a given data file.
    
    Parameters
    ----------
    time : array-like
        A time, or an array of times, at which the amplitudes should be returned.
    datafile : str
        The path to the data file containing the injection.
    """
    
    data = np.genfromtxt(datafile)
    
    hp = np.interp(time, data[:,0], data[:,1])
    hx = np.interp(time, data[:,0], data[:,2])
    
    return {"plus": hp, "cross": hx}

With only a small amount of work it should be possible to rescale this for distance. I’m not in any hurry to start doing this, however, as there’s already support for this in Minke which is the Python package I originally developed for testing analysis pipelines in LIGO, but it produces correctly rescaled waveforms, including NR waveforms.

I’ve added an item to my to do list to make Minke explicitly compatible with the format expected by Bilby.

As far as I can tell Bilby doesn’t like having a waveform generator which needs a text argument, so I need to rely on a little functional programming here, and will make a “partial” to cope.

from functools import partial

nr_injection_partial = partial(nr_injection, datafile="./rescale-h_m16_L0.18_l2m2_r300.dat")

This basically just makes a new function which has the appropriate datafile hardwired into it.

Finally, this lets me make a Bilby waveform generator.

# call the waveform_generator to create our waveform model.
waveform = bilby.gw.waveform_generator.WaveformGenerator(
    duration=duration, sampling_frequency=sampling_frequency,
    time_domain_source_model=nr_injection_partial,
    start_time=-0.5)

Then the rest of the injection can be handled in the same way as in this example from the Bilby documentation.

# inject the signal into three interferometers
ifos = bilby.gw.detector.InterferometerList(['H1', 'L1'])
ifos.set_strain_data_from_power_spectral_densities(
    sampling_frequency=sampling_frequency, duration=duration,
    start_time=-0.5)
ifos.inject_signal(waveform_generator=waveform,
                   parameters=injection_parameters);
Share Share Share