Skip to content

Handle incoming polarized beam for analyzer transmission computation #64

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

Merged
merged 11 commits into from
Jul 5, 2024

Conversation

SimonHeybrock
Copy link
Member

Fixes #58.

I need a detailed review here @astellhorn, since I am not at all confident that this is correct.

@SimonHeybrock SimonHeybrock requested a review from astellhorn June 24, 2024 14:19
class He3AnalyzerTransmissionFraction(
sl.ScopeTwoParams[PolarizerSpin, PolarizationState, sc.DataArray], sc.DataArray
):
"""Transmission fraction of the analyzer with polarized incoming beam"""
Copy link
Collaborator

Choose a reason for hiding this comment

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

Hm, for me, the namings are unlogical. Do I see it correctly that you define He3CellTransmissionFraction as the transmission fraction for a 3He cell with an unpolarized incoming beam, vs. He3AnalyzerTransmissionFraction for an analyzer with polarized incoming beam?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes. Which names would you suggest?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I would call it He3TransmissionFractionIncomingPolarized and He3TransmissionFractionIncomingUnpolarized.
I know the names are long, but precise

Comment on lines 298 to 303
# The two transmission fractions do not share a common time coordinate. Therefore,
# we cannot concat along a third dimension for the fit, but concat along time,
# with an additional coordinate for the incoming polarization.
up = transmission_fraction_up.assign_coords(incoming_polarization=sc.scalar(1))
down = transmission_fraction_down.assign_coords(incoming_polarization=sc.scalar(-1))
transmission_fraction = sc.concat([up, down], 'time')
Copy link
Member Author

Choose a reason for hiding this comment

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

Another question: Can it happen that we have only one of the two?

Copy link
Collaborator

Choose a reason for hiding this comment

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

No. For the polarized incoming beam, we need to compute this for both Up and Down, and then get the same fitparameters from both fits (combined fitting), for the output of T1 and C. We will define for the users to always measure both.

Copy link
Collaborator

@astellhorn astellhorn Jun 27, 2024

Choose a reason for hiding this comment

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

Actually its even more complicated. Because we assume that this is an analyzer 3He cell, its polarized for itself, so we do not only have incoming Up and Down, but also the polarization of the cell itself with Up and Down. But in the end, the transmission through the cell (and hence its parameters after this fit) only depend on two channels: if the incoming beam is parallel or antiparallel to the cell spin.

We could do that in 2 ways: (i) we combine the 2 spin channels (UU+DD, and UD+DU, as "parallel" and "antiparallel", respectively) or (ii) we only take one measured channel of each, i.e., in the workflow we could say take only UU OR DD for "parallel" and DU OR UD for "antiparallel. I am tending towards (ii). Because if the polarizer is not good then UU will be only = DD after the corrections, but not before.

Then we only have two fitting functions.

Copy link
Member Author

Choose a reason for hiding this comment

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

See update please!

Copy link
Member Author

Choose a reason for hiding this comment

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

For now I am assuming we have all four channels. It should be easy to adapt this later if we do not, but I wanted to avoid complicating this further. If it is ok with you then we postpone the (ii) case for later (could be soon, if needed).

Copy link
Member Author

Choose a reason for hiding this comment

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

So this is not something the software can decide/figure out, but the (instrument?) scientist needs to know, somehow?

Copy link
Collaborator

Choose a reason for hiding this comment

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

If e.g. a supermirror is used, and the Flipper after the Supermirror polarizer is not perfect, then for the analyzer the incoming beam Up is not the same anymore as incoming Down, and hence T+ (for the "parallel" state, i.e., to get UU or DD) would "look different" for incoming Up and Down.

Similarly, if a 3He cell is used as polarizer, also T+ and T- for this cell can be slightly different and the same as above can arise.

But I would assume here that this can be a general case, and we have to differ it always for an incoming polarized beam.

Copy link
Member Author

Choose a reason for hiding this comment

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

... but if there are two different T+, wouldn't we also need to distinguish those two for performing the polarization correction, instead of using only the T+ obtained from UU?

Copy link
Collaborator

Choose a reason for hiding this comment

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

T+ SHOULD be the same for incoming Up and incoming Down. I mean, if the incoming polarized beam (without sample) would be "perfect", then U should be the same as D, which it would be if we would have performed the correction already just for the polarizer/flipper, i.e., for the analyzer they would look the same. Then they have the same T+ of the analyzer, which should be the case. But if we do not perform the correction of intensities for the polarizer/flipper alone before we even compute T+ of the analyzer, I think it would look as if T+ would not be the same.

Copy link
Member Author

Choose a reason for hiding this comment

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

I split it off, see update please (or wait for our call).

@@ -187,6 +194,8 @@ def __call__(
polarization = self.polarization_function(time)
if plus_minus == 'plus':
polarization *= -1.0
elif isinstance(plus_minus, sc.Variable):
polarization *= -plus_minus
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why -plus_minus? Is that basically giving the "down"-channel with leaving the computation to "polarization *= +1.0"?

Copy link
Member Author

Choose a reason for hiding this comment

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

Compared to the lines above, where we heaver either plus or minus, when plus_minus is a Variable we can handle different sections at once, some plus, some minus.

Copy link
Collaborator

Choose a reason for hiding this comment

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

My question was rather a different one - what happens here for (i) plus_minus = plus or (ii) plus_minus = minus? If plus_minus = plus, then as beforepolarization *= -1.0, and if plus_minus = minus then polarization *= +1.0 ?

Copy link
Member Author

Choose a reason for hiding this comment

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

plus_minus is a scipp.Variable, containing values of +1 and/or -1. +1 means "plus", -1 means "minus". So plus_minus could be something like

[1,1,1,1,-1,-1,-1]

if we first measure the, say, UU channel, then UD.

Copy link
Collaborator

Choose a reason for hiding this comment

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

And for the transmission function that means for 'plus': self.transmission_empty_glass * sc.exp(-opacity * (1.0 - polarization) and for 'minus':
self.transmission_empty_glass * sc.exp(-opacity * (1.0 + polarization) ? I actually just wanted to make sure I understand the calculation of transmission for different values of polus_minus

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, correct.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ok thanks!

the fitted T(t, lambda).

DB_pol/DB = T_E * cosh(O(lambda)*P(t))*exp(-O(lambda))
"""
Copy link
Collaborator

Choose a reason for hiding this comment

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

This comment needs to be either changed or deleted here for the incoming polarized beam. Because its not the cosh(O(lambda)*P(t))*exp(-O(lambda)) function anymore, but the self.transmission_empty_glass * sc.exp(-opacity * (1.0 + polarization)) as written in class He3TransmissionFunction(TransmissionFunction[PolarizingElement]): in line 199

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

Comment on lines 298 to 303
# The two transmission fractions do not share a common time coordinate. Therefore,
# we cannot concat along a third dimension for the fit, but concat along time,
# with an additional coordinate for the incoming polarization.
up = transmission_fraction_up.assign_coords(incoming_polarization=sc.scalar(1))
down = transmission_fraction_down.assign_coords(incoming_polarization=sc.scalar(-1))
transmission_fraction = sc.concat([up, down], 'time')
Copy link
Collaborator

Choose a reason for hiding this comment

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

No. For the polarized incoming beam, we need to compute this for both Up and Down, and then get the same fitparameters from both fits (combined fitting), for the output of T1 and C. We will define for the users to always measure both.

Comment on lines 298 to 303
# The two transmission fractions do not share a common time coordinate. Therefore,
# we cannot concat along a third dimension for the fit, but concat along time,
# with an additional coordinate for the incoming polarization.
up = transmission_fraction_up.assign_coords(incoming_polarization=sc.scalar(1))
down = transmission_fraction_down.assign_coords(incoming_polarization=sc.scalar(-1))
transmission_fraction = sc.concat([up, down], 'time')
Copy link
Collaborator

@astellhorn astellhorn Jun 27, 2024

Choose a reason for hiding this comment

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

Actually its even more complicated. Because we assume that this is an analyzer 3He cell, its polarized for itself, so we do not only have incoming Up and Down, but also the polarization of the cell itself with Up and Down. But in the end, the transmission through the cell (and hence its parameters after this fit) only depend on two channels: if the incoming beam is parallel or antiparallel to the cell spin.

We could do that in 2 ways: (i) we combine the 2 spin channels (UU+DD, and UD+DU, as "parallel" and "antiparallel", respectively) or (ii) we only take one measured channel of each, i.e., in the workflow we could say take only UU OR DD for "parallel" and DU OR UD for "antiparallel. I am tending towards (ii). Because if the polarizer is not good then UU will be only = DD after the corrections, but not before.

Then we only have two fitting functions.

class He3AnalyzerTransmissionFraction(
sl.ScopeTwoParams[PolarizerSpin, PolarizationState, sc.DataArray], sc.DataArray
):
"""Transmission fraction of the analyzer with polarized incoming beam"""
Copy link
Collaborator

Choose a reason for hiding this comment

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

I would call it He3TransmissionFractionIncomingPolarized and He3TransmissionFractionIncomingUnpolarized.
I know the names are long, but precise

@SimonHeybrock SimonHeybrock enabled auto-merge July 5, 2024 09:19
@SimonHeybrock SimonHeybrock merged commit 611e4eb into main Jul 5, 2024
3 checks passed
@SimonHeybrock SimonHeybrock deleted the incoming-polarized branch July 5, 2024 09:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

Choosing correct sign in transmission function for if incoming beam is polarized
2 participants