calibration: support to-physical-only softcal boards.
authorW. Trevor King <wking@tremily.us>
Fri, 19 Oct 2012 13:53:22 +0000 (09:53 -0400)
committerW. Trevor King <wking@tremily.us>
Fri, 19 Oct 2012 13:53:22 +0000 (09:53 -0400)
This is a hack to fix Éric Piel's issue:

On Thu, Oct 18, 2012 at 12:10:49PM +0200, Éric Piel wrote:
> Unfortunately, with my device there seems to still be a problem with
> comedi_get_softcal_converter(), which returns -1 with direction
> from_physical. I get the same problem when using the SWIG wrapper, so
> it's probably not an error in pycomedi. So when I run cmd.py I get this
> error, but it works anyway as the _to_phys converter works:
> ./cmd.py -f /dev/comedi0 -s 0 -c 0 -a diff -N 1 -p
> Exception pycomedi.PyComediError:
> PyComediError('comedi_get_softcal_converter: Resource temporarily
> unavailable (-1)',) in
> 'pycomedi.channel.AnalogChannel.get_softcal_converter' ignored
> 0.220157

I feel like we should make an effort to invert the from_physical
polynomial, but as a stop-gap measure, we can just raise the original
exception and let the user decide what to do about it.

pycomedi/calibration.pxd
pycomedi/calibration.pyx
pycomedi/channel.pyx

index a0a687ae3e1bf2758689afbf224c073d709f0735..12a4e3f5911b846c782e88184bb7a4af7fe04178 100644 (file)
@@ -21,6 +21,7 @@ cimport _comedilib_h
 
 cdef class CalibratedConverter (object):
     cdef _comedilib_h.comedi_polynomial_t _to_physical, _from_physical
+    cdef object _from_physical_error
 
     cdef _str_poly(self, _comedilib_h.comedi_polynomial_t polynomial)
     cpdef to_physical(self, data)
index 70388de1911cace970d719405eb0b323ba4020a4..a3183e522367eb9080e1a9f6e71e5ab391cb877b 100644 (file)
@@ -161,11 +161,32 @@ cdef class CalibratedConverter (object):
     1.0
     >>> c.get_to_physical_coefficients()
     array([ 1.,  2.,  3.])
+
+    For some soft-calibrated boards, there is no from_physical
+    conversion polynomial.
+
+    >>> c = CalibratedConverter(
+    ...     from_physical_error=Exception('no conversion polynomial'))
+    >>> c.from_physical(1.0)
+    Traceback (most recent call last):
+      ...
+    Exception: no conversion polynomial
+
+    However, even with the error, you can extract dummy coefficients.
+
+    >>> c.get_from_physical_expansion_origin()
+    0.0
+    >>> c.get_from_physical_coefficients()
+    array([ 0.])
     """
+    def __cinit__(self):
+        self._from_physical_error = None
+
     def __init__(self, to_physical_coefficients=None,
                  to_physical_expansion_origin=0,
                  from_physical_coefficients=None,
-                 from_physical_expansion_origin=0):
+                 from_physical_expansion_origin=0,
+                 from_physical_error=None):
         if to_physical_coefficients:
             _setup_comedi_polynomial_t(
                 &self._to_physical, to_physical_coefficients,
@@ -174,6 +195,7 @@ cdef class CalibratedConverter (object):
             _setup_comedi_polynomial_t(
                 &self._from_physical, from_physical_coefficients,
                  from_physical_expansion_origin)
+        self._from_physical_error = from_physical_error
 
     cdef _str_poly(self, _comedilib_h.comedi_polynomial_t polynomial):
         return '{coefficients:%s origin:%s}' % (
@@ -194,6 +216,8 @@ cdef class CalibratedConverter (object):
                         _constant.CONVERSION_DIRECTION.to_physical)
 
     cpdef from_physical(self, data):
+        if self._from_physical_error is not None:
+            raise self._from_physical_error
         return _convert(&self._from_physical, data,
                         _constant.CONVERSION_DIRECTION.from_physical)
 
index 81f6df075fc22a47a7844a02cb72c215f8650cba..41cdbd31ea7a4eafd9824273e77c7f1f8b279a11 100644 (file)
@@ -420,23 +420,28 @@ cdef class AnalogChannel (Channel):
         cdef _comedilib_h.comedi_polynomial_t to_physical, from_physical
         cdef _CalibratedConverter ret
         flags = self.subdevice.get_flags()
+        from_physical_error = None
         if flags.soft_calibrated:
             if calibration is None:
                 calibration = self.subdevice.device.parse_calibration()
             to_physical = self.get_softcal_converter(
                 _constant.CONVERSION_DIRECTION.to_physical,
                 calibration)
-            from_physical = self.get_softcal_converter(
-                _constant.CONVERSION_DIRECTION.from_physical,
-                calibration)
+            try:
+                from_physical = self.get_softcal_converter(
+                    _constant.CONVERSION_DIRECTION.from_physical,
+                    calibration)
+            except _PyComediError as e:
+                from_physical_error = e
         else:
             to_physical = self.get_hardcal_converter(
                 _constant.CONVERSION_DIRECTION.to_physical)
             from_physical = self.get_hardcal_converter(
                 _constant.CONVERSION_DIRECTION.from_physical)
-        ret = _CalibratedConverter()
+        ret = _CalibratedConverter(from_physical_error=from_physical_error)
         ret._to_physical = to_physical
-        ret._from_physical = from_physical
+        if from_physical_error is not None:
+            ret._from_physical = from_physical
         return ret
 
     def get_converter(self, calibration=None):