'Return vectors in local coordinates representing the width and height of a view pixel.
If direction is specified, then return vectors parallel and orthogonal to it.
Return (None, None) if pixel size is not yet defined (usually because the item has not yet been displayed)
or if pixel size is below floating-point precision limit.'

def pixelVectors(self, direction=None):

    dt = self.deviceTransform()
    if (dt is None):
        return (None, None)
    dt.setMatrix(dt.m11(), dt.m12(), 0, dt.m21(), dt.m22(), 0, 0, 0, 1)
    if ((direction is None) and (dt == self._pixelVectorCache[0])):
        return tuple(map(Point, self._pixelVectorCache[1]))
    key = (dt.m11(), dt.m21(), dt.m12(), dt.m22())
    pv = self._pixelVectorGlobalCache.get(key, None)
    if ((direction is None) and (pv is not None)):
        self._pixelVectorCache = [dt, pv]
        return tuple(map(Point, pv))
    if (direction is None):
        direction = QtCore.QPointF(1, 0)
    if (direction.manhattanLength() == 0):
        raise Exception('Cannot    compute    pixel    length    for    0-length    vector.')
    directionr = direction
    dirLine = QtCore.QLineF(QtCore.QPointF(0, 0), directionr)
    viewDir = dt.map(dirLine)
    if (viewDir.length() == 0):
        return (None, None)
    try:
        normView = viewDir.unitVector()
        normOrtho = normView.normalVector()
    except:
        raise Exception(('Invalid    direction    %s' % directionr))
    dti = fn.invertQTransform(dt)
    pv = (Point(dti.map(normView).p2()), Point(dti.map(normOrtho).p2()))
    self._pixelVectorCache[1] = pv
    self._pixelVectorCache[0] = dt
    self._pixelVectorGlobalCache[key] = pv
    return self._pixelVectorCache[1]
