-
Notifications
You must be signed in to change notification settings - Fork 86
/
Copy pathTriton.py
213 lines (174 loc) · 8.1 KB
/
Triton.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# This Python file uses the following encoding: utf-8
# Etienne Dumur <[email protected]>, october 2020
import os
from typing import Optional
import pandas as pd
import subprocess
import time
from qcodes.instrument.base import Instrument
class Triton(Instrument):
"""
This is the QCoDeS python driver to extract the temperature and pressure
from a Oxford Triton fridge.
"""
def __init__(self, name: str, file_path: str, converter_path: str,
threshold_temperature: float = 4, conversion_timer: float = 30,
magnet: bool = False, **kwargs) -> None:
"""
QCoDeS driver for Oxford Triton fridges.
! This driver get parameters from the fridge log files.
! It does not interact with the fridge electronics.
Since Oxford fridges use binary format for their log file "vcl", this
driver convert vcl log files into csv files before returning fridge
parameters.
The conversion is done by using a binary file named
"VCL_2_ASCII_CONVERTER.exe" that is provided by Oxford Instrument along
with other binaries to handle the fridge log files.
You must provide a valid path toward the VCL converter and consequently
we advice users to make sure the converter is always reachable by the
driver.
Args:
name: Name of the instrument.
file_path: Path of the vcl log file.
converter_path: Path of the vcl converter file.
threshold_temperature: Threshold temperature of
the mixing chamber thermometers.
Defaults to 4K.
Below, the temperature is read from the RuO2.
Above, the temperature is read from the cernox.
conversion_timer: Time between two vcl conversions.
Defaults to 30s.
magnet: Is there a magnet in the fridge.
Default True.
"""
if not os.path.isfile(converter_path):
raise ValueError('converter_path is not a valid file path.')
if not os.path.isfile(file_path):
raise ValueError('file_path is not a valid file path.')
super().__init__(name=name, **kwargs)
self.file_path = os.path.abspath(file_path)
self.threshold_temperature = threshold_temperature
self.converter_path = os.path.abspath(converter_path)
self.conversion_timer = conversion_timer
self._timer = time.time()
self.add_parameter(name='pressure_condensation_line',
unit='Bar',
get_parser=float,
get_cmd=lambda: self.get_pressure('condensation'),
docstring='Pressure of the condensation line',)
self.add_parameter(name='pressure_mixture_tank',
unit='Bar',
get_parser=float,
get_cmd=lambda: self.get_pressure('tank'),
docstring='Pressure of the mixture tank',)
self.add_parameter(name='pressure_forepump_back',
unit='Bar',
get_parser=float,
get_cmd=lambda: self.get_pressure('forepump'),
docstring='Pressure of the forepump back',)
self.add_parameter(name='temperature_50k_plate',
unit='K',
get_parser=float,
get_cmd=lambda: self.get_temperature('50k'),
docstring='Temperature of the 50K plate',)
self.add_parameter(name='temperature_4k_plate',
unit='K',
get_parser=float,
get_cmd=lambda: self.get_temperature('4k'),
docstring='Temperature of the 4K plate',)
if magnet:
self.add_parameter(name='temperature_magnet',
unit='K',
get_parser=float,
get_cmd=lambda: self.get_temperature('magnet'),
docstring='Temperature of the magnet',)
self.add_parameter(name='temperature_still',
unit='K',
get_parser=float,
get_cmd=lambda: self.get_temperature('still'),
docstring='Temperature of the still',)
self.add_parameter(name='temperature_100mk',
unit='K',
get_parser=float,
get_cmd=lambda: self.get_temperature('100mk'),
docstring='Temperature of the 100mk plate',)
self.add_parameter(name='temperature_mixing_chamber',
unit='K',
get_parser=float,
get_cmd=lambda: self.get_temperature('mc'),
docstring='Temperature of the mixing chamber',)
self.connect_message()
def vcl2csv(self) -> Optional[str]:
"""
Convert vcl file into csv file using proprietary binary exe.
The executable is called through the python subprocess library.
To avoid to frequent file conversion, a timer of self.conversion_timer
second is used.
Returns:
str: The output of the bash command
"""
conversion = False
if self._timer+self.conversion_timer <= time.time():
conversion = True
elif not os.path.isfile(self.file_path[:-3]+'txt'):
conversion = True
if conversion:
self._timer = time.time()
# Run a bash command to convert vcl into csv
cp = subprocess.run([self.converter_path, self.file_path],
stdout=subprocess.PIPE,
universal_newlines=True,
shell=True)
return cp.stdout
else:
return None
def get_temperature(self, channel: str) -> float:
"""
Return the last registered temperature of the channel.
Args:
channel: Channel from which the temperature is extracted.
Returns:
temperature: Temperature of the channel in Kelvin.
"""
# Convert the vcl file into csv file
self.vcl2csv()
df = pd.read_csv(self.file_path[:-3]+'txt', delimiter="\t")
if channel == '50k':
return df.iloc[-1]['PT1 Plate T(K)']
elif channel == '4k':
return df.iloc[-1]['PT2 Plate T(K)']
elif channel == 'magnet':
return df.iloc[-1]['Magnet T(K)']
elif channel == 'still':
return df.iloc[-1]['Still T(K)']
elif channel == '100mk':
return df.iloc[-1]['100mK Plate T(K)']
elif channel == 'mc':
# There are two thermometers for the mixing chamber.
# Depending of the threshold temperature we return one or the other
temp = df.iloc[-1]['MC cernox T(K)']
if temp > self.threshold_temperature:
return temp
else:
return df.iloc[-1]['MC RuO2 T(K)']
else:
raise ValueError('Unknown channel: '+channel)
def get_pressure(self, channel: str) -> float:
"""
Return the last registered pressure of the channel.
Args:
channel: Channel from which the pressure is extracted.
Returns:
pressure: Pressure of the channel in Bar.
"""
# Convert the vcl file into csv file
self.vcl2csv()
df = pd.read_csv(self.file_path[:-3]+'txt', delimiter="\t")
if channel == 'condensation':
return df.iloc[-1]['P2 Condense (Bar)']
elif channel == 'tank':
return df.iloc[-1]['P1 Tank (Bar)']
elif channel == 'forepump':
return df.iloc[-1]['P5 ForepumpBack (Bar)']
else:
raise ValueError('Unknown channel: '+channel)