def run_OpenCL(oclu, ctx, queue, scene, leaf_array, fluence_data, intensities, settingsList, optimizationParameters):
    debugOpenCL = Debug()
    
    X_size = int(optimizationParameters[1][1])
    Y_size = int(optimizationParameters[2][1])
    Z_size = int(optimizationParameters[3][1])
    if Settings.AUTOTUNE == 1:
        Settings.PIECES = int(optimizationParameters[4][1])
        [scene, collimators, leaf_array] = init_scene(Settings.PIECES)
        settingsList = define_settings(scene, leaf_array)
    
    settingsString = Settings.macroString(settingsList)
    optParametersString = Settings.macroString(optimizationParameters)
    Settings.WG_LIGHT_SAMPLING_SIZE = X_size*Y_size*Z_size
    optParametersString += " -D WG_LIGHT_SAMPLING_SIZE=" + str(X_size*Y_size*Z_size)

    #program = oclu.loadProgram(ctx, Settings.PATH_OPENCL + "RayTracingGPU.cl", "-cl-nv-verbose " + settingsString)
    #program = oclu.loadProgram(ctx, Settings.PATH_OPENCL + "RayTracingGPU.cl", "-cl-auto-vectorize-disable " + settingsString)
    #program = oclu.loadProgram(ctx, Settings.PATH_OPENCL + "RayTracingGPU.cl", " " + settingsString + " " + optParametersString)
    program = oclu.loadCachedProgram(ctx, Settings.PATH_OPENCL + "RayTracing.cl", " " + settingsString + " " + optParametersString)

    mf = cl.mem_flags
    time0 = time()
    scene_buf = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=scene)
    #render_buf = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=render)
    leaf_array_buf = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=leaf_array)
    intensities_buf = cl.Buffer(ctx, mf.READ_WRITE | mf.ALLOC_HOST_PTR, size=intensities.nbytes)
    fluence_data_buf = cl.Buffer(ctx, mf.READ_WRITE | mf.ALLOC_HOST_PTR, size=fluence_data.nbytes)
    debugOpenCL_buf = cl.Buffer(ctx, mf.WRITE_ONLY, sizeof(debugOpenCL))
    
    time1 = time()
    program.flatLightSourceSampling(queue, intensities.shape, (X_size, Y_size, Z_size), scene_buf, leaf_array_buf, intensities_buf, debugOpenCL_buf).wait()
    #program.flatLightSourceSampling(queue, intensities.shape, None, scene_buf, leaf_array_buf, intensities_buf, debugOpenCL_buf).wait()

    time2 = time()
    program.calculateIntensityDecreaseWithDistance(queue, fluence_data.shape, None, scene_buf, fluence_data_buf, debugOpenCL_buf).wait()
    time3 = time()
    program.calcFluenceElement(queue, fluence_data.shape, None, scene_buf, intensities_buf, fluence_data_buf, debugOpenCL_buf).wait()
    time4 = time()
    cl.enqueue_read_buffer(queue, fluence_data_buf, fluence_data)
    cl.enqueue_read_buffer(queue, debugOpenCL_buf, debugOpenCL).wait()
    totalTime = time()-time0
    calculationTime = time4-time1

    #print "flatLightSourceSampling(): ", time2 - time1, ", calculateIntensityDecreaseWithDistance():", time3 - time2, ", calcFluenceElement():", time4 - time3
    samplesPerSecondOpenCL = Settings.FLX*Settings.FLY*Settings.LSAMPLESSQR/totalTime
    #print "Time OpenCL: ", timeOpenCL, " Samples per second: ", samplesPerSecondOpenCL
    #print fluence_data

    return [fluence_data, totalTime, calculationTime, samplesPerSecondOpenCL]
def define_settings(scene, leaf_array):
    # Settings
    Settings.XSTEP = float(length(scene.fluenceMap.rectangle.p1 - scene.fluenceMap.rectangle.p0)/Settings.FLX) # Length in x / x resolution
    Settings.YSTEP = float(length(scene.fluenceMap.rectangle.p3 - scene.fluenceMap.rectangle.p0)/Settings.FLY) # Length in y / y resolution
    Settings.XOFFSET = float(Settings.XSTEP/2.0)
    Settings.YOFFSET = float(Settings.YSTEP/2.0)
    Settings.LSTEP = float(scene.raySource.radius*2/(Settings.LSAMPLES-1))
    Settings.LEAF_DATA_SIZE = len(leaf_array)
    settingsList = Settings.getDefaultSettingsList()
    settingsList.append(("XSTEP", str(Settings.XSTEP)+'f', True))
    settingsList.append(("YSTEP", str(Settings.YSTEP)+'f', True))
    settingsList.append(("XOFFSET", str(Settings.XOFFSET)+'f', True))
    settingsList.append(("YOFFSET", str(Settings.YOFFSET)+'f', True))
    settingsList.append(("LSTEP", str(Settings.LSTEP)+'f', True))
    settingsList.append(("LEAF_DATA_SIZE", str(Settings.LEAF_DATA_SIZE), True))

    return settingsList
def main():
    setDefaultSettings()
    #select_excecution_environment()
    if Settings.OPENCL == 1:
        [ctx, queue] = init_OpenCL()
    #test()
    [scene, collimators, leaf_array] = init_scene(Settings.PIECES)
    settingsList = define_settings(scene, leaf_array)
    oclu = OpenCLUtility.OpenCLUtility()

    if Settings.AUTOTUNE == 1:
        list = []
        list.append(Parameter("LINE_TRIANGLE_INTERSECTION_ALGORITHM", [2], True))
        list.append(Parameter("WG_LIGHT_SAMPLING_X", [1,2,4,8,16,32,64,128], False))
        list.append(Parameter("WG_LIGHT_SAMPLING_Y", [1,2,4,8,16,32,64,128], False))
        list.append(Parameter("WG_LIGHT_SAMPLING_Z", [1,2,4,8,16], False))
        list.append(Parameter("PIECES", [1,2,4,10,20], False))
        list.append(Parameter("RAY_AS", [0], True))
        list.append(Parameter("LEAF_AS", [1], True))
        list.append(Parameter("LEAF_DATA_AS", [2], True))
        list.append(Parameter("SCENE_AS", [2], True))
        list.append(Parameter("DEPTH_FIRST", [0], True))

        fluence_data = numpy.zeros(shape=(Settings.FLX,Settings.FLY), dtype=numpy.float32)
        intensities = numpy.zeros(shape=(Settings.FLX,Settings.FLY,Settings.LSAMPLESSQR), dtype=numpy.float32)

        at = Autotune(ParameterSet(list), run_OpenCL, (oclu, ctx, queue, scene, leaf_array, fluence_data, intensities, settingsList))

        at.findOptimizationParameters()

        #print at.getTable()
        at.saveCSV()

        [fluence_data_OpenCL, total_time_OpenCL, calculation_time_OpenCL, samplesPerSecond_OpenCL] = run_OpenCL(oclu, ctx, queue, scene, leaf_array, fluence_data, intensities, settingsList, at.best_parameters)
    else:
        fluence_data = numpy.zeros(shape=(Settings.FLX,Settings.FLY), dtype=numpy.float32)
        intensities = numpy.zeros(shape=(Settings.FLX,Settings.FLY,Settings.LSAMPLESSQR), dtype=numpy.float32)
        [fluence_data_OpenCL, total_time_OpenCL, calculation_time_OpenCL, samplesPerSecond_OpenCL] = run_OpenCL(oclu, ctx, queue, scene, leaf_array, fluence_data, intensities, settingsList, Settings.getDefaultOptimizationParameterList())

    if Settings.SHOW_PLOT == 1:
        if Settings.PYTHON == 1:
            show_plot(scene, fluence_data_Python, time_Python, samplesPerSecond_Python)
        if Settings.OPENCL == 1:
            show_plot(scene, fluence_data_OpenCL, total_time_OpenCL, samplesPerSecond_OpenCL)
    if Settings.SHOW_3D_SCENE == 1:
        show_3D_scene(scene, leaf_array, collimators)