|Ask a Question||Search PSRCHIVE:|
PSRCHIVE Python Interface
This is a draft user's manual for the PSRCHIVE Python interface.
Suggestions and contributions are welcome!
In addition to the standard PSRCHIVE dependencies, the Python interface requires a small number of additional external programs or libraries. The minimum requirements are:
Not strictly required, but very useful are:
The Python interface comes with the standard PSRCHIVE distribution. It requires PSRCHIVE shared libraries to be built. The Python interface will be compiled and installed automatically when the --enable-shared option is given to configure, and the necessary external software (see above) is found. Refer to the standard installation instructions for more information.
If the installation was successful, running import psrchive in Python should not return an error.
The basic way the interface works is to provide Python programs with access to the C++ classes that PSRCHIVE is built on. Currently, only the core PSRCHIVE classes - Archive, Integration, and Profile - are represented in Python. However, these three classes alone provide access to a very large fraction of PSRCHIVE's functionality. Detailed documentation about the class methods can be found in the C++ Library Reference Manual.
In addition to the C++ methods, each of these classes has some extra Python-specific functionality added to it:
An Archive object represents a single data file, and contains a collection of Integration objects, also known as subintegrations. An Archive can be loaded into python using the Archive_load function, as demonstrated in the following IPython session:
In : import psrchive In : arch = psrchive.Archive_load('file.fits') In : arch.get_source() Out: '1744-1134'
The get_data() method is an extra Python function that returns the raw data from the file as a NumPy array:
In : data = arch.get_data() In : data.shape Out: (10, 4, 2048, 256)The dimensions of the data array are subintegration, polarization, channel, and profile bin. Important note: The get_data() function returns a copy of the Archive data. So changes made to the returned array will not be reflected in the Archive, and vice-versa.
Integrations within an Archive can be accessed in Python by indexing the Archive object. So the following two lines are equivalent:
In : subint = arch.get_Integration(0) In : subint = arch
An Integration object represents a collection of pulse profiles recorded simultaneously, typically from a number of frequency channels and polarization states (Stokes parameters):
In : subint.get_duration() Out: 60.230205439999999 In : subint.get_nchan() Out: 2048
The existing baseline_stats() and cal_levels() methods have been modified for Python to return tuples of arrays, for example:
In : (b_mean, b_var) = subint.baseline_stats() In : b_mean.shape Out: (4, 2048)
An Integration object contains a number of pulse profiles that can be accessed via get_Profile(ipol,ichan):
In : prof = subint.get_Profile(0,0)
A Profile object represents a single pulse profile. The get_amps() method returns the profile data as a NumPy array:
In : pdata = prof.get_amps() In : pdata.shape Out: (256,)In contrast to the arch.get_data() example above, the pdata array here points into the actual C++ data structure. So changes made to the array values will be reflected in the underlying Profile object.
The profile data values can also be read and/or altered by indexing the Profile object directly, for example:
In : pdata Out: 91.366058 In : prof Out: 91.366058349609375 In : prof = 500.0 In : pdata Out: 500.0
The MJD class is also now available in Python to deal with high-precision date/time values. Return values for date/time functions such as Integration.get_epoch() were previously converted to doubles for convenience. To reproduce the old behavior and get a double-precision MJD value, use the MJD.in_days() method, for example:
mjd_dbl = arch.get_Integration(0).get_start_time().in_days()
In this example, we recreate the helpful "pav -GTdp" plot using python, and demonstrate some common psrchive functionality:
#! /usr/bin/env python import pylab import psrchive arch = psrchive.Archive_load('1744_0001_0001.fits') arch.bscrunch_to_nbin(256) arch.dedisperse() arch.fscrunch_to_nchan(512) arch.remove_baseline() arch.convert_state('Stokes') data = arch.get_data() freq_lo = arch.get_centre_frequency() - arch.get_bandwidth()/2.0 freq_hi = arch.get_centre_frequency() + arch.get_bandwidth()/2.0 pylab.imshow(data[:,0,:,:].mean(0),extent=(0,1,freq_lo,freq_hi)) pylab.xlabel('Pulse phase') pylab.ylabel('Frequency (MHz)') pylab.savefig('python_plot_example.png')
This results in the following plot: