1
2 """
3 Skeins a 3D model into gcode.
4 """
5
6 from config import config
7 from datetime import timedelta
8 from entities import SlicedModel
9 from fabmetheus_utilities import archive
10 from importlib import import_module
11 from utilities import memory_tracker
12 import argparse
13 import logging
14 import os
15 import re
16 import sys
17 import time
18 import traceback
19 import StringIO
20 try:
21 import cPickle as pickle
22 except:
23 import pickle
24
25 __plugins_path__ = 'plugins'
26 logger = logging.getLogger('engine')
27
28 -def getCraftedTextFromPlugins(pluginSequence, gcode):
29 'Get a crafted shape file from a list of pluginSequence.'
30 lastProcedureTime = time.time()
31 if __plugins_path__ not in sys.path:
32 sys.path.insert(0, __plugins_path__)
33 for plugin in pluginSequence:
34 pluginModule = import_module(plugin)
35 if pluginModule != None:
36 if gcode.runtimeParameters.profileMemory:
37 memory_tracker.create_snapshot('Before %s action' % plugin)
38 pluginModule.performAction(gcode)
39 logger.info('%s plugin took %s seconds.', plugin.capitalize(), timedelta(seconds=time.time() - lastProcedureTime).total_seconds())
40 lastProcedureTime = time.time()
41
43 "Starting point for skeinforge engine."
44 parser = argparse.ArgumentParser(description='Skeins a 3D model into slicedModel.')
45 parser.add_argument('file', help='The file to skein. Files accepted: stl, obj, gts, and svg or pickledgcode files produced by Skeinforge.')
46 parser.add_argument('-c', metavar='config', help='Configuration for skeinforge engine.', default='skeinforge_engine.cfg')
47 parser.add_argument('-p', metavar='profile', help='Profile for the skeining.')
48 parser.add_argument('-o', metavar='output', help='Output filename. Overrides other export filename settings.')
49 parser.add_argument('-r', metavar='reprocess', help='Comma seperated list of plugins to reprocess a pickled slicedModel file. The export plugin is automatically appended.')
50
51
52 if argv is None:
53 argv = sys.argv[1:]
54 args = parser.parse_args(argv)
55
56 if args.c == None:
57 logger.error('Invalid or missing configuration file.')
58 return
59 config.read(args.c)
60
61 logLevel = config.get('general', 'log.level')
62 logging.basicConfig(level=logLevel, format='%(asctime)s %(levelname)s (%(name)s) %(message)s')
63
64 defaultProfile = config.get('general', 'default.profile')
65 if defaultProfile != None:
66 config.read(defaultProfile)
67 profileName = config.get('profile', 'name')
68
69 if args.p != None:
70 config.read(args.p)
71 if profileName == 'default':
72 profileName = os.path.basename(args.p)
73
74 logger.info("Profile: %s", profileName)
75
76 inputFilename = args.file
77
78 if not os.path.isfile(inputFilename):
79 logger.error('File not found: %s', inputFilename)
80 return
81
82 logger.info("Processing file: %s", os.path.basename(inputFilename))
83
84 if inputFilename.endswith('.pickled_slicedmodel'):
85 pickledSlicedModel = archive.getFileText(inputFilename)
86 slicedModel = pickle.loads(pickledSlicedModel)
87 slicedModel.runtimeParameters.startTime = time.time()
88 slicedModel.runtimeParameters.endTime = None
89 else:
90 slicedModel = SlicedModel()
91
92 if args.o != None:
93 slicedModel.runtimeParameters.outputFilename = args.o
94
95 if args.r != None:
96 pluginSequence = args.r.split(',')
97 if 'carve' in pluginSequence:
98 logger.error('Reprocessing a pickled sliced model file with carve is not possible. Please process the original file instead.')
99 return
100 if 'export' not in pluginSequence:
101 pluginSequence.append('export')
102 else:
103 pluginSequence = config.get('general', 'plugin.sequence').split(',')
104
105 logger.debug("Plugin Sequence: %s", pluginSequence)
106
107 if slicedModel.runtimeParameters.profileMemory:
108 memory_tracker.track_object(slicedModel)
109 memory_tracker.create_snapshot('Start')
110
111 slicedModel.runtimeParameters.profileName = profileName
112 slicedModel.runtimeParameters.inputFilename = inputFilename
113
114 getCraftedTextFromPlugins(pluginSequence[:], slicedModel)
115
116 slicedModel.runtimeParameters.endTime = time.time()
117
118 logger.info('It took %s seconds to complete.', timedelta(seconds=slicedModel.runtimeParameters.endTime - slicedModel.runtimeParameters.startTime).total_seconds())
119
120 if slicedModel.runtimeParameters.profileMemory:
121 memory_tracker.create_snapshot('End')
122 if config.getboolean('general', 'profile.memory.print.summary'):
123 memory_tracker.tracker.stats.print_summary()
124 if config.getboolean('general', 'profile.memory.export.data'):
125 memory_tracker.tracker.stats.dump_stats('%s.memory_tracker.dat' % inputFilename)
126 if config.getboolean('general', 'profile.memory.export.html'):
127 from pympler.classtracker_stats import HtmlStats
128 HtmlStats(tracker=memory_tracker.tracker).create_html('%s.memory_tracker.html' % inputFilename)
129
130 return slicedModel
131
133 traceback.print_stack()
134
135 if __name__ == "__main__":
136 logging.Handler.handleError = handleError
137 main()
138