source: branches/GUIdev/OutputGUI/SpectralGraph.py @ 1441

Last change on this file since 1441 was 1344, checked in by KelvinHsu, 10 years ago

Initial Commit

File size: 10.3 KB
Line 
1#-------------------------------------------------------------------------------
2# Name:        SpectralGraph
3# Purpose:
4#
5# Author:      Kelvin
6#
7# Created:     02/01/2014
8#-------------------------------------------------------------------------------
9
10import matplotlib.pyplot as plt
11import matplotlib.widgets as mwidgets
12import matplotlib.cm as cm
13
14from matplotlib.figure import Figure
15from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
16
17from numpy import *
18
19from PyQt4 import QtCore
20
21import pywcs
22
23class SpectralGraph(FigureCanvas):
24
25    def __init__(self, Results, maskFits, realFits, maskImage):
26
27        # Create the figure containing our final image
28        self.fig = Figure()
29
30        self.channelText = self.fig.text(0.9, 0.15, '')
31        self.velocityText = self.fig.text(0.9, 0.30, '')
32        self.intensityText = self.fig.text(0.9, 0.45, '')
33
34        self.descriptionText = self.fig.text(0.65, 0.95, '')
35
36        self.ax = self.fig.add_subplot(111)
37        self.ax.cla()
38        #self.ax.plot(arange(0, self.lenZ), zeros(self.lenZ))
39        self.ax.set_xlabel('Frequency Channels (GHz)')
40        self.ax.set_ylabel('Intensity (mJ)')
41        self.spectralTitle = self.fig.suptitle("Spectral Characteristic")
42
43        # Initialise the parent class
44        FigureCanvas.__init__(self, self.fig)
45
46        self.Results = Results
47
48        # Those are our data cubes
49        self.maskCube = maskFits[0].data
50        self.realCube = realFits[0].data
51
52        self.maskImage = maskImage
53
54        # Those are the size of our data cubes
55        [self.lenZ, self.lenY, self.lenX] = self.maskCube.shape
56
57        self.maskHeader = maskFits[0].header
58
59        hdr = bytes(self.maskHeader.tostring(), 'utf-8')
60
61        imwcs = pywcs.WCS(header = hdr)
62
63        self.freq = arange(0, self.lenZ)
64
65        self.vel = imwcs.wcs.crval[2] + imwcs.wcs.cdelt[2]*(self.freq - imwcs.wcs.crpix[2])
66
67        self.velunit = str(imwcs.wcs.cunit[2], 'utf-8')
68       
69        self.zAxis = 'vel'
70
71        fx = maskFits[0].header.get('BMAJ')
72        fy = maskFits[0].header.get('BMIN')
73
74        self.C = pi*fx*fy/(4*log(2))
75
76        self.zmin = 0
77        self.zmax = self.lenZ
78
79        self.currentObjID = 0
80
81        self.spectralType = 'max'
82
83        self.trackCursorLink = self.mpl_connect('motion_notify_event', self.trackCursor)
84        self.changeZaxisLink = self.mpl_connect('button_press_event', self.changeZaxis)
85
86        self.intensityUnit = 'Jy/beam'
87        self.draw()
88        self.show()
89
90    def plotMax(self):
91
92        self.spectralType = 'max'
93        self.intensityUnit = 'Jy/beam'
94        self.plotSource()
95
96    def plotSum(self):
97
98        self.spectralType = 'sum'
99        self.intensityUnit = 'Jy'
100        self.plotSource()
101
102    def changeZaxis(self, event):
103
104        if event.button != 1:
105            return
106
107        if self.zAxis == 'vel':
108            self.zAxis = 'freq'
109        else:
110            self.zAxis = 'vel'
111
112        self.plotSource()
113
114    def setCurrentObjID(self, ObjID):
115
116        self.currentObjID = ObjID
117
118    def trackCursor(self, event):
119
120        if not event.inaxes:
121            return
122
123        self.channelText.set_text('Freq. Channel: %d'%(int(event.xdata)))
124        self.velocityText.set_text('Velocity: %.3f k%s'%(self.vel[int(event.xdata)]/1000, self.velunit))
125        self.intensityText.set_text('Intensity: %.3f %s'%(event.ydata, self.intensityUnit))
126        self.draw()
127
128    def plotSource(self):
129
130        self.ax.cla()
131             
132        if self.currentObjID <= 0 or (self.spectralType != 'max' and self.spectralType != 'sum'):
133            self.draw()
134            return
135           
136       
137        ObjStats = self.Results.SkyObjects[self.currentObjID].stats     
138       
139        if self.spectralType == 'max':
140
141            x_peak = ObjStats['X_peak']
142            y_peak = ObjStats['Y_peak']
143            flux = self.realCube[:, y_peak, x_peak]
144
145            self.descriptionText.set_text('Peak Intensity occurs at (x, y) = (%d, %d)'%(x_peak, y_peak))
146           
147            self.intensityUnit = 'Jy/beam'
148            self.ax.set_ylabel('Intensity (%s)'%self.intensityUnit)
149
150        elif self.spectralType == 'sum':
151
152            flux = zeros(self.freq.shape)
153           
154            x1 = ObjStats['X1']
155            x2 = ObjStats['X2']
156            y1 = ObjStats['Y1']
157            y2 = ObjStats['Y2']
158
159            for x in range(x1, x2 + 1):
160                for y in range(y1, y2 + 1):
161
162                    if self.maskImage[y][x] == self.currentObjID:                       
163
164                        flux += self.realCube[:, y, x]
165
166            flux = self.C*flux
167
168            self.intensityUnit = 'Jy'
169            self.ax.set_ylabel('Intensity (%s)'%self.intensityUnit)
170
171        self.spectralTitle.set_text("Spectral Characteristic of Source " + str(self.currentObjID))
172
173        self.linef1 = self.ax.axvline(x = self.Results.zf1, color = "r")
174        self.linef2 = self.ax.axvline(x = self.Results.zf2, color = "r")
175
176        z1 = ObjStats['Z1']
177        z2 = ObjStats['Z2']
178
179        self.linef1 = self.ax.axvline(x = z1, color = "g", linestyle = "--")
180        self.linef2 = self.ax.axvline(x = z2, color = "g", linestyle = "--")
181
182        self.minflux = flux[0]
183        self.maxflux = flux[0]
184
185        for z in range(self.lenZ):
186
187            if z >= self.Results.zf1 and z <= self.Results.zf2:
188                pass
189            else:
190
191                if flux[z] < self.minflux:
192                    self.minflux = flux[z]
193
194                if flux[z] > self.maxflux:
195                    self.maxflux = flux[z]
196
197        self.fluxrange = self.maxflux - self.minflux
198        self.fluxstep = 0.1*self.fluxrange
199        self.fluxbottom = self.minflux  - self.fluxstep
200        self.fluxtop = self.maxflux + self.fluxstep
201        self.fluxsteps = arange(self.fluxbottom, self.fluxtop, self.fluxstep)
202
203        zf1_ratio = self.Results.zf1/self.lenZ
204        zf2_ratio = self.Results.zf2/self.lenZ
205
206        for f in self.fluxsteps:
207
208            self.ax.axhline(y = f, xmin = zf1_ratio, xmax = zf2_ratio, color = "r")
209
210        zspace = 10
211
212        self.zmin = max(0, z1 - zspace)
213        self.zmax = min(z2 + zspace, self.lenZ)
214
215        self.ax.plot(self.freq, flux)
216        self.ax.set_xlim(0, self.lenZ)
217
218        if self.zAxis == 'freq':
219
220            self.ax.set_xlabel('Frequency Channels (Channel Number)')
221        else:
222
223            xticks = self.ax.get_xticks()
224
225            velticklabels = []
226            for xtick in xticks:
227
228                if xtick >= 0 and xtick < self.lenZ:
229
230                    velticklabel = '%.3f'%(self.vel[int(xtick)]/1000)
231
232                    velticklabels += [velticklabel]
233
234            self.ax.set_xticklabels(velticklabels)
235            self.ax.set_xlabel('Velocity (%s%s)'%('k',self.velunit))
236
237
238        self.ax.set_ylim(self.fluxbottom, self.fluxtop)
239        self.draw()
240
241       
242
243class ZoomGraph(SpectralGraph):
244
245    trackCursorSignal = QtCore.pyqtSignal(object)
246
247    def __init__(self, Results, maskFits, realFits, maskImage):
248
249        SpectralGraph.__init__(self, Results, maskFits, realFits, maskImage)
250
251    def trackCursor(self, event):
252
253        self.trackCursorSignal.emit(event)
254
255    def plotSource(self):
256
257        self.ax.cla()
258       
259        if self.currentObjID <= 0 or (self.spectralType != 'max' and self.spectralType != 'sum'):
260            self.draw()
261            return
262
263       
264        ObjStats = self.Results.SkyObjects[self.currentObjID].stats 
265
266        z1 = ObjStats['Z1']
267        z2 = ObjStats['Z2']
268
269        zspace = 10
270
271        zmin = max(0, z1 - zspace)
272        zmax = min(z2 + zspace, self.lenZ - 1)
273
274        zrange = arange(zmin, zmax + 1)
275
276        if self.spectralType == 'max':
277
278            x_peak = ObjStats['X_peak']
279            y_peak = ObjStats['Y_peak']
280
281            flux = self.realCube[zrange, y_peak, x_peak]
282
283            self.intensityUnit = 'Jy/beam'
284            self.ax.set_ylabel('Intensity (%s)'%self.intensityUnit)
285
286        elif self.spectralType == 'sum':
287
288            flux = zeros(zrange.shape)
289           
290            x1 = ObjStats['X1']
291            x2 = ObjStats['X2']
292            y1 = ObjStats['Y1']
293            y2 = ObjStats['Y2']
294
295            for x in range(x1, x2 + 1):
296                for y in range(y1, y2 + 1):
297
298                    if self.maskImage[y][x] == self.currentObjID:                       
299
300                        flux += self.realCube[zrange, y, x]
301
302           
303            flux = self.C*flux
304            self.intensityUnit = 'Jy'
305            self.ax.set_ylabel('Intensity (%s)'%self.intensityUnit)
306
307        self.linef1 = self.ax.axvline(x = z1, color = "g", linestyle = "--")
308        self.linef2 = self.ax.axvline(x = z2, color = "g", linestyle = "--")
309
310
311
312        self.minflux = flux[0]
313        self.maxflux = flux[0]
314
315        for i in range(len(flux)):
316
317            if zrange[i] >= self.Results.zf1 and zrange[i] <= self.Results.zf2:
318                pass
319            else:
320
321                if flux[i] < self.minflux:
322                    self.minflux = flux[i]
323
324                if flux[i] > self.maxflux:
325                    self.maxflux = flux[i]
326
327        self.fluxrange = self.maxflux - self.minflux
328        self.fluxstep = 0.1*self.fluxrange
329        self.fluxbottom = self.minflux  - self.fluxstep
330        self.fluxtop = self.maxflux + self.fluxstep
331        self.fluxsteps = arange(self.fluxbottom, self.fluxtop, self.fluxstep)
332       
333        self.ax.plot(zrange, flux)
334        self.ax.set_xlim(zmin, zmax)
335
336        if self.zAxis == 'freq':
337
338            self.ax.set_xlabel('Frequency Channels (Channel Number)')
339        else:
340
341            xticks = self.ax.get_xticks()
342
343            velticklabels = []
344            for xtick in xticks:
345
346                if xtick >= 0 and xtick < self.lenZ:
347
348                    velticklabel = velticklabel = '%4.0f'%(self.vel[int(xtick)]/1000)
349
350                    velticklabels += [velticklabel]
351
352            self.ax.set_xticklabels(velticklabels)
353            self.ax.set_xlabel('Velocity (%s%s)'%('k',self.velunit))
354
355        self.ax.set_ylim(self.fluxbottom, self.fluxtop)
356        self.spectralTitle.set_text("Source " + str(self.currentObjID))
357        self.draw()
Note: See TracBrowser for help on using the repository browser.