# Licensed under a 3-clause BSD style license - see LICENSE.rst
"""Diagnostic polarization plot pipeline step."""
import os
from astropy import log
import numpy as np
from matplotlib.backends.backend_agg \
import FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure
from sofia_redux.instruments.hawc.stepparent import StepParent
__all__ = ['StepLabPolPlots']
[docs]
class StepLabPolPlots(StepParent):
"""
Produce diagnostic plots for lab-generated polarization data.
This step makes a two panel figure showing percentage polarization
on the left and polarization angle on the right. Histograms are
shown below.
This step is intended to be run in place of StepPolMap. All other
steps in the standard chop/nod polarimetry pipeline should be run
prior to this step. The input data expected is the output of
the `sofia_redux.instruments.hawc.steps.StepPolVec` pipeline step,
containing Percent Pol and Pol Angle extensions. Output data for this
step is identical to the input data. PNG plots are produced as a side
effect and are saved to disk with the same basename and directory
as the input data.
"""
[docs]
def setup(self):
"""
Set parameters and metadata for the pipeline step.
Output files have PRODTYPE = 'labpolplots', and are named with
the step abbreviation 'PLT'.
Parameters defined for this step are:
region : list of int
Region box given as [xmin, xmax, ymin, ymax].
polrange : list of float
Limit to only use percent polarization in this range,
given as [pol_min, pol_max].
anglerange : list of float
Limit to only use polarization angles in this range,
given as [angle_min, angle_max], in degrees.
"""
# Name of the pipeline reduction step
self.name = 'labpolplots'
self.description = "Make Lab Pol Plots"
# Shortcut for pipeline reduction step and identifier for
# saved file names.
self.procname = 'plt'
# Clear Parameter list
self.paramlist = []
# Append parameters
self.paramlist.append(['region', [5, 28, 13, 34],
'Region box given as xmin,xmax,ymin,ymax'])
self.paramlist.append(['polrange', [0, 5],
'Limit to only use percent pol '
'in the given range'])
self.paramlist.append(['anglerange', [-45, 45],
'Limit to only use pol angle in '
'the given range'])
[docs]
def run(self):
"""
Run the data reduction algorithm.
Because this step is single-in, single-out (SISO),
self.datain must be a DataFits object. The output
is also a DataFits object, stored in self.dataout.
The process is:
1. Read percent polarization and angle from the input.
2. Restrict data to range specified by parameters.
3. Plot the data and save to disk.
"""
# copy input to output
self.dataout = self.datain
# Get input parameters
reg = list(self.getarg('region'))
polrange = self.getarg('polrange')
anglerange = self.getarg('anglerange')
# Get the data from the input file
pol = self.datain.imageget('Percent Pol')
theta = self.datain.imageget('Pol Angle')
# Extract and calculate data statistics based on the region
polstats = pol[reg[0] - 1:reg[1], reg[2] - 1:reg[3]]
thetastats = theta[reg[0] - 1:reg[1], reg[2] - 1:reg[3]]
mask = np.where((polstats >= polrange[0]) & (polstats <= polrange[1]))
polstats = polstats[mask]
mask = np.where((thetastats >= anglerange[0])
& (thetastats <= anglerange[1]))
thetastats = thetastats[mask]
polmedian = np.median(polstats)
thetamedian = np.median(thetastats)
outfile = self.datain.filenamebegin + self.procname.upper()
outfile += self.datain.filenameend.replace('.fits', '.png')
# Make top left subplot, Polarization Percent
fig = Figure()
FigureCanvas(fig)
ax = fig.add_subplot(2, 2, 1)
img = ax.imshow(pol, origin='lower', cmap='rainbow',
interpolation='nearest',
aspect='equal', vmin=0., vmax=100.0)
ax.plot([reg[0] - 1.5, reg[1] - 0.5, reg[1] - 0.5,
reg[0] - 1.5, reg[0] - 1.5],
[reg[2] - 1.5, reg[2] - 1.5, reg[3] - 0.5,
reg[3] - 0.5, reg[2] - 1.5], 'w--', lw=2)
fig.colorbar(img, orientation='vertical', pad=0.01)
ax.get_xaxis().set_ticks([])
ax.get_yaxis().set_ticks([])
ax.set_xlim([-0.5, 31.5])
ax.set_ylim([-0.5, 40.5])
# Make top right subplot, Polarization Angle
ax = fig.add_subplot(2, 2, 2)
img = ax.imshow(theta, origin='lower', cmap='rainbow',
interpolation='nearest',
aspect='equal', vmin=anglerange[0],
vmax=anglerange[1])
ax.plot([reg[0] - 1.5, reg[1] - 0.5, reg[1] - 0.5,
reg[0] - 1.5, reg[0] - 1.5],
[reg[2] - 1.5, reg[2] - 1.5, reg[3] - 0.5,
reg[3] - 0.5, reg[2] - 1.5], 'w--', lw=2)
fig.colorbar(img, orientation='vertical', pad=0.01)
ax.get_xaxis().set_ticks([])
ax.get_yaxis().set_ticks([])
ax.set_xlim([-0.5, 31.5])
ax.set_ylim([-0.5, 40.5])
# Make bottom left subplot, Polarization Percent Histogram
ax = fig.add_subplot(2, 2, 3)
ax.hist(polstats.flatten())
limits = ax.get_ylim()
ax.plot([polmedian, polmedian], limits, 'r--')
ax.text(0.9, 0.9,
'Median = %.1f %%' % polmedian,
horizontalalignment='right',
transform=ax.transAxes)
ax.set_xlabel('Polarization (%)')
ax.set_ylabel('Number')
# Make bottom right subplot, Polarization Angle Histogram
ax = fig.add_subplot(2, 2, 4)
ax.hist(thetastats.flatten())
limits = ax.get_ylim()
ax.plot([thetamedian, thetamedian], limits, 'r--')
ax.text(0.9, 0.9,
r'Median = $%.1f^\circ$' % thetamedian,
horizontalalignment='right',
transform=ax.transAxes)
ax.set_xlabel('Pol. Angle (deg)')
ax.set_ylabel('Number')
# Finish plots
fig.subplots_adjust(hspace=0.05)
title = os.path.basename(outfile)
fig.suptitle(title, y=0.95)
fig.savefig(outfile)
fig.clear()
self.auxout = [outfile]
log.info('Saved result %s' % outfile)