Skip to content

Commit d5fd24d

Browse files
committed
added bakeout plugin
1 parent 5448d3f commit d5fd24d

File tree

21 files changed

+643
-40
lines changed

21 files changed

+643
-40
lines changed

pychron/bakeout/__init__.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# ===============================================================================
2+
# Copyright 2024 ross
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
# ===============================================================================
16+
17+
# ============= EOF =============================================

pychron/bakeout/bakeout_manager.py

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# ===============================================================================
2+
# Copyright 2024 ross
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
# ===============================================================================
16+
from traits.api import Any
17+
from traitsui.api import UItem, TableEditor, InstanceEditor, HGroup
18+
from traitsui.table_column import ObjectColumn
19+
from traitsui.extras.checkbox_column import CheckboxColumn
20+
21+
from pychron.graph.time_series_graph import TimeSeriesStreamStackedGraph
22+
from pychron.hardware.bakeout_plc import BakeoutPLC
23+
from pychron.loggable import Loggable
24+
from pychron.managers.stream_graph_manager import StreamGraphManager
25+
26+
27+
class BakeoutManager(StreamGraphManager):
28+
controller = Any
29+
settings_name = 'bakeout_streaming'
30+
31+
def _create_manager(
32+
self, klass, manager, params, port=None, host=None, remote=False
33+
):
34+
return self.application.get_service(BakeoutManager)
35+
36+
def _controller_default(self):
37+
return BakeoutPLC(name='controller', configuration_dir_name='bakeout')
38+
39+
def prepare_destroy(self):
40+
self.set_streaming_active(False)
41+
self.stop_scan()
42+
self.controller.prepare_destroy()
43+
44+
def activate(self):
45+
self.debug('asdfascasdcasdc')
46+
self.set_streaming_active(True)
47+
# self.bind_preferences()
48+
49+
# self.load_event_marker_config()
50+
self.setup_scan()
51+
# self.readout_view.start()
52+
self.reset_scan_timer()
53+
54+
def setup_scan(self):
55+
self._reset_graph()
56+
self.graph_scan_width = 10
57+
self._graph_scan_width_changed()
58+
59+
def _update_scan_graph(self):
60+
for ci in self.get_display_channels():
61+
t = self.controller.read_temperature(ci.index)
62+
if t is None:
63+
continue
64+
65+
sp = self.controller.read_setpoint(ci.index)
66+
dc = self.controller.read_duty_cycle(ci.index)
67+
self.controller.read_overtemp_ishighhigh(ci.index)
68+
69+
self.graph.record(t, series=ci.index)
70+
self.graph.record(sp, series=ci.index + 1)
71+
self.graph.record(dc, plotid=1, series=ci.index)
72+
73+
def _graph_factory(self, *args, **kw):
74+
g = TimeSeriesStreamStackedGraph()
75+
# g.plotcontainer.padding_top = 5
76+
# g.plotcontainer.padding_right = 5
77+
g.new_plot(
78+
xtitle="Time (s)",
79+
ytitle="Temp. (C)",
80+
padding_top=5,
81+
padding_left=75,
82+
padding_right=5,
83+
show_legend="ul",
84+
)
85+
g.set_scan_width(600, plotid=0)
86+
g.set_data_limits(1.8 * 600, plotid=0)
87+
88+
# Output/Duty Cycle
89+
g.new_plot(ytitle="Output/Duty Cycle (%)", padding_top=5, padding_left=75, padding_right=5)
90+
91+
g.set_scan_width(600, plotid=1)
92+
g.set_data_limits(1.8 * 600, plotid=1)
93+
g.set_y_limits(min_=-2, max_=102, plotid=1)
94+
for channel in self.controller.channels:
95+
series, _ = g.new_series(plotid=0, color=channel.color, name=channel.shortname)
96+
g.new_series(plotid=0,
97+
# render_style="connectedhold",
98+
line_style='dash',
99+
color=series.color, name=f'{channel.shortname}, Setpoint')
100+
101+
g.new_series(plotid=1, name=channel.shortname, color=series.color)
102+
103+
return g
104+
105+
def get_display_channels(self):
106+
return [ci for ci in self.controller.channels if ci.display]
107+
108+
109+
110+
111+
if __name__ == '__main__':
112+
b = BakeoutManager()
113+
b.activate()
114+
b.setup_scan()
115+
116+
# ============= EOF =============================================

pychron/bakeout/tasks/__init__.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# ===============================================================================
2+
# Copyright 2024 ross
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
# ===============================================================================
16+
17+
# ============= EOF =============================================
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# ===============================================================================
2+
# Copyright 2024 ross
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
# ===============================================================================
16+
from locale import format_string
17+
18+
from click import style
19+
from pyface.tasks.traits_dock_pane import TraitsDockPane
20+
from pyface.tasks.traits_task_pane import TraitsTaskPane
21+
from traitsui.api import View, UItem, InstanceEditor, TableEditor, EnumEditor, ListEditor, ButtonEditor
22+
from traitsui.extras.checkbox_column import CheckboxColumn
23+
from traitsui.table_column import ObjectColumn
24+
25+
26+
class BakeoutGraphPane(TraitsTaskPane):
27+
28+
def traits_view(self):
29+
v = View(UItem("graph", style="custom", editor=InstanceEditor()))
30+
return v
31+
32+
class BakeoutControlPane(TraitsDockPane):
33+
name = 'Controls'
34+
id = "pychron.bakeout.control"
35+
36+
def traits_view(self):
37+
cols = [
38+
# CheckboxColumn(name='display'),
39+
CheckboxColumn(name='enabled'),
40+
ObjectColumn(name='name', editable=False),
41+
ObjectColumn(name='setpoint',
42+
format='%0.3f',
43+
editable=False),
44+
ObjectColumn(name='temperature',
45+
format='%0.3f',
46+
editable=False),
47+
ObjectColumn(name='duty_cycle',
48+
format='%0.3f',
49+
editable=False),
50+
CheckboxColumn(name='overtemp', editable=False),
51+
# ObjectColumn(name='clear_overtemp',
52+
# style='custom',
53+
# editor=ButtonEditor(),
54+
# label='Clear Over Temp.'),
55+
56+
# ObjectColumn(name='temperature_address', editable=False),
57+
# ObjectColumn(name='duty_cycle_address', editable=False),
58+
# ObjectColumn(name='setpoint_address', editable=False),
59+
]
60+
61+
edit_view = View(
62+
UItem('object.temperature'),
63+
UItem('object.clear_overtemp', style='custom'),
64+
)
65+
66+
v = View(
67+
UItem('object.controller.configuration',
68+
editor=EnumEditor(name='object.controller.configurations'),
69+
width=200),
70+
UItem("object.controller.channels", style="custom",
71+
editor=TableEditor(
72+
columns=cols,
73+
selection_mode="rows",
74+
edit_view=edit_view,
75+
orientation='vertical',
76+
selected="object.controller.selected_channel",
77+
)),
78+
# UItem(
79+
# 'object.controller.channels',
80+
# editor=ListEditor(style='custom')
81+
# )
82+
83+
)
84+
return v
85+
# ============= EOF =============================================
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# ===============================================================================
2+
# Copyright 2024 ross
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
# ===============================================================================
16+
from envisage.ui.tasks.task_factory import TaskFactory
17+
18+
from pychron.bakeout.bakeout_manager import BakeoutManager
19+
from pychron.envisage.tasks.base_task_plugin import BaseTaskPlugin
20+
21+
22+
class BakeoutPlugin(BaseTaskPlugin):
23+
id = 'pychron.bakeout.plugin'
24+
name = 'Bakeout'
25+
26+
def _tasks_default(self):
27+
return [TaskFactory(
28+
id="pychron.bakeout.task",
29+
factory=self._task_factory,
30+
name="Bakeout",
31+
image="applications-science",
32+
task_group="hardware",
33+
accelerator="Ctrl+Shift+B",
34+
)]
35+
36+
def _service_offers_default(self):
37+
""" """
38+
so = self.service_offer_factory(
39+
protocol=BakeoutManager, factory=self._factory
40+
)
41+
return [so]
42+
43+
def _factory(self):
44+
return BakeoutManager(application=self.application)
45+
46+
def _task_factory(self):
47+
from pychron.bakeout.tasks.bakeout_task import BakeoutTask
48+
return BakeoutTask(application=self.application,
49+
manager=self.application.get_service(BakeoutManager))
50+
51+
def _managers_default(self):
52+
""" """
53+
return [
54+
dict(
55+
name="bakeout",
56+
plugin_name=self.name,
57+
manager=self.application.get_service(BakeoutManager),
58+
)
59+
]
60+
# ============= EOF =============================================
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# ===============================================================================
2+
# Copyright 2024 ross
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
# ===============================================================================
16+
from pyface.tasks.task_layout import TaskLayout, PaneItem
17+
18+
from pychron.bakeout.tasks.bakeout_panes import BakeoutGraphPane, BakeoutControlPane
19+
from pychron.envisage.tasks.base_task import BaseManagerTask
20+
21+
22+
class BakeoutTask(BaseManagerTask):
23+
24+
def create_central_pane(self):
25+
return BakeoutGraphPane(model=self.manager)
26+
27+
def create_dock_panes(self):
28+
control = BakeoutControlPane(model=self.manager)
29+
return [control]
30+
31+
def _default_layout_default(self):
32+
return TaskLayout(left=PaneItem("pychron.bakeout.control"))
33+
34+
# ============= EOF =============================================

pychron/entry/tasks/basic/task.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ class BasicEntryTask(BaseManagerTask):
2828

2929
tool_bars = [SToolBar(SaveAction())]
3030

31-
def activated(self):
32-
self.manager.activated()
33-
3431
def prepare_destroy(self):
3532
self.manager.prepare_destroy()
3633

pychron/entry/tasks/project/task.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ class ProjectTask(BaseManagerTask):
2929
name = "Project Database"
3030
id = "pychron.entry.project.task"
3131

32-
def activated(self):
33-
self.manager.activated()
3432

3533
def create_central_pane(self):
3634
return ProjectPane(model=self.manager)

pychron/entry/tasks/sample/task.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,6 @@ class SampleEntryTask(BaseManagerTask):
4949
SToolBar(ImportSamplesAction(), MakeSampleTemplateAction()),
5050
]
5151

52-
def activated(self):
53-
self.manager.activated()
54-
5552
def prepare_destroy(self):
5653
self.manager.prepare_destroy()
5754

pychron/entry/tasks/sample_prep/task.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,6 @@ class SamplePrepTask(BaseManagerTask):
4141

4242
tool_bars = [SToolBar(LocateSampleAction())]
4343

44-
def activated(self):
45-
self.manager.activated()
46-
4744
def prepare_destroy(self):
4845
self.manager.prepare_destroy()
4946

0 commit comments

Comments
 (0)