-
Notifications
You must be signed in to change notification settings - Fork 52
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
[WIP] AbstractDiffractometer #695
base: develop
Are you sure you want to change the base?
Conversation
Make temporary changes because of bug in get_roles.
Implement do_characterisation_scan method
update_value generic method, instead of update_*. Add constraint Enum and methods. Cleanup. head_type initialised in init().
Add value_to_enum method.
Implement get_value_motors and set_value_motors to use the available motors only. Implement constrains.
Returns: | ||
(dict): Dictionary key=role: value=hardware_object | ||
""" | ||
return self.motors_hwobj_dict |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can I recommend you return a copy? It takes little longer, and then the internal dictionary is not exposed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not indeed. I guess that this method will be quite often overloaded in the concrete implementation.
"""Do characterisation.""" | ||
raise NotImplementedError | ||
|
||
def update_value(self, value=None, method=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I understand this one.
Small stuff: the 'method' parameter is actually transferring a value not a method.
Bigger stuff, 'update_value' is the same name as for Actuators, but the calling interface is different. Since the diffractometer is not an actuator this is not fatal, but it could be confusing.
Also, imaging value is None and 'method' is , say, UNKNOWN. This function will set curr_value to UNKNOWN and emit valueChanged. 1) curr_value is not persisted (so what effect does it have?), and could be either a Phase or a Constraint. 2) How much sense does it make to talk about the 'value' of a Diffractometer'? 3) What kind of function would take this signal and be prepared to receive either a Phase or a Constraint? 4) What hapens when someone at a beamline use htese generic-named functions for yet a third parameter?
I cannot make suggestions, since I d not understand what this is for, but could one make separate update_phase and update_constraint, and deal with values changing by another way, e.g. the equivalent of self._nominal_phase etc.?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @rhfogh, you are right, maybe _update_value is more appropriate, as it is meant for internal use only.
The idea behind is that there is no need to define specific update value for each method, that needs it, but one generic, that can take as a parameter (the method) which is the method or the property when you want to get a recent value. This is probably a bit personal style - I've implemented update_phase and update_constraint at first and than changed.
As you correctly pointed out, there is no meaning for a value of a Diffractometer, but still valueCjanged can be emitted.
Also, imaging value is None and 'method' is , say, UNKNOWN. This function will set curr_value to UNKNOWN and emit valueChanged.
This is correct. But as we use it only internally, is also a way to be sure that the one, using the method knows what is going on.
deal with values changing by another way, e.g. the equivalent of self._nominal_phase etc.?
I do not think that the phase (or the constraint) should have a persistent value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What you say makes sense, but there are still things I wonder about.
- What you are passing is not a method, but the value you get from calling it. method=self.get_phase(), not method=self.get_phase. Why name the function parameter 'method'?
- The only thing that function does that has any effect is
self.emit("valueChanged", (value,))
Why not code that directly instead of calling this function? - What is supposed to catch that signal (that may have either a Phase or a Constraint as parameter)? What does it do ?
- Does it make sense that the AbstractDiffractometer emits valueChanged and limitsChanged (as it says in the documentation) when diffractometers do not have a value? Would it not make sense to give it a name that better reflects what it is doing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1. What you are passing is not a method, but the value you get from calling it. method=self.get_phase(), not method=self.get_phase. Why name the function parameter 'method'?
You are right, I've changed the name of the method and its parameter.
2. The only thing that function does that has any effect is self.emit("valueChanged", (value,)) Why not code that directly instead of calling this function?
Just for not repeating the code (at least twice).
3. What is supposed to catch that signal (that may have either a Phase or a Constraint as parameter)? What does it do ?
The GUI that wants to update the label, when the diffractometer changes the Phase ...
4. Does it make sense that the AbstractDiffractometer emits valueChanged and limitsChanged (as it says in the documentation) when diffractometers do not have a value? Would it not make sense to give it a name that better reflects what it is doing?
This makes the code more versatile in respect of the GUI.
The equipment is identified by the roles. | ||
The fixed motor roles are: | ||
omega, kappa, kappa_phi, horizontal_alignment, vertical_alignment, | ||
horizontal_centring, vertical_centring, focus, front_light, back_light |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good, but maybe it is incomplete? I see no mention of vertical_centring etc. in the AbstractDiffractometer code, but I do see mention of phiy, phix, sampx etc. Should this not be homologised?
It would be great if there was a way of putting in the code which role names were mandatory and how they should be spelled, but if we cannot find a good way we shall of course have to do without. Presumably we cannot make the motors mandatory, in case some beamlines lack then? Could we require that roles should eb set (in the dictionary) in the init so that you can only add motors in the config if they are already in the init?
Would it be useful with more detaild docs for some of the centring motors? If we have a vertical instead of horizontal omega axis, what might taht do to the identity of horizontal_centring, vertical_centring etc.?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rhfogh I was planning to find a schema and put it in the documentation with all the pre-defined roles. Everybody's input is welcome. @ALL, if you have such a scheme, it will be great if you can share it.
It would be great if there was a way of putting in the code which role names were mandatory.
That would depend on the diffractometer and its head.
What we could do is to decide for a list of mandatory roles, which we check in the init and if not specified in the config, we set the object as None in the dictionary of the motors. This is a bit too much in my opinion, but the only was to make some check against the correct spelling.
Could we require that roles should be set (in the dictionary) in the init so that you can only add motors in the config if they are already in the init?
I would avoid limiting the number of roles for either motors or nstate equipment. This make the AbstractDiffractometer less versatile, especially taking into account the new head types, used by the SSX experiments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had in mind something like the way it works for yaml objects. There properties can only be put in the configuration if the corresponding attributes are defined in the __init__ (if hasattr(object, 'newrolename') returns True, basically). BUT there is nothing to stop you from adding additional role names in the __init__ of subclasses and then putting the relevant data in the config files, which will give you as many additional (sub)roles as you want. The point is that doing something similar here would make it visible in the code which roles there are for a given object, and not allow people to code to roles that only appear in config files. Ideally these should be attributes, not just dictionary members, so that linters will pick them up. But hey, we cannot be ideal all the time.
while not self._ready: | ||
sleep(0.5) | ||
|
||
def get_motors(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why def get_motors(self)
is needed here? and why it returns list?
It is defined in Abstract and it it returns dict there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @meghdadyazdi, well spotted. Somehow, when committing I've included the wrong implementation of the get_motors.
The method is overloaded in MicroDiffractometer, as we want only the currently available motors to be used. The dictionary of these motors is not only static - depending on the head (plate, kappa, ssx ...) but also dynamic - depending on the constraints applied (as in the latest implementation of the MD java software)
AbstractDiffractometer class:
MD2 implementation - overload or fill in the abstract methods.