Пример #1
0
def xia2_setup():
    """Actually process something..."""
    Citations.cite("xia2")

    # print versions of related software
    logger.info(dials_version())

    ccp4_version = get_ccp4_version()
    if ccp4_version:
        logger.info("CCP4 %s", ccp4_version)

    CommandLine = get_command_line()

    # check that something useful has been assigned for processing...
    xtals = CommandLine.get_xinfo().get_crystals()

    for name, xtal in xtals.items():
        if not xtal.get_all_image_names():
            logger.info("-----------------------------------" +
                        "-" * len(name))
            logger.info("| No images assigned for crystal %s |", name)
            logger.info("-----------------------------------" +
                        "-" * len(name))

    from xia2.Handlers.Phil import PhilIndex

    params = PhilIndex.get_python_object()
    xinfo = CommandLine.get_xinfo()
    logger.info(f"Project directory: {xinfo.path}")
    logger.info(f"xinfo written to: {params.xia2.settings.input.xinfo}")
    logger.info(f"Parameters: {PhilIndex.get_diff().as_str()}")
Пример #2
0
def run():
    try:
        check_environment()
    except Exception as e:
        with open("xia2-error.txt", "w") as fh:
            traceback.print_exc(file=fh)
        logger.error('Status: error "%s"', str(e))

    if len(sys.argv) < 2 or "-help" in sys.argv:
        help()
        sys.exit()

    cwd = os.getcwd()

    try:
        from .xia2_main import xia2_main

        xia2_main(stop_after="integrate")
        logger.info("Status: normal termination")

        wd = os.path.join(cwd, "strategy")
        if not os.path.exists(wd):
            os.mkdir(wd)
        os.chdir(wd)

        CommandLine = get_command_line()
        xinfo = CommandLine.get_xinfo()
        crystals = xinfo.get_crystals()

        assert len(crystals) == 1
        crystal = list(crystals.values())[0]
        assert len(crystal.get_wavelength_names()) == 1
        wavelength = crystal.get_xwavelength(crystal.get_wavelength_names()[0])
        sweeps = wavelength.get_sweeps()

        from xia2.Handlers.Phil import PhilIndex

        params = PhilIndex.get_python_object()
        strategy_params = params.strategy
        if not len(strategy_params):
            strategy_params = [
                PhilIndex.get_scope_by_name("strategy")[0].extract()
            ]

        from dxtbx.model import MultiAxisGoniometer

        gonio = sweeps[0].get_imageset().get_goniometer()
        if (isinstance(gonio, MultiAxisGoniometer)
                and len(gonio.get_axes()) == 3 and gonio.get_scan_axis() == 2):
            from xia2.Wrappers.Dials.AlignCrystal import AlignCrystal

            align_crystal = AlignCrystal()
            align_crystal.set_experiments_filename(
                sweeps[0]._get_integrater().get_integrated_experiments())
            align_crystal.set_working_directory(wd)
            auto_logfiler(align_crystal)
            align_crystal.set_json_filename("%i_align_crystal.json" %
                                            align_crystal.get_xpid())
            align_crystal.run()
            logger.info("".join(align_crystal.get_all_output()))

        results_all = {}

        def process_one_strategy(args):
            assert len(args) == 4
            experiments, reflections, strategy, t_ref = args
            from xia2.Wrappers.EMBL import Best

            best = Best.BestStrategy()
            for isweep, (expt, refl) in enumerate(zip(experiments,
                                                      reflections)):
                from xia2.Wrappers.Dials.ExportBest import ExportBest

                export = ExportBest()
                export.set_experiments_filename(expt)
                export.set_reflections_filename(refl)
                export.set_working_directory(wd)
                auto_logfiler(export)
                prefix = "%i_best" % export.get_xpid()
                export.set_prefix(prefix)
                export.run()
                if isweep == 0:
                    best.set_t_ref(t_ref)
                    best.set_mos_dat("%s.dat" % prefix)
                    best.set_mos_par("%s.par" % prefix)
                best.add_mos_hkl("%s.hkl" % prefix)
            best.set_i2s(strategy.i_over_sigi)
            best.set_T_max(strategy.max_total_exposure)
            best.set_t_min(strategy.min_exposure)
            # best.set_trans_ref(25.0)
            best.set_S_max(strategy.max_rotation_speed)
            best.set_w_min(strategy.min_oscillation_width)
            best.set_M_min(strategy.multiplicity)
            best.set_C_min(strategy.completeness)
            best.set_GpS(strategy.dose_rate)
            best.set_shape(strategy.shape)
            best.set_susceptibility(strategy.susceptibility)
            best.set_anomalous(strategy.anomalous)

            best.set_detector("pilatus6m")
            best.set_working_directory(wd)
            auto_logfiler(best)
            xmlout = os.path.join(best.get_working_directory(),
                                  "%i_best.xml" % best.get_xpid())
            best.set_xmlout(xmlout)
            best.strategy()

            results = best.get_results_dict()
            results["description"] = strategy.description
            if "phi_end" not in results:
                results["phi_end"] = str(
                    float(results["phi_start"]) +
                    float(results["number_of_images"]) *
                    float(results["phi_width"]))
            from dxtbx.serialize import load

            expt = load.experiment_list(experiments[0])[0]
            results["spacegroup"] = (
                expt.crystal.get_space_group().type().lookup_symbol())
            return results

        args = []
        for istrategy, strategy in enumerate(strategy_params):
            imageset = sweeps[0].get_imageset()
            scan = imageset.get_scan()
            experiments = [
                sweep._get_integrater().get_integrated_experiments()
                for sweep in sweeps
            ]
            reflections = [
                sweep._get_integrater().get_integrated_reflections()
                for sweep in sweeps
            ]
            t_ref = scan.get_exposure_times()[0]
            args.append((experiments, reflections, strategy, t_ref))

        nproc = params.xia2.settings.multiprocessing.nproc
        from libtbx import easy_mp

        results = easy_mp.parallel_map(
            process_one_strategy,
            args,
            processes=nproc,
            method="multiprocessing",
            preserve_order=True,
            preserve_exception_message=True,
        )

        for istrategy, (result,
                        strategy) in enumerate(zip(results, strategy_params)):
            name = strategy.name
            description = strategy.description
            if name is None:
                name = "Strategy%i" % (istrategy + 1)
            results_all[name] = result
            multiplicity = result["redundancy"]
            try:
                multiplicity = "%.2f" % multiplicity
            except TypeError:
                pass
            logger.info("Strategy %i", istrategy)
            if description is not None:
                logger.info(description)
            logger.info(
                "Start / end / width: %.2f/%.2f/%.2f",
                float(result["phi_start"]),
                float(result["phi_end"]),
                float(result["phi_width"]),
            )
            logger.info(
                "Completeness / multiplicity / resolution: %.2f/%s/%.2f",
                float(result["completeness"]),
                multiplicity,
                float(result["resolution"]),
            )
            logger.info(
                "Transmission / exposure %.3f/%.3f",
                float(result["transmission"]),
                float(result["exposure_time"]),
            )

        with open("strategies.json", "wb") as f:
            json.dump(results_all, f, indent=2)

    except Exception as e:
        with open(os.path.join(cwd, "xia2-error.txt"), "w") as fh:
            traceback.print_exc(file=fh)
        logger.error('Status: error "%s"', str(e))
    os.chdir(cwd)
Пример #3
0
def xia2_main(stop_after=None):
    '''Actually process something...'''
    Citations.cite('xia2')

    # print versions of related software
    Chatter.write(dials_version())

    ccp4_version = get_ccp4_version()
    if ccp4_version is not None:
        Chatter.write('CCP4 %s' % ccp4_version)

    start_time = time.time()

    CommandLine = get_command_line()
    start_dir = Flags.get_starting_directory()

    # check that something useful has been assigned for processing...
    xtals = CommandLine.get_xinfo().get_crystals()

    no_images = True

    for name in xtals.keys():
        xtal = xtals[name]

        if not xtal.get_all_image_names():

            Chatter.write('-----------------------------------' + \
                          '-' * len(name))
            Chatter.write('| No images assigned for crystal %s |' % name)
            Chatter.write('-----------------------------------' + '-' \
                          * len(name))
        else:
            no_images = False

    args = []

    from xia2.Handlers.Phil import PhilIndex
    params = PhilIndex.get_python_object()
    mp_params = params.xia2.settings.multiprocessing
    njob = mp_params.njob

    from libtbx import group_args

    xinfo = CommandLine.get_xinfo()

    if os.path.exists('xia2.json'):
        from xia2.Schema.XProject import XProject
        xinfo_new = xinfo
        xinfo = XProject.from_json(filename='xia2.json')

        crystals = xinfo.get_crystals()
        crystals_new = xinfo_new.get_crystals()
        for crystal_id in crystals_new.keys():
            if crystal_id not in crystals:
                crystals[crystal_id] = crystals_new[crystal_id]
                continue
            crystals[crystal_id]._scaler = None  # reset scaler
            for wavelength_id in crystals_new[crystal_id].get_wavelength_names(
            ):
                wavelength_new = crystals_new[crystal_id].get_xwavelength(
                    wavelength_id)
                if wavelength_id not in crystals[
                        crystal_id].get_wavelength_names():
                    crystals[crystal_id].add_wavelength(
                        crystals_new[crystal_id].get_xwavelength(
                            wavelength_new))
                    continue
                wavelength = crystals[crystal_id].get_xwavelength(
                    wavelength_id)
                sweeps_new = wavelength_new.get_sweeps()
                sweeps = wavelength.get_sweeps()
                sweep_names = [s.get_name() for s in sweeps]
                sweep_keys = [(s.get_directory(), s.get_template(),
                               s.get_image_range()) for s in sweeps]
                for sweep in sweeps_new:
                    if ((sweep.get_directory(), sweep.get_template(),
                         sweep.get_image_range()) not in sweep_keys):
                        if sweep.get_name() in sweep_names:
                            i = 1
                            while 'SWEEEP%i' % i in sweep_names:
                                i += 1
                            sweep._name = 'SWEEP%i' % i
                            break
                        wavelength.add_sweep(
                            name=sweep.get_name(),
                            sample=sweep.get_xsample(),
                            directory=sweep.get_directory(),
                            image=sweep.get_image(),
                            beam=sweep.get_beam_centre(),
                            reversephi=sweep.get_reversephi(),
                            distance=sweep.get_distance(),
                            gain=sweep.get_gain(),
                            dmin=sweep.get_resolution_high(),
                            dmax=sweep.get_resolution_low(),
                            polarization=sweep.get_polarization(),
                            frames_to_process=sweep.get_frames_to_process(),
                            user_lattice=sweep.get_user_lattice(),
                            user_cell=sweep.get_user_cell(),
                            epoch=sweep._epoch,
                            ice=sweep._ice,
                            excluded_regions=sweep._excluded_regions,
                        )
                        sweep_names.append(sweep.get_name())

    crystals = xinfo.get_crystals()

    failover = params.xia2.settings.failover

    if mp_params.mode == 'parallel' and njob > 1:
        driver_type = mp_params.type
        command_line_args = CommandLine.get_argv()[1:]
        for crystal_id in crystals.keys():
            for wavelength_id in crystals[crystal_id].get_wavelength_names():
                wavelength = crystals[crystal_id].get_xwavelength(
                    wavelength_id)
                sweeps = wavelength.get_sweeps()
                for sweep in sweeps:
                    sweep._get_indexer()
                    sweep._get_refiner()
                    sweep._get_integrater()
                    args.append((group_args(
                        driver_type=driver_type,
                        stop_after=stop_after,
                        failover=failover,
                        command_line_args=command_line_args,
                        nproc=mp_params.nproc,
                        crystal_id=crystal_id,
                        wavelength_id=wavelength_id,
                        sweep_id=sweep.get_name(),
                    ), ))

        from xia2.Driver.DriverFactory import DriverFactory
        default_driver_type = DriverFactory.get_driver_type()

        # run every nth job on the current computer (no need to submit to qsub)
        for i_job, arg in enumerate(args):
            if (i_job % njob) == 0:
                arg[0].driver_type = default_driver_type

        if mp_params.type == "qsub":
            method = "sge"
        else:
            method = "multiprocessing"
        nproc = mp_params.nproc
        qsub_command = mp_params.qsub_command
        if not qsub_command:
            qsub_command = 'qsub'
        qsub_command = '%s -V -cwd -pe smp %d' % (qsub_command, nproc)

        from libtbx import easy_mp
        results = easy_mp.parallel_map(
            process_one_sweep,
            args,
            processes=njob,
            #method=method,
            method="multiprocessing",
            qsub_command=qsub_command,
            preserve_order=True,
            preserve_exception_message=True)

        # Hack to update sweep with the serialized indexers/refiners/integraters
        i_sweep = 0
        for crystal_id in crystals.keys():
            for wavelength_id in crystals[crystal_id].get_wavelength_names():
                wavelength = crystals[crystal_id].get_xwavelength(
                    wavelength_id)
                remove_sweeps = []
                sweeps = wavelength.get_sweeps()
                for sweep in sweeps:
                    success, output, xsweep_dict = results[i_sweep]
                    if output is not None:
                        Chatter.write(output)
                    if not success:
                        Chatter.write('Sweep failed: removing %s' %
                                      sweep.get_name())
                        remove_sweeps.append(sweep)
                    else:
                        assert xsweep_dict is not None
                        Chatter.write('Loading sweep: %s' % sweep.get_name())
                        from xia2.Schema.XSweep import XSweep
                        new_sweep = XSweep.from_dict(xsweep_dict)
                        sweep._indexer = new_sweep._indexer
                        sweep._refiner = new_sweep._refiner
                        sweep._integrater = new_sweep._integrater
                    i_sweep += 1
                for sweep in remove_sweeps:
                    wavelength.remove_sweep(sweep)
                    sample = sweep.get_xsample()
                    sample.remove_sweep(sweep)

    else:
        for crystal_id in crystals.keys():
            for wavelength_id in crystals[crystal_id].get_wavelength_names():
                wavelength = crystals[crystal_id].get_xwavelength(
                    wavelength_id)
                remove_sweeps = []
                sweeps = wavelength.get_sweeps()
                for sweep in sweeps:
                    from dials.command_line.show import show_datablocks
                    from dxtbx.datablock import DataBlock
                    Debug.write(sweep.get_name())
                    Debug.write(
                        show_datablocks([DataBlock([sweep.get_imageset()])]))
                    try:
                        if stop_after == 'index':
                            sweep.get_indexer_cell()
                        else:
                            sweep.get_integrater_intensities()
                        sweep.serialize()
                    except Exception as e:
                        if failover:
                            Chatter.write('Processing sweep %s failed: %s' % \
                                          (sweep.get_name(), str(e)))
                            remove_sweeps.append(sweep)
                        else:
                            raise
                for sweep in remove_sweeps:
                    wavelength.remove_sweep(sweep)
                    sample = sweep.get_xsample()
                    sample.remove_sweep(sweep)

    # save intermediate xia2.json file in case scaling step fails
    xinfo.as_json(filename='xia2.json')

    if stop_after not in ('index', 'integrate'):
        Chatter.write(xinfo.get_output(), strip=False)

    for crystal in crystals.values():
        crystal.serialize()

    # save final xia2.json file in case report generation fails
    xinfo.as_json(filename='xia2.json')

    duration = time.time() - start_time

    # write out the time taken in a human readable way
    Chatter.write('Processing took %s' % \
                  time.strftime("%Hh %Mm %Ss", time.gmtime(duration)))

    if stop_after not in ('index', 'integrate'):
        # and the summary file
        with open('xia2-summary.dat', 'w') as fh:
            for record in xinfo.summarise():
                fh.write('%s\n' % record)

        # looks like this import overwrites the initial command line
        # Phil overrides so... for https://github.com/xia2/xia2/issues/150
        from xia2.command_line.html import generate_xia2_html

        if params.xia2.settings.small_molecule == True:
            params.xia2.settings.report.xtriage_analysis = False
            params.xia2.settings.report.include_radiation_damage = False

        generate_xia2_html(xinfo,
                           filename='xia2.html',
                           params=params.xia2.settings.report)

    write_citations()

    # delete all of the temporary mtz files...
    cleanup()
    Environment.cleanup()
Пример #4
0
def xia2_main(stop_after=None):
    """Actually process something..."""
    Citations.cite("xia2")

    # print versions of related software
    logger.info(dials_version())

    ccp4_version = get_ccp4_version()
    if ccp4_version:
        logger.info("CCP4 %s", ccp4_version)

    start_time = time.time()

    CommandLine = get_command_line()

    # check that something useful has been assigned for processing...
    xtals = CommandLine.get_xinfo().get_crystals()

    for name, xtal in xtals.items():
        if not xtal.get_all_image_names():
            logger.info("-----------------------------------" +
                        "-" * len(name))
            logger.info("| No images assigned for crystal %s |", name)
            logger.info("-----------------------------------" +
                        "-" * len(name))

    from xia2.Handlers.Phil import PhilIndex

    params = PhilIndex.get_python_object()
    mp_params = params.xia2.settings.multiprocessing
    njob = mp_params.njob

    xinfo = CommandLine.get_xinfo()
    logger.info("Project directory: %s", xinfo.path)

    if (params.xia2.settings.developmental.continue_from_previous_job
            and os.path.exists("xia2.json")):
        logger.debug("==== Starting from existing xia2.json ====")
        xinfo_new = xinfo
        xinfo = XProject.from_json(filename="xia2.json")

        crystals = xinfo.get_crystals()
        crystals_new = xinfo_new.get_crystals()
        for crystal_id in crystals_new:
            if crystal_id not in crystals:
                crystals[crystal_id] = crystals_new[crystal_id]
                continue
            crystals[crystal_id]._scaler = None  # reset scaler
            for wavelength_id in crystals_new[crystal_id].get_wavelength_names(
            ):
                wavelength_new = crystals_new[crystal_id].get_xwavelength(
                    wavelength_id)
                if wavelength_id not in crystals[
                        crystal_id].get_wavelength_names():
                    crystals[crystal_id].add_wavelength(
                        crystals_new[crystal_id].get_xwavelength(
                            wavelength_new))
                    continue
                wavelength = crystals[crystal_id].get_xwavelength(
                    wavelength_id)
                sweeps_new = wavelength_new.get_sweeps()
                sweeps = wavelength.get_sweeps()
                sweep_names = {s.get_name() for s in sweeps}
                sweep_keys = {(s.get_directory(), s.get_template(),
                               s.get_image_range())
                              for s in sweeps}
                for sweep in sweeps_new:
                    if (
                            sweep.get_directory(),
                            sweep.get_template(),
                            sweep.get_image_range(),
                    ) not in sweep_keys:
                        if sweep.get_name() in sweep_names:
                            i = 1
                            while "SWEEEP%i" % i in sweep_names:
                                i += 1
                            sweep._name = "SWEEP%i" % i
                            break
                        wavelength.add_sweep(
                            name=sweep.get_name(),
                            sample=sweep.sample,
                            directory=sweep.get_directory(),
                            image=sweep.get_image(),
                            beam=sweep.get_beam_centre(),
                            reversephi=sweep.get_reversephi(),
                            distance=sweep.get_distance(),
                            gain=sweep.get_gain(),
                            dmin=sweep.get_resolution_high(),
                            dmax=sweep.get_resolution_low(),
                            polarization=sweep.get_polarization(),
                            frames_to_process=sweep.get_frames_to_process(),
                            user_lattice=sweep.get_user_lattice(),
                            user_cell=sweep.get_user_cell(),
                            epoch=sweep._epoch,
                            ice=sweep._ice,
                            excluded_regions=sweep._excluded_regions,
                        )
                        sweep_names.add(sweep.get_name())

    crystals = xinfo.get_crystals()

    failover = params.xia2.settings.failover

    with cleanup(xinfo.path):
        if mp_params.mode == "parallel" and njob > 1:
            driver_type = mp_params.type
            command_line_args = CommandLine.get_argv()[1:]
            jobs = []
            for crystal_id in crystals:
                for wavelength_id in crystals[crystal_id].get_wavelength_names(
                ):
                    wavelength = crystals[crystal_id].get_xwavelength(
                        wavelength_id)
                    sweeps = wavelength.get_sweeps()
                    for sweep in sweeps:
                        sweep._get_indexer()
                        sweep._get_refiner()
                        sweep._get_integrater()
                        jobs.append((group_args(
                            driver_type=driver_type,
                            stop_after=stop_after,
                            failover=failover,
                            command_line_args=command_line_args,
                            nproc=mp_params.nproc,
                            crystal_id=crystal_id,
                            wavelength_id=wavelength_id,
                            sweep_id=sweep.get_name(),
                        ), ))

            from xia2.Driver.DriverFactory import DriverFactory

            default_driver_type = DriverFactory.get_driver_type()

            # run every nth job on the current computer (no need to submit to qsub)
            for i_job, arg in enumerate(jobs):
                if (i_job % njob) == 0:
                    arg[0].driver_type = default_driver_type

            nproc = mp_params.nproc
            qsub_command = mp_params.qsub_command or "qsub"
            qsub_command = "%s -V -cwd -pe smp %d" % (qsub_command, nproc)

            from libtbx import easy_mp

            results = easy_mp.parallel_map(
                process_one_sweep,
                jobs,
                processes=njob,
                method="multiprocessing",
                qsub_command=qsub_command,
                preserve_order=True,
                preserve_exception_message=True,
            )

            # Hack to update sweep with the serialized indexers/refiners/integraters
            i_sweep = 0
            for crystal_id in crystals:
                for wavelength_id in crystals[crystal_id].get_wavelength_names(
                ):
                    wavelength = crystals[crystal_id].get_xwavelength(
                        wavelength_id)
                    remove_sweeps = []
                    sweeps = wavelength.get_sweeps()
                    for sweep in sweeps:
                        success, output, xsweep_dict = results[i_sweep]
                        if output is not None:
                            logger.info(output)
                        if not success:
                            logger.info("Sweep failed: removing %s",
                                        sweep.get_name())
                            remove_sweeps.append(sweep)
                        else:
                            assert xsweep_dict is not None
                            logger.info("Loading sweep: %s", sweep.get_name())
                            new_sweep = XSweep.from_dict(xsweep_dict)
                            sweep._indexer = new_sweep._indexer
                            sweep._refiner = new_sweep._refiner
                            sweep._integrater = new_sweep._integrater
                        i_sweep += 1
                    for sweep in remove_sweeps:
                        wavelength.remove_sweep(sweep)
                        sample = sweep.sample
                        sample.remove_sweep(sweep)

        else:
            for crystal_id in list(crystals.keys()):
                for wavelength_id in crystals[crystal_id].get_wavelength_names(
                ):
                    wavelength = crystals[crystal_id].get_xwavelength(
                        wavelength_id)
                    remove_sweeps = []
                    sweeps = wavelength.get_sweeps()
                    for sweep in sweeps:
                        from dials.command_line.show import show_experiments
                        from dxtbx.model.experiment_list import ExperimentListFactory

                        logger.debug(sweep.get_name())
                        logger.debug(
                            show_experiments(
                                ExperimentListFactory.
                                from_imageset_and_crystal(
                                    sweep.get_imageset(), None)))
                        Citations.cite("dials")
                        try:
                            if stop_after == "index":
                                sweep.get_indexer_cell()
                            else:
                                sweep.get_integrater_intensities()
                            sweep.serialize()
                        except Exception as e:
                            if failover:
                                logger.info(
                                    "Processing sweep %s failed: %s",
                                    sweep.get_name(),
                                    str(e),
                                )
                                remove_sweeps.append(sweep)
                            else:
                                raise
                    for sweep in remove_sweeps:
                        wavelength.remove_sweep(sweep)
                        sample = sweep.sample
                        sample.remove_sweep(sweep)

        # save intermediate xia2.json file in case scaling step fails
        xinfo.as_json(filename="xia2.json")

        if stop_after not in ("index", "integrate"):
            logger.info(xinfo.get_output())

        for crystal in list(crystals.values()):
            crystal.serialize()

        # save final xia2.json file in case report generation fails
        xinfo.as_json(filename="xia2.json")

        if stop_after not in ("index", "integrate"):
            # and the summary file
            with open("xia2-summary.dat", "w") as fh:
                for record in xinfo.summarise():
                    fh.write("%s\n" % record)

            # looks like this import overwrites the initial command line
            # Phil overrides so... for https://github.com/xia2/xia2/issues/150
            from xia2.command_line.html import generate_xia2_html

            if params.xia2.settings.small_molecule:
                params.xia2.settings.report.xtriage_analysis = False
                params.xia2.settings.report.include_radiation_damage = False

            with xia2.Driver.timing.record_step("xia2.report"):
                generate_xia2_html(xinfo,
                                   filename="xia2.html",
                                   params=params.xia2.settings.report)

        duration = time.time() - start_time

        # write out the time taken in a human readable way
        logger.info("Processing took %s",
                    time.strftime("%Hh %Mm %Ss", time.gmtime(duration)))

        write_citations()
Пример #5
0
def run():
    try:
        check_environment()
    except Exception as e:
        traceback.print_exc(file=open('xia2.error', 'w'))
        Chatter.write('Status: error "%s"' % str(e))

    if len(sys.argv) < 2 or '-help' in sys.argv:
        help()
        sys.exit()

    cwd = os.getcwd()

    try:
        from xia2.command_line.xia2_main import xia2_main
        xia2_main(stop_after='integrate')
        Chatter.write('Status: normal termination')

        wd = os.path.join(cwd, 'strategy')
        if not os.path.exists(wd):
            os.mkdir(wd)
        os.chdir(wd)

        CommandLine = get_command_line()
        xinfo = CommandLine.get_xinfo()
        crystals = xinfo.get_crystals()

        assert len(crystals) == 1
        crystal = crystals.values()[0]
        assert len(crystal.get_wavelength_names()) == 1
        wavelength = crystal.get_xwavelength(crystal.get_wavelength_names()[0])
        sweeps = wavelength.get_sweeps()

        from xia2.Handlers.Phil import PhilIndex
        params = PhilIndex.get_python_object()
        strategy_params = params.strategy
        if not len(strategy_params):
            strategy_params = [
                PhilIndex.get_scope_by_name('strategy')[0].extract()
            ]

        from dxtbx.model import MultiAxisGoniometer
        gonio = sweeps[0].get_imageset().get_goniometer()
        if (isinstance(gonio, MultiAxisGoniometer)
                and len(gonio.get_axes()) == 3 and gonio.get_scan_axis() == 2):
            from xia2.Wrappers.Dials.AlignCrystal import AlignCrystal
            align_crystal = AlignCrystal()
            align_crystal.set_experiments_filename(
                sweeps[0]._get_integrater().get_integrated_experiments())
            align_crystal.set_working_directory(wd)
            auto_logfiler(align_crystal)
            align_crystal.set_json_filename('%i_align_crystal.json' %
                                            align_crystal.get_xpid())
            align_crystal.run()
            Chatter.write("".join(align_crystal.get_all_output()))

        results_all = {}

        def process_one_strategy(args):
            assert len(args) == 4
            experiments, reflections, strategy, t_ref = args
            from xia2.Wrappers.EMBL import Best
            best = Best.BestStrategy()
            for isweep, (expt, refl) in enumerate(zip(experiments,
                                                      reflections)):
                integrater = sweep._get_integrater()
                from xia2.Wrappers.Dials.ExportBest import ExportBest
                export = ExportBest()
                export.set_experiments_filename(expt)
                export.set_reflections_filename(refl)
                export.set_working_directory(wd)
                auto_logfiler(export)
                prefix = '%i_best' % export.get_xpid()
                export.set_prefix(prefix)
                export.run()
                if isweep == 0:
                    imageset = sweep.get_imageset()
                    scan = imageset.get_scan()
                    best.set_t_ref(t_ref)
                    best.set_mos_dat('%s.dat' % prefix)
                    best.set_mos_par('%s.par' % prefix)
                best.add_mos_hkl('%s.hkl' % prefix)
            best.set_i2s(strategy.i_over_sigi)
            best.set_T_max(strategy.max_total_exposure)
            best.set_t_min(strategy.min_exposure)
            #best.set_trans_ref(25.0)
            best.set_S_max(strategy.max_rotation_speed)
            best.set_w_min(strategy.min_oscillation_width)
            best.set_M_min(strategy.multiplicity)
            best.set_C_min(strategy.completeness)
            best.set_GpS(strategy.dose_rate)
            best.set_shape(strategy.shape)
            best.set_susceptibility(strategy.susceptibility)
            best.set_anomalous(strategy.anomalous)

            best.set_detector('pilatus6m')
            best.set_working_directory(wd)
            auto_logfiler(best)
            xmlout = '%s/%i_best.xml' % (best.get_working_directory(),
                                         best.get_xpid())
            best.set_xmlout(xmlout)
            best.strategy()

            results = best.get_results_dict()
            results['description'] = strategy.description
            if 'phi_end' not in results:
                results['phi_end'] = str(
                    float(results['phi_start']) +
                    float(results['number_of_images']) *
                    float(results['phi_width']))
            from dxtbx.serialize import load
            expt = load.experiment_list(experiments[0])[0]
            results['spacegroup'] = expt.crystal.get_space_group().type(
            ).lookup_symbol()
            return results

        args = []
        for istrategy, strategy in enumerate(strategy_params):
            imageset = sweeps[0].get_imageset()
            scan = imageset.get_scan()
            experiments = [
                sweep._get_integrater().get_integrated_experiments()
                for sweep in sweeps
            ]
            reflections = [
                sweep._get_integrater().get_integrated_reflections()
                for sweep in sweeps
            ]
            t_ref = scan.get_exposure_times()[0]
            args.append((experiments, reflections, strategy, t_ref))

        nproc = params.xia2.settings.multiprocessing.nproc
        from libtbx import easy_mp
        results = easy_mp.parallel_map(process_one_strategy,
                                       args,
                                       processes=nproc,
                                       method='multiprocessing',
                                       preserve_order=True,
                                       preserve_exception_message=True)

        for istrategy, (result,
                        strategy) in enumerate(zip(results, strategy_params)):
            name = strategy.name
            description = strategy.description
            if name is None:
                name = 'Strategy%i' % (istrategy + 1)
            results_all[name] = result
            multiplicity = result['redundancy']
            try:
                mutiplicity = '%.2f' % multiplicity
            except TypeError:
                pass
            Chatter.write('Strategy %i' % istrategy)
            if description is not None:
                Chatter.write(description)
            Chatter.write('Start / end / width: %.2f/%.2f/%.2f' %
                          (float(result['phi_start']), float(
                              result['phi_end']), float(result['phi_width'])))
            Chatter.write(
                'Completeness / multiplicity / resolution: %.2f/%s/%.2f' %
                (float(result['completeness']), multiplicity,
                 float(result['resolution'])))
            Chatter.write('Transmission / exposure %.3f/%.3f' % (float(
                result['transmission']), float(result['exposure_time'])))

        import json
        with open('strategies.json', 'wb') as f:
            json.dump(results_all, f, indent=2)

    except Exception as e:
        traceback.print_exc(file=open(os.path.join(cwd, 'xia2.error'), 'w'))
        Chatter.write('Status: error "%s"' % str(e))
    os.chdir(cwd)