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
Adapter and Instrument methods #567
Comments
Possibly related to #512 |
I see you point I think, although I'm wondering if the problem in #559 (i.e., the need to copy the |
@bilderbuchi I agree some guidelines could be extremely useful, prior to this I would make some effort to clarify the software architecture and what we target with |
In my understanding, looking at the code, I see the following:
If an adapter is not available, user can develop its own and pass to According to this interpretation, putting instrument behaviour/control inside an adapter could be inappropriate. Finally, Some open points:
Just sharing some ideas and doubts to encourage the contribution and have finally better documentation |
In this case a custom wrapper-class could be proposed to do the interfaceing between the properties in the instrument definition and the backend (adpter-class and lower HW IF) There is also the case that we have a mixed communcation, some pars are text-based and some are binary.
IMO, these should be defined in the Instrument class as I think they are instrument-specific
It might also be worth to think about if in this example the functionality added could also be ported to theunderlaying VISA lib, e.g. pyvisa,
SCPI itself also supports event-based communication, however for use with pyvisa, pyvisa-py and linux-gpib this is not fully supported yet. Commercial VISA libaries and other HW-drivers might support this.
We should not forget that not everybody working with pymeasure is the absolute python-developer. Good documentation is important and I also see it as some kind of advertising for a project. With this base there should be enough availble to build a libary of use-cases/sucess-stories which could be used as more advanced examples. But this might be out the scope of this discussion, back to the more technical discussion about the separation line between adapters and instruments |
Agreed on all points
I think we should probably choose a frame-based method (i.e., message frames are a header + payload), I've seen that in several non-SCPI instruments. After getting the safekeywords and dynamic properties issues sorted, this is near/at the top of my "big-feature" priority list. There is #296 and some beginning in #239 to review/adapt. Maybe it makes sense to take a stab at #249 first, to be able to test what the WIP implementation sends over the wire reasonably easily/without a device. PyVISA also has a RegisterBasedResource that might be useful, but investigating that is still todo.
The most frequent pattern is Channel classes derived from
IMO an Adapter-level concern, but controlled by the Instrument with params passed on during construction. Stuff like
Instrument initialiser, after the super call.
Depends, I guess. What do you mean with instrument "behaviour"? Protocol quirks? I think these should be in the adapter, especially if they are shared among several of that manufacturer's model. If having this is mandatory, the instrument implementor should make sure that only an appropriate Adapter instance (or int/str) is passed to the instrument initialiser (as otherwise the device would not work, anyway. Why do you need/want to use another PrologixAdapter if a specific adapter is available (I'm not familiar with the Prologix stuff)
I see
I don't know yet where pyvisa RegisterBasedResource fits in, and if that is actually maintained/used in the wild or just a skeleton. |
Yes, this is one thing we need to hash out -- if we have a non-messagebased adapter, how do we define our commands? Right now, everything revolves around To start with, I want to study #239 (again) to get a feeling for things.
can you explain/summarize that a little more? What is it?
Absolutely, see #102 and documentation . I think the docs could use a restructuring along the lines of https://documentation.divio.com/ and expansion as in that issue. Alas, manpower :-/ -- do you want to help out, with guidance/reviews from us? If so, let's continue in #102 |
Maybe my phrase was not clear and misleading;
I will have a look at this and might chime in some ideas/comments in #102 |
Thanks! |
I think we're focusing all our consideration on We could imagine to base everything on PyVISA and drop Prologix support. Other considerations are:
In my opinion, we may have two choices:
I agree, but when the flexibility defined is not enough, do we need to define a specific adapter or not (my current opinion is no).
I agree, but then I don't understand the code here https://github.com/pymeasure/pymeasure/blob/9f265683a2bd28e8a87139e8d01cad37baaafc27/pymeasure/instruments/toptica/adapters.py, where a custom adapter includes instrument specific settings that are lost when you are using a different adapter.
GPIB instruments can be interfaced with hardware adapters from National Instruments or other brands supported by PyVisa. You can also use Prologix hardware adapters that are much cheaper and offer a USB (Virtual serial port) or Ethernet interface (unfortunately Prologix is not yet suppoted by PyVISA, pyvisa/pyvisa#112). |
AFAIK, USB and LAN can be handled by PyVISA, too.
You'll notice that the instrument only accepty int/str and then uses only that specific adapter, so lost settings are not a concern. Any other adapter would not make sense/work anyway because of the specific communication quirks handled by that adapter.
Huh, I never understood our "adapter" as a (GoF) design pattern, but as encapsulating the hardware comm/protocol side of things (as opposed to the command set, which belongs to Instrument). At the same time, I did not realise the special role of prologix things as (if you allow the imprecision) "meta-adapters-in-between". |
Re supporting Prologix: Might be worth it to ping the pyvisa maintainer in that issue, he seems open to merging a PR (and there is some draft code below that comment). It sounds like you have experience/ a Prologix device to test -- maybe a PR adding prologix compatibility to pyvisa would be feasible? also, @paulgoulain who has been active was in that issue, too, maybe you can collaborate? Failing that, do we need to adapt If this is the main pain point:
Maybe we can find a design pattern to account for that use case? Off the top of my head, if a Probably would be easier to see if we can get Prologix support merged upstream, then we could probably really, as you say, retire most other adapters in favour of |
I had the same understanding of hardware adapter. In summary
The summary question could be, if I ignore for a moment Prologix and I always use VISAAdapter why do I need any other Adapter class at all ? |
I agree here, I understood the pymeasure "adapter" as encapsulating the communication behavior, while the "Instrument" defines the concrete command set, regardless over which type of communication they are actually sent. So, even if the
How about Mixins? I know, this adds complexity to the codebase, and new contributors would possibly need to understand how mixins work in the first place in python, but I think this could be solved through a good documentation, and possibly templates. Maybe this could be done even with fully fleshed out adapter classes like |
Yeah, Mixins could be a nice solution to this problem, as we typically only have to override a couple of classes. There are a couple of rules/guidelines to observe (order of inheritance, super usage, should be named I think here the scope is more limited and the changes are limited to a couple of adapter classes we control (so it's easier to ensure correct usage), so it might be the more attractive option this time around. So, a user story for the #586 case,
In
This way, there is no need to manually create various adapter subclasses Alternatively, we could put the mixin on the Instrument subclass ( |
My gut feeling is that last draft proposal from @bilderbuchi is preferred. In my mind, it is a more linear approach.
Regarding the |
Sorry for not numbering my alternatives. I'm assuming you mean this approach "put the mixin on the Instrument subclass". Correct?
Yes, it's a normal class. It is primarily convention that Python mixins are named
Yes (all classes inherit from
I'm afraid I don't fully understand. To clarify what I'm proposing (maybe you're saying the same):
The main question that I cannot yet answer: Can this approach deal with all "behaviour quirks" that are currently present in the codebase (often implemented in custom Adapter subclasses). This needs some research in the codebase.
Yes, this is in #409 (comment) |
EDIT: @bilderbuchi was faster. I do agree in general that instrument specific quirks in the communication feel a bit more on the side of the |
On the contrary, I like the fact that in Python, doing diamond inheritance does not make your code go 💥 (looking at you, C++) 😁 |
Well, yes, I do like it too, I just tend to sometimes disregard good practice and wildly add functionalities via Mixins because it's so convenient - this can be dangerous, I like your term of "footgun potential" :D. Now I am not sure which approach you named "adpater mixin". Full Instrument Mixin/Inheritance Static/Dynamic Adapter Level Mixin class
The code of the current adapters (VISAAdapter, PrologixAdapter etc) remains untouched, their methods might become overridden by a Mixin, if one is defined. Instrument Level Mixin class Instrument/Adapter Separated Mixin(s) (new on 2022/02/17) |
sorry about that >.< Thank you for compiling a summary with named alternatives! With "adapter mixin" I meant "Static/Dynamic Adapter Level Mixin class" |
Separately from listing these approaches in an agnostic way (I hope), in this naming, I prefer the Dynamic Adapter level Mixin. Changes to the codebase and the structure of the classes |
Actually, I meant that |
Yes, that is correct. |
I have added another approach, according to the last two comments by @msmttchr. I have to admit, I am now not sure I understand what you prefer in total, and I am not sure the added approach represents what you intend. If I understand you correctly, the initial idea of this issue was to move the So, I think we can separate some things here, although I now might not include all the topics discussed in the conversation:
As I understand the conversation now, we agree that instrument specific behavior would be best packed into a Personally, I think that |
@bklebel thanks a lot for your effort and energy to try to shed some light in this complex subject.
I think your understanding is correct, but allow me to further explain my point of view based on the code review and the exchange with @bilderbuchi and other people. [Of course, there is a certain degree of assumption/simplification and opinion that can be challenged] The strategy to manage instruments in PyMeasure was designed by using two main classes:
When an instrument was implemented using the
This design choice had some implications:
If you implement some part of the instrument behavior at Let's make an example, my instrument has a GPIB interface and I want to use the following hardware adapters to interface it:
First of of all I need to make sure that there is an Now let's assume, that my instrument has a bug/feature that requires a delay of at least 100 ms after each write command. If I do it at Instrument class level, on the other hand, I have to amend the My conclusion is that there is a degree of fuzziness and interpretation on My personal preference is that everything related to the instrument behavior (including protocol quirk or other stuff) is static and should be implemented at Instrument class level. Finally, I think your point of separating command part from communication part is worth discussing as a design choice for the instrument implementation, but in my opinion could be decided after the roles of |
My two cents as someone new to pymeasure: For the separation of communication and commands, there could be an optional |
I just looked at pyvisa's RegisterBasedResource. It is useful, if you can access the memory of the device itself, but you know how to do it right. Instead we should focus on the VISAAdapter. For frame based communication read_bytes and write_raw (pyvisa names) is necessary. Until now, only read_bytes is present. EDIT: The names of those methods could be |
One protocol quirk, which should be moved from the Adapter, is the "preprocess_reply", as it has nothing to do with the Adapter itself, more with the message composition (aka protocol). Maybe even the whole "values" method should be moved, wherever the protocol is: to the Instrument or another class which is between Adapter and Instrument. An argument for "values" in "Adapter" would be, that you could use the adapter's methods like pyvisa's query_ascii_values, but VISAAdapter.values does not use it either, probably exactly because you cannot preprocess the response. EDIT: |
My proposal is: This provides a single point (for each direction) of writing things and don't create confusion, why the pymeasure properties do not work, even though you change both read and write. All other methods (ask, values, etc.) are implemented either in the base EDIT
(list edited by @bilderbuchi ) |
As highlighted in #559 (comment) by @CodingMarco, there could be some design issue in the way
Instrument
andAdapter
class implement some methods.In particular,
values
andask
methods implemented inAdapter
class are simply calling other methods or making text processing which has nothing to do with low level instrument access.This requires, in certain circumstances, to reimplement them at
Instrument
class level even though no changes are needed.A possible solution is to move the default implementation of these methods from
Adapter
toInstrument
The text was updated successfully, but these errors were encountered: