Пример #1
0
def test_TaskThread_onError():

    taskCalled = [False]
    onFinishCalled = [False]
    onErrorCalled = [False]

    def task():
        taskCalled[0] = True
        raise Exception('Task error')

    def onFinish():
        onFinishCalled[0] = True

    def onError(e):
        onErrorCalled[0] = str(e)

    tt = idle.TaskThread()
    tt.start()

    tt.enqueue(task, onFinish=onFinish, onError=onError)

    time.sleep(0.5)

    tt.stop()
    tt.join()

    assert taskCalled[0]
    assert onErrorCalled[0] == 'Task error'
    assert not onFinishCalled[0]
Пример #2
0
def test_TaskThread_dequeue():

    called = [False]

    def busyTask():
        time.sleep(0.5)

    def realTask():
        called[0] = True

    tt = idle.TaskThread()
    tt.start()

    tt.enqueue(busyTask)
    tt.enqueue(realTask, taskName='realTask')

    time.sleep(0.25)

    tt.dequeue('realTask')

    time.sleep(0.3)

    tt.stop()
    tt.join()

    assert not called[0]
Пример #3
0
def test_TaskThread():

    called = [False]

    def task():
        called[0] = True

    tt = idle.TaskThread()
    tt.start()

    tt.enqueue(task)

    time.sleep(0.5)

    tt.stop()
    tt.join()

    assert called[0]
Пример #4
0
def test_TaskThread_onFinish():

    taskCalled = [False]
    onFinishCalled = [False]

    def task():
        taskCalled[0] = True

    def onFinish():
        onFinishCalled[0] = True

    tt = idle.TaskThread()
    tt.start()

    tt.enqueue(task, onFinish=onFinish)

    time.sleep(0.5)

    tt.stop()
    tt.join()

    assert taskCalled[0]
    assert onFinishCalled[0]
Пример #5
0
    def __init__(self,
                 image,
                 name=None,
                 loadData=False,
                 dataRange=None,
                 threaded=False):
        """Create an ``ImageWrapper``.

        :arg image:     A ``nibabel.Nifti1Image`` or ``nibabel.Nifti2Image``.

        :arg name:      A name for this ``ImageWrapper``, solely used for
                        debug log messages.

        :arg loadData:  If ``True``, the image data is loaded into memory.
                        Otherwise it is kept on disk (and data access is
                        performed through the ``nibabel.Nifti1Image.dataobj``
                        array proxy).

        :arg dataRange: A tuple containing the initial ``(min, max)``  data
                        range to use. See the :meth:`reset` method for
                        important information about this parameter.

        :arg threaded:  If ``True``, the data range is updated on a
                        :class:`.TaskThread`. Otherwise (the default), the
                        data range is updated directly on reads/writes.
        """

        self.__image = image
        self.__name = name
        self.__taskThread = None

        # Save the number of 'real' dimensions,
        # that is the number of dimensions minus
        # any trailing dimensions of length 1
        self.__numRealDims = len(image.shape)
        for d in reversed(image.shape):
            if d == 1: self.__numRealDims -= 1
            else: break

        # Degenerate case - if every
        # dimension has length 1
        if self.__numRealDims == 0:
            self.__numRealDims = len(image.shape)

        # And save the number of
        # 'padding' dimensions too.
        self.__numPadDims = len(image.shape) - self.__numRealDims

        # Too many shapes! Figure out
        # what shape we should present
        # the data as (e.g. at least 3
        # dimensions). This is used in
        # __getitem__ to force the
        # result to have the correct
        # dimensionality.
        self.__canonicalShape = canonicalShape(image.shape)

        # The internal state is stored
        # in these attributes - they're
        # initialised in the reset method.
        self.__range = None
        self.__coverage = None
        self.__volRanges = None
        self.__covered = False

        self.reset(dataRange)

        if loadData:
            self.loadData()

        if threaded:
            self.__taskThread = idle.TaskThread()
            self.__taskThread.daemon = True
            self.__taskThread.start()
Пример #6
0
    def __init__(self,
                 name,
                 ndims,
                 nvals,
                 threaded=False,
                 settings=None,
                 textureFormat=None,
                 internalFormat=None,
                 **kwargs):
        """Create a ``Texture``.

        :arg name:           The name of this texture - should be unique.

        :arg ndims:          Number of dimensions - must be 1, 2 or 3.

        :arg nvals:          Number of values stored in each texture element.

        :arg threaded:       If ``True``, the texture data will be prepared on
                             a separate thread (on calls to
                             :meth:`refresh`). If ``False``, the texture data
                             is prepared on the calling thread, and the
                             :meth:`refresh` call will block until it has been
                             prepared.

        :arg settings:       Additional settings to make available through the
                             :class:`TextureSettingsMixin`.

        :arg textureFormat:  Texture format to use - if not specified, this is
                             automatically determined. If specified, an
                             ``internalFormat`` must also be specified.

        :arg internalFormat: Internal texture format to use - if not specified,
                             this is automatically determined.

        All other arguments are passed through to the initial call to
        :meth:`set`.

        .. note:: All subclasses must accept a ``name`` as the first parameter
                  to their ``__init__`` method, and must pass said ``name``
                  through to the :meth:`__init__` method.

        .. note:: In normal cases, the ``textureFormat`` and ``internalFormat``
                  do not need to be specified - they will be automatically
                  determined using the :func:`.data.getTextureType` function.
                  However, there can be instances where a specific texture type
                  needs to be used. In these instances, it is up to the calling
                  code to ensure that the texture data can be coerced into
                  the correct GL data type.
        """

        TextureBase.__init__(self, name, ndims, nvals)
        TextureSettingsMixin.__init__(self, settings)

        if ((textureFormat is not None) and (internalFormat is     None)) or \
           ((textureFormat is     None) and (internalFormat is not None)):
            raise ValueError('Both textureFormat and internalFormat '
                             'must be specified')

        self.__ready = False
        self.__threaded = threaded

        # The data, type and shape are
        # refreshed on every call to
        # set or refresh (the former
        # calls the latter)
        self.__data = None
        self.__dtype = None
        self.__shape = None
        self.__preparedData = None

        # The data is refreshed on
        # every call to set or refresh
        # These attributes are set by
        # the __determineTextureType
        # and __prepareTextureData
        # methods (which are called
        # by refresh)
        self.__voxValXform = None
        self.__invVoxValXform = None

        self.__autoTexFmt = textureFormat is None
        self.__texFmt = textureFormat
        self.__texIntFmt = internalFormat
        self.__texDtype = None

        # If threading is enabled, texture
        # refreshes are performed with an
        # idle.TaskThread.
        if threaded:
            self.__taskThread = idle.TaskThread()
            self.__taskName = '{}_{}_refresh'.format(
                type(self).__name__, id(self))

            self.__taskThread.daemon = True
            self.__taskThread.start()
        else:
            self.__taskThread = None
            self.__taskName = None

        self.set(**kwargs)
Пример #7
0
    def __init__(self, name, nvals=1, notify=True, threaded=None, **kwargs):
        """Create a ``Texture3D``.

        :arg name:      A unique name for the texture.

        :arg nvals:     Number of values per voxel. Currently must be either
                        ``1`` or ``3``.

        :arg notify:    Passed to the initial call to :meth:`refresh`.

        :arg threaded: If ``True``, the texture data will be prepared on a
                        separate thread (on calls to
                        :meth:`refresh`). If ``False``, the texture data is
                        prepared on the calling thread, and the
                        :meth:`refresh` call will block until it has been
                        prepared.


        All other keyword arguments are passed through to the :meth:`set`
        method, and thus used as initial texture settings.


        .. note:: The default value of the ``threaded`` parameter is set to
                  the value of :attr:`.fsl.utils.platform.Platform.haveGui`.
        """

        if nvals not in (1, 3):
            raise ValueError('nvals must be either 1 or 3')

        if threaded is None:
            threaded = fslplatform.haveGui

        texture.Texture.__init__(self, name, 3)

        self.__name = '{}_{}'.format(type(self).__name__, id(self))
        self.__nvals = nvals
        self.__threaded = threaded

        # All of these texture settings
        # are updated in the set method,
        # called below.
        self.__data = None
        self.__preparedData = None
        self.__prefilter = None
        self.__prefilterRange = None
        self.__resolution = None
        self.__scales = None
        self.__interp = None
        self.__normalise = None
        self.__normaliseRange = None

        # These attributes are modified
        # in the refresh method (which is
        # called via the set method below).
        self.__ready = True

        # These attributes are set by the
        # __refresh, __determineTextureType,
        # and __prepareTextureData methods.
        self.__voxValXform = None
        self.__invVoxValXform = None
        self.__textureShape = None
        self.__texFmt = None
        self.__texIntFmt = None
        self.__texDtype = None

        # If threading is enabled, texture
        # refreshes are performed with an
        # idle.TaskThread.
        if threaded:
            self.__taskThread = idle.TaskThread()
            self.__taskName = '{}_{}_refresh'.format(
                type(self).__name__, id(self))

            self.__taskThread.daemon = True
            self.__taskThread.start()
        else:
            self.__taskThread = None
            self.__taskName = None

        self.set(refresh=False, **kwargs)

        callback = kwargs.get('callback', None)

        self.__refresh(notify=notify, callback=callback)