Source code for handwriting_features.features.implementation.conventional.temporal

import numpy


[docs] def stroke_duration(sample_wrapper, in_air): """ Returns stroke duration. :param sample_wrapper: sample wrapper object :type sample_wrapper: HandwritingSampleWrapper :param in_air: in-air flag :type in_air: bool :return: stroke duration :rtype: numpy.ndarray or np.NaN """ # Get the strokes strokes = sample_wrapper.on_surface_strokes \ if not in_air \ else sample_wrapper.in_air_strokes # Check the presence of strokes if not strokes: return numpy.nan # Return the stokes duration return numpy.array([max(stroke.time) - min(stroke.time) for stroke in strokes])
[docs] def ratio_of_stroke_durations(sample_wrapper): """ Returns ratio of stroke durations: on-surface / in-air. :param sample_wrapper: sample wrapper object :type sample_wrapper: HandwritingSampleWrapper :return: ratio of stroke durations :rtype: numpy.ndarray or np.NaN """ # Get on-surface and in-air stroke durations on_surface_strokes = stroke_duration(sample_wrapper, in_air=False) in_air_strokes = stroke_duration(sample_wrapper, in_air=True) # Check the presence of the stroke durations if any((not isinstance(on_surface_strokes, numpy.ndarray), not isinstance(in_air_strokes, numpy.ndarray))): return numpy.nan # Get the ratio between the stroke durations ratio = [(x / (y + numpy.finfo(float).eps)) for x, y in zip(on_surface_strokes, in_air_strokes)] ratio = numpy.array(ratio) if ratio else numpy.nan # Return the ratio return ratio
[docs] def writing_duration(sample_wrapper, in_air): """ Returns writing duration. :param sample_wrapper: sample wrapper object :type sample_wrapper: HandwritingSampleWrapper :param in_air: in-air flag :type in_air: bool :return: writing duration :rtype: float """ return numpy.sum(stroke_duration(sample_wrapper, in_air))
[docs] def writing_duration_overall(sample_wrapper): """ Returns overall writing duration. :param sample_wrapper: sample wrapper object :type sample_wrapper: HandwritingSampleWrapper :return: overall writing duration :rtype: float """ return float(sample_wrapper.sample_time[-1] - sample_wrapper.sample_time[0])
[docs] def ratio_of_writing_durations(sample_wrapper): """ Returns ratio of writing durations: on-surface / in-air. :param sample_wrapper: sample wrapper object :type sample_wrapper: HandwritingSampleWrapper :return: ratio of writing durations :rtype: float """ # Get on-surface and in-air writing durations on_surface_writing_duration = writing_duration(sample_wrapper, in_air=False) in_air_writing_duration = writing_duration(sample_wrapper, in_air=True) # Check the presence of the writing durations if any((not numpy.isfinite(on_surface_writing_duration), not numpy.isfinite(in_air_writing_duration))): return numpy.nan # Return the ratio between the writing durations return on_surface_writing_duration / (in_air_writing_duration + numpy.finfo(float).eps)
[docs] def number_of_interruptions(sample_wrapper): """ Returns the number of interruptions. :param sample_wrapper: sample wrapper object :type sample_wrapper: HandwritingSampleWrapper :return: number of interruptions :rtype: float """ # Get the pen status pen_status = sample_wrapper.sample_pen_status # Return the number of interruptions return float(max(sum(abs(numpy.logical_xor(pen_status[:-1], pen_status[1:]))), 0))
[docs] def number_of_interruptions_relative(sample_wrapper): """ Returns the number of interruptions relative to the duration. :param sample_wrapper: sample wrapper object :type sample_wrapper: HandwritingSampleWrapper :return: number of interruptions relative to the duration :rtype: float """ # Get the number of interruptions and the overal writing duration interruptions = number_of_interruptions(sample_wrapper) duration = writing_duration_overall(sample_wrapper) # Return the number of interruptions relative to the duration return interruptions / (duration + numpy.finfo(float).eps)