def get_nebs_analysis(cls, wf):
        assert wf.metadata['workflow_class'] == cls.workflow_class
        assert wf.metadata['workflow_module'] == cls.workflow_module

        terminal_start_step_index = -1
        terminal_start_final_fw_id = None
        terminal_end_step_index = -1
        terminal_end_final_fw_id = None

        neb_tasks_step_index = {}
        neb_tasks_step_final_fw_id = {}

        neb_setup_tasks_step_index = {}
        neb_setup_tasks_step_final_fw_id = {}

        for fw_id, fw in wf.id_fw.items():
            if 'SRC_task_index' in fw.spec:
                src_type = fw.tasks[-1].src_type
                if src_type in ['run', 'setup']:
                    task_index = fw.spec['SRC_task_index']
                    match = re.match("neb\d+$", task_index.task_type)
                    if match and match.string == task_index.task_type:
                        if src_type == 'run':
                            if task_index.task_type not in neb_tasks_step_index:
                                neb_tasks_step_index[task_index.task_type] = task_index.index
                                neb_tasks_step_final_fw_id[task_index.task_type] = fw_id
                            else:
                                if task_index.index > neb_tasks_step_index[task_index.task_type]:
                                    neb_tasks_step_index[task_index.task_type] = task_index.index
                                    neb_tasks_step_final_fw_id[task_index.task_type] = fw_id
                        elif src_type == 'setup':
                            if task_index.task_type not in neb_setup_tasks_step_index:
                                neb_setup_tasks_step_index[task_index.task_type] = task_index.index
                                neb_setup_tasks_step_final_fw_id[task_index.task_type] = fw_id
                            else:
                                if task_index.index > neb_setup_tasks_step_index[task_index.task_type]:
                                    neb_setup_tasks_step_index[task_index.task_type] = task_index.index
                                    neb_setup_tasks_step_final_fw_id[task_index.task_type] = fw_id
                    elif task_index.task_type == 'MPRelaxVasp-start':
                        if src_type == 'run':
                            if task_index.index > terminal_start_step_index:
                                terminal_start_step_index = task_index.index
                                terminal_start_final_fw_id = fw_id
                    elif task_index.task_type == 'MPRelaxVasp-end':
                        if src_type == 'run':
                            if task_index.index > terminal_end_step_index:
                                terminal_end_step_index = task_index.index
                                terminal_end_final_fw_id = fw_id
        if terminal_start_final_fw_id is None:
            raise RuntimeError('No terminal-start relaxation found ...')
        if terminal_end_final_fw_id is None:
            raise RuntimeError('No terminal-end relaxation found ...')
        if len(neb_tasks_step_index) == 0:
            raise RuntimeError('No NEB analysis found ...')
        # Terminal start dir
        terminal_start_fw = wf.id_fw[terminal_start_final_fw_id]
        terminal_start_last_launch = (terminal_start_fw.archived_launches + terminal_start_fw.launches)[-1]
        terminal_start_run_dir = terminal_start_last_launch.launch_dir
        # Terminal end dir
        terminal_end_fw = wf.id_fw[terminal_end_final_fw_id]
        terminal_end_last_launch = (terminal_end_fw.archived_launches + terminal_end_fw.launches)[-1]
        terminal_end_run_dir = terminal_end_last_launch.launch_dir
        nebs_analysis = []
        nebs_calculations_parameters = []
        helper = MPNEBTaskHelper()
        for ineb in range(1, len(neb_tasks_step_index)+1):
            neb_task_type = 'neb{:d}'.format(ineb)
            nebfw = wf.id_fw[neb_tasks_step_final_fw_id[neb_task_type]]
            last_launch = (nebfw.archived_launches + nebfw.launches)[-1]
            neb_analysis = NEBAnalysis.from_dir(last_launch.launch_dir,
                                                relaxation_dirs=(terminal_start_run_dir, terminal_end_run_dir))
            nebs_analysis.append(neb_analysis)
            nebsetupfw = wf.id_fw[neb_setup_tasks_step_final_fw_id[neb_task_type]]
            nebsetuptask = nebsetupfw.tasks[-1]
            neb_vasp_input_set = nebsetuptask.vasp_input_set
            kpoints_generation_description = get_kpoints_generation_description(neb_vasp_input_set)

            neb_task = nebfw.tasks[-1]
            last_launch = (nebfw.archived_launches + nebfw.launches)[-1]
            helper.set_task(neb_task)
            helper.task.setup_rundir(last_launch.launch_dir)

            vasprun = helper.get_vasprun()
            if vasprun == 'vasprun.xml malformed':
                incar = helper.get_incar()
                calculation_parameters = {'origin': 'incar',
                                          'INCAR': incar,
                                          'INCAR_ALL': 'unknown',
                                          'potcar_symbols': 'unknown',
                                          'ENCUT': incar.get('ENCUT', 'DEFAULT'),
                                          'EDIFFG': incar.get('EDIFFG', 'DEFAULT'),
                                          'ISMEAR': incar.get('ISMEAR', 'DEFAULT'),
                                          'SIGMA': incar.get('SIGMA', 'DEFAULT'),
                                          'kpoints_generation_description': kpoints_generation_description}
            else:
                calculation_parameters = {'origin': 'vasprun.xml',
                                          'INCAR': vasprun.incar,
                                          'INCAR_ALL': vasprun.parameters,
                                          'potcar_symbols': vasprun.potcar_symbols,
                                          'ENCUT': vasprun.incar['ENCUT'] or vasprun.parameters['ENCUT'],
                                          'EDIFFG': vasprun.incar.get('EDIFFG') or vasprun.parameters.get('EDIFFG'),
                                          'ISMEAR': vasprun.incar.get('ISMEAR') or vasprun.parameters.get('ISMEAR'),
                                          'SIGMA': vasprun.incar.get('SIGMA') or vasprun.parameters.get('SIGMA'),
                                          'kpoints_generation_description': kpoints_generation_description}

            nebs_calculations_parameters.append(calculation_parameters)

        return {'nebs_analysis': [neb_analysis.as_dict() for neb_analysis in nebs_analysis],
                'nebs_calculations_parameters': nebs_calculations_parameters}
    def get_terminal_computed_entries(cls, wf):
        assert wf.metadata['workflow_class'] == cls.workflow_class
        assert wf.metadata['workflow_module'] == cls.workflow_module

        terminal_start_step_index = -1
        terminal_start_final_fw_id = None
        terminal_start_setup_step_index = -1
        terminal_start_setup_fw_id = None
        terminal_end_step_index = -1
        terminal_end_final_fw_id = None
        terminal_end_setup_step_index = -1
        terminal_end_setup_fw_id = None

        for fw_id, fw in wf.id_fw.items():
            if 'SRC_task_index' in fw.spec:
                src_type = fw.tasks[-1].src_type
                if src_type in ['run', 'setup']:
                    task_index = fw.spec['SRC_task_index']
                    if task_index.task_type == 'MPRelaxVasp-start':
                        if src_type == 'run':
                            if task_index.index > terminal_start_step_index:
                                terminal_start_step_index = task_index.index
                                terminal_start_final_fw_id = fw_id
                        elif src_type == 'setup':
                            if task_index.index > terminal_start_setup_step_index:
                                terminal_start_setup_step_index = task_index.index
                                terminal_start_setup_fw_id = fw_id
                    elif task_index.task_type == 'MPRelaxVasp-end':
                        if src_type == 'run':
                            if task_index.index > terminal_end_step_index:
                                terminal_end_step_index = task_index.index
                                terminal_end_final_fw_id = fw_id
                        elif src_type == 'setup':
                            if task_index.index > terminal_end_setup_step_index:
                                terminal_end_setup_step_index = task_index.index
                                terminal_end_setup_fw_id = fw_id
        if terminal_start_final_fw_id is None:
            raise RuntimeError('No terminal-start relaxation found ...')
        if terminal_end_final_fw_id is None:
            raise RuntimeError('No terminal-end relaxation found ...')
        # Terminal start dir
        terminal_start_fw = wf.id_fw[terminal_start_final_fw_id]
        terminal_start_last_launch = (terminal_start_fw.archived_launches + terminal_start_fw.launches)[-1]
        terminal_start_run_dir = terminal_start_last_launch.launch_dir
        # Terminal end dir
        terminal_end_fw = wf.id_fw[terminal_end_final_fw_id]
        terminal_end_last_launch = (terminal_end_fw.archived_launches + terminal_end_fw.launches)[-1]
        terminal_end_run_dir = terminal_end_last_launch.launch_dir

        helper = MPRelaxTaskHelper()

        # Get the information for the terminal start
        terminal_start_task = terminal_start_fw.tasks[-1]
        helper.set_task(terminal_start_task)
        helper.task.setup_rundir(terminal_start_run_dir)
        terminal_start_all_info = helper.get_all_info(raise_error=True)

        terminal_start_setup_fw = wf.id_fw[terminal_start_setup_fw_id]
        terminal_start_setup_task = terminal_start_setup_fw.tasks[-1]
        terminal_start_vasp_input_set = terminal_start_setup_task.vasp_input_set
        terminal_start_kpts_generation_description = get_kpoints_generation_description(terminal_start_vasp_input_set)

        terminal_start_computed_entry = terminal_start_all_info['computed_entry']
        terminal_start_vasprun = terminal_start_all_info['vasprun']
        terminal_start_calculation_parameters = {'INCAR': terminal_start_vasprun.incar,
                                                 'INCAR_ALL': terminal_start_vasprun.parameters,
                                                 'potcar_symbols': terminal_start_vasprun.potcar_symbols,
                                                 'ENCUT': terminal_start_vasprun.incar['ENCUT'] or terminal_start_vasprun.parameters['ENCUT'],
                                                 'EDIFFG': terminal_start_vasprun.incar.get('EDIFFG') or terminal_start_vasprun.parameters.get('EDIFFG'),
                                                 'ISMEAR': terminal_start_vasprun.incar.get('ISMEAR') or terminal_start_vasprun.parameters.get('ISMEAR'),
                                                 'SIGMA': terminal_start_vasprun.incar.get('SIGMA') or terminal_start_vasprun.parameters.get('SIGMA'),
                                                 'kpoints_generation_description': terminal_start_kpts_generation_description}
        if terminal_start_computed_entry.data is None:
            terminal_start_computed_entry.data = {}

        terminal_start_computed_entry.data['calculation_parameters'] = terminal_start_calculation_parameters

        # Get the information for the terminal end
        terminal_end_task = terminal_end_fw.tasks[-1]
        helper.set_task(terminal_end_task)
        helper.task.setup_rundir(terminal_end_run_dir)
        terminal_end_all_info = helper.get_all_info(raise_error=True)

        terminal_end_setup_fw = wf.id_fw[terminal_end_setup_fw_id]
        terminal_end_setup_task = terminal_end_setup_fw.tasks[-1]
        terminal_end_vasp_input_set = terminal_end_setup_task.vasp_input_set
        terminal_end_kpts_generation_description = get_kpoints_generation_description(
            terminal_end_vasp_input_set)

        terminal_end_computed_entry = terminal_end_all_info['computed_entry']
        terminal_end_vasprun = terminal_end_all_info['vasprun']
        terminal_end_calculation_parameters = {'INCAR': terminal_end_vasprun.incar,
                                               'INCAR_ALL': terminal_end_vasprun.parameters,
                                               'potcar_symbols': terminal_end_vasprun.potcar_symbols,
                                               'ENCUT': terminal_end_vasprun.incar['ENCUT'] or
                                                        terminal_end_vasprun.parameters['ENCUT'],
                                               'EDIFFG': terminal_end_vasprun.incar.get(
                                                   'EDIFFG') or terminal_end_vasprun.parameters.get('EDIFFG'),
                                               'ISMEAR': terminal_end_vasprun.incar.get(
                                                   'ISMEAR') or terminal_end_vasprun.parameters.get('ISMEAR'),
                                               'SIGMA': terminal_end_vasprun.incar.get(
                                                   'SIGMA') or terminal_end_vasprun.parameters.get('SIGMA'),
                                               'kpoints_generation_description': terminal_end_kpts_generation_description}
        if terminal_end_computed_entry.data is None:
            terminal_end_computed_entry.data = {}

        terminal_end_computed_entry.data['calculation_parameters'] = terminal_end_calculation_parameters

        return {'computed_entry_terminal_start': terminal_start_computed_entry.as_dict(),
                'computed_entry_terminal_end': terminal_end_computed_entry.as_dict()}
    def get_final_results(cls, wf):
        assert wf.metadata['workflow_class'] == cls.workflow_class
        assert wf.metadata['workflow_module'] == cls.workflow_module
        step_index = -1
        final_fw_id = None
        nrelaxations = 1
        fw_ids = {}
        final_setup_fw_id = None
        final_setup_step_index = -1
        final_setup_nrelaxations = 1
        for fw_id, fw in wf.id_fw.items():
            if 'SRC_task_index' in fw.spec:
                src_type = fw.tasks[-1].src_type
                if src_type in ['run', 'setup']:
                    task_index = fw.spec['SRC_task_index']
                    if 'MPRelaxVasp' in task_index.task_type:
                        if task_index.task_type == 'MPRelaxVasp':
                            if src_type == 'run':
                                fw_ids[(1, task_index.index)] = fw_id
                                if task_index.index > step_index:
                                    step_index = task_index.index
                                    final_fw_id = fw_id
                            elif src_type == 'setup':
                                if task_index.index > final_setup_step_index:
                                    final_setup_step_index = task_index.index
                                    final_setup_fw_id = fw_id
                        else:
                            match = re.match("MPRelaxVasp-\d+", task_index.task_type)
                            if match and match.string == task_index.task_type:
                                nn = int(task_index.task_type[12:])
                                if src_type == 'run':
                                    fw_ids[(nn, task_index.index)] = fw_id
                                    if nn == nrelaxations:
                                        if task_index.index > step_index:
                                            step_index = task_index.index
                                            final_fw_id = fw_id
                                    elif nn > nrelaxations:
                                        step_index = task_index.index
                                        final_fw_id = fw_id
                                        nrelaxations = nn
                                elif src_type == 'setup':
                                    if nn == final_setup_nrelaxations:
                                        if task_index.index > final_setup_step_index:
                                            final_setup_step_index = task_index.index
                                            final_setup_fw_id = fw_id
                                    elif nn > final_setup_nrelaxations:
                                        final_setup_step_index = task_index.index
                                        final_setup_fw_id = fw_id
                                        final_setup_nrelaxations = nn
        if final_fw_id is None:
            raise RuntimeError('Final structure not found ...')
        rlx_and_task_indices = sorted(fw_ids.keys())
        ionic_steps = []
        helper = MPRelaxTaskHelper()
        for rlx_and_task_index in rlx_and_task_indices:
            fw_id = fw_ids[rlx_and_task_index]
            myfw = wf.id_fw[fw_id]
            mytask = myfw.tasks[-1]
            last_launch = (myfw.archived_launches + myfw.launches)[-1]
            helper.set_task(mytask)
            helper.task.setup_rundir(last_launch.launch_dir)

            all_info = helper.get_all_info(raise_error=False)
            if all_info:
                task_ionic_steps = all_info['ionic_steps']
                for ionstep in task_ionic_steps:
                    ionstep.pop('structure')
                ionic_steps.append(task_ionic_steps)

        final_setup_fw = wf.id_fw[final_setup_fw_id]
        final_setup_task = final_setup_fw.tasks[-1]
        final_vasp_input_set = final_setup_task.vasp_input_set
        kpoints_generation_description = get_kpoints_generation_description(final_vasp_input_set)

        all_info_final = helper.get_all_info(raise_error=True)
        computed_entry = all_info_final['computed_entry']
        vasprun = all_info_final['vasprun']

        calculation_parameters = {'INCAR': vasprun.incar,
                                  'INCAR_ALL': vasprun.parameters,
                                  'potcar_symbols': vasprun.potcar_symbols,
                                  'ENCUT': vasprun.incar['ENCUT'] or vasprun.parameters['ENCUT'],
                                  'EDIFFG': vasprun.incar.get('EDIFFG') or vasprun.parameters.get('EDIFFG'),
                                  'ISMEAR': vasprun.incar.get('ISMEAR') or vasprun.parameters.get('ISMEAR'),
                                  'SIGMA': vasprun.incar.get('SIGMA') or vasprun.parameters.get('SIGMA'),
                                  'kpoints_generation_description': kpoints_generation_description}

        if computed_entry.data is None:
            computed_entry.data = {}

        computed_entry.data['calculation_parameters'] = calculation_parameters

        return {'computed_entry': computed_entry.as_dict(),
                'final_structure': all_info_final['final_structure'].as_dict(),
                'ionic_steps': ionic_steps}