Skip to content

Commit 1a263b4

Browse files
authored
Merge pull request #162 from yucongalicechen/wavelength-workflow
feat: new wavelength workflow
2 parents 270127c + 1dc6972 commit 1a263b4

File tree

4 files changed

+95
-47
lines changed

4 files changed

+95
-47
lines changed

news/wavelength-workflow.rst

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
**Added:**
2+
3+
* <news item>
4+
5+
**Changed:**
6+
7+
* Workflow for loading wavelength - raise an error when both wavelength and anode type are specified.
8+
9+
**Deprecated:**
10+
11+
* <news item>
12+
13+
**Removed:**
14+
15+
* <news item>
16+
17+
**Fixed:**
18+
19+
* <news item>
20+
21+
**Security:**
22+
23+
* <news item>

src/diffpy/labpdfproc/labpdfprocapp.py

+9-12
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@ def define_arguments():
3030
"in a file with name file_list.txt. "
3131
"If one or more directory is provided, all valid "
3232
"data-files in that directory will be processed. "
33-
"Examples of valid "
34-
"inputs are 'file.xy', 'data/file.xy', "
33+
"Examples of valid inputs are 'file.xy', 'data/file.xy', "
3534
"'file.xy, data/file.xy', "
3635
"'.' (load everything in the current directory), "
3736
"'data' (load everything in the folder ./data), "
@@ -48,18 +47,16 @@ def define_arguments():
4847
"name": ["-a", "--anode-type"],
4948
"help": (
5049
f"The type of the x-ray source. "
51-
f"Allowed values are {*[known_sources], }. "
50+
f"Allowed values are {*known_sources, }. "
5251
f"Either specify a known x-ray source or specify wavelength."
5352
),
54-
"default": "Mo",
53+
"default": None,
5554
},
5655
{
5756
"name": ["-w", "--wavelength"],
5857
"help": (
5958
"X-ray source wavelength in angstroms. "
60-
"Not needed if the anode-type is specified. "
61-
"This wavelength will override the anode wavelength "
62-
"if both are specified."
59+
"Not needed if the anode-type is specified."
6360
),
6461
"type": float,
6562
},
@@ -104,7 +101,7 @@ def define_arguments():
104101
f"The method for computing absorption correction. "
105102
f"Allowed methods: {*CVE_METHODS, }. "
106103
f"Default method is polynomial interpolation "
107-
f"if not specified. "
104+
f"if not specified."
108105
),
109106
"default": "polynomial_interpolation",
110107
},
@@ -121,7 +118,7 @@ def define_arguments():
121118
"For example, facility='NSLS II', "
122119
"'facility=NSLS II', beamline=28ID-2, "
123120
"'beamline'='28ID-2', 'favorite color'=blue, "
124-
"are all valid key=value items. "
121+
"are all valid key=value items."
125122
),
126123
"nargs": "+",
127124
"metavar": "KEY=VALUE",
@@ -131,7 +128,7 @@ def define_arguments():
131128
"help": (
132129
"Username will be loaded from config files. "
133130
"Specify here only if you want to "
134-
"override that behavior at runtime. "
131+
"override that behavior at runtime."
135132
),
136133
"default": None,
137134
},
@@ -140,7 +137,7 @@ def define_arguments():
140137
"help": (
141138
"Email will be loaded from config files. "
142139
"Specify here only if you want to "
143-
"override that behavior at runtime. "
140+
"override that behavior at runtime."
144141
),
145142
"default": None,
146143
},
@@ -149,7 +146,7 @@ def define_arguments():
149146
"help": (
150147
"ORCID will be loaded from config files. "
151148
"Specify here only if you want to "
152-
"override that behavior at runtime. "
149+
"override that behavior at runtime."
153150
),
154151
"default": None,
155152
},

src/diffpy/labpdfproc/tools.py

+32-16
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,10 @@ def set_input_lists(args):
160160

161161

162162
def set_wavelength(args):
163-
"""Set the wavelength based on the given anode_type.
164-
If a wavelength is provided,
165-
it will be used, and the anode_type argument will be removed.
163+
"""Set the wavelength based on the given anode_type or wavelength.
164+
165+
First checks from args. If neither is provided,
166+
it attempts to load from local and then global config file.
166167
167168
Parameters
168169
----------
@@ -172,15 +173,32 @@ def set_wavelength(args):
172173
Raises
173174
------
174175
ValueError
175-
Raised when input wavelength is non-positive
176-
or if input anode_type is not one of the known sources.
176+
Raised if:
177+
(1) neither wavelength or anode type is provided,
178+
and xtype is not the two-theta grid,
179+
(2) both are provided,
180+
(3) anode_type is not one of the known sources,
181+
(4) wavelength is non-positive.
177182
178183
Returns
179184
-------
180185
args : argparse.Namespace
181186
The updated arguments with the wavelength.
182187
"""
183-
if args.wavelength is None:
188+
# first load values from config file
189+
if args.wavelength is None and args.anode_type is None:
190+
if args.xtype not in ANGLEQUANTITIES:
191+
raise ValueError(
192+
f"Please provide a wavelength or anode type "
193+
f"because the independent variable axis is not on two-theta. "
194+
f"Allowed anode types are {*known_sources, }."
195+
)
196+
elif args.wavelength is not None and args.anode_type is not None:
197+
raise ValueError(
198+
f"Please provide either a wavelength or an anode type, not both. "
199+
f"Allowed anode types are {*known_sources, }."
200+
)
201+
elif args.anode_type is not None:
184202
matched_anode_type = next(
185203
(
186204
key
@@ -197,15 +215,12 @@ def set_wavelength(args):
197215
)
198216
args.anode_type = matched_anode_type
199217
args.wavelength = WAVELENGTHS[args.anode_type]
200-
else:
201-
if args.wavelength <= 0:
202-
raise ValueError(
203-
"No valid wavelength. "
204-
"Please rerun specifying a known anode_type "
205-
"or a positive wavelength."
206-
)
207-
else:
208-
delattr(args, "anode_type")
218+
elif args.wavelength is not None and args.wavelength <= 0:
219+
raise ValueError(
220+
"No valid wavelength. "
221+
"Please rerun specifying a known anode_type "
222+
"or a positive wavelength."
223+
)
209224
return args
210225

211226

@@ -362,7 +377,8 @@ def load_package_info(args):
362377
def preprocessing_args(args):
363378
"""Perform preprocessing on the provided args.
364379
The process includes loading package and user information,
365-
setting input, output, wavelength, xtype, mu*D, and loading user metadata.
380+
setting input, output, wavelength, anode type, xtype, mu*D,
381+
and loading user metadata.
366382
367383
Parameters
368384
----------

tests/test_tools.py

+31-19
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,7 @@ def test_set_output_directory_bad(user_filesystem):
198198
@pytest.mark.parametrize(
199199
"inputs, expected",
200200
[
201-
# C1: nothing passed in, expect default is Mo
202-
([], {"wavelength": 0.71073, "anode_type": "Mo"}),
203-
# C2: only a valid anode type was entered (case independent),
201+
# C1: only a valid anode type was entered (case independent),
204202
# expect to match the corresponding wavelength
205203
# and preserve the correct case anode type
206204
(["--anode-type", "Mo"], {"wavelength": 0.71073, "anode_type": "Mo"}),
@@ -239,45 +237,52 @@ def test_set_output_directory_bad(user_filesystem):
239237
["--anode-type", "cuka1"],
240238
{"wavelength": 1.54056, "anode_type": "CuKa1"},
241239
),
242-
# C3: only a valid wavelength was entered,
240+
# C2: a valid wavelength was entered,
243241
# expect to include the wavelength only and anode type is None
244242
(["--wavelength", "0.25"], {"wavelength": 0.25, "anode_type": None}),
245-
# C4: both valid anode type and wavelength were entered,
246-
# expect to remove the anode type and preserve wavelength only
247-
(
248-
["--wavelength", "0.25", "--anode-type", "Ag"],
249-
{"wavelength": 0.25, "anode_type": None},
250-
),
243+
# C3: nothing passed in, but mu*D was provided and xtype is on tth
244+
# expect wavelength and anode type to be None
245+
# and program proceeds without error
246+
([], {"wavelength": None, "anode_type": None}),
251247
],
252248
)
253249
def test_set_wavelength(inputs, expected):
254250
cli_inputs = ["2.5", "data.xy"] + inputs
255251
actual_args = get_args(cli_inputs)
256252
actual_args = set_wavelength(actual_args)
257253
assert actual_args.wavelength == expected["wavelength"]
258-
assert getattr(actual_args, "anode_type", None) == expected["anode_type"]
254+
assert actual_args.anode_type == expected["anode_type"]
259255

260256

261257
@pytest.mark.parametrize(
262258
"inputs, expected_error_msg",
263259
[
264-
(
260+
( # C1: nothing passed in, xtype is not on tth
261+
# expect error asking for either wavelength or anode type
262+
["--xtype", "q"],
263+
f"Please provide a wavelength or anode type "
264+
f"because the independent variable axis is not on two-theta. "
265+
f"Allowed anode types are {*known_sources, }.",
266+
),
267+
( # C2: both wavelength and anode type were specified
268+
# expect error asking not to specify both
269+
["--wavelength", "0.7", "--anode-type", "Mo"],
270+
f"Please provide either a wavelength or an anode type, not both. "
271+
f"Allowed anode types are {*known_sources, }.",
272+
),
273+
( # C3: invalid anode type
274+
# expect error asking to specify a valid anode type
265275
["--anode-type", "invalid"],
266276
f"Anode type not recognized. "
267277
f"Please rerun specifying an anode_type from {*known_sources, }.",
268278
),
269-
(
279+
( # C4: invalid wavelength
280+
# expect error asking to specify a valid wavelength or anode type
270281
["--wavelength", "0"],
271282
"No valid wavelength. "
272283
"Please rerun specifying a known anode_type "
273284
"or a positive wavelength.",
274285
),
275-
(
276-
["--wavelength", "-1", "--anode-type", "Mo"],
277-
"No valid wavelength. "
278-
"Please rerun specifying a known anode_type "
279-
"or a positive wavelength.",
280-
),
281286
],
282287
)
283288
def test_set_wavelength_bad(inputs, expected_error_msg):
@@ -502,6 +507,11 @@ def test_load_package_info(mocker):
502507

503508

504509
def test_load_metadata(mocker, user_filesystem):
510+
# Test if the function loads args
511+
# (which will be loaded into the header file).
512+
# Expect to include mu*D, anode type, xtype, cve method,
513+
# user-specified metadata, user info, package info, z-scan file,
514+
# and full paths for current input and output directories.
505515
cwd = Path(user_filesystem)
506516
home_dir = cwd / "home_dir"
507517
mocker.patch("pathlib.Path.home", lambda _: home_dir)
@@ -515,6 +525,8 @@ def test_load_metadata(mocker, user_filesystem):
515525
cli_inputs = [
516526
"2.5",
517527
".",
528+
"--anode-type",
529+
"Mo",
518530
"--user-metadata",
519531
"key=value",
520532
"--username",

0 commit comments

Comments
 (0)