forked from fogleman/ribbon
/
main.go
116 lines (99 loc) · 2.61 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package main
import (
"compress/gzip"
"fmt"
"log"
"net/http"
"os"
"strings"
"time"
. "github.com/fogleman/fauxgl"
"github.com/fogleman/ribbon/pdb"
"github.com/fogleman/ribbon/ribbon"
"github.com/nfnt/resize"
)
const (
size = 2048
scale = 4
)
func main() {
args := os.Args[1:]
if len(args) != 1 || len(args[0]) != 4 {
fmt.Println("Usage: rcsb XXXX")
fmt.Println(" XXXX: 4-digit RCSB PDB Structure ID")
os.Exit(1)
}
structureID := args[0]
var done func()
done = timed("downloading pdb file")
models, err := downloadAndParse(structureID)
if err != nil {
log.Fatal(err)
}
model := models[0]
done()
fmt.Printf("atoms = %d\n", len(model.Atoms))
fmt.Printf("residues = %d\n", len(model.Residues))
fmt.Printf("chains = %d\n", len(model.Chains))
fmt.Printf("helixes = %d\n", len(model.Helixes))
fmt.Printf("strands = %d\n", len(model.Strands))
fmt.Printf("het-atoms = %d\n", len(model.HetAtoms))
fmt.Printf("connections = %d\n", len(model.Connections))
done = timed("generating triangle mesh")
mesh := ribbon.ModelMesh(model)
done()
fmt.Printf("triangles = %d\n", len(mesh.Triangles))
done = timed("transforming mesh")
m := mesh.BiUnitCube()
done()
done = timed("finding ideal camera position")
c := ribbon.PositionCamera(model, m)
done()
done = timed("writing mesh to disk")
mesh.SaveSTL(fmt.Sprintf("%s.stl", structureID))
done()
// render
done = timed("rendering image")
context := NewContext(int(size*scale*c.Aspect), size*scale)
context.ClearColorBufferWith(HexColor("1D181F"))
matrix := LookAt(c.Eye, c.Center, c.Up).Perspective(c.Fovy, c.Aspect, 1, 100)
light := c.Eye.Sub(c.Center).Normalize()
shader := NewPhongShader(matrix, light, c.Eye)
shader.AmbientColor = Gray(0.3)
shader.DiffuseColor = Gray(0.9)
context.Shader = shader
context.DrawTriangles(mesh.Triangles)
done()
// save image
done = timed("downsampling image")
image := context.Image()
image = resize.Resize(uint(size*c.Aspect), size, image, resize.Bilinear)
done()
done = timed("writing image to disk")
SavePNG(fmt.Sprintf("%s.png", structureID), image)
done()
}
func downloadAndParse(structureID string) ([]*pdb.Model, error) {
url := fmt.Sprintf(
"https://files.rcsb.org/download/%s.pdb.gz",
strings.ToUpper(structureID))
resp, err := http.Get(url)
if err != nil {
return nil, err
}
defer resp.Body.Close()
r, err := gzip.NewReader(resp.Body)
if err != nil {
return nil, err
}
return pdb.NewReader(r).ReadAll()
}
func timed(name string) func() {
if len(name) > 0 {
fmt.Printf("%s... ", name)
}
start := time.Now()
return func() {
fmt.Println(time.Since(start))
}
}