0

I am trying to plot some data from a .fits file that contains count rate vs time. My goal is to over plot the count rates of different events in the same plot, with different times on three different x-axis. As the events I want to plot are periodic, I imposed a condition on the identification of the right times, so I can extract count rates only from the time ranges I need. This is my effort:

#!/usr/bin/env python

from scipy import *
from numpy import *
from pylab import *
from scipy import optimize
import pyfits, os, re, glob
import matplotlib.pyplot as plt
import matplotlib as mpl
from matplotlib.ticker import FuncFormatter

rc('font',**{'family':'serif','serif':['Helvetica']})
rc('ps',usedistiller='xpdf')
rc('text', usetex=True)

#------------------------------------------------------

tmin=56200
tmax=56249

data=pyfits.open('http://heasarc.gsfc.nasa.gov/docs/swift/results/transients/weak/GX304-1.orbit.lc.fits')

time  = data[1].data.field(0)/86400. + data[1].header['MJDREFF'] + data[1].header['MJDREFI']
rate  = data[1].data.field(1)
error = data[1].data.field(2)
data.close()

cond= ((time > tmin-5) & (time < tmax)) | ((time + 132.5 > tmin) & (time + 132.5 < tmax-10)) | ((time + 265 > tmin) & (time + 265 < tmax-12))
time=time[cond]
rate=rate[cond]
error=error[cond]

fig, ax1 = plt.subplots()
newax2 = ax1.twiny()
newax3 = ax1.twiny()

# Make some room at the bottom
fig.subplots_adjust(bottom=0.30)

newax2.set_frame_on(True)
newax2.patch.set_visible(False)
newax2.xaxis.set_ticks_position('bottom')
newax2.xaxis.set_label_position('bottom')
newax2.spines['bottom'].set_position(('outward', 20))

newax3.set_frame_on(True)
newax3.patch.set_visible(False)
newax3.xaxis.set_ticks_position('bottom')
newax3.xaxis.set_label_position('bottom')
newax3.spines['bottom'].set_position(('outward', 40))

#..plot the current light curve
errorbar(time, rate, error, fmt='r.', capsize=0)
gca().xaxis.set_major_formatter(FormatStrFormatter('%5.1f'))

#..overplot a previous outburst
errorbar(time + 122.5, rate, error, fmt='g.', capsize=0)
errorbar(time + 255, rate, error, fmt='k.', capsize=0)

axis([tmin-10,tmax,-0.00,0.45])
xlabel('Time, MJD')
ylabel("BAT cts/s/cm$^2$")
savefig("sync.eps",orientation='portrait',papertype='a4',format='eps')
os.system('gv sync.eps')

I am plotting three events, so I need three x-axis; however, I would like to write the correspective times on the x-axis with the correspective color too, if possible. The time reported on the bottom line is the correct one for the red curve, that is the most recent event. Any suggestions, please? Many thanks in advance.

Py-ser
  • 1,860
  • 9
  • 32
  • 58
  • Does [this question and answers](http://stackoverflow.com/questions/1982770/matplotlib-changing-the-color-of-an-axis) help? –  Mar 14 '13 at 14:31
  • Thanks for the reply Evert. However, I need to "redefine" the x-axis too, to show the right times for each series of data. And I think this is more tricky than just change the colors on the axis. Anyway, soon or after I will need that part too. – Py-ser Mar 14 '13 at 14:44
  • Btw, is there a reason you don't let matplotlib/pylab display the figure for you, but you run it through gv? You can then save the file from the pylab interactive figure window. Or is pylab that badly configured on your system that you can't use this interactive approach? –  Mar 14 '13 at 15:13

1 Answers1

0

If I understand your question correctly, the problem are the incorrect ticks on the first and second x axes. You should simply tie the errorbar functions to the correct axis, and then matplotlib will do the scaling for you. Like this:

...
#..plot the current light curve
ax1.errorbar(time, rate, error, fmt='r.', capsize=0)
gca().xaxis.set_major_formatter(FormatStrFormatter('%5.1f'))

#..overplot a previous outburst
newax2.errorbar(time + 122.5, rate, error, fmt='g.', capsize=0)
newax3.errorbar(time + 255, rate, error, fmt='k.', capsize=0)
...

I generally prefer the more object-oriented approach in matplotlib anyway, so then this is the only way to do it.

I'll leave the colouring part to the reference in my comment, if you don't mind.

Update

Below is some updated code; perhaps this is what you're looking for. The trick is to not move the x data (time), but simply shift the x limits (the "window" you're looking at) to what you want. So I applied the 122.5 and 255 offsets (reversed) to the x limits of each axes separately.

I also had to set the formatter for each axes separately; if I don't set the formatter, you end up with, for example, an offset notation (0 .. 10 .. 20 .. 30 + 56190). Using the global formatter like you had, works (I think) only on ax1. Note that I only set the y limits globally, commenting out the axis command.

...
##..plot the current light curve
ax1.errorbar(time, rate, error, fmt='r.', capsize=0)
ax1.set_xlim(tmin-10,tmax)
ax1.xaxis.set_major_formatter(FormatStrFormatter('%5.1f'))
##..overplot a previous outburst
newax2.errorbar(time, rate, error, fmt='g.', capsize=0)
newax3.errorbar(time, rate, error, fmt='k.', capsize=0)
newax2.set_xlim(tmin-10-122.5,tmax-122.5)
newax2.xaxis.set_major_formatter(FormatStrFormatter('%5.1f'))
newax3.set_xlim(tmin-10-255,tmax-255)
newax3.xaxis.set_major_formatter(FormatStrFormatter('%5.1f'))
ylim(0,0.45)
#axis([tmin-10,tmax,-0.00,0.45])
...

This results in enter image description here which is what your original script produces, but with a hopefully correct set of x-axes (apart from the colouring).

  • Thanks again Evert. The problem is that, following your suggestion, I don't obtain an "overplotting", but a "multi-plot", like it is showed here: http://tinypic.com/view.php?pic=15zlcht&s=6 – Py-ser Mar 14 '13 at 16:16
  • Well, the data are overplotted into a single graph; what else do you mean by overplotted then? A multi-plot has, as far as my definition goes, multiple graphs, and your figure doesn't have that. –  Mar 14 '13 at 16:26
  • If you run the original code I wrote, you can get an idea of what I nedd and what, insted, I obtain with "multi-plot" – Py-ser Mar 14 '13 at 16:40
  • @Py-ser: I've updated my answer; let me know if this is what you were looking for. –  Mar 15 '13 at 11:13
  • Yes, Evert, this is what I needed. So, it is not necessary to directly input different sets of data, but just to shift the window where to take the x-axis data. Nice! Thanks really a lot! – Py-ser Mar 18 '13 at 13:56
  • Yes, for creating the plot, this actually works best. If you want to perform calculations on the data, you'll of course have to time-shift the actual data. I didn't think about shifting the window initially, because I was confused how it almost worked for you with the global `errorbar` command. I think keeping the data to the actual axis is clearer anyway. –  Mar 18 '13 at 14:53
  • Btw, feel free to accept the answer, so that future visitors that may have a similar problem know that this is (likely) the solution to their problem. –  Mar 18 '13 at 14:53