Skip to content

Registering Custom Operations

The purpose of this functionality is to provide an extension mechanism for KDB-X Python allowing users to register extension logic for KDB-X Python.

Specifically this allows users to:

  1. Extend the supported conversions from Pythonic types to KDB-X Python objects when using the pykx.toq function
  2. Extend the supported custom functions on pykx.Column objects

pykx.register

Functionality for the registration of conversion functions between KDB-X Python and Python

py_toq

py_toq(py_type, conversion_function, *, overwrite=False)

Register conversion logic for a specified Python type when converting it to a pykx object.

Note

The return of registered functions should be a valid pykx object type returns of Pythonic types can result in unexpected errors

Warning

Application of this functionality is at a users discretion, issues arising from overwritten default conversion types are unsupported

Parameters:

Name Type Description Default
py_type Any

The type signature used for determining when a conversion should be triggered for KDB-X Python, in particular this will check the type(x) on incoming data to determine this.

required
conversion_function Callable

The function/callable which will be used to convert the supplied object to a KDB-X Python object specified by the user.

required
overwrite bool

If a definition for this type already exists should it be overwritten by default this is set to False to avoid accidental overwriting of conversion logic used within the library

False

Returns:

Type Description
None

A None object on successful invocation

Examples:

Register conversion logic for complex Python object types

>>> import pykx as kx
>>> kx.toq(complex(1, 2))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "pykx/toq.pyx", line 2543, in pykx.toq.ToqModule.__call__
  File "pykx/toq.pyx", line 245, in pykx.toq._default_converter
TypeError: Cannot convert <class 'complex'> '(1+2j)' to K object
>>> def complex_toq(data):
...    return kx.toq([data.real, data.imag])
>>> kx.register.py_toq(complex, complex_toq)
>>> kx.toq(complex(1, 2))
pykx.FloatVector(pykx.q('1 2f'))

Register conversion logic for complex Python objects overwriting previous logic above

>>> def complex_toq_upd(data):
...    return kx.q('{`real`imag!(x;y)}', kx.toq(data.real), kx.toq(data.imag)
>>> kx.register.py_toq(complex, complex_toq_upd, overwrite=True)
>>> kx.toq(complex(1, 2))
pykx.Dictionary(pykx.q('
real| 1
imag| 2
'))
>>>

column_function

column_function(name, conversion_function, overwrite=False)

Register a function to be accessible as a callable function off the kx.Column objects

Note

The return of this function should be a QueryPhrase object

Warning

Application of this functionality is at a users discretion, issues arising from overwritten default conversion types are unsupported

Parameters:

Name Type Description Default
name str

The name to be given to the method which can be used on a column

required
conversion_function Callable

The function/callable which will be applied when calling a query

required

Returns:

Type Description
None

A None object on successful invocation

Examples:

Register min-max scaler function for application on column

>>> import pykx as kx
>>> tab = kx.Table(data = {
...     'sym': kx.random.random(100, ['a', 'b', 'c']),
...     'true': kx.random.random(100, 100.0),
...     'pred': kx.random.random(100, 100.0)
... })
>>> def min_max_scaler(self):
...     return self.call('{(x-minData)%max[x]-minData:min x}')
>>> kx.register.column_function('minmax', min_max_scaler)
>>> tab.select(kx.Column('true') & kx.Column('true').minmax().rename('scaled_true'))

Register mean-absolute error function to be applied between 'true' and 'pred' columns

>>> import pykx as kx
>>> tab = kx.Table(data = {
...     'sym': kx.random.random(100, ['a', 'b', 'c']),
...     'true': kx.random.random(100, 100.0),
...     'pred': kx.random.random(100, 100.0)
... })
>>> def mean_abs_error(self, other):
...     return self.call('{avg abs x-y}', other)
>>> kx.register.column_function('mean_abs_error', mean_abs_error)
>>> tab.exec(kx.Column('pred').mean_abs_error(kx.Column('true')))
>>> tab.select(kx.Column('pred').mean_abs_error(kx.Column('true')), by=kx.Column('sym'))