Add config file managing class
This commit is contained in:
parent
154235dbe5
commit
2631898c35
@ -53,26 +53,31 @@ from .led_script import LedScript
|
||||
from .measurement import measure as _measure
|
||||
from .utility.data import DataCollector
|
||||
from .utility.data import plot_cpd_data as data_plot
|
||||
from .utility.config_file import ConfigFile
|
||||
from .utility import file_io
|
||||
from .update_funcs import _Monitor, _update_print
|
||||
|
||||
config_path = path.expanduser("~/.config/cpdctrl.json")
|
||||
|
||||
# CONFIGURATION
|
||||
_runtime_vars = {
|
||||
"last-measurement": ""
|
||||
}
|
||||
|
||||
# defaults, these may be overridden by a config file
|
||||
settings = {
|
||||
"datadir": path.expanduser("~/data"),
|
||||
"name": "interactive-test",
|
||||
"led": "unkown",
|
||||
"led": "unknown",
|
||||
"interval": 0.5,
|
||||
"flush_after": 3000,
|
||||
"use_buffer": False,
|
||||
}
|
||||
|
||||
cfilename: str = "cpdctrl.yaml"
|
||||
config_path: str = ""
|
||||
config_file: ConfigFile = ConfigFile("")
|
||||
|
||||
test = False
|
||||
|
||||
# DEVICES
|
||||
# global variable for the instrument/client returned by pyvisa/bleak
|
||||
dev: VoltageMeasurementDevice|None = None
|
||||
led: LedControlDevice|None = None
|
||||
@ -81,7 +86,7 @@ t0 = 0
|
||||
data = None
|
||||
md = None
|
||||
|
||||
def monitor(script: str|int=0, interval: float|None=None, metadata:dict={}, flush_after: int|None=None, use_buffer: bool|None=None, max_measurements=None, max_points_shown=None):
|
||||
def monitor(script: str|int=0, interval: float|None=None, metadata:dict={}, flush_after: int|None=None, use_buffer: bool|None=None, max_measurements=None, stop_on_script_end: bool=False, max_points_shown=None):
|
||||
"""
|
||||
Monitor the voltage with matplotlib.
|
||||
- Opens a matplotlib window and takes measurements depending on settings["interval"]
|
||||
@ -96,7 +101,7 @@ def monitor(script: str|int=0, interval: float|None=None, metadata:dict={}, flus
|
||||
Parameters
|
||||
----------
|
||||
script : str|int
|
||||
Path to a led script file or a constant value between 0 and 100 for the LED.
|
||||
Path to a led script file, or a constant value between 0 and 100 for the LED.
|
||||
interval : float|None
|
||||
Time between measurements.
|
||||
If None, the value is taken from the settings.
|
||||
@ -106,12 +111,15 @@ def monitor(script: str|int=0, interval: float|None=None, metadata:dict={}, flus
|
||||
flush_after : int|None
|
||||
Flush the data to disk after <flush_after> readings
|
||||
If None, the value is taken from the settings.
|
||||
use_buffer : Bool
|
||||
use_buffer : bool
|
||||
If True, use the voltage measurement device's internal buffer for readings, which leads to more accurate timings.
|
||||
If None, the value is taken from the settings.
|
||||
max_points_shown : int|None
|
||||
how many points should be shown at once. None means infinite
|
||||
max_measurements : maximum number of measurements. None means infinite
|
||||
max_measurements : int|None
|
||||
maximum number of measurements. None means infinite
|
||||
stop_on_script_end : bool, optional
|
||||
Stop measurement when the script end is reached
|
||||
"""
|
||||
global _runtime_vars, data_collector, dev, led
|
||||
global data, md
|
||||
@ -140,7 +148,8 @@ def monitor(script: str|int=0, interval: float|None=None, metadata:dict={}, flus
|
||||
interval,
|
||||
flush_after,
|
||||
use_buffer,
|
||||
max_measurements,
|
||||
max_measurements,
|
||||
stop_on_script_end,
|
||||
False, # verbose
|
||||
command_queue,
|
||||
data_queue
|
||||
@ -158,6 +167,7 @@ def monitor(script: str|int=0, interval: float|None=None, metadata:dict={}, flus
|
||||
pass
|
||||
command_queue.put("stop")
|
||||
proc_measure.join()
|
||||
print("Measurement stopped" + " "*50)
|
||||
led_script.stop_updating() # stop watching for file updates (if enabled)
|
||||
data_collector.save_csv(verbose=True)
|
||||
data, metadata = data_collector.get_data()
|
||||
@ -165,8 +175,7 @@ def monitor(script: str|int=0, interval: float|None=None, metadata:dict={}, flus
|
||||
plt.ioff()
|
||||
fig_path = path.join(data_collector.path, data_collector.dirname + ".pdf")
|
||||
fig.savefig(fig_path)
|
||||
|
||||
|
||||
|
||||
|
||||
# DATA
|
||||
def data_load(dirname:str) -> tuple[np.ndarray, dict]:
|
||||
@ -186,8 +195,6 @@ def data_load(dirname:str) -> tuple[np.ndarray, dict]:
|
||||
dirpath = path.join(settings["datadir"], dirname)
|
||||
data, md = DataCollector.load_data(dirpath, verbose=True)
|
||||
|
||||
# data_plot imported
|
||||
|
||||
# SETTINGS
|
||||
def set(setting, value):
|
||||
global settings, config_path
|
||||
@ -196,19 +203,20 @@ def set(setting, value):
|
||||
print(f"set: setting '{setting}' currently holds a value of type '{type(settings[setting])}'")
|
||||
return
|
||||
settings[setting] = value
|
||||
config_file.set(setting, value)
|
||||
|
||||
def name(s:str):
|
||||
global settings
|
||||
settings["name"] = s
|
||||
|
||||
def save_settings():
|
||||
with open(config_path, "w") as file:
|
||||
json.dump(settings, file, indent=4)
|
||||
global settings
|
||||
config_file.set_values(settings)
|
||||
config_file.save()
|
||||
|
||||
def load_settings():
|
||||
global settings, config_path
|
||||
with open(config_path, "r") as file:
|
||||
settings = json.load(file)
|
||||
settings = config_file.get_values()
|
||||
settings["datadir"] = path.expanduser(settings["datadir"]) # replace ~
|
||||
|
||||
def help(topic=None):
|
||||
@ -226,23 +234,29 @@ Available topics:
|
||||
Run 'help("topic")' to see more information on a topic""")
|
||||
|
||||
elif topic in [settings, "settings"]:
|
||||
print("""Settings:
|
||||
print(f"""Settings:
|
||||
name: str - name of the measurement, determines filename
|
||||
led: str - name/model of the LED that is being used
|
||||
datadir: str - output directory for the csv files
|
||||
interval: int - interval (inverse frequency) of the measurements, in seconds
|
||||
beep: bool - wether the device should beep or not
|
||||
beep: bool - whether the device should beep or not
|
||||
|
||||
|
||||
Functions:
|
||||
name("<name>") - short for set("name", "<name>")
|
||||
set("setting", value) - set a setting to a value
|
||||
save_settings() - store the settings as "cpdctrl.json" in the working directory
|
||||
load_settings() - load settings from a file
|
||||
The global variable 'config_path' determines the path used by save/load_settings. Use -c '<path>' to set another path.
|
||||
The serach path is:
|
||||
<working-dir>/cpdctrl.json
|
||||
$XDG_CONFIG_HOME/cpdctrl.json
|
||||
~/.config/cpdctrl.json
|
||||
|
||||
Upon startup, settings are loaded from the config file.
|
||||
The global variable 'config_path' determines the path used by save/load_settings. Use -c '<path>' to set another path.
|
||||
The search path is:
|
||||
<working-dir>/{cfilename}
|
||||
$XDG_CONFIG_HOME/{cfilename}
|
||||
~/.config/cpdctrl/{cfilename}
|
||||
|
||||
The current file path is:
|
||||
{config_path}
|
||||
""")
|
||||
elif topic == "imports":
|
||||
print("""Imports:
|
||||
@ -255,7 +269,7 @@ Functions:
|
||||
|
||||
|
||||
def init():
|
||||
global dev, led, settings, config_path
|
||||
global dev, led, settings, config_path, config_file
|
||||
print(r""" .___ __ .__
|
||||
____ ______ __| _/_____/ |________| |
|
||||
_/ ___\\____ \ / __ |/ ___\ __\_ __ \ |
|
||||
@ -266,21 +280,19 @@ Interactive Shell for CPD measurements with Keithley 2700B
|
||||
---
|
||||
Enter 'help()' for a list of commands""")
|
||||
from os import environ
|
||||
if path.isfile("cpdctrl.json"):
|
||||
config_path = "cpdctrl.json"
|
||||
|
||||
if path.isfile(cfilename):
|
||||
config_path = cfilename
|
||||
elif 'XDG_CONFIG_HOME' in environ.keys():
|
||||
# and path.isfile(environ["XDG_CONFIG_HOME"] + "/cpdctrl.json"):
|
||||
config_path = environ["XDG_CONFIG_HOME"] + "/cpdctrl.json"
|
||||
config_path = path.join(environ["XDG_CONFIG_HOME"], "cpdctrl", cfilename)
|
||||
else:
|
||||
config_path = path.expanduser("~/.config/cpdctrl.json")
|
||||
config_path = path.join(path.expanduser("~/.config/cpdctrl"), cfilename)
|
||||
if args["config"]:
|
||||
config_path = args["config"]
|
||||
|
||||
if not path.isdir(path.dirname(config_path)):
|
||||
makedirs(path.dirname(config_path))
|
||||
|
||||
if path.isfile(config_path):
|
||||
load_settings()
|
||||
config_file = ConfigFile(config_path, init_values=settings)
|
||||
load_settings()
|
||||
|
||||
if not path.isdir(settings["datadir"]):
|
||||
makedirs(settings["datadir"])
|
||||
|
33
cpdctrl/utility/config_file.py
Normal file
33
cpdctrl/utility/config_file.py
Normal file
@ -0,0 +1,33 @@
|
||||
from os import environ, makedirs, path
|
||||
import yaml
|
||||
|
||||
class ConfigFile:
|
||||
def __init__(self, filepath: str, init_values = None):
|
||||
self.values = {}
|
||||
if init_values:
|
||||
self.values = init_values
|
||||
self.filepath = filepath
|
||||
if path.isfile(self.filepath):
|
||||
with open(self.filepath, "r") as file:
|
||||
self.values |= yaml.safe_load(file)
|
||||
|
||||
def save(self):
|
||||
if not self.filepath: return
|
||||
directory = path.dirname(self.filepath)
|
||||
if not path.isdir(directory):
|
||||
makedirs(directory)
|
||||
with open(self.filepath, "w") as file:
|
||||
yaml.dump(self.values, file)
|
||||
|
||||
def get(self, name: str, default=None):
|
||||
if name in self.values: return self.values[name]
|
||||
return default
|
||||
|
||||
def set(self, name: str, value):
|
||||
self.values[name] = value
|
||||
|
||||
def get_values(self):
|
||||
return self.values.copy()
|
||||
|
||||
def set_values(self, values):
|
||||
self.values = values
|
Loading…
x
Reference in New Issue
Block a user