bluesky / hklpy

Diffractometer computation library with ophyd pseudopositioner support
https://blueskyproject.io/hklpy
BSD 3-Clause "New" or "Revised" License
3 stars 11 forks source link

TwoC geometry: ValueError: Unknown engine name or type #165

Open prjemian opened 3 years ago

prjemian commented 3 years ago

While the 2-circle geometry and calculations are admittedly trivial to implement separately in a PseudoPositioner, an exception is raised (see below) while trying to create an instance of hkl.geometries.TwoC or an instance of hkl.calc.CalcTwoC. It comes down to this inescapable fact: the list of engines for TwoC geometry is empty [as defined in the libhkl library](https://repo.or.cz/hkl.git/blob/HEAD:/hkl/hkl-engine-2c.c#l56).

static HklEngineList *hkl_engine_list_new_twoC(const HklFactory *factory)
{
    HklEngineList *self = hkl_engine_list_new();

    return self;
}

Since the hkl.calc.CalcRecip constructor provides a default "hkl" for an undefined engine kwarg, it is not possible to override and pass a None through as the TwoC calc is being constructed,


Exception

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
~/Documents/projects/Bluesky/hklpy/hkl/calc.py in engine(self, engine)
    210             try:
--> 211                 self._engine = engines[engine]
    212             except KeyError:

KeyError: 'hkl'

During handling of the above exception, another exception occurred:

ValueError                                Traceback (most recent call last)
<ipython-input-7-62ebf9de0150> in <module>
      1 import hkl.geometries
----> 2 cc = hkl.geometries.TwoC("", name="cc")

~/Documents/projects/Bluesky/hklpy/hkl/diffract.py in __init__(self, prefix, calc_kw, decision_fcn, calc_inst, configuration_attrs, read_attrs, **kwargs)
    204                 calc_kw = {}
    205 
--> 206             self._calc = self.calc_class(lock_engine=True, **calc_kw)
    207 
    208         if not self.calc.engine_locked:

~/Documents/projects/Bluesky/hklpy/hkl/calc.py in __init__(self, **kwargs)
    703         # FIXME: Cannot create: TwoC has **no engines** defined in libhkl
    704         # CalcRecip has default engine="hkl" as constructor kwarg.
--> 705         super().__init__("TwoC", **kwargs)
    706 
    707 

~/Documents/projects/Bluesky/hklpy/hkl/calc.py in __init__(self, dtype, engine, sample, lattice, degrees, units, lock_engine, inverted_axes)
    159                 self.new_sample(sample, lattice=lattice)
    160 
--> 161         self.engine = engine
    162 
    163     @property

~/Documents/projects/Bluesky/hklpy/hkl/calc.py in wrapped(self, *args, **kwargs)
     53     def wrapped(self, *args, **kwargs):
     54         with self._lock:
---> 55             return func(self, *args, **kwargs)
     56 
     57     return wrapped

~/Documents/projects/Bluesky/hklpy/hkl/calc.py in engine(self, engine)
    211                 self._engine = engines[engine]
    212             except KeyError:
--> 213                 raise ValueError("Unknown engine name or type")
    214 
    215         self._re_init()

ValueError: Unknown engine name or type
prjemian commented 3 years ago

@klauer Was this ever tested?

klauer commented 3 years ago

@prjemian I have no recollection of it

prjemian commented 3 years ago

I recommend we drop this geometry for now. Otherwise, this will take some refactoring of CalcRecip to get around this one geometry. I'd recommend the upstream libhkl be changed instead, to add a q engine, since that is the only one that makes any sense: q = (4pi/lambda)sin(tth/2) -- hkl* makes no sense for TwoC and that ruins the engine="hkl" default in CalcRecip.__init__(). TwoC would still need a special case.

prjemian commented 3 years ago

Since TwoC is not supported by libhkl, the theta-2theta geometry seems an ideal case for support with an alternative back-end (as substitute for libhkl). See, for example, issues #14, #162, and #163. The geometry is simple but full support would require most, if not all, of the alternative back-end to be functional.

prjemian commented 2 years ago

with hklpy v1.0.3:

In [1]: import hkl
   ...: 
   ...: class CalcTwoC(hkl.calc.CalcRecip):
   ...:     """Geometry: TwoC"""
   ...: 
   ...:     def __init__(self, **kwargs):
   ...:         super().__init__("TwoC", **kwargs)
   ...: 
   ...: class TwoC(hkl.diffract.Diffractometer):
   ...:     """2-circle"""
   ...: 
   ...:     calc_class = CalcTwoC
   ...: 
   ...: cc = hkl.TwoC("", name="cc", engine=None)
   ...: 
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Input In [1], in <cell line: 14>()
     10     """2-circle"""
     12     calc_class = CalcTwoC
---> 14 cc = hkl.TwoC("", name="cc", engine=None)

AttributeError: module 'hkl' has no attribute 'TwoC'
prjemian commented 2 years ago

Definitely for v1.2 milestone, needs