Skip to content

SRS 830 LockIn Driver#139

Merged
giulioungaretti merged 18 commits into
masterfrom
srs830-dev
Jun 30, 2016
Merged

SRS 830 LockIn Driver#139
giulioungaretti merged 18 commits into
masterfrom
srs830-dev

Conversation

@spauka

@spauka spauka commented May 2, 2016

Copy link
Copy Markdown
Contributor

Instrument driver for the Stanford Research Systems SRS830 Lockin Amplifier

There are still a couple of todo's left, however at this point it is able to take data.
Still remaining is:

  • Still some parameters not coded, such as Auxilliary In/Out and display options.
  • Complete getters and setters for range and time constant parameters
  • Write an auto-offset operation

@alexcjohnson
I wrote a new validator for boolean-type values, it seems like this sort of parameter is generic enough to warrant a new validator. It may also make sense to create a getter/setter shared between instruments as on/off type values will occur often. Whether or not this is the best way of handling it, we should come up with a guideline for handling this sort of parameter.

spauka added 2 commits May 2, 2016 17:20
Add a validator for boolean type values such as on/off, true/false etc.

TODO: Follow this up with a getter/setter that can handle these values
as defined here
Initial commit for the SRS 830 Lockin Amplifier.

Still a couple of TODO's before it is feature complete however there is
enough here to start taking data off instruments.
@alexcjohnson

Copy link
Copy Markdown
Contributor

@spauka cool! The driver looks very good so far.

We do have a Bool validator... it maps onto actual booleans rather than numbers or strings. cc @AdriaanRol @MerlinSmiles we've had various drivers handle boolean parameters differently so far, I feel like we should standardize.

My own preference would be to always use True and False as long as it's obvious which is which, and not allow strings or numbers. As it is, you could have one person set the parameter to 'on', another to 1 or 'true' (or equivalently, you set the parameter and later get it), and the system would be in the same state but the parameter looks different, so you can't write simple code like if sr830.sync_filter.get()=='on': ..., you'd have to know about all the "on" values.

Comment thread qcodes/instrument_drivers/SRS/SR830.py Outdated

def set_tc(self, val):
return 0

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor style point - can you set your editor to always strip trailing whitespace on save? It just makes awkward diffs in the future when someone else's unrelated commit does it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, done :)

@AdriaanRol

Copy link
Copy Markdown
Contributor

@alexcjohnson , I agree on having a convention for Bools. However the problem I see is that instruments usually have a status parameter, which can then be either On or Off. What would status = True mean? Moreover, what would happen if we apply the same logic to an AWG, some old version may only have status = running and idle in which case we would stick to the Bool convention and a new version may have Idle, Running, Waiting for trigger. In which case the boolean convention breaks down.

So what convention do you propose?

@alexcjohnson

Copy link
Copy Markdown
Contributor

The main point of my comment is I don't think we should be allowing multiple values that mean the same thing when setting a parameter. If we let every user choose whether to set the parameter True, 1, 'ON', 'On', 'on', etc... it will cause problems SOMEWHERE no matter how we handle it upfront.

You're right, status doesn't map nicely onto True/False - so in that case either we make the options be eg 'on' and 'off' or we change the parameter name to something that's clearly a boolean. on could work, but since we have the __call__ syntax it's weird to think of inst.on() as returning a value, that looks more like you're turning it on. outputting seems clear but awkward... perhaps is_on?

The possibility of values proliferating later on is a good point - for some parameters it would probably be hard to imagine the hardware changing to accept more than two options, so you can safely name them to be clearly boolean and move on. And if a parameter like THAT suddenly accepts a third value you should change its name. So for the old AWG, you could make a running parameter, with values True and False... then when "waiting for trigger" comes along it's obviously not a boolean anymore so you should change the parameter name to status with values 'running', 'idle', and 'waiting'... that way code like if awg.running(): would break upfront, forcing you to be explicit about which of the new status value(s) you are accepting.

As a general convention for NON-boolean enums, I would propose the shortest clear lower-case word. I know @MerlinSmiles will complain about the keystrokes, he wants to type inst.status(1) instead of inst.status('on'), I would argue he should just make methods on and off in instruments that support this.

@spauka

spauka commented May 3, 2016

Copy link
Copy Markdown
Contributor Author

Agreed regarding bool for filter states.

I seems like now would be a good time to have a discussion about standardizing some of these naming/typing conventions. I suggest state or output_state for this sort of parameter? In terms of writing concise code, having the ability to pass boolean values into these on-off values makes sense.

@AdriaanRol

Copy link
Copy Markdown
Contributor

@alexcjohnson

So for the old AWG, you could make a running parameter,

I oppose changing variable names for instrument driers for the sake of Booleans. I think the name should be as close as possible to the one that is used in the manual of the specific instrument.

it's weird to think of inst.on() as returning a value, that looks more like you're turning it on.

In fact all the MW-sources I have written have the parameter status which accepts on off as inputs. There then exists a function .on() and .off which calls this parameter. I think on and off as functions sholud be exactly that.

As a general convention for NON-boolean enums, I would propose the shortest clear lower-case word.

I would propose allowing any capitalization and using .lower on the input to convert it to all lowercase.

So to summarize what I propose

  1. Do not change command names from an instrument for the sake of us
  2. Convenience functions for things like on and off while remaining status as parameter (whit string input)
  3. No case sensitivity on input (might require a change to validators)

@alexcjohnson

Copy link
Copy Markdown
Contributor

@AdriaanRol

1 Do not change command names from an instrument for the sake of us

Sounds like a good rule of thumb. That means most parameters like this will end up with string values rather than booleans, which also has the advantage of being more future-proof in case more options are added.

2 Convenience functions for things like on and off while remaining status as parameter (whit string input)

Yes, I had seen you do that - I agree. That should satisfy @MerlinSmiles 's fingers while maintaining

3 No case sensitivity on input (might require a change to validators)

This would be more than just a validator change - it would need to change the value you, the user, supplied, so that the stored (get_latest, or snapshot) value is consistently lower case too. I'm not a big fan of this, it adds complexity and could still lead to confusing bugs like this infinite loop:

while inst.status() != 'On':
    inst.status('On')

What's wrong with just standardizing on lowercase? People will learn quickly: when the validator rejects their capitalized word, it tells them what the allowed values are.

spauka added 2 commits May 4, 2016 11:58
Create a parser that checks for integer matches in the get_parser when a
val_mapping is given for an instrument.
return self._get_mapping[val]
except (ValueError, KeyError):
raise KeyError("Unmapped value from instrument: {:r}".format(val))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@spauka this looks reasonable, but can you give me an example or two of how you intend to use this? ie what are the specific commands you pass to the instrument on setting, responses on getting, and the corresponding val_mapping?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is used in a couple of places where the lockin uses integers to set some flag.
Used for mappings such as:

ILIN = {'Off': 0, 'Line': 1, '2xLine': 2, 'Both': 3}
RMOD = {'High_Reserve': 0, 'Normal': 1, 'Low_Noise': 2}

It would be possible to make the dictionaries map to strings instead, however it seems more logical to allow mapping to integers given that that is how they are described in the docs.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good - I think this is nice, integer codes come up all the time. I've added a test of it qdev-dk-archive@9f6cca9

Another way to do this would be to manipulate _get_mapping - since the input to this mapping (a raw return from the instrument) is always going to be a string, we could just force that from the outset:

self._get_mapping = {str(v): k for k, v in val_mapping.items()}

This would be a bit faster, since get doesn't have to go through the try/except, but it would behave differently in some cases: if the instrument for some reason padded its response with whitespace for example, your version would still work but not mine. Commands like this are unlikely to be time bottlenecks, I would imagine (they'll rarely be in the inner loop of an acquisition... so perhaps the whitespace behavior is enough reason to keep it as is.

@Rubenknex

Copy link
Copy Markdown
Contributor

I merged the functionality of spauka's and my SR830 driver. All parameters like sensitivity and time constant are now set using numbers, and have the appropriate units for measuring either voltages or current.

@alexcjohnson

Copy link
Copy Markdown
Contributor

@spauka I haven't looked in detail at this yet, but I encouraged @Rubenknex to bring his work into this PR. Can you take a look at it now and see if you're happy with it all?

@spauka

spauka commented Jun 18, 2016

Copy link
Copy Markdown
Contributor Author

I would express a personal preference for capitalizing parameters (ground->Ground), particularly in the case of initialisms (ac->AC, dc->DC). was looking over other drivers but there does not seem to much precedence here.

I would also express a preference for calling the company SRS, if for no other reason that the class name for the instrument becomes pretty long and inconvenient to type. I think we had a discussion at some point about instrument names, don't recall if this was raised?

Other than that, once missing features are completed this looks pretty good :)

@Rubenknex

Copy link
Copy Markdown
Contributor

I myself don't have a strong opinion about the parameter values yet. I think the point above by @alexcjohnson about standardizing lowercase is good, however like you say maybe an exception for acronyms should be made. The class name is indeed a bit long. But I think we shouldn't worry so much about naming conventions yet in new drivers until we agree on a proper standard, after which we can update the existing drivers.


def _set_units(self, units):
for param in [self.X, self.Y, self.R, self.sensitivity]:
param.units = units

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not seem to update the units of that parameter, at least when it is remote, or does that work for you?

Merlin added 2 commits June 18, 2016 15:31
refactor: made those conversion tables (constant) class attributes
- Capitalized acronyms
- Change current input config options
@Rubenknex

Copy link
Copy Markdown
Contributor

@MerlinSmiles I changed the input config options for current measurement. What did you mean exactly with the remote parameters, I'm not familiar with those yet.

@MerlinSmiles

Copy link
Copy Markdown
Contributor

@Rubenknex Thats much clearer, maybe we should add docstrings to the parameters where it makes sense to have some? like the input config.

The remote parameters are a consequence of multiprocessing, there the instrument itself lives in a separate process, and all communication goes through queues, so just setting xx.units='A' is maybe not enough as it wont get transferred and updated to/from the instrument server.
But I have not the complete overview of that, that's where @alexcjohnson has to chime in.

@alexcjohnson

Copy link
Copy Markdown
Contributor

@MerlinSmiles that's right, I hadn't considered that these attributes could change when I wrote the remote stuff... We should change them into properties using getattr and setattr so the remote doesn't hold their state at all.

@Rubenknex

Copy link
Copy Markdown
Contributor

@MerlinSmiles So a parameter docstring is only meant to be used when a parameter requires some further explanation? Because I saw one instrument driver where most parameters had a docstring, but this would be like copying the instrument manual.

@MerlinSmiles

Copy link
Copy Markdown
Contributor

@Rubenknex actually I dont know. I think there is no need for a docstring when the parameter makes sense by itself, but I'm sure @giulioungaretti will yell at me for that statement. I think it makes sense when there are parameters with a few options, so one can check for the possibilities.

@Rubenknex

Copy link
Copy Markdown
Contributor

@MerlinSmiles Yes I agree with that. If the parameter docstrings will be used in the auto generated documentation of qcodes then I think it will be useful to people when writing measurement scripts.

@MerlinSmiles

Copy link
Copy Markdown
Contributor

@Rubenknex I'm sure that will happen. But also from an interactive environment to do a <shift><tab> and see the docstring is very handy.

@MerlinSmiles

Copy link
Copy Markdown
Contributor

But then we also have a problem with updating the docstring when changing the meaning of a parameter, @alexcjohnson

@alexcjohnson

Copy link
Copy Markdown
Contributor

I would think the docstring should describe all the possible behaviors of the parameter. It will be useful to people to see when a parameter has the possibility of changing in response to another one. That is also the only way this can be compatible with auto-generated docs - although I suspect this will be hard for drivers, you basically have to instantiate one before you can figure out what parameters even exist. It will be nearly impossible just by parsing the code, particularly in cases like making parameters inside a loop.

@MerlinSmiles

Copy link
Copy Markdown
Contributor

Hm, so how should we deal with this?
I think its very important to have the drivers in the documentation so the users can see whats there.

@alexcjohnson

Copy link
Copy Markdown
Contributor

We'll still get all the regular docstrings, so it'll be easy to see all of the static docs. It's just Parameters and Functions that will be tricky. I'm sure we'll come up with a solution at some point, but at least initially it may involve things like documenting that there's a parameter named 'chan{}'. Perhaps @giulioungaretti has clever ideas about this?

Actually, this connects with another issue, making some sort of tests instrument drivers can run offline - so we avoid problems like #202 IDN breaking everything. I have some ideas about this (it basically requires giving the qcodes core a nice way to override the real comm channels with mocks, and the driver writer describing enough expected commands and responses that the driver thinks it's connected to a real instrument enough to initialize and run a couple of tests) but if we do make that work, we'd have an instance independent of real hardware from which we could generate auto docs. It would be a bit of extra work for the driver writer, but if it came with twin benefits of offline tests and good auto docs I imagine people could get interested in it.

@giulioungaretti

Copy link
Copy Markdown
Contributor

@MerlinSmiles

Copy link
Copy Markdown
Contributor

@giulioungaretti when the meaning of sensitivity chages from volts to amps the docstring needs to be updated too, no? Not sure how that works with #244 though.

@alexcjohnson

Copy link
Copy Markdown
Contributor

@giulioungaretti when the meaning of sensitivity chages from volts to amps the docstring needs to be updated too, no?

As I said above I would argue the docstring would be more useful if it described all possible behaviors, regardless of what it's doing right now. So then it doesn't need to change.

@AdriaanRol

Copy link
Copy Markdown
Contributor

@alexcjohnson , @giulioungaretti

As I said above I would argue the docstring would be more useful if it described all possible behaviors,

How about supporting both? The default docstring explains both options but also shows which one is currently selected. I feel that having the current one in there is quite important for usability, however I also feel that that is a different issue unrelated to the quality of this driver.

@alexcjohnson

Copy link
Copy Markdown
Contributor

How about supporting both? The default docstring explains both options but also shows which one is currently selected. I feel that having the current one in there is quite important for usability, however I also feel that that is a different issue unrelated to the quality of this driver.

Yes, I can see that. This would work fine for local instruments, but unfortunately it's not so easy for remote ones. For annoying reasons that I can't seem to get around, we can't have the remote query the server every time the docstring is requested, so we would have to have the remote somehow know, from the server, when there has been a change to the docstring. I described this problem a bit in https://github.com/qdev-dk/Qcodes/pull/244#issuecomment-228189701

Anyway, quite right that this is a separate issue. What are we still waiting for to merge this? I don't think we need feature completeness, future PRs can add in missing pieces, but we should make sure features that are here aren't broken. Also naming conventions? I agree that SRS is nicer than stanford_research_systems as long as everyone will know what that means - but I'm not sure that's true if we would like qcodes to be accessible to folks outside our community.

Re: capitalization - for parameter names I would like to follow the python attribute naming convention, which is normally lowercase or snake_case. For (string) parameter values I don't have such a strong opinion but I think it will be easiest to use if we standardize, and the standard I would vote for is lowercase.

@giulioungaretti

Copy link
Copy Markdown
Contributor

As far as code goes I 💃 this! merge conflicts are now fixed.
I will summarise and split the discussion in new issues. @MerlinSmiles @spauka @Rubenknex @Rubenknex

@alexcjohnson

Copy link
Copy Markdown
Contributor

Just one more quick discussion on naming - since the folder name here conflicts with #190 where @MerlinSmiles has a driver for SR560. What Merlin did is:
instrument_drivers.stanford_research.SR_560.SR_560
I might take out the _ in the model number (so it matches what's written on the front panel of these boxes):
instrument_drivers.stanford_research.SR560.SR560
But I think this is both completely unambiguous and discoverable, any objections to using that style here too?

@spauka

spauka commented Jun 30, 2016

Copy link
Copy Markdown
Contributor Author

Looks good, I prefer the shorter name as well. To confirm this would make
the full path: instrument_drivers.stanford_research.SR830, the class name
is SR830.

On Thu, 30 Jun 2016 at 18:24 alexcjohnson notifications@github.com wrote:

Just one more quick discussion on naming - since the folder name here
conflicts with #190 https://github.com/qdev-dk/Qcodes/pull/190 where
@MerlinSmiles https://github.com/MerlinSmiles has a driver for SR560.
What Merlin did is:
instrument_drivers.stanford_research.SR_560.SR_560
I might take out the _ in the model number (so it matches what's written
on the front panel of these boxes):
instrument_drivers.stanford_research.SR560.SR560
But I think this is both completely unambiguous and discoverable, any
objections to using that style here too?


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/qdev-dk/Qcodes/pull/139#issuecomment-229594359, or mute
the thread
https://github.com/notifications/unsubscribe/AAmyvO-6qy7BMY3_t6LmJTs_F4SqHifsks5qQ30ngaJpZM4IVLO4
.

@alexcjohnson

Copy link
Copy Markdown
Contributor

the full path: instrument_drivers.stanford_research.SR830, the class name is SR830.

Exactly.

@giulioungaretti

Copy link
Copy Markdown
Contributor

@spauka @alexcjohnson cool, then I will just go ahead and make this change

Reflect the model number/name on front panel and simplify the path.
@giulioungaretti

Copy link
Copy Markdown
Contributor

merging now, later an or few issues will be made to summarise some of the points that came up!

@giulioungaretti giulioungaretti merged commit f10d9ff into master Jun 30, 2016
@giulioungaretti giulioungaretti deleted the srs830-dev branch June 30, 2016 14:58
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.

6 participants