Exemplo n.º 1
0
    def constrain(self, constraints):

        #algorithm 1.  Use pre-defined crystal_systems to give hard-coded restraints.
        # dps_core.constrainment.s_minimizer uses LBFGS minimizer to adapt
        # all 9 components of the orientation matrix.   This gives the best-fit
        # to the starting matrix (better than algorithm #2), but the disadvantage
        # is that it is keyed to the crystal_system descriptors.  It is therefore
        # not adapted to all small-molecule space groups (monoclinics),
        # and will not take into account non-standard settings.

        if constraints in [
                "triclinic", "monoclinic", 'orthorhombic', 'tetragonal',
                "cubic", "rhombohedral", 'hexagonal'
        ]:

            from rstbx.dps_core.constrainment import s_minimizer
            S = s_minimizer(self, constraint=constraints)
            return S.newOrientation()

        #algorithm 2:  Tensor_rank_2 symmetrization
        # Advantages:  constraints are calculated directly from the space
        # group, so will account for non-standard settings.
        # Disadvantages:  drift away from starting orientation is greater than
        # for algorithm #1.

        from cctbx.sgtbx import space_group
        if isinstance(constraints, space_group):

            from rstbx.symmetry.constraints import AGconvert
            converter = AGconvert()
            converter.forward(self)
            average_cell = constraints.average_unit_cell(self.unit_cell())
            converter.validate_and_setG(
                average_cell.reciprocal().metrical_matrix())
            return Orientation(converter.back(), basis_type.reciprocal)
Exemplo n.º 2
0
  def symmetrize(self):
      converter = AGconvert()
      converter.forward(self.orientation) # allows subsequent back-conversion of symmetrized

      # takes member-data orientation; returns symmetrized metrical matrix
      uc = self.orientation.unit_cell()
      avg = self.space_group.average_unit_cell(uc) # assumes direct-space cell
      sym_mm = avg.reciprocal().metrical_matrix()

      converter.validate_and_setG(sym_mm)
      self.orientation = converter.back_as_orientation()
Exemplo n.º 3
0
  def symmetrize(self):
      converter = AGconvert()
      converter.forward(self.orientation) # allows subsequent back-conversion of symmetrized

      # takes member-data orientation; returns symmetrized metrical matrix
      uc = self.orientation.unit_cell()
      avg = self.space_group.average_unit_cell(uc) # assumes direct-space cell
      sym_mm = avg.reciprocal().metrical_matrix()

      converter.validate_and_setG(sym_mm)
      self.orientation = converter.back_as_orientation()
Exemplo n.º 4
0
class symmetrize_reduce_enlarge(object):
                        # symmetrize the metrical matrix &
                        # reduce the number of parameters to reflect symmetry
                        # also, provide back transform to increase
                        # number of parameters back to six

  def __init__(self, space_group):

    self.space_group = space_group
    self.constraints = sgtbx.tensor_rank_2_constraints(
      space_group=self.space_group,reciprocal_space=True)

  def set_orientation(self, orientation, length_unit=1.E-10):
    #provide orientation as either an A matrix (Rossmann) or B matrix (Busing & Levy)
    # data type can be either scitbx.matrix.sqr or scitbx::mat3
    # in either the reciprocal or direct space setting
    # or as a cctbx.crystal_orientation.crystal_orientation
    # if space group is not triclinic the orientation matrix should be close to
    #  symmetrized, but exact symmetrization is done by averaging within the constructor.

    # length unit defaults to 1.E-10 meters = 1 Angstrom

    if "direct_matrix" in dir(orientation):
      self.orientation = orientation # data is already a cctbx orientation
    else:
      from cctbx.crystal_orientation import crystal_orientation
      which_setting = [crystal_orientation(orientation,True),
                       crystal_orientation(orientation,False)]
      #kludgy test for space setting: unit cell volume is never < 100 Angstroms^3
      conversion_to_A3 = (length_unit*length_unit*length_unit)/1.E-30
      select = [a.unit_cell().volume()*conversion_to_A3 > 100.
                for a in which_setting]
      self.orientation = which_setting[select.index(True)]


  def symmetrize(self):
      converter = AGconvert()
      converter.forward(self.orientation) # allows subsequent back-conversion of symmetrized

      # takes member-data orientation; returns symmetrized metrical matrix
      uc = self.orientation.unit_cell()
      avg = self.space_group.average_unit_cell(uc) # assumes direct-space cell
      sym_mm = avg.reciprocal().metrical_matrix()

      converter.validate_and_setG(sym_mm)
      self.orientation = converter.back_as_orientation()

  # it is assumed that metrical_matrix and independent are in reciprocal setting
  def reduce(self,metrical_matrix):
    # takes 6-parameter metrical matrix, returns reduced number of independent parameters
    return self.constraints.independent_params(all_params=metrical_matrix)

  def enlarge(self,independent):
    # takes reduced number independent parameters, returns 6-parameter metrical matrix
    u_star = self.constraints.all_params(independent_params=tuple(independent))
    assert len(u_star) == 6
    return u_star

  def forward_independent_parameters(self):
    # returns the independent parameters given the set_orientation() B matrix
    self.Bconverter=AGconvert()
    self.Bconverter.forward(self.orientation)
    return self.reduce(metrical_matrix = self.Bconverter.G)

  def forward_gradients(self):
    #Specifically for refinement of the B-matrix parameters.
    from rstbx.symmetry.constraints.g_gradients import g_gradients
    gradient_engine = g_gradients(agadaptor = self.Bconverter, symred = self)
    return gradient_engine.dB_dp()

  def backward_orientation(self,independent):
    # given new values of the independent parameters, back-calculate and
    # set the new orientation matrix
    new_mm = self.enlarge(independent)
    self.Bconverter.validate_and_setG(new_mm)
    self.orientation = self.Bconverter.back_as_orientation()
    return self.orientation
Exemplo n.º 5
0
  def parameter_based_model_one_frame_detail(self,frame_id,iframe,all_model):
      PIXEL_SZ = 0.11 # mm/pixel
      SIGN = -1.
      if iframe < self.n_refined_frames:
        detector_origin = col((-self.FRAMES["beam_x"][iframe]
                             + SIGN * PIXEL_SZ * self.frame_translations.x[2*iframe],
                             -self.FRAMES["beam_y"][iframe]
                             + SIGN * PIXEL_SZ * self.frame_translations.x[1+2*iframe],
                             0.))
        self.OUTPUT["beam_x"][iframe] = -detector_origin[0]
        self.OUTPUT["beam_y"][iframe] = -detector_origin[1]
      else:
        detector_origin = col((-self.FRAMES["beam_x"][iframe],-self.FRAMES["beam_y"][iframe],0.))

      if not self.bandpass_models.has_key(frame_id):

        reserve_orientation = self.FRAMES["orientation"][iframe]
        effective_orientation = reserve_orientation

        #Not necessary to apply the 3 offset rotations; they have apparently
        #  been applied already.\
        #  .rotate_thru((1,0,0),self.FRAMES["rotation100_rad"][iframe]
        # ).rotate_thru((0,1,0),self.FRAMES["rotation010_rad"][iframe]
        # ).rotate_thru((0,0,1),self.FRAMES["rotation001_rad"][iframe])

        crystal = symmetry(unit_cell=effective_orientation.unit_cell(),space_group = "P1")
        indices = all_model.frame_indices(frame_id)

        parameters = parameters_bp3(
           indices=indices, orientation=effective_orientation,
           incident_beam=col(correction_vectors.INCIDENT_BEAM),
           packed_tophat=col((1.,1.,0.)),
           detector_normal=col(correction_vectors.DETECTOR_NORMAL),
           detector_fast=col((0.,1.,0.)),detector_slow=col((1.,0.,0.)),
           pixel_size=col((PIXEL_SZ,PIXEL_SZ,0)),
           pixel_offset=col((0.,0.,0.0)),
           distance=self.FRAMES["distance"][iframe],
           detector_origin=detector_origin
        )

        #print "PARAMETER check   ", effective_orientation
        #print "PARAMETER distance", self.FRAMES['distance'][iframe]
        #print "PARAMETER origin  ", detector_origin

        ucbp3 = bandpass_gaussian(parameters=parameters)
        ucbp3.set_active_areas( self.tiles ) #self.params.effective_tile_boundaries
        integration_signal_penetration=0.0 # easier to calculate distance derivatives

        ucbp3.set_sensor_model( thickness_mm = 0.5, mu_rho = 8.36644, # CS_PAD detector at 1.3 Angstrom
          signal_penetration = integration_signal_penetration)
        #ucbp3.set_subpixel( flex.double(tp038_trans_values) ) #back off this; let minimizer figure it out.

        half_mosaicity_rad = self.FRAMES["half_mosaicity_deg"][iframe] * pi/180.
        ucbp3.set_mosaicity(half_mosaicity_rad)
        ucbp3.set_bandpass(self.FRAMES["wave_HE_ang"][iframe],self.FRAMES["wave_LE_ang"][iframe])
        ucbp3.set_orientation(effective_orientation)
        ucbp3.set_domain_size(self.FRAMES["domain_size_ang"][iframe])
        ucbp3.set_vector_output_pointers(self.vector_data,
                                         frame_id,iframe<self.n_refined_frames)

        if not self.bandpass_models.has_key("best_index"):
          from labelit.dptbx import lepage
          M = lepage.character(effective_orientation)
          s = len(M.best())
          for index in M.best():
            index['counter'] = s
            s-=1
            if index["max_angular_difference"]==0.0:
              best_index = index
              break

          self.bandpass_models["best_index"] = best_index
          self.bandpass_models["constraints"] = tensor_rank_2_constraints(space_group=best_index['reduced_group'],reciprocal_space=True)
          self.bandpass_models["n_independent"] = self.bandpass_models["constraints"].n_independent_params()

        self.bandpass_models[frame_id]=ucbp3

      if iframe < self.n_refined_frames:
        self.bandpass_models[frame_id].set_detector_origin(detector_origin)
        self.bandpass_models[frame_id].set_distance(
          self.FRAMES["distance"][iframe] + self.frame_distances.x[iframe])
        self.OUTPUT["distance"][iframe] = self.FRAMES["distance"][iframe] + self.frame_distances.x[iframe]
        #half_mosaicity_rad = self.FRAMES["half_mosaicity_deg"][iframe] * pi/180. + \
        #                     self.half_mosaicity_rad.x[iframe]
        #self.bandpass_models[frame_id].set_mosaicity(half_mosaicity_rad)
        reserve_orientation = self.FRAMES["orientation"][iframe]
        effective_orientation =   reserve_orientation.rotate_thru((0,0,1),self.frame_rotz.x[iframe])
        effective_orientation = effective_orientation.rotate_thru((0,1,0),self.frame_roty.x[iframe])
        effective_orientation = effective_orientation.rotate_thru((1,0,0),self.frame_rotx.x[iframe])

        convert = AGconvert()
        convert.forward(effective_orientation)
        u_independent = list(self.bandpass_models["constraints"].independent_params(all_params=convert.G))
        for x in xrange(self.bandpass_models["n_independent"]):
          u_independent[x] *= self.g_factor.x[x+6*iframe]
        u_star = self.bandpass_models["constraints"].all_params(independent_params=tuple(u_independent))
        convert.validate_and_setG(u_star)
        effective_orientation = convert.back_as_orientation()
        self.OUTPUT["orientation"][iframe]=effective_orientation
        self.bandpass_models[frame_id].set_orientation(effective_orientation)
        mean_wave = (self.FRAMES["wave_HE_ang"][iframe] + self.FRAMES["wave_LE_ang"][iframe])/2.
        #mean_wave *= self.mean_energy_factor.x[iframe]
        bandpassHW =(self.FRAMES["wave_LE_ang"][iframe] - self.FRAMES["wave_HE_ang"][iframe])/2.
        self.bandpass_models[frame_id].set_bandpass(mean_wave - bandpassHW, mean_wave + bandpassHW)

      return detector_origin
Exemplo n.º 6
0
class symmetrize_reduce_enlarge(object):
                        # symmetrize the metrical matrix &
                        # reduce the number of parameters to reflect symmetry
                        # also, provide back transform to increase
                        # number of parameters back to six

  def __init__(self, space_group):

    self.space_group = space_group
    self.constraints = sgtbx.tensor_rank_2_constraints(
      space_group=self.space_group,reciprocal_space=True)

  def set_orientation(self, orientation, length_unit=1.E-10):
    #provide orientation as either an A matrix (Rossmann) or B matrix (Busing & Levy)
    # data type can be either scitbx.matrix.sqr or scitbx::mat3
    # in either the reciprocal or direct space setting
    # or as a cctbx.crystal_orientation.crystal_orientation
    # if space group is not triclinic the orientation matrix should be close to
    #  symmetrized, but exact symmetrization is done by averaging within the constructor.

    # length unit defaults to 1.E-10 meters = 1 Angstrom

    if "direct_matrix" in dir(orientation):
      self.orientation = orientation # data is already a cctbx orientation
    else:
      from cctbx.crystal_orientation import crystal_orientation
      which_setting = [crystal_orientation(orientation,True),
                       crystal_orientation(orientation,False)]
      #kludgy test for space setting: unit cell volume is never < 70 Angstroms^3
      conversion_to_A3 = (length_unit*length_unit*length_unit)/1.E-30
      select = [a.unit_cell().volume()*conversion_to_A3 > 70.
                for a in which_setting]
      self.orientation = which_setting[select.index(True)]


  def symmetrize(self):
      converter = AGconvert()
      converter.forward(self.orientation) # allows subsequent back-conversion of symmetrized

      # takes member-data orientation; returns symmetrized metrical matrix
      uc = self.orientation.unit_cell()
      avg = self.space_group.average_unit_cell(uc) # assumes direct-space cell
      sym_mm = avg.reciprocal().metrical_matrix()

      converter.validate_and_setG(sym_mm)
      self.orientation = converter.back_as_orientation()

  # it is assumed that metrical_matrix and independent are in reciprocal setting
  def reduce(self,metrical_matrix):
    # takes 6-parameter metrical matrix, returns reduced number of independent parameters
    return self.constraints.independent_params(all_params=metrical_matrix)

  def enlarge(self,independent):
    # takes reduced number independent parameters, returns 6-parameter metrical matrix
    u_star = self.constraints.all_params(independent_params=tuple(independent))
    assert len(u_star) == 6
    return u_star

  def forward_independent_parameters(self):
    # returns the independent parameters given the set_orientation() B matrix
    self.Bconverter=AGconvert()
    self.Bconverter.forward(self.orientation)
    return self.reduce(metrical_matrix = self.Bconverter.G)

  def forward_gradients(self):
    #Specifically for refinement of the B-matrix parameters.
    from rstbx.symmetry.constraints.g_gradients import g_gradients
    gradient_engine = g_gradients(agadaptor = self.Bconverter, symred = self)
    return gradient_engine.dB_dp()

  def backward_orientation(self,independent):
    # given new values of the independent parameters, back-calculate and
    # set the new orientation matrix
    new_mm = self.enlarge(independent)
    self.Bconverter.validate_and_setG(new_mm)
    self.orientation = self.Bconverter.back_as_orientation()
    return self.orientation
Exemplo n.º 7
0
def finite_difference_test(orient):
    from rstbx.symmetry.constraints import AGconvert as AG
    from labelit.symmetry.metricsym.a_g_conversion import pp
    from libtbx.tst_utils import approx_equal
    adaptor = AG()
    adaptor.forward(orient)
    grad = g_gradients(adaptor, symred=None)
    epsilon = 1.E-10

    dAij_dphi = grad.get_all_da()[0]
    AGback = AG()
    F = []
    for x in [-1., 1.]:
        AGback.setAngles(adaptor.phi + x * epsilon, adaptor.psi, adaptor.theta)
        AGback.G = adaptor.G
        F.append(flex.double(AGback.back()))
    diff_mat = (F[1] - F[0]) / (2. * epsilon)
    rule = "dAij_dphi: Analytical gradient vs. finite difference gradient\n"+\
           pp(list(dAij_dphi))+"\n"+\
           pp(diff_mat)
    if not (approx_equal(dAij_dphi, diff_mat, 1.E-7)): raise Exception(rule)

    dAij_dpsi = grad.get_all_da()[1]
    AGback = AG()
    F = []
    for x in [-1., 1.]:
        AGback.setAngles(adaptor.phi, adaptor.psi + x * epsilon, adaptor.theta)
        AGback.G = adaptor.G
        F.append(flex.double(AGback.back()))
    diff_mat = (F[1] - F[0]) / (2. * epsilon)
    rule = "dAij_dpsi: Analytical gradient vs. finite difference gradient\n"+\
           pp(list(dAij_dpsi))+"\n"+\
           pp(diff_mat)
    if not (approx_equal(dAij_dpsi, diff_mat, 1.E-7)): raise Exception(rule)

    dAij_dtheta = grad.get_all_da()[2]
    AGback = AG()
    F = []
    for x in [-1., 1.]:
        AGback.setAngles(adaptor.phi, adaptor.psi, adaptor.theta + x * epsilon)
        AGback.G = adaptor.G
        F.append(flex.double(AGback.back()))
    diff_mat = (F[1] - F[0]) / (2. * epsilon)
    rule = "dAij_dtheta: Analytical gradient vs. finite difference gradient\n"+\
           pp(list(dAij_dtheta))+"\n"+\
           pp(diff_mat)
    if not (approx_equal(dAij_dtheta, diff_mat, 1.E-7)): raise Exception(rule)

    g0, g1, g2, g3, g4, g5 = adaptor.G

    dAij_dg0 = grad.get_all_da()[3]
    AGback = AG()
    F = []
    for x in [-1., 1.]:
        AGback.setAngles(adaptor.phi, adaptor.psi, adaptor.theta)
        AGback.G = (g0 + x * epsilon, g1, g2, g3, g4, g5)
        F.append(flex.double(AGback.back()))
    diff_mat = (F[1] - F[0]) / (2. * epsilon)
    rule = "dAij_dg0: Analytical gradient vs. finite difference gradient\n"+\
           pp(list(dAij_dg0))+"\n"+\
           pp(diff_mat)
    if not (approx_equal(dAij_dg0, diff_mat, 1.E-7)): raise Exception(rule)

    dAij_dg1 = grad.get_all_da()[4]
    AGback = AG()
    F = []
    for x in [-1., 1.]:
        AGback.setAngles(adaptor.phi, adaptor.psi, adaptor.theta)
        AGback.G = (g0, g1 + x * epsilon, g2, g3, g4, g5)
        F.append(flex.double(AGback.back()))
    diff_mat = (F[1] - F[0]) / (2. * epsilon)
    rule = "dAij_dg1: Analytical gradient vs. finite difference gradient\n"+\
           pp(list(dAij_dg1))+"\n"+\
           pp(diff_mat)
    if not (approx_equal(dAij_dg1, diff_mat, 1.E-7)): raise Exception(rule)

    dAij_dg2 = grad.get_all_da()[5]
    AGback = AG()
    F = []
    for x in [-1., 1.]:
        AGback.setAngles(adaptor.phi, adaptor.psi, adaptor.theta)
        AGback.G = (g0, g1, g2 + x * epsilon, g3, g4, g5)
        F.append(flex.double(AGback.back()))
    diff_mat = (F[1] - F[0]) / (2. * epsilon)
    rule = "dAij_dg2: Analytical gradient vs. finite difference gradient\n"+\
           pp(list(dAij_dg2))+"\n"+\
           pp(diff_mat)
    if not (approx_equal(dAij_dg2, diff_mat, 1.E-6)): raise Exception(rule)

    dAij_dg3 = grad.get_all_da()[6]
    AGback = AG()
    F = []
    for x in [-1., 1.]:
        AGback.setAngles(adaptor.phi, adaptor.psi, adaptor.theta)
        AGback.G = (g0, g1, g2, g3 + x * epsilon, g4, g5)
        F.append(flex.double(AGback.back()))
    diff_mat = (F[1] - F[0]) / (2. * epsilon)
    rule = "dAij_dg3: Analytical gradient vs. finite difference gradient\n"+\
           pp(list(dAij_dg3))+"\n"+\
           pp(diff_mat)
    if not (approx_equal(dAij_dg3, diff_mat, 1.E-7)): raise Exception(rule)

    dAij_dg4 = grad.get_all_da()[7]
    AGback = AG()
    F = []
    for x in [-1., 1.]:
        AGback.setAngles(adaptor.phi, adaptor.psi, adaptor.theta)
        AGback.G = (g0, g1, g2, g3, g4 + x * epsilon, g5)
        F.append(flex.double(AGback.back()))
    diff_mat = (F[1] - F[0]) / (2. * epsilon)
    rule = "dAij_dg4: Analytical gradient vs. finite difference gradient\n"+\
           pp(list(dAij_dg4))+"\n"+\
           pp(diff_mat)
    if not (approx_equal(dAij_dg4, diff_mat, 1.E-7)): raise Exception(rule)

    dAij_dg5 = grad.get_all_da()[8]
    AGback = AG()
    F = []
    for x in [-1., 1.]:
        AGback.setAngles(adaptor.phi, adaptor.psi, adaptor.theta)
        AGback.G = (g0, g1, g2, g3, g4, g5 + x * epsilon)
        F.append(flex.double(AGback.back()))
    diff_mat = (F[1] - F[0]) / (2. * epsilon)
    rule = "dAij_dg5: Analytical gradient vs. finite difference gradient\n"+\
           pp(list(dAij_dg5))+"\n"+\
           pp(diff_mat)
    if not (approx_equal(dAij_dg5, diff_mat, 1.E-6)): raise Exception(rule)