Remove silly tex/ directory.
[thesis.git] / src / figures / schematic / unfolding.asy
1 // Protein unfolding graphic
2
3 //size(x=9cm,keepAspect=true);
4
5 import stats;    // for unitrand
6 import base_afm; // for Cantilever, Substrate, ...
7
8 struct Wiggle {
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
14
15   pair start;
16   pair end;
17   real roughness;
18   real tense;
19   int num;
20   int random_seed;
21   pair points[];
22
23   void generate(bool labels=false) {
24     int n = this.num;
25     pair step = (this.end-this.start) / (n-1);
26     pair perp = scale(this.roughness)*rotate(90)*unit(step);
27     real y, envelope;
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) {
31         y = 0.0;
32       } else {
33         real frac = i/n;
34         envelope = (frac*(1.0-frac)*4)**3;
35         y = (2*unitrand()-1.0) * envelope;
36       }
37       this.points.push(this.start + i*step + perp*y);
38       if (labels==true)
39         dot(format("%d", i), this.points[-1], S);
40     }
41   }
42
43   guide guide() {
44     guide g;
45     for (int i; i < this.points.length; i+=1) {
46       g = g .. tension this.tense .. this.points[i];
47     }
48     this.end = point(g, length(g));
49     return g;
50   }
51
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) {
54     this.start = start;
55     this.end = end;
56     this.roughness = roughness;
57     this.tense = tense;
58     this.num = num;
59     this.random_seed = random_seed;
60     this.generate();
61   }
62 }
63
64 struct ProteinChain {
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
70   pair start;
71   pair end;
72   real angle;
73   real len_u = 2cm;
74   real len_f = 0.5cm;
75   real rough_u = 0.4cm;
76   real rough_f = 0.6cm;
77   Wiggle prot_u;
78   Wiggle prot_f;
79   bool folded[];
80
81   void gen_prots() {
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);
84   }
85
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;
93       else
94         start += u*this.len_u;
95     }
96     return start;
97   }
98
99   Wiggle prot(int n) {
100     assert(n < this.folded.length);
101     if (this.folded[n] == true)
102       return this.prot_f;
103     else
104       return this.prot_u;
105   }    
106
107   guide guide() {
108     guide g;
109     guide p;
110     for (int i=0; i < this.folded.length; i+=1) {
111       p = shift(this.prot_start(i))*this.prot(i).guide();
112       g = g .. p;
113     }
114     return g;
115   }
116
117   void operator init(pair start=(0,0), real angle=90,
118                      bool folded[]={true,true,false,true}) {
119     this.start = start;
120     this.angle = angle;
121     this.folded = folded;
122     this.gen_prots();
123     guide g = this.guide();
124     this.end = point(g, length(g));
125   }
126 }
127
128 defaultpen(fontsize(size=10pt, lineskip=10pt));
129
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);
135
136
137 Cantilever c = Cantilever();
138 // position base so tip touches protein when bent
139 c.set_tip_for_dx(12pt);
140 c.align_tip(p.end);
141 // unbend the tip and draw it in grey
142 c.set_tip_for_dx(0);
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);
151
152 Substrate s = Substrate();
153 s.draw(dir=S);
154
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));
163 real 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));