barsukov 0.0.5__py3-none-any.whl → 1.0.9__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.
barsukov/exp/mwHP.py CHANGED
@@ -1,357 +1,263 @@
1
- ### BEGIN Dependencies ###
2
- import numpy as np
3
- import sys
4
- from barsukov.exp.exp_utils import *
5
- ### END Dependencies
6
-
7
- # STATUS: f() finished, nor test it and then add more funcitons
8
-
9
- class mwHP:
10
- def __init__(self, gpib=None, visa_rm=None, logger=None, gpib_card=0, log='default', script=None):
11
- # Pass the Script object, if available.
12
- # If Script has no visa_rm or if no Script is passed, you'll need to pass the visa_rm=visa.ResourceManager manually.
13
- # If Script has no logger or if no Script is passed, you can pass the logger manually.
14
- # If no logger is passed, will simply print to screen.
15
- # Change log from 'default' to 'screen', 'file', 'both', 'no'.
16
- # gpib_card is per default 0. You can change, if you have multiple.
17
-
18
- self.script = script
19
- self.logger = logger
20
- self.eq_default_log = log
21
- self.rm = visa_rm
22
- self.gpib_card = gpib_card
23
- self.gpib = gpib
24
-
25
- self.msg_deco = f'[mwHP {self.gpib_card}::{self.gpib}]'
26
- #print( 'visa_rm is ', visa_rm )
27
- #print( 'script is ', script )
28
- self.eq = initialize_gpib(self) # This will initialize self.eq = visa.open_resource()
29
- self.log( f'Initialized: {self.identify()}', log='important' ) # This is the 'welcome message' and a check if communication works.
30
-
31
- self.f_digits = 9 # Digits of precision of mw frequency
32
- self.f_limits = [0.01, 20.5] # Lower and upper GHz limits
33
- self.p_digits = 1 #TODO -- Digits of precision of mw power
34
- self.p_limits = [-15.0, 17.0] #TODO -- Lower and upper __ limits
35
- self.pulsef_digits = 3 # digits in KHz
36
- self.pulsew_digits = 3 # digits in ms
37
- self.pulsef_limits = [0.016, 500]
38
- self.pulsew_limits = [0.001, 65.53] # digits in ms
39
- self.pulsedc_limits = [0, 100]
40
-
41
- ### BEGIN The definition of the following functions may be specific to this equipment.
42
- def query(self, cmd):
43
- return self.eq.query(cmd)
44
-
45
- def write(self, cmd):
46
- return self.eq.write(cmd)
47
-
48
- def identify(self):
49
- return str(self.eq.query('*IDN?'))
50
- ### END The definition of the following functions may be specific to this equipment.
51
-
52
- def log(self, msg, log=None):
53
- if log is None: log=self.eq_default_log
54
- log_in_eq(self, msg, log=log)
55
- ### END These functions could be shared across all equipment.
56
-
57
-
58
- def f(self, f=None, log=None, check=False):
59
- ### Always has a return! Which is frequency in GHz.
60
- ### f() reads and returns the frequency in GHz.
61
- ### f(10) writes frequency to 10 GHz.
62
- ### f(10) returns the frequency that was actually sent to equipment.
63
- ### f(10, check=True) returns the frequency queried after writing.
64
- ### Do set log='no' to avoid latency for repeated calls.
65
- if log is None: log=self.eq_default_log
66
- if f is None:
67
- try:
68
- y = self.eq.query('freq?')
69
- y = float(y)/1e9 # Is the frequency returned in GHz??
70
- self.log(f'Reading f as {y} GHz.', log=log)
71
- return y
72
- except:
73
- self.log(f'Error while reading Frequency.', log='important')
74
- return np.nan
75
- else:
76
- try:
77
- x = round(f, self.f_digits) # rounding the digits
78
- x = max(self.f_limits[0], min(x, self.f_limits[1])) # sets x within f_limits
79
- self.eq.write(f'freq {x} GHz')
80
- if check: y = self.f(log='no')
81
- else: y = x
82
- print(y, f)
83
- if abs(y-f)<10.0**(-self.f_digits): self.log(f'Writing f as {x}.', log=log) #################### THIS IS WRONG!!!! IT SHOULD BE abs(y-f)<(10**self.f_digits)
84
- else: self.log(f'Warning: writing Frequency as {x}, but was asked {f}.', log='important')
85
- return y
86
- except:
87
- self.log(f'Error while writing Frequency as {f}.', log='important')
88
- return np.nan
89
-
90
- def p(self, p=None, log=None, check=False):
91
- ### Always has a return! Which is the power in dBm.
92
- ### p() reads and returns the power in dBm.
93
- ### p(1) writes power to 1 dBm.
94
- ### p(1) returns the power that was actually sent to equipment.
95
- ### p(1, check=True) returns the power queried after writing
96
- ### Do set log='no' to avoid latency for repeated calls.
97
- if log is None: log=self.eq_default_log
98
- if p is None:
99
- try:
100
- y = self.eq.query('pow?')
101
- y = float(y)
102
- self.log(f'Reading p as {y} dBm.', log=log)
103
- return y
104
- except:
105
- self.log(f'Error while reading Power.', log='important')
106
- return np.nan
107
- else:
108
- try:
109
- x = round(p, self.p_digits) # rounding the digits
110
- x = max(self.p_limits[0], min(x, self.p_limits[1])) # sets x within p_limits
111
- self.eq.write(f'pow {x} dBm')
112
- if check: y = self.p(log='no')
113
- else: y = x
114
- if abs(y-p)<10**(-self.p_digits): self.log(f'Writing p as {x}.', log=log)
115
- else: self.log(f'Warning: writing Power as {x}, but was asked {p}.', log='important')
116
- return y
117
- except:
118
- self.log(f'Error while writing Power as {p}.', log='important')
119
- return np.nan
120
-
121
- def output(self, state=None, log=None, check=False):
122
- ### Always has a return! Which is the state of Output.
123
- ### output() reads and returns the state of Output.
124
- ### output(1) writes state of Output to ON.
125
- ### output(1) returns the state that was actually sent to equipment.
126
- ### output(1, check=True) returns the state queried after writing
127
- if log is None: log=self.eq_default_log
128
- if state is None:
129
- try:
130
- y = self.eq.query('output?')
131
- y = int(y)
132
- self.log(f'Output is {y}.')
133
- return y
134
- except:
135
- self.log(f'Error while reading Output.', log='important')
136
- return np.nan
137
- else:
138
- if (state == 1) or (state == 'on') or (state=='ON') or (state=='On'): sstate = 1
139
- else: sstate = 0
140
- try:
141
- self.eq.write(f'output {sstate}')
142
- if check: y=self.output(log='no')
143
- else: y = sstate
144
- if y == state: self.log(f'Output set to {sstate}.')
145
- else: self.log(f'Warning: Setting Output to {sstate}, but was asked for {state}.')
146
- return y
147
- except:
148
- self.log(f'Error while changing Output state.', log='important')
149
- return np.nan
150
-
151
- #def sweep(self, mode, state=None, step=None, dwell=None, minm=None, maxm=None, log=None, check=False):
152
- #if log is None: log=self.eq_default_log
153
- #if (mode == 'pow') or (mode == 'freq'): ### Sweep function can write to power or frequency
154
- #if state is None: ### sweep(pow) or sweep(freq) reads and returns if the sweep mode is on or off
155
- #try:
156
- #y = self.eq.query(f'{mode} swe?')
157
- #y = float(y)
158
- #self.log(f'{mode} Sweep state is {y}.')
159
- #return y
160
- #except:
161
- #self.log(f'Error while reading {mode} Sweep state.', log='important')
162
- #return np.nan
163
- #else:
164
- #if (state == 1) or (state == 'on') or (state=='ON') or (state=='On'): sstate = 'swe' ### sweep(pow, 1) or sweep (freq, 1) turns the sweep mode for pow/freq ON
165
- #else: sstate = 'fix'
166
- #try:
167
- #self.eq.write(f'{mode} {sstate}')
168
- #if check: y=self.output(log='no')
169
- #else: y = sstate
170
- #if y == state:
171
- #self.log(f'{mode} Sweep state set to {sstate}.')
172
- #if (step=None) or (dwell=None) or (maxm=None) or (minm=None):
173
- #self.log(f'Warning: missing arguements to conduct {mode} Sweep.') ### indicates that while power mode on, sweep
174
- #else:
175
- #if (mode == 'pow'): level = 'dBm'
176
- #elif (mode == 'freq'): level = 'GHz'
177
- #dwellunit = 'us' ### is it in microseconds?
178
- #self.eq.write(f'{mode} step {step} {level})
179
- #self.eq.write(f'{mode} dwel1 {dwell} {dwellunit})
180
- #self.eq.write(f'{mode} star {minm} {level}')
181
- #self.eq.write(f'{mode} stop {maxm} {level}')
182
- ### write checks to see if values are actually written to Output
183
- #self.eq.write(f'init imm')
184
- #return y
185
- #else:
186
- #self.log(f'Warning: Setting {mode} Sweep state to {sstate}, but was asked for {state}.')
187
- #return y
188
- #except:
189
- #self.log(f'Error while changing {mode} Sweep state.', log='important')
190
- #return np.nan
191
- #else:
192
- #self.log(f'Warning: mode for sweep was not specified.', log=log)
193
- #return np.nan
194
-
195
-
196
-
197
-
198
- def pulse(self, f=None, duty=None, log=None):
199
- if log is None: log=self.eq_default_log
200
- if f is None and duty is None:
201
- T = float(self.eq.query('puls:per?')) * 10.0**3
202
- f = 1.0 / T
203
- w = float(self.eq.query('puls:widt?')) * 10.0**3
204
- duty = w / T * 100.0
205
- y = self.eq.query('pulm:stat?')
206
- y = int(y)
207
- x = self.eq.query('pulm:sour?')
208
- x = x[:-1].lower()
209
- self.log(f'Pulse Frequency {f} KHz, duty-cycle {duty}%. state {y}, source {x}.', log=log)
210
- return f, duty
211
-
212
- else:
213
- if f is None and duty is not None:
214
- duty_write = max(self.pulsedc_limits[0], min(float(duty), self.pulsedc_limits[1]))
215
- T = float(self.eq.query('puls:per?')) * 10.0**3
216
- w = duty_write * T / 100.0
217
- self.eq.write(f'puls:widt {w} ms')
218
-
219
- elif f is not None and duty is None:
220
- f_write = max(self.pulsef_limits[0], min(float(f), self.pulsef_limits[1]))
221
- duty_write = 50.0
222
- T = 1.0 / f
223
- w = duty_write * T / 100.0
224
- self.eq.write(f'puls:per {T} ms')
225
- self.eq.write(f'puls:widt {w} ms')
226
-
227
- elif f is not None and duty is not None:
228
- f_write = max(self.pulsef_limits[0], min(float(f), self.pulsef_limits[1]))
229
- duty_write = max(self.pulsedc_limits[0], min(float(duty), self.pulsedc_limits[1]))
230
- T = 1.0 / f
231
- w = duty_write * T / 100.0
232
- self.eq.write(f'puls:per {T} ms')
233
- self.eq.write(f'puls:widt {w} ms')
234
-
235
- check = self.pulse()
236
- return check
237
-
238
-
239
- #def pulse(self, on_off=None, freq=None, duty_cycle=None, int_ext=None, log=None):
240
- ### Always has a return! Which is the state, freq, duty cycle, and source of pulse
241
- ### Frequency in KHz, Duty Cycle in %, source int(ernal) or ext(ernal)
242
- ### pulse() reads and returns state, frequency, duty cycle, and source of pulse
243
- ### pulse(1,1,50,int) writes state ON, frequency 1KHz, duty cycle 50%, and internal mode to Pulse
244
- ### pulse(1,1,50,int) returns the state, frequency, duty cycle, and source that was actually sent to the equipment
245
- ### pulse(1,1,50,int) returns the state, frequency, duty cycle, and source queried after writing
246
- #if log is None: log=self.eq_default_log
247
- #if (on_off is None) and (freq is None) and (duty_cycle is None) and (int_ext is None):
248
- ### Accesser Code - returns whats on equipment object
249
- #try:
250
- #y = self.eq.query('pulm:stat?')
251
- #y = int(y)
252
- #f = float(self.eq.query('puls:freq?')) / 10.0**3
253
- # returns in Khz
254
- #dc = float(self.eq.query('puls:widt?')) * f * 10.0**5
255
- # returns in %
256
- #x = self.eq.query('pulm:sour?')
257
- #x = x[:-1].lower()
258
- # returns in lowercase
259
- #self.log(f'Pulse state is {y}, frequency {f} KHz, duty-cycle {dc}%, source {x}.', log=log)
260
- #return [y, f, dc, x]
261
- #except:
262
- #self.log(f'Error while reading Pulse state.', log='important')
263
- #return np.nan
264
- #else:
265
- ### Mutator Code - Writes to equipment object
266
- #if (on_off == 1) or (on_off == 'on') or (on_off=='ON') or (on_off=='On'): state = 1
267
- #else: state = 0
268
- #error = False
269
- #if (int_ext == 'int') or (int_ext == 'ext') or (int_ext == 'INT') or (int_ext == 'EXT'):
270
- ### writes mode (int/ext)
271
- #try:
272
- #self.eq.write(f'pulm:sour {int_ext}')
273
- #y = self.eq.query('pulm:sour?')
274
- #y = y[:-1].lower()
275
- #if (str(y) == str(int_ext.lower())): self.log(f'Setting Pulse to {int_ext}.', log=log)
276
- #else: self.log(f'Warning:Setting Pulse to {y[3]}, but was asked {int_ext}.', log='important')
277
- #except:
278
- #self.log(f'Error while changing Pulse Source.', log='important')
279
- #return np.nan
280
- #elif (int_ext is not None): self.log(f'Error: Invalid Pulse Source.', log='important')
281
- #if (freq is None) and (duty_cycle is not None):
282
- ### if frequency and duty cycle not in ratio, changes duty cycle to acceptable value
283
- #try:
284
- #writeduty_cycle = float(duty_cycle)
285
- #writeduty_cycle = max(self.pulsedc_limits[0], min(writeduty_cycle, self.pulsedc_limits[1])) # sets writeduty_cycle within pulsedc_limits
286
- #y = float(self.eq.query(f'puls:freq?')) / 1000.0 #returns in KHz
287
- #writefreq = y
288
- #width = writeduty_cycle * 0.01 / writefreq # units of ms
289
- #width = max(self.pulsew_limits[0], min(width, self.pulsew_limits[1]))
290
- #wdth = ceil(width * 1000.0) / 1000.0
291
- #idth = round(width, self.pulsew_digits)
292
- #lf.eq.write(f'puls:widt {width} ms')
293
- #except:
294
- #self.log(f'Error while changing Duty Cycle within limits.', log='important')
295
- #error = True
296
- #return np.nan
297
- #elif (duty_cycle is None) and (freq is not None):
298
- ### if frequency and duty cycle not in ratio, changes frequency to acceptable value
299
- # try:
300
- # writeduty_cycle = 50.0
301
- # writefreq = round(freq, self.pulsef_digits) # rounding the digits
302
- # writefreq = max(self.pulsef_limits[0], min(writefreq, self.pulsef_limits[1])) # sets writeduty_cycle within pulsedc_limits
303
- # print(writefreq)
304
- # width = writeduty_cycle * 0.01 / writefreq # units of ms
305
- # width = max(self.pulsew_limits[0], min(width, self.pulsew_limits[1]))
306
- # width = ceil(width * 1000.0) / 1000.0
307
- #width = round(width, self.pulsew_digits)
308
- # print(width)
309
- # self.eq.write(f'puls:freq {writefreq} KHz')
310
- # self.eq.write(f'puls:widt {width} ms')
311
- # except:
312
- # print(width)
313
- # self.log(f'Error while changing Pulse Frequency within limits.', log='important')
314
- # error = True
315
- # return np.nan
316
- #elif (freq is not None) and (duty_cycle is not None):
317
- ### writing both duty cycle and frequency
318
- # writeduty_cycle = float(duty_cycle) # rounding the digits
319
- # writeduty_cycle = max(self.pulsedc_limits[0], min(writeduty_cycle, self.pulsedc_limits[1])) # sets writeduty_cycle within pulsedc_limits
320
- # writefreq = round(freq, self.pulsef_digits) # rounding the digits
321
- # writefreq = max(self.pulsef_limits[0], min(writefreq, self.pulsef_limits[1])) # sets writeduty_cycle within pulsedc_limits
322
- # try:
323
- # width = writeduty_cycle * 0.01 / writefreq # units of ms
324
- #width = max(self.pulsew_limits[0], min(width, self.pulsew_limits[1]))
325
- # width = ceil(width * 1000.0) / 1000.0
326
- # width = round(width, self.pulsew_digits)
327
- #self.eq.write(f'puls:freq {writefreq} KHz')
328
- #self.eq.write(f'puls:widt {width} ms')
329
- #xcept:
330
- # self.log(f'Error while writing Duty Cycle.', log='important')
331
- # self.log(f'Error while writing Pulse Frequency.', log='important')
332
- # error = True
333
- # return np.nan
334
- #y = self.pulse(log='no')
335
- ### returns the actual parameters written to machine to be compared
336
- #if (freq is not None) and (error == False):
337
- ### Checker Code
338
- # if abs(y[1] - freq)< 10**(-self.pulsef_digits): self.log(f'Writing Pulse Frequency as {y[1]}.', log=log)
339
- # else: self.log(f'Warning:Writing Pulse Frequency as {y[1]}, but was asked {freq}.', log='important')
340
- #if (duty_cycle is not None) and (error == False):
341
- ### Checker Code
342
- # if abs(y[2] - duty_cycle)<10**(-3): self.log(f'Writing Pulse duty cycle as {y[2]}.', log=log)
343
- # else: self.log(f'Warning:Writing Pulse duty cycle as {y[2]}, but was asked {duty_cycle}.', log='important')
344
- #if (on_off is not None):
345
- # try:
346
- # self.eq.write(f'pulm:stat {on_off}')
347
- # x = self.eq
348
- # y = self.pulse(log='no')
349
- # if y[0] == state: self.log(f'Pulse state set to {on_off}.')
350
- # else: self.log(f'Warning: Setting Pulse state to {sstate}, but was asked for {on_off}.')
351
- #xept:
352
- # self.log(f'Error while changing Pulse state.', log='important')
353
- # error = True
354
- # return np.nan
355
- #if (error == False): return y
356
- #else: return np.nan
357
-
1
+ ### BEGIN Dependencies ###
2
+ import numpy as np
3
+ import sys
4
+ from barsukov.exp.exp_utils import *
5
+ ### END Dependencies
6
+
7
+
8
+ class mwHP:
9
+ def __init__(self, gpib=None, visa_rm=None, logger=None, gpib_card=0, log='default', script=None):
10
+ # Pass the Script object, if available.
11
+ # If Script has no visa_rm or if no Script is passed, you'll need to pass the visa_rm=visa.ResourceManager manually.
12
+ # If Script has no logger or if no Script is passed, you can pass the logger manually.
13
+ # If no logger is passed, will simply print to screen.
14
+ # Change log from 'default' to 'screen', 'file', 'both', 'no'.
15
+ # gpib_card is per default 0. You can change, if you have multiple.
16
+
17
+ self.script = script
18
+ self.logger = logger
19
+ self.eq_default_log = log
20
+ self.rm = visa_rm
21
+ self.gpib_card = gpib_card
22
+ self.gpib = gpib
23
+
24
+ self.msg_deco = f'[mwHP {self.gpib_card}::{self.gpib}]'
25
+ self.eq = initialize_gpib(self) # This will initialize self.eq = visa.open_resource()
26
+ self.log( f'Initialized: {self.identify()}', log='important' ) # This is the 'welcome message' and a check if communication works.
27
+
28
+ self.f_digits = 9 # Digits of precision of mw frequency
29
+ self.f_limits = [0.01, 20.5] # Lower and upper GHz limits
30
+ self.p_digits = 1 # Digits of precision of mw power
31
+ self.p_limits = [-15.0, 17.0] # Lower and upper dBm limits
32
+ self.phase_limits = [0.0, 360.0]
33
+ self.pulsef_limits = [0.016, 500]
34
+ self.pulsedc_limits = [0, 100] # Lower and upper % limits
35
+
36
+
37
+ ### BEGIN The definition of the following functions may be specific to this equipment.
38
+ def query(self, cmd):
39
+ return self.eq.query(cmd)
40
+
41
+ def write(self, cmd):
42
+ return self.eq.write(cmd)
43
+
44
+ def identify(self):
45
+ return str(self.eq.query('*IDN?'))
46
+ ### END The definition of the following functions may be specific to this equipment.
47
+ def disconnect(self):
48
+ eq_disconnect(self)
49
+
50
+ def reconnect(self):
51
+ eq_reconnect(self)
52
+
53
+ def log(self, msg, log=None):
54
+ if log is None: log=self.eq_default_log
55
+ log_in_eq(self, msg, log=log)
56
+ ### END These functions could be shared across all equipment.
57
+
58
+ def output(self, state=None, log=None, check=False):
59
+ ### Always has a return! Which is the state of Output.
60
+ ### output() reads and returns the state of Output.
61
+ ### output(1) writes state of Output to ON.
62
+ ### output(1) returns the state that was actually sent to equipment.
63
+ ### output(1, check=True) returns the state queried after writing
64
+ if log is None: log=self.eq_default_log
65
+ if state is None:
66
+ try:
67
+ y = self.eq.query('output?')
68
+ y = int(y)
69
+ self.log(f'Output is {y}.')
70
+ return y
71
+ except:
72
+ self.log(f'Error while reading Output.', log='important')
73
+ return np.nan
74
+ else:
75
+ if (state == 1) or (state == 'on') or (state=='ON') or (state=='On'): sstate = 1
76
+ else: sstate = 0
77
+ try:
78
+ self.eq.write(f'output {sstate}')
79
+ if check: y=self.output(log='no')
80
+ else: y = sstate
81
+ if y == state: self.log(f'Output set to {sstate}.')
82
+ else: self.log(f'Warning: Setting Output to {sstate}, but was asked for {state}.')
83
+ return y
84
+ except:
85
+ self.log(f'Error while changing Output state.', log='important')
86
+ return np.nan
87
+
88
+
89
+ def f(self, f=None, log=None, check=False):
90
+ ### Always has a return! Which is frequency in GHz.
91
+ ### f() reads and returns the frequency in GHz.
92
+ ### f(10) writes frequency to 10 GHz.
93
+ ### f(10) returns the frequency that was actually sent to equipment.
94
+ ### f(10, check=True) returns the frequency queried after writing.
95
+ ### Do set log='no' to avoid latency for repeated calls.
96
+ if log is None: log=self.eq_default_log
97
+ if f is None:
98
+ try:
99
+ y = self.eq.query('freq?')
100
+ y = float(y)/1e9 # Is the frequency returned in GHz??
101
+ self.log(f'Reading f as {y} GHz.', log=log)
102
+ return y
103
+ except:
104
+ self.log(f'Error while reading Frequency.', log='important')
105
+ return np.nan
106
+ else:
107
+ try:
108
+ x = round(f, self.f_digits) # rounding the digits
109
+ x = max(self.f_limits[0], min(x, self.f_limits[1])) # sets x within f_limits
110
+ self.eq.write(f'freq {x} GHz')
111
+ if check: y = self.f(log='no')
112
+ else: y = x
113
+ if abs(y-f)<10.0**(-self.f_digits): self.log(f'Writing f as {x}.', log=log)
114
+ else: self.log(f'Warning: writing Frequency as {x}, but was asked {f}.', log='important')
115
+ return y
116
+ except:
117
+ self.log(f'Error while writing Frequency as {f}.', log='important')
118
+ return np.nan
119
+
120
+
121
+ def p(self, p=None, log=None, check=False):
122
+ ### Always has a return! Which is the power in dBm.
123
+ ### p() reads and returns the power in dBm.
124
+ ### p(1) writes power to 1 dBm.
125
+ ### p(1) returns the power that was actually sent to equipment.
126
+ ### p(1, check=True) returns the power queried after writing
127
+ ### Do set log='no' to avoid latency for repeated calls.
128
+ if log is None: log=self.eq_default_log
129
+ if p is None:
130
+ try:
131
+ y = self.eq.query('pow?')
132
+ y = float(y)
133
+ self.log(f'Reading p as {y} dBm.', log=log)
134
+ return y
135
+ except:
136
+ self.log(f'Error while reading Power.', log='important')
137
+ return np.nan
138
+ else:
139
+ try:
140
+ x = round(p, self.p_digits) # rounding the digits
141
+ x = max(self.p_limits[0], min(x, self.p_limits[1])) # sets x within p_limits
142
+ self.eq.write(f'pow {x} dBm')
143
+ if check: y = self.p(log='no')
144
+ else: y = x
145
+ if abs(y-p)<10**(-self.p_digits): self.log(f'Writing p as {x}.', log=log)
146
+ else: self.log(f'Warning: writing Power as {x}, but was asked {p}.', log='important')
147
+ return y
148
+ except:
149
+ self.log(f'Error while writing Power as {p}.', log='important')
150
+ return np.nan
151
+
152
+
153
+ def sweep(self, start, stop, step, dwell, mode, log=None):
154
+ if log is None: log=self.eq_default_log
155
+ units, write_start, write_stop, mode = '', start, stop, mode.lower()
156
+ if (mode == 'freq') or (mode == 'frequency') or (mode == 'f'):
157
+ write_start = max(self.f_limits[0], min(write_start, self.f_limits[1]))
158
+ write_stop = max(self.f_limits[0], min(write_stop, self.f_limits[1]))
159
+ mode = 'Frequency'
160
+ units = 'GHz'
161
+ if (mode == 'pow') or (mode == 'power') or (mode == 'p'):
162
+ write_start = max(self.p_limits[0], min(write_start, self.p_limits[1]))
163
+ write_stop = max(self.p_limits[0], min(write_stop, self.p_limits[1]))
164
+ mode = 'Power'
165
+ units = 'dBm'
166
+ if (write_start != start):
167
+ self.log(f'Warning: Writing {mode} Sweep start to {write_start} but was asked {start}.', log='important')
168
+ if (write_stop != stop):
169
+ self.log(f'Warning: Writing {mode} Sweep stop to {write_stop} but was asked {stop}.', log='important')
170
+ try:
171
+ self.log(f'{mode} Sweep parameters are start: {write_start} {units}, stop: {write_stop} {units}, step: {step} {units}, dwell: {dwell} s.', log=log)
172
+ self.log(f'Initiating {mode} Sweep: ', log=log)
173
+ from time import sleep
174
+ for point in np.arange(write_start, write_stop+(step/2.0), step):
175
+ if mode == 'Frequency':
176
+ self.f(f=point)
177
+ elif mode == 'Power':
178
+ self.p(p=point)
179
+ sleep(dwell)
180
+ self.log(f'{mode} Sweep completed.', log=log)
181
+ except:
182
+ self.log(f'Error while conducting Sweep.', log='important')
183
+ return np.nan
184
+
185
+
186
+ def pulse(self, f=None, duty=None, log=None):
187
+ if log is None: log=self.eq_default_log
188
+ if f is None and duty is None:
189
+ try:
190
+ T = float(self.eq.query('puls:per?')) * 10.0**3
191
+ f = 1.0 / T
192
+ w = float(self.eq.query('puls:widt?')) * 10.0**3
193
+ duty = w / T * 100.0
194
+ y = self.eq.query('pulm:stat?')
195
+ y = int(y)
196
+ x = self.eq.query('pulm:sour?')
197
+ x = x[:-1].lower()
198
+ self.log(f'Pulse Frequency {f} KHz, duty-cycle {duty}%. state {y}, source {x}.', log=log)
199
+ return f, duty
200
+ except:
201
+ self.log(f'Error while reading Pulse state.', log='important')
202
+ return np.nan
203
+ else:
204
+ if duty is None: duty = 50.0
205
+ try:
206
+ if f is None and duty != 50.0:
207
+ duty_write = max(self.pulsedc_limits[0], min(float(duty), self.pulsedc_limits[1]))
208
+ T = float(self.eq.query('puls:per?')) * 10.0**3
209
+ w = duty_write * T / 100.0
210
+ self.eq.write(f'puls:widt {w} ms')
211
+ elif f is not None and duty == 50.0:
212
+ f_write = max(self.pulsef_limits[0], min(float(f), self.pulsef_limits[1]))
213
+ duty_write = duty
214
+ T = 1.0 / f_write
215
+ w = duty_write * T / 100.0
216
+ self.eq.write(f'puls:per {T} ms')
217
+ self.eq.write(f'puls:widt {w} ms')
218
+ else:
219
+ f_write = max(self.pulsef_limits[0], min(float(f), self.pulsef_limits[1]))
220
+ duty_write = max(self.pulsedc_limits[0], min(float(duty), self.pulsedc_limits[1]))
221
+ T = 1.0 / f_write
222
+ w = duty_write * T / 100.0
223
+ self.eq.write(f'puls:per {T} ms')
224
+ self.eq.write(f'puls:widt {w} ms')
225
+ except:
226
+ self.log(f'Error while writing pulse frequency as {f} and duty cycle as {duty}', log='important')
227
+ return np.nan
228
+ freal, dutyreal = self.pulse()
229
+ if abs(freal - f) < 0.10*float(f): self.log(f'Writing Pulse Frequency as {freal}.', log=log)
230
+ else: self.log(f'Warning:Writing Pulse Frequency as {freal}, but was asked {f}.', log='important')
231
+ if abs(dutyreal - duty) < 0.03*float(duty): self.log(f'Writing Pulse duty cycle as {dutyreal}.', log=log)
232
+ else: self.log(f'Warning:Writing Pulse duty cycle as {dutyreal}, but was asked {duty}.', log='important')
233
+ return freal, dutyreal
234
+
235
+
236
+ ### BEGIN: OBJ2FILE Tools
237
+ # Prepares the Script object for serialization by removing non-seriable attributes (e.g. logger and rm).
238
+ # Returns:
239
+ # dict: A dictionary representing the serializable state of the Script object.
240
+ def __getstate__(self):
241
+ seriable_data = self.__dict__.copy()
242
+ # take the attributes of unseriable data
243
+ if self.script is None:
244
+ seriable_data['logger'] == 'needsrebuild'
245
+ seriable_data['logger_information'] = self.logger.__getargs__()
246
+ else:
247
+ seriable_data['script'] == 'needsrebuild'
248
+ seriable_data['script_information'] = self.script.__getstate__()
249
+ seriable_data['rm'] = None
250
+ seriable_data['eq'] = None
251
+ return seriable_data
252
+
253
+
254
+ def __setstate__(self, seriable_data):
255
+ from barsukov.script import Script
256
+ from barsukov.logger import Logger
257
+ self.__dict__.update(seriable_data)
258
+ if self.script == 'needsrebuild':
259
+ self.script = Script(**seriable_data['script_information'])
260
+ if self.logger == 'needsrebuild':
261
+ self.logger = Logger(**seriable_data['logger_information'])
262
+ eq_reconnect(self)
263
+ ### END: OBJ2FILE Tools