Source code for cellpy.parameters.prms

"""cellpy parameters"""

from __future__ import annotations
import os
import sys
from dataclasses import dataclass, field
from pathlib import Path
from typing import List, Tuple, Union, Optional, TYPE_CHECKING

# Using TYPE_CHECKING to avoid circular imports
# (this will only work without from __future__ import annotations for python 3.11 and above)
from cellpy.internals.core import OtherPath

import box

# When adding prms, please
#   1) check / update the internal_settings.py file as well to
#      ensure that copying / splitting cellpy objects
#      behaves properly.
#   2) check / update the .cellpy_prms_default.conf file

# locations etc. for reading custom parameters
[docs] script_dir = os.path.abspath(os.path.dirname(__file__))
[docs] cur_dir = os.path.abspath(os.path.dirname(sys.argv[0]))
[docs] user_dir = Path.home()
[docs] wdir = Path(cur_dir)
[docs] op_wdir = str(wdir)
@dataclass
[docs] class CellPyDataConfig: """Settings that can be unique for each CellpyCell instance.""" ...
@dataclass
[docs] class CellPyConfig: """Session settings (global)."""
[docs] def keys(self): return self.__dataclass_fields__.keys()
# If updating PathsClass, you will have to do a lot of tweaks. # .cellpy_prms_default.conf # cli.py (_update_paths) # test_cli_setup_interactive (NUMBER_OF_DIRS) # test_prms.py (config_file_txt) # _convert_paths_to_dict # This can stay global: @dataclass
[docs] class PathsClass(CellPyConfig): """Paths used in cellpy."""
[docs] outdatadir: Union[Path, str] = wdir
_rawdatadir: Union[OtherPath, str] = op_wdir _cellpydatadir: Union[OtherPath, str] = op_wdir
[docs] db_path: Union[Path, str] = wdir # used for simple excel db reader
[docs] filelogdir: Union[Path, str] = wdir
[docs] examplesdir: Union[Path, str] = wdir
[docs] notebookdir: Union[Path, str] = wdir
[docs] templatedir: Union[Path, str] = wdir
[docs] batchfiledir: Union[Path, str] = wdir
[docs] instrumentdir: Union[Path, str] = wdir
[docs] db_filename: str = "cellpy_db.xlsx" # used for simple excel db reader
[docs] env_file: Union[Path, str] = user_dir / ".env_cellpy"
@property
[docs] def rawdatadir(self) -> OtherPath: return OtherPath(self._rawdatadir)
@rawdatadir.setter def rawdatadir(self, value: Union[OtherPath, Path, str]): self._rawdatadir = OtherPath(value) @property
[docs] def cellpydatadir(self) -> OtherPath: return OtherPath(self._cellpydatadir)
@cellpydatadir.setter def cellpydatadir(self, value: Union[OtherPath, Path, str]): self._cellpydatadir = OtherPath(value)
@dataclass
[docs] class BatchClass(CellPyConfig): """Settings for batch processing."""
[docs] auto_use_file_list: bool = False
[docs] template: str = "standard"
[docs] fig_extension: str = "png"
[docs] backend: str = "plotly"
[docs] notebook: bool = True
[docs] dpi: int = 300
[docs] markersize: int = 4
[docs] symbol_label: str = "simple"
[docs] color_style_label: str = "seaborn-deep"
[docs] figure_type: str = "unlimited"
[docs] summary_plot_width: int = 900
[docs] summary_plot_height: int = 800
[docs] summary_plot_height_fractions: List[float] = field( default_factory=lambda: [0.2, 0.5, 0.3] )
@dataclass
[docs] class FileNamesClass(CellPyConfig): """Settings for file names and file handling."""
[docs] file_name_format: str = "YYYYMMDD_[NAME]EEE_CC_TT_RR"
[docs] raw_extension: str = "res"
[docs] reg_exp: str = None
[docs] sub_folders: bool = True
[docs] file_list_location: str = None
[docs] file_list_type: str = None
[docs] file_list_name: str = None
[docs] cellpy_file_extension: str = "h5"
@dataclass
[docs] class ReaderClass(CellPyConfig): """Settings for reading data."""
[docs] diagnostics: bool = False
[docs] filestatuschecker: str = "size"
[docs] force_step_table_creation: bool = True
[docs] force_all: bool = False # not used yet - should be used when saving
[docs] sep: str = ";"
[docs] cycle_mode: str = "anode"
[docs] sorted_data: bool = True # finding step-types assumes sorted data
[docs] select_minimal: bool = False
[docs] limit_loaded_cycles: Optional[int] = ( None # limit loading cycles to given cycle number )
[docs] ensure_step_table: bool = False
[docs] ensure_summary_table: bool = False
[docs] voltage_interpolation_step: float = 0.01
[docs] time_interpolation_step: float = 10.0
[docs] capacity_interpolation_step: float = 2.0
[docs] use_cellpy_stat_file: bool = False
[docs] auto_dirs: bool = ( True # v2.0 search in prm-file for res and hdf5 dirs in cellpy.get() )
[docs] jupyter_executable: str = "jupyter"
@dataclass
[docs] class DbClass(CellPyConfig): """Settings for the handling the simple database."""
[docs] db_type: str = "simple_excel_reader"
[docs] db_table_name: str = "db_table" # used for simple excel db reader
[docs] db_header_row: int = 0 # used for simple excel db reader
[docs] db_unit_row: int = 1 # used for simple excel db reader
[docs] db_data_start_row: int = 2 # used for simple excel db reader
[docs] db_search_start_row: int = 2 # used for simple excel db reader
[docs] db_search_end_row: int = -1 # used for simple excel db reader
[docs] db_file_sqlite: str = "excel.db" # used when converting from Excel to sqlite
# database connection string - used for more advanced db readers:
[docs] db_connection: Optional[str] = None
@dataclass
[docs] class DbColsClass(CellPyConfig): # used for simple excel db reader """Names of the columns in the simple database.""" # Note to developers: # 1) This is ONLY for the excel-reader (dbreader.py)! More advanced # readers should get their own way of handling the db-columns. # 2) If you would like to change the names of the attributes, # you will have to change the names in the # a .cellpy_prms_default.conf # b. dbreader.py # c. test_dbreader.py # d. internal_settings.py (renaming when making sqlite from Excel) # As well as the DbColsTypeClass below.
[docs] id: str = "id"
[docs] exists: str = "exists"
[docs] project: str = "project"
[docs] label: str = "label"
[docs] group: str = "group"
[docs] selected: str = "selected"
[docs] cell_name: str = "cell"
[docs] cell_type: str = "cell_type"
[docs] experiment_type: str = "experiment_type"
[docs] mass_active: str = "mass_active_material"
[docs] area: str = "area"
[docs] mass_total: str = "mass_total"
[docs] loading: str = "loading_active_material"
[docs] nom_cap: str = "nominal_capacity"
[docs] file_name_indicator: str = "file_name_indicator"
[docs] instrument: str = "instrument"
[docs] raw_file_names: str = "raw_file_names"
[docs] cellpy_file_name: str = "cellpy_file_name"
[docs] comment_slurry: str = "comment_slurry"
[docs] comment_cell: str = "comment_cell"
[docs] comment_general: str = "comment_general"
[docs] freeze: str = "freeze"
[docs] argument: str = "argument"
[docs] batch: str = "batch"
[docs] sub_batch_01: str = "b01"
[docs] sub_batch_02: str = "b02"
[docs] sub_batch_03: str = "b03"
[docs] sub_batch_04: str = "b04"
[docs] sub_batch_05: str = "b05"
[docs] sub_batch_06: str = "b06"
[docs] sub_batch_07: str = "b07"
@dataclass
[docs] class DbColsUnitClass(CellPyConfig): """Unit of the columns in the simple database.""" # Note to developers: # 1) This is ONLY for the excel-reader (dbreader.py)! More advanced # readers should get their own way of handling the db-columns.
[docs] id: str = "str"
[docs] exists: str = "int"
[docs] project: str = "str"
[docs] label: str = "str"
[docs] group: str = "str"
[docs] selected: str = "int"
[docs] cell_name: str = "str"
[docs] cell_type: str = "str"
[docs] experiment_type: str = "str"
[docs] mass_active: str = "float"
[docs] area: str = "float"
[docs] mass_total: str = "float"
[docs] loading: str = "float"
[docs] nom_cap: str = "float"
[docs] file_name_indicator: str = "str"
[docs] instrument: str = "str"
[docs] raw_file_names: str = "str"
[docs] cellpy_file_name: str = "str"
[docs] comment_slurry: str = "str"
[docs] comment_cell: str = "str"
[docs] comment_general: str = "str"
[docs] freeze: str = "int"
[docs] argument: str = "str"
[docs] batch: str = "str"
[docs] sub_batch_01: str = "str"
[docs] sub_batch_02: str = "str"
[docs] sub_batch_03: str = "str"
[docs] sub_batch_04: str = "str"
[docs] sub_batch_05: str = "str"
[docs] sub_batch_06: str = "str"
[docs] sub_batch_07: str = "str"
@dataclass
[docs] class CellInfoClass(CellPyDataConfig): """Values used for setting the parameters related to the cell and the cycling"""
[docs] voltage_lim_low: float = 0.0
[docs] voltage_lim_high: float = 1.0
[docs] active_electrode_area: float = 1.0
[docs] active_electrode_thickness: float = 1.0
[docs] electrolyte_volume: float = 1.0
[docs] electrolyte_type: str = "standard"
[docs] active_electrode_type: str = "standard"
[docs] counter_electrode_type: str = "standard"
[docs] reference_electrode_type: str = "standard"
[docs] experiment_type: str = "cycling"
[docs] cell_type: str = "standard"
[docs] separator_type: str = "standard"
[docs] active_electrode_current_collector: str = "standard"
[docs] reference_electrode_current_collector: str = "standard"
[docs] comment: str = ""
@dataclass
[docs] class MaterialsClass(CellPyDataConfig): """Default material-specific values used in processing the data."""
[docs] cell_class: str = "Li-Ion"
[docs] default_material: str = "silicon"
[docs] default_mass: float = 1.0
[docs] default_nom_cap: float = 1.0
[docs] default_nom_cap_specifics: str = "gravimetric"
[docs] Paths = PathsClass()
[docs] FileNames = FileNamesClass()
[docs] Reader = ReaderClass()
[docs] Db = DbClass()
[docs] DbCols = DbColsClass()
[docs] CellInfo = CellInfoClass()
[docs] Materials = MaterialsClass()
[docs] Batch = BatchClass(backend="plotly")
# ------------------------------------------------------------------------------ # Instruments # # This should be updated - currently using dicts instead of subclasses of # dataclasses. I guess I could update this but is a bit challenging # so maybe replace later using e.g. pydantic # ------------------------------------------------------------------------------ # This can stay global: # remark! using box.Box for each instrument @dataclass
[docs] class InstrumentsClass(CellPyConfig): """Settings for the instruments."""
[docs] tester: Union[str, None]
[docs] custom_instrument_definitions_file: Union[str, None]
[docs] Arbin: box.Box
[docs] Maccor: box.Box
[docs] Neware: box.Box
# Pre-defined instruments: # These can stay global: _Arbin = { "max_res_filesize": 150_000_000, "chunk_size": None, "max_chunks": None, "use_subprocess": False, "detect_subprocess_need": False, "sub_process_path": None, "office_version": "64bit", "SQL_server": r"localhost\SQLEXPRESS", "SQL_UID": "sa", "SQL_PWD": "ChangeMe123", "SQL_Driver": "SQL Server", }
[docs] Arbin = box.Box(_Arbin)
_Maccor = {"default_model": "one"}
[docs] Maccor = box.Box(_Maccor)
_Neware = {"default_model": "one"}
[docs] Neware = box.Box(_Neware)
[docs] Instruments = InstrumentsClass( tester=None, # TODO: moving this to DataSetClass (deprecate) custom_instrument_definitions_file=None, Arbin=Arbin, Maccor=Maccor, Neware=Neware, )
# ------------------------------------------------------------------------------ # Other secret- or non-config (only for developers and super-users) # ------------------------------------------------------------------------------ _github_repo_parent = "jepegit" _github_repo = "cellpy" _github_templates_repo = "cellpy_cookies.git" _url_example_data = f"https://raw.githubusercontent.com/{_github_repo_parent}/{_github_repo}/master/examples/data/" _url_example_data_download_with_progressbar = True _example_data_in_example_folder_if_available = True _db_cols_unit = DbColsUnitClass() _debug = False _variable_that_is_not_saved_to_config = "Hei" _prm_default_name = ".cellpy_prms_default.conf" _prm_globtxt = ".cellpy_prms*.conf" _odbcs = ["pyodbc", "ado", "pypyodbc"] _odbc = "pyodbc" _search_for_odbc_driver = True _allow_multi_test_file = False _use_filename_cache = True _sub_process_path = Path(__file__) / "../../../bin/mdbtools-win/mdb-export" _sub_process_path = _sub_process_path.resolve() _sort_if_subprocess = True _cellpyfile_root = "CellpyData" _cellpyfile_raw = "/raw" _cellpyfile_step = "/steps" _cellpyfile_summary = "/summary" _cellpyfile_fid = "/fid" _cellpyfile_common_meta = "/info" _cellpyfile_test_dependent_meta = "/info_test_dependent" _cellpyfile_raw_unit_pre_id = "raw_unit_" _cellpyfile_raw_limit_pre_id = "" _cellpyfile_complevel = 1 _cellpyfile_complib = None # currently, defaults to "zlib" _cellpyfile_raw_format = "table" _cellpyfile_summary_format = "table" _cellpyfile_stepdata_format = "table" _cellpyfile_infotable_format = "fixed" _cellpyfile_fidtable_format = "fixed" _date_time_format = "%Y-%m-%d %H:%M:%S:%f" # templates _standard_template_uri = ( f"https://github.com/{_github_repo_parent}/{_github_templates_repo}" ) _registered_templates = { "standard": (_standard_template_uri, "standard"), # (repository, name-of-folder) "ife": (_standard_template_uri, "ife"), "single": (_standard_template_uri, "single"), } # used as global variables _globals_status = "" _globals_errors = [] _globals_message = [] # general settings for loaders _minimum_columns_to_keep_for_raw_if_exists = [ "data_point_txt", "datetime_txt", "test_time_txt", "step_time_txt", "cycle_index_txt", "step_time_txt", "step_index_txt", "current_txt", "voltage_txt", "charge_capacity_txt", "discharge_capacity_txt", "power_txt", ] # used during development for testing new features _res_chunk = 0