Moved AFM-drawing functions from unfolding.asy to base_afm.asy & made substrate motio...
authorW. Trevor King <wking@drexel.edu>
Thu, 18 Feb 2010 17:34:14 +0000 (12:34 -0500)
committerW. Trevor King <wking@drexel.edu>
Thu, 18 Feb 2010 17:35:16 +0000 (12:35 -0500)
tex/src/figures/schematic/Makefile
tex/src/figures/schematic/base_afm.asy [new file with mode: 0644]
tex/src/figures/schematic/unfolding.asy

index c66dc390ec8b3407cfb9fce6c493bda2cd92d79f..2f440a6c4e2e40e83cc2de8a301fb947a2c5e29e 100644 (file)
@@ -3,5 +3,5 @@ all : unfolding.pdf
 clean :
        rm -f unfolding.pdf
 
-unfolding.pdf :
+unfolding.pdf : unfolding.asy base_afm.asy
         asy -f pdf unfolding.asy
diff --git a/tex/src/figures/schematic/base_afm.asy b/tex/src/figures/schematic/base_afm.asy
new file mode 100644 (file)
index 0000000..1859b86
--- /dev/null
@@ -0,0 +1,169 @@
+// AFM drawing utilities.
+
+struct Cantilever {
+  // draw an AFM cantilever with the tip at TIP (x,y) position on page
+  // the cantilever arm is roughly parallel to DIR_TO_BASE (x,y) vector
+  // POINT_SCALE x gives the height of the tip.
+  pair tip;
+  pair tip_top;
+  pair base;
+  real arm_length;
+  real tip_height;
+  real rest_angle; // in degrees
+  real dx;
+  real theta; // in radians
+  real r_curve;
+  
+  void align_tip(pair tip) {
+    pair offset = tip - this.tip;
+    this.tip += offset;
+    this.tip_top += offset;
+    this.base += offset;
+  }
+
+  real dx_error(real theta) {
+    /* Call the radius of curvature, r_curve=R
+     * arm_length=L lies along the perimiter, so
+     *   R\theta = L
+     * The perpendicular deflection dx is then
+     *   R(1-\cos\theta) = L(1-\cos\theta)/\theta = dx
+     * and the horizontal displacement L' from the base is
+     *   R\sin\theta = L\sin\theta/\theta = L\sinc\theta= L'
+     */
+     return this.arm_length * (1.0 - cos(theta)) / theta  -  this.dx;
+  }
+
+  real dx_prime(real theta) {
+    /* d(dx)/d(\theta) = L/\theta * [(\cos\theta-1)/\theta + \sin\theta]  */
+    return this.arm_length/theta * ((cos(theta)-1)/theta + sin(theta));
+  }
+
+  void set_tip_for_dx(real dx) {
+    /* invert dx(theta) using bracketed Newton-Raphson bisection.
+     * First order theta from
+     *   dx = L(1-\cos\theta)/\theta
+     *      = L[1-(1-\theta^2/2!+...)]/\theta
+     *      ~= L\theta/2
+     *   \theta != 2dx/L
+     */
+    this.dx = dx;
+    real Lp;
+    if (dx == 0) {
+      this.theta = 0;
+      this.r_curve = -1;
+      Lp = this.arm_length;
+    } else {
+      real first_order_theta = 2.0*dx/this.arm_length;
+      this.theta = newton(this.dx_error, this.dx_prime,
+                         0.1 * first_order_theta,
+                         min(3.0 * first_order_theta, pi/2.0));
+      /* because we ignored tip_height when we calculated theta, cheat a
+       * bit and pretend the tip is directly under our caculated
+       * tip_top.  Then adjust tip_top accordingly.  This throws off the
+       * bend (and maybe the arm length) a bit, but ah well :p.
+       */
+      this.r_curve = this.arm_length / this.theta;
+      Lp = this.r_curve * sin(this.theta);
+    }
+    pair uy = dir(this.rest_angle);
+    pair ux = dir(this.rest_angle+90);
+    pair utx = dir(this.rest_angle+90+degrees(this.theta));
+    this.tip = this.base + Lp*uy + (dx+this.tip_height)*utx;
+    this.tip_top = this.tip - this.tip_height*utx;
+  }
+
+  guide tip_guide() {
+    path p;
+    pair uty, tip_distal, tip_proximal;
+    pair uty = dir(this.rest_angle+degrees(this.theta));
+    tip_distal = this.tip_top + this.tip_height/3.0*uty;
+    tip_proximal = this.tip_top - this.tip_height/3.0*uty;
+    p = this.tip -- tip_distal -- tip_proximal -- cycle;
+    return p;
+  }
+
+  guide arm_guide() {
+    path p;
+    pair uy, uty, tip_distal, tip_proximal;
+    pair uy = dir(this.rest_angle);
+    pair ux = dir(this.rest_angle+90);
+    pair uty = dir(this.rest_angle+degrees(this.theta));
+    tip_distal = this.tip_top + this.tip_height/3.0*uty;
+    tip_proximal = this.tip_top - this.tip_height/3.0*uty;
+    if (this.dx == 0) {
+      p = tip_distal -- tip_proximal -- this.base; // should be colinear
+    } else {
+      p = tip_distal -- tip_proximal{-uty} .. tension 0.75 .. {-uy}this.base;
+      /*      real angle_tip_proximal, angle_base;
+      pair center = this.base + this.r_curve*dx;
+      angle_tip_proximal = angle(tip_proximal - center);
+      angle_base = angle(this.base - center);
+      p = tip_distal -- arc(center, this.r_curve, angle_tip_proximal, angle_base);
+      tip_proximal{-uty} .. tension 0.75 .. {uy}this.base;
+      */
+    }
+    return p;
+  }
+
+  void operator init (pair base=(0,0), real arm_length=2.5cm, real tip_height=0.5cm, real rest_angle=185, real dx=0) {
+    this.base = base;
+    this.arm_length = arm_length;
+    this.tip_height = tip_height;
+    this.rest_angle = rest_angle;
+    this.set_tip_for_dx(dx);
+  }
+}
+
+struct Substrate {
+  pair prot_connect_point;
+  real substrate_width = 3cm;
+  real substrate_height = 10pt;
+  real piezo_width = 1.5cm;
+  real piezo_height = 0.75cm;
+  pen substrate_fill = grey;
+
+  path box(pair top_center, real width, real height) {
+    real w = width/2;
+    pair ul = top_center+(-w,0);
+    pair ur = top_center+( w,0);
+    pair ll = top_center+(-w,-height);
+    pair lr = top_center+( w,-height);
+    path p = ul -- ur -- lr -- ll -- cycle;
+    return p;
+  }
+
+  void draw(pair dir=(0,0)) {
+    pair piezo_top = this.prot_connect_point - (0,this.substrate_height);
+    pair piezo_bot = this.prot_connect_point - (0,this.substrate_height+this.piezo_height);
+    filldraw(this.box(this.prot_connect_point, this.substrate_width, this.substrate_height),
+             fillpen=this.substrate_fill);
+    label("Substrate", this.prot_connect_point - (0,this.substrate_height/2));
+    draw(this.box(piezo_top, this.piezo_width, this.piezo_height));
+    label("Piezo", piezo_top, S);
+    if (dir != (0,0)) {
+      real arrow_length = this.piezo_height/3;
+      pair arrow_center = piezo_bot + (0, arrow_length/2 + 2pt);
+      arrow(b=arrow_center + dir*arrow_length/2, dir=-dir,
+           length=this.piezo_height/3, Arrow(size=8pt),
+           margin=NoMargin);
+    }
+  }
+
+  void operator init(pair prot_connect_point=(0,0)) {
+    this.prot_connect_point = prot_connect_point;
+  }
+}
+
+void distance(Label L, pair start, pair end) {
+  pair center = (start+end)/2;
+  pair u = unit(end-start);
+  picture picL;
+  label(picL, L);
+  pair label_size = 1.2 * (max(picL)-min(picL));
+  real arrow_length = length(end-start)/2 - label_size.y;
+  if (arrow_length > 4pt) {
+    arrow(b=start, dir=u, length=arrow_length, Arrow(size=4pt));
+    arrow(b=end, dir=-u, length=arrow_length, Arrow(size=4pt));
+  }
+  label(L, center);
+}
index 6b5d871e1f4f517980f3dc2bb25095f395334939..bc702057bab6fcd5c1e7666c83708fe092238ba3 100644 (file)
@@ -2,7 +2,8 @@
 
 //size(x=9cm,keepAspect=true);
 
-import stats; // for Gaussrand()
+import stats;    // for unitrand
+import base_afm; // for Cantilever, Substrate, ...
 
 struct Wiggle {
   // Generate a horizontal wiggly line, centered at CENTER (x,y)
@@ -124,168 +125,6 @@ struct ProteinChain {
   }
 }
 
-struct Cantilever {
-  // draw an AFM cantilever with the tip at TIP (x,y) position on page
-  // the cantilever arm is roughly parallel to DIR_TO_BASE (x,y) vector
-  // POINT_SCALE x gives the height of the tip.
-  pair tip;
-  pair tip_top;
-  pair base;
-  real arm_length;
-  real tip_height;
-  real rest_angle; // in degrees
-  real dx;
-  real theta; // in radians
-  real r_curve;
-  
-  void align_tip(pair tip) {
-    pair offset = tip - this.tip;
-    this.tip += offset;
-    this.tip_top += offset;
-    this.base += offset;
-  }
-
-  real dx_error(real theta) {
-    /* Call the radius of curvature, r_curve=R
-     * arm_length=L lies along the perimiter, so
-     *   R\theta = L
-     * The perpendicular deflection dx is then
-     *   R(1-\cos\theta) = L(1-\cos\theta)/\theta = dx
-     * and the horizontal displacement L' from the base is
-     *   R\sin\theta = L\sin\theta/\theta = L\sinc\theta= L'
-     */
-     return this.arm_length * (1.0 - cos(theta)) / theta  -  this.dx;
-  }
-
-  real dx_prime(real theta) {
-    /* d(dx)/d(\theta) = L/\theta * [(\cos\theta-1)/\theta + \sin\theta]  */
-    return this.arm_length/theta * ((cos(theta)-1)/theta + sin(theta));
-  }
-
-  void set_tip_for_dx(real dx) {
-    /* invert dx(theta) using bracketed Newton-Raphson bisection.
-     * First order theta from
-     *   dx = L(1-\cos\theta)/\theta
-     *      = L[1-(1-\theta^2/2!+...)]/\theta
-     *      ~= L\theta/2
-     *   \theta != 2dx/L
-     */
-    this.dx = dx;
-    real Lp;
-    if (dx == 0) {
-      this.theta = 0;
-      this.r_curve = -1;
-      Lp = this.arm_length;
-    } else {
-      real first_order_theta = 2.0*dx/this.arm_length;
-      this.theta = newton(this.dx_error, this.dx_prime,
-                         0.1 * first_order_theta,
-                         min(3.0 * first_order_theta, pi/2.0));
-      /* because we ignored tip_height when we calculated theta, cheat a
-       * bit and pretend the tip is directly under our caculated
-       * tip_top.  Then adjust tip_top accordingly.  This throws off the
-       * bend (and maybe the arm length) a bit, but ah well :p.
-       */
-      this.r_curve = this.arm_length / this.theta;
-      Lp = this.r_curve * sin(this.theta);
-    }
-    pair uy = dir(this.rest_angle);
-    pair ux = dir(this.rest_angle+90);
-    pair utx = dir(this.rest_angle+90+degrees(this.theta));
-    this.tip = this.base + Lp*uy + (dx+this.tip_height)*utx;
-    this.tip_top = this.tip - this.tip_height*utx;
-  }
-
-  guide tip_guide() {
-    path p;
-    pair uty, tip_distal, tip_proximal;
-    pair uty = dir(this.rest_angle+degrees(this.theta));
-    tip_distal = this.tip_top + this.tip_height/3.0*uty;
-    tip_proximal = this.tip_top - this.tip_height/3.0*uty;
-    p = this.tip -- tip_distal -- tip_proximal -- cycle;
-    return p;
-  }
-
-  guide arm_guide() {
-    path p;
-    pair uy, uty, tip_distal, tip_proximal;
-    pair uy = dir(this.rest_angle);
-    pair ux = dir(this.rest_angle+90);
-    pair uty = dir(this.rest_angle+degrees(this.theta));
-    tip_distal = this.tip_top + this.tip_height/3.0*uty;
-    tip_proximal = this.tip_top - this.tip_height/3.0*uty;
-    if (this.dx == 0) {
-      p = tip_distal -- tip_proximal -- this.base; // should be colinear
-    } else {
-      p = tip_distal -- tip_proximal{-uty} .. tension 0.75 .. {-uy}this.base;
-      /*      real angle_tip_proximal, angle_base;
-      pair center = this.base + this.r_curve*dx;
-      angle_tip_proximal = angle(tip_proximal - center);
-      angle_base = angle(this.base - center);
-      p = tip_distal -- arc(center, this.r_curve, angle_tip_proximal, angle_base);
-      tip_proximal{-uty} .. tension 0.75 .. {uy}this.base;
-      */
-    }
-    return p;
-  }
-
-  void operator init (pair base=(0,0), real arm_length=2.5cm, real tip_height=0.5cm, real rest_angle=185, real dx=0) {
-    this.base = base;
-    this.arm_length = arm_length;
-    this.tip_height = tip_height;
-    this.rest_angle = rest_angle;
-    this.set_tip_for_dx(dx);
-  }
-}
-
-struct Substrate {
-  pair prot_connect_point;
-  real substrate_width = 3cm;
-  real substrate_height = 10pt;
-  real piezo_width = 1.5cm;
-  real piezo_height = 0.75cm;
-  pen substrate_fill = grey;
-
-  path box(pair top_center, real width, real height) {
-    real w = width/2;
-    pair ul = top_center+(-w,0);
-    pair ur = top_center+( w,0);
-    pair ll = top_center+(-w,-height);
-    pair lr = top_center+( w,-height);
-    path p = ul -- ur -- lr -- ll -- cycle;
-    return p;
-  }
-
-  void draw() {
-    pair piezo_top = this.prot_connect_point - (0,this.substrate_height);
-    pair piezo_bot = this.prot_connect_point - (0,this.substrate_height+this.piezo_height);
-    filldraw(this.box(this.prot_connect_point, this.substrate_width, this.substrate_height),
-             fillpen=this.substrate_fill);
-    label("Substrate", this.prot_connect_point - (0,this.substrate_height/2));
-    draw(this.box(piezo_top, this.piezo_width, this.piezo_height));
-    label("Piezo", piezo_top, S);
-    arrow(b=piezo_bot, dir=N, length=this.piezo_height/3, Arrow(size=8pt));
-  }
-
-  void operator init(pair prot_connect_point=(0,0)) {
-    this.prot_connect_point = prot_connect_point;
-  }
-}
-
-void distance(Label L, pair start, pair end) {
-  pair center = (start+end)/2;
-  pair u = unit(end-start);
-  picture picL;
-  label(picL, L);
-  pair label_size = 1.2 * (max(picL)-min(picL));
-  real arrow_length = length(end-start)/2 - label_size.y;
-  if (arrow_length > 4pt) {
-    arrow(b=start, dir=u, length=arrow_length, Arrow(size=4pt));
-    arrow(b=end, dir=-u, length=arrow_length, Arrow(size=4pt));
-  }
-  label(L, center);
-}
-
 defaultpen(fontsize(size=10pt, lineskip=10pt));
 
 bool folded[] = {true,true,false,true};
@@ -299,19 +138,19 @@ Cantilever c = Cantilever();
 // position base so tip touches protein when bent
 c.set_tip_for_dx(12pt);
 c.align_tip(p.end);
-// now unbend the tip and draw it in grey
+// unbend the tip and draw it in grey
 c.set_tip_for_dx(0);
 pair unbent_tip = c.tip;
 filldraw(c.tip_guide(), fillpen=grey, grey);
 draw(c.arm_guide(), grey);
-// now rebend the tip and draw it in black
+// rebend the tip and draw it in black
 c.set_tip_for_dx(12pt);
 filldraw(c.tip_guide(), fillpen=black);
 draw(c.arm_guide(), black);
 label("Cantilever", c.base-(0,10pt), SW);
 
 Substrate s = Substrate();
-s.draw();
+s.draw(dir=S);
 
 real xt_x = -0.45*s.substrate_width;
 real xi_x = -0.27*s.substrate_width;