예제 #1
0
def thin_ds1(idx, frame_params):

    from libtbx.phil import parse
    from simtbx.diffBragg.phil import philz
    from simtbx.diffBragg.phil import hopper_phil
    philz = hopper_phil + philz
    phil_scope_db = parse(philz)
    from LS49.adse13_187.report_versions import ds1_params_v4 as ds1_params
    user_phil = parse(ds1_params)
    working_phil = phil_scope_db.fetch(sources=[user_phil])
    params = working_phil.extract()
    from simtbx.diffBragg import hopper_utils
    BERNINA = os.environ.get("BERNINA")

    try:
      exp, ref, data_modeler, x = hopper_utils.refine(
      exp=os.path.join(BERNINA, "split_cs", "split_%04d.expt"%idx),
      ref = os.path.join(BERNINA, "split2b" , "split_%04d.refl"%idx),
      params=params, return_modeler=True)
      (scale, rotX, rotY, rotZ, Na, Nb, Nc,
       diff_gam_a, diff_gam_b, diff_gam_c, diff_sig_a, diff_sig_b, diff_sig_c,
       a,b,c,al,be,ga, detz) = hopper_utils.get_param_from_x(x,data_modeler.SIM)
      from dxtbx.model.experiment_list import ExperimentList
      L = ExperimentList()
      L.append(exp)
      L.as_file("ds1_%04d.expt"%idx)
      print("DS1 parameters index %d Na Nb Nc %.3f %.3f %.3f"%(idx,Na,Nb,Nc))

      from LS49.adse13_187.adse13_221.basic_runner import run as basic_run
      anaparams = mcmc_runner_parse_input()
      anaparams.trusted_mask=os.path.join(BERNINA, "trusted_Py3.mask")
      anaparams.cryst="ds1_%04d.expt"%idx
      anaparams.expt = os.path.join(BERNINA, "split_cs", "split_%04d.expt"%idx)
      anaparams.refl=os.path.join(BERNINA, "split2b" , "split_%04d.refl"%idx)
      anaparams.output.enable=False
      anaparams.output.label="mcmc3"
      anaparams.output.index=idx
      anaparams.model.mosaic_spread.value=0.001
      anaparams.model.Nabc.value=(Na,Nb,Nc)
      anaparams.model.Nabc.hyperparameter=0.8
      anaparams.model.rot.refine=True
      anaparams.model.cell.covariance=os.path.join(
      BERNINA,"..", "covariance_cytochrome_form.pickle")
      anaparams.simplex.cycles=200
      anaparams.mcmc.cycles=2000
      anaparams.model.plot=False
      print(anaparams.trusted_mask)
      print(anaparams.cryst)
      print(anaparams.expt)
      print(anaparams.refl)
      print(anaparams.model.cell.covariance)
      basic_run(anaparams)

    except Exception as e:
      print("CATCH EXCEPTION",e)
      traceback.print_exc()
예제 #2
0
파일: index.py 프로젝트: hattne/dials
    def export_experiments(self, filename):
        experiments = self._indexed_experiments
        if self._params.output.split_experiments:
            logger.info("Splitting experiments before output")

            experiments = ExperimentList(
                [copy.deepcopy(re) for re in experiments])
        logger.info("Saving refined experiments to %s" % filename)

        assert experiments.is_consistent()
        experiments.as_file(filename)
예제 #3
0
def run(phil=working_phil, args=None):
    usage = "dials.index [options] models.expt strong.refl"

    parser = OptionParser(
        usage=usage,
        phil=phil,
        read_reflections=True,
        read_experiments=True,
        check_format=False,
        epilog=help_message,
    )

    params, options = parser.parse_args(args=args, show_diff_phil=False)

    # Configure the logging
    log.config(verbosity=options.verbose, logfile=params.output.log)
    logger.info(dials_version())

    # Log the diff phil
    diff_phil = parser.diff_phil.as_str()
    if diff_phil != "":
        logger.info("The following parameters have been modified:\n")
        logger.info(diff_phil)

    experiments = flatten_experiments(params.input.experiments)
    reflections = flatten_reflections(params.input.reflections)

    if len(experiments) == 0:
        parser.print_help()
        return

    try:
        indexed_experiments, indexed_reflections = index(
            experiments, reflections, params)
    except (DialsIndexError, ValueError) as e:
        sys.exit(str(e))

    # Save experiments
    if params.output.split_experiments:
        logger.info("Splitting experiments before output")
        indexed_experiments = ExperimentList(
            [copy.deepcopy(re) for re in indexed_experiments])
    logger.info("Saving refined experiments to %s" % params.output.experiments)
    assert indexed_experiments.is_consistent()
    indexed_experiments.as_file(params.output.experiments)

    # Save reflections
    logger.info("Saving refined reflections to %s" % params.output.reflections)
    indexed_reflections.as_msgpack_file(filename=params.output.reflections)
예제 #4
0
    def as_explist(self, fname=None, toggle_conventions=False):
        """
    return experiment list for simulated image
    """
        C = self.crystal
        if toggle_conventions:
            # switch to DIALS convention before writing CBF
            # also change basis of crystal
            CURRENT_CONV = self.beamcenter_convention
            FSO = sqr(self.fdet_vector + self.sdet_vector +
                      self.pix0_vector_mm)
            self.beamcenter_convention = DIALS
            FSO2 = sqr(self.fdet_vector + self.sdet_vector +
                       self.dials_origin_mm)
            xtal_transform = FSO.inverse() * FSO2

            # transform the crystal vectors
            a, b, c = map(lambda x: xtal_transform * col(x),
                          C.get_real_space_vectors())
            Cdict = C.to_dict()
            Cdict['real_space_a'] = a
            Cdict['real_space_b'] = b
            Cdict['real_space_b'] = c
            C = CrystalFactory.from_dict(Cdict)

        exp = Experiment()
        exp.crystal = C
        exp.beam = self.beam
        exp.detector = self.detector
        exp.imageset = self.imageset
        explist = ExperimentList()
        explist.append(exp)
        if fname is not None:
            explist.as_file(fname)
        if toggle_conventions:
            self.beamcenter_convention = CURRENT_CONV

        return explist
예제 #5
0
파일: hopper.py 프로젝트: dials/cctbx
def save_to_pandas(x, SIM, orig_exp_name, params, expt, rank_exp_idx, stg1_refls, stg1_img_path):
    LOGGER = logging.getLogger("refine")
    rank_exper_outdir = make_rank_outdir(params.outdir, "expers")
    rank_pandas_outdir =make_rank_outdir(params.outdir, "pandas")

    #if SIM.num_xtals > 1:
    #    raise NotImplemented("cant save pandas for multiple crystals yet")
    scale, rotX, rotY, rotZ, Na, Nb, Nc,diff_gam_a, diff_gam_b, diff_gam_c, diff_sig_a, diff_sig_b, diff_sig_c, a,b,c,al,be,ga,detz_shift = hopper_utils.get_param_from_x(x, SIM)
    if params.isotropic.diffuse_gamma:
        diff_gam_b = diff_gam_c = diff_gam_a
    if params.isotropic.diffuse_sigma:
        diff_sig_b = diff_sig_c = diff_sig_a
    shift = np.nan
    #if SIM.shift_param is not None:
    #    shift = SIM.shift_param.get_val(x[-1])
    xtal_scales = [scale]
    eta_a, eta_b, eta_c = hopper_utils.get_mosaicity_from_x(x, SIM)
    a_init, b_init, c_init, al_init, be_init, ga_init = SIM.crystal.dxtbx_crystal.get_unit_cell().parameters()

    xax = col((-1, 0, 0))
    yax = col((0, -1, 0))
    zax = col((0, 0, -1))
    ## update parameters:
    RX = xax.axis_and_angle_as_r3_rotation_matrix(rotX, deg=False)
    RY = yax.axis_and_angle_as_r3_rotation_matrix(rotY, deg=False)
    RZ = zax.axis_and_angle_as_r3_rotation_matrix(rotZ, deg=False)
    M = RX * RY * RZ
    U = M * sqr(SIM.crystal.dxtbx_crystal.get_U())
    SIM.crystal.dxtbx_crystal.set_U(U)

    ucparam = a, b, c, al, be, ga
    ucman = utils.manager_from_params(ucparam)
    SIM.crystal.dxtbx_crystal.set_B(ucman.B_recipspace)

    Amats = [SIM.crystal.dxtbx_crystal.get_A()]
    ncells_def_vals = [(0, 0, 0)]
    ncells_vals = [(Na, Nb, Nc)]
    eta = [0]
    lam0 = [-1]
    lam1 = [-1]
    df = pandas.DataFrame({
        # "panX": list(panX), "panY": list(panY), "panZ": list(panZ),
        # "panO": list(panO), "panF": list(panF), "panS": list(panS),
        "spot_scales": xtal_scales, "Amats": Amats, "ncells": ncells_vals,
        "eta_abc": [(eta_a, eta_b, eta_c)],
        "detz_shift_mm": [detz_shift * 1e3],
        "ncells_def": ncells_def_vals,
        "diffuse_gamma": [(diff_gam_a, diff_gam_b, diff_gam_c)],
        "diffuse_sigma": [(diff_sig_a, diff_sig_b, diff_sig_c)],
        "fp_fdp_shift": [shift],
        "use_diffuse_models": [params.use_diffuse_models],
        "gamma_miller_units": [params.gamma_miller_units],
        # "bgplanes": bgplanes, "image_corr": image_corr,
        # "init_image_corr": init_img_corr,
        # "fcell_xstart": fcell_xstart,
        # "ucell_xstart": ucell_xstart,
        # "init_misorient": init_misori, "final_misorient": final_misori,
        # "bg_coef": bg_coef,
        "eta": eta,
        "rotX": rotX,
        "rotY": rotY,
        "rotZ": rotZ,
        "a": a, "b": b, "c": c, "al": al, "be": be, "ga": ga,
        "a_init": a_init, "b_init": b_init, "c_init": c_init, "al_init": al_init,
        "lam0": lam0, "lam1": lam1,
        "be_init": be_init, "ga_init": ga_init})
    # "scale_xpos": scale_xpos,
    # "ncells_xpos": ncells_xstart,
    # "bgplanes_xpos": bgplane_xpos})

    basename = os.path.splitext(os.path.basename(orig_exp_name))[0]
    opt_exp_path = os.path.join(rank_exper_outdir, "%s_%s_%d.expt" % (params.tag, basename, rank_exp_idx))
    pandas_path = os.path.join(rank_pandas_outdir, "%s_%s_%d.pkl" % (params.tag, basename, rank_exp_idx))
    expt.crystal = SIM.crystal.dxtbx_crystal
    # expt.detector = refiner.get_optimized_detector()
    new_exp_list = ExperimentList()
    new_exp_list.append(expt)
    new_exp_list.as_file(opt_exp_path)
    LOGGER.debug("saved opt_exp %s with wavelength %f" % (opt_exp_path, expt.beam.get_wavelength()))

    spec_file = None
    if params.simulator.spectrum.filename is not None:
        spec_file = os.path.abspath(params.simulator.spectrum.filename)
    df["spectrum_filename"] = spec_file
    df["spectrum_stride"] = params.simulator.spectrum.stride

    df["total_flux"] = SIM.D.flux  # params.simulator.total_flux
    df["beamsize_mm"] = SIM.beam.size_mm
    df["exp_name"] = os.path.abspath(orig_exp_name)
    df["opt_exp_name"] = os.path.abspath(opt_exp_path)
    df["spectrum_from_imageset"] = params.spectrum_from_imageset
    df["oversample"] = params.simulator.oversample
    if params.opt_det is not None:
        df["opt_det"] = params.opt_det
    df["stage1_refls"] = stg1_refls
    df["stage1_output_img"] = stg1_img_path

    df.to_pickle(pandas_path)
    return df
예제 #6
0
)
n_exper = len(El)
new_refl = flex.reflection_table()
new_expl = ExperimentList()

for i_exp in range(n_exper):

    exper_img_path = El[i_exp].imageset.get_path(0)
    exper_basename = os.path.basename(exper_img_path)
    exper_basename = exper_basename.split(".h5.npz")[0]
    exper_crystal = El[i_exp].crystal
    new_crystal = deepcopy(exper_crystal)
    df_sel = df.query("basename=='%s'" % exper_basename)
    if not len(df_sel) == 1:
        continue
    new_A = df_sel["Amats"].values[0]
    new_crystal.set_A(new_A)
    a, _, c, _, _, _ = new_crystal.get_unit_cell().parameters()
    if i_exp % 50 == 0:
        print("Processed %d / %d experiments" % (i_exp + 1, n_exper))
    El[i_exp].crystal = new_crystal

    # save the experiemnts
    new_expl.append(El[i_exp])
    refl_i = refl.select(
        refl['id'] == i_exp)  # NOTE: this might change at some point...
    new_refl.extend(refl_i)

new_refl.as_file(args.out + ".refl")
new_expl.as_file(args.out + ".expt")
예제 #7
0
    def run(self):
        """Execute the script."""

        from dials.util.options import reflections_and_experiments_from_files

        # Parse the command line
        params, options = self.parser.parse_args(show_diff_phil=True)
        reflections, experiments = reflections_and_experiments_from_files(
            params.input.reflections, params.input.experiments)

        # Try to load the models and data
        slice_exps = len(experiments) > 0
        slice_refs = len(reflections) > 0

        # Catch case of nothing to do
        if not slice_exps and not slice_refs:
            print("No suitable input provided")
            self.parser.print_help()
            return

        if reflections:
            if len(reflections) > 1:
                raise Sorry(
                    "Only one reflections list can be imported at present")
            reflections = reflections[0]

            # calculate frame numbers if needed
            if experiments:
                reflections = calculate_frame_numbers(reflections, experiments)

            # if we still don't have the right column give up
            if "xyzobs.px.value" not in reflections:
                raise Sorry(
                    "These reflections do not have frame numbers set, and "
                    "there are no experiments provided to calculate these.")

        # set trivial case where no scan range is provided at all
        if not params.image_range:
            params.image_range = [None]

        # check if slicing into blocks
        if params.block_size is not None:
            if slice_exps:
                if len(experiments) > 1:
                    raise Sorry(
                        "For slicing into blocks please provide a single "
                        "scan only")
                scan = experiments[0].scan

            # Having extracted the scan, calculate the blocks
            params.image_range = calculate_block_ranges(
                scan, params.block_size)

            # Do the slicing then recombine
            if slice_exps:
                sliced = [
                    slice_experiments(experiments, [sr])[0]
                    for sr in params.image_range
                ]
                sliced_experiments = ExperimentList()
                for exp in sliced:
                    sliced_experiments.append(exp)

            # slice reflections if present
            if slice_refs:
                sliced = [
                    slice_reflections(reflections, [sr])
                    for sr in params.image_range
                ]
                sliced_reflections = sliced[0]
                for i, rt in enumerate(sliced[1:]):
                    rt["id"] += i + 1  # set id
                    sliced_reflections.extend(rt)

        else:
            # slice each dataset into the requested subset
            if slice_exps:
                sliced_experiments = slice_experiments(experiments,
                                                       params.image_range)
            if slice_refs:
                sliced_reflections = slice_reflections(reflections,
                                                       params.image_range)

        # Save sliced experiments
        if slice_exps:
            output_experiments_filename = params.output.experiments_filename
            if output_experiments_filename is None:
                # take first filename as template
                bname = basename(params.input.experiments[0].filename)
                bname = splitext(bname)[0]
                if not bname:
                    bname = "experiments"
                if len(params.image_range
                       ) == 1 and params.image_range[0] is not None:
                    ext = "_{0}_{1}.expt".format(*params.image_range[0])
                else:
                    ext = "_sliced.expt"
                output_experiments_filename = bname + ext
            print("Saving sliced experiments to {}".format(
                output_experiments_filename))

            sliced_experiments.as_file(output_experiments_filename)

        # Save sliced reflections
        if slice_refs:
            output_reflections_filename = params.output.reflections_filename
            if output_reflections_filename is None:
                # take first filename as template
                bname = basename(params.input.reflections[0].filename)
                bname = splitext(bname)[0]
                if not bname:
                    bname = "reflections"
                if len(params.image_range
                       ) == 1 and params.image_range[0] is not None:
                    ext = "_{0}_{1}.refl".format(*params.image_range[0])
                else:
                    ext = "_sliced.refl"
                output_reflections_filename = bname + ext

            print("Saving sliced reflections to {0}".format(
                output_reflections_filename))
            sliced_reflections.as_file(output_reflections_filename)

        return
예제 #8
0
def generate_mask(
    experiments: ExperimentList,
    params: phil.scope_extract,
) -> Tuple[Masks, Optional[ExperimentList]]:
    """
    Generate a pixel mask for each imageset in an experiment list.

    Use the masking parameters :param:`params` and the experiments in the experiment
    list :param:`experiments` to define a pixel mask for each of the associated
    imagesets.  The masks are generated using :mod:`dials.util.masking`.

    The masks will be saved to disk at the location specified by
    :attr:`params.output.mask`.  If the experiment list contains more than one
    imageset, multiple mask files will be produced, with filenames differentiated by
    an appended number.  Optionally, if a path :attr:`params.output.experiments` is
    set, a modified copy of :param:`experiments` with the masks applied will be saved
    to that location.

    Args:
        experiments: An experiment list containing only one imageset.
        params: Masking parameters, having the structure defined in
            :data:`phil_scope`.

    Returns:
        A list of masks, one for each imageset.

        A copy of :param:`experiments` with the masks applied (optional,
        only returned if :attr:`params.output.experiments` is set).
    """
    imagesets = experiments.imagesets()
    masks = []

    # Create output mask filenames
    num_imagesets = len(imagesets)
    if num_imagesets == 1:
        filenames = [params.output.mask]
    else:
        # If there is more than one imageset, append a number to each output filename
        name, ext = os.path.splitext(params.output.mask)
        pad = len(str(num_imagesets))
        filenames = [
            "{name}_{num:0{pad}}{ext}".format(name=name,
                                              num=i + 1,
                                              pad=pad,
                                              ext=ext)
            for i in range(num_imagesets)
        ]

    for imageset, filename in zip(imagesets, filenames):
        mask = dials.util.masking.generate_mask(imageset, params)
        masks.append(mask)

        # Save the mask to file
        log.info("Writing mask to %s", filename)
        with open(filename, "wb") as fh:
            pickle.dump(mask, fh)

        if params.output.experiments:
            # Apply the mask to the imageset
            imageset.external_lookup.mask.data = ImageBool(mask)
            imageset.external_lookup.mask.filename = filename

    if params.output.experiments:
        # Save the experiment list
        log.info("Saving experiments to %s", params.output.experiments)
        experiments.as_file(params.output.experiments)
    else:
        experiments = None

    return masks, experiments
예제 #9
0
 def prepare_input(self, experiment):
     self.make_workdir()
     experiment_list = ExperimentList()
     experiment_list.append(experiment)
     experiment_list.as_file(self.input_experiment_fname)
예제 #10
0
    def run(self):
        """Execute the script."""
        start_time = time()

        # Parse the command line
        params, _ = self.parser.parse_args(show_diff_phil=False)

        # set up global experiments and reflections lists

        reflections = flex.reflection_table()
        global_id = 0

        experiments = ExperimentList()

        # loop through the input, building up the global lists
        nrefs_per_exp = []
        for ref_wrapper, exp_wrapper in zip(
            params.input.reflections, params.input.experiments
        ):
            refs = ref_wrapper.data
            exps = exp_wrapper.data
            for i, exp in enumerate(exps):
                sel = refs["id"] == i
                sub_ref = refs.select(sel)
                nrefs_per_exp.append(len(sub_ref))
                sub_ref["id"] = flex.int(len(sub_ref), global_id)
                reflections.extend(sub_ref)
                experiments.append(exp)
                global_id += 1

        # Try to load the models and data
        nexp = len(experiments)
        if nexp == 0:
            print("No Experiments found in the input")
            self.parser.print_help()
            return
        if not reflections:
            print("No reflection data found in the input")
            self.parser.print_help()
            return

        self.check_input(reflections)

        # Configure the logging
        log.config(info=params.output.log, debug=params.output.debug_log)
        logger.info(dials_version())

        # Log the diff phil
        diff_phil = self.parser.diff_phil.as_str()
        if diff_phil != "":
            logger.info("The following parameters have been modified:\n")
            logger.info(diff_phil)

        # Convert to P 1?
        if params.refinement.triclinic:
            reflections, experiments = self.convert_to_P1(reflections, experiments)

        # Combine crystals?
        if params.refinement.combine_crystal_models and len(experiments) > 1:
            logger.info("Combining {0} crystal models".format(len(experiments)))
            experiments = self.combine_crystals(experiments)

        # Filter integrated centroids?
        if params.refinement.filter_integrated_centroids:
            reflections = self.filter_integrated_centroids(reflections)

        # Filter data if scaled to remove outliers
        if "inverse_scale_factor" in reflections:
            try:
                reflections = filter_reflection_table(reflections, ["scale"])
            except ValueError as e:
                logger.warn(e)
                logger.info(
                    "Filtering on scaled data failed, proceeding with integrated data."
                )

        # Get the refiner
        logger.info("Configuring refiner")
        refiner = self.create_refiner(params, reflections, experiments)

        # Refine the geometry
        if nexp == 1:
            logger.info("Performing refinement of a single Experiment...")
        else:
            logger.info("Performing refinement of {} Experiments...".format(nexp))
        refiner.run()

        # get the refined experiments
        experiments = refiner.get_experiments()
        crystals = experiments.crystals()

        if len(crystals) == 1:
            # output the refined model for information
            logger.info("")
            logger.info("Final refined crystal model:")
            logger.info(crystals[0])
            logger.info(self.cell_param_table(crystals[0]))

        # Save the refined experiments to file
        output_experiments_filename = params.output.experiments
        logger.info(
            "Saving refined experiments to {}".format(output_experiments_filename)
        )
        experiments.as_file(output_experiments_filename)

        # Create correlation plots
        if params.output.correlation_plot.filename is not None:
            create_correlation_plots(refiner, params.output)

        if params.output.cif is not None:
            self.generate_cif(crystals[0], refiner, filename=params.output.cif)

        if params.output.p4p is not None:
            self.generate_p4p(
                crystals[0], experiments[0].beam, filename=params.output.p4p
            )

        if params.output.mmcif is not None:
            self.generate_mmcif(crystals[0], refiner, filename=params.output.mmcif)

        # Log the total time taken
        logger.info("\nTotal time taken: {:.2f}s".format(time() - start_time))
예제 #11
0
def save_to_pandas(x, SIM, orig_exp_name, params, expt, rank_exp_idx,
                   stg1_refls, stg1_img_path):
    LOGGER = logging.getLogger("refine")
    rank_exper_outdir = make_rank_outdir(params.outdir, "expers")
    rank_pandas_outdir = make_rank_outdir(params.outdir, "pandas")

    scale, rotX, rotY, rotZ, Na, Nb, Nc, diff_gam_a, diff_gam_b, diff_gam_c, diff_sig_a, diff_sig_b, diff_sig_c, a, b, c, al, be, ga, detz_shift = hopper_utils.get_param_from_x(
        x, SIM)
    scale_p = SIM.P["G_xtal0"]
    scale_init = scale_p.init
    Nabc_init = []
    for i in [0, 1, 2]:
        p = SIM.P["Nabc%d" % i]
        Nabc_init.append(p.init)
    Nabc_init = tuple(Nabc_init)

    if params.isotropic.diffuse_gamma:
        diff_gam_b = diff_gam_c = diff_gam_a
    if params.isotropic.diffuse_sigma:
        diff_sig_b = diff_sig_c = diff_sig_a
    eta_a, eta_b, eta_c = hopper_utils.get_mosaicity_from_x(x, SIM)
    a_init, b_init, c_init, al_init, be_init, ga_init = SIM.crystal.dxtbx_crystal.get_unit_cell(
    ).parameters()

    xax = col((-1, 0, 0))
    yax = col((0, -1, 0))
    zax = col((0, 0, -1))
    ## update parameters:
    RX = xax.axis_and_angle_as_r3_rotation_matrix(rotX, deg=False)
    RY = yax.axis_and_angle_as_r3_rotation_matrix(rotY, deg=False)
    RZ = zax.axis_and_angle_as_r3_rotation_matrix(rotZ, deg=False)
    M = RX * RY * RZ
    U = M * sqr(SIM.crystal.dxtbx_crystal.get_U())
    SIM.crystal.dxtbx_crystal.set_U(U)

    ucparam = a, b, c, al, be, ga
    ucman = utils.manager_from_params(ucparam)
    SIM.crystal.dxtbx_crystal.set_B(ucman.B_recipspace)

    Amat = SIM.crystal.dxtbx_crystal.get_A()
    eta = [0]
    lam_coefs = [0], [1]
    if hasattr(SIM, "P"):
        names = "lambda_offset", "lambda_scale"
        if names[0] in SIM.P and names[1] in SIM.P:
            lam_coefs = []
            for name in names:
                if name in SIM.P:
                    p = SIM.P[name]
                    val = p.get_val(x[p.xpos])
                    lam_coefs.append([val])
            lam_coefs = tuple(lam_coefs)

    basename = os.path.splitext(os.path.basename(orig_exp_name))[0]
    opt_exp_path = os.path.join(
        rank_exper_outdir,
        "%s_%s_%d.expt" % (params.tag, basename, rank_exp_idx))
    pandas_path = os.path.join(
        rank_pandas_outdir,
        "%s_%s_%d.pkl" % (params.tag, basename, rank_exp_idx))
    expt.crystal = SIM.crystal.dxtbx_crystal
    # expt.detector = refiner.get_optimized_detector()
    new_exp_list = ExperimentList()
    new_exp_list.append(expt)
    new_exp_list.as_file(opt_exp_path)
    LOGGER.debug("saved opt_exp %s with wavelength %f" %
                 (opt_exp_path, expt.beam.get_wavelength()))
    _, flux_vals = zip(*SIM.beam.spectrum)

    df = single_expt_pandas(xtal_scale=scale,
                            Amat=Amat,
                            ncells_abc=(Na, Nb, Nc),
                            ncells_def=(0, 0, 0),
                            eta_abc=(eta_a, eta_b, eta_c),
                            diff_gamma=(diff_gam_a, diff_gam_b, diff_gam_c),
                            diff_sigma=(diff_sig_a, diff_sig_b, diff_sig_c),
                            detz_shift=detz_shift,
                            use_diffuse=params.use_diffuse_models,
                            gamma_miller_units=params.gamma_miller_units,
                            eta=eta,
                            rotXYZ=(rotX, rotY, rotZ),
                            ucell_p=(a, b, c, al, be, ga),
                            ucell_p_init=(a_init, b_init, c_init, al_init,
                                          be_init, ga_init),
                            lam0_lam1=lam_coefs,
                            spec_file=params.simulator.spectrum.filename,
                            spec_stride=params.simulator.spectrum.stride,
                            flux=sum(flux_vals),
                            beamsize_mm=SIM.beam.size_mm,
                            orig_exp_name=orig_exp_name,
                            opt_exp_name=opt_exp_path,
                            spec_from_imageset=params.spectrum_from_imageset,
                            oversample=params.simulator.oversample,
                            opt_det=params.opt_det,
                            stg1_refls=stg1_refls,
                            stg1_img_path=stg1_img_path,
                            ncells_init=Nabc_init,
                            spot_scales_init=scale_init)
    df.to_pickle(pandas_path)
    return df