barsukov 0.0.4__py3-none-any.whl → 1.0.8__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.

Potentially problematic release.


This version of barsukov might be problematic. Click here for more details.

barsukov/logger.py CHANGED
@@ -1,123 +1,127 @@
1
- ### BEGIN Dependencies ###
2
- import os
3
- from barsukov.time import time_stamp
4
- ### END Dependencies ###
5
-
6
- class Logger:
7
- """
8
- ### Don't create multiple Logger objects.
9
- ### Logger can be opened and closed with start() and close() methods.
10
- ### Restarting the logger will log to the same file, unless self.full_file_path has been changed by hand.
11
- ### start=True will start the logger automatically, but be careful
12
- ### about the full_folder_path=os.getcwd() in init.
13
- ### Log options are 'screen', 'file', 'both', 'no'. The logger default is 'both'.
14
- ### The log='important' is for the Logger.log() method only. Try not to use it.
15
- ### Default hyerarchy is logger-default overriden by object-default overriden by instance.
16
- ### Instances, that log errors, will usually use 'both'.
17
- ###
18
- """
19
- def __init__(self,
20
- description=None, # Will be passed by Script. If not, write a brief description!
21
- full_folder_path=os.getcwd(), # Will be passed by Script. If not, specify!
22
- full_file_path=None, # Specify only if you want to log into an already existing file.
23
- log='both', # Logger default will be passed by Script. If not, you may choose to change.
24
- start_file=True
25
- ):
26
-
27
- ### Initializing all variables before setting/getting them ###
28
- self.full_file_path = full_file_path # If changed by hand later, needs start() to take effect
29
- self.description = description # If changed by hand later, needs set_full_file_path and start() to take effect
30
- self.log_mode = log # Default log mode can be changed by hand any time, no restart needed.
31
-
32
- if self.full_file_path is not None:
33
- self.full_folder_path = None
34
- else:
35
- self.full_folder_path = full_folder_path # If changed by hand later, needs set_full_file_path and start() to take effect
36
- self.set_full_file_path(description=description, full_folder_path=full_folder_path)
37
-
38
- self.file_error = False # If a problem with file, will be set to True. Just in case for later.
39
- # If problem is remedied, you need to set file_error to False by hand.
40
-
41
- #
42
- if start_file:
43
- self.start_file()
44
- else:
45
- self.file = None
46
-
47
- self.log(f'Logger initialization complete.', log='important')
48
-
49
- def set_full_file_path(self, description=None, full_folder_path=None):
50
- ### Checking if optional arguments are filled or if defaults are provided ###
51
- if description is None:
52
- description = self.description
53
- if full_folder_path is None:
54
- full_folder_path = self.full_folder_path
55
- #
56
- ### Create a file name like log_timeStamp_description_.txt ###
57
- if not (description is None or description == ''):
58
- description = '_' + description
59
- else:
60
- description = ''
61
- file_name = 'log_' + time_stamp() + description + '_.txt'
62
- #print(file_name)
63
- #print(full_folder_path)
64
- self.full_file_path = os.path.join(full_folder_path, file_name)
65
-
66
- def start_file(self):
67
- try:
68
- self.file = open(self.full_file_path, 'a')
69
- self.log('Logging file started.', log='important')
70
- except:
71
- print(f'{time_stamp()} Logger failed to open the log file \"{self.full_file_path}\".', log='important')
72
-
73
- def close_file(self): # If closed, you'll need to restart before logging.
74
- self.log('Logger is closing log file.', log='important')
75
- self.file.close()
76
- self.file = None
77
-
78
- def decorated_msg(self, msg):
79
- decorated_msg = time_stamp() + ' ' + msg + '\n'
80
- return decorated_msg
81
-
82
- def write_to_file(self, msg):
83
- if self.file:
84
- self.file.write(msg)
85
- ### flushing the log file to make sure it's written ###
86
- self.file.flush()
87
- os.fsync(self.file)
88
- else:
89
- self.file_error = True
90
- print(f'{time_stamp()} Logger is trying to write to a closed or non-existent file.')
91
-
92
- def log(self, msg, log='default'):
93
- ### This is the main function. Log options: 'screen', 'file', 'both', 'no', 'default', 'important'
94
- if log == 'important' and self.log_mode == 'no':
95
- log = 'screen'
96
- elif log == 'important' and self.log_mode == 'file':
97
- log = 'both'
98
- elif (log == 'important') or(log == 'default') or (log is None):
99
- log = self.log_mode
100
-
101
- decorated_message = self.decorated_msg(msg)
102
-
103
- if log == 'both':
104
- print(self.decorated_msg(msg))
105
- self.write_to_file(decorated_message)
106
- elif log == 'file':
107
- self.write_to_file(decorated_message)
108
- elif log == 'no':
109
- pass
110
- else: # log == 'screen' or anything else
111
- print(decorated_message)
112
-
113
-
114
-
115
- ### Use this function in other libraries if needed for debugging -- Not really needed
116
- DEBUG = False
117
- def debug(msg):
118
- if DEBUG:
119
- print(msg)
120
- return msg+'\n'
121
- else:
122
- return msg
1
+ ### BEGIN Dependencies ###
2
+ import os
3
+ from barsukov.time import time_stamp
4
+ ### END Dependencies ###
5
+
6
+ class Logger:
7
+ """
8
+ ### Don't create multiple Logger objects.
9
+ ### Logger can be opened and closed with start() and close() methods.
10
+ ### Restarting the logger will log to the same file, unless self.full_file_path has been changed by hand.
11
+ ### start=True will start the logger automatically, but be careful
12
+ ### about the full_folder_path=os.getcwd() in init.
13
+ ### Log options are 'screen', 'file', 'both', 'no'. The logger default is 'both'.
14
+ ### The log='important' is for the Logger.log() method only. Try not to use it.
15
+ ### Default hyerarchy is logger-default overriden by object-default overriden by instance.
16
+ ### Instances, that log errors, will usually use 'both'.
17
+ ###
18
+ """
19
+ def __init__(self,
20
+ description=None, # Will be passed by Script. If not, write a brief description!
21
+ full_folder_path=os.getcwd(), # Will be passed by Script. If not, specify!
22
+ full_file_path=None, # Specify only if you want to log into an already existing file.
23
+ log='both', # Logger default will be passed by Script. If not, you may choose to change.
24
+ start_file=True
25
+ ):
26
+
27
+ ### Initializing all variables before setting/getting them ###
28
+ self.full_file_path = full_file_path # If changed by hand later, needs start() to take effect
29
+ self.description = description # If changed by hand later, needs set_full_file_path and start() to take effect
30
+ self.log_mode = log # Default log mode can be changed by hand any time, no restart needed.
31
+
32
+ if self.full_file_path is not None:
33
+ self.full_folder_path = None
34
+ else:
35
+ self.full_folder_path = full_folder_path # If changed by hand later, needs set_full_file_path and start() to take effect
36
+ self.set_full_file_path(description=description, full_folder_path=full_folder_path)
37
+
38
+ self.file_error = False # If a problem with file, will be set to True. Just in case for later.
39
+ # If problem is remedied, you need to set file_error to False by hand.
40
+
41
+ #
42
+ if start_file:
43
+ self.start_file()
44
+ else:
45
+ self.file = None
46
+
47
+ self.log(f'Logger initialization complete.', log='important')
48
+
49
+ def to_dict(self):
50
+ seriable_data = self.__dict__.copy()
51
+ return seriable_data
52
+
53
+ def set_full_file_path(self, description=None, full_folder_path=None):
54
+ ### Checking if optional arguments are filled or if defaults are provided ###
55
+ if description is None:
56
+ description = self.description
57
+ if full_folder_path is None:
58
+ full_folder_path = self.full_folder_path
59
+ #
60
+ ### Create a file name like log_timeStamp_description_.txt ###
61
+ if not (description is None or description == ''):
62
+ description = '_' + description
63
+ else:
64
+ description = ''
65
+ file_name = 'log_' + time_stamp() + description + '_.txt'
66
+ #print(file_name)
67
+ #print(full_folder_path)
68
+ self.full_file_path = os.path.join(full_folder_path, file_name)
69
+
70
+ def start_file(self):
71
+ try:
72
+ self.file = open(self.full_file_path, 'a')
73
+ self.log('Logging file started.', log='important')
74
+ except:
75
+ print(f'{time_stamp()} Logger failed to open the log file \"{self.full_file_path}\".', log='important')
76
+
77
+ def close_file(self): # If closed, you'll need to restart before logging.
78
+ self.log('Logger is closing log file.', log='important')
79
+ self.file.close()
80
+ self.file = None
81
+
82
+ def decorated_msg(self, msg):
83
+ decorated_msg = time_stamp() + ' ' + msg + '\n'
84
+ return decorated_msg
85
+
86
+ def write_to_file(self, msg):
87
+ if self.file:
88
+ self.file.write(msg)
89
+ ### flushing the log file to make sure it's written ###
90
+ self.file.flush()
91
+ os.fsync(self.file)
92
+ else:
93
+ self.file_error = True
94
+ print(f'{time_stamp()} Logger is trying to write to a closed or non-existent file.')
95
+
96
+ def log(self, msg, log='default'):
97
+ ### This is the main function. Log options: 'screen', 'file', 'both', 'no', 'default', 'important'
98
+ if log == 'important' and self.log_mode == 'no':
99
+ log = 'screen'
100
+ elif log == 'important' and self.log_mode == 'file':
101
+ log = 'both'
102
+ elif (log == 'important') or(log == 'default') or (log is None):
103
+ log = self.log_mode
104
+
105
+ decorated_message = self.decorated_msg(msg)
106
+
107
+ if log == 'both':
108
+ print(self.decorated_msg(msg))
109
+ self.write_to_file(decorated_message)
110
+ elif log == 'file':
111
+ self.write_to_file(decorated_message)
112
+ elif log == 'no':
113
+ pass
114
+ else: # log == 'screen' or anything else
115
+ print(decorated_message)
116
+
117
+
118
+
119
+ ### Use this function in other libraries if needed for debugging -- Not really needed
120
+ DEBUG = False
121
+ def debug(msg):
122
+ if DEBUG:
123
+ print(msg)
124
+ return msg+'\n'
125
+ else:
126
+ return msg
123
127
  ###
barsukov/obj2file.py CHANGED
@@ -1,107 +1,105 @@
1
- # This is unfinished
2
-
3
-
4
- #import pickle
5
- import os
6
- #import glob
7
-
8
- import obj_name, time_stamp
9
-
10
- class Obj2File:
11
- def __init__(self, logger=None, log='default', script=None):
12
- self.script = script
13
- self.logger = logger
14
- self.default_log = log
15
- self.msg_deco = f'[Obj2File]'
16
-
17
- if self.logger is None:
18
- try: self.logger = self.script.logger
19
- except: pass
20
-
21
- self.mtj_calib_directory = '/Users/alexandrakorotneva/Desktop/2024-11-18 obj import test'
22
- self.tosave = {}
23
-
24
-
25
- def log(self, msg, log=None):
26
- if log is None: log = self.default_log
27
- if self.logger is not None:
28
- try:
29
- self.logger.log(f'{self.msg_deco} {msg}', log=log)
30
- return
31
- except: pass
32
- print(f'{time_stamp()} {self.msg_deco} {msg}')
33
-
34
- def save(self, obj, directory=None, full_file=None, short_file=None, log='default'):
35
- if full_file is None:
36
- if directory is None: directory = self.script.full_folder_path #current measurement folder
37
- if short_file is None: short_file = f'{time_stamp()}_{obj_name(obj)}.pkl'
38
- full_file = os.path.join(directory, short_file)
39
- try:
40
- with open(full_file, 'wb') as file:
41
- pickle.dump(obj, file)
42
- self.log(f'Object {obj_name(obj)} is written to file {full_file}.', log=log)
43
- except:
44
- self.log('Error: could not write object to file.', log='important')
45
-
46
- def load(self, directory=None, full_file=None, short_file=None, log='default'):
47
- if full_file is None:
48
- if directory is None:
49
- directory = self.script.full_folder_path
50
- if short_file is None:
51
- files = [f for f in glob.glob(os.path.join(directory, '*.pkl'))]
52
- short_file = files[0]
53
- full_file = os.path.join(directory, short_file)
54
-
55
- try:
56
- with open(filepath, 'rb') as file:
57
- toload = pickle.load(file)
58
- self.log(f'Object is uploaded from file {full_file}.', log=log)
59
- except:
60
- self.log('Error: could not upload object from file.', log='important')
61
- return toload
62
-
63
-
64
-
65
-
66
- def mtj_fieldcalib(self, directory=None, upd=False, log='default', spl_ind=None):
67
- if directory is None: directory = self.mtj_calib_directory
68
- else:
69
- if upd:
70
- self.mtj_calib_directory = directory
71
- self.log(f'MTJ station field calibration directory has been updated to {directory}', log='important')
72
-
73
- files = [f for f in glob.glob(os.path.join(directory, '*.pkl'))]
74
- if len(files)==1:
75
- short_file = files[0]
76
- else:
77
- ##
78
-
79
- full_file = os.path.join(directory, short_file)
80
- splines = self.load(full_file=full_file, log=log)
81
-
82
- if spl_ind is None:
83
- return: splines
84
- elif spl_ind=='c':
85
- return: splines['cheap_to_H']
86
- elif spl_ind=='v':
87
- return: Vsplines['V_to_H']
88
- elif spl_ind=='h':
89
- return: splines['H_to_V']
90
-
91
- def pack_tosave(self, obj, obj_name=None, overwrite=False, save=False):
92
- #prepares a dictionary {'obj name':obj, ...}
93
- tosave = self.tosave
94
- if obj_name is None: obj_name = obj_name(obj)
95
-
96
- if overwrite:
97
- tosave.update({obj_name : obj})
98
- else:
99
- add = tosave.setdefault(obj_name, obj) #for already excisting name returns corresponding element and doesn't overwrite
100
- if add!=obj:
101
- print(f'Overwriting attempt!')
102
-
103
- self.tosave = tosave
104
- if save:
105
- self.save(tosave)
106
- return tosave
107
-
1
+ # This is unfinished
2
+
3
+
4
+ #import pickle
5
+ import os
6
+ #import glob
7
+
8
+ import obj_name, time_stamp
9
+
10
+ class Obj2File:
11
+ def __init__(self, logger=None, log='default', script=None):
12
+ self.script = script
13
+ self.logger = logger
14
+ self.default_log = log
15
+ self.msg_deco = f'[Obj2File]'
16
+
17
+ if self.logger is None:
18
+ try: self.logger = self.script.logger
19
+ except: pass
20
+
21
+ self.mtj_calib_directory = '/Users/alexandrakorotneva/Desktop/2024-11-18 obj import test'
22
+ self.tosave = {}
23
+
24
+
25
+ def log(self, msg, log=None):
26
+ if log is None: log = self.default_log
27
+ if self.logger is not None:
28
+ try:
29
+ self.logger.log(f'{self.msg_deco} {msg}', log=log)
30
+ return
31
+ except: pass
32
+ print(f'{time_stamp()} {self.msg_deco} {msg}')
33
+
34
+ def save(self, obj, directory=None, full_file=None, short_file=None, log='default'):
35
+ if full_file is None:
36
+ if directory is None: directory = self.script.full_folder_path #current measurement folder
37
+ if short_file is None: short_file = f'{time_stamp()}_{obj_name(obj)}.pkl'
38
+ full_file = os.path.join(directory, short_file)
39
+ try:
40
+ with open(full_file, 'wb') as file:
41
+ pickle.dump(obj, file)
42
+ self.log(f'Object {obj_name(obj)} is written to file {full_file}.', log=log)
43
+ except:
44
+ self.log('Error: could not write object to file.', log='important')
45
+
46
+ def load(self, directory=None, full_file=None, short_file=None, log='default'):
47
+ if full_file is None:
48
+ if directory is None:
49
+ directory = self.script.full_folder_path
50
+ if short_file is None:
51
+ files = [f for f in glob.glob(os.path.join(directory, '*.pkl'))]
52
+ short_file = files[0]
53
+ full_file = os.path.join(directory, short_file)
54
+
55
+ try:
56
+ with open(filepath, 'rb') as file:
57
+ toload = pickle.load(file)
58
+ self.log(f'Object is uploaded from file {full_file}.', log=log)
59
+ except:
60
+ self.log('Error: could not upload object from file.', log='important')
61
+ return toload
62
+
63
+
64
+
65
+
66
+ def mtj_fieldcalib(self, directory=None, upd=False, log='default', spl_ind=None):
67
+ if directory is None: directory = self.mtj_calib_directory
68
+ else:
69
+ if upd:
70
+ self.mtj_calib_directory = directory
71
+ self.log(f'MTJ station field calibration directory has been updated to {directory}', log='important')
72
+
73
+ files = [f for f in glob.glob(os.path.join(directory, '*.pkl'))]
74
+ if len(files)==1:
75
+ short_file = files[0]
76
+
77
+ full_file = os.path.join(directory, short_file)
78
+ splines = self.load(full_file=full_file, log=log)
79
+
80
+ if spl_ind is None:
81
+ return splines
82
+ elif spl_ind=='c':
83
+ return splines['cheap_to_H']
84
+ elif spl_ind=='v':
85
+ return Vsplines['V_to_H']
86
+ elif spl_ind=='h':
87
+ return splines['H_to_V']
88
+
89
+ def pack_tosave(self, obj, obj_name=None, overwrite=False, save=False):
90
+ #prepares a dictionary {'obj name':obj, ...}
91
+ tosave = self.tosave
92
+ if obj_name is None: obj_name = obj_name(obj)
93
+
94
+ if overwrite:
95
+ tosave.update({obj_name : obj})
96
+ else:
97
+ add = tosave.setdefault(obj_name, obj) #for already excisting name returns corresponding element and doesn't overwrite
98
+ if add!=obj:
99
+ print(f'Overwriting attempt!')
100
+
101
+ self.tosave = tosave
102
+ if save:
103
+ self.save(tosave)
104
+ return tosave
105
+
barsukov/script.py CHANGED
@@ -1,82 +1,96 @@
1
- from barsukov.time import *
2
- from barsukov.logger import Logger
3
-
4
- import sys
5
- import os
6
-
7
- class Script():
8
- def __init__(self,
9
- ### Please ALWAYS specify the following:
10
- operator='Anon', # ib, Rundong, Sasha, Ameerah, Alex, or AlexH if ambiguous
11
- station='No Stn', # qd, ppms, mseppms, data, orange, ...
12
- sample='No Sample', # Use sample name from the sample table, e.g. "cro2410a1" or "yig2207"
13
- description='No Description', # Briefly: what are you doing. Sets the folder name.
14
- # i.e. 'Testing modulation' or 'fH OOP long average'
15
- project_folder = os.getcwd(), # Full path to your project folder. Please follow this convention:
16
- # D:/Rundong/Projects/AFM sims/2024-07-06 Autooscillations
17
- # Will grab the current directory if not specified.
18
-
19
- ### Optional:
20
- log='both', # This is the default log setting which will be passed to the logger.
21
- ### It will be overriden by other objects,
22
- ### which in turn will be overriden by methods.
23
- ### Choose here and everywhere from screen, file, both, no.
24
-
25
- ### Usually, it's better not to change these:
26
- log_full_folder_path=None,
27
- log_full_file_path=None
28
- ):
29
-
30
- self.operator = operator
31
- self.station = station
32
- self.sample = sample
33
- self.description = description
34
- self.project_folder = project_folder
35
-
36
- self.rm = None
37
-
38
- ### Creating the sub-project folder
39
- self.folder_name = date() + '_' + self.station + '_' + self.operator + '_' + self.sample + '_' + self.description
40
- self.full_folder_path = os.path.join(self.project_folder, self.folder_name)
41
- os.makedirs(self.full_folder_path, exist_ok=True)
42
-
43
- ### Starting the logger
44
- if log_full_folder_path is None:
45
- self.logger = Logger(
46
- description=self.operator + '_' + self.description,
47
- full_file_path=log_full_file_path,
48
- log=log, # Script.log becomes Logger's default
49
- start_file=True)
50
- else:
51
- self.logger = Logger(
52
- description=self.operator + '_' + self.description,
53
- full_folder_path=log_full_folder_path,
54
- full_file_path=log_full_file_path,
55
- log=log, # Script.log becomes Logger's default
56
- start_file=True)
57
-
58
- self.logger.log(f'Script object initialized. Logger started.', log='both')
59
-
60
- def log(self, msg, log='default'): # default means the default of the logger
61
- self.logger.log(msg, log=log)
62
-
63
-
64
- ### BEGIN: Equipment related stuff
65
-
66
- def init_rm(self):
67
- # Imports pyvisa as method library #
68
- import pyvisa as visa # ----------------XXX Can this be done like this??????????????
69
- try:
70
- self.rm = visa.ResourceManager()
71
- except:
72
- self.rm = None
73
- self.log('Script could not import pyvisa.', log='important')
74
- sys.exit()
75
- self.log(f'Script started pyvisa.ResourceManager.', log='both')
76
- return self.rm
77
-
78
- ### BEGIN Equipment devices
79
-
80
- def mwHP(self, **kwargs):
81
- from barsukov.src.exp.mwHP import mwHP as eq
82
- return eq(**kwargs, script=self, logger=self.logger)
1
+ from barsukov.time import *
2
+ from barsukov.logger import Logger
3
+
4
+ import sys
5
+ import os
6
+
7
+ class Script():
8
+ def __init__(self,
9
+ ### Please ALWAYS specify the following:
10
+ operator='Anon', # ib, Rundong, Sasha, Ameerah, Alex, or AlexH if ambiguous
11
+ station='No Stn', # qd, ppms, mseppms, data, orange, ...
12
+ sample='No Sample', # Use sample name from the sample table, e.g. "cro2410a1" or "yig2207"
13
+ description='No Description', # Briefly: what are you doing. Sets the folder name.
14
+ # i.e. 'Testing modulation' or 'fH OOP long average'
15
+ project_folder = os.getcwd(), # Full path to your project folder. Please follow this convention:
16
+ # D:/Rundong/Projects/AFM sims/2024-07-06 Autooscillations
17
+ # Will grab the current directory if not specified.
18
+
19
+ ### Optional:
20
+ log='both', # This is the default log setting which will be passed to the logger.
21
+ ### It will be overriden by other objects,
22
+ ### which in turn will be overriden by methods.
23
+ ### Choose here and everywhere from screen, file, both, no.
24
+
25
+ ### Usually, it's better not to change these:
26
+ log_full_folder_path=None,
27
+ log_full_file_path=None,
28
+ **kwargs
29
+ ):
30
+
31
+ self.operator = operator
32
+ self.station = station
33
+ self.sample = sample
34
+ self.description = description
35
+ self.project_folder = project_folder
36
+
37
+ self.rm = None
38
+
39
+ ### Creating the sub-project folder
40
+ self.folder_name = date() + '_' + self.station + '_' + self.operator + '_' + self.sample + '_' + self.description
41
+ self.full_folder_path = os.path.join(self.project_folder, self.folder_name)
42
+ os.makedirs(self.full_folder_path, exist_ok=True)
43
+
44
+ ### Starting the logger
45
+ if log_full_folder_path is None:
46
+ self.logger = Logger(
47
+ description=self.operator + '_' + self.description,
48
+ full_file_path=log_full_file_path,
49
+ log=log, # Script.log becomes Logger's default
50
+ start_file=True)
51
+ else:
52
+ self.logger = Logger(
53
+ description=self.operator + '_' + self.description,
54
+ full_folder_path=log_full_folder_path,
55
+ full_file_path=log_full_file_path,
56
+ log=log, # Script.log becomes Logger's default
57
+ start_file=True)
58
+
59
+ self.logger.log(f'Script object initialized. Logger started.', log='both')
60
+
61
+ def to_dict(self):
62
+ seriable_data = self.__dict__.copy()
63
+ # take the attributes of unseriable data
64
+ del seriable_data['logger']
65
+ del seriable_data['rm']
66
+ del
67
+ seriable_data['logger_information'] = self.logger.to_dict()
68
+ return seriable_data
69
+
70
+ def __setstate__(self, seriable_data):
71
+ self.__dict__.update(seriable_data)
72
+ self.logger = Logger(**state['logger_information'])
73
+
74
+ def log(self, msg, log='default'): # default means the default of the logger
75
+ self.logger.log(msg, log=log)
76
+
77
+
78
+ ### BEGIN: Equipment related stuff
79
+
80
+ def init_rm(self):
81
+ # Imports pyvisa as method library #
82
+ import pyvisa as visa # ----------------XXX Can this be done like this??????????????
83
+ try:
84
+ self.rm = visa.ResourceManager()
85
+ except:
86
+ self.rm = None
87
+ self.log('Script could not import pyvisa.', log='important')
88
+ sys.exit()
89
+ self.log(f'Script started pyvisa.ResourceManager.', log='both')
90
+ return self.rm
91
+
92
+ ### BEGIN Equipment devices
93
+
94
+ def mwHP(self, **kwargs):
95
+ from barsukov.exp.mwHP import mwHP as eq
96
+ return eq(**kwargs, script=self, logger=self.logger)