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

Improvements to Container classes #1123

Merged
merged 27 commits into from
Oct 25, 2019
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
488fc55
change prefix and members of leakage and concentration containers
kosack Aug 22, 2019
7f58494
added ImageParametersContainer to group various parameter containers
kosack Aug 22, 2019
47bfeb6
fixed typo
kosack Aug 22, 2019
467244c
added EventIndexContainer and TelEventIndexContainers
kosack Aug 22, 2019
6cafa86
added telescope type_id to TelIndexContainer
kosack Aug 23, 2019
1fe53b8
rename leakage parameters
kosack Aug 28, 2019
961486c
Merge branch 'master' of https://github.com/cta-observatory/ctapipe i…
kosack Aug 30, 2019
ee73032
new containers, renaming, and deprecation
kosack Sep 30, 2019
8a6cf8d
Update SimTelEventSource
kosack Sep 30, 2019
d8f98e5
add "Set" to standard traits
kosack Sep 30, 2019
4d530d0
fix forgotten rename in test
kosack Sep 30, 2019
a4e2b5b
fix test using leakage parameters (renamed)
kosack Sep 30, 2019
7f580d6
fix tutorial
kosack Sep 30, 2019
b6b39ed
fix a few style warnings
kosack Sep 30, 2019
a10a881
change percent to fraction in LeakageContainer
kosack Oct 2, 2019
cef2b6a
also fix test
kosack Oct 2, 2019
d1a7811
updated names of leakage parameters again
kosack Oct 14, 2019
1aafefc
update leakage names in calculation
kosack Oct 14, 2019
ad79916
again updated leakage names
kosack Oct 14, 2019
570301f
fixed one more place I forgot to rename
kosack Oct 15, 2019
92816b6
Merge branch 'master' of https://github.com/cta-observatory/ctapipe i…
kosack Oct 23, 2019
541699b
used @maxnoe's suggestion of a Deprecated wrapper class
kosack Oct 23, 2019
ea6f8a6
help -> reason (to avoid keyword)
kosack Oct 23, 2019
7e37739
removed accidental commit
kosack Oct 23, 2019
ab4350f
Revert "used @maxnoe's suggestion of a Deprecated wrapper class"
kosack Oct 23, 2019
6f6b7f5
add reason for deprecation and issue warning
kosack Oct 23, 2019
c8e7313
fix test
kosack Oct 23, 2019
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
3 changes: 2 additions & 1 deletion ctapipe/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"""

from .component import Component, non_abstract_children
from .container import Container, Field, Map
from .container import Container, Field, DeprecatedField, Map
from .provenance import Provenance, get_module_version
from .tool import Tool, ToolConfigurationError

Expand All @@ -13,6 +13,7 @@
'Container',
'Tool',
'Field',
'DeprecatedField',
'Map',
'Provenance',
'ToolConfigurationError',
Expand Down
66 changes: 35 additions & 31 deletions ctapipe/core/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,18 @@ def __init__(self, default, description="", unit=None, ucd=None):
self.ucd = ucd

def __repr__(self):
desc = f'{self.description}'
desc = f"{self.description}"
if self.unit is not None:
desc += f' [{self.unit}]'
desc += f" [{self.unit}]"
return desc


class DeprecatedField(Field):
kosack marked this conversation as resolved.
Show resolved Hide resolved
""" used to mark which fields may be removed in next version """

pass


class ContainerMeta(type):
"""
The MetaClass for the Containers
Expand All @@ -47,27 +53,24 @@ class ContainerMeta(type):
"""

def __new__(cls, name, bases, dct):
field_names = [
k for k, v in dct.items()
if isinstance(v, Field)
]
dct['__slots__'] = tuple(field_names + ['meta', 'prefix'])
dct['fields'] = {}
field_names = [k for k, v in dct.items() if isinstance(v, Field)]
dct["__slots__"] = tuple(field_names + ["meta", "prefix"])
dct["fields"] = {}

# inherit fields from baseclasses
for b in bases:
if issubclass(b, Container):
for k, v in b.fields.items():
dct['fields'][k] = v
dct["fields"][k] = v

for k in field_names:
dct['fields'][k] = dct.pop(k)
dct["fields"][k] = dct.pop(k)

new_cls = type.__new__(cls, name, bases, dct)

# if prefix was not set as a class variable, build a default one
if 'container_prefix' not in dct:
new_cls.container_prefix = name.lower().replace('container', '')
if "container_prefix" not in dct:
new_cls.container_prefix = name.lower().replace("container", "")

return new_cls

Expand Down Expand Up @@ -142,10 +145,10 @@ def __setitem__(self, key, value):

def items(self, add_prefix=False):
"""Generator over (key, value) pairs for the items"""
if not add_prefix or self.prefix == '':
if not add_prefix or self.prefix == "":
return ((k, getattr(self, k)) for k in self.fields.keys())

return ((self.prefix + '_' + k, getattr(self, k)) for k in self.fields.keys())
return ((self.prefix + "_" + k, getattr(self, k)) for k in self.fields.keys())

def keys(self):
"""Get the keys of the container"""
Expand Down Expand Up @@ -176,13 +179,14 @@ def as_dict(self, recursive=False, flatten=False, add_prefix=False):
for key, val in self.items(add_prefix=add_prefix):
if isinstance(val, Container) or isinstance(val, Map):
if flatten:
d.update({
f"{key}_{k}": v
for k, v in val.as_dict(
recursive,
add_prefix=add_prefix
).items()
})
d.update(
{
f"{key}_{k}": v
for k, v in val.as_dict(
recursive, add_prefix=add_prefix
).items()
}
)
else:
d[key] = val.as_dict(
recursive=recursive, flatten=flatten, add_prefix=add_prefix
Expand Down Expand Up @@ -220,7 +224,7 @@ def __repr__(self):
if isinstance(getattr(self, name), Map):
extra = "[*]"
desc = "{:>30s}: {}".format(name + extra, repr(item))
lines = wrap(desc, 80, subsequent_indent=' ' * 32)
lines = wrap(desc, 80, subsequent_indent=" " * 32)
text.extend(lines)
return "\n".join(text)

Expand All @@ -239,17 +243,17 @@ def as_dict(self, recursive=False, flatten=False, add_prefix=False):
for key, val in self.items():
if isinstance(val, Container) or isinstance(val, Map):
if flatten:
d.update({
f"{key}_{k}": v
for k, v in val.as_dict(
recursive, add_prefix=add_prefix
).items()
})
d.update(
{
f"{key}_{k}": v
for k, v in val.as_dict(
recursive, add_prefix=add_prefix
).items()
}
)
else:
d[key] = val.as_dict(
recursive=recursive,
flatten=flatten,
add_prefix=add_prefix,
recursive=recursive, flatten=flatten, add_prefix=add_prefix
)
continue
d[key] = val
Expand Down
31 changes: 17 additions & 14 deletions ctapipe/core/traits.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from traitlets import (
Bool,
CaselessStrEnum,
CRegExp,
Dict,
Enum,
Float,
Expand All @@ -15,6 +14,8 @@
TraitType,
Unicode,
observe,
Set,
CRegExp,
)
from traitlets.config import boolean_flag as flag

Expand All @@ -30,6 +31,7 @@
"Long",
"List",
"Bool",
"Set",
"CRegExp",
"Dict",
"flag",
Expand All @@ -43,20 +45,21 @@


class Path(TraitType):
"""
A path Trait for input/output files.

Parameters
----------
exists: boolean or None
If True, path must exist, if False path must not exist

directory_ok: boolean
If False, path must not be a directory
file_ok: boolean
If False, path must not be a file
"""

def __init__(self, exists=None, directory_ok=True, file_ok=True):
"""
A path Trait for input/output files.

Parameters
----------
exists: boolean or None
If True, path must exist, if False path must not exist

directory_ok: boolean
If False, path must not be a directory
file_ok: boolean
If False, path must not be a file
"""
super().__init__()
self.exists = exists
self.directory_ok = directory_ok
Expand Down
14 changes: 7 additions & 7 deletions ctapipe/image/concentration.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,34 @@


def concentration(geom, image, hillas_parameters):
'''
"""
Calculate concentraion values.

Concentrations are ratios of the amount of light in certain
areas to the full intensity of the image.

These features are usefull for g/h separation and energy estimation.
'''
"""

h = hillas_parameters

delta_x = geom.pix_x - h.x
delta_y = geom.pix_y - h.y

# sort pixels by distance to cog
cog_pixels = np.argsort(delta_x**2 + delta_y**2)
cog_pixels = np.argsort(delta_x ** 2 + delta_y ** 2)
conc_cog = np.sum(image[cog_pixels[:3]]) / h.intensity

longi, trans = camera_to_shower_coordinates(geom.pix_x, geom.pix_y, h.x, h.y, h.psi)

# get all pixels inside the hillas ellipse
mask_core = (longi**2 / h.length**2) + (trans**2 / h.width**2) <= 1.0
mask_core = (longi ** 2 / h.length ** 2) + (trans ** 2 / h.width ** 2) <= 1.0
conc_core = image[mask_core].sum() / h.intensity

concentration_pixel = image.max() / h.intensity

return ConcentrationContainer(
concentration_cog=conc_cog,
concentration_core=conc_core,
concentration_pixel=concentration_pixel,
cog=conc_cog,
core=conc_core,
pixel=concentration_pixel,
)
14 changes: 7 additions & 7 deletions ctapipe/image/leakage.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
from ..io.containers import LeakageContainer


__all__ = ['leakage']
__all__ = ["leakage"]


def leakage(geom, image, cleaning_mask):
'''
"""
Calculating the leakage-values for a given image.
Image must be cleaned for example with tailcuts_clean.
Leakage describes how strong a shower is on the edge of a telescope.
Expand All @@ -27,7 +27,7 @@ def leakage(geom, image, cleaning_mask):
Returns
-------
LeakageContainer
'''
"""
border1 = geom.get_border_pixel_mask(1)
border2 = geom.get_border_pixel_mask(2)

Expand All @@ -43,8 +43,8 @@ def leakage(geom, image, cleaning_mask):
size = np.sum(image[cleaning_mask])

return LeakageContainer(
leakage1_pixel=leakage_pixel1 / geom.n_pixels,
leakage2_pixel=leakage_pixel2 / geom.n_pixels,
leakage1_intensity=leakage_intensity1 / size,
leakage2_intensity=leakage_intensity2 / size,
pixels_width_1=leakage_pixel1 / geom.n_pixels,
pixels_width_2=leakage_pixel2 / geom.n_pixels,
intensity_width_1=leakage_intensity1 / size,
intensity_width_2=leakage_intensity2 / size,
)
6 changes: 3 additions & 3 deletions ctapipe/image/tests/test_concentration.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ def test_concentration():

conc = concentration(geom, image, hillas)

assert 0.1 <= conc.concentration_cog <= 0.3
assert 0.05 <= conc.concentration_pixel <= 0.2
assert 0.3 <= conc.concentration_core <= 0.6
assert 0.1 <= conc.cog <= 0.3
assert 0.05 <= conc.pixel <= 0.2
assert 0.3 <= conc.core <= 0.6


if __name__ == '__main__':
Expand Down
8 changes: 4 additions & 4 deletions ctapipe/image/tests/test_leakage.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def test_leakage():
ratio1 = np.sum(geom.get_border_pixel_mask(1)) / geom.n_pixels
ratio2 = np.sum(geom.get_border_pixel_mask(2)) / geom.n_pixels

assert l.leakage1_intensity == ratio1
assert l.leakage2_intensity == ratio2
assert l.leakage1_pixel == ratio1
assert l.leakage2_pixel == ratio2
assert l.intensity_width_1 == ratio1
assert l.intensity_width_2 == ratio2
assert l.pixels_width_1 == ratio1
assert l.pixels_width_2 == ratio2
Loading