-
Notifications
You must be signed in to change notification settings - Fork 12
add fast_cve to labpdfprocapp.py and some other fixes #87
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
Changes from 8 commits
329a895
6954a29
97bcc00
2487ae6
7d0d574
b7e037e
a450dda
fc4d876
956408d
4bbe4a2
b91b6ec
e7d3d05
bb28204
3c6b128
377607a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,22 @@ | ||
import math | ||
import os | ||
|
||
import numpy as np | ||
import pandas as pd | ||
from scipy.interpolate import interp1d | ||
|
||
from diffpy.utils.scattering_objects.diffraction_objects import Diffraction_object | ||
|
||
RADIUS_MM = 1 | ||
N_POINTS_ON_DIAMETER = 300 | ||
TTH_GRID = np.arange(1, 141, 1) | ||
TTH_GRID = np.arange(1, 180.1, 0.1) | ||
|
||
# pre-computed datasets for fast calculation | ||
MUD_LIST = [0.5, 1, 2, 3, 4, 5, 6] | ||
CWD = os.path.dirname(os.path.abspath(__file__)) | ||
MULS = np.loadtxt(CWD + "/data/inverse_cve.xy") | ||
COEFFICIENT_LIST = np.array(pd.read_csv(CWD + "/data/coefficient_list.csv", header=None)) | ||
INTERPOLATION_FUNCTIONS = [interp1d(MUD_LIST, coefficients, kind="quadratic") for coefficients in COEFFICIENT_LIST] | ||
|
||
|
||
class Gridded_circle: | ||
|
@@ -27,7 +37,7 @@ def _get_grid_points(self): | |
self.grid = {(x, y) for x in xs for y in ys if x**2 + y**2 <= self.radius**2} | ||
self.total_points_in_grid = len(self.grid) | ||
|
||
# def get_coordinate_index(self, coordinate): # I think we probably dont need this function? | ||
# def get_coordinate_index(self, coordinate): | ||
yucongalicechen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# count = 0 | ||
# for i, target in enumerate(self.grid): | ||
# if coordinate == target: | ||
|
@@ -172,9 +182,9 @@ def get_path_length(self, grid_point, angle): | |
return total_distance, primary_distance, secondary_distance | ||
|
||
|
||
def compute_cve(diffraction_data, mud, wavelength): | ||
def compute_cve(diffraction_data, mud, wavelength, brute_force=False): | ||
yucongalicechen marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function naming is a bit confusing. I think the cve is computed in the function you call Let's maybe have a quick conversation about this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added the method argument to args and cleaned up the four relevant functions in functions.py (_cve_brute_force, _cve_polynomial_interpolation, _compute_cve, and interpolate_cve). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I guess my question is whether we need this function. I feel like I want a function where I give it a grid (in the form of a DO) and it gives me a cve, and a function that I give a diffraction pattern and a cve on hte same grid as each other and it gives me a corrected pattern, regardless of what backend is used. So the interpolation step is not needed for the brute-force case, and it probably should be done as part of the cve calculation in the fast cve calculator? I am interested in the cleanest interface for the user. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this function is necessary. If we use the original grid for brute-force calculations, it could take forever to run (so I think the interpolation would be necessary), and the interpolation is accurate since the numbers are small. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. that's ok, I don't mind having an interpolation. I just don't like the current structure because it gives a messy api and difficult to follow code. btw, we might be able to interpolate onto different grids in the DO itself. I wanted to have that capability but not sure if I implemented it. |
||
""" | ||
compute the cve for given diffraction data, mud and wavelength | ||
compute the cve for given diffraction data, mud and wavelength, and a boolean to determine the way to compute | ||
|
||
Parameters | ||
sbillinge marked this conversation as resolved.
Show resolved
Hide resolved
|
||
---------- | ||
|
@@ -185,28 +195,41 @@ def compute_cve(diffraction_data, mud, wavelength): | |
wavelength float | ||
the wavelength of the diffraction object | ||
|
||
Returns | ||
------- | ||
the diffraction object with cve curves | ||
|
||
it is computed as follows: | ||
the brute-force method is computed as follows: | ||
We first resample data and absorption correction to a more reasonable grid, | ||
then calculate corresponding cve for the given mud in the resample grid | ||
(since the same mu*D yields the same cve, we can assume that D/2=1, so mu=mud/2), | ||
and finally interpolate cve to the original grid in diffraction_data. | ||
|
||
Returns | ||
------- | ||
the diffraction object with cve curves | ||
|
||
""" | ||
|
||
mu_sample_invmm = mud / 2 | ||
abs_correction = Gridded_circle(mu=mu_sample_invmm) | ||
distances, muls = [], [] | ||
for angle in TTH_GRID: | ||
abs_correction.set_distances_at_angle(angle) | ||
abs_correction.set_muls_at_angle(angle) | ||
distances.append(sum(abs_correction.distances)) | ||
muls.append(sum(abs_correction.muls)) | ||
distances = np.array(distances) / abs_correction.total_points_in_grid | ||
muls = np.array(muls) / abs_correction.total_points_in_grid | ||
cve = 1 / muls | ||
if brute_force: | ||
mu_sample_invmm = mud / 2 | ||
abs_correction = Gridded_circle(mu=mu_sample_invmm) | ||
distances, muls = [], [] | ||
for angle in TTH_GRID: | ||
abs_correction.set_distances_at_angle(angle) | ||
abs_correction.set_muls_at_angle(angle) | ||
distances.append(sum(abs_correction.distances)) | ||
muls.append(sum(abs_correction.muls)) | ||
distances = np.array(distances) / abs_correction.total_points_in_grid | ||
muls = np.array(muls) / abs_correction.total_points_in_grid | ||
cve = 1 / muls | ||
else: | ||
if mud > 6 or mud < 0.5: | ||
raise ValueError( | ||
"mu*D is out of the acceptable range (0.5 to 6) for fast calculation. " | ||
"Please rerun with a value within this range or use -b to enable brute-force calculation. " | ||
) | ||
coeff_a, coeff_b, coeff_c, coeff_d, coeff_e = [ | ||
interpolation_function(mud) for interpolation_function in INTERPOLATION_FUNCTIONS | ||
] | ||
muls = np.array(coeff_a * MULS**4 + coeff_b * MULS**3 + coeff_c * MULS**2 + coeff_d * MULS + coeff_e) | ||
cve = 1 / muls | ||
|
||
orig_grid = diffraction_data.on_tth[0] | ||
newcve = np.interp(orig_grid, TTH_GRID, cve) | ||
yucongalicechen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -312,6 +312,7 @@ def test_load_metadata(mocker, user_filesystem): | |
"wavelength": 0.71, | ||
"output_directory": str(Path.cwd().resolve()), | ||
"xtype": "tth", | ||
"brute_force": False, | ||
"key": "value", | ||
"username": "cli_username", | ||
"email": "[email protected]", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,15 +17,15 @@ def set_output_directory(args): | |
args argparse.Namespace | ||
the arguments from the parser | ||
|
||
Returns | ||
------- | ||
pathlib.PosixPath that contains the full path of the output directory | ||
|
||
it is determined as follows: | ||
If user provides an output directory, use it. | ||
Otherwise, we set it to the current directory if nothing is provided. | ||
We then create the directory if it does not exist. | ||
|
||
Returns | ||
------- | ||
pathlib.PosixPath that contains the full path of the output directory | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why are we returning posixPath and not just Path? We want it to be platform independent, no? |
||
|
||
""" | ||
output_dir = Path(args.output_directory).resolve() if args.output_directory else Path.cwd().resolve() | ||
output_dir.mkdir(parents=True, exist_ok=True) | ||
|
@@ -110,13 +110,13 @@ def set_wavelength(args): | |
args argparse.Namespace | ||
the arguments from the parser | ||
|
||
we raise an ValueError if the input wavelength is non-positive | ||
yucongalicechen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
or if the input anode_type is not one of the known sources | ||
|
||
Returns | ||
------- | ||
args argparse.Namespace | ||
|
||
we raise an ValueError if the input wavelength is non-positive | ||
or if the input anode_type is not one of the known sources | ||
|
||
""" | ||
if args.wavelength is not None and args.wavelength <= 0: | ||
raise ValueError( | ||
|
Uh oh!
There was an error while loading. Please reload this page.