Skip to content

Conversation

@ohcpaull
Copy link
Contributor

@ohcpaull ohcpaull commented Nov 1, 2020

First attempt at integrating polarised neutron reflectometry files in the reduction workflow. I have slightly altered the reduction code by adding some flags so it knows when data is polarised and to use the new dict element "m_spec_polcorr" instead of "m_spec" for polarised data. Let me know whether you're OK with this approach. I haven't implemented uncertainty analysis for the correction process yet.

ohcpaull and others added 19 commits October 28, 2020 16:33
-correct_PA_efficiencies applies the matrix equation to the raw data.
-polarised_correction returns PlatypusNexus files that have a m_spec_polcorr attribute containing the efficiency corrected spectra
-Have included an extra ReductionOption "polarised" which is True or False

Still some minor teething issues that need to be ironed out
Needed to mess around with ReductionOptions to tell refnx when to reduce m_spec and when to reduce m_spec_polcorr. Still not 100% sure whether this is foolproof, but I am able to plot both raw and polarisation-corrected data using this. Need to make more robust for less vanilla test cases.

Also included new functions in __init__ file
Include a processing step in polarised_correction, and added some comments
np.matrix will be deprecated eventually.
-correct_PA_efficiencies applies the matrix equation to the raw data.
-polarised_correction returns PlatypusNexus files that have a m_spec_polcorr attribute containing the efficiency corrected spectra
-Have included an extra ReductionOption "polarised" which is True or False

Still some minor teething issues that need to be ironed out
Needed to mess around with ReductionOptions to tell refnx when to reduce m_spec and when to reduce m_spec_polcorr. Still not 100% sure whether this is foolproof, but I am able to plot both raw and polarisation-corrected data using this. Need to make more robust for less vanilla test cases.

Also included new functions in __init__ file
Include a processing step in polarised_correction, and added some comments
np.matrix will be deprecated eventually.
# If polarised, add an entry for the polarisation
# efficiency corrected spectra
if polarised is True:
d["m_spec_polcorr"] = np.zeros_like(m_spec)
Copy link
Contributor

Choose a reason for hiding this comment

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

How about d["m_spec_polcorr"] = None?

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think one needs the logic check either.

"""
# Ensure 'polarised' reduction option is initialized
if "polarised" not in reduction_options:
reduction_options["polarised"] = False
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need to check this? Just assume that polarised is in reduction_options.

normalise_bins=True,
manual_beam_find=None,
event_filter=None,
polarised=False,
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it really necessary to have a polarised keyword?

Parameters
----------
pp : PlatypusNexus object
Copy link
Contributor

Choose a reason for hiding this comment

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

the docstring doesn't correspond to the parameters and how they're used later in the function

Copy link
Contributor

Choose a reason for hiding this comment

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

Also in wrong order.

raw11.processed_spectrum["m_spec_polcorr"] = np.asarray(
[[val[0] for val in I11]]
)
elif pm is None and mp is not None:
Copy link
Contributor

Choose a reason for hiding this comment

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

is it necessary to duplicate this section?


# Create efficiency matrices from individual
# component efficiency matrices
efficiencies_matrix = [
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 can be vectorised. If flipper1_eff_matrix, flipper2_eff_matrix, polariser_eff_matrix, analyser_eff_matrix all have the same shape (wavelength.size, 4, 4) then I think one can just do:

flipper1_eff_matrix @ flipper2_eff_matrix @ polariser_eff_matrix @ analyser_eff_matrix

# Invert efficiency matrices for each wavelength
inv_eff_matrix = [
np.linalg.inv(eff_mat) for eff_mat in efficiencies_matrix
]
Copy link
Contributor

@andyfaff andyfaff Dec 2, 2020

Choose a reason for hiding this comment

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

inv_eff_matrix = np.array(list(map(np.linalg.inv, efficiencies_matrix)))?

data : PlatypusNexus object
Polarised spectra for a given spin channel
channel : tuple
nominal spin channel - (0,0), (0,1), (1,0), or (1,1)
Copy link
Contributor

Choose a reason for hiding this comment

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

not clear what (0, 0) is. Is this mm or uu?
Perhaps we should use enumerations here?

PlatypusNexus or None,
PlatypusNexus or None,
PlatypusNexus or None
The corrected datasets within the PlatypusNexus
Copy link
Contributor

Choose a reason for hiding this comment

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

Mention what combinations are accepted.

++, --
++, --, +-
++, --, +-, -+


# Check if R++ or R-- channel is missing
if mm is None:
print("Error: Missing R-- channel")
Copy link
Contributor

Choose a reason for hiding this comment

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

raise RuntimeError("Missing R-- channel")



def polarised_correction(
mm=None, mp=None, pm=None, pp=None, reduction_options=None
Copy link
Contributor

Choose a reason for hiding this comment

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

make pp and mm positional parameters, no keyword.

print("Error: Input for +- channel doesn't match flipper statuses!")
return -1
elif mm is not None and _check_spin_channel(mm, (0, 0)) is False:
print("Error: Input for -- channel doesn't match flipper statuses!")
Copy link
Contributor

Choose a reason for hiding this comment

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

Exceptions for all of these.


# Initialise reduction options if not passed to function
if reduction_options is None:
reduction_options = {
Copy link
Contributor

@andyfaff andyfaff Dec 3, 2020

Choose a reason for hiding this comment

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

options = ReductionOptions(lo_wavelength=2.5, hi_wavelength=12.5)
options.update(reduction_options)

Returns
-------
I00, I01, I10, I11 : PlatypusNexus object
Copy link
Contributor

Choose a reason for hiding this comment

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

you're not returning the PN objects, you're returning the spectra.

for f1l in F1
]
# Define flipper 2 efficiency matrix
flipper2_eff_matrix = [
Copy link
Contributor

Choose a reason for hiding this comment

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

np.array([

p1a = 0.993
p1b = 0.57
p1c = 0.47
P1 = p1a - p1b * p1c ** (wavelength).astype("float")
Copy link
Contributor

Choose a reason for hiding this comment

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

@np.vectorize
def efficiency_matrix(wavelength, tuple_of_spin_channels):
    # return 4*4 array

)
]

I00_polcorr = [corr_pt[0] for corr_pt in np.array(corrected_data)]
Copy link
Contributor

Choose a reason for hiding this comment

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

we should be returning an array


for channel in _not_none(mm, mp, pm, pp):
if not channel.processed_spectrum:
channel.process(**reduction_options)
Copy link
Contributor

Choose a reason for hiding this comment

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

(**options)

I10=raw10.processed_spectrum["m_spec"][0],
I11=raw11.processed_spectrum["m_spec"][0],
)
raw00.processed_spectrum["m_spec_polcorr"] = np.asarray(
Copy link
Contributor

Choose a reason for hiding this comment

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

don't convert to arrays here, do it in correct_POL_efficiencies

)
raw01 = None
raw10 = None
raw11.processed_spectrum["m_spec_polcorr"] = np.asarray(
Copy link
Contributor

Choose a reason for hiding this comment

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

do array in correct_POL_efficiences

Returns
-------
I00, I01, I10, I11 : PlatypusNexus or None,
Copy link
Contributor

Choose a reason for hiding this comment

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

NSF aren't going to be None

ohcpaull and others added 11 commits January 12, 2021 11:21
Added SpinChannel Enum class that gets assigned to the spin_state attribute of PlatypusNexus objects based of the flipper1 and flipper2 statuses.
Uses Enum spin state class to arrange the scan's spin states to 00, 01, 10, 11.  Change workings in polarised_correction to use I00, I01, I10, I11 for raw flipper statuses and mm, mp, pm, pp for corrected spin channels
PolarisedReduce encompasses all data for a typical reduction of polarised neutron reflectometry data. It needs direct beams for initialisation, that is made into a SpinSet which creates a PlatypusReduce object for each spin channel measured. TODO: add reflected beams into object for reduction

SpinSet is an class to keep a spin set for a given angle together. it creates a PLatypusReduce object for each spin channel. TODO: incorporate polarisation correction in the initialisation routine

Added both classes to __init__.py
More work on SpinSet so it works as expected now, and moved to platypusnexus.py file as I think it fits here more.
@andyfaff
Copy link
Contributor

@ohcpaull please have a look at andyfaff#9 for what I think PNR reduction should look like.

@andyfaff
Copy link
Contributor

We should talk on Thursday.

@andyfaff andyfaff closed this May 25, 2021
@ohcpaull ohcpaull deleted the PNR_correction branch July 28, 2021 10:33
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.

3 participants