Repository navigation
Simplify ElementHolder API: one accessor per element family (merge magnet/magnets, bpm/bpms, …) #468
Description
Activity
Personally I would prefer to keep the 's' and update bpm interface using same rules.
For instance we will always work with variables that won't tell you if you work with a vector or not.
strengthstell, as is the example below, that sextu is an array.k = sextu.strengths.get() k += self.correct(dchroma) sextu.strengths.set(k)
To follow pyAML style, i would prefer:
sextu = sr.design.magnet.arrays.get(self.sextu_array_name)
3. Personally I would prefer to keep the 's' and update bpm interface using same rules.
For instance we will always work with variables that won't tell you if you work with a vector or not.
strengthstell, as is the example below, that sextu is an array.
k = sextu.strengths.get()
k += self.correct(dchroma)
sextu.strengths.set(k)To follow pyAML style, i would prefer: sextu = sr.design.magnet.arrays.get(self.sextu_array_name)For me it's not great but I can live with it if you think it's neccessary.
Do you agree on the 1st part of the issue?I think it's OK to have both ways to access things; it's more of a question of taste. So either one is fine for me.
If 's' is too confusing and too typo-friendly, maybe it can be renamed to array? So, instead of
sr.design.bpmsyou would havesr.design.bpm_array.It is just my opinion. If you want to have strength without the 's' for array it is ok. To me having 's' make the code more readable as you immediately see that it is a family.
Concerning point 1, I would just like to avoid theget_...()but why not keeping it as you propose or as Vadim using abpm_arrayfield instead of bpms.
It is subjective.I think an element and an array should have the same interface. Having
magnetandmagnetsis very confusing and so is havingstrengthandstrengths. I don't think that is a good user interface. I think a user shouldn't need to know if something is a single device or an array because that is to some extent a configuration choice. They should be able to use them in the same way.But I think it also relates to the interface we are still missing to be able to get/set independently of unit. The users are not supposed to do
sr.design.magnet.strength.get()but justsr.design.magnet.get()or optionally something likesr.design.magnet.get('physics')in case they want to specify another view than the one that has been set as default. Without that interface it's not possible to write applications that can be used by all machines.If that's the interface I'm not sure why
strengthswould be needed? Then an array only need to call the underlying get on the elements in the array and I don't think there is any need for it to define it's own strength attribute?
Here is my proposal to simplify further the API to access elements after #430
@JeanLucPons @TeresiaOlsson @gupichon-soleil @gubaidulinvadim @kparasch
Context
Follow-up of #430 / #199. After #430 every element family has two accessors:
sr.design.magnetsr.design.magnetscombined_function_magnetcombined_function_magnetsserialized_magnetserialized_magnetsdiagnostic.bpmdiagnostic.bpmsBefore #430 the split made sense: the singular accessor looked up one element and the plural one looked up families. Since #430, the plural accessor can do almost everything the singular one does, so having both is redundant. It is also confusing: users have to remember singular vs plural, and some first thought one of them was a typo.
Results are also inconsistent:
Proposal
Keep one accessor per family, named after the type, in the singular:
magnet,combined_function_magnet,serialized_magnet,diagnostic.bpm. Remove the plural ones.The accessor has a small, explicit set of methods. The method you call decides what comes back, not whether
the name is singular or plural:
Rules:
get(name)always returns one element, andget_array(name)/ attribute access always return a configured array. This is the way we access element/arrays in pyAML code internally. Each has one precise return type, so static typing and IDE autocompletion stay accurate (this answers@JeanLucPons's concern about generic signatures).
[key]is the interactive shortcut: a literal name gives the element, a pattern gives a typed array. One rule everywhere.Element names and family names live in separate namespaces (
get/[]for elements,get_array/attribute for families), so they never clash.The same
get/get_arrayconvention applies at the root of the holder. Todaysr.design.get(name)returns an array (ElementHolder.get), whilerf.get(name),tool.get(name)anddiagnostic.get(name)already return a single element. The root is the odd one out, so we align it:After this,
getmeans "one element" andget_arraymeans "an array" everywhere in the API.The alternative proposal is to just use
["key"]for everything but I think the concern of @JeanLucPons are justified. At least internally, in the pyAML codebase, it's very good to have exact ways to get element/array separated.Same problem one level down:
strengthvsstrengthsThe value accessors have the same singular/plural problem, and the plural is not used consistently:
get()returnsMagnetstrength,hardwareCombinedFunctionMagnet(one element)strengths,hardwaresSerializedMagnets(group of N magnets)strength,hardwareMagnetArray,CombinedFunctionMagnetArray,SerializedMagnetsArraystrengths,hardwaresBPMpositions,offset,tilt[x, y],[x, y], scalarBPMArraypositions,h,v(nooffset/tilt)A single CFM uses the plural but a serialized group uses the singular, and
offsetis singular butpositionsis plural.
Proposal: use the same attribute name on an element and on an array. Whether
get()returns a scalar or a vector depends on the object, not on the attribute name:get()returnsMagnetstrength,hardwareCombinedFunctionMagnetstrength,hardwareSerializedMagnetsstrength,hardwarestrength,hardwareBPM/BPMArrayposition,offset,tilt, plush/von bothI think that what is done on the Element/Array level is enough to have a clear difference.
BPMArraygainsoffset/tiltandBPMgainsh/v, so the same code works on one BPM or on an array.Implementation
These two topics can be covered in two sub-issues and their related PR.
We could merge
GenericElementHolderandGenericArrayHolder(pyaml/common/holders/) into a singleGenericHolder, and merge eachXHolder/XsHolderpair insub_holders.pyinto one class. Then update the internal callers (tuning tools:peer.magnets.get(...)→peer.magnet.get_array(...)), the tests, the examples/notebooks and the docs.At the root,
ElementHolder.get(name)returnsself._get_element(name), and_get_arraybecomes the publicget_array(name=None).