This is a follow up on my previous post, but it’s now in the proper category and a broader question.

I find the TauP API a little awkward in that we can’t mutate `Arrival`

objects very easily. Consider the documented ways to access TauP calculation results. There are different methods for travel times, ray paths, pierce points, etc. and they all return their own `Arrivals`

interface. But IMHO it is not uncommon to start with just travel times and later realise that ray paths/pierce points/etc. are also needed. Instead of:

```
from obspy.taup import TauPyModel
model = TauPyModel()
arrivals = model.get_travel_times(source_depth_in_km=55, distance_in_degree=67)
# Some other stuff
# Aw crap I need ray paths...
arrivals = model.get_ray_paths(source_depth_in_km=55, distance_in_degree=67)
```

I propose to move these members (or their wrappers) to `Arrivals`

, incrementally adding missing information as it is requested:

```
from obspy.taup import TauPyModel()
model = TauPyModel()
arrivals = model.get_arrivals(...)
# Get ray paths
paths = arrivals.get_ray_paths(...) # Returns cached paths or calculates new ones.
# Get travel times
times = arrivals.get_travel_times(...) # Returns cached times or calculates new ones.
# Etc.
```

This way the method names are also more intuitive (IMHO, compare `get_ray_paths(...) -> paths`

with `get_ray_paths(...) -> arrivals`

).

Notice that I wrote “cached”, this is something I have been patching in for my project built on Obspy: new arrival information is only calculated when different parameters are requested (“memoization”). After thinking about it, I don’t see why this couldn’t be implemented in ObsPy itself, subject to backwards compatibility issues. It could be achieved relatively easily with the above proposed API, by using either `cached_property`

(python>=3.8) or regular old properties with setters. I have been doing it the second way.

Thanks for all your hard work on ObsPy. This got rather long, let me know if I should open an issue instead.