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 .measurement import measure as _measure
|
||||||
from .utility.data import DataCollector
|
from .utility.data import DataCollector
|
||||||
from .utility.data import plot_cpd_data as data_plot
|
from .utility.data import plot_cpd_data as data_plot
|
||||||
|
from .utility.config_file import ConfigFile
|
||||||
from .utility import file_io
|
from .utility import file_io
|
||||||
from .update_funcs import _Monitor, _update_print
|
from .update_funcs import _Monitor, _update_print
|
||||||
|
|
||||||
config_path = path.expanduser("~/.config/cpdctrl.json")
|
# CONFIGURATION
|
||||||
|
|
||||||
_runtime_vars = {
|
_runtime_vars = {
|
||||||
"last-measurement": ""
|
"last-measurement": ""
|
||||||
}
|
}
|
||||||
|
# defaults, these may be overridden by a config file
|
||||||
settings = {
|
settings = {
|
||||||
"datadir": path.expanduser("~/data"),
|
"datadir": path.expanduser("~/data"),
|
||||||
"name": "interactive-test",
|
"name": "interactive-test",
|
||||||
"led": "unkown",
|
"led": "unknown",
|
||||||
"interval": 0.5,
|
"interval": 0.5,
|
||||||
"flush_after": 3000,
|
"flush_after": 3000,
|
||||||
"use_buffer": False,
|
"use_buffer": False,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfilename: str = "cpdctrl.yaml"
|
||||||
|
config_path: str = ""
|
||||||
|
config_file: ConfigFile = ConfigFile("")
|
||||||
|
|
||||||
test = False
|
test = False
|
||||||
|
|
||||||
|
# DEVICES
|
||||||
# global variable for the instrument/client returned by pyvisa/bleak
|
# global variable for the instrument/client returned by pyvisa/bleak
|
||||||
dev: VoltageMeasurementDevice|None = None
|
dev: VoltageMeasurementDevice|None = None
|
||||||
led: LedControlDevice|None = None
|
led: LedControlDevice|None = None
|
||||||
@ -81,7 +86,7 @@ t0 = 0
|
|||||||
data = None
|
data = None
|
||||||
md = 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.
|
Monitor the voltage with matplotlib.
|
||||||
- Opens a matplotlib window and takes measurements depending on settings["interval"]
|
- 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
|
Parameters
|
||||||
----------
|
----------
|
||||||
script : str|int
|
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
|
interval : float|None
|
||||||
Time between measurements.
|
Time between measurements.
|
||||||
If None, the value is taken from the settings.
|
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_after : int|None
|
||||||
Flush the data to disk after <flush_after> readings
|
Flush the data to disk after <flush_after> readings
|
||||||
If None, the value is taken from the settings.
|
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 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.
|
If None, the value is taken from the settings.
|
||||||
max_points_shown : int|None
|
max_points_shown : int|None
|
||||||
how many points should be shown at once. None means infinite
|
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 _runtime_vars, data_collector, dev, led
|
||||||
global data, md
|
global data, md
|
||||||
@ -141,6 +149,7 @@ def monitor(script: str|int=0, interval: float|None=None, metadata:dict={}, flus
|
|||||||
flush_after,
|
flush_after,
|
||||||
use_buffer,
|
use_buffer,
|
||||||
max_measurements,
|
max_measurements,
|
||||||
|
stop_on_script_end,
|
||||||
False, # verbose
|
False, # verbose
|
||||||
command_queue,
|
command_queue,
|
||||||
data_queue
|
data_queue
|
||||||
@ -158,6 +167,7 @@ def monitor(script: str|int=0, interval: float|None=None, metadata:dict={}, flus
|
|||||||
pass
|
pass
|
||||||
command_queue.put("stop")
|
command_queue.put("stop")
|
||||||
proc_measure.join()
|
proc_measure.join()
|
||||||
|
print("Measurement stopped" + " "*50)
|
||||||
led_script.stop_updating() # stop watching for file updates (if enabled)
|
led_script.stop_updating() # stop watching for file updates (if enabled)
|
||||||
data_collector.save_csv(verbose=True)
|
data_collector.save_csv(verbose=True)
|
||||||
data, metadata = data_collector.get_data()
|
data, metadata = data_collector.get_data()
|
||||||
@ -167,7 +177,6 @@ def monitor(script: str|int=0, interval: float|None=None, metadata:dict={}, flus
|
|||||||
fig.savefig(fig_path)
|
fig.savefig(fig_path)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# DATA
|
# DATA
|
||||||
def data_load(dirname:str) -> tuple[np.ndarray, dict]:
|
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)
|
dirpath = path.join(settings["datadir"], dirname)
|
||||||
data, md = DataCollector.load_data(dirpath, verbose=True)
|
data, md = DataCollector.load_data(dirpath, verbose=True)
|
||||||
|
|
||||||
# data_plot imported
|
|
||||||
|
|
||||||
# SETTINGS
|
# SETTINGS
|
||||||
def set(setting, value):
|
def set(setting, value):
|
||||||
global settings, config_path
|
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])}'")
|
print(f"set: setting '{setting}' currently holds a value of type '{type(settings[setting])}'")
|
||||||
return
|
return
|
||||||
settings[setting] = value
|
settings[setting] = value
|
||||||
|
config_file.set(setting, value)
|
||||||
|
|
||||||
def name(s:str):
|
def name(s:str):
|
||||||
global settings
|
global settings
|
||||||
settings["name"] = s
|
settings["name"] = s
|
||||||
|
|
||||||
def save_settings():
|
def save_settings():
|
||||||
with open(config_path, "w") as file:
|
global settings
|
||||||
json.dump(settings, file, indent=4)
|
config_file.set_values(settings)
|
||||||
|
config_file.save()
|
||||||
|
|
||||||
def load_settings():
|
def load_settings():
|
||||||
global settings, config_path
|
global settings, config_path
|
||||||
with open(config_path, "r") as file:
|
settings = config_file.get_values()
|
||||||
settings = json.load(file)
|
|
||||||
settings["datadir"] = path.expanduser(settings["datadir"]) # replace ~
|
settings["datadir"] = path.expanduser(settings["datadir"]) # replace ~
|
||||||
|
|
||||||
def help(topic=None):
|
def help(topic=None):
|
||||||
@ -226,23 +234,29 @@ Available topics:
|
|||||||
Run 'help("topic")' to see more information on a topic""")
|
Run 'help("topic")' to see more information on a topic""")
|
||||||
|
|
||||||
elif topic in [settings, "settings"]:
|
elif topic in [settings, "settings"]:
|
||||||
print("""Settings:
|
print(f"""Settings:
|
||||||
name: str - name of the measurement, determines filename
|
name: str - name of the measurement, determines filename
|
||||||
led: str - name/model of the LED that is being used
|
led: str - name/model of the LED that is being used
|
||||||
datadir: str - output directory for the csv files
|
datadir: str - output directory for the csv files
|
||||||
interval: int - interval (inverse frequency) of the measurements, in seconds
|
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:
|
Functions:
|
||||||
name("<name>") - short for set("name", "<name>")
|
name("<name>") - short for set("name", "<name>")
|
||||||
set("setting", value) - set a setting to a value
|
set("setting", value) - set a setting to a value
|
||||||
save_settings() - store the settings as "cpdctrl.json" in the working directory
|
save_settings() - store the settings as "cpdctrl.json" in the working directory
|
||||||
load_settings() - load settings from a file
|
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:
|
Upon startup, settings are loaded from the config file.
|
||||||
<working-dir>/cpdctrl.json
|
The global variable 'config_path' determines the path used by save/load_settings. Use -c '<path>' to set another path.
|
||||||
$XDG_CONFIG_HOME/cpdctrl.json
|
The search path is:
|
||||||
~/.config/cpdctrl.json
|
<working-dir>/{cfilename}
|
||||||
|
$XDG_CONFIG_HOME/{cfilename}
|
||||||
|
~/.config/cpdctrl/{cfilename}
|
||||||
|
|
||||||
|
The current file path is:
|
||||||
|
{config_path}
|
||||||
""")
|
""")
|
||||||
elif topic == "imports":
|
elif topic == "imports":
|
||||||
print("""Imports:
|
print("""Imports:
|
||||||
@ -255,7 +269,7 @@ Functions:
|
|||||||
|
|
||||||
|
|
||||||
def init():
|
def init():
|
||||||
global dev, led, settings, config_path
|
global dev, led, settings, config_path, config_file
|
||||||
print(r""" .___ __ .__
|
print(r""" .___ __ .__
|
||||||
____ ______ __| _/_____/ |________| |
|
____ ______ __| _/_____/ |________| |
|
||||||
_/ ___\\____ \ / __ |/ ___\ __\_ __ \ |
|
_/ ___\\____ \ / __ |/ ___\ __\_ __ \ |
|
||||||
@ -266,21 +280,19 @@ Interactive Shell for CPD measurements with Keithley 2700B
|
|||||||
---
|
---
|
||||||
Enter 'help()' for a list of commands""")
|
Enter 'help()' for a list of commands""")
|
||||||
from os import environ
|
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():
|
elif 'XDG_CONFIG_HOME' in environ.keys():
|
||||||
# and path.isfile(environ["XDG_CONFIG_HOME"] + "/cpdctrl.json"):
|
# 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:
|
else:
|
||||||
config_path = path.expanduser("~/.config/cpdctrl.json")
|
config_path = path.join(path.expanduser("~/.config/cpdctrl"), cfilename)
|
||||||
if args["config"]:
|
if args["config"]:
|
||||||
config_path = args["config"]
|
config_path = args["config"]
|
||||||
|
|
||||||
if not path.isdir(path.dirname(config_path)):
|
config_file = ConfigFile(config_path, init_values=settings)
|
||||||
makedirs(path.dirname(config_path))
|
load_settings()
|
||||||
|
|
||||||
if path.isfile(config_path):
|
|
||||||
load_settings()
|
|
||||||
|
|
||||||
if not path.isdir(settings["datadir"]):
|
if not path.isdir(settings["datadir"]):
|
||||||
makedirs(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