// Converts an array of strings to an array of float32. func StringArrayAsFloat32Array(v []string) []float32 { data := make([]float32, len(v)) for i := 0; i < len(v); i++ { x := strings.TrimSpace(v[i]) data[i] = what.Atof32(x) } return data }
// Load an inpcrd file into this system func (mol *System) LoadRst(inpcrdFilename string) { inpcrdFile, err := os.Open(inpcrdFilename) if err != nil { fmt.Println("Error opening inpcrd:", err) return } // defer == awesome! defer inpcrdFile.Close() inpcrd := bufio.NewReader(inpcrdFile) // Header line - discard s, err := inpcrd.ReadString('\n') // Number of atoms s, err = inpcrd.ReadString('\n') n, _ := strconv.Atoi(strings.TrimSpace(s)) numCoords := mol.NumAtoms() * 3 if n*3 != numCoords { fmt.Fprintf(os.Stderr, "Inpcrd says it has %d atoms but I'm expecting %d instead.\n", n, numCoords) return } // Now we know how many tokens to expect. They are all of length 12, // with up to 6 per line. mol.Coords = make(map[int][]float32) frame := 0 mol.Coords[frame] = make([]float32, numCoords) numThings := 6 thingLen := 12 ctr := 0 for err == nil { s, err = inpcrd.ReadString('\n') // s contains some number of things n := (len(s) - 1) / thingLen if n > numThings { n = numThings } thisFrame := mol.Coords[frame] for i := 0; i < n*thingLen && ctr < numCoords; i += thingLen { thisFrame[ctr] = what.Atof32(s[i : i+thingLen]) ctr++ } } // TODO: if it has a box, read the box, and move on to the next frame if mol.GetInt("POINTERS", IFBOX) > 0 { fmt.Fprintf(os.Stderr, "There's a box! We should do something about this.\n") } }
// Assumes file pointer is at the start of a frame func GetNextFrameFromTrajectory(trj *bufio.Reader, numAtoms int, hasBox bool) ([]float32, error) { // Calculate how many lines per frame linesPerFrame := numAtoms * 3 / 10 if numAtoms*3%10 != 0 { linesPerFrame++ } // fmt.Println("Lines per frame:", linesPerFrame); // var ok bool var coords = make([]float32, numAtoms*3) coords = <-coordsFreeList // if (!ok) { // fmt.Println("Allocating a new coords buffer.") // coords = make([]float32, numAtoms*3) // } // ci := 0 for i := 0; i < linesPerFrame; i++ { // Read and trim a line line, err := trj.ReadString('\n') if err != nil { return nil, err } line = trimSpace(line) // Each token is ended by whitespace or eol. for b := 0; b < len(line); { var e int // Advance to end of token for e = b; e < len(line) && line[e] != ' ' && line[e] != '\n' && line[e] != '\t'; e++ { } //fmt.Println(b, e, line[b:e]); coords[ci] = what.Atof32(line[b:e]) ci++ // Now, e is either at end of line or points to whitespace. // Advance b to start of next token or eol for b = e; b < len(line) && (line[b] == ' ' || line[b] == '\n' || line[b] == '\t'); b++ { } } } // Eat box line if hasBox { trj.ReadString('\n') } return coords, nil }
// Loads an AMBER system - both a prmtop and inpcrd. func LoadSystem(prmtopFilename string) *System { var mol System mol.Blocks = make(map[string][]string) mol.Formats = make(map[string][]string) prmtopFile, err := os.Open(prmtopFilename) if err != nil { fmt.Println("Error opening prmtop:", err) return nil } // defer == awesome! defer prmtopFile.Close() prmtop := bufio.NewReader(prmtopFile) // Set up us the regular expression formatRe, _ := regexp.Compile("[(]([0-9]+)([aIE]+)([0-9.]+)[)]") // Eat header line s, err := prmtop.ReadString('\n') //fmt.Println(s); // Get first FLAG line s, err = prmtop.ReadString('\n') for err == nil { //fmt.Println(s); if len(s) < 5 { break } blockName := strings.TrimSpace(s[6 : len(s)-1]) mol.Blocks[blockName] = make([]string, 0) // FORMAT line s, err = prmtop.ReadString('\n') fmtSpec := formatRe.FindStringSubmatch(s) var numThings, thingLen int if len(fmtSpec) == 4 { numThings, _ = strconv.Atoi(fmtSpec[1]) //thingType = fmtSpec[2]; lenSpec := what.Atof32(fmtSpec[3]) thingLen = int(lenSpec) mol.Formats[blockName] = fmtSpec } else { fmt.Println("Couldn't understand format specifier - bad prmtop") fmt.Println(fmtSpec, s) return nil } // Now that we know what type of data to expect, read it // until we hit another FLAG line for err == nil { s, err = prmtop.ReadString('\n') if len(s) >= 5 && s[0:5] == "%FLAG" { break } // s contains some number of things n := (len(s) - 1) / thingLen if n > numThings { n = numThings } for i := 0; i < (n * thingLen); i += thingLen { mol.Blocks[blockName] = append(mol.Blocks[blockName], s[i:i+thingLen]) } } } return &mol }