package statalign.model.ext.plugins.structalign; import org.apache.commons.math3.geometry.euclidean.threed.Rotation; import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; import org.apache.commons.math3.linear.ArrayRealVector; import org.apache.commons.math3.linear.RealVector; import statalign.base.Utils; import statalign.model.ext.plugins.StructAlign; import statalign.model.ext.plugins.structalign.vonMises; public class RotationMove extends RotationOrTranslationMove { public RotationMove (StructAlign s, String n) { owner = s; structAlign = s; name = n; proposalWidthControlVariable = 1.0/structAlign.angleP; minProposalWidthControlVariable = 1e-5; maxProposalWidthControlVariable = 1e3; } public double proposal(Object externalState) { double logProposalRatio = super.proposal(externalState); double smallAngle = vonMises.simulate(1.0/proposalWidthControlVariable, 0); RealVector randomAxis = new ArrayRealVector(3); for(int i = 0; i < 3; i++) randomAxis.setEntry(i, Utils.generator.nextGaussian()); randomAxis.unitize(); Rotation Q = new Rotation(new Vector3D(randomAxis.toArray()), smallAngle); for(int i = 0; i < subtreeLeaves.size(); i++){ int j = subtreeLeaves.get(i); if (structAlign.coords[j] == null) continue; Rotation R = new Rotation(new Vector3D(structAlign.axes[j]), structAlign.angles[j]); R = Q.applyTo(R); structAlign.axes[j] = R.getAxis().toArray(); structAlign.angles[j] = R.getAngle(); } return logProposalRatio; // logProposalRatio is 0 because prior is uniform and proposal is symmetric } }