Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: new wavelength workflow #162

Merged
merged 4 commits into from
Feb 6, 2025

Conversation

yucongalicechen
Copy link
Collaborator

@yucongalicechen yucongalicechen commented Jan 31, 2025

closes #161
I will add functionality to load wavelength/anode type from config file in another PR after this is merged
@sbillinge ready for review


Returns
-------
args : argparse.Namespace
The updated arguments with the wavelength.
"""
if args.wavelength is None:
# first load values from config file
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added a comment here. will make another PR for this functionality

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you do that, if possible, let's make things reusable. Either reuse the user machinery in diffpy.utils, or refactor over there so that we can reuse it here for this more general task, rather than putting some bespoke function here. I think one task is maintaining and interacting with a diffpy config file, and specific functions are interacting it for user, orcid and so on, and another it interact with it for wavelength, etc. let's just come up with some "plan" that makes sense.

Copy link
Collaborator Author

@yucongalicechen yucongalicechen Feb 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the idea would be similar to the get_user_info function, but since the parameters we pass in are different we cannot reuse it completely. I'm thinking about a function like this:

def load_config_file(args):
         load local config file
         load global config file
         if wavelength/anodetype is present in args:
               return
         elif look for wavelength/anode type in local config file:
               if present:
                   return
         elif look for wavelength/anode type in global config file:
               if present:
                   return
         return args

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the difference between this and user info is that we cannot just use what's in the config file if user specified anything in args. For example, if user specified wavelength=0.25 while having config file info with anodetype=Mo we don't want to overload anode type to Mo which will cause an error. So I'm not sure how much can be reused. But maybe we can make this more general here, so that this function can be reused in the future?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess what I am saying is that there are general tasks (like load_config_file()) that should be in diffpy-utils and do just one thing (in that case, run the config-file loading logic).

Then different apps like yours would use that file, so in your app you would have logic like

config_args = load_config_file()
parser_args = load_parser()
args = <logic for merging config and cli args>

kind of thing. Your "load_config_file" is doing two things. It is loading the config files in the right order, but it is also running logic on the contents.

Copy link

codecov bot commented Jan 31, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 99.21%. Comparing base (f805fe3) to head (1dc6972).
Report is 10 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #162   +/-   ##
=======================================
  Coverage   99.21%   99.21%           
=======================================
  Files           5        5           
  Lines         254      254           
=======================================
  Hits          252      252           
  Misses          2        2           
Files with missing lines Coverage Δ
tests/test_tools.py 98.50% <100.00%> (ø)

Copy link
Contributor

@sbillinge sbillinge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

super! Please see comments.

Raised when input wavelength is non-positive
or if input anode_type is not one of the known sources.
Raised if:
(1) neither is provided, and either mu*D needs to be looked up or
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

neither what? It is implied but I would make it explicit here.


Returns
-------
args : argparse.Namespace
The updated arguments with the wavelength.
"""
if args.wavelength is None:
# first load values from config file
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you do that, if possible, let's make things reusable. Either reuse the user machinery in diffpy.utils, or refactor over there so that we can reuse it here for this more general task, rather than putting some bespoke function here. I think one task is maintaining and interacting with a diffpy config file, and specific functions are interacting it for user, orcid and so on, and another it interact with it for wavelength, etc. let's just come up with some "plan" that makes sense.

if args.wavelength is None:
# first load values from config file
if args.wavelength is None and args.anode_type is None:
if not (args.mud is not None and args.xtype in ANGLEQUANTITIES):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a comment might help readability here. Whilst the logic can, in principle, be parsed from the code, double-negatives and ANDs make it hard, so a brief comment about the desired outcome could help here. Normally, I like code to "self comment" and not put comments, and to simplify code to accomplish this, but here probably there is no way to simplify the logic correctly so a comment is ok.

@@ -515,6 +519,8 @@ def test_load_metadata(mocker, user_filesystem):
cli_inputs = [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs the "such and such, expect so and so" treatment

@yucongalicechen
Copy link
Collaborator Author

@sbillinge ready for another review!

Copy link
Contributor

@sbillinge sbillinge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good progress. Please see my comment. We can move things to a different PR to make it easier to review if you want to make an issue again.....


Returns
-------
args : argparse.Namespace
The updated arguments with the wavelength.
"""
if args.wavelength is None:
# first load values from config file
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess what I am saying is that there are general tasks (like load_config_file()) that should be in diffpy-utils and do just one thing (in that case, run the config-file loading logic).

Then different apps like yours would use that file, so in your app you would have logic like

config_args = load_config_file()
parser_args = load_parser()
args = <logic for merging config and cli args>

kind of thing. Your "load_config_file" is doing two things. It is loading the config files in the right order, but it is also running logic on the contents.

@yucongalicechen
Copy link
Collaborator Author

good progress. Please see my comment. We can move things to a different PR to make it easier to review if you want to make an issue again.....

Yes I can work on the config workflow on a separate PR. I see what you mean. I think there's a load_config function in diffpy.utils that we can reuse.

Raised when input wavelength is non-positive
or if input anode_type is not one of the known sources.
Raised if:
(1) neither wavelength or anode type is provided,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the muD requirement here to simplify the logic. I think we will set wavelength before setting muD, so maybe we can raise the error there when we look up the muD?

raise ValueError(
f"Please provide a wavelength or anode type "
f"because the independent variable axis is not on two-theta. "
f"Allowed anode types are {*known_sources, }."
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

edited error msg

@sbillinge sbillinge merged commit 1a263b4 into diffpy:main Feb 6, 2025
5 checks passed
@sbillinge
Copy link
Contributor

ok, thanks @yucongalicechen . I got a bit tired of looking at this PR so I merged it. I hope that we have good issues posted for all the unfinished work...... :)

@yucongalicechen yucongalicechen deleted the wavelength-workflow branch February 7, 2025 00:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

feat: workflow for getting wavelength/anode type
2 participants