//PDBStringWrite writes a string in PDB format for a given reference, coordinate set and bfactor set, which must match each other //returns the written string and error or nil. func PDBStringWrite(coords *v3.Matrix, mol Atomer, bfact []float64) (string, error) { if bfact == nil { bfact = make([]float64, mol.Len()) } cr, _ := coords.Dims() br := len(bfact) if cr != mol.Len() || cr != br { return "", CError{"Ref and Coords and/or Bfactors dont have the same number of atoms", []string{"PDBStringWrite"}} } chainprev := mol.Atom(0).Chain //this is to know when the chain changes. var outline string var outstring string var err error for i := 0; i < mol.Len(); i++ { // r,c:=coords.Dims() // fmt.Println("IIIIIIIIIIIi", i,coords,r,c, "lllllll") writecoord := coords.VecView(i) outline, chainprev, err = writePDBLine(mol.Atom(i), writecoord, bfact[i], chainprev) if err != nil { return "", errDecorate(err, "PDBStringWrite "+fmt.Sprintf("Could not print PDB line: %d", i)) } outstring = strings.Join([]string{outstring, outline}, "") } outstring = strings.Join([]string{outstring, "END\n"}, "") return outstring, nil }
func pdbWrite(out io.Writer, coords *v3.Matrix, mol Atomer, bfact []float64) error { if bfact == nil { bfact = make([]float64, mol.Len()) } cr, _ := coords.Dims() br := len(bfact) if cr != mol.Len() || cr != br { return CError{"Ref and Coords and/or Bfactors dont have the same number of atoms", []string{"pdbWrite"}} } chainprev := mol.Atom(0).Chain //this is to know when the chain changes. var outline string var err error iowriteError := func(err error) error { return CError{"Failed to write in io.Writer" + err.Error(), []string{"io.Write.Write", "pdbWrite"}} } for i := 0; i < mol.Len(); i++ { // r,c:=coords.Dims() // fmt.Println("IIIIIIIIIIIi", i,coords,r,c, "lllllll") writecoord := coords.VecView(i) outline, chainprev, err = writePDBLine(mol.Atom(i), writecoord, bfact[i], chainprev) if err != nil { return errDecorate(err, "pdbWrite "+fmt.Sprintf("Could not print PDB line: %d", i)) } _, err := out.Write([]byte(outline)) if err != nil { return iowriteError(err) } } _, err = out.Write([]byte("END")) //no newline, this is in case the write is part of a PDB and one needs to write "ENDMODEL". if err != nil { return iowriteError(err) } return nil }
//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 }
//ScaleBonds scales all bonds between atoms in the same residue with names n1, n2 to a final lenght finallengt, by moving the atoms n2. //the operation is executed in place. func ScaleBonds(coords *v3.Matrix, mol Atomer, n1, n2 string, finallenght float64) { for i := 0; i < mol.Len(); i++ { c1 := mol.Atom(i) if c1.Name != n1 { continue } for j := 0; j < mol.Len(); j++ { c2 := mol.Atom(j) if c1.MolID == c2.MolID && c1.Name == n1 && c2.Name == n2 { A := coords.VecView(i) B := coords.VecView(j) ScaleBond(A, B, finallenght) } } } }
// RamaCalc Obtains the values for the phi and psi dihedrals indicated in []Ramaset, for the // structure M. It returns a slice of 2-element slices, one for the phi the next for the psi // dihedral, a and an error or nil. func RamaCalc(M *v3.Matrix, dihedrals []RamaSet) ([][]float64, error) { if M == nil || dihedrals == nil { return nil, Error{ErrNilData, "", "RamaCalc", "", true} } r, _ := M.Dims() Rama := make([][]float64, 0, len(dihedrals)) for _, j := range dihedrals { if j.Npost >= r { return nil, Error{ErrOutOfRange, "", "RamaCalc", "", true} } Cprev := M.VecView(j.Cprev) N := M.VecView(j.N) Ca := M.VecView(j.Ca) C := M.VecView(j.C) Npost := M.VecView(j.Npost) phi := chem.Dihedral(Cprev, N, Ca, C) psi := chem.Dihedral(N, Ca, C, Npost) temp := []float64{phi * (180 / math.Pi), psi * (180 / math.Pi)} Rama = append(Rama, temp) } return Rama, nil }