vtir-wizard 1.4.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- vtir_wizard/__init__.py +34 -0
- vtir_wizard/config.py +115 -0
- vtir_wizard/data/__init__.py +2 -0
- vtir_wizard/data/vt_ir_config.ini +231 -0
- vtir_wizard/ir_plot.py +400 -0
- vtir_wizard/orchestrator.py +1465 -0
- vtir_wizard/spectra_io.py +347 -0
- vtir_wizard/temp_plot.py +444 -0
- vtir_wizard-1.4.1.dist-info/METADATA +495 -0
- vtir_wizard-1.4.1.dist-info/RECORD +13 -0
- vtir_wizard-1.4.1.dist-info/WHEEL +4 -0
- vtir_wizard-1.4.1.dist-info/entry_points.txt +2 -0
- vtir_wizard-1.4.1.dist-info/licenses/LICENSE +22 -0
vtir_wizard/__init__.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""vtir_wizard -- variable-temperature IR orchestrator for a Thermo Nicolet iS5
|
|
2
|
+
+ Specac heated Golden Gate ATR + Specac USB temperature controller.
|
|
3
|
+
|
|
4
|
+
The package exposes three entry points:
|
|
5
|
+
|
|
6
|
+
vtir_wizard.orchestrator the run wizard (``vtir-wizard`` console script)
|
|
7
|
+
vtir_wizard.temp_plot live temperature/setpoint overlay window
|
|
8
|
+
vtir_wizard.ir_plot live stacked-IR-spectrum window
|
|
9
|
+
|
|
10
|
+
Only light-weight, dependency-free shared constants live in this top-level
|
|
11
|
+
module so the plot subprocesses (which import ``SCHEDULE_KINDS``) don't drag in
|
|
12
|
+
the orchestrator's pywin32 dependency.
|
|
13
|
+
"""
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
__version__ = "1.4.1"
|
|
17
|
+
|
|
18
|
+
# Single source of truth for per-direction metadata used across the wizard
|
|
19
|
+
# summary (glyph), the per-step log line (arrow), and the live plots' overlay
|
|
20
|
+
# shading (color, label). Adding a new schedule kind means adding one row here
|
|
21
|
+
# -- not editing four sites. Background ("bg") is also listed even though it
|
|
22
|
+
# isn't a step direction, because the live plots shade BG scans too.
|
|
23
|
+
SCHEDULE_KINDS = {
|
|
24
|
+
"up": {"glyph": "^", "arrow": "Heating up to",
|
|
25
|
+
"color": (1.0, 0.2, 0.2, 0.22), "label": "Sample (up)"},
|
|
26
|
+
"down": {"glyph": "v", "arrow": "Cooling down to",
|
|
27
|
+
"color": (1.0, 0.6, 0.0, 0.25), "label": "Sample (down)"},
|
|
28
|
+
"return": {"glyph": "*", "arrow": "Cooling back to starting temperature",
|
|
29
|
+
"color": (0.2, 0.7, 0.2, 0.28), "label": "Sample (return)"},
|
|
30
|
+
"bg": {"glyph": "B", "arrow": "(background, not a step)",
|
|
31
|
+
"color": (0.2, 0.2, 1.0, 0.18), "label": "Background"},
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
__all__ = ["__version__", "SCHEDULE_KINDS"]
|
vtir_wizard/config.py
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"""Config-file discovery and loading for the pip-installed wizard.
|
|
2
|
+
|
|
3
|
+
When the project lived as loose scripts the config sat next to ``vt_ir.py``.
|
|
4
|
+
Installed via pip the package lives in a read-only ``site-packages`` directory,
|
|
5
|
+
so the editable ``vt_ir_config.ini`` must live somewhere the user owns.
|
|
6
|
+
|
|
7
|
+
Resolution order (``resolve_config_path``):
|
|
8
|
+
|
|
9
|
+
1. an explicit ``--config PATH`` (always wins)
|
|
10
|
+
2. ``./vt_ir_config.ini`` in the current folder (per-experiment configs)
|
|
11
|
+
3. ``%APPDATA%/vtir-wizard/vt_ir_config.ini`` (the per-user copy)
|
|
12
|
+
|
|
13
|
+
``vtir-wizard --init-config`` writes the packaged template to the per-user
|
|
14
|
+
location so a fresh install has something to edit.
|
|
15
|
+
"""
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import configparser
|
|
19
|
+
import os
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
from typing import Optional
|
|
22
|
+
|
|
23
|
+
APP_DIR_NAME = "vtir-wizard"
|
|
24
|
+
CONFIG_NAME = "vt_ir_config.ini"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# ---------------------------------------------------------------------------
|
|
28
|
+
# Locations
|
|
29
|
+
# ---------------------------------------------------------------------------
|
|
30
|
+
def user_config_dir() -> Path:
|
|
31
|
+
"""Per-user config directory. ``%APPDATA%/vtir-wizard`` on Windows (the
|
|
32
|
+
documented target); falls back to ``~/.config/vtir-wizard`` elsewhere so the
|
|
33
|
+
package still imports/tests on non-Windows CI."""
|
|
34
|
+
appdata = os.environ.get("APPDATA")
|
|
35
|
+
if appdata:
|
|
36
|
+
return Path(appdata) / APP_DIR_NAME
|
|
37
|
+
return Path.home() / ".config" / APP_DIR_NAME
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def user_config_path() -> Path:
|
|
41
|
+
return user_config_dir() / CONFIG_NAME
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def packaged_template_text() -> str:
|
|
45
|
+
"""The bundled template ``vt_ir_config.ini`` shipped under the package's
|
|
46
|
+
``data`` directory. Read through importlib.resources so it works from a
|
|
47
|
+
wheel, an editable install, or a source checkout."""
|
|
48
|
+
from importlib import resources
|
|
49
|
+
|
|
50
|
+
return (resources.files("vtir_wizard.data")
|
|
51
|
+
.joinpath(CONFIG_NAME)
|
|
52
|
+
.read_text(encoding="utf-8"))
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# ---------------------------------------------------------------------------
|
|
56
|
+
# Resolution + loading
|
|
57
|
+
# ---------------------------------------------------------------------------
|
|
58
|
+
def resolve_config_path(explicit: Optional[str]) -> Optional[Path]:
|
|
59
|
+
"""Return the config file to use, or ``None`` if nothing was found.
|
|
60
|
+
|
|
61
|
+
An explicit path that does not exist is a hard error (the user clearly meant
|
|
62
|
+
that file); the implicit search just falls through to the next candidate."""
|
|
63
|
+
if explicit:
|
|
64
|
+
p = Path(explicit).expanduser()
|
|
65
|
+
if not p.exists():
|
|
66
|
+
raise SystemExit(f"--config path does not exist: {p}")
|
|
67
|
+
return p
|
|
68
|
+
cwd = Path.cwd() / CONFIG_NAME
|
|
69
|
+
if cwd.exists():
|
|
70
|
+
return cwd
|
|
71
|
+
user = user_config_path()
|
|
72
|
+
if user.exists():
|
|
73
|
+
return user
|
|
74
|
+
return None
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def load_config(path: Path) -> configparser.ConfigParser:
|
|
78
|
+
cfg = configparser.ConfigParser(inline_comment_prefixes=("#", ";"))
|
|
79
|
+
cfg.read(path, encoding="utf-8")
|
|
80
|
+
return cfg
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def load_config_optional(path: Optional[Path]) -> configparser.ConfigParser:
|
|
84
|
+
"""Tolerant load used by the plot helpers: returns an empty parser if the
|
|
85
|
+
path is missing, so a standalone plot window still starts."""
|
|
86
|
+
cfg = configparser.ConfigParser(inline_comment_prefixes=("#", ";"))
|
|
87
|
+
if path and Path(path).exists():
|
|
88
|
+
cfg.read(path, encoding="utf-8")
|
|
89
|
+
return cfg
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def init_user_config(force: bool = False) -> tuple[Path, bool]:
|
|
93
|
+
"""Write the packaged template to the per-user config location.
|
|
94
|
+
|
|
95
|
+
Returns ``(path, written)`` -- ``written`` is False if the file already
|
|
96
|
+
existed and ``force`` was not given (so we never clobber a tuned config by
|
|
97
|
+
accident)."""
|
|
98
|
+
dest = user_config_path()
|
|
99
|
+
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
100
|
+
if dest.exists() and not force:
|
|
101
|
+
return dest, False
|
|
102
|
+
dest.write_text(packaged_template_text(), encoding="utf-8")
|
|
103
|
+
return dest, True
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def missing_config_message() -> str:
|
|
107
|
+
"""Actionable message when no config is found anywhere."""
|
|
108
|
+
return (
|
|
109
|
+
"No vt_ir_config.ini found.\n"
|
|
110
|
+
f"Looked for: ./{CONFIG_NAME} (current folder) and {user_config_path()}.\n"
|
|
111
|
+
"Create the per-user copy with:\n"
|
|
112
|
+
" vtir-wizard --init-config\n"
|
|
113
|
+
"then edit it (the path is printed) and re-run. Or pass an explicit\n"
|
|
114
|
+
"file with --config <path>."
|
|
115
|
+
)
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# vt_ir_config.ini -- machine-specific paths and defaults for the VT-IR wizard
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Edit the values below to match the lab PC. Most lines have a comment that
|
|
5
|
+
# explains what changes if you tweak the value. All path values are plain
|
|
6
|
+
# Windows paths (backslashes are fine -- no escaping needed in INI files).
|
|
7
|
+
# =============================================================================
|
|
8
|
+
|
|
9
|
+
[paths]
|
|
10
|
+
# ---------------------------------------------------------------------------
|
|
11
|
+
# Specac USB controller CLI. Installed by the Specac controller installer at
|
|
12
|
+
# this default location. Confirm with: where specac.cmd.exe
|
|
13
|
+
# ---------------------------------------------------------------------------
|
|
14
|
+
specac_exe = C:\Program Files (x86)\Specac\Temperature Controller\1.0\bin\specac.cmd.exe
|
|
15
|
+
|
|
16
|
+
# ---------------------------------------------------------------------------
|
|
17
|
+
# Where all collected spectra are written. One sub-folder is created per
|
|
18
|
+
# experiment, named after the sample (sanitized).
|
|
19
|
+
# ---------------------------------------------------------------------------
|
|
20
|
+
output_root = C:\Users\<you>\Documents\VT-IR\spectra
|
|
21
|
+
|
|
22
|
+
# ---------------------------------------------------------------------------
|
|
23
|
+
# Where to look for background files in sample mode. Usually the same as
|
|
24
|
+
# output_root -- BG files live in <bg_root>/<sample>/BG_<sample>_<T>C.SPA.
|
|
25
|
+
# Override only if you collect BG files in a separate location.
|
|
26
|
+
# ---------------------------------------------------------------------------
|
|
27
|
+
bg_root = C:\Users\<you>\Documents\VT-IR\spectra
|
|
28
|
+
|
|
29
|
+
# ---------------------------------------------------------------------------
|
|
30
|
+
# Where the wizard drops its timestamped session log files.
|
|
31
|
+
# ---------------------------------------------------------------------------
|
|
32
|
+
log_dir = C:\Users\<you>\Documents\VT-IR\logs
|
|
33
|
+
|
|
34
|
+
# ---------------------------------------------------------------------------
|
|
35
|
+
# Where the Specac controller GUI writes its temperature .log files.
|
|
36
|
+
# Used by the temperature overlay plot to find the active log.
|
|
37
|
+
# ---------------------------------------------------------------------------
|
|
38
|
+
specac_log_dir = C:\Users\<you>\Documents\Specac Temperature Controller\Logs
|
|
39
|
+
|
|
40
|
+
# ---------------------------------------------------------------------------
|
|
41
|
+
# Where the live overlay plot saves its SVG snapshots. Parallel to the
|
|
42
|
+
# spectra and log folders. One sub-folder per sample is created here, and
|
|
43
|
+
# snapshots are named <sample>_<BG|SAMPLE>_<timestamp>.svg so background and
|
|
44
|
+
# sample plots stay distinguishable. If left blank, defaults to a "plots"
|
|
45
|
+
# folder next to output_root.
|
|
46
|
+
# ---------------------------------------------------------------------------
|
|
47
|
+
plot_dir = C:\Users\<you>\Documents\VT-IR\plots
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
[defaults]
|
|
51
|
+
# ---------------------------------------------------------------------------
|
|
52
|
+
# Default OMNIC experiment file (.exp). Loaded once at the start of each run
|
|
53
|
+
# with the KeepBkg flag so subsequent BackgroundFileName pokes survive.
|
|
54
|
+
# ---------------------------------------------------------------------------
|
|
55
|
+
omnic_exp_file = C:\my documents\omnic\Param\VT_128_2.exp
|
|
56
|
+
|
|
57
|
+
# Default temperature program -- accepts the (Tmin,Tmax,Tstep) range syntax or
|
|
58
|
+
# a whitespace-separated list "50 75 100 150".
|
|
59
|
+
temps_default = (50,200,20)
|
|
60
|
+
|
|
61
|
+
# Allowed temperature window in C. Hard guard against typos and against
|
|
62
|
+
# exceeding the ATR cell rating.
|
|
63
|
+
tmin = 20
|
|
64
|
+
tmax = 250
|
|
65
|
+
|
|
66
|
+
# Extra dwell at each set point after the Specac CLI returns "temperature
|
|
67
|
+
# reached". Useful for letting the sample (not just the cell body) reach
|
|
68
|
+
# thermal equilibrium, and for damping any residual gradient near tolerance.
|
|
69
|
+
# Default 120 s (2 min); tune down to ~30 s for fast empty-ATR test runs.
|
|
70
|
+
equilibration_s = 120
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
[omnic]
|
|
74
|
+
# ---------------------------------------------------------------------------
|
|
75
|
+
# How long to wait for a single CollectBackground / CollectSample to finish.
|
|
76
|
+
# pywin32's DDE Exec call has a hard 60-second internal timeout, which is far
|
|
77
|
+
# shorter than a real 128-scan @ 2 cm-1 collection -- so the wizard issues
|
|
78
|
+
# collect commands with the 'Polling' keyword and waits in Python by polling
|
|
79
|
+
# OMNIC's MenuStatus. The two knobs below govern that polling loop.
|
|
80
|
+
# ---------------------------------------------------------------------------
|
|
81
|
+
# How often to query MenuStatus while waiting.
|
|
82
|
+
poll_interval_s = 2
|
|
83
|
+
|
|
84
|
+
# Hard cap on a single collection. 1800 s = 30 minutes; bump up only if your
|
|
85
|
+
# experiment file legitimately runs longer than that per spectrum.
|
|
86
|
+
collect_timeout_s = 1800
|
|
87
|
+
|
|
88
|
+
# If OMNIC refuses to START a collection (the Polling Exec blocks ~60 s and
|
|
89
|
+
# raises a DDE error -- usually the iS5 bench has gone offline / OMNIC is
|
|
90
|
+
# wedged), the orchestrator reconnects the DDE channel and retries this many
|
|
91
|
+
# times before giving up with an actionable message. Set to 0 to disable
|
|
92
|
+
# retrying. Note: a hard bench wedge usually needs OMNIC restarted; retrying
|
|
93
|
+
# only recovers transient DDE-channel glitches.
|
|
94
|
+
collect_retries = 2
|
|
95
|
+
|
|
96
|
+
# Seconds to wait between those retries.
|
|
97
|
+
retry_delay_s = 5
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
[live_plot]
|
|
101
|
+
# ---------------------------------------------------------------------------
|
|
102
|
+
# Auto-launch the temperature/setpoint overlay window when a run starts. It
|
|
103
|
+
# opens in its own console window AFTER the "Ready?" confirmation, locked onto
|
|
104
|
+
# the current sample's session folder. Close the window to dismiss it; the
|
|
105
|
+
# orchestrator continues regardless.
|
|
106
|
+
# ---------------------------------------------------------------------------
|
|
107
|
+
# Set to false to disable auto-launch (or pass --no-live-plot on the CLI; note
|
|
108
|
+
# --no-live-plot disables BOTH the temperature overlay and the IR stack window).
|
|
109
|
+
enabled = true
|
|
110
|
+
|
|
111
|
+
# Refresh interval in seconds.
|
|
112
|
+
interval_s = 5
|
|
113
|
+
|
|
114
|
+
# Estimated scan duration in seconds (used to draw the shaded scan band).
|
|
115
|
+
# 210 s ~= 128 scans @ 2 cm-1. Match this to your OMNIC .exp file.
|
|
116
|
+
scan_duration_s = 210
|
|
117
|
+
|
|
118
|
+
# How long after a run finishes the live plot waits before auto-saving its
|
|
119
|
+
# SVG snapshot. The delay lets the passive cool-down tail show up in the
|
|
120
|
+
# saved image. 600 s = 10 min. The plot ALSO saves immediately if you close
|
|
121
|
+
# its window manually.
|
|
122
|
+
save_delay_s = 600
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
[ir_plot]
|
|
126
|
+
# ---------------------------------------------------------------------------
|
|
127
|
+
# Auto-launch the live stacked-IR-spectrum window alongside the temperature
|
|
128
|
+
# overlay. It re-reads the session's .SPA files as they land and re-draws a
|
|
129
|
+
# temperature-colored waterfall of every scan so far. After each new scan it
|
|
130
|
+
# overwrites a SINGLE SVG at <plot_dir>/<sample>/<sample>_IR_stack.svg (only
|
|
131
|
+
# the final stacked spectrum persists), in the same plot_dir as the temperature
|
|
132
|
+
# snapshots.
|
|
133
|
+
# ---------------------------------------------------------------------------
|
|
134
|
+
# Set to false to disable just this window (or pass --no-ir-plot on the CLI).
|
|
135
|
+
enabled = true
|
|
136
|
+
|
|
137
|
+
# Layout: stack = fixed-offset waterfall (default)
|
|
138
|
+
# overlay = all spectra on a shared baseline
|
|
139
|
+
mode = stack
|
|
140
|
+
|
|
141
|
+
# Display unit: A = absorbance, T = %transmittance.
|
|
142
|
+
unit = A
|
|
143
|
+
|
|
144
|
+
# Refresh interval in seconds.
|
|
145
|
+
interval_s = 5
|
|
146
|
+
|
|
147
|
+
# Major x-tick spacing in cm-1 (0 = let matplotlib choose).
|
|
148
|
+
tick_step = 500
|
|
149
|
+
|
|
150
|
+
# Fixed vertical offset between stacked spectra. Leave blank for an automatic
|
|
151
|
+
# offset scaled to the data; set a number to pin it (stack mode only).
|
|
152
|
+
offset =
|
|
153
|
+
|
|
154
|
+
# Matplotlib colormap used to color spectra by temperature.
|
|
155
|
+
cmap = gnuplot2
|
|
156
|
+
|
|
157
|
+
# Figure sizing. The saved SVG's HEIGHT grows with the number of spectra so a
|
|
158
|
+
# tall stack keeps its peaks legible instead of squashing them into a fixed
|
|
159
|
+
# canvas. Raise height_per_spectrum to give each spectrum more vertical room.
|
|
160
|
+
# fig_width - figure width in inches
|
|
161
|
+
# height_per_spectrum - inches of height added per stacked scan (stack mode)
|
|
162
|
+
# max_height - cap on the saved figure height in inches
|
|
163
|
+
fig_width = 10
|
|
164
|
+
height_per_spectrum = 0.5
|
|
165
|
+
max_height = 30
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
[export]
|
|
169
|
+
# ---------------------------------------------------------------------------
|
|
170
|
+
# Every collected spectrum is always saved as OMNIC's native .SPA (needed if
|
|
171
|
+
# you ever want to re-process in OMNIC). In addition, each spectrum is saved
|
|
172
|
+
# in the formats listed below -- OMNIC picks the format from the extension.
|
|
173
|
+
#
|
|
174
|
+
# Comma-separated list of extensions (without the dot). Common choices:
|
|
175
|
+
# csv -> comma/tab-separated X,Y text (best for most plotting tools)
|
|
176
|
+
# jdx -> JCAMP-DX spectroscopy text (.dx is the same format; use 'jdx'
|
|
177
|
+
# if your reader is picky -- it's the
|
|
178
|
+
# extension OMNIC documents)
|
|
179
|
+
# tif -> image
|
|
180
|
+
# Leave blank to save ONLY .SPA. Examples: csv | csv,jdx | (blank)
|
|
181
|
+
# ---------------------------------------------------------------------------
|
|
182
|
+
additional_formats = csv
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
[backgrounds]
|
|
186
|
+
# ---------------------------------------------------------------------------
|
|
187
|
+
# How sample collections pick the background to ratio against. Backgrounds
|
|
188
|
+
# do NOT have to match the sample temperature exactly -- the heated cell sits
|
|
189
|
+
# in a controlled glovebox -- so mismatches and old backgrounds are WARNED
|
|
190
|
+
# about (and logged for the audit trail) but never block a run.
|
|
191
|
+
# ---------------------------------------------------------------------------
|
|
192
|
+
# Default temperature-matching mode (the wizard asks each run, pre-filled with
|
|
193
|
+
# this):
|
|
194
|
+
# exact - use the BG collected at each sample temperature (fails only if a
|
|
195
|
+
# temperature has no BG at all -- then it suggests closest/fixed)
|
|
196
|
+
# closest - use the nearest-temperature BG available for each step
|
|
197
|
+
# fixed - use ONE background (chosen at the prompt) for every step
|
|
198
|
+
match_mode = exact
|
|
199
|
+
|
|
200
|
+
# Warn (but never block) when a chosen background file is older than this many
|
|
201
|
+
# days. The warning is written to the run log so there is a record of exactly
|
|
202
|
+
# which (possibly old) background each measurement used.
|
|
203
|
+
max_age_warn_days = 1
|
|
204
|
+
|
|
205
|
+
# Minutes written to OMNIC's Collect/MaxBackgroundAge (with BackgroundHandling =
|
|
206
|
+
# AfterTime) so OMNIC silently reuses the background the wizard binds instead of
|
|
207
|
+
# stopping to ask "the background is old -- collect a new one?". That prompt is
|
|
208
|
+
# a modal dialog that blocks the DDE call and hangs the run, so this is set huge
|
|
209
|
+
# by default (~1.9 years). The wizard applies this over DDE every run, but the
|
|
210
|
+
# primary fix is to ALSO select "Background after N minutes" with this value in
|
|
211
|
+
# the OMNIC experiment (.exp) and SAVE it. Lower only if you actually want OMNIC
|
|
212
|
+
# to force a fresh background after some age.
|
|
213
|
+
max_bg_age_min = 999999
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
[heater]
|
|
217
|
+
# ---------------------------------------------------------------------------
|
|
218
|
+
# Specac controller settings. Applied at the start of every run.
|
|
219
|
+
# ---------------------------------------------------------------------------
|
|
220
|
+
# +/- tolerance window (in deg C) used by the "sp <T> w" wait.
|
|
221
|
+
tolerance_c = 1
|
|
222
|
+
|
|
223
|
+
# Ramp rate in C/min. Specac default 50 has been calibrated; only change with
|
|
224
|
+
# a re-calibration (the old make_temperature_program.py picked timings based on
|
|
225
|
+
# this value).
|
|
226
|
+
ramp_c_per_min = 50
|
|
227
|
+
|
|
228
|
+
# Timeout for any single "go to setpoint and wait" call, in seconds. 3600 = 1h.
|
|
229
|
+
# Generous -- a real ramp 30 -> 250 C at 50 C/min plus settling is well under
|
|
230
|
+
# 10 minutes, so this only fires if the controller hangs.
|
|
231
|
+
ramp_timeout_s = 3600
|