Ejemplo n.º 1
0
def manage_reconstruction(proc, experiment_dir, rec_id=None):
    """
    This function starts the interruption discovery process and continues the recontruction processing.
    
    It reads configuration file defined as <experiment_dir>/conf/config_rec.
    If multiple generations are configured, or separate scans are discovered, it will start concurrent reconstructions.
    It creates image.npy file for each successful reconstruction.

    Parameters
    ----------
    proc : str
        processing library, choices are: cpu, cuda, opencl
    experiment_dir : str
        directory where the experiment files are loacted
    rec_id : str
        optional, if given, alternate configuration file will be used for reconstruction, (i.e. <rec_id>_config_rec)

    Returns
    -------
    nothing
    """
    if os.path.exists('stopfile'):
        os.remove('stopfile')
    print('starting reconstruction')

    # the rec_id is a postfix added to config_rec configuration file. If defined, use this configuration.
    conf_dir = os.path.join(experiment_dir, 'conf')
    if rec_id is None:
        conf_file = os.path.join(conf_dir, 'config_rec')
    else:
        conf_file = os.path.join(conf_dir, rec_id + '_config_rec')

    # check if file exists
    if not os.path.isfile(conf_file):
        print('no configuration file ' + conf_file + ' found')
        return

    # verify the configuration file
    if not ver.ver_config_rec(conf_file):
        # if not verified, the ver will print message
        return

    try:
        config_map = ut.read_config(conf_file)
        if config_map is None:
            print("can't read configuration file " + conf_file)
            return
    except Exception as e:
        print('Cannot parse configuration file ' + conf_file +
              ' , check for matching parenthesis and quotations')
        print(str(e))
        return

    # exp_dirs_data list hold pairs of data and directory, where the directory is the root of data/data.tif file, and
    # data is the data.tif file in this directory.
    exp_dirs_data = []
    # experiment may be multi-scan in which case reconstruction will run for each scan
    for dir in os.listdir(experiment_dir):
        if dir.startswith('scan'):
            datafile = os.path.join(experiment_dir, dir, 'data', 'data.tif')
            if os.path.isfile(datafile):
                exp_dirs_data.append(
                    (datafile, os.path.join(experiment_dir, dir)))
    # if there are no scan directories, assume it is combined scans experiment
    if len(exp_dirs_data) == 0:
        # in typical scenario data_dir is not configured, and it is defaulted to <experiment_dir>/data
        # the data_dir is ignored in multi-scan scenario
        try:
            data_dir = config_map.data_dir
        except AttributeError:
            data_dir = os.path.join(experiment_dir, 'data')
        datafile = os.path.join(data_dir, 'data.tif')
        if os.path.isfile(datafile):
            exp_dirs_data.append((datafile, experiment_dir))
    no_runs = len(exp_dirs_data)
    if no_runs == 0:
        print('did not find data.tif file(s). ')
        return
    try:
        generations = config_map.generations
    except:
        generations = 0
    try:
        reconstructions = config_map.reconstructions
    except:
        reconstructions = 1
    device_use = []
    if proc == 'cpu':
        cpu_use = [-1] * reconstructions
        if no_runs > 1:
            for _ in range(no_runs):
                device_use.append(cpu_use)
        else:
            device_use = cpu_use
    else:
        try:
            devices = config_map.device
        except:
            devices = [-1]

        if no_runs * reconstructions > 1:
            data_shape = ut.read_tif(exp_dirs_data[0][0]).shape
            device_use = get_gpu_use(devices, no_runs, reconstructions,
                                     data_shape)
        else:
            device_use = devices

    # start the interrupt process
    interrupt_process = Process(target=interrupt_thread, args=())
    interrupt_process.start()

    if no_runs == 1:
        if len(device_use) == 0:
            device_use = [-1]
        dir_data = exp_dirs_data[0]
        datafile = dir_data[0]
        dir = dir_data[1]
        if generations > 1:
            gen_rec.reconstruction(proc, conf_file, datafile, dir, device_use)
        elif reconstructions > 1:
            mult_rec.reconstruction(proc, conf_file, datafile, dir, device_use)
        else:
            rec.reconstruction(proc, conf_file, datafile, dir, device_use)
    else:
        if len(device_use) == 0:
            device_use = [[-1]]
        else:
            # check if is it worth to use last chunk
            if proc != 'cpu' and len(device_use[0]) > len(device_use[-1]) * 2:
                device_use = device_use[0:-1]
        if generations > 1:
            r = 'g'
        elif reconstructions > 1:
            r = 'm'
        else:
            r = 's'
        q = Queue()
        for gpus in device_use:
            q.put((None, gpus))
        # index keeps track of the multiple directories
        index = 0
        processes = {}
        while index < no_runs:
            pid, gpus = q.get()
            if pid is not None:
                os.kill(pid, signal.SIGKILL)
                del processes[pid]
            datafile = exp_dirs_data[index][0]
            dir = exp_dirs_data[index][1]
            p = Process(target=rec_process,
                        args=(proc, conf_file, datafile, dir, gpus, r, q))
            p.start()
            processes[p.pid] = index
            index += 1

        # close the queue
        while len(processes.items()) > 0:
            pid, gpus = q.get()
            os.kill(pid, signal.SIGKILL)
            del processes[pid]
        q.close()

    interrupt_process.terminate()
    print('finished reconstruction')
def write_conf(conf_map, dir, file):
    """
    It creates configuration file from the parameters included in dictionary, verifies, and saves in the configuration directory.
    Parameters
    ----------
    conf_map : dict
        dictionary containing configuration parameters
    dir : str
        a directory where the configuration file will be saved
    file : str
        name of the configuration file to save
    Returns
    -------
    nothing
    """
    # create "temp" file first, verify it, and if ok, copy to a configuration file
    if not os.path.exists(dir):
        os.makedirs(dir)
    conf_file = os.path.join(dir, file)
    temp_file = os.path.join(dir, 'temp')
    if os.path.isfile(temp_file):
        os.remove(temp_file)
    with open(temp_file, 'a') as f:
        for key in conf_map:
            value = conf_map[key]
            if len(value) > 0:
                f.write(key + ' = ' + conf_map[key] + '\n')
    f.close()

    if file == 'config':
        if not ver.ver_config(temp_file):
            os.remove(temp_file)
            msg_window(
                'please check the entries in the main window. Cannot save this format'
            )
            return False
    elif file == 'config_prep':
        if not ver.ver_config_prep(temp_file):
            os.remove(temp_file)
            msg_window(
                'please check the entries in the Data prep tab. Cannot save this format'
            )
            return False
    elif file == 'config_data':
        if not ver.ver_config_data(temp_file):
            os.remove(temp_file)
            msg_window(
                'please check the entries in the Data tab. Cannot save this format'
            )
            return False
    elif file.endswith('config_rec'):
        if not ver.ver_config_rec(temp_file):
            os.remove(temp_file)
            msg_window(
                'please check the entries in the Reconstruction tab. Cannot save this format'
            )
            return False
    elif file == 'config_disp':
        if not ver.ver_config_disp(temp_file):
            os.remove(temp_file)
            msg_window(
                'please check the entries in the Display tab. Cannot save this format'
            )
            return False
    # copy if verified
    shutil.copy(temp_file, conf_file)
    os.remove(temp_file)
    return True