Sonifying LSD profiles#

The sonification of images is one way to diversify the accessibility of astrophysical data. The idea is to produce an audio representation of data in addition to a visual representation.

Here we provide an example of how to sonify an LSD profile.

Note

This tutorial makes use of the astronify package, which will need to be installed separately.
You can read more about astronify here.

0. Import specpolFlow, astronify, and other packages#

import astronify as snd
import specpolFlow as pol
from astropy.table import Table
import numpy as np

1. sono_lsd Function#

First we define the function sono_lsd, which uses the astronify package. Feel free to modify this function for your specific data!

def sono_lsd(lsd):
    ''' 
    Creates a sonification of a LSD profile object. 
    '''

    # The astronify package requires astropy tables. 
    # data_table_I = Table({"vel":lsd.vel, "Stokes":lsd.specI})
    # data_table_N1 = Table({"vel":lsd.vel, "Stokes":lsd.specN1})
    # data_table_V = Table({"vel":lsd.vel, "Stokes":lsd.specV})

    sigmaN = np.std(lsd.specN1) # The stdev of N1:
    maxV = np.max(np.abs(lsd.specV)) # The max of V
    # We clip the sound range at either 5 times the deviation of N
    # (in the case where StokesV is not detected) 
    # or to the max value of Stokes V
    clip = np.max([5*sigmaN, maxV])

    data_table = Table({"vel":lsd.vel, "stokes":lsd.specI})
    data_soni = snd.series.SoniSeries(data_table, time_col='vel', val_col='stokes')
    data_soni.note_spacing = 0.02
    data_soni.pitch_mapper.pitch_map_args["zero_point"] = 1.0
    data_soni.pitch_mapper.pitch_map_args['minmax_value'] = [0.5, 1.5]
    data_soni.pitch_mapper.pitch_map_args['pitch_range'] = [100, 700]
    data_soni.pitch_mapper.pitch_map_args['center_pitch'] = 400
    data_soni.sonify()
    data_soni.play() 
    data_soni.write('I.wav')

    for i, Stokes in enumerate([lsd.specN1, lsd.specV]):

        data_table = Table({"vel":lsd.vel, "stokes":Stokes})
        data_soni = snd.series.SoniSeries(data_table, time_col='vel', val_col='stokes')
        data_soni.note_spacing = 0.02
        data_soni.pitch_mapper.pitch_map_args["zero_point"] = 0.0
        data_soni.pitch_mapper.pitch_map_args['minmax_value'] = [-1*clip, clip]
        data_soni.pitch_mapper.pitch_map_args['pitch_range'] = [100, 700]
        data_soni.pitch_mapper.pitch_map_args['center_pitch'] = 400
        data_soni.sonify()
        data_soni.play() 
        if i==0:
            data_soni.write('N1.wav')
        else:
            data_soni.write('V.wav')

    
    return(data_soni)

Then we run our custom function on an example LSD profile.

lsd = pol.read_lsd('CalculateBz_tutorialfiles/SampleLSD.lsd')
lsd = lsd[np.logical_and(lsd.vel>-50,lsd.vel<150)]
fig, ax = lsd.plot()


data_soni = sono_lsd(lsd)

# The sono_lsd function already does these things, 
# but you can repeat them using the returned object
# data_soni.sonify()
# data_soni.play() 
# data_soni.write('N1.wav')