wip
This commit is contained in:
parent
82c01ff78c
commit
61d82dbdc8
|
@ -6,10 +6,11 @@ from math import modf
|
||||||
from serial import Serial
|
from serial import Serial
|
||||||
from serial.tools.list_ports import comports
|
from serial.tools.list_ports import comports
|
||||||
|
|
||||||
|
from .paths import path_length
|
||||||
from .planner import Planner
|
from .planner import Planner
|
||||||
from .progress import Bar
|
from .progress import Bar
|
||||||
|
|
||||||
TIMESLICE_MS = 10
|
TIMESLICE_MS = 20
|
||||||
|
|
||||||
MICROSTEPPING_MODE = 2
|
MICROSTEPPING_MODE = 2
|
||||||
STEP_DIVIDER = 2 ** (MICROSTEPPING_MODE - 1)
|
STEP_DIVIDER = 2 ** (MICROSTEPPING_MODE - 1)
|
||||||
|
@ -27,7 +28,7 @@ PEN_DOWN_DELAY = 0
|
||||||
|
|
||||||
ACCELERATION = 8
|
ACCELERATION = 8
|
||||||
MAX_VELOCITY = 4
|
MAX_VELOCITY = 4
|
||||||
CORNER_FACTOR = 0.005
|
CORNER_FACTOR = 0.0025
|
||||||
|
|
||||||
VID_PID = '04D8:FD92'
|
VID_PID = '04D8:FD92'
|
||||||
|
|
||||||
|
@ -160,13 +161,15 @@ class Device(object):
|
||||||
def run_drawing(self, drawing, progress=True):
|
def run_drawing(self, drawing, progress=True):
|
||||||
self.pen_up()
|
self.pen_up()
|
||||||
position = (0, 0)
|
position = (0, 0)
|
||||||
bar = Bar(enabled=progress)
|
bar = Bar(drawing.length, enabled=progress)
|
||||||
for path in bar(drawing.paths):
|
for path in drawing.paths:
|
||||||
self.run_path([position, path[0]])
|
self.run_path([position, path[0]])
|
||||||
self.pen_down()
|
self.pen_down()
|
||||||
self.run_path(path)
|
self.run_path(path)
|
||||||
self.pen_up()
|
self.pen_up()
|
||||||
position = path[-1]
|
position = path[-1]
|
||||||
|
bar.increment(path_length(path))
|
||||||
|
bar.done()
|
||||||
self.run_path([position, (0, 0)])
|
self.run_path([position, (0, 0)])
|
||||||
|
|
||||||
def plan_drawing(self, drawing):
|
def plan_drawing(self, drawing):
|
||||||
|
|
|
@ -4,7 +4,7 @@ from math import sin, cos, radians
|
||||||
|
|
||||||
from .paths import (
|
from .paths import (
|
||||||
simplify_paths, sort_paths, join_paths, crop_paths, convex_hull,
|
simplify_paths, sort_paths, join_paths, crop_paths, convex_hull,
|
||||||
expand_quadratics)
|
expand_quadratics, paths_length)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import cairo
|
import cairo
|
||||||
|
@ -14,7 +14,12 @@ except ImportError:
|
||||||
class Drawing(object):
|
class Drawing(object):
|
||||||
def __init__(self, paths=None):
|
def __init__(self, paths=None):
|
||||||
self.paths = paths or []
|
self.paths = paths or []
|
||||||
|
self.dirty()
|
||||||
|
|
||||||
|
def dirty(self):
|
||||||
self._bounds = None
|
self._bounds = None
|
||||||
|
self._length = None
|
||||||
|
self._hull = None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def loads(cls, data):
|
def loads(cls, data):
|
||||||
|
@ -70,11 +75,13 @@ class Drawing(object):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def convex_hull(self):
|
def convex_hull(self):
|
||||||
return convex_hull(self.points)
|
if self._hull is None:
|
||||||
|
self._hull = convex_hull(self.points)
|
||||||
|
return self._hull
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def bounds(self):
|
def bounds(self):
|
||||||
if not self._bounds:
|
if self._bounds is None:
|
||||||
points = self.points
|
points = self.points
|
||||||
if points:
|
if points:
|
||||||
x1 = min(x for x, y in points)
|
x1 = min(x for x, y in points)
|
||||||
|
@ -86,6 +93,12 @@ class Drawing(object):
|
||||||
self._bounds = (x1, y1, x2, y2)
|
self._bounds = (x1, y1, x2, y2)
|
||||||
return self._bounds
|
return self._bounds
|
||||||
|
|
||||||
|
@property
|
||||||
|
def length(self):
|
||||||
|
if self._length is None:
|
||||||
|
self._length = paths_length(self.paths)
|
||||||
|
return self._length
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def width(self):
|
def width(self):
|
||||||
x1, y1, x2, y2 = self.bounds
|
x1, y1, x2, y2 = self.bounds
|
||||||
|
@ -124,7 +137,7 @@ class Drawing(object):
|
||||||
|
|
||||||
def add(self, drawing):
|
def add(self, drawing):
|
||||||
self.paths.extend(drawing.paths)
|
self.paths.extend(drawing.paths)
|
||||||
self._bounds = None
|
self.dirty()
|
||||||
|
|
||||||
def transform(self, func):
|
def transform(self, func):
|
||||||
return Drawing([[func(x, y) for x, y in path] for path in self.paths])
|
return Drawing([[func(x, y) for x, y in path] for path in self.paths])
|
||||||
|
|
21
axi/paths.py
21
axi/paths.py
|
@ -1,4 +1,5 @@
|
||||||
from math import hypot
|
from math import hypot
|
||||||
|
from pyhull.convex_hull import ConvexHull
|
||||||
from shapely import geometry
|
from shapely import geometry
|
||||||
|
|
||||||
from .spatial import Index
|
from .spatial import Index
|
||||||
|
@ -14,6 +15,15 @@ def load_paths(filename):
|
||||||
paths.append(path)
|
paths.append(path)
|
||||||
return paths
|
return paths
|
||||||
|
|
||||||
|
def path_length(points):
|
||||||
|
result = 0
|
||||||
|
for (x1, y1), (x2, y2) in zip(points, points[1:]):
|
||||||
|
result += hypot(x2 - x1, y2 - y1)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def paths_length(paths):
|
||||||
|
return sum([path_length(path) for path in paths], 0)
|
||||||
|
|
||||||
def simplify_path(points, tolerance):
|
def simplify_path(points, tolerance):
|
||||||
if len(points) < 2:
|
if len(points) < 2:
|
||||||
return points
|
return points
|
||||||
|
@ -111,14 +121,9 @@ def crop_paths(paths, x1, y1, x2, y2):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def convex_hull(points):
|
def convex_hull(points):
|
||||||
hull = geometry.MultiPoint(points).convex_hull
|
hull = ConvexHull(points)
|
||||||
if isinstance(hull, geometry.Polygon):
|
vertices = set(i for v in hull.vertices for i in v)
|
||||||
return list(hull.exterior.coords)
|
return [hull.points[i] for i in vertices]
|
||||||
if isinstance(hull, geometry.LineString):
|
|
||||||
return list(hull.coords)
|
|
||||||
if isinstance(hull, geometry.Point):
|
|
||||||
return list(hull.coords)
|
|
||||||
raise Exception('unhandled convex hull geometry')
|
|
||||||
|
|
||||||
def quadratic_path(x0, y0, x1, y1, x2, y2):
|
def quadratic_path(x0, y0, x1, y1, x2, y2):
|
||||||
n = int(hypot(x1 - x0, y1 - y0) + hypot(x2 - x1, y2 - y1))
|
n = int(hypot(x1 - x0, y1 - y0) + hypot(x2 - x1, y2 - y1))
|
||||||
|
|
|
@ -46,6 +46,9 @@ class Bar(object):
|
||||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||||
self.stop()
|
self.stop()
|
||||||
|
|
||||||
|
def increment(self, delta):
|
||||||
|
self.update(self.value + delta)
|
||||||
|
|
||||||
def update(self, value):
|
def update(self, value):
|
||||||
self.value = value
|
self.value = value
|
||||||
if self.enabled:
|
if self.enabled:
|
||||||
|
|
|
@ -16,7 +16,7 @@ def prepare():
|
||||||
print 'rendering'
|
print 'rendering'
|
||||||
im = d.render(
|
im = d.render(
|
||||||
scale=109 * 1, line_width=0.3/25.4,
|
scale=109 * 1, line_width=0.3/25.4,
|
||||||
)#show_axi_bounds=False, use_axi_bounds=False)
|
show_axi_bounds=False, use_axi_bounds=False)
|
||||||
im.write_to_png('isolines.png')
|
im.write_to_png('isolines.png')
|
||||||
d.dump('isolines.axi')
|
d.dump('isolines.axi')
|
||||||
|
|
||||||
|
@ -53,5 +53,5 @@ def main():
|
||||||
d.dump('out.axi')
|
d.dump('out.axi')
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# prepare()
|
prepare()
|
||||||
main()
|
# main()
|
||||||
|
|
|
@ -4,22 +4,28 @@ import sys
|
||||||
def main():
|
def main():
|
||||||
filename = sys.argv[1]
|
filename = sys.argv[1]
|
||||||
print 'loading paths'
|
print 'loading paths'
|
||||||
d = axi.Drawing(axi.load_paths(filename))
|
# d = axi.Drawing(axi.load_paths(filename))
|
||||||
|
d = axi.Drawing.load(filename)
|
||||||
|
print len(d.paths)
|
||||||
# print 'eliminating duplicate paths'
|
# print 'eliminating duplicate paths'
|
||||||
# d.paths = list(set([tuple(x) for x in d.paths]))
|
# d.paths = list(set([tuple(x) for x in d.paths]))
|
||||||
print 'joining paths'
|
# print 'joining paths'
|
||||||
d = d.join_paths(0.001)
|
# d = d.join_paths(0.001)
|
||||||
|
# print len(d.paths)
|
||||||
print 'transforming paths'
|
print 'transforming paths'
|
||||||
d = d.scale(1, -1)
|
# d = d.scale(1, -1)
|
||||||
|
d = d.rotate(180)
|
||||||
d = d.rotate_and_scale_to_fit(12, 8.5, step=90)
|
d = d.rotate_and_scale_to_fit(12, 8.5, step=90)
|
||||||
print 'sorting paths'
|
print 'sorting paths'
|
||||||
d = d.sort_paths()
|
d = d.sort_paths()
|
||||||
print 'joining paths'
|
print 'joining paths'
|
||||||
d = d.join_paths(0.01)
|
d = d.join_paths(0.01)
|
||||||
|
print len(d.paths)
|
||||||
print 'simplifying paths'
|
print 'simplifying paths'
|
||||||
d = d.simplify_paths(0.001)
|
d = d.simplify_paths(0.001)
|
||||||
print 'rendering paths'
|
print 'rendering paths'
|
||||||
d.render(line_width=0.25/25.4).write_to_png('out.png')
|
d.render(line_width=0.25/25.4).write_to_png('out.png')
|
||||||
|
d.dump('out.axi')
|
||||||
# axi.draw(d)
|
# axi.draw(d)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -2,16 +2,17 @@ import axi
|
||||||
import sys
|
import sys
|
||||||
import textwrap
|
import textwrap
|
||||||
|
|
||||||
NUMBER = 'XX'
|
NUMBER = '34'
|
||||||
LABEL = '#%s' % NUMBER
|
LABEL = '#%s' % NUMBER
|
||||||
|
|
||||||
TITLE = textwrap.wrap(
|
TITLE = textwrap.wrap(
|
||||||
"X-ray structure of human beta3beta3 alcohol dehydrogenase"
|
"Beta Subunit of the 20S Proteasome from T. acidophilum"
|
||||||
, 40)
|
, 36)
|
||||||
|
|
||||||
ABSTRACT = textwrap.wrap(
|
SUBTITLE = textwrap.wrap(
|
||||||
"The three-dimensional structure of the human beta3beta3 dimeric alcohol dehydrogenase (beta3) was determined to 2.4-A resolution. beta3 was crystallized as a ternary complex with the coenzyme NAD+ and the competitive inhibitor 4-iodopyrazole. beta3 is a polymorphic variant at ADH2 that differs from beta1 by a single amino acid substitution of Arg-369 --> Cys. The available x-ray structures of mammalian alcohol dehydrogenases show that the side chain of Arg-369 forms an ion pair with the NAD(H) pyrophosphate to stabilize the E.NAD(H) complex. The Cys-369 side chain of beta3 cannot form this interaction. The three-dimensional structures of beta3 and beta1 are virtually identical, with the exception that Cys-369 and two water molecules in beta3 occupy the position of Arg-369 in beta1. The two waters occupy the same positions as two guanidino nitrogens of Arg-369. Hence, the number of hydrogen bonding interactions between the enzyme and NAD(H) are the same for both isoenzymes. However, beta3 differs from beta1 by the loss of the electrostatic interaction between the NAD(H) pyrophosphate and the Arg-369 side chain. The equilibrium dissociation constants of beta3 for NAD+ and NADH are 350-fold and 4000-fold higher, respectively, than those for beta1. These changes correspond to binding free energy differences of 3.5 kcal/mol for NAD+ and 4.9 kcal/mol for NADH. Thus, the Arg-369 --> Cys substitution of beta3 isoenzyme destabilizes the interaction between coenzyme and beta3 alcohol dehydrogenase."
|
"These coordinates are from the 1995 crystal structure by Lowe et al. (Lowe et al., 1995). PDB entry 1PMA."
|
||||||
, 120)
|
# "Coordinates from the 1995 crystal structure by Lowe et al. PDB entry 1PMA."
|
||||||
|
, 60)
|
||||||
|
|
||||||
def concat(ds):
|
def concat(ds):
|
||||||
result = axi.Drawing()
|
result = axi.Drawing()
|
||||||
|
@ -46,16 +47,21 @@ def title():
|
||||||
spacing = max(d.height for d in ds) * 1.5
|
spacing = max(d.height for d in ds) * 1.5
|
||||||
ds = [d.translate(-d.width / 2, i * spacing) for i, d in enumerate(ds)]
|
ds = [d.translate(-d.width / 2, i * spacing) for i, d in enumerate(ds)]
|
||||||
d = concat(ds)
|
d = concat(ds)
|
||||||
d = d.scale_to_fit_width(8.5)
|
d = d.scale_to_fit_width(8.5 * 4 / 5)
|
||||||
|
d = d.scale_to_fit_height(0.8)
|
||||||
d = d.join_paths(0.01)
|
d = d.join_paths(0.01)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def abstract():
|
def subtitle():
|
||||||
ds = [axi.Drawing(p) for p in axi.justify_text(ABSTRACT, axi.TIMESR)]
|
# ds = [axi.Drawing(p) for p in axi.justify_text(SUBTITLE, axi.TIMESR)]
|
||||||
|
# spacing = max(d.height for d in ds) * 1.5
|
||||||
|
# ds = [d.translate(0, i * spacing) for i, d in enumerate(ds)]
|
||||||
|
ds = [axi.Drawing(axi.text(line, axi.TIMESR)) for line in SUBTITLE]
|
||||||
spacing = max(d.height for d in ds) * 1.5
|
spacing = max(d.height for d in ds) * 1.5
|
||||||
ds = [d.translate(0, i * spacing) for i, d in enumerate(ds)]
|
ds = [d.translate(-d.width / 2, i * spacing) for i, d in enumerate(ds)]
|
||||||
d = concat(ds)
|
d = concat(ds)
|
||||||
d = d.scale_to_fit_width(8.5)
|
d = d.scale_to_fit_width(8.5 * 2 / 3)
|
||||||
|
d = d.scale_to_fit_height(0.4)
|
||||||
d = d.join_paths(0.01)
|
d = d.join_paths(0.01)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
@ -68,8 +74,10 @@ def label():
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
# text = stack_drawings([title(), abstract()], 0.25)
|
text = stack_drawings([title(), subtitle()], 0.3125)
|
||||||
text = title()
|
text = text.rotate(-90)
|
||||||
|
text = text.move(12, 8.5 / 2, 1, 0.5)
|
||||||
|
# text = title()
|
||||||
|
|
||||||
filenames = [
|
filenames = [
|
||||||
sys.argv[1],
|
sys.argv[1],
|
||||||
|
@ -83,7 +91,7 @@ def main():
|
||||||
print 'loading paths'
|
print 'loading paths'
|
||||||
ds = []
|
ds = []
|
||||||
for filename, angle in zip(filenames, angles):
|
for filename, angle in zip(filenames, angles):
|
||||||
ds.append(axi.Drawing(axi.load_paths(filename)).scale_to_fit(8.5, 12).scale(1, -1))
|
ds.append(axi.Drawing(axi.load_paths(filename)).scale(1, -1))
|
||||||
# d = grid_drawings(ds, 2, 1)
|
# d = grid_drawings(ds, 2, 1)
|
||||||
d = ds[0]
|
d = ds[0]
|
||||||
print len(d.paths)
|
print len(d.paths)
|
||||||
|
@ -92,7 +100,8 @@ def main():
|
||||||
print len(d.paths)
|
print len(d.paths)
|
||||||
print 'transforming paths'
|
print 'transforming paths'
|
||||||
# d = d.scale(1, -1)
|
# d = d.scale(1, -1)
|
||||||
d = d.rotate_and_scale_to_fit(8.5, 12 - text.height - 0.75)
|
d = d.rotate(180)
|
||||||
|
d = d.rotate_and_scale_to_fit(8.5, 12 - text.height)
|
||||||
# d = d.origin()
|
# d = d.origin()
|
||||||
print 'sorting paths'
|
print 'sorting paths'
|
||||||
d = d.sort_paths()
|
d = d.sort_paths()
|
||||||
|
@ -103,12 +112,13 @@ def main():
|
||||||
d = d.simplify_paths(0.001)
|
d = d.simplify_paths(0.001)
|
||||||
|
|
||||||
# add title and label and fit to page
|
# add title and label and fit to page
|
||||||
d = stack_drawings([d, text], 0.75)
|
# d = stack_drawings([d, text], 1)
|
||||||
d = d.rotate(-90)
|
# d = d.rotate(-90)
|
||||||
# d = d.center(12, 8.5)
|
# d = d.center(12, 8.5)
|
||||||
d = d.scale_to_fit(12, 8.5)
|
d = d.rotate_and_scale_to_fit(12, 8.5).translate(-text.width * 0.6666, 0)
|
||||||
|
d.add(text)
|
||||||
# d.add(title())
|
# d.add(title())
|
||||||
# d.add(label())
|
d.add(label())
|
||||||
|
|
||||||
print 'rendering paths'
|
print 'rendering paths'
|
||||||
d.render(line_width=0.25/25.4).write_to_png('out.png')
|
d.render(line_width=0.25/25.4).write_to_png('out.png')
|
||||||
|
|
|
@ -1 +1,4 @@
|
||||||
pyserial==3.2.1
|
pyserial
|
||||||
|
pyhull
|
||||||
|
Shapely
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue