microsoft / Qcodes

Modular data acquisition framework
http://microsoft.github.io/Qcodes/
MIT License
323 stars 309 forks source link

keithley 2000 readout error #961

Open peendebak opened 6 years ago

peendebak commented 6 years ago

From the code:

        self.add_parameter('trigger_count',
                           get_cmd='TRIG:COUN?',
                           get_parser=int,
                           set_cmd='TRIG:COUN {}',
                           vals=MultiType(Ints(min_value=1, max_value=9999),
                                          Enum('inf',
                                               'default',
                                               'minimum',
                                               'maximum')))

When doing an instrument.ask_raw('TRIG:COUN?') my device returns a string '+9.9e37'. This gives an error since int('+9.9e37' results in ValueError: invalid literal for int() with base 10: '+9.9e37'.

We might want to change the get_parser into lambda x: int(float(x)).

Also: since the get_parser is int, does the MultiType validator make sense?

@jenshnielsen @WilliamHPNielsen

jenshnielsen commented 6 years ago

I guess this is implemented in the same way as the Keysight 33xxx series driver in KeysightAgilent_33XXX.py where it uses 9.9e37 as the response to signal infinity?

It could probably be solved in the same way using a val mapping that looks something like this

        def val_parser(parser: type, inputstring: str) -> str:
            """
            Parses return values from instrument. Meant to be used when a query
            can return a meaningful finite number or a numeric representation
            of infinity

            Args:
                parser: Either int or float, what to return in finite
                    cases
                inputstring: The raw return value
            """

            inputstring = inputstring.strip()

            if float(inputstring) == 9.9e37:
                output = float('inf')
            else:
                output = float(inputstring)
                if parser == int:
                    output = parser(output)

            return output
peendebak commented 6 years ago

@jenshnielsen Ok, I see how the parser works. But from the KeysightAgilent_33XXX.py

            self.add_parameter('trigger_count',
                               label='Channel {} trigger count'.format(channum),
                               set_cmd='TRIGger{}:COUNt {{}}'.format(channum),
                               get_cmd='TRIGger{}:COUNt?'.format(channum),
                               vals=vals.Ints(1, 1000000),
                               get_parser=partial(val_parser, int)
                               )

The validator vals.Ints(1, 1000000), only accepts an int, but the parser can return a float. So the parameter there also seems inconsistent.

jenshnielsen commented 6 years ago

Yes I'm not sure that parameter makes sense in that context. burst_ncycles seems to make more sense.

In this case it should maybe return the string 'Inf' instead of a float('inf'). That way it will round trip correctly but you will naturally lose the ability to do math directly with the result