Exemple #1
1
//RotatorTranslatorToSuper superimposes the set of cartesian coordinates given as the rows of the matrix test on the gnOnes of the rows
//of the matrix templa. Returns the transformed matrix, the rotation matrix, 2 translation row vectors
//For the superposition plus an error. In order to perform the superposition, without using the transformed
//the first translation vector has to be added first to the moving matrix, then the rotation must be performed
//and finally the second translation has to be added.
//This is a low level function, although one can use it directly since it returns the transformed matrix.
//The math for this function is by Prof. Veronica Jimenez-Curihual, University of Concepcion, Chile.
func RotatorTranslatorToSuper(test, templa *v3.Matrix) (*v3.Matrix, *v3.Matrix, *v3.Matrix, *v3.Matrix, error) {
	tmr, tmc := templa.Dims()
	tsr, tsc := test.Dims()
	if tmr != tsr || tmc != 3 || tsc != 3 {
		return nil, nil, nil, nil, CError{"goChem: Ill-formed matrices", []string{"RotatorTranslatorToSuper"}}
	}
	var Scal float64
	Scal = float64(1.0) / float64(tmr)
	j := gnOnes(tmr, 1) //Mass is not important for this matter so we'll just use this.
	ctest, distest, err := MassCenter(test, test, j)
	if err != nil {
		return nil, nil, nil, nil, errDecorate(err, "RotatorTranslatorToSuper")
	}
	ctempla, distempla, err := MassCenter(templa, templa, j)
	if err != nil {
		return nil, nil, nil, nil, errDecorate(err, "RotatorTranslatorToSuper")

	}
	Mid := gnEye(tmr)
	jT := gnT(j)
	ScaledjProd := gnMul(j, jT)
	ScaledjProd.Scale(Scal, ScaledjProd)
	aux2 := gnMul(gnT(ctempla), Mid)
	r, _ := aux2.Dims()
	Maux := v3.Zeros(r)
	Maux.Mul(aux2, ctest)
	Maux.Tr() //Dont understand why this is needed
	factors := mat64.SVD(v3.Matrix2Dense(Maux), appzero, math.SmallestNonzeroFloat64, true, true)
	U := factors.U
	V := factors.V
	//	if err != nil {
	//		return nil, nil, nil, nil, err  //I'm not sure what err is this one
	//	}
	U.Scale(-1, U)
	V.Scale(-1, V)
	//SVD gives different results here than in numpy. U and V are multiplide by -1 in one of them
	//and gomatrix gives as V the transpose of the matrix given as V by numpy. I guess is not an
	//error, but don't know for sure.
	vtr, _ := V.Dims()
	Rotation := v3.Zeros(vtr)
	Rotation.Mul(V, gnT(U))
	Rotation.Tr() //Don't know why does this work :(
	RightHand := gnEye(3)
	if det(Rotation) < 0 {
		RightHand.Set(2, 2, -1)
		Rotation.Mul(V, RightHand)
		Rotation.Mul(Rotation, gnT(U)) //If I get this to work Ill arrange so gnT(U) is calculated once, not twice as now.
		Rotation.Tr()                  //TransposeTMP contains the transpose of the original Rotation      //Same, no ide why I need this
		//return nil, nil, nil, nil, fmt.Errorf("Got a reflection instead of a translations. The objects may be specular images of each others")
	}
	jT.Scale(Scal, jT)
	subtempla := v3.Zeros(tmr)
	subtempla.Copy(ctempla)
	sub := v3.Zeros(ctest.NVecs())
	sub.Mul(ctest, Rotation)
	subtempla.Sub(subtempla, sub)
	jtr, _ := jT.Dims()
	Translation := v3.Zeros(jtr)
	Translation.Mul(jT, subtempla)
	Translation.Add(Translation, distempla)
	//This alings the transformed with the original template, not the mean centrate one
	transformed := v3.Zeros(ctest.NVecs())
	transformed.Mul(ctest, Rotation)
	transformed.AddVec(transformed, Translation)
	//end transformed
	distest.Scale(-1, distest)
	return transformed, Rotation, distest, Translation, nil
}
Exemple #2
0
//MassCenter centers in in the center of mass of oref. Mass must be
//A column vector. Returns the centered matrix and the displacement matrix.
func MassCenter(in, oref *v3.Matrix, mass *mat64.Dense) (*v3.Matrix, *v3.Matrix, error) {
	or, _ := oref.Dims()
	ir, _ := in.Dims()
	if mass == nil { //just obtain the geometric center
		tmp := ones(or)
		mass = mat64.NewDense(or, 1, tmp) //gnOnes(or, 1)
	}
	ref := v3.Zeros(or)
	ref.Copy(oref)
	gnOnesvector := gnOnes(1, or)
	f := func() { ref.ScaleByCol(ref, mass) }
	if err := gnMaybe(gnPanicker(f)); err != nil {
		return nil, nil, CError{err.Error(), []string{"v3.Matrix.ScaleByCol", "MassCenter"}}
	}
	ref2 := v3.Zeros(1)
	g := func() { ref2.Mul(gnOnesvector, ref) }
	if err := gnMaybe(gnPanicker(g)); err != nil {
		return nil, nil, CError{err.Error(), []string{"v3.gOnesVector", "MassCenter"}}
	}
	ref2.Scale(1.0/mass.Sum(), ref2)
	returned := v3.Zeros(ir)
	returned.Copy(in)
	returned.SubVec(returned, ref2)
	/*	for i := 0; i < ir; i++ {
			if err := returned.GetRowVector(i).Subtract(ref2); err != nil {
				return nil, nil, err
			}
		}
	*/
	return returned, ref2, nil
}
Exemple #3
0
//EulerRotateAbout uses Euler angles to rotate the coordinates in coordsorig around by angle
//radians around the axis given by the vector axis. It returns the rotated coordsorig,
//since the original is not affected. It seems more clunky than the RotateAbout, which uses Clifford algebra.
//I leave it for benchmark, mostly, and might remove it later. There is no test for this function!
func EulerRotateAbout(coordsorig, ax1, ax2 *v3.Matrix, angle float64) (*v3.Matrix, error) {
	r, _ := coordsorig.Dims()
	coords := v3.Zeros(r)
	translation := v3.Zeros(ax1.NVecs())
	translation.Copy(ax1)
	axis := v3.Zeros(ax2.NVecs())
	axis.Sub(ax2, ax1) //now it became the rotation axis
	f := func() { coords.SubVec(coordsorig, translation) }
	if err := gnMaybe(gnPanicker(f)); err != nil {
		return nil, CError{err.Error(), []string{"v3.Matrix.Subvec", "EulerRotateAbout"}}

	}
	Zswitch := RotatorToNewZ(axis)
	coords.Mul(coords, Zswitch) //rotated
	Zrot, err := RotatorAroundZ(angle)
	if err != nil {
		return nil, errDecorate(err, "EulerRotateAbout")
	}
	//	Zsr, _ := Zswitch.Dims()
	//	RevZ := v3.Zeros(Zsr)
	RevZ, err := gnInverse(Zswitch)
	if err != nil {
		return nil, errDecorate(err, "EulerRotateAbout")
	}
	coords.Mul(coords, Zrot) //rotated
	coords.Mul(coords, RevZ)
	coords.AddVec(coords, translation)
	return coords, nil
}
Exemple #4
0
func TestWater(Te *testing.T) {
	//	runtime.GOMAXPROCS(2) ///////////////////////////
	mol, err := XYZFileRead("test/sample.xyz")
	if err != nil {
		Te.Error(err)
	}
	for i := 0; i < 6; i++ {
		s := new(Atom)
		if i == 0 || i == 3 {
			s.Symbol = "O"
		} else {
			s.Symbol = "H"
		}
		mol.AppendAtom(s)
	}
	mol.SetCharge(1)
	mol.SetMulti(1)
	c2 := v3.Zeros(mol.Len())
	v := v3.Zeros(6)
	l, _ := mol.Coords[0].Dims()
	fmt.Println(l, mol.Len())
	c2.Stack(mol.Coords[0], v)
	mol.Coords[0] = c2
	c := mol.Coords[0].VecView(43)
	h1 := mol.Coords[0].VecView(42)
	coords := v3.Zeros(mol.Len())
	coords.Copy(mol.Coords[0])
	w1 := MakeWater(c, h1, 2, Deg2Rad*30, true)
	w2 := MakeWater(c, h1, 2, Deg2Rad*-30, false)
	tmp := v3.Zeros(6)
	tmp.Stack(w1, w2)
	fmt.Println("tmp water", w1, w2, tmp, c, h1)
	coords.SetMatrix(mol.Len()-6, 0, tmp)
	XYZFileWrite("test/WithWater.xyz", coords, mol)
}
Exemple #5
0
//Super determines the best rotation and translations to superimpose the coords in test
//listed in testlst on te atoms of molecule templa, frame frametempla, listed in templalst.
//It applies those rotation and translations to the whole frame frametest of molecule test, in palce.
//testlst and templalst must have the same number of elements. If any of the two slices, or both, are
//nil or have a zero lenght, they will be replaced by a list containing the number of all atoms in the
//corresponding molecule.
func Super(test, templa *v3.Matrix, testlst, templalst []int) (*v3.Matrix, error) {
	//_, testcols := test.Dims()
	//_, templacols := templa.Dims()
	structs := []*v3.Matrix{test, templa}
	lists := [][]int{testlst, templalst}
	//In case one or both lists are nil or have lenght zero.
	for k, v := range lists {
		if v == nil || len(v) == 0 {
			lists[k] = make([]int, structs[k].NVecs(), structs[k].NVecs())
			for k2, _ := range lists[k] {
				lists[k][k2] = k2
			}
		}
	}
	//fmt.Println(lists[0])
	if len(lists[0]) != len(lists[1]) {
		return nil, CError{fmt.Sprintf("Mismatched template and test atom numbers: %d, %d", len(lists[1]), len(lists[0])), []string{"Super"}}
	}
	ctest := v3.Zeros(len(lists[0]))
	ctest.SomeVecs(test, lists[0])
	ctempla := v3.Zeros(len(lists[1]))
	ctempla.SomeVecs(templa, lists[1])
	_, rotation, trans1, trans2, err1 := RotatorTranslatorToSuper(ctest, ctempla)
	if err1 != nil {
		return nil, errDecorate(err1, "Super")
	}
	test.AddVec(test, trans1)
	//	fmt.Println("test1",test, rotation) /////////////77
	test.Mul(test, rotation)
	//	fmt.Println("test2",test) ///////////
	test.AddVec(test, trans2)
	//	fmt.Println("test3",test) ///////
	return test, nil
}
Exemple #6
0
//Dihedral calculates the dihedral between the points a, b, c, d, where the first plane
//is defined by abc and the second by bcd.
func Dihedral(a, b, c, d *v3.Matrix) float64 {
	all := []*v3.Matrix{a, b, c, d}
	for number, point := range all {
		pr, pc := point.Dims()
		if point == nil {
			panic(PanicMsg(fmt.Sprintf("goChem-Dihedral: Vector %d is nil", number)))
		}
		if pr != 1 || pc != 3 {
			panic(PanicMsg(fmt.Sprintf("goChem-Dihedral: Vector %d has invalid shape", number)))
		}
	}
	//bma=b minus a
	bma := v3.Zeros(1)
	cmb := v3.Zeros(1)
	dmc := v3.Zeros(1)
	bmascaled := v3.Zeros(1)
	bma.Sub(b, a)
	cmb.Sub(c, b)
	dmc.Sub(d, c)
	bmascaled.Scale(cmb.Norm(0), bma)
	first := bmascaled.Dot(cross(cmb, dmc))
	v1 := cross(bma, cmb)
	v2 := cross(cmb, dmc)
	second := v1.Dot(v2)
	dihedral := math.Atan2(first, second)
	return dihedral
}
Exemple #7
0
//This program will align the best plane passing through a set of atoms in a molecule with the XY-plane.
//Usage:
func main() {
	if len(os.Args) < 2 {
		fmt.Printf("Usage:\n%s file.xyz [indexes.dat]\nindexes.dat is a file containing one single line, with all the atoms defining the plane separated by spaces. If it is not given, all the atoms of the molecule will be taken to define the plane.\n", os.Args[0])
		os.Exit(1)
	}
	mol, err := chem.XYZFileRead(os.Args[1])
	if err != nil {
		panic(err.Error())
	}
	var indexes []int
	//if no file with indexes given, will just use all the atoms.
	if len(os.Args) < 3 {
		indexes = make([]int, mol.Len())
		for k, _ := range indexes {
			indexes[k] = k
		}
	} else {
		indexes, err = scu.IndexFileParse(os.Args[2])
		if err != nil {
			panic(err.Error())
		}
	}
	some := v3.Zeros(len(indexes)) //will contain the atoms selected to define the plane.
	some.SomeVecs(mol.Coords[0], indexes)
	//for most rotation things it is good to have the molecule centered on its mean.
	mol.Coords[0], _, _ = chem.MassCenter(mol.Coords[0], some, nil)
	//As we changed the atomic positions, must extract the plane-defining atoms again.
	some.SomeVecs(mol.Coords[0], indexes)
	//The strategy is: Take the normal to the plane of the molecule (os molecular subset), and rotate it until it matches the Z-axis
	//This will mean that the plane of the molecule will now match the XY-plane.
	best, err := chem.BestPlane(some, nil)
	if err != nil {
		panic(err.Error())
	}
	z, _ := v3.NewMatrix([]float64{0, 0, 1})
	zero, _ := v3.NewMatrix([]float64{0, 0, 0})
	fmt.Fprintln(os.Stderr, "Best  Plane", best, z, indexes)
	axis := v3.Zeros(1)
	axis.Cross(best, z)
	fmt.Fprintln(os.Stderr, "axis", axis)
	//The main part of the program, where the rotation actually happens. Note that we rotate the whole
	//molecule, not just the planar subset, this is only used to calculate the rotation angle.
	mol.Coords[0], err = chem.RotateAbout(mol.Coords[0], zero, axis, chem.Angle(best, z))
	if err != nil {
		panic(err.Error())
	}
	//Now we write the rotated result.
	final, err := chem.XYZStringWrite(mol.Coords[0], mol)
	fmt.Print(final)
	fmt.Fprintln(os.Stderr, err)
}
Exemple #8
0
func BackBone(stdin *bufio.Reader, options *chemjson.Options, i int) (coords, optcoords *v3.Matrix, optatoms *chem.Topology, list, frozen []int) {
	mol, coordarray, err := chemjson.DecodeMolecule(stdin, options.AtomsPerSel[i], 1)
	if err != nil {
		fmt.Fprint(os.Stderr, err.Marshal())
		log.Fatal(err)
	}
	coords = coordarray[0]

	//chem.PDBWrite("OPTpp.pdb", mol,coords,nil) /////////////////////////////////////
	resid, chain := GetResidueIds(mol)
	fmt.Fprintln(os.Stderr, "resid, chains, atomspersel, i", resid, chain, options.AtomsPerSel[i], i)
	var err2 error
	list, err2 = chem.CutBackRef(mol, []string{chain[0]}, [][]int{resid[1 : len(resid)-1]}) //in each backbone selection the chain should be the same for all residues
	if err != nil {
		panic(err2.Error()) //at least for now
	}
	optcoords = v3.Zeros(len(list))
	optcoords.SomeVecs(coords, list)
	optatoms = chem.NewTopology(nil, 0, 0) //the last 2 options are charge and multiplicity
	optatoms.SomeAtoms(mol, list)
	chem.ScaleBonds(optcoords, optatoms, "NTZ", "HNZ", chem.CHDist)
	chem.ScaleBonds(optcoords, optatoms, "CTZ", "HCZ", chem.CHDist)
	frozen = make([]int, 0, 2*len(list))
	for i := 0; i < optatoms.Len(); i++ {
		curr := optatoms.Atom(i)
		//In the future there could be an option to see whether C and N are fixed
		if curr.Name == "NTZ" || curr.Name == "CTZ" || curr.Name == "C" || curr.Name == "N" {
			frozen = append(frozen, i)
		}
	}
	return coords, optcoords, optatoms, list, frozen
}
Exemple #9
0
func SideChains(stdin *bufio.Reader, options *chemjson.Options) (coords, optcoords *v3.Matrix, optatoms *chem.Topology, list, frozen []int) {
	mol, coordarray, err := chemjson.DecodeMolecule(stdin, options.AtomsPerSel[0], 1)
	if err != nil {
		fmt.Fprint(os.Stderr, err.Marshal())
		log.Fatal(err)
	}
	coords = coordarray[0]
	resid, chains := GetResidueIds(mol)
	//	fmt.Fprintln(os.Stderr,"SIDE! resid, chains", resid, chains)
	toscale := []string{"CA", "HA2", "HA3"}
	if options.BoolOptions[0][1] {
		list = chem.CutAlphaRef(mol, chains, resid)
	} else {
		list = chem.CutBetaRef(mol, chains, resid)
		toscale = []string{"CB", "HB4", "HB4"} //Yes, I am doing this twice for no reason other to have 3 elements in this slice.
	}
	optcoords = v3.Zeros(len(list))
	optcoords.SomeVecs(coords, list)
	optatoms = chem.NewTopology(nil, 0, 0) //the last 2 options are charge and multiplicity
	optatoms.SomeAtoms(mol, list)
	chem.ScaleBonds(optcoords, optatoms, toscale[0], toscale[1], chem.CHDist)
	chem.ScaleBonds(optcoords, optatoms, toscale[0], toscale[2], chem.CHDist)
	frozen = make([]int, 0, 2*len(list))
	for i := 0; i < optatoms.Len(); i++ {
		curr := optatoms.Atom(i)
		if curr.Name == "HA" || curr.Name == "CA" || curr.Name == "CB" {
			frozen = append(frozen, i)
		}
	}
	return coords, optcoords, optatoms, list, frozen
}
Exemple #10
0
func TestFrameDCDConc(Te *testing.T) {
	traj, err := New("../test/test.dcd")
	if err != nil {
		Te.Error(err)
	}
	frames := make([]*v3.Matrix, 3, 3)
	for i, _ := range frames {
		frames[i] = v3.Zeros(traj.Len())
	}
	results := make([][]chan *v3.Matrix, 0, 0)
	for i := 0; ; i++ {
		results = append(results, make([]chan *v3.Matrix, 0, len(frames)))
		coordchans, err := traj.NextConc(frames)
		if err != nil {
			if _, ok := err.(chem.LastFrameError); ok && coordchans == nil {
				break
			}
			Te.Error(err)
			break
		}
		for key, channel := range coordchans {
			results[len(results)-1] = append(results[len(results)-1], make(chan *v3.Matrix))
			go SecondRow(channel, results[len(results)-1][key], len(results)-1, key)
		}
		res := len(results) - 1
		for frame, k := range results[res] {
			if k == nil {
				fmt.Println(frame)
				continue
			}
			fmt.Println(res, frame, <-k)
		}
	}
}
Exemple #11
0
//ScaleBond takes a C-H bond and moves the H (in place) so the distance between them is the one given (bond).
//CAUTION: I have only tested it for the case where the original distance>bond, although I expect it to also work in the other case.
func ScaleBond(C, H *v3.Matrix, bond float64) {
	Odist := v3.Zeros(1)
	Odist.Sub(H, C)
	distance := Odist.Norm(0)
	Odist.Scale((distance-bond)/distance, Odist)
	H.Sub(H, Odist)
}
Exemple #12
0
//Projection returns the projection of test in ref.
func Projection(test, ref *v3.Matrix) *v3.Matrix {
	rr, _ := ref.Dims()
	Uref := v3.Zeros(rr)
	Uref.Unit(ref)
	scalar := test.Dot(Uref) //math.Abs(la)*math.Cos(angle)
	Uref.Scale(scalar, Uref)
	return Uref
}
Exemple #13
0
//CenterOfMass returns the center of mass the atoms represented by the coordinates in geometry
//and the masses in mass, and an error. If mass is nil, it calculates the geometric center
func CenterOfMass(geometry *v3.Matrix, mass *mat64.Dense) (*v3.Matrix, error) {
	if geometry == nil {
		return nil, CError{"goChem: nil matrix to get the center of mass", []string{"CenterOfMass"}}
	}
	gr, _ := geometry.Dims()
	if mass == nil { //just obtain the geometric center
		tmp := ones(gr)
		mass = mat64.NewDense(gr, 1, tmp) //gnOnes(gr, 1)
	}
	tmp2 := ones(gr)
	gnOnesvector := mat64.NewDense(1, gr, tmp2) //gnOnes(1, gr)

	ref := v3.Zeros(gr)
	ref.ScaleByCol(geometry, mass)
	ref2 := v3.Zeros(1)
	ref2.Mul(gnOnesvector, ref)
	ref2.Scale(1.0/mass.Sum(), ref2)
	return ref2, nil
}
Exemple #14
0
//AntiProjection returns a vector in the direction of ref with the magnitude of
//a vector A would have if |test| was the magnitude of its projection
//in the direction of test.
func AntiProjection(test, ref *v3.Matrix) *v3.Matrix {
	rr, _ := ref.Dims()
	testnorm := test.Norm(0)
	Uref := v3.Zeros(rr)
	Uref.Unit(ref)
	scalar := test.Dot(Uref)
	scalar = (testnorm * testnorm) / scalar
	Uref.Scale(scalar, Uref)
	return Uref
}
Exemple #15
0
func TestProjectionAndAntiProjection(Te *testing.T) {
	A := v3.Zeros(1)
	A.Set(0, 0, 2.0)
	B, _ := v3.NewMatrix([]float64{1, 1, 0})
	C := AntiProjection(A, B)
	D := Projection(B, A)
	fmt.Println("Projection of B on A (D)", D)
	fmt.Println("Anti-projection of A on B (C):", C)
	fmt.Println("Norm of C: ", C.Norm(0), " Norm of A,B: ", A.Norm(0), B.Norm(0), "Norm of D:", D.Norm(0))
}
Exemple #16
0
//TestChangeAxis reads the PDB 2c9v.pdb from the test directory, collects
//The CA and CB of residue D124 of the chain A, and uses Clifford algebra to rotate the
//whole molecule such as the vector defined by these 2 atoms is
//aligned with the Z axis. The new molecule is written
//as 2c9v_aligned.pdb to the test folder.
func TestChangeAxis(Te *testing.T) {
	//runtime.GOMAXPROCS(2) ///////////////////////////
	mol, err := PDBFileRead("test/2c9v.pdb", true)
	if err != nil {
		Te.Error(err)
	}
	PDBFileWrite("test/2c9v-Readtest.pdb", mol.Coords[0], mol, nil)
	//The selection thing
	orient_atoms := [2]int{0, 0}
	for index := 0; index < mol.Len(); index++ {
		atom := mol.Atom(index)
		if atom.Chain == "A" && atom.MolID == 124 {
			if atom.Name == "CA" {
				orient_atoms[0] = index
			} else if atom.Name == "CB" {
				orient_atoms[1] = index
			}
		}
	}
	//Get the axis of rotation
	//ov1:=mol.Coord(orient_atoms[0], 0)
	ov2 := mol.Coord(orient_atoms[1], 0)
	//now we center the thing in the beta carbon of D124
	mol.Coords[0].SubVec(mol.Coords[0], ov2)
	PDBFileWrite("test/2c9v-translated.pdb", mol.Coords[0], mol, nil)
	//Now the rotation
	ov1 := mol.Coord(orient_atoms[0], 0) //make sure we have the correct versions
	ov2 = mol.Coord(orient_atoms[1], 0)  //same
	orient := v3.Zeros(ov2.NVecs())
	orient.Sub(ov2, ov1)
	//	PDBWrite(mol,"test/2c9v-124centered.pdb")
	Z, _ := v3.NewMatrix([]float64{0, 0, 1})
	axis := cross(orient, Z)
	angle := Angle(orient, Z)
	oldcoords := v3.Zeros(mol.Coords[0].NVecs())
	oldcoords.Copy(mol.Coords[0])
	mol.Coords[0] = Rotate(oldcoords, mol.Coords[0], axis, angle)
	if err != nil {
		Te.Error(err)
	}
	PDBFileWrite("test/2c9v-aligned.pdb", mol.Coords[0], mol, nil)
	fmt.Println("bench1")
}
Exemple #17
0
//BestPlaneP takes sorted evecs, according to the eval,s and returns a row vector that is normal to the
//Plane that best contains the molecule. Notice that the function can't possibly check
//that the vectors are sorted. The P at the end of the name is for Performance. If
//That is not an issue it is safer to use the BestPlane function that wraps this one.
func BestPlaneP(evecs *v3.Matrix) (*v3.Matrix, error) {
	evr, evc := evecs.Dims()
	if evr != 3 || evc != 3 {
		return evecs, CError{"goChem: Eigenvectors matrix must be 3x3", []string{"BestPlaneP"}} //maybe this should be a panic
	}
	v1 := evecs.VecView(2)
	v2 := evecs.VecView(1)
	normal := v3.Zeros(1)
	normal.Cross(v1, v2)
	return normal, nil
}
Exemple #18
0
func TestNWChem(Te *testing.T) {
	mol, err := chem.XYZFileRead("../test/ethanol.xyz")
	fmt.Println(mol.Coords[0], len(mol.Coords), "Quiere quedar leyenda, compadre?", err)
	if err != nil {
		Te.Error(err)
	}
	if err := mol.Corrupted(); err != nil {
		Te.Error(err)
	}
	mol.SetCharge(0)
	mol.SetMulti(1)
	calc := new(Calc)
	calc.SCFTightness = 1 //quite tight
	calc.SCFConvHelp = 1
	calc.Job = Job{Opti: true}
	calc.Method = "TPSS"
	calc.Dielectric = 4
	calc.Basis = "def2-SVP"
	calc.HighBasis = "def2-TZVP"
	calc.Grid = 4
	calc.Memory = 1000
	calc.HBAtoms = []int{2}
	calc.HBElements = []string{"O"}
	calc.CConstraints = []int{1}
	calc.SetDefaults()
	nw := NewNWChemHandle()
	orca := NewOrcaHandle()
	nw.SetName("gochem")
	orca.SetName("gochemII")
	atoms := v3.Zeros(mol.Len())
	mol.Next(atoms)
	if err = os.Chdir("../test"); err != nil {
		Te.Error(err)
	}
	err = nw.BuildInput(atoms, mol, calc)
	if err != nil {
		Te.Error(err)
	}
	_ = orca.BuildInput(atoms, mol, calc)
	//The files are already in ./test.
	os.Chdir("../test")
	defer os.Chdir("../qm")
	energy, err := nw.Energy()
	if err != nil {
		Te.Error(err)
	}
	fmt.Println("NWChem Energy: ", energy)
	newg, err := nw.OptimizedGeometry(mol)
	if err != nil {
		Te.Error(err)
	}
	chem.XYZFileWrite("optiNW.xyz", newg, mol)

}
Exemple #19
0
//RotateAbout about rotates the coordinates in coordsorig around by angle radians around the axis
//given by the vector axis. It returns the rotated coordsorig, since the original is not affected.
//Uses Clifford algebra.
func RotateAbout(coordsorig, ax1, ax2 *v3.Matrix, angle float64) (*v3.Matrix, error) {
	coordsLen := coordsorig.NVecs()
	coords := v3.Zeros(coordsLen)
	translation := v3.Zeros(ax1.NVecs())
	translation.Copy(ax1)
	axis := v3.Zeros(ax2.NVecs())
	axis.Sub(ax2, ax1) // the rotation axis
	f := func() { coords.SubVec(coordsorig, translation) }
	if err := gnMaybe(gnPanicker(f)); err != nil {
		return nil, CError{err.Error(), []string{"v3.Matrix.SubVec", "RotateAbout"}}
	}
	Rot := v3.Zeros(coordsLen)
	Rot = Rotate(coords, Rot, axis, angle)
	g := func() { Rot.AddVec(Rot, translation) }
	if err := gnMaybe(gnPanicker(g)); err != nil {
		return nil, CError{err.Error(), []string{"v3.Matrix.AddVec", "RotateAbout"}}

	}
	return Rot, nil
}
Exemple #20
0
//Aligns the main plane of a molecule with the XY-plane.
//Here XYZRead and XYZWrite are tested
func TestPutInXYPlane(Te *testing.T) {
	myxyz, _ := os.Open("test/sample_plane.xyz")
	mol, err := XYZRead(myxyz)
	if err != nil {
		Te.Error(err)
	}
	indexes := []int{0, 1, 2, 3, 23, 22, 21, 20, 25, 44, 39, 40, 41, 42, 61, 60, 59, 58, 63, 5}
	some := v3.Zeros(len(indexes))
	some.SomeVecs(mol.Coords[0], indexes)
	//for most rotation things it is good to have the molecule centered on its mean.
	mol.Coords[0], _, _ = MassCenter(mol.Coords[0], some, nil)
	//The test molecule is not completely planar so we use a subset of atoms that are contained in a plane
	//These are the atoms given in the indexes slice.
	some.SomeVecs(mol.Coords[0], indexes)
	//The strategy is: Take the normal to the plane of the molecule (os molecular subset), and rotate it until it matches the Z-axis
	//This will mean that the plane of the molecule will now match the XY-plane.
	best, err := BestPlane(some, nil)
	if err != nil {
		err2 := err.(Error)
		fmt.Println(err2.Decorate(""))
		Te.Fatal(err)
		//		panic(err.Error())
	}
	z, _ := v3.NewMatrix([]float64{0, 0, 1})
	zero, _ := v3.NewMatrix([]float64{0, 0, 0})
	fmt.Println("Best  Plane", best, z)
	axis := v3.Zeros(1)
	axis.Cross(best, z)
	fmt.Println("axis", axis)
	//The main part of the program, where the rotation actually happens. Note that we rotate the whole
	//molecule, not just the planar subset, this is only used to calculate the rotation angle.
	//	fmt.Println("DATA", mol.Coords[0], zero, axis, Angle(best, z))
	mol.Coords[0], err = RotateAbout(mol.Coords[0], zero, axis, Angle(best, z))
	if err != nil {
		Te.Error(err)
	}
	//	fmt.Println("after!", mol.Coords[0], err)
	//Now we write the rotated result.
	outxyz, _ := os.Create("test/Rotated.xyz") //This is the XYZWrite written file
	XYZWrite(outxyz, mol.Coords[0], mol)
}
Exemple #21
0
/*	for framebunch, j := range results {
		if j == nil {
			break
		}
		for frame, k := range j {
			if k == nil {
				fmt.Println(framebunch, frame)
				continue
			}
			fmt.Println(framebunch, frame, <-k)
		}
	}
}
*/
func SecondRow(channelin, channelout chan *v3.Matrix, current, other int) {
	if channelin != nil {
		temp := <-channelin
		viej := v3.Zeros(1)
		vector := temp.VecView(2)
		viej.Copy(vector)
		fmt.Println("sending througt", channelin, channelout, viej, current, other)
		channelout <- vector
	} else {
		channelout <- nil
	}
	return
}
Exemple #22
0
//SelCone, Given a set of cartesian points in sellist, obtains a vector "plane" normal to the best plane passing through the points.
//It selects atoms from the set A that are inside a cone in the direction of "plane" that starts from the geometric center of the cartesian points,
//and has an angle of angle (radians), up to a distance distance. The cone is approximated by a set of radius-increasing cilinders with height thickness.
//If one starts from one given point, 2 cgnOnes, one in each direction, are possible. If whatcone is 0, both cgnOnes are considered.
//if whatcone<0, only the cone opposite to the plane vector direction. If whatcone>0, only the cone in the plane vector direction.
//the 'initial' argument  allows the construction of a truncate cone with a radius of initial.
func SelCone(B, selection *v3.Matrix, angle, distance, thickness, initial float64, whatcone int) []int {
	A := v3.Zeros(B.NVecs())
	A.Copy(B) //We will be altering the input so its better to work with a copy.
	ar, _ := A.Dims()
	selected := make([]int, 0, 3)
	neverselected := make([]int, 0, 30000)     //waters that are too far to ever be selected
	nevercutoff := distance / math.Cos(angle)  //cutoff to be added to neverselected
	A, _, err := MassCenter(A, selection, nil) //Centrate A in the geometric center of the selection, Its easier for the following calculations
	if err != nil {
		panic(PanicMsg(err.Error()))
	}
	selection, _, _ = MassCenter(selection, selection, nil) //Centrate the selection as well
	plane, err := BestPlane(selection, nil)                 //I have NO idea which direction will this vector point. We might need its negative.
	if err != nil {
		panic(PanicMsg(err.Error()))
	}
	for i := thickness / 2; i <= distance; i += thickness {
		maxdist := math.Tan(angle)*i + initial //this should give me the radius of the cone at this point
		for j := 0; j < ar; j++ {
			if isInInt(selected, j) || isInInt(neverselected, j) { //we dont scan things that we have already selected, or are too far
				continue
			}
			atom := A.VecView(j)
			proj := Projection(atom, plane)
			norm := proj.Norm(0)
			//Now at what side of the plane is the atom?
			angle := Angle(atom, plane)
			if whatcone > 0 {
				if angle > math.Pi/2 {
					continue
				}
			} else if whatcone < 0 {
				if angle < math.Pi/2 {
					continue
				}
			}
			if norm > i+(thickness/2.0) || norm < (i-thickness/2.0) {
				continue
			}
			proj.Sub(proj, atom)
			projnorm := proj.Norm(0)
			if projnorm <= maxdist {
				selected = append(selected, j)
			}
			if projnorm >= nevercutoff {
				neverselected = append(neverselected, j)
			}
		}
	}
	return selected
}
Exemple #23
0
//One opens the sample.xyz file in the test directory, and pull a number of hardcoded atoms
//In the direction of a hardcoded vectos. It builds 12 files with the pulled atoms  displaced by
//different ammounts along the pulling vector
func One() {
	pulled_atoms := []int{43, 41, 42, 40, 85, 86, 87} //indexes
	pulling_vector := []int{40, 88}                   //The direction in which we pull is given by atoms 40 and 88 counting from 0
	pull_ammount := 4.0                               //how much do we want to pull, in Angstroms
	mol, err := chem.XYZFileRead("sample.xyz")
	if err != nil {
		panic(err.Error())
	}
	pulled := v3.Zeros(7)
	pulled.SomeVecs(mol.Coords[0], pulled_atoms) //We use the pulled_atoms set of indexes to get the atoms we will be pulling
	at1 := mol.Coord(pulling_vector[0], 0)
	vector := v3.Zeros(1)
	vector.Copy(mol.Coord(pulling_vector[1], 0)) //We copy to avoid altering the atom 88 coordinates
	vector.Sub(vector, at1)
	vector.Unit(vector)
	vector.Scale(pull_ammount, vector) //we started with an unit lenght bector and now multiply by the desired pull ammount
	pulled.AddRow(pulled, vector)
	if err != nil {
		panic(err.Error())
	}
	mol.Coords[0].SetVecs(pulled, pulled_atoms) //Now we put the pulled coordinates into the original molecule
	chem.XYZFileWrite("sample_pulled.xyz", mol.Coords[0], mol)
}
Exemple #24
0
//Obtains and prints the distance between atoms 2 and 10 (counting from zero) for each frame of trajectory
//traj.
func ProcessTraj(traj chem.Traj) {
	coords := v3.Zeros(traj.Len())
	for i := 0; ; i++ { //infinite loop, we only break out of it by using "break"
		err := traj.Next(coords) //Obtain the next frame of the trajectory.
		if err != nil {
			_, ok := err.(chem.LastFrameError)
			if ok {
				break //We processed all frames and are ready, not a real error.

			} else {
				panic(err.Error)
			}
		} else {
			atom10 := coords.VecView(10)
			atom2 := coords.VecView(2)
			fmt.Println("Distance between the third and tenth atoms in the ", i+1, " frame: ", Distance(atom10, atom2), "A")
		}
	}
}
Exemple #25
0
//This is a throw-away mini program, so the data is hardcoded.
func main() {
	mol, err := chem.XYZFileRead("../sample.xyz")
	if err != nil {
		panic(err.Error())
	}
	mol.SetCharge(1)
	mol.SetMulti(1)
	//Setting up the calculations
	//We will mosstly go with the defaults.
	calc := new(qm.Calc)
	calc.SCFTightness = 1 //rather demanding.
	calc.Method = "TPSS"
	calc.Dielectric = 80 //COSMO with epsilon=80. Just delete this line to avoid COSMO usage.
	calc.Basis = "def2-TZVP"
	calc.RI = true //RI approximation (also called charge-density fitting, in some programs).
	calc.Dispersion = "D3"
	orca := qm.NewOrcaHandle() //Change this line to use MOPAC2012 or Turbomole
	//Now we play with a bond and make orca inputs
	// to calculate a SP energy for each geometry.
	//*******************************************
	//I just hard-coded these ones, they make sense
	//for my test system but you will have to change them for yours.
	axis1 := mol.Coords[0].VecView(6) //the 2 atoms defining the rotation axis
	axis2 := mol.Coords[0].VecView(7)
	torotate_indexes := []int{8, 9, 10, 11, 70, 83, 69}
	torotate := v3.Zeros(len(torotate_indexes))
	torotate.SomeVecs(mol.Coords[0], torotate_indexes)                  //The atoms that will rotate
	angles := []float64{0, 0.2 * math.Pi, 0.4 * math.Pi, 0.5 * math.Pi} //The rotation angles in radians.
	for _, angle := range angles {
		rotated, err := chem.RotateAbout(torotate, axis1, axis2, angle)
		if err != nil {
			panic(err.Error())
		}
		//now we put the rotated coords in the molecule
		mol.Coords[0].SetVecs(rotated, torotate_indexes)
		orca.SetName(fmt.Sprintf("angle%1.1f", angle))
		//We first write the QM input and then an XYZ witht he non optimized geometry.
		if err := orca.BuildInput(mol.Coords[0], mol, calc); err != nil {
			panic(err.Error())
		}
		chem.XYZFileWrite(fmt.Sprintf("angle%1.1f.xyz", angle), mol.Coords[0], mol)
	}
}
Exemple #26
0
func main() {
	mol, err := chem.XYZFileRead(os.Args[1])
	if err != nil {
		panic(err.Error())
	}
	ndx, _ := scu.IndexStringParse(os.Args[2])
	fmt.Println(ndx)
	coord := mol.Coords[0]
	piv := coord.VecView(ndx[0])
	v1 := coord.VecView(ndx[1])
	v2 := coord.VecView(ndx[2])
	v1.Sub(v1, piv)
	v2.Sub(v2, piv)
	plane := v3.Zeros(1)
	plane.Cross(v1, v2)
	vfin := coord.VecView(ndx[3])
	vfin.Sub(vfin, piv)
	angle := chem.Angle(vfin, plane)
	fmt.Println(90-angle*chem.Rad2Deg, 90+angle*chem.Rad2Deg)
}
Exemple #27
0
/*TestXtc reads the frames of the test xtc file using the
 * "interactive" or "low level" functions, i.e. one frame at a time
 * It prints the firs 2 coordinates of each frame and the number of
 * read frames at the end.*/
func TestDCD(Te *testing.T) {
	fmt.Println("Fist test!")
	traj, err := New("../test/test.dcd")
	if err != nil {
		Te.Error(err)
	}
	i := 0
	mat := v3.Zeros(traj.Len())
	for ; ; i++ {
		err := traj.Next(mat)
		if err != nil {
			if _, ok := err.(chem.LastFrameError); ok {
				break
			}
			Te.Error(err)
			break
		}
		fmt.Println(mat.VecView(2))
	}
	fmt.Println("Over! frames read:", i)
}
Exemple #28
0
//TestOldChangeAxis reads the PDB 2c9v.pdb from the test directory, collects
//The CA and CB of residue D124 of the chain A, and rotates the
//whole molecule such as the vector defined by these 2 atoms is
//aligned with the Z axis. The new molecule is written
//as 2c9v_aligned.pdb to the test folder.
func TestOldChangeAxis(Te *testing.T) {
	viej, _ := os.Open("test/2c9v.pdb")
	mol, err := PDBRead(viej, true)
	if err != nil {
		Te.Error(err)
	}
	orient_atoms := [2]int{0, 0}
	for index := 0; index < mol.Len(); index++ {
		atom := mol.Atom(index)
		if atom.Chain == "A" && atom.MolID == 124 {
			if atom.Name == "CA" {
				orient_atoms[0] = index
			} else if atom.Name == "CB" {
				orient_atoms[1] = index
			}
		}
	}
	ov1 := mol.Coord(orient_atoms[0], 0)
	ov2 := mol.Coord(orient_atoms[1], 0)
	//now we center the thing in the beta carbon of D124
	mol.Coords[0].SubVec(mol.Coords[0], ov2)
	//Now the rotation
	ov1 = mol.Coord(orient_atoms[0], 0) //make sure we have the correct versions
	ov2 = mol.Coord(orient_atoms[1], 0) //same
	orient := v3.Zeros(ov2.NVecs())
	orient.Sub(ov2, ov1)
	rotation := RotatorToNewZ(orient)
	cr, cc := mol.Coords[0].Dims()
	fmt.Println("rotation: ", rotation, cr, cc) ////////////////////////////////////////////////////////
	mol.Coords[0].Mul(mol.Coords[0], rotation)
	//	fmt.Println(orient_atoms[1], mol.Atom(orient_atoms[1]),mol.Atom(orient_atoms[0]))
	if err != nil {
		Te.Error(err)
	}
	PDBFileWrite("test/2c9v-old-aligned.pdb", mol.Coords[0], mol, nil)
	fmt.Println("bench2")
}
Exemple #29
0
//RMSD returns the RSMD (root of the mean square deviation) for the sets of cartesian
//coordinates in test and template.
func RMSD(test, template *v3.Matrix) (float64, error) {
	//This is a VERY naive implementation.
	tmr, tmc := template.Dims()
	tsr, tsc := test.Dims()
	if tmr != tsr || tmc != 3 || tsc != 3 {
		return 0, fmt.Errorf("Ill formed matrices for RMSD calculation")
	}
	tr := tmr
	ctempla := v3.Zeros(template.NVecs())
	ctempla.Copy(template)
	//the maybe thing might not be needed since we check the dimensions before.
	f := func() { ctempla.Sub(ctempla, test) }
	if err := gnMaybe(gnPanicker(f)); err != nil {
		return 0, CError{err.Error(), []string{"v3.Matrix.Sub", "RMSD"}}
	}
	var RMSD float64
	for i := 0; i < template.NVecs(); i++ {
		temp := ctempla.VecView(i)
		RMSD += math.Pow(temp.Norm(0), 2)
	}
	RMSD = RMSD / float64(tr)
	RMSD = math.Sqrt(RMSD)
	return RMSD, nil
}
Exemple #30
0
//MakeWater Creates a water molecule at distance Angstroms from a2, in a direction that is angle radians from the axis defined by a1 and a2.
//Notice that the exact position of the water is not well defined when angle is not zero. One can always use the RotateAbout
//function to move the molecule to the desired location. If oxygen is true, the oxygen will be pointing to a2. Otherwise,
//one of the hydrogens will.
func MakeWater(a1, a2 *v3.Matrix, distance, angle float64, oxygen bool) *v3.Matrix {
	water := v3.Zeros(3)
	const WaterOHDist = 0.96
	const WaterAngle = 52.25
	const deg2rad = 0.0174533
	w := water.VecView(0) //we first set the O coordinates
	w.Copy(a2)
	w.Sub(w, a1)
	w.Unit(w)
	dist := v3.Zeros(1)
	dist.Sub(a1, a2)
	a1a2dist := dist.Norm(0)
	fmt.Println("ala2dist", a1a2dist, distance) ////////////////7777
	w.Scale(distance+a1a2dist, w)
	w.Add(w, a1)
	for i := 0; i <= 1; i++ {
		o := water.VecView(0)
		w = water.VecView(i + 1)
		w.Copy(o)
		fmt.Println("w1", w) ////////
		w.Sub(w, a2)
		fmt.Println("w12", w) ///////////////
		w.Unit(w)
		fmt.Println("w4", w)
		w.Scale(WaterOHDist+distance, w)
		fmt.Println("w3", w, WaterOHDist, distance)
		o.Sub(o, a2)
		t, _ := v3.NewMatrix([]float64{0, 0, 1})
		upp := v3.Zeros(1)
		upp.Cross(w, t)
		fmt.Println("upp", upp, w, t)
		upp.Add(upp, o)
		upp.Add(upp, a2)
		//water.SetMatrix(3,0,upp)
		w.Add(w, a2)
		o.Add(o, a2)
		sign := 1.0
		if i == 1 {
			sign = -1.0
		}
		temp, _ := RotateAbout(w, o, upp, deg2rad*WaterAngle*sign)
		w.SetMatrix(0, 0, temp)
	}
	var v1, v2 *v3.Matrix
	if angle != 0 {
		v1 = v3.Zeros(1)
		v2 = v3.Zeros(1)
		v1.Sub(a2, a1)
		v2.Copy(v1)
		v2.Set(0, 2, v2.At(0, 2)+1) //a "random" modification. The idea is that its not colinear with v1
		v3 := cross(v1, v2)
		v3.Add(v3, a2)
		water, _ = RotateAbout(water, a2, v3, angle)
	}
	if oxygen {
		return water
	}
	//we move things so an hydrogen points to a2 and modify the distance acordingly.
	e1 := water.VecView(0)
	e2 := water.VecView(1)
	e3 := water.VecView(2)
	if v1 == nil {
		v1 = v3.Zeros(1)
	}
	if v2 == nil {
		v2 = v3.Zeros(1)
	}
	v1.Sub(e2, e1)
	v2.Sub(e3, e1)
	axis := cross(v1, v2)
	axis.Add(axis, e1)
	water, _ = RotateAbout(water, e1, axis, deg2rad*(180-WaterAngle))
	v1.Sub(e1, a2)
	v1.Unit(v1)
	v1.Scale(WaterOHDist, v1)
	water.AddVec(water, v1)
	return water
}