Skip to content

feat: generalize AR calculations, chi center, polarizations, reflections #133

@BijalBPatel

Description

@BijalBPatel

Proposed changes:

  1. Generalize Calculation beyond para, perp, and polarization framing. Allow parameters chi_1, chi_2 as optional parameters to choose where the chi wedges are centered. Default behavior will be chi_1 = 0, chi_2 = chi1 - 90, but allow users to override this. This enables more flexibility e.g., computing AR along a target chi aligned with a biaxial director, or sanity check of calculating AR aligned 45 degrees to uniaxial director. Goal is for default behavior to match current behavior.
  2. Add a flag to integrate 4 chi wedges per image, instead of 2. Presently, AR is calculated from two chi-wedges, centered on 0 +- chi_width (para) and -90 +- chi_width (perp). The proposed change would allow incorporating the reflection (so I_para is calculated from the wedges centered on 0 and 180, and I_perp is from wedges centered on 90 and -90).

Possible QOL additions:

  • Warn if chi_1 and chi_2 are not perpendicular
  • Warn if any wedges are overlapping
  • Add a flag to enable inferring chi_1 and chi_2 from polarization metadata

Possible Connections with existing issues:

Existing Code for reference:

def AR(self,calc2d=False,two_AR=False,chi_width=5,calc2d_norm_energy=None):
'''
Calculate the RSoXS Anisotropic Ratio (AR) of either a single RSoXS scan or a polarized pair of scans.
AR is defined as (para-perp)/(para+perp) where para is the chi slice parallel to the polarization direction, and perp is the chi slice 90 deg offset from the polarization direction.
Args:
img (xarray): image to plot
calc2d (bool): calculate the AR using both polarizations
two_AR (bool): return both polarizations if calc2d = True. If two_AR = False, return the average AR between the two polarizations.
calc2d_norm_energy (numeric): if set, normalizes each polarization's AR at a given energy. THIS EFFECTIVELY FORCES THE AR TO 0 AT THIS ENERGY.
chi_width (int, default 5): the width of chi slices used in calculating AR.
'''
if(not calc2d):
para = self.slice_chi(0,chi_width=chi_width)
perp = self.slice_chi(-90,chi_width=chi_width)
return ((para - perp) / (para+perp))
elif(calc2d):
para_pol = self.select_pol(0)
perp_pol = self.select_pol(90)
para_para = para_pol.rsoxs.slice_chi(0,chi_width=chi_width)
para_perp = para_pol.rsoxs.slice_chi(-90,chi_width=chi_width)
perp_perp = perp_pol.rsoxs.slice_chi(-90,chi_width=chi_width)
perp_para = perp_pol.rsoxs.slice_chi(0,chi_width=chi_width)
AR_para = ((para_para - para_perp)/(para_para+para_perp))
AR_perp = ((perp_perp - perp_para)/(perp_perp+perp_para))
if calc2d_norm_energy is not None:
AR_para = AR_para / AR_para.sel(energy=calc2d_norm_energy)
AR_perp = AR_perp / AR_perp.sel(energy=calc2d_norm_energy)
if (AR_para < AR_perp).all() or (AR_perp < AR_para).all():
warnings.warn('One polarization has a systematically higher/lower AR than the other. Typically this indicates bad intensity values.',stacklevel=2)
if two_AR:
return (AR_para,AR_perp)
else:
return (AR_para+AR_perp)/2
else:
raise NotImplementedError('Need either a single DataArray or a list of 2 dataarrays')

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions