Skip to content

Commit

Permalink
Adds otype attribute to Observable
Browse files Browse the repository at this point in the history
From now on, it is possible to know whether an Observable object corresponds to a HEALPix map, tabular data or plain data by checking the `otype` attribute.
This attribute should be present both in Simulated and Observational data.
Such awareness is a pre-requisite for writing  generic tools for plotting Observables/Observable_dict objects.
  • Loading branch information
luizfelippesr committed Oct 2, 2020
1 parent cd213e7 commit f8c8400
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 85 deletions.
4 changes: 4 additions & 0 deletions imagine/observables/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def __init__(self):
self._cov = None
self._error = None
self._data = None
self.otype = None

@property
@req_attr
Expand Down Expand Up @@ -174,6 +175,7 @@ def __init__(self, data, name, *, data_col=None, units=None,

# Set Nside
self.Nside = "tab"
self.otype = "tabular"


class HEALPixDataset(Dataset):
Expand All @@ -194,6 +196,8 @@ def __init__(self, data, error=None, cov=None, Nside=None):
raise

self.Nside = Nside
self.otype = 'HEALPix'

assert len(data.shape) == 1
self._data = data

Expand Down
57 changes: 30 additions & 27 deletions imagine/observables/observable.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,12 @@ class Observable(object):
distributed/copied data
dtype : str
Data type, must be either: 'measured', 'simulated' or 'covariance'
otype : str
Observable type, must be either: 'HEALPix', 'tabular' or 'plain'
"""
def __init__(self, data=None, dtype=None, coords=None):
def __init__(self, data=None, dtype=None, coords=None, otype=None):
self.dtype = dtype
self.otype = otype

if isinstance(data, u.Quantity):
self.data = data.value
Expand All @@ -75,6 +78,24 @@ def data(self):
"""
return self._data

@data.setter
def data(self, data):
"""
extra input format check for 'measured' and 'covariance'
no extra check for 'simulated'
"""
log.debug('@ observable::data')
if data is None:
self._data = None
else:
assert (len(data.shape) == 2)
assert isinstance(data, np.ndarray)
if (self._dtype == 'measured'): # copy single-row data from memory
assert (data.shape[0] == 1)
self._data = np.copy(data)
if (self._dtype == 'covariance'):
assert np.equal(*self.shape)

@property
def shape(self):
"""
Expand Down Expand Up @@ -112,46 +133,28 @@ def ensemble_mean(self):
else:
raise TypeError('unsupported data type')

@property
def rw_flag(self):
"""
Rewriting flag, if true, append method will perform rewriting
"""
return self._rw_flag

@property
def dtype(self):
"""
Data type, can be either: 'measured', 'simulated' or 'covariance'
"""
return self._dtype

@data.setter
def data(self, data):
"""
extra input format check for 'measured' and 'covariance'
no extra check for 'simulated'
"""
log.debug('@ observable::data')
if data is None:
self._data = None
else:
assert (len(data.shape) == 2)
assert isinstance(data, np.ndarray)
if (self._dtype == 'measured'): # copy single-row data from memory
assert (data.shape[0] == 1)
self._data = np.copy(data)
if (self._dtype == 'covariance'):
assert np.equal(*self.shape)

@dtype.setter
def dtype(self, dtype):
if dtype is None:
raise ValueError('dtype cannot be none')
raise ValueError('dtype cannot be None')
else:
assert (dtype in ('measured', 'simulated', 'covariance'))
self._dtype = str(dtype)

@property
def rw_flag(self):
"""
Rewriting flag, if true, append method will perform rewriting
"""
return self._rw_flag

@rw_flag.setter
def rw_flag(self, rw_flag):
assert isinstance(rw_flag, bool)
Expand Down
42 changes: 22 additions & 20 deletions imagine/observables/observable_dict.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def __getitem__(self, key):
return self._archive[key]

@abc.abstractmethod
def append(self, dataset=None, *, name=None, data=None, plain=False,
def append(self, dataset=None, *, name=None, data=None, otype=None,
coords=None):
"""
Adds/updates name and data
Expand All @@ -126,9 +126,11 @@ def append(self, dataset=None, *, name=None, data=None, plain=False,
`ext` can be 'I','Q','U','PI','PA', None or other customized tags.
data : numpy.ndarray or imagine.observables.observable.Observable
distributed/copied :py:class:`numpy.ndarray` or :py:class:`Observable <imagine.observables.observable.Observable>`
plain : bool
If True, means unstructured/tabular data.
If False (default case), means HEALPix-like sky map.
otype : str
Type of observable. May be: 'HEALPix', for HEALPix-like sky map;
'tabular', for tabular data; or 'plain' for unstructured data.
coords : dict
A dictionary containing the coordinates of tabular data
"""

if dataset is not None:
Expand All @@ -137,15 +139,12 @@ def append(self, dataset=None, *, name=None, data=None, plain=False,
data = dataset.data
cov = dataset.cov
coords = dataset.coords
if isinstance(dataset, HEALPixDataset):
plain=False
else:
plain=True
otype = dataset.otype
else:
cov = data

assert (len(name) == 4), 'Wrong format for Observable key!'
return(name, data, cov, plain, coords)
return(name, data, cov, otype, coords)



Expand Down Expand Up @@ -180,16 +179,16 @@ class Masks(ObservableDict):

def append(self, *args, **kwargs):
log.debug('@ observable_dict::Masks::append')
name, data, _, plain, _ = super().append(*args, **kwargs)
name, data, _, otype, _ = super().append(*args, **kwargs)

if isinstance(data, Observable):
assert (data.dtype == 'measured')
if not plain:
if otype == 'HEALPix':
assert (data.size == 12*np.uint(name[2])**2)
self._archive.update({name: data})
elif isinstance(data, np.ndarray):
assert (data.shape[0] == 1)
if not plain:
if otype == 'HEALPix':
assert (data.shape[1] == _Nside_to_Npixels(name[2]))
self._archive.update({name: Observable(data, 'measured')})
else:
Expand Down Expand Up @@ -237,9 +236,10 @@ def __call__(self, observable_dict):
new_name = (name[0], name[1], masked_data.shape[1], name[3])
masked_dict.append(name=new_name,
data=masked_data,
plain=True)
otype='plain')
masked_dict.coords = observable.coords
masked_dict.unit = observable.unit

return masked_dict


Expand All @@ -253,17 +253,18 @@ class Measurements(ObservableDict):

def append(self, *args, **kwargs):
log.debug('@ observable_dict::Measurements::append')
name, data, _, plain, coords = super().append(*args, **kwargs)
name, data, _, otype, coords = super().append(*args, **kwargs)

if isinstance(data, Observable):
assert (data.dtype == 'measured')
self._archive.update({name: data})
elif isinstance(data, np.ndarray):
if not plain:
if otype == 'HEALPix':
assert (data.shape[1] == _Nside_to_Npixels(name[2]))
self._archive.update({name: Observable(data=data,
dtype='measured',
coords=coords)})
coords=coords,
otype=otype)})
else:
raise TypeError('Unsupported data type')

Expand All @@ -278,7 +279,7 @@ class Simulations(ObservableDict):

def append(self, *args, **kwargs):
log.debug('@ observable_dict::Simulations::append')
name, data, *_, coords = super().append(*args, **kwargs)
name, data, _, otype, coords = super().append(*args, **kwargs)

if name in self._archive.keys(): # app
self._archive[name].rw_flag = False
Expand All @@ -289,7 +290,8 @@ def append(self, *args, **kwargs):
elif isinstance(data, np.ndarray): # distributed data
self._archive.update({name: Observable(data=data,
dtype='simulated',
coords=coords)})
coords=coords,
otype=otype)})
else:
raise TypeError('unsupported data type')

Expand All @@ -304,12 +306,12 @@ class Covariances(ObservableDict):

def append(self, *args, **kwargs):
log.debug('@ observable_dict::Covariances::append')
name, _, data, plain, _ = super().append(*args, **kwargs)
name, _, data, otype, _ = super().append(*args, **kwargs)

if isinstance(data, Observable): # always rewrite
self._archive.update({name: data}) # rw
elif isinstance(data, np.ndarray):
if not plain:
if otype == 'HEALPix':
assert (data.shape[1] == _Nside_to_Npixels(name[2]))
self._archive.update({name: Observable(data, 'covariance')})
else:
Expand Down
5 changes: 4 additions & 1 deletion imagine/simulators/simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ def __init__(self, measurements):
self.observables = []
self.output_coords = {}
self.output_units = {}
self.output_type = {}
self._ensemble_size = None
self.register_observables(measurements)

Expand All @@ -79,6 +80,7 @@ def register_observables(self, measurements):
# perhaps, be useful later
self.observables.append(key)
self.output_coords[key] = measurements[key].coords
self.output_type[key] = measurements[key].otype
self.output_units[key] = measurements[key].unit
assert len(self.observables) > 0, 'No valid observable was requested!'

Expand Down Expand Up @@ -415,5 +417,6 @@ def __call__(self, field_list):
output_units=self.output_units[key])
sims.append(name=key,
data=sim[np.newaxis, :].to(self.output_units[key]),
coords=self.output_coords[key])
coords=self.output_coords[key],
otype=self.output_type[key])
return sims
24 changes: 10 additions & 14 deletions imagine/tests/test_likelihood.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ def test_without_cov(self):
arr_a = np.random.rand(1, 48)
comm.Bcast(arr_a, root=0)
mea = Observable(arr_a, 'measured')
meadict.append(name=('test', None, 2, None), data=mea)
meadict.append(name=('test', None, 2, None), data=mea, otype='HEALPix')
# mock sims
arr_b = np.random.rand(3, 48)
sim = Observable(arr_b, 'simulated')
simdict.append(name=('test', None, 2, None), data=sim)
simdict.append(name=('test', None, 2, None), data=sim, otype='HEALPix')
# no covariance
lh = SimpleLikelihood(meadict)
# calc by likelihood
Expand All @@ -51,19 +51,17 @@ def test_with_cov(self):
comm.Bcast(arr_a, root=0)
mea = Observable(arr_a, 'measured')
meadict.append(name=('test', None, 4*mpisize, None),
data=mea,
plain=True)
data=mea, otype='plain')
# mock sims
arr_b = np.random.rand(5, 4*mpisize)
sim = Observable(arr_b, 'simulated')
simdict.append(name=('test', None, 4*mpisize, None),
data=sim)
data=sim, otype='plain')
# mock covariance
arr_c = np.random.rand(4, 4*mpisize)
cov = Observable(arr_c, 'covariance')
covdict.append(name=('test', None, 4*mpisize, None),
data=cov,
plain=True)
data=cov)
# with covariance
lh = SimpleLikelihood(meadict, covdict)
# calc by likelihood
Expand All @@ -87,14 +85,12 @@ def test_without_simcov(self):
comm.Bcast(arr_a, root=0)
mea = Observable(arr_a, 'measured')
meadict.append(name=('test', None, 4*mpisize, None),
data=mea,
plain=True)
data=mea, otype='plain')
# mock covariance
arr_c = np.random.rand(4, 4*mpisize)
cov = Observable(arr_c, 'covariance')
covdict.append(name=('test', None, 4*mpisize, None),
data=cov,
plain=True)
data=cov)
# mock observable with repeated single realisation
arr_b = np.random.rand(1, 4*mpisize)
comm.Bcast(arr_b, root=0)
Expand All @@ -103,7 +99,7 @@ def test_without_simcov(self):
arr_ens[i] = arr_b
sim = Observable(arr_ens, 'simulated')
simdict.append(name=('test', None, 4*mpisize, None),
data=sim)
data=sim, otype='plain')
# simplelikelihood
lh_simple = SimpleLikelihood(meadict, covdict)
rslt_simple = lh_simple(simdict)
Expand All @@ -120,7 +116,7 @@ def test_without_cov(self):
comm.Bcast(arr_a, root=0)
mea = Observable(arr_a, 'measured')
meadict.append(name=('test', None, mpisize, None),
data=mea)
data=mea, otype='HEALPix')
# mock observable with repeated single realisation
arr_b = np.random.rand(1, 12*mpisize**2)
comm.Bcast(arr_b, root=0)
Expand All @@ -132,7 +128,7 @@ def test_without_cov(self):
arr_ens[i] = arr_b
sim = Observable(arr_ens, 'simulated')
simdict.append(name=('test', None, mpisize, None),
data=sim)
data=sim, otype='HEALPix')
# simplelikelihood
lh_simple = SimpleLikelihood(meadict)
rslt_simple = lh_simple(simdict)
Expand Down

0 comments on commit f8c8400

Please sign in to comment.