3939# and will be written into separate arguments for clarity.
4040METADATA_KEYS_TO_EXCLUDE = [
4141 "output_correction" ,
42- "force_overwrite" ,
4342 "input" ,
4443 "input_paths" ,
45- "wavelength" ,
46- "theoretical_from_density" ,
47- "theoretical_from_packing" ,
48- "subcommand" ,
44+ "force" ,
45+ "energy" ,
4946]
5047
5148
@@ -166,8 +163,52 @@ def set_input_lists(args):
166163 return args
167164
168165
166+ def normalize_wavelength (args ):
167+ """Normalize args.wavelength to a float.
168+
169+ If args.wavelength is:
170+ - None: return args unchanged
171+ - float-like: convert to float
172+ - string: look up corresponding value in WAVELENGTHS (case-insensitive)
173+
174+ Parameters
175+ ----------
176+ args : argparse.Namespace
177+ The arguments from the parser.
178+
179+ Returns
180+ -------
181+ args : argparse.Namespace
182+ The updated arguments with args.wavelength.
183+
184+ Raises
185+ ------
186+ ValueError
187+ If a string wavelength is not a known source.
188+ """
189+ if args .wavelength is None :
190+ return args
191+ try :
192+ args .wavelength = float (args .wavelength )
193+ return args
194+ except (TypeError , ValueError ):
195+ pass
196+ key = str (args .wavelength ).strip ()
197+ matched = next (
198+ (k for k in WAVELENGTHS if k .lower () == key .lower ()),
199+ None ,
200+ )
201+ if matched is None :
202+ raise ValueError (
203+ f"Anode type '{ args .wavelength } ' not recognized. "
204+ f"Please rerun specifying an anode type from { * known_sources , } ."
205+ )
206+ args .wavelength = WAVELENGTHS [matched ]
207+ return args
208+
209+
169210def load_wavelength_from_config_file (args ):
170- """Load wavelength and anode type from config files.
211+ """Load wavelength from config files.
171212
172213 It prioritizes values in the following order:
173214 1. cli inputs, 2. local config file, 3. global config file.
@@ -184,12 +225,8 @@ def load_wavelength_from_config_file(args):
184225 """
185226 global_config = _load_config (Path ().home () / "diffpyconfig.json" )
186227 local_config = _load_config (Path ().cwd () / "diffpyconfig.json" )
187- local_has_data = local_config and (
188- "wavelength" in local_config or "anode_type" in local_config
189- )
190- global_has_data = global_config and (
191- "wavelength" in global_config or "anode_type" in global_config
192- )
228+ local_has_data = local_config and "wavelength" in local_config
229+ global_has_data = global_config and "wavelength" in global_config
193230 if not local_has_data and not global_has_data :
194231 print (
195232 "No configuration file was found containing information "
@@ -202,76 +239,54 @@ def load_wavelength_from_config_file(args):
202239 "For more information, please refer to www.diffpy.org/"
203240 "diffpy.labpdfproc/examples/toolsexample.html"
204241 )
205-
206- if args .wavelength or args .anode_type :
207- return args
242+ if args .wavelength is not None :
243+ return normalize_wavelength (args )
208244 config = local_config if local_has_data else global_config
209245 if config :
210- args .wavelength = args . wavelength or config .get ("wavelength" )
211- args . anode_type = args . anode_type or config . get ( "anode_type" )
246+ args .wavelength = config .get ("wavelength" )
247+ return normalize_wavelength ( args )
212248 return args
213249
214250
215251def set_wavelength (args ):
216- """Set the wavelength based on the given anode_type or wavelength.
252+ """Set the wavelength based on args. wavelength.
217253
218- First checks from args. If neither is provided,
219- it attempts to load from local and then global config file.
254+ args.wavelength may be:
255+ - None
256+ - a number (explicit wavelength in Å)
257+ - a string (X-ray source name)
258+
259+ If a string is provided, it must match a key in WAVELENGTHS.
220260
221261 Parameters
222262 ----------
223263 args : argparse.Namespace
224- The arguments from the parser.
225264
226265 Raises
227266 ------
228267 ValueError
229- Raised if:
230- (1) neither wavelength or anode type is provided
231- and xtype is not the two-theta grid,
232- (2) both are provided,
233- (3) anode_type is not one of the known sources,
234- (4) wavelength is non-positive.
268+ If wavelength is required but missing,
269+ if a string wavelength is not a known source,
270+ or if a numeric wavelength is non-positive.
235271
236272 Returns
237273 -------
238274 args : argparse.Namespace
239- The updated arguments with the wavelength.
275+ Updated arguments with args. wavelength as a float .
240276 """
241- args = load_wavelength_from_config_file (args )
242- if args .wavelength is None and args . anode_type is None :
277+ args = normalize_wavelength (args )
278+ if args .wavelength is None :
243279 if args .xtype not in ANGLEQUANTITIES :
244280 raise ValueError (
245281 f"Please provide a wavelength or anode type "
246282 f"because the independent variable axis is not on two-theta. "
247283 f"Allowed anode types are { * known_sources , } ."
248284 )
249- elif args .wavelength is not None and args .anode_type is not None :
250- raise ValueError (
251- f"Please provide either a wavelength or an anode type, not both. "
252- f"Allowed anode types are { * known_sources , } ."
253- )
254- elif args .anode_type is not None :
255- matched_anode_type = next (
256- (
257- key
258- for key in WAVELENGTHS
259- if key .lower () == args .anode_type .lower ()
260- ),
261- None ,
262- )
263- if matched_anode_type is None :
264- raise ValueError (
265- f"Anode type '{ args .anode_type } ' not recognized. "
266- f"Please rerun specifying an anode_type "
267- f"from { * known_sources , } ."
268- )
269- args .anode_type = matched_anode_type
270- args .wavelength = WAVELENGTHS [args .anode_type ]
271- elif args .wavelength is not None and args .wavelength <= 0 :
285+ return args
286+ if args .wavelength <= 0 :
272287 raise ValueError (
273288 f"Wavelength = { args .wavelength } is not valid. "
274- "Please rerun specifying a known anode_type "
289+ "Please rerun specifying a known anode type "
275290 "or a positive wavelength."
276291 )
277292 return args
@@ -336,16 +351,18 @@ def _parse_theoretical_input(input_str):
336351def _set_theoretical_mud_from_density (args ):
337352 """Theoretical estimation of mu*D from sample composition, energy, and
338353 sample mass density."""
339- sample_composition , energy , sample_mass_density = _parse_theoretical_input (
340- args .theoretical_from_density
341- )
342- args . sample_composition = sample_composition
354+ args = normalize_wavelength ( args )
355+ if args .wavelength is None :
356+ args = load_wavelength_from_config_file ( args )
357+ energy = 12.398 / args . wavelength
343358 args .energy = energy
344- args .sample_mass_density = sample_mass_density
345- args .mud = compute_mu_using_xraydb (
346- args .sample_composition ,
347- args .energy ,
348- sample_mass_density = args .sample_mass_density ,
359+ args .mud = (
360+ compute_mu_using_xraydb (
361+ args .sample_composition ,
362+ args .energy ,
363+ sample_mass_density = args .sample_mass_density ,
364+ )
365+ * args .diameter
349366 )
350367 return args
351368
@@ -359,10 +376,13 @@ def _set_theoretical_mud_from_packing(args):
359376 args .sample_composition = sample_composition
360377 args .energy = energy
361378 args .packing_fraction = packing_fraction
362- args .mud = compute_mu_using_xraydb (
363- args .sample_composition ,
364- args .energy ,
365- packing_fraction = args .packing_fraction ,
379+ args .mud = (
380+ compute_mu_using_xraydb (
381+ args .sample_composition ,
382+ args .energy ,
383+ packing_fraction = args .packing_fraction ,
384+ )
385+ * args .diameter
366386 )
367387 return args
368388
@@ -386,12 +406,12 @@ def set_mud(args):
386406 args : argparse.Namespace
387407 The updated arguments with mu*D.
388408 """
389- if args .z_scan_file :
409+ if args .command == "mud" :
410+ return args
411+ if args .command == "zscan" :
390412 return _set_mud_from_zscan (args )
391- elif args .theoretical_from_density :
413+ if args .command == "sample" :
392414 return _set_theoretical_mud_from_density (args )
393- elif args .theoretical_from_packing :
394- return _set_theoretical_mud_from_packing (args )
395415 return args
396416
397417
@@ -507,6 +527,7 @@ def preprocessing_args(args):
507527 args : argparse.Namespace
508528 The updated argparse Namespace with arguments preprocessed.
509529 """
530+ args = load_wavelength_from_config_file (args )
510531 args = set_mud (args )
511532 args = set_input_lists (args )
512533 args = set_output_directory (args )
@@ -518,6 +539,7 @@ def preprocessing_args(args):
518539 return args
519540
520541
542+ # Update load_metadata to use 'input_directory' consistently:
521543def load_metadata (args , filepath ):
522544 """Load the relevant metadata from args to write into the header of the
523545 output files.
@@ -538,6 +560,7 @@ def load_metadata(args, filepath):
538560 metadata = copy .deepcopy (vars (args ))
539561 for key in METADATA_KEYS_TO_EXCLUDE :
540562 metadata .pop (key , None )
563+ metadata ["mud" ] = round (float (metadata ["mud" ]), 4 )
541564 metadata ["input_directory" ] = str (filepath )
542565 metadata ["output_directory" ] = str (metadata ["output_directory" ])
543566 return metadata
0 commit comments