Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include params in HDF5 output #142

Merged
merged 18 commits into from
Aug 14, 2015
Merged
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
36 changes: 30 additions & 6 deletions astrodendro/dendrogram.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def static_warning(self, *args, **kwargs):
self.load_from = static_warning

@staticmethod
def compute(data, min_value=-np.inf, min_delta=0, min_npix=0,
def compute(data, min_value="min", min_delta=0, min_npix=0,
is_independent=None, verbose=False, neighbours=None, wcs=None):
"""
Compute a dendrogram from a Numpy array.
Expand All @@ -96,9 +96,10 @@ def compute(data, min_value=-np.inf, min_delta=0, min_npix=0,
----------
data : :class:`numpy.ndarray`
The n-dimensional array to compute the dendrogram for
min_value : float, optional
min_value : float or "min", optional
The minimum data value to go down to when computing the
dendrogram. Values below this threshold will be ignored.
dendrogram. Values below this threshold will be ignored. Defaults
to the minimum value in the data.
min_delta : float, optional
The minimum height a leaf has to have in order to be considered an
independent entity.
Expand Down Expand Up @@ -128,9 +129,9 @@ def compute(data, min_value=-np.inf, min_delta=0, min_npix=0,
that has been padded with one element along each edge.

wcs : WCS object, optional
A WCS object that describes `data`. This is used in the
interactive viewer to properly display the data's coordinates
on the image axes. (Requires that `wcsaxes` is installed; see
A WCS object that describes `data`. This is used in the
interactive viewer to properly display the data's coordinates
on the image axes. (Requires that `wcsaxes` is installed; see
http://wcsaxes.readthedocs.org/ for install instructions.)


Expand Down Expand Up @@ -160,6 +161,10 @@ def compute(data, min_value=-np.inf, min_delta=0, min_npix=0,
is_independent = pruning.all_true(tests)
neighbours = neighbours or Dendrogram.neighbours

# Default min_val to the minimum in the data
if min_value == "min":
min_value = np.min(data[np.isfinite(data)]) - 1

self = Dendrogram()
self.data = data
self.n_dim = len(data.shape)
Expand Down Expand Up @@ -463,6 +468,25 @@ def __eq__(self, other):
if not (self.data == other.data).all():
return False

if self.params['min_value'] != other.params['min_value']:
return False

self_params = self.params.copy()
other_params = other.params.copy()

self_params.pop('min_value')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ooo careful here -- pop permanently mutates the params dict of the parent dendrograms. Better to set self_params = self.params.copy(), other_params = other.params.copy()

other_params.pop('min_value')

# Hack for not comparing params that have not been set
# There is currently no explicit way to tell if it has not been set
# We assume that if it is =0, then it is not set and won't be compared
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

for key in self_params.keys():
if self_params[key] == 0 or other_params[key] == 0:
continue

if self_params[key] != other_params[key]:
return False

# structures should have the same extent,
# but idx values need not be identical. This
# tests the index map for that
Expand Down
13 changes: 12 additions & 1 deletion astrodendro/io/fits.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ def dendro_export_fits(d, filename):
except AttributeError:
primary_hdu = fits.PrimaryHDU()

primary_hdu.header["MIN_NPIX"] = (d.params['min_npix'],
"Minimum number of pixels in a leaf.")
primary_hdu.header["MIN_DELT"] = (d.params['min_delta'],
"Minimum branch height.")
primary_hdu.header["MIN_VAL"] = (d.params['min_value'],
"Minimum intensity value.")

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should these parameters be in the fits header instead of a new extension? That would seem more standard to me

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I agree, these belong in the header (I think of the primary HDU)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, the table seemed quite clunky. I moved them to the header.

hdus = [primary_hdu,
fits.ImageHDU(d.data),
fits.ImageHDU(d.index_map),
Expand All @@ -59,7 +66,11 @@ def dendro_import_fits(filename):
index_map = hdus[2].data
newick = ''.join(chr(x) for x in hdus[3].data.flat)

return parse_dendrogram(newick, data, index_map, wcs)
params = {"min_npix": hdus[0].header['MIN_NPIX'],
"min_value": hdus[0].header['MIN_VAL'],
"min_delta": hdus[0].header['MIN_DELT']}

return parse_dendrogram(newick, data, index_map, params, wcs)


FITSHandler = IOHandler(identify=is_fits,
Expand Down
10 changes: 9 additions & 1 deletion astrodendro/io/hdf5.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ def dendro_export_hdf5(d, filename):
ds.attrs['IMAGE_VERSION'] = '1.2'
ds.attrs['IMAGE_MINMAXRANGE'] = [d.data.min(), d.data.max()]

for key in d.params.keys():
f.create_dataset(key, data=d.params[key])

try:
f.create_dataset('wcs_header', data=d.wcs.to_header_string())
except AttributeError:
Expand All @@ -59,13 +62,18 @@ def dendro_import_hdf5(filename):
newick = h5f['newick'].value
data = h5f['data'].value
index_map = h5f['index_map'].value

params = {}
params['min_value'] = h5f['min_value'].value
params['min_delta'] = h5f['min_delta'].value
params['min_npix'] = h5f['min_npix'].value
try:
wcs = WCS(h5f['wcs_header'].value)
except KeyError:
wcs = None

log.debug('Parsing dendrogram...')
return parse_dendrogram(newick, data, index_map, wcs)
return parse_dendrogram(newick, data, index_map, params, wcs)


HDF5Handler = IOHandler(identify=is_hdf5,
Expand Down
3 changes: 2 additions & 1 deletion astrodendro/io/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def collect(d):
return items['trunk']


def parse_dendrogram(newick, data, index_map, wcs=None):
def parse_dendrogram(newick, data, index_map, params, wcs=None):
from ..dendrogram import Dendrogram
from ..structure import Structure

Expand All @@ -80,6 +80,7 @@ def parse_dendrogram(newick, data, index_map, wcs=None):
d._structures_dict = {}
d.data = data
d.index_map = index_map
d.params = params
d.wcs = wcs

try:
Expand Down
Binary file modified astrodendro/tests/benchmark_data/2d1.fits
Binary file not shown.
Binary file modified astrodendro/tests/benchmark_data/2d2.fits
Binary file not shown.
Binary file modified astrodendro/tests/benchmark_data/2d3.fits
Binary file not shown.
Binary file modified astrodendro/tests/benchmark_data/3d1.fits
Binary file not shown.
Binary file modified astrodendro/tests/benchmark_data/3d2.fits
Binary file not shown.
Binary file modified astrodendro/tests/benchmark_data/3d3.fits
Binary file not shown.
2 changes: 1 addition & 1 deletion astrodendro/tests/test_is_independent.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def is_independent_test(structure, index=None, value=None):

d1 = Dendrogram.compute(data,
is_independent=is_independent_test,
min_value=p['min_value'] if 'min_value' in p else -np.inf)
min_value=p['min_value'] if 'min_value' in p else "min")
d2 = Dendrogram.load_from(path)

assert d1 == d2