Skip to content

Commit 07aa64e

Browse files
Merge pull request #14 from rosalindfranklininstitute/dev-temp
Dev temp
2 parents 2d94e8b + ac6ed1d commit 07aa64e

File tree

14 files changed

+1247
-376
lines changed

14 files changed

+1247
-376
lines changed

GeoLlama/calc_by_slice.py

Lines changed: 88 additions & 147 deletions
Large diffs are not rendered by default.

GeoLlama/config.py

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
# Copyright 2023 Rosalind Franklin Institute
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing,
10+
# software distributed under the License is distributed on an
11+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
12+
# either express or implied. See the License for the specific
13+
# language governing permissions and limitations under the License.
14+
15+
###########################################
16+
## Module : GeoLlama.config ##
17+
## Created : Neville Yee ##
18+
## Date created : 03-May-2024 ##
19+
## Date last modified : 03-May-2024 ##
20+
###########################################
21+
22+
import os
23+
24+
import typing
25+
from pathlib import Path
26+
import multiprocessing as mp
27+
28+
from GeoLlama import objects
29+
30+
31+
def generate_config(output_path):
32+
"""
33+
Generates default configuration file
34+
35+
Args:
36+
output_path (str) : Path to output yaml file
37+
"""
38+
import ruamel.yaml
39+
40+
config_str = """ \
41+
# Essential parameters
42+
data_path: null
43+
pixel_size_nm: null
44+
45+
# Optional parameters
46+
binning: 0
47+
autocontrast: True
48+
adaptive: True
49+
bandpass: False
50+
num_cores: 1
51+
output_csv_path: null
52+
output_star_path: null
53+
output_mask: True
54+
55+
# Analytics parameters
56+
thickness_lower_limit: 120
57+
thickness_upper_limit: 300
58+
thickness_std_limit: 15
59+
xtilt_std_limit: 5
60+
displacement_limit : 25
61+
displacement_std_limit : 5
62+
"""
63+
64+
yaml = ruamel.yaml.YAML()
65+
data = yaml.load(config_str)
66+
67+
yaml.default_flow_style=False
68+
yaml.dump(data, Path(output_path))
69+
70+
71+
def read_config(
72+
config_fname: str
73+
) -> objects.Config:
74+
"""
75+
Parse GeoLlama config YAML file
76+
77+
Args:
78+
config_fname (str) : Path to config file
79+
80+
Returns:
81+
Config
82+
"""
83+
import ruamel.yaml
84+
85+
if not os.path.exists(config_fname):
86+
raise IOError(f"{config_fname} does not exist.")
87+
88+
yaml = ruamel.yaml.YAML()
89+
config_dict = yaml.load(Path(config_fname))
90+
91+
# Initialise a Config object
92+
params = objects.Config()
93+
94+
# Check config file has correct dictionary keys
95+
for key in params.__dict__.keys():
96+
try:
97+
params.__setattr__(key, config_dict[key])
98+
except ValueError:
99+
print(f"{key} keyword missing in config file.")
100+
101+
return params
102+
103+
104+
def objectify_user_input(
105+
autocontrast: typing.Optional[bool],
106+
adaptive: typing.Optional[bool],
107+
bandpass: typing.Optional[bool],
108+
data_path: typing.Optional[str],
109+
pixel_size_nm: typing.Optional[float],
110+
binning: typing.Optional[int],
111+
num_cores: typing.Optional[int],
112+
output_csv_path: typing.Optional[str],
113+
output_star_path: typing.Optional[str],
114+
output_mask: typing.Optional[bool],
115+
116+
thickness_lower_limit: typing.Optional[float],
117+
thickness_upper_limit: typing.Optional[float],
118+
thickness_std_limit: typing.Optional[float],
119+
xtilt_std_limit: typing.Optional[float],
120+
displacement_limit : typing.Optional[float],
121+
displacement_std_limit : typing.Optional[float],
122+
) -> objects.Config:
123+
"""
124+
Objectifying user provided input as a Config object
125+
126+
Args:
127+
autocontrast (bool) : Apply autocontrast to slices prior to evaluation
128+
adaptive (bool) : Use adaptive sampling for slice evaluation
129+
bandpass (bool) : Apply bandpass filter to tomograms prior to evaluation
130+
user_path (str) : Path to folder holding all tomograms in batch mode
131+
pixel_size (float) : Pixel size of input tomogram in nm
132+
binning (int) : Binning factor for tomogram evaluation
133+
cpu (int) : Number of CPUs used
134+
output_csv (str) : Output path for CSV file
135+
output_star (str) : Output path for STAR file
136+
output_mask (bool) : Produce 3D mask of estimated lamella region (same shape as input tomogram)
137+
thickness_lower_limit (float) : Lower limit of lamella thickness in nm (for feature extraction)
138+
thickness_upper_limit (float) : Upper limit of lamella thickness in nm (for feature extraction)
139+
thickness_std_limit (float) : Limit of lamella thickness standard deviation in nm (for feature extraction)
140+
xtilt_std_limit (float) : Limit of lamella xtilt standard deviation in degrees (for feature extraction)
141+
displacement_limit (float) : Limit of lamella centroid displacement in % (for feature extraction)
142+
displacement_std_limit (float) : Limit of lamella centroid displacement standard deviation in % (for feature extraction)
143+
144+
Returns:
145+
Config
146+
"""
147+
params = objects.Config()
148+
for key in params.__dict__.keys():
149+
params.__setattr__(key, locals()[key])
150+
151+
return params
152+
153+
154+
def check_config(
155+
params: objects.Config
156+
):
157+
"""
158+
Check datatypes in parameters
159+
160+
Args:
161+
config (Config) : Config object storing all parameters
162+
"""
163+
164+
if params.data_path is None:
165+
raise ValueError("Data path (-p) must be given.")
166+
elif not os.path.isdir(Path(params.data_path)):
167+
raise NotADirectoryError("Given path must be a folder.")
168+
169+
if params.pixel_size_nm is None:
170+
raise ValueError("Pixel size (-s) must be given.")
171+
elif params.pixel_size_nm <= 0:
172+
raise ValueError("Pixel size (-s) must be a positive number.")
173+
174+
if not isinstance(params.num_cores, int):
175+
raise ValueError("num_cores (-np) must be an integer.")
176+
elif not 1 <= params.num_cores <= mp.cpu_count():
177+
raise ValueError(f"num_cores (-np) must be between 1 and # CPUs available ({mp.cpu_count()}). Current settings: {params.num_cores}")

0 commit comments

Comments
 (0)