"""
Sets up the project configration.
"""
import os
import json
import pathlib
from typing import List, Optional
from exr.io import create_folder_structure
from exr.utils import chmod, configure_logger
logger = configure_logger('ExR-Tools')
[docs]
class Config:
r"""
A class used to manage and represent the configuration for the ExR-Tools software.
This class handles the setup of paths, parameters, and project-specific settings. It also manages
the creation of directory structures and file permissions as required. Configurations can be saved to
or loaded from a JSON file for persistent use.
**Methods:**
- `set_config`: Configures various parameters for the ExR-Tools.
- `save_config`: Saves the current configuration to a JSON file.
- `load_config`: Loads configuration from a JSON file.
- `create_directory_structure`: Creates the necessary directory structure for the project.
- `set_permissions`: Modifies file permissions for the project directory.
- `print`: Outputs all current configuration attributes.
"""
def __init__(self):
pass
def __str__(self):
r"""Returns a string representation of the Config object."""
return str(self.__dict__)
def __repr__(self):
r"""Returns a string that reproduces the Config object when fed to eval()."""
return self.__str__()
[docs]
def set_config(self,
raw_data_path: str,
processed_data_path: Optional[str] = None,
rounds: List[int] = list(range(10)),
rois: Optional[int] = None,
spacing: List[float] = [0.250,0.1625,0.1625],
channel_names: List[str] = ['640','561','488'],
ref_round: int = 1,
ref_channel: str = '640',
permission: Optional[bool] = False,
create_directory_structure: Optional[bool] = True,
config_file_name: str = 'exr_tools_config',
) -> None:
r"""
Sets up the configuration parameters for running ExR-Tools.
:param raw_data_path: The absolute path to the raw data directory. There is no default value, this must be provided.
:type raw_data_path: str
:param processed_data_path: The absolute path to the processed data directory. Default is a 'processed_data' subdirectory inside the raw_data_path.
:type processed_data_path: str
:param rounds: List of the number of rounds in the ExR dataset. Default is list(range(10)).
:type rounds: List[int]
:param rois: The number of region of interests. Default is None, in which case the regions of interest will be inferred from the raw data.
:type rois: List[int]
:param spacing: Spacing between pixels in the format [X,Y,Z]. Default is [0.1625,0.1625,0.250].
:type spacing: List[float]
:param channel_names: Names of channels in the ND2 file. Default is ['633','546','488'].
:type channel_names: List[str]
:param ref_round: Reference round number. Default is 1.
:type ref_round: int
:param ref_channel: Reference channel name. Default is '633'.
:type ref_channel: str
:param permission: If set to True, changes permission of the raw_data_path to allow other users to read and write on the generated files. Default is None, in which case permissions will not be modified.
:type permission: bool
:param create_directroy_struc: If set to True, creates the directory structure in the specified project path. Default is None, in which case the directory structure will not be created.
:type create_directroy_struc: bool
:param config_file_name: Name of the configuration file. Default is 'exr_tools_config'.
:type config_file_name: str
"""
try:
self.raw_data_path = os.path.abspath(raw_data_path)
self.rounds = rounds
self.spacing = spacing
self.ref_round = ref_round
self.ref_channel = ref_channel
self.channel_names = channel_names
# Input ND2 path
self.nd2_path = os.path.join(self.raw_data_path , "R{}" , "ROI{}.nd2")
#TODO start files name at 0
if rois is None:
self.rois = list(range(1,len(os.listdir(os.path.dirname(self.nd2_path.format(self.ref_round,1))))+1))
else:
self.rois = list(range(1,rois+1))
# Output h5 path
if processed_data_path is not None:
self.processed_data_path = os.path.abspath(processed_data_path)
else:
self.processed_data_path = os.path.join(self.raw_data_path,"processed_data")
self.h5_path = os.path.join(self.processed_data_path , "R{}" , "ROI{}.h5")
self.roi_analysis_path = os.path.join(self.processed_data_path,"roi_analysis")
if create_directory_structure is not None:
self.create_directory_structure()
if permission is not None:
self.set_permissions()
self.save_config(config_file_name)
except Exception as e:
logger.error(f"Failed to set configuration. Error: {e}")
raise
[docs]
def create_directory_structure(self):
r"""Creates the directory structure in the specified project path."""
try:
create_folder_structure(str(self.processed_data_path),self.rois, self.rounds)
except Exception as e:
logger.error(f"Failed to create directory structure. Error: {e}")
raise
[docs]
def set_permissions(self):
r"""Changes permission of the raw_data_path to allow other users to read and write on the generated files."""
try:
chmod(pathlib.Path(self.processed_data_path))
except Exception as e:
logger.error(f"Failed to set permissions. Error: {e}")
raise
[docs]
def save_config(self, config_file_name):
r"""Saves the configuration to a .json file.
:param config_file_name: Name of the configuration file.
:type config_file_name: str
"""
try:
with open(os.path.join(self.processed_data_path , config_file_name + '.json'), "w") as f:
json.dump(self.__dict__, f)
except Exception as e:
logger.error(f"Failed to save configuration. Error: {e}")
raise
[docs]
def load_config(self, param_path: str) -> None:
r"""Saves the configuration to a .json file.
:param config_file_name: Name of the configuration file.
:type config_file_name: str
"""
try:
param_path = os.path.abspath(param_path)
with open(param_path, "r") as f:
self.__dict__.update(json.load(f))
except Exception as e:
logger.error(f"Failed to load configuration. Error: {e}")
raise
[docs]
def print(self) -> None:
r"""Prints all attributes of the Config object."""
try:
for key, value in self.__dict__.items():
print(f"{key}: {value}")
except Exception as e:
logger.error(f"Failed to print configuration. Error: {e}")
raise