Skip to content

Instantly share code, notes, and snippets.

@sirpercival
Created June 16, 2015 15:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sirpercival/5618e66a1ec16271228d to your computer and use it in GitHub Desktop.
Save sirpercival/5618e66a1ec16271228d to your computer and use it in GitHub Desktop.
Numpy-compatible properties
# -*- coding: utf-8 -*-
from kivy.compat import string_types
from kivy.properties cimport PropertyStorage
import numpy as np
cimport numpy as np
cdef float g_dpi = -1
cdef float g_density = -1
cdef float g_fontscale = -1
cpdef float dpi2px_np(value, ext):
# 1in = 2.54cm = 25.4mm = 72pt = 12pc
global g_dpi, g_density, g_fontscale
if g_dpi == -1:
from kivy.metrics import Metrics
g_dpi = Metrics.dpi
g_density = Metrics.density
g_fontscale = Metrics.fontscale
rv = np.min_scalar_type(value)
if ext == 'in':
return rv * g_dpi
elif ext == 'px':
return rv
elif ext == 'dp':
return rv * g_density
elif ext == 'sp':
return rv * g_density * g_fontscale
elif ext == 'pt':
return rv * g_dpi / 72.
elif ext == 'cm':
return rv * g_dpi / 2.54
elif ext == 'mm':
return rv * g_dpi / 25.4
cdef class NumpyricProperty(Property):
'''Property that represents a numeric value, with the flexibility of numpy dtypes.
:Parameters:
`defaultvalue`: a numeric value (any type that numpy can parse), defaults to 0 (int)
Specifies the default value of the property.
'''
def __init__(self, defaultvalue=0, **kw):
super(NumpyricProperty, self).__init__(defaultvalue, **kw)
cdef init_storage(self, EventDispatcher obj, PropertyStorage storage):
storage.numeric_fmt = 'px'
Property.init_storage(self, obj, storage)
cdef check(self, EventDispatcher obj, value):
if Property.check(self, obj, value):
return True
if np.min_scalar_type(value).kind not in 'biufc':
raise ValueError("%s.%s accepts numpy kinds 'biufc' (got %r)" % (
obj.__class__.__name__,
self.name, value))
cdef convert(self, EventDispatcher obj, x):
if x is None:
return x
tp = type(x)
mp = np.min_scalar_type(x).kind
if tp is tuple or tp is list:
if len(x) != 2:
raise ValueError('%s.%s must have 2 components (got %r)' % (
obj.__class__.__name__,
self.name, x))
return self.parse_list(obj, x[0], x[1])
elif isinstance(x, string_types):
return self.parse_str(obj, x)
elif mp in 'biufc':
return x
else:
raise ValueError('%s.%s has an invalid format (got %r)' % (
obj.__class__.__name__,
self.name, x))
cdef float parse_str(self, EventDispatcher obj, value):
return self.parse_list(obj, value[:-2], value[-2:])
cdef float parse_list(self, EventDispatcher obj, value, ext):
cdef PropertyStorage ps = obj.__storage[self._name]
ps.numeric_fmt = ext
return dpi2px_np(value, ext)
def get_format(self, EventDispatcher obj):
'''
Return the format used for Numeric calculation. Default is px (mean
the value have not been changed at all). Otherwise, it can be one of
'in', 'pt', 'cm', 'mm'.
'''
cdef PropertyStorage ps = obj.__storage[self._name]
return ps.numeric_fmt
cdef class ArrayProperty(Property):
def __init__(self, defaultvalue=np.empty(0), **kw):
super(ArrayProperty, self).__init__(defaultvalue, **kw)
cdef check(self, EventDispatcher obj, value):
if Property.check(self, obj, value):
return True
if not isinstance(value, np.ndarray):
raise ValueError('{}.{} accepts only numpy.ndarray'.format(
obj.__class__.__name__,
self.name))
cdef compare_value(self, a, b):
return np.all(a == b)
# -*- coding: utf-8 -*-
from kivy.properties cimport Property
from kivy._event cimport EventDispatcher
cdef class NumpyricProperty(Property):
cdef float parse_str(self, EventDispatcher obj, value)
cdef float parse_list(self, EventDispatcher obj, value, ext)
cdef class ArrayProperty(Property):
cdef check(self, EventDispatcher obj, value)
cdef compare_value(self, a, b)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment