Skip to content

Commit

Permalink
fixed to repr and str for all objects (#45)
Browse files Browse the repository at this point in the history
* bug fix to Stack repr which also broke resp repr

* bug fix

* adding tests

* updates based on comments

* black reformat

* added a ValueError if trying to extrapolate and update to documentation (#41)

* added example to illustrate interpolation of edges

* added info about interpolation and custom materials

* added info on energy range for NIST data

* typo on energy range

* change to error if outside energy range

* Update CHANGELOG.rst

* black reformat

* changed ranges to remove now ValueErrors

* Update docs/examples/tutorial1b.rst

Co-authored-by: Shane Maloney <shane.maloney@dias.ie>

Co-authored-by: Shane Maloney <shane.maloney@dias.ie>

* adding tests

* updates based on comments

* merged upstream and black reformat

* black format

Co-authored-by: Shane Maloney <shane.maloney@dias.ie>
  • Loading branch information
ehsteve and samaloney committed Jan 9, 2023
1 parent 304983a commit 640c031
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 25 deletions.
64 changes: 39 additions & 25 deletions roentgen/absorption/material.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,13 @@ def __init__(self, material_input, thickness: u.m, density=None):
raise TypeError("Material input must be a string or a dictionary.")

def __repr__(self):
"""Returns a human-readable representation."""
txt = f"Material({self.name}) {self.thickness} {self.density.to('kg/m**3'):2.1f})"
return txt
"""Returns a developer-relevant representation."""
# at this point, no reason for this to be different than __str__
return self.__str__()

def __str__(self):
"""Returns a human-readable representation."""
txt = f"{self.name} {self.thickness} {self.density.to('kg/m**3'):2.1f}"
"""Returns a human-readable user-focused representation."""
txt = f"Material('{self.name}' thickness={self.thickness} density={self.density.to('kg/m**3'):2.1f})"
return txt

def __add__(self, other):
Expand Down Expand Up @@ -234,12 +234,18 @@ def __add__(self, other):
else:
raise TypeError(f"Cannot add {self} and {other}")

def __repr__(self):
"""Returns a human-readable representation."""
txt = "Stack("
for material in self.materials:
txt += str(material)
return txt + ")"
def __repr__(self) -> str:
"""Returns a developer-relevant representation."""
# at this point, no reason for this to be different than __str__
return self.__str__()

def __str__(self) -> str:
"""Returns a human-readable user-focused representation."""
txt = "Stack(["
for this_material in self.materials:
txt += f"{this_material}, "
txt = f"{txt[:-2]}])"
return txt

def transmission(self, energy):
"""Provides the transmission fraction (0 to 1).
Expand Down Expand Up @@ -294,7 +300,7 @@ class Response(object):
Examples
--------
>>> from roentgen.absorption.material import Material, Response
>>> from roentgen.absorption.material import Material, Response, Stack
>>> import astropy.units as u
>>> optical_path = Stack([Material('air', 1 * u.m), Material('Al', 500 * u.mm)])
>>> resp = Response(optical_path, detector=Material('cdte', 500 * u.um))
Expand All @@ -313,20 +319,14 @@ def __init__(self, optical_path, detector):
else:
raise TypeError("detector must be a Material")

def __repr__(self):
"""Returns a human-readable representation."""
txt = "Response(path="
for material in self.optical_path:
txt += str(material)
txt += " detector=" + str(self.detector)
return txt + ")"
def __repr__(self) -> str:
"""Returns a developer-relevant representation."""
# at this point, no reason for this to be different than __str__
return self.__str__()

def __str__(self):
"""Returns a human-readable representation."""
txt = "path="
for material in self.optical_path:
txt += str(material) + " "
txt += " detector=" + str(self.detector)
def __str__(self) -> str:
"""Returns a human-readable user-focused representation."""
txt = f"Response(optical_path={self.optical_path} detector={self.detector})"
return txt

def response(self, energy):
Expand Down Expand Up @@ -381,6 +381,10 @@ class MassAttenuationCoefficient(object):
The interpolation range is 1 keV to 20 MeV.
Going outside that range will result in a ValueError.
Examples
--------
>>> from roentgen.absorption.material import MassAttenuationCoefficient
>>> mass_atten = MassAttenuationCoefficient('air')
"""

def __init__(self, material):
Expand Down Expand Up @@ -427,6 +431,16 @@ def __init__(self, material):
)
self.func = lambda x: u.Quantity(10 ** self._f(np.log10(x.to("keV").value)), "cm^2/g")

def __repr__(self) -> str:
"""Returns a developer-relevant representation."""
# at this point, no reason for this to be different than __str__
return self.__str__()

def __str__(self) -> str:
"""Returns a human-readable user-focused representation."""
txt = f"MassAttenuationCoefficient('{self.name}')"
return txt

def _remove_double_vals_from_data(self):
"""Remove double-values energy values. Edges are represented with
the same energy index and at the bottom and top value of the edge. This
Expand Down
6 changes: 6 additions & 0 deletions roentgen/tests/test_massatten.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,9 @@ def test_interpolate_matches_at_data():
def test_nonexistent_material(element):
with pytest.raises(ValueError):
MassAttenuationCoefficient(element)


def test_repr_str():
te = MassAttenuationCoefficient("Au")
assert isinstance(te.__repr__(), str)
assert isinstance(te.__str__(), str)
7 changes: 7 additions & 0 deletions roentgen/tests/test_material.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,3 +239,10 @@ def test_raise_outside_of_data_range():

with pytest.raises(ValueError):
mat.transmission(energy)


def test_repr_str():
a = {"Fe": 0.98, "C": 0.02}
this_mat = Material(a, 5 * u.m)
assert isinstance(this_mat.__repr__(), str)
assert isinstance(this_mat.__str__(), str)
6 changes: 6 additions & 0 deletions roentgen/tests/test_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,9 @@ def test_raise_outside_of_data_range():
energy = u.Quantity(np.arange(10, 23, 0.1), "MeV")
with pytest.raises(ValueError):
resp.response(energy)


def test_repr_str():
resp = Response(optical_path=Material("air", thickness=1e-30 * u.um), detector=thin_material)
assert isinstance(resp.__repr__(), str)
assert isinstance(resp.__str__(), str)
6 changes: 6 additions & 0 deletions roentgen/tests/test_stack.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,9 @@ def test_bad_add_to_stack():
def test_mat_add_stack():
stack1 = Material("Ge", 500 * u.micron) + Material("Si", 100 * u.micron)
assert isinstance(Material("Ge", 500 * u.micron) + stack1, Stack)


def test_repr_str():
stack = Material("Ge", 500 * u.micron) + Material("Si", 100 * u.micron)
assert isinstance(stack.__repr__(), str)
assert isinstance(stack.__str__(), str)

0 comments on commit 640c031

Please sign in to comment.