1 // Protein unfolding graphic
3 //size(x=9cm,keepAspect=true);
5 import stats; // for unitrand
6 import base_afm; // for Cantilever, Substrate, ...
9 // Generate a horizontal wiggly line, centered at CENTER (x,y)
10 // with a width WIDTH x
11 // and randomly distributed heights.
12 // The random points are unformly distributed within an envelope
13 // with the maximum possible deviation given by ROUGHNESS x
23 void generate(bool labels=false) {
25 pair step = (this.end-this.start) / (n-1);
26 pair perp = scale(this.roughness)*rotate(90)*unit(step);
28 srand(this.random_seed);
29 for (int i=0; i < n; i+=1) {
30 if (i == (n-1)/2 || i == 0 || i == n-1) {
34 envelope = (frac*(1.0-frac)*4)**3;
35 y = (2*unitrand()-1.0) * envelope;
37 this.points.push(this.start + i*step + perp*y);
39 dot(format("%d", i), this.points[-1], S);
45 for (int i; i < this.points.length; i+=1) {
46 g = g .. tension this.tense .. this.points[i];
48 this.end = point(g, length(g));
52 void operator init(pair start=(0,0), pair end=(1cm,0), real roughness=1cm,
53 real tense=1, int num=15, int random_seed=5) {
56 this.roughness = roughness;
59 this.random_seed = random_seed;
65 // Generate and draw a mixed protein (2nd protein unfolded)
66 // starting at START (x,y)
67 // of folded length LEN, with NUM segments
68 // with the unfolded protein's dimensions given by UNFOLD_LEN and UNFOLD_WID
69 // (so the final length with be LEN - LEN/NUM + UNFOLD_LEN
82 this.prot_u = Wiggle(end=(0,this.len_u), roughness=this.rough_u);
83 this.prot_f = Wiggle(end=(0,this.len_f), roughness=this.rough_f);
86 pair prot_start(int n) {
87 assert(n < this.folded.length);
88 pair start = this.start;
89 pair u = dir(this.angle);
90 for (int i; i < n; i+=1) {
91 if (this.folded[i] == true)
92 start += u*this.len_f;
94 start += u*this.len_u;
100 assert(n < this.folded.length);
101 if (this.folded[n] == true)
110 for (int i=0; i < this.folded.length; i+=1) {
111 p = shift(this.prot_start(i))*this.prot(i).guide();
117 void operator init(pair start=(0,0), real angle=90,
118 bool folded[]={true,true,false,true}) {
121 this.folded = folded;
123 guide g = this.guide();
124 this.end = point(g, length(g));
128 defaultpen(fontsize(size=10pt, lineskip=10pt));
130 bool folded[] = {true,true,false,true};
131 ProteinChain p = ProteinChain(folded=folded);
132 draw(p.guide(), red);
133 label("\vbox{\hbox{Folded}\hbox{protein}}", p.prot_start(1)+(1.4*p.rough_f, 0)/2, E);
134 label("\vbox{\hbox{Unfolded}\hbox{protein}}", p.prot_start(2)+(1.3*p.rough_u, p.len_u)/2, E);
137 Cantilever c = Cantilever();
138 // position base so tip touches protein when bent
139 c.set_tip_for_dx(12pt);
141 // unbend the tip and draw it in grey
143 pair unbent_tip = c.tip;
144 filldraw(c.tip_guide(), fillpen=grey, grey);
145 draw(c.arm_guide(), grey);
146 // rebend the tip and draw it in black
147 c.set_tip_for_dx(12pt);
148 filldraw(c.tip_guide(), fillpen=black);
149 draw(c.arm_guide(), black);
150 label("Cantilever", c.base-(0,16pt), SW);
152 Substrate s = Substrate();
155 real xt_x = -0.45*s.substrate_width;
156 real xi_x = -0.27*s.substrate_width;
157 real bar_extra = 6pt;
158 distance("$x_t$", (xt_x, 0), (xt_x, unbent_tip.y));
159 distance("$x_c$", (xi_x, c.tip.y), (xi_x, unbent_tip.y));
160 distance("$x_{f1}$", (xi_x, p.prot_start(3).y), (xi_x, c.tip.y));
161 distance("$x_u$", (xi_x, p.prot_start(2).y), (xi_x, p.prot_start(3).y));
162 distance("$x_{f2}$", (xi_x, 0), (xi_x, p.prot_start(2).y));
164 y = unbent_tip.y; draw((xt_x-bar_extra,y)--(xi_x+bar_extra,y));
165 y = p.prot_start(2).y; draw((xi_x-bar_extra,y)--(xi_x+bar_extra,y));
166 y = p.prot_start(3).y; draw((xi_x-bar_extra,y)--(xi_x+bar_extra,y));
167 y = c.tip.y; draw((xi_x-bar_extra,y)--(xi_x+bar_extra,y));