Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
7/13/18: Add 2D histogram option for ScatterPlotSysTest (issue #94)
7/11/18: Update code to python3
3/17/16: Update documentation to Sphinx standard and add documentation build files (issue #17)
2/17/16: Changes to correlation function plots & documentation (issue #77)
Expand Down
107 changes: 78 additions & 29 deletions stile/sys_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -1856,7 +1856,8 @@ class BaseScatterPlotSysTest(SysTest):
short_name = 'scatterplot'
def __call__(self, array, x_field, y_field, yerr_field, z_field=None, residual=False,
per_ccd_stat=None, xlabel=None, ylabel=None, zlabel=None, color="",
lim=None, equal_axis=False, linear_regression=False, reference_line=None):
lim=None, equal_axis=False, linear_regression=False, reference_line=None,
histogram=False, histogram_n_bins=40, histogram_cmap='Blues'):
"""
Draw a scatter plot and return a :class:`matplotlib.figure.Figure` object.
This method has a bunch of options for controlling appearance of a plot, which is
Expand Down Expand Up @@ -1902,6 +1903,15 @@ def __call__(self, array, x_field, y_field, yerr_field, z_field=None, residual=F
``x=y`` is drawn. If ``reference_line == 'zero'``, ``y=0`` is drawn.
A user-specific function can be used by passing an object which
has an attribute :func:`__call__` and returns a 1-d Numpy array.
:param histogram: Plot a 2-d histogram (instead of plotting each point individually)
for crowded plots. Setting `histogram=True` will cause any data
given for `z` to be ignored, and any uncertainty on `y` will not be
plotted (though it will still be used to compute a trendline).
[default: False]
:param histogram_n_bins: The number of bins along *each* axis for the histogram; ignored if
`histogram=False`. [default: 40]
:param histogram_cmap: The matplotlib colormap used for the histogram; ignored if
`histogram=False`. [default: 'Blues']
:returns: a :class:`matplotlib.figure.Figure` object
"""
if per_ccd_stat:
Expand Down Expand Up @@ -1946,7 +1956,9 @@ def __call__(self, array, x_field, y_field, yerr_field, z_field=None, residual=F
return self.scatterPlot(x, y, yerr, z,
xlabel=xlabel, ylabel=ylabel,
color=color, lim=lim, equal_axis=False,
linear_regression=True, reference_line=reference_line)
linear_regression=True, reference_line=reference_line,
histogram=histogram, histogram_n_bins=histogram_n_bins,
histogram_cmap=histogram_cmap)

def getData(self):
"""
Expand All @@ -1958,7 +1970,8 @@ def getData(self):
return self.data

def scatterPlot(self, x, y, yerr=None, z=None, xlabel=None, ylabel=None, zlabel=None, color="",
lim=None, equal_axis=False, linear_regression=False, reference_line=None):
lim=None, equal_axis=False, linear_regression=False, reference_line=None,
histogram=False, histogram_n_bins=40, histogram_cmap='Blues'):
"""
Draw a scatter plot and return a :class:`matplotlib.figure.Figure` object.
This method has a bunch of options for controlling appearance of a plot, which is
Expand Down Expand Up @@ -1998,11 +2011,19 @@ def scatterPlot(self, x, y, yerr=None, z=None, xlabel=None, ylabel=None, zlabel=
A user-specific function can be used by passing an object which has
an attribute :func:`__call__` and returns a 1-d Numpy array.
[default: False]
:param histogram: Plot a 2-d histogram (instead of plotting each point individually)
for crowded plots. Setting `histogram=True` will cause any data
given for `z` to be ignored, and any uncertainty on `y` will not be
plotted (though it will still be used to compute a trendline).
[default: False]
:param histogram_n_bins: The number of bins along *each* axis for the histogram; ignored if
`histogram=False`. [default: 40]
:param histogram_cmap: The matplotlib colormap used for the histogram; ignored if
`histogram=False`. [default: 'Blues']
:returns: a :class:`matplotlib.figure.Figure` object
"""
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)

# mask data with nan. Emit a warning if an array has nan in it.
x_isnan = numpy.isnan(x)
y_isnan = numpy.isnan(y)
Expand All @@ -2019,6 +2040,8 @@ def scatterPlot(self, x, y, yerr=None, z=None, xlabel=None, ylabel=None, zlabel=
% (numpy.sum(yerr_isnan), len(yerr_isnan)))
sel = numpy.logical_and(sel, numpy.invert(yerr_isnan))
if z is not None:
if histogram:
warnings.warn('Plotting a histogram - z (color) data will be ignored.')
z_isnan = numpy.isnan(z)
if numpy.sum(z_isnan) != 0:
warnings.warn('There are %s nans in z, out of %s.'
Expand Down Expand Up @@ -2057,19 +2080,24 @@ def scatterPlot(self, x, y, yerr=None, z=None, xlabel=None, ylabel=None, zlabel=
ylim = None

# plot
if z is None:
if yerr is None:
p = ax.plot(x, y, ".%s" % color)
if not histogram:
if z is None:
if yerr is None:
p = ax.plot(x, y, ".%s" % color)
else:
p = ax.errorbar(x, y, yerr, fmt=".%s" % color)
# store color for latter use
used_color = p[0].get_color()
else:
p = ax.errorbar(x, y, yerr, fmt=".%s" % color)
# store color for latter use
used_color = p[0].get_color()
if yerr is not None:
plt.errorbar(x, y, yerr=yerr, linestyle="None", color="k", zorder=0)
plt.scatter(x, y, c=z, zorder=1)
cb = plt.colorbar()
used_color = "b"
else:
if yerr is not None:
plt.errorbar(x, y, yerr=yerr, linestyle="None", color="k", zorder=0)
plt.scatter(x, y, c=z, zorder=1)
plt.hist2d(x, y, bins=histogram_n_bins, cmap=histogram_cmap)
cb = plt.colorbar()
used_color = "b"
used_color = color

# make axes ticks equal to each other if specified
if equal_axis:
Expand Down Expand Up @@ -2139,7 +2167,7 @@ def scatterPlot(self, x, y, yerr=None, z=None, xlabel=None, ylabel=None, zlabel=
ax.set_xlabel(xlabel)
if ylabel is not None:
ax.set_ylabel(ylabel)
if zlabel is not None:
if zlabel is not None and not histogram:
cb.set_label(zlabel)

fig.tight_layout()
Expand Down Expand Up @@ -2238,13 +2266,16 @@ class ScatterPlotStarVsPSFG1SysTest(BaseScatterPlotSysTest):
objects_list = ['star PSF']
required_quantities = [('g1', 'g1_err', 'psf_g1')]

def __call__(self, array, per_ccd_stat=None, color='', lim=None):
def __call__(self, array, per_ccd_stat=None, color='', lim=None,
histogram=False, histogram_n_bins=40, histogram_cmap='Blues'):
return super(ScatterPlotStarVsPSFG1SysTest,
self).__call__(array, 'psf_g1', 'g1', 'g1_err', residual=False,
per_ccd_stat=per_ccd_stat, xlabel=r'$g^{\rm PSF}_1$',
ylabel=r'$g^{\rm star}_1$', color=color, lim=lim,
equal_axis=False, linear_regression=True,
reference_line='one-to-one')
reference_line='one-to-one',
histogram=histogram, histogram_n_bins=histogram_n_bins,
histogram_cmap=histogram_cmap)


class ScatterPlotStarVsPSFG2SysTest(BaseScatterPlotSysTest):
Expand All @@ -2256,13 +2287,16 @@ class ScatterPlotStarVsPSFG2SysTest(BaseScatterPlotSysTest):
objects_list = ['star PSF']
required_quantities = [('g2', 'g2_err', 'psf_g2')]

def __call__(self, array, per_ccd_stat=None, color='', lim=None):
def __call__(self, array, per_ccd_stat=None, color='', lim=None,
histogram=False, histogram_n_bins=40, histogram_cmap='Blues'):
return super(ScatterPlotStarVsPSFG2SysTest,
self).__call__(array, 'psf_g2', 'g2', 'g2_err', residual=False,
per_ccd_stat=per_ccd_stat, xlabel=r'$g^{\rm PSF}_2$',
ylabel=r'$g^{\rm star}_2$', color=color, lim=lim,
equal_axis=False, linear_regression=True,
reference_line='one-to-one')
reference_line='one-to-one',
histogram=histogram, histogram_n_bins=histogram_n_bins,
histogram_cmap=histogram_cmap)


class ScatterPlotStarVsPSFSigmaSysTest(BaseScatterPlotSysTest):
Expand All @@ -2274,14 +2308,17 @@ class ScatterPlotStarVsPSFSigmaSysTest(BaseScatterPlotSysTest):
objects_list = ['star PSF']
required_quantities = [('sigma', 'sigma_err', 'psf_sigma')]

def __call__(self, array, per_ccd_stat=None, color='', lim=None):
def __call__(self, array, per_ccd_stat=None, color='', lim=None,
histogram=False, histogram_n_bins=40, histogram_cmap='Blues'):
return super(ScatterPlotStarVsPSFSigmaSysTest,
self).__call__(array, 'psf_sigma', 'sigma', 'sigma_err', residual=False,
per_ccd_stat=per_ccd_stat,
xlabel=r'$\sigma^{\rm PSF}$ [arcsec]',
ylabel=r'$\sigma^{\rm star}$ [arcsec]',
color=color, lim=lim, equal_axis=False,
linear_regression=True, reference_line='one-to-one')
linear_regression=True, reference_line='one-to-one',
histogram=histogram, histogram_n_bins=histogram_n_bins,
histogram_cmap=histogram_cmap)


class ScatterPlotResidualVsPSFG1SysTest(BaseScatterPlotSysTest):
Expand All @@ -2293,13 +2330,16 @@ class ScatterPlotResidualVsPSFG1SysTest(BaseScatterPlotSysTest):
objects_list = ['star PSF']
required_quantities = [('g1', 'g1_err', 'psf_g1')]

def __call__(self, array, per_ccd_stat=None, color='', lim=None):
def __call__(self, array, per_ccd_stat=None, color='', lim=None,
histogram=False, histogram_n_bins=40, histogram_cmap='Blues'):
return super(ScatterPlotResidualVsPSFG1SysTest,
self).__call__(array, 'psf_g1', 'g1', 'g1_err', residual=True,
per_ccd_stat=per_ccd_stat, xlabel=r'$g^{\rm PSF}_1$',
ylabel=r'$g^{\rm star}_1 - g^{\rm PSF}_1$',
color=color, lim=lim, equal_axis=False,
linear_regression=True, reference_line='zero')
linear_regression=True, reference_line='zero',
histogram=histogram, histogram_n_bins=histogram_n_bins,
histogram_cmap=histogram_cmap)


class ScatterPlotResidualVsPSFG2SysTest(BaseScatterPlotSysTest):
Expand All @@ -2311,13 +2351,16 @@ class ScatterPlotResidualVsPSFG2SysTest(BaseScatterPlotSysTest):
objects_list = ['star PSF']
required_quantities = [('g2', 'g2_err', 'psf_g2')]

def __call__(self, array, per_ccd_stat=None, color='', lim=None):
def __call__(self, array, per_ccd_stat=None, color='', lim=None,
histogram=False, histogram_n_bins=40, histogram_cmap='Blues'):
return super(ScatterPlotResidualVsPSFG2SysTest,
self).__call__(array, 'psf_g2', 'g2', 'g2_err', residual=True,
per_ccd_stat=per_ccd_stat, xlabel=r'$g^{\rm PSF}_2$',
ylabel=r'$g^{\rm star}_2 - g^{\rm PSF}_2$',
color=color, lim=lim, equal_axis=False,
linear_regression=True, reference_line='zero')
linear_regression=True, reference_line='zero',
histogram=histogram, histogram_n_bins=histogram_n_bins,
histogram_cmap=histogram_cmap)


class ScatterPlotResidualVsPSFSigmaSysTest(BaseScatterPlotSysTest):
Expand All @@ -2329,14 +2372,17 @@ class ScatterPlotResidualVsPSFSigmaSysTest(BaseScatterPlotSysTest):
objects_list = ['star PSF']
required_quantities = [('sigma', 'sigma_err', 'psf_sigma')]

def __call__(self, array, per_ccd_stat=None, color='', lim=None):
def __call__(self, array, per_ccd_stat=None, color='', lim=None,
histogram=False, histogram_n_bins=40, histogram_cmap='Blues'):
return super(ScatterPlotResidualVsPSFSigmaSysTest,
self).__call__(array, 'psf_sigma', 'sigma', 'sigma_err', residual=True,
per_ccd_stat=per_ccd_stat,
xlabel=r'$\sigma^{\rm PSF}$ [arcsec]',
ylabel=r'$\sigma^{\rm star} - \sigma^{\rm PSF}$ [arcsec]',
color=color, lim=lim, equal_axis=False,
linear_regression=True, reference_line='zero')
linear_regression=True, reference_line='zero',
histogram=histogram, histogram_n_bins=histogram_n_bins,
histogram_cmap=histogram_cmap)


class ScatterPlotResidualSigmaVsPSFMagSysTest(BaseScatterPlotSysTest):
Expand All @@ -2348,7 +2394,8 @@ class ScatterPlotResidualSigmaVsPSFMagSysTest(BaseScatterPlotSysTest):
objects_list = ['star PSF']
required_quantities = [('sigma', 'sigma_err', 'psf_sigma', 'mag_inst')]

def __call__(self, array, per_ccd_stat='None', color='', lim=None):
def __call__(self, array, per_ccd_stat='None', color='', lim=None,
histogram=False, histogram_n_bins=40, histogram_cmap='Blues'):
self.per_ccd_stat = None if per_ccd_stat == 'None' else per_ccd_stat
import numpy.lib.recfunctions
use_array = numpy.copy(array)
Expand All @@ -2367,5 +2414,7 @@ def __call__(self, array, per_ccd_stat='None', color='', lim=None):
ylabel=
r'$(\sigma^{\rm star} - \sigma^{\rm PSF})/\sigma^{\rm PSF}$',
color=color, lim=lim, equal_axis=False,
linear_regression=True, reference_line='zero')
linear_regression=True, reference_line='zero',
histogram=histogram, histogram_n_bins=histogram_n_bins,
histogram_cmap=histogram_cmap)

28 changes: 28 additions & 0 deletions tests/test_sys_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import numpy
import unittest

try:
import stile
except ImportError:
sys.path.append('..')
import stile

class TestSysTests(unittest.TestCase):
def test_histogram_scatterplot(self):
source_data = stile.ReadASCIITable('../examples/example_source_catalog.dat',
fields={'id': 0, 'ra': 1, 'dec': 2, 'z': 3, 'g1': 4, 'g2': 5})
data = numpy.rec.fromarrays([source_data['ra'], source_data['dec'], source_data['g1'],
source_data['g2'], source_data['g1']+0.1*source_data['ra'], source_data['g2']+0.05*source_data['dec'],
numpy.ones_like(source_data['ra']), numpy.ones_like(source_data['ra'])+0.02,
source_data['g1']*0.05, source_data['g2']*0.05, source_data['g1']*0.05,
source_data['g2']*0.05],
names = ['x', 'y', 'g1', 'g2', 'psf_g1', 'psf_g2', 'sigma', 'psf_sigma',
'g1_err', 'g2_err', 'psf_g1_err', 'psf_g2_err'])
obj = stile.ScatterPlotSysTest('StarVsPSFG1')
obj(data, color='g')
obj(data, histogram=True, color='g')


if __name__=='__main__':
unittest.main()