Skip to content

Conversation

@nkrah
Copy link
Collaborator

@nkrah nkrah commented Nov 23, 2024

This PR reworks the way actor output classes are associated with actor classes.
Previously, this was done at an instance level. Now, each actor class gets its own copies of the actor output classes it needs and default values of the actor output can be set at a class level per actor class.

The mechanism makes use of the existing class factory mechanism used for all GateObjects and extends it for all actors.

The actor class docstrings now automatically contain information about the user output (the interfaces to the output, to be precise) and well as the default settings, e.g. active, write_to_disk, etc. Sphinx/autodoc pick this up automatically.

nkrah and others added 30 commits November 20, 2024 01:53
…_for_actoroutput

# Conflicts:
#	docs/source/user_guide/user_guide_reference_actors.rst
@nkrah nkrah changed the title Automatic docstring for actoroutput Consolidate ActorOutput and introduce automatic docstring Nov 28, 2024
@nkrah
Copy link
Collaborator Author

nkrah commented Nov 28, 2024

UPDATE: I am still fixing some structural stuff with the actor output handling in this PR, but I am almost done. Hope this can be merged tomorrow.

@nkrah nkrah mentioned this pull request Nov 28, 2024
nkrah and others added 20 commits November 29, 2024 12:07
@nkrah
Copy link
Collaborator Author

nkrah commented Nov 29, 2024

Some background on this PR (will integrate this in the dev doc later).

Technical level:
​Before, the interfaces and defaults (e.g. dose.active=False by default) were handled via init() at an instance level. But this is actually incorrect because these are class-level configurations. In fact, in the previous implementation, it was impossible to automatically extract the default output configuration of an actor. Now, the interfaces and defaults are processed as part of the class manufacturing step through which all classes inheriting from GateObject go.

​Benefits:
​Interfaces and defaults now exist once a class is processed, i.e. once you import opengate.
​1) Autodoc can automatically extract docstrings and defaults and we can use that in the user guide. Look at this example:
https://opengate-python.readthedocs.io/en/automatic_docstring_for_actoroutput/user_guide/user_guide_reference_actors.html#doseactor

​2) Users can invoke help() in an interactive python terminal to know what output the actor produces and how it is configured by default:
​help(gate.actors.doseactors.DoseActor)
​or, given an existing instance my_dose_actor:
​help(my_dose_actor)

​Or more specifically:
​help(my_dose_actor.dose)​
​help(my_dose_actor.dose_uncertainty)​​

Change for the developer:
Instead of defining the output and interfaces in the init() method of the actor with self._add_user_output() and self._add_interface_to_user_output(), and then setting the defaults, e.g.
​self.user_output.dose_with_uncertainty.set_active(False, item="all")

​... the developer now configures the output via a class-level dictionary user_output_config.
For an actor with a simple "single-item" output, this is:

​ user_output_config = {
"production_stopping": {
"actor_output_class": ActorOutputSingleImage,
},
}​

If inheriting classes do not define their own config, the one from the base class is used. For example, the class DigitizerWithRootOutput​ configures the root output that inheriting Digitizers can use.

For an actor with more complex outputs, like the dose actor, you can also define the interfaces pointing to the data items:

user_output_config = {
"edep_with_uncertainty": {
"actor_output_class": ActorOutputSingleImageWithVariance,
"interfaces": {
"edep": {
"interface_class": UserInterfaceToActorOutputImage,
"item": 0,
"active": True,
},
"edep_squared": {
"interface_class": UserInterfaceToActorOutputImage,
"item": 1,
"active": False,
},
"edep_uncertainty": {
"interface_class": UserInterfaceToActorOutputImage,
"item": "uncertainty",
"active": False,
},
},
},
"dose_with_uncertainty": {
"actor_output_class": ActorOutputSingleImageWithVariance,
"interfaces": {
"dose": {
"interface_class": UserInterfaceToActorOutputImage,
"item": 0,
"active": False,
},
"dose_squared": {
"interface_class": UserInterfaceToActorOutputImage,
"item": 1,
"active": False,
},
"dose_uncertainty": {
"interface_class": UserInterfaceToActorOutputImage,
"item": "uncertainty",
"active": False,
},
},
},
"density": {
"actor_output_class": ActorOutputSingleMeanImage,
"active": False,
},
"counts": {
"actor_output_class": ActorOutputSingleImage,
"active": False,
},
}

​GATE digests all this automatically and issues a GateImplementationError if anything is missing.

​In my opinion, this reworked mechanism is more correct, much better for the doc, and easier to configure for the developer.

@nkrah nkrah merged commit c1f4971 into master Nov 29, 2024
30 checks passed
@nkrah nkrah deleted the automatic_docstring_for_actoroutput branch November 29, 2024 19:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants