def visualization(partitionId, iterator):
    # Setup MPI context
    import os
    os.environ["PMI_PORT"] = pmi_port
    os.environ["PMI_ID"] = str(partitionId)
    os.environ["PV_ALLOW_BATCH_INTERACTION"] = "1"
    os.environ["DISPLAY"] = ":0"

    numYears = 0
    localYears = []
    localAvgData = []
    for item in iterator:
        numYears += 1
        print(
            'visualize (partition %d) peeking at next year %s, shape = [%d, %d]'
            % (partitionId, item[0], item[1].shape[1], item[1].shape[0]))
        localYears.append(item[0])
        localAvgData.append(item[1])

    sizeX = localAvgData[0].shape[1]
    sizeY = localAvgData[0].shape[0]

    sliceSize = sizeX * sizeY
    localNumSlices = numYears
    size = localNumSlices * sliceSize

    print(
        'visualize, partition id = %d, sizeX = %d, sizeY = %d, sliceSize = %d, localNumSlices = %d, size = %d'
        % (partitionId, sizeX, sizeY, sliceSize, localNumSlices, size))

    # Copy data from iterator into data chunk
    t0 = time.time()
    count = 0
    globalSliceIndices = []
    dataChunk = np.arange(size, dtype=np.float32)
    sidChunk = np.arange(size, dtype=np.uint8)
    for localSliceIdx in range(len(localYears)):
        globalSliceIdx = allYearsList.index(localYears[localSliceIdx])
        globalSliceIndices.append(globalSliceIdx)
        nextAvgArray = localAvgData[localSliceIdx]
        (imgHeight, imgWidth) = nextAvgArray.shape
        for y in range(imgHeight):
            for x in range(imgWidth):
                count += 1
                pixelValue = nextAvgArray[y][x]
                destIdx = x + (y * sizeX) + (localSliceIdx * sliceSize)
                dataChunk[destIdx] = pixelValue
                sidChunk[destIdx] = globalSliceIdx

    t1 = time.time()
    print('%d # MPI Gather %s | %d' % (partitionId, str(t1 - t0), count))
    t0 = t1

    # Configure Paraview for MPI
    import paraview
    paraview.options.batch = True

    from vtk.vtkPVVTKExtensionsCore import vtkDistributedTrivialProducer
    from vtk.vtkCommonCore import vtkIntArray, vtkUnsignedCharArray, vtkFloatArray
    from vtk.vtkCommonDataModel import vtkImageData, vtkPointData

    # -------------------------------------------------------------------------

    dataset = vtkImageData()

    sliceIdxArray = vtkUnsignedCharArray()
    sliceIdxArray.SetName('Slice Index')
    sliceIdxArray.SetNumberOfComponents(1)
    sliceIdxArray.SetNumberOfTuples(size)

    dataArray = vtkFloatArray()
    dataArray.SetName('Annual Avg Temp')
    dataArray.SetNumberOfComponents(1)
    dataArray.SetNumberOfTuples(size)
    for i in range(size):
        dataArray.SetTuple1(i, dataChunk[i])
        sliceIdxArray.SetTuple1(i, sidChunk[i])

    minZ = globalSliceIndices[0]
    maxZ = globalSliceIndices[-1]

    print('partition %d extents: [%d, %d, %d, %d, %d, %d]' %
          (partitionId, 0, sizeX, 0, sizeY, minZ, maxZ + 1))
    dataset.SetExtent(0, sizeX, 0, sizeY, minZ, maxZ + 1)
    dataset.GetCellData().SetScalars(dataArray)

    procIdArray = vtkUnsignedCharArray()
    procIdArray.SetName('Process Id')
    procIdArray.SetNumberOfComponents(1)
    procIdArray.SetNumberOfTuples(size)

    for i in range(size):
        procIdArray.SetTuple1(i, partitionId)

    dataset.GetCellData().AddArray(procIdArray)
    dataset.GetCellData().AddArray(sliceIdxArray)

    t1 = time.time()
    print('%d # build resulting image data %s | ' %
          (partitionId, str(t1 - t0)))
    t0 = t1

    # -------------------------------------------------------------------------

    vtkDistributedTrivialProducer.SetGlobalOutput('Spark', dataset)

    from vtk.vtkPVClientServerCoreCore import vtkProcessModule
    from paraview import simple
    from vtk.web import server
    from paraview.web import wamp as pv_wamp
    from paraview.web import protocols as pv_protocols

    class _VisualizerServer(pv_wamp.PVServerProtocol):
        dataDir = '/data'
        groupRegex = "[0-9]+\\.[0-9]+\\.|[0-9]+\\."
        excludeRegex = "^\\.|~$|^\\$"
        allReaders = True
        viewportScale = 1.0
        viewportMaxWidth = 2560
        viewportMaxHeight = 1440

        def initialize(self):
            # Bring used components
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebFileListing(
                    _VisualizerServer.dataDir, "Home",
                    _VisualizerServer.excludeRegex,
                    _VisualizerServer.groupRegex))
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebProxyManager(
                    baseDir=_VisualizerServer.dataDir,
                    allowUnconfiguredReaders=_VisualizerServer.allReaders))
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebColorManager())
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebMouseHandler())
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebViewPort(
                    _VisualizerServer.viewportScale,
                    _VisualizerServer.viewportMaxWidth,
                    _VisualizerServer.viewportMaxHeight))
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebViewPortImageDelivery())
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebViewPortGeometryDelivery())
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebTimeHandler())
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebSelectionHandler())
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebWidgetManager())
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebKeyValuePairStore())
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebSaveData(
                    baseSavePath=_VisualizerServer.dataDir))
            # Disable interactor-based render calls
            simple.GetRenderView().EnableRenderOnInteraction = 0
            simple.GetRenderView().Background = [0, 0, 0]
            # Update interaction mode
            pxm = simple.servermanager.ProxyManager()
            interactionProxy = pxm.GetProxy('settings',
                                            'RenderViewInteractionSettings')
            interactionProxy.Camera3DManipulators = [
                'Rotate', 'Pan', 'Zoom', 'Pan', 'Roll', 'Pan', 'Zoom',
                'Rotate', 'Zoom'
            ]

    pm = vtkProcessModule.GetProcessModule()

    # -------------------------------------------------------------------------

    print('%d # > Start visualization - %s | ' %
          (partitionId, str(datetime.now())))

    # -------------------------------------------------------------------------

    args = Options()
    if pm.GetPartitionId() == 0:
        print('%d # ==> %d' % (partitionId, pm.GetPartitionId()))
        producer = simple.DistributedTrivialProducer()
        producer.UpdateDataset = ''
        producer.UpdateDataset = 'Spark'
        print(
            'rank 0 process setting whole extent to [%d, %d, %d, %d, %d, %d]' %
            (0, sizeX, 0, sizeY, 0, sizeZ))
        producer.WholeExtent = [0, sizeX, 0, sizeY, 0, sizeZ]
        server.start_webserver(options=args, protocol=_VisualizerServer)
        pm.GetGlobalController().TriggerBreakRMIs()

    print('%d # < Stop visualization - %s | ' %
          (partitionId, str(datetime.now())))
    yield (partitionId, nbMPIPartition)
def visualization(partitionId, iterator):
    # Setup MPI context
    import os
    os.environ["PMI_PORT"] = pmi_port
    os.environ["PMI_ID"] = str(partitionId)
    os.environ["PV_ALLOW_BATCH_INTERACTION"] = "1"
    os.environ["DISPLAY"] = ":0"

    # Extract iOffset
    iOffset = 0
    localSizeX = getMPISizeX(partitionId)
    size = localSizeX * sizeY * sizeY
    for i in range(partitionId):
        iOffset += getMPISizeX(i)

    # Copy data from iterator into data chunk
    t0 = time.time()
    count = 0
    dataChunk = np.arange(size, dtype=float)
    for item in iterator:
        count += 1
        globalIndex = item[0]
        pixelValue = item[1]
        # print('%d # %d: %f' % (partitionId, globalIndex, pixelValue))
        ijk = _ijk(globalIndex)
        ijk[0] -= iOffset
        destIdx = ijk[0] + (ijk[1] * localSizeX) + (ijk[2] * localSizeX *
                                                    sizeY)
        dataChunk[destIdx] = pixelValue

    t1 = time.time()
    print('%d # MPI Gather %s | %d' % (partitionId, str(t1 - t0), count))
    t0 = t1

    # Configure Paraview for MPI
    import paraview
    paraview.options.batch = True

    from vtk.vtkPVVTKExtensionsCore import vtkDistributedTrivialProducer
    from vtk.vtkCommonCore import vtkIntArray, vtkUnsignedCharArray, vtkFloatArray
    from vtk.vtkCommonDataModel import vtkImageData, vtkPointData

    # -------------------------------------------------------------------------
    # Data access helper
    # -------------------------------------------------------------------------

    def createSlice():
        size = sizeY * sizeY
        array = np.arange(size, dtype=float)
        return array

    def getSideSlice(offset, xSize):
        size = sizeY * sizeY
        slice = np.arange(size, dtype=float)

        for i in range(size):
            slice[i] = dataChunk[int(offset + (i * xSize))]
        return slice

    # -------------------------------------------------------------------------
    # Add ghost points from neighbors
    # -------------------------------------------------------------------------

    from mpi4py import MPI
    comm = MPI.COMM_WORLD
    remoteLowerSlice = None
    remoteUpperSlice = None

    if partitionId + 1 < nbMPIPartition:
        # Share upper slice
        remoteUpperSlice = createSlice()
        localUpperSlice = getSideSlice(localSizeX - 1, localSizeX)
        comm.Sendrecv(localUpperSlice, (partitionId + 1),
                      (2 * partitionId + 1), remoteUpperSlice,
                      (partitionId + 1), (2 * partitionId))
    if partitionId > 0:
        # Share lower slice
        remoteLowerSlice = createSlice()
        localLowerSlice = getSideSlice(0, localSizeX)
        comm.Sendrecv(localLowerSlice, (partitionId - 1),
                      (2 * (partitionId - 1)), remoteLowerSlice,
                      (partitionId - 1), (2 * (partitionId - 1) + 1))

    t1 = time.time()
    print('%d # MPI share %s | ' % (partitionId, str(t1 - t0)))
    t0 = t1

    # -------------------------------------------------------------------------

    dataset = vtkImageData()
    minX = 0
    maxX = 0
    for i in range(partitionId + 1):
        minX = maxX
        maxX += getMPISizeX(i)

    # -------------------------------------------------------------------------
    # Add slice(s) to data
    # -------------------------------------------------------------------------

    arrayWithSlices = vtkFloatArray()
    arrayWithSlices.SetName('Scalars')
    if remoteLowerSlice != None and remoteUpperSlice != None:
        # Add both slices
        minX -= 1
        maxX += 1
        localSizeX = maxX - minX
        newSize = localSizeX * sizeY * sizeY
        arrayWithSlices.SetNumberOfTuples(newSize)
        localOffset = 0
        for i in range(newSize):
            if i % localSizeX == 0:
                arrayWithSlices.SetTuple1(i, remoteLowerSlice[i / localSizeX])
            elif (i + 1) % localSizeX == 0:
                arrayWithSlices.SetTuple1(
                    i, remoteUpperSlice[((i + 1) / localSizeX) - 1])
            else:
                arrayWithSlices.SetTuple1(i, dataChunk[localOffset])
                localOffset += 1

    elif remoteLowerSlice != None:
        # Add lower slice
        minX -= 1
        localSizeX = maxX - minX
        newSize = localSizeX * sizeY * sizeY
        arrayWithSlices.SetNumberOfTuples(newSize)
        localOffset = 0
        for i in range(newSize):
            if i % localSizeX == 0:
                arrayWithSlices.SetTuple1(i, remoteLowerSlice[i / localSizeX])
            else:
                arrayWithSlices.SetTuple1(i, dataChunk[localOffset])
                localOffset += 1
    elif remoteUpperSlice != None:
        # Add upper slice
        maxX += 1
        localSizeX = maxX - minX
        newSize = localSizeX * sizeY * sizeY
        arrayWithSlices.SetNumberOfTuples(newSize)
        localOffset = 0
        for i in range(newSize):
            if (i + 1) % localSizeX == 0:
                arrayWithSlices.SetTuple1(
                    i, remoteUpperSlice[((i + 1) / localSizeX) - 1])
            else:
                arrayWithSlices.SetTuple1(i, dataChunk[localOffset])
                localOffset += 1

    dataset.SetExtent(minX, maxX - 1, 0, sizeY - 1, 0, sizeY - 1)
    dataset.GetPointData().SetScalars(arrayWithSlices)

    t1 = time.time()
    print('%d # build resutling image data %s | ' %
          (partitionId, str(t1 - t0)))
    t0 = t1

    # -------------------------------------------------------------------------

    vtkDistributedTrivialProducer.SetGlobalOutput('Spark', dataset)

    from vtk.vtkPVClientServerCoreCore import vtkProcessModule
    from paraview import simple
    from vtk.web import server
    from paraview.web import wamp as pv_wamp
    from paraview.web import protocols as pv_protocols

    class _VisualizerServer(pv_wamp.PVServerProtocol):
        dataDir = '/data'
        groupRegex = "[0-9]+\\.[0-9]+\\.|[0-9]+\\."
        excludeRegex = "^\\.|~$|^\\$"
        allReaders = True
        viewportScale = 1.0
        viewportMaxWidth = 2560
        viewportMaxHeight = 1440

        def initialize(self):
            # Bring used components
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebFileListing(
                    _VisualizerServer.dataDir, "Home",
                    _VisualizerServer.excludeRegex,
                    _VisualizerServer.groupRegex))
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebProxyManager(
                    baseDir=_VisualizerServer.dataDir,
                    allowUnconfiguredReaders=_VisualizerServer.allReaders))
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebColorManager())
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebMouseHandler())
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebViewPort(
                    _VisualizerServer.viewportScale,
                    _VisualizerServer.viewportMaxWidth,
                    _VisualizerServer.viewportMaxHeight))
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebViewPortImageDelivery())
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebViewPortGeometryDelivery())
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebTimeHandler())
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebSelectionHandler())
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebWidgetManager())
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebKeyValuePairStore())
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebSaveData(
                    baseSavePath=_VisualizerServer.dataDir))
            # Disable interactor-based render calls
            simple.GetRenderView().EnableRenderOnInteraction = 0
            simple.GetRenderView().Background = [0, 0, 0]
            # Update interaction mode
            pxm = simple.servermanager.ProxyManager()
            interactionProxy = pxm.GetProxy('settings',
                                            'RenderViewInteractionSettings')
            interactionProxy.Camera3DManipulators = [
                'Rotate', 'Pan', 'Zoom', 'Pan', 'Roll', 'Pan', 'Zoom',
                'Rotate', 'Zoom'
            ]

    pm = vtkProcessModule.GetProcessModule()

    # -------------------------------------------------------------------------

    print('%d # > Start visualization - %s | ' %
          (partitionId, str(datetime.now())))

    # -------------------------------------------------------------------------

    args = Options()
    if pm.GetPartitionId() == 0:
        print('%d # ==> %d' % (partitionId, pm.GetPartitionId()))
        producer = simple.DistributedTrivialProducer()
        producer.UpdateDataset = ''
        producer.UpdateDataset = 'Spark'
        producer.WholeExtent = [0, sizeX - 1, 0, sizeY - 1, 0, sizeY - 1]
        server.start_webserver(options=args, protocol=_VisualizerServer)
        pm.GetGlobalController().TriggerBreakRMIs()

    print('%d # < Stop visualization - %s | ' %
          (partitionId, str(datetime.now())))
    yield (partitionId, nbMPIPartition)
for s in range(Nslice):
    f[:] = 0
    b = tiltSeries[s, :, :].transpose().flatten()
    for i in range(Niter):
        for j in range(Nrow):
            row[:] = A[j, ].copy()
            row_f_product = np.dot(row, f)
            a = (b[j] - row_f_product) / rowInnerProduct[j]
            f = f + row * a * beta

    recon[s, :, :] = f.reshape((Nray, Nray))

# -------------------------------------------------------------------------

arr = recon.ravel(order='A')
# arr = recon.reshape(-1, order='F')
vtkarray = numpy_support.numpy_to_vtk(arr)

# -------------------------------------------------------------------------

dataset = vtkImageData()
dataset.SetDimensions(originalDimensions[0], originalDimensions[1],
                      originalDimensions[1])
dataset.GetPointData().SetScalars(vtkarray)

writer = vtk.vtkDataSetWriter()
writer.SetFileName('/tmp/recon.vtk')
writer.SetInputData(dataset)
writer.Write()

print('write file to /tmp/recon.vtk')
def processPartition(idx, iterator):
    print('==============> processPartition %d' % idx)
    import os
    os.environ["PMI_PORT"] = pmi_port
    os.environ["PMI_ID"] = str(idx)
    os.environ["PV_ALLOW_BATCH_INTERACTION"] = "1"
    os.environ["DISPLAY"] = ":0"

    import paraview
    paraview.options.batch = True

    from vtk.vtkCommonExecutionModel import vtkTrivialProducer
    from vtk.vtkPVVTKExtensionsCore import vtkDistributedTrivialProducer
    from vtk.vtkCommonCore import vtkIntArray, vtkUnsignedCharArray
    from vtk.vtkCommonDataModel import vtkImageData, vtkPointData, vtkCellData

    offset = 0
    for i in range(idx):
        offset += zSizes[i] * sliceSize
    size = zSizes[idx] * sliceSize

    maxIdx = 0
    minIdx = globalMaxIndex

    data = vtkIntArray()
    data.SetName('scalar')
    data.SetNumberOfTuples(size)
    data.Fill(0)

    for row in iterator:
        #print('pid: %d - %d | %d' % (idx, row[0], row[1]))
        data.SetValue(row[0] - offset, row[1])
        maxIdx = row[0] if row[0] > maxIdx else maxIdx
        minIdx = row[0] if row[0] < minIdx else minIdx

    print('pid %d - min: %d - max: %d' % (idx, minIdx, maxIdx))

    dataset = vtkImageData()
    minZ = 0
    maxZ = 0
    for i in range(idx + 1):
        minZ = maxZ
        maxZ += zSizes[i]

    print('%d extent %d, %d' % (idx, minZ, maxZ - 1))
    dataset.SetExtent(0, sizeX - 1, 0, sizeY - 1, minZ, maxZ - 1)
    dataset.GetPointData().SetScalars(data)

    print('%d - (%d, %d) - offset %d - size %d - dimension %d, %d, %d ' %
          (idx, minIdx - offset, maxIdx - offset, offset, size, sizeX, sizeY,
           zSizes[idx]))

    vtkDistributedTrivialProducer.SetGlobalOutput('Spark', dataset)

    from vtk.vtkPVClientServerCoreCore import vtkProcessModule
    from paraview import simple
    from paraview.web import wamp as pv_wamp
    from paraview.web import protocols as pv_protocols
    from vtk.web import server

    pm = vtkProcessModule.GetProcessModule()

    class Options(object):
        debug = False
        nosignalhandlers = True
        host = 'localhost'
        port = 9753
        timeout = 300
        content = '/data/sebastien/SparkMPI/runtime/visualizer/dist'
        forceFlush = False
        sslKey = ''
        sslCert = ''
        ws = 'ws'
        lp = 'lp'
        hp = 'hp'
        nows = False
        nobws = False
        nolp = False
        fsEndpoints = ''
        uploadPath = None
        testScriptPath = ''
        baselineImgDir = ''
        useBrowser = 'nobrowser'
        tmpDirectory = '.'
        testImgFile = ''

    class _VisualizerServer(pv_wamp.PVServerProtocol):
        dataDir = '/data'
        groupRegex = "[0-9]+\\.[0-9]+\\.|[0-9]+\\."
        excludeRegex = "^\\.|~$|^\\$"
        allReaders = True
        viewportScale = 1.0
        viewportMaxWidth = 2560
        viewportMaxHeight = 1440

        def initialize(self):
            # Bring used components
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebFileListing(
                    _VisualizerServer.dataDir, "Home",
                    _VisualizerServer.excludeRegex,
                    _VisualizerServer.groupRegex))
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebProxyManager(
                    baseDir=_VisualizerServer.dataDir,
                    allowUnconfiguredReaders=_VisualizerServer.allReaders))
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebColorManager())
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebMouseHandler())
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebViewPort(
                    _VisualizerServer.viewportScale,
                    _VisualizerServer.viewportMaxWidth,
                    _VisualizerServer.viewportMaxHeight))
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebViewPortImageDelivery())
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebViewPortGeometryDelivery())
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebTimeHandler())
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebSelectionHandler())
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebWidgetManager())
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebKeyValuePairStore())
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebSaveData(
                    baseSavePath=_VisualizerServer.dataDir))
            # Disable interactor-based render calls
            simple.GetRenderView().EnableRenderOnInteraction = 0
            simple.GetRenderView().Background = [0, 0, 0]
            # Update interaction mode
            pxm = simple.servermanager.ProxyManager()
            interactionProxy = pxm.GetProxy('settings',
                                            'RenderViewInteractionSettings')
            interactionProxy.Camera3DManipulators = [
                'Rotate', 'Pan', 'Zoom', 'Pan', 'Roll', 'Pan', 'Zoom',
                'Rotate', 'Zoom'
            ]

    args = Options()
    if pm.GetPartitionId() == 0:
        producer = simple.DistributedTrivialProducer()
        producer.UpdateDataset = ''
        producer.UpdateDataset = 'Spark'
        producer.WholeExtent = [0, 99, 0, 215, 0, 260]
        server.start_webserver(options=args, protocol=_VisualizerServer)
        pm.GetGlobalController().TriggerBreakRMIs()

    yield (idx, targetPartition)
def processPartition(idx, iterator):
    print('### Start data processing for %d - %s | ' %
          (idx, str(datetime.now())))
    import os
    os.environ["PMI_PORT"] = pmi_port
    os.environ["PMI_ID"] = str(idx)
    os.environ["PV_ALLOW_BATCH_INTERACTION"] = "1"
    os.environ["DISPLAY"] = ":0"

    import paraview
    paraview.options.batch = True

    from vtk.vtkCommonExecutionModel import vtkTrivialProducer
    from vtk.vtkPVVTKExtensionsCore import vtkDistributedTrivialProducer
    from vtk.vtkCommonCore import vtkIntArray, vtkUnsignedCharArray
    from vtk.vtkCommonDataModel import vtkImageData, vtkPointData, vtkCellData

    iOffset = 0
    for i in range(idx):
        iOffset += xSizes[i]
    size = xSizes[idx] * sizeY * sizeZ

    # -------------------------------------------------------------------------
    # Gather data chunk
    # -------------------------------------------------------------------------

    dataChunk = vtkIntArray()
    dataChunk.SetName('scalar')
    dataChunk.SetNumberOfTuples(size)
    dataChunk.Fill(0)

    t0 = time.time()
    count = 0
    for row in iterator:
        count += 1
        coords = idxToCoord(row[0])
        originCoords = '[%d, %d, %d]' % (coords[0], coords[1], coords[2])
        coords[0] -= iOffset
        destIdx = coords[0] + (coords[1] * xSizes[idx]) + (coords[2] *
                                                           xSizes[idx] * sizeY)
        dataChunk.SetValue(destIdx, row[1])

    t1 = time.time()
    print('%d # Gather %s | ' % (idx, str(t1 - t0)))
    t0 = t1

    # -------------------------------------------------------------------------
    # Reshape data into 3D Fortran array ordering
    # -------------------------------------------------------------------------

    npDataChunk = numpy_support.vtk_to_numpy(dataChunk)
    scalars_array3d = np.reshape(npDataChunk, (xSizes[idx], sizeY, sizeZ),
                                 order='F')
    t1 = time.time()
    print('%d # Reshape %s | ' % (idx, str(t1 - t0)))
    t0 = t1

    # -------------------------------------------------------------------------
    # Reconstruction helper
    # -------------------------------------------------------------------------

    def parallelRay(Nside, pixelWidth, angles, Nray, rayWidth):
        # Suppress warning messages that pops up when dividing zeros
        np.seterr(all='ignore')
        Nproj = len(angles)  # Number of projections

        # Ray coordinates at 0 degrees.
        offsets = np.linspace(-(Nray * 1.0 - 1) / 2,
                              (Nray * 1.0 - 1) / 2, Nray) * rayWidth
        # Intersection lines/grid Coordinates
        xgrid = np.linspace(-Nside * 0.5, Nside * 0.5, Nside + 1) * pixelWidth
        ygrid = np.linspace(-Nside * 0.5, Nside * 0.5, Nside + 1) * pixelWidth
        # Initialize vectors that contain matrix elements and corresponding
        # row/column numbers
        rows = np.zeros(2 * Nside * Nproj * Nray)
        cols = np.zeros(2 * Nside * Nproj * Nray)
        vals = np.zeros(2 * Nside * Nproj * Nray)
        idxend = 0

        for i in range(0, Nproj):  # Loop over projection angles
            ang = angles[i] * np.pi / 180.
            # Points passed by rays at current angles
            xrayRotated = np.cos(ang) * offsets
            yrayRotated = np.sin(ang) * offsets
            xrayRotated[np.abs(xrayRotated) < 1e-8] = 0
            yrayRotated[np.abs(yrayRotated) < 1e-8] = 0

            a = -np.sin(ang)
            a = rmepsilon(a)
            b = np.cos(ang)
            b = rmepsilon(b)

            for j in range(0, Nray):  # Loop rays in current projection
                #Ray: y = tx * x + intercept
                t_xgrid = (xgrid - xrayRotated[j]) / a
                y_xgrid = b * t_xgrid + yrayRotated[j]

                t_ygrid = (ygrid - yrayRotated[j]) / b
                x_ygrid = a * t_ygrid + xrayRotated[j]
                # Collect all points
                t_grid = np.append(t_xgrid, t_ygrid)
                xx = np.append(xgrid, x_ygrid)
                yy = np.append(y_xgrid, ygrid)
                # Sort the coordinates according to intersection time
                I = np.argsort(t_grid)
                xx = xx[I]
                yy = yy[I]

                # Get rid of points that are outside the image grid
                Ix = np.logical_and(xx >= -Nside / 2.0 * pixelWidth,
                                    xx <= Nside / 2.0 * pixelWidth)
                Iy = np.logical_and(yy >= -Nside / 2.0 * pixelWidth,
                                    yy <= Nside / 2.0 * pixelWidth)
                I = np.logical_and(Ix, Iy)
                xx = xx[I]
                yy = yy[I]

                # If the ray pass through the image grid
                if (xx.size != 0 and yy.size != 0):
                    # Get rid of double counted points
                    I = np.logical_and(
                        np.abs(np.diff(xx)) <= 1e-8,
                        np.abs(np.diff(yy)) <= 1e-8)
                    I2 = np.zeros(I.size + 1)
                    I2[0:-1] = I
                    xx = xx[np.logical_not(I2)]
                    yy = yy[np.logical_not(I2)]

                    # Calculate the length within the cell
                    length = np.sqrt(np.diff(xx)**2 + np.diff(yy)**2)
                    #Count number of cells the ray passes through
                    numvals = length.size

                    # Remove the rays that are on the boundary of the box in the
                    # top or to the right of the image grid
                    check1 = np.logical_and(
                        b == 0,
                        np.absolute(yrayRotated[j] - Nside / 2 * pixelWidth) <
                        1e-15)
                    check2 = np.logical_and(
                        a == 0,
                        np.absolute(xrayRotated[j] - Nside / 2 * pixelWidth) <
                        1e-15)
                    check = np.logical_not(np.logical_or(check1, check2))

                    if np.logical_and(numvals > 0, check):
                        # Calculate corresponding indices in measurement matrix
                        # First, calculate the mid points coord. between two
                        # adjacent grid points
                        midpoints_x = rmepsilon(0.5 * (xx[0:-1] + xx[1:]))
                        midpoints_y = rmepsilon(0.5 * (yy[0:-1] + yy[1:]))
                        #Calculate the pixel index for mid points
                        pixelIndicex = \
                            (np.floor(Nside / 2.0 - midpoints_y / pixelWidth)) * \
                            Nside + (np.floor(midpoints_x /
                                              pixelWidth + Nside / 2.0))
                        # Create the indices to store the values to the measurement
                        # matrix
                        idxstart = idxend
                        idxend = idxstart + numvals
                        idx = np.arange(idxstart, idxend)
                        # Store row numbers, column numbers and values
                        rows[idx] = i * Nray + j
                        cols[idx] = pixelIndicex
                        vals[idx] = length
                else:
                    print("Ray No. %d at %f degree is out of image grid!" %
                          (j + 1, angles[i]))

        # Truncate excess zeros.
        rows = rows[:idxend]
        cols = cols[:idxend]
        vals = vals[:idxend]
        A = ss.coo_matrix((vals, (rows, cols)), shape=(Nray * Nproj, Nside**2))
        return A

    def rmepsilon(input):
        if (input.size > 1):
            input[np.abs(input) < 1e-10] = 0
        else:
            if np.abs(input) < 1e-10:
                input = 0
        return input

    # -------------------------------------------------------------------------
    # Reconstruction
    # -------------------------------------------------------------------------

    tiltSeries = scalars_array3d
    tiltAngles = range(-sizeZ + 1, sizeZ, 2)  # Delta angle of 2
    (Nslice, Nray, Nproj) = tiltSeries.shape
    Niter = 1

    A = parallelRay(Nray, 1.0, tiltAngles, Nray, 1.0)  # A is a sparse matrix
    recon = np.empty([Nslice, Nray, Nray], dtype=float, order='F')

    A = A.todense()

    (Nrow, Ncol) = A.shape
    rowInnerProduct = np.zeros(Nrow)
    row = np.zeros(Ncol)
    f = np.zeros(Ncol)  # Placeholder for 2d image
    beta = 1.0

    # Calculate row inner product
    for j in range(Nrow):
        row[:] = A[j, ].copy()
        rowInnerProduct[j] = np.dot(row, row)

    for s in range(Nslice):
        f[:] = 0
        b = tiltSeries[s, :, :].transpose().flatten()
        for i in range(Niter):
            for j in range(Nrow):
                row[:] = A[j, ].copy()
                row_f_product = np.dot(row, f)
                a = (b[j] - row_f_product) / rowInnerProduct[j]
                f = f + row * a * beta

        recon[s, :, :] = f.reshape((Nray, Nray))

    (iSize, jSize, kSize) = recon.shape
    t1 = time.time()
    print('%d # Reconstruction %s | ' % (idx, str(t1 - t0)))
    t0 = t1

    # -------------------------------------------------------------------------
    # Convert reconstruction array into VTK format
    # -------------------------------------------------------------------------

    arr = recon.ravel(order='A')
    vtkarray = numpy_support.numpy_to_vtk(arr)
    vtkarray.SetName('Scalars')
    t1 = time.time()
    print('%d # Reshape result %s | ' % (idx, str(t1 - t0)))
    t0 = t1

    # -------------------------------------------------------------------------
    # Data access helper
    # -------------------------------------------------------------------------

    def createSlice():
        size = sizeY * sizeY
        array = np.arange(size, dtype=np.int32)
        return array

    def getSideSlice(offset, xSize):
        size = sizeY * sizeY
        slice = np.arange(size, dtype=np.int32)

        for i in range(size):
            slice[i] = vtkarray.GetTuple1(int(offset + (i * xSize)))
        return slice

    # -------------------------------------------------------------------------
    # Add ghost points from neighbors
    # -------------------------------------------------------------------------

    from mpi4py import MPI
    comm = MPI.COMM_WORLD
    remoteLowerSlice = None
    remoteUpperSlice = None

    if idx + 1 < targetPartition:
        # Share upper slice
        remoteUpperSlice = createSlice()
        localUpperSlice = getSideSlice(xSizes[idx] - 1, xSizes[idx])
        comm.Sendrecv(localUpperSlice, (idx + 1), (2 * idx + 1),
                      remoteUpperSlice, (idx + 1), (2 * idx))
    if idx > 0:
        # Share lower slice
        remoteLowerSlice = createSlice()
        localLowerSlice = getSideSlice(0, xSizes[idx])
        comm.Sendrecv(localLowerSlice, (idx - 1), (2 * (idx - 1)),
                      remoteLowerSlice, (idx - 1), (2 * (idx - 1) + 1))

    t1 = time.time()
    print('%d # MPI share %s | ' % (idx, str(t1 - t0)))
    t0 = t1

    # -------------------------------------------------------------------------

    dataset = vtkImageData()
    minX = 0
    maxX = 0
    for i in range(idx + 1):
        minX = maxX
        maxX += xSizes[i]

    # -------------------------------------------------------------------------
    # Add slice(s) to data
    # -------------------------------------------------------------------------

    arrayWithSlices = vtkarray.NewInstance()
    arrayWithSlices.SetName('Scalars')
    if remoteLowerSlice != None and remoteUpperSlice != None:
        # Add both slices
        minX -= 1
        maxX += 1
        localSizeX = maxX - minX
        newSize = localSizeX * sizeY * sizeY
        arrayWithSlices.SetNumberOfTuples(newSize)
        localOffset = 0
        for i in range(newSize):
            if i % localSizeX == 0:
                arrayWithSlices.SetTuple1(i, remoteLowerSlice[i / localSizeX])
            elif (i + 1) % localSizeX == 0:
                arrayWithSlices.SetTuple1(
                    i, remoteUpperSlice[((i + 1) / localSizeX) - 1])
            else:
                arrayWithSlices.SetTuple1(i, vtkarray.GetTuple1(localOffset))
                localOffset += 1

    elif remoteLowerSlice != None:
        # Add lower slice
        minX -= 1
        localSizeX = maxX - minX
        newSize = localSizeX * sizeY * sizeY
        arrayWithSlices.SetNumberOfTuples(newSize)
        localOffset = 0
        for i in range(newSize):
            if i % localSizeX == 0:
                arrayWithSlices.SetTuple1(i, remoteLowerSlice[i / localSizeX])
            else:
                arrayWithSlices.SetTuple1(i, vtkarray.GetTuple1(localOffset))
                localOffset += 1
    elif remoteUpperSlice != None:
        # Add upper slice
        maxX += 1
        localSizeX = maxX - minX
        newSize = localSizeX * sizeY * sizeY
        arrayWithSlices.SetNumberOfTuples(newSize)
        localOffset = 0
        for i in range(newSize):
            if (i + 1) % localSizeX == 0:
                arrayWithSlices.SetTuple1(
                    i, remoteUpperSlice[((i + 1) / localSizeX) - 1])
            else:
                arrayWithSlices.SetTuple1(i, vtkarray.GetTuple1(localOffset))
                localOffset += 1

    dataset.SetExtent(minX, maxX - 1, 0, sizeY - 1, 0, sizeY - 1)
    dataset.GetPointData().SetScalars(arrayWithSlices)

    t1 = time.time()
    print('%d # build resutling image data %s | ' % (idx, str(t1 - t0)))
    t0 = t1

    # -------------------------------------------------------------------------

    vtkDistributedTrivialProducer.SetGlobalOutput('Spark', dataset)

    from vtk.vtkPVClientServerCoreCore import vtkProcessModule
    from paraview import simple
    from paraview.web import wamp as pv_wamp
    from paraview.web import protocols as pv_protocols
    from vtk.web import server

    pm = vtkProcessModule.GetProcessModule()

    class Options(object):
        debug = False
        nosignalhandlers = True
        host = 'localhost'
        port = 9753
        timeout = 300
        content = '/data/sebastien/SparkMPI/runtime/visualizer/dist'
        forceFlush = False
        sslKey = ''
        sslCert = ''
        ws = 'ws'
        lp = 'lp'
        hp = 'hp'
        nows = False
        nobws = False
        nolp = False
        fsEndpoints = ''
        uploadPath = None
        testScriptPath = ''
        baselineImgDir = ''
        useBrowser = 'nobrowser'
        tmpDirectory = '.'
        testImgFile = ''

    class _VisualizerServer(pv_wamp.PVServerProtocol):
        dataDir = '/data'
        groupRegex = "[0-9]+\\.[0-9]+\\.|[0-9]+\\."
        excludeRegex = "^\\.|~$|^\\$"
        allReaders = True
        viewportScale = 1.0
        viewportMaxWidth = 2560
        viewportMaxHeight = 1440
        proxies = '/data/sebastien/SparkMPI/defaultProxies.json'

        def initialize(self):
            # Bring used components
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebFileListing(
                    _VisualizerServer.dataDir, "Home",
                    _VisualizerServer.excludeRegex,
                    _VisualizerServer.groupRegex))
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebProxyManager(
                    baseDir=_VisualizerServer.dataDir,
                    allowedProxiesFile=_VisualizerServer.proxies,
                    allowUnconfiguredReaders=_VisualizerServer.allReaders))
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebColorManager())
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebMouseHandler())
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebViewPort(
                    _VisualizerServer.viewportScale,
                    _VisualizerServer.viewportMaxWidth,
                    _VisualizerServer.viewportMaxHeight))
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebViewPortImageDelivery())
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebViewPortGeometryDelivery())
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebTimeHandler())
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebSelectionHandler())
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebWidgetManager())
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebKeyValuePairStore())
            self.registerVtkWebProtocol(
                pv_protocols.ParaViewWebSaveData(
                    baseSavePath=_VisualizerServer.dataDir))
            # Disable interactor-based render calls
            simple.GetRenderView().EnableRenderOnInteraction = 0
            simple.GetRenderView().Background = [0, 0, 0]
            # Update interaction mode
            pxm = simple.servermanager.ProxyManager()
            interactionProxy = pxm.GetProxy('settings',
                                            'RenderViewInteractionSettings')
            interactionProxy.Camera3DManipulators = [
                'Rotate', 'Pan', 'Zoom', 'Pan', 'Roll', 'Pan', 'Zoom',
                'Rotate', 'Zoom'
            ]

    # -------------------------------------------------------------------------

    print('%d # > Start visualization - %s | ' % (idx, str(datetime.now())))

    # -------------------------------------------------------------------------

    args = Options()
    if pm.GetPartitionId() == 0:
        producer = simple.DistributedTrivialProducer()
        producer.UpdateDataset = ''
        producer.UpdateDataset = 'Spark'
        producer.WholeExtent = [0, sizeX - 1, 0, sizeY - 1, 0, sizeY - 1]
        server.start_webserver(options=args, protocol=_VisualizerServer)
        pm.GetGlobalController().TriggerBreakRMIs()

    print('%d # < Stop visualization - %s | ' % (idx, str(datetime.now())))
    yield (idx, targetPartition)
def processPartition(idx, iterator):
    import os
    os.environ["PMI_PORT"] = pmi_port
    os.environ["PMI_ID"] = str(idx)
    os.environ["PV_ALLOW_BATCH_INTERACTION"] = "1"
    os.environ["DISPLAY"] = ":0"

    print(idx, pmi_port, '='*80)

    import paraview
    paraview.options.batch = True

    from vtk.vtkPVVTKExtensionsCore import vtkDistributedTrivialProducer
    from vtk.vtkCommonCore import vtkIntArray, vtkUnsignedCharArray
    from vtk.vtkCommonDataModel import vtkImageData, vtkCellData

    cellArray = vtkIntArray()
    cellArray.SetName('scalar')
    cellArray.SetNumberOfTuples(maxIndex)

    cellMask = vtkUnsignedCharArray()
    cellMask.SetName('vtkGhostType')
    cellMask.SetNumberOfTuples(maxIndex)
    cellMask.Fill(32) # HIDDENCELL

    for pix in iterator:
        cellArray.SetValue(int(pix[0]), int(pix[1]))
        cellMask.SetTuple1(pix[0], 1) # DUPLICATECELL

    imageData = vtkImageData()
    imageData.SetDimensions(101, 217, 262)
    imageData.GetCellData().SetScalars(cellArray)
    imageData.GetCellData().AddArray(cellMask)

    print('has ghost type %s' % str(imageData.HasAnyGhostCells()))

    vtkDistributedTrivialProducer.SetGlobalOutput('Spark', imageData)

    from vtk.vtkPVClientServerCoreCore import vtkProcessModule
    from paraview     import simple
    from paraview.web import wamp      as pv_wamp
    from paraview.web import protocols as pv_protocols
    from vtk.web      import server

    pm = vtkProcessModule.GetProcessModule()

    class Options(object):
        debug = False
        nosignalhandlers = True
        host = 'localhost'
        port = 9753
        timeout = 300
        content = '/data/sebastien/SparkMPI/runtime/visualizer/dist'
        forceFlush = False
        sslKey = ''
        sslCert = ''
        ws = 'ws'
        lp = 'lp'
        hp = 'hp'
        nows = False
        nobws = False
        nolp = False
        fsEndpoints = ''
        uploadPath = None
        testScriptPath = ''
        baselineImgDir = ''
        useBrowser = 'nobrowser'
        tmpDirectory = '.'
        testImgFile = ''

    class _VisualizerServer(pv_wamp.PVServerProtocol):
        dataDir = '/data'
        groupRegex = "[0-9]+\\.[0-9]+\\.|[0-9]+\\."
        excludeRegex = "^\\.|~$|^\\$"
        allReaders = True
        viewportScale=1.0
        viewportMaxWidth=2560
        viewportMaxHeight=1440

        def initialize(self):
            # Bring used components
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebFileListing(_VisualizerServer.dataDir, "Home", _VisualizerServer.excludeRegex, _VisualizerServer.groupRegex))
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebProxyManager(baseDir=_VisualizerServer.dataDir, allowUnconfiguredReaders=_VisualizerServer.allReaders))
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebColorManager())
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebMouseHandler())
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebViewPort(_VisualizerServer.viewportScale, _VisualizerServer.viewportMaxWidth,
                                                                         _VisualizerServer.viewportMaxHeight))
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebViewPortImageDelivery())
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebViewPortGeometryDelivery())
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebTimeHandler())
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebSelectionHandler())
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebWidgetManager())
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebKeyValuePairStore())
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebSaveData(baseSavePath=_VisualizerServer.dataDir))
            # Disable interactor-based render calls
            simple.GetRenderView().EnableRenderOnInteraction = 0
            simple.GetRenderView().Background = [0,0,0]
            # Update interaction mode
            pxm = simple.servermanager.ProxyManager()
            interactionProxy = pxm.GetProxy('settings', 'RenderViewInteractionSettings')
            interactionProxy.Camera3DManipulators = ['Rotate', 'Pan', 'Zoom', 'Pan', 'Roll', 'Pan', 'Zoom', 'Rotate', 'Zoom']

    args = Options()
    if pm.GetPartitionId() == 0:
        producer = simple.DistributedTrivialProducer()
        producer.UpdateDataset = ''
        producer.UpdateDataset = 'Spark'
        server.start_webserver(options=args, protocol=_VisualizerServer)
        pm.GetGlobalController().TriggerBreakRMIs()

    yield (idx, partition)
Exemple #7
0
def visualization(partitionId, iterator):
    # Setup MPI context
    import os
    os.environ["PMI_PORT"] = pmi_port
    os.environ["PMI_ID"] = str(partitionId)
    os.environ["PV_ALLOW_BATCH_INTERACTION"] = "1"
    os.environ["DISPLAY"] = ":0"

    localNumSlices = processSlices[partitionId]
    size = localNumSlices * sliceSize
    kOffset = 0
    for i in range(partitionId):
        kOffset += processSlices[i]

    # Copy data from iterator into data chunk
    t0 = time.time()
    count = 0
    dataChunk = np.arange(size, dtype=np.float32)
    sidChunk = np.arange(size, dtype=np.uint8)
    for item in iterator:
        count += 1
        globalIndex = item[0]
        pixelValue = item[1]
        # print('%d # %d: %f' % (partitionId, globalIndex, pixelValue))
        ijk = _ijk(globalIndex)
        ijk[2] -= kOffset
        destIdx = ijk[0] + (ijk[1] * sizeX)  + (ijk[2] * sliceSize)
        dataChunk[destIdx] = pixelValue
        sidChunk[destIdx] = ijk[2] + kOffset

    t1 = time.time()
    print('%d # MPI Gather %s | %d' % (partitionId, str(t1 - t0), count))
    t0 = t1

    # Configure Paraview for MPI
    import paraview
    paraview.options.batch = True

    from vtk.vtkPVVTKExtensionsCore import vtkDistributedTrivialProducer
    from vtk.vtkCommonCore import vtkIntArray, vtkUnsignedCharArray, vtkFloatArray
    from vtk.vtkCommonDataModel import vtkImageData, vtkPointData

    # -------------------------------------------------------------------------

    dataset = vtkImageData()

    sliceIdxArray = vtkUnsignedCharArray()
    sliceIdxArray.SetName('Slice Index')
    sliceIdxArray.SetNumberOfComponents(1)
    sliceIdxArray.SetNumberOfTuples(size)

    dataArray = vtkFloatArray()
    dataArray.SetName('Annual Avg Temp')
    dataArray.SetNumberOfComponents(1)
    dataArray.SetNumberOfTuples(size)
    for i in range(size):
        dataArray.SetTuple1(i, dataChunk[i])
        sliceIdxArray.SetTuple1(i, sidChunk[i])

    minZ = 0
    maxZ = 0
    for i in range(partitionId + 1):
        minZ = maxZ
        maxZ += processSlices[i]

    # dataset.SetExtent(0, sizeX - 1, 0, sizeY - 1, minZ, maxZ - 1)
    # print('partition %d extents: [%d, %d, %d, %d, %d, %d]' % (partitionId, 0, sizeX - 1, 0, sizeY - 1, minZ, maxZ - 1))
    dataset.SetExtent(0, sizeX, 0, sizeY, minZ, maxZ)
    print('partition %d extents: [%d, %d, %d, %d, %d, %d]' % (partitionId, 0, sizeX, 0, sizeY, minZ, maxZ))
    #dataset.GetPointData().AddArray(dataArray)
    # dataset.GetPointData().SetScalars(dataArray)
    dataset.GetCellData().SetScalars(dataArray)

    procIdArray = vtkUnsignedCharArray()
    procIdArray.SetName('Process Id')
    procIdArray.SetNumberOfComponents(1)
    procIdArray.SetNumberOfTuples(size)

    for i in range(size):
        procIdArray.SetTuple1(i, partitionId)

    dataset.GetCellData().AddArray(procIdArray)
    dataset.GetCellData().AddArray(sliceIdxArray)

    t1 = time.time()
    print('%d # build resulting image data %s | ' % (partitionId, str(t1 - t0)))
    t0 = t1

    # -------------------------------------------------------------------------

    vtkDistributedTrivialProducer.SetGlobalOutput('Spark', dataset)

    from vtk.vtkPVClientServerCoreCore import vtkProcessModule
    from paraview     import simple
    from vtk.web      import server
    from paraview.web import wamp as pv_wamp
    from paraview.web import protocols as pv_protocols

    class _VisualizerServer(pv_wamp.PVServerProtocol):
        dataDir = '/data'
        groupRegex = "[0-9]+\\.[0-9]+\\.|[0-9]+\\."
        excludeRegex = "^\\.|~$|^\\$"
        allReaders = True
        viewportScale=1.0
        viewportMaxWidth=2560
        viewportMaxHeight=1440

        def initialize(self):
            # Bring used components
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebFileListing(_VisualizerServer.dataDir, "Home", _VisualizerServer.excludeRegex, _VisualizerServer.groupRegex))
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebProxyManager(baseDir=_VisualizerServer.dataDir, allowUnconfiguredReaders=_VisualizerServer.allReaders))
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebColorManager())
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebMouseHandler())
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebViewPort(_VisualizerServer.viewportScale, _VisualizerServer.viewportMaxWidth,
                                                                         _VisualizerServer.viewportMaxHeight))
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebViewPortImageDelivery())
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebViewPortGeometryDelivery())
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebTimeHandler())
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebSelectionHandler())
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebWidgetManager())
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebKeyValuePairStore())
            self.registerVtkWebProtocol(pv_protocols.ParaViewWebSaveData(baseSavePath=_VisualizerServer.dataDir))
            # Disable interactor-based render calls
            simple.GetRenderView().EnableRenderOnInteraction = 0
            simple.GetRenderView().Background = [0,0,0]
            # Update interaction mode
            pxm = simple.servermanager.ProxyManager()
            interactionProxy = pxm.GetProxy('settings', 'RenderViewInteractionSettings')
            interactionProxy.Camera3DManipulators = ['Rotate', 'Pan', 'Zoom', 'Pan', 'Roll', 'Pan', 'Zoom', 'Rotate', 'Zoom']


    pm = vtkProcessModule.GetProcessModule()

    # -------------------------------------------------------------------------

    print('%d # > Start visualization - %s | ' % (partitionId, str(datetime.now())))

    # -------------------------------------------------------------------------

    args = Options()
    if pm.GetPartitionId() == 0:
        print('%d # ==> %d' % (partitionId, pm.GetPartitionId()))
        producer = simple.DistributedTrivialProducer()
        producer.UpdateDataset = ''
        producer.UpdateDataset = 'Spark'
        producer.WholeExtent = [0, sizeX, 0, sizeY, 0, sizeZ]
        server.start_webserver(options=args, protocol=_VisualizerServer)
        pm.GetGlobalController().TriggerBreakRMIs()

    print('%d # < Stop visualization - %s | ' % (partitionId, str(datetime.now())))
    yield (partitionId, nbMPIPartition)