N2O AF calcs v1, with polarization dependence

24/05/24

  • Fixed frame rotations, now for z-pol case as required.
  • Updated plots + added %age change heatmaps.

18/05/24

Version with polarization dependence.

22/03/24

Alignment frame calcs preliminary:

Note all plots are interactive, mouse-over for data points, and use toolbars for zoom/selection, and widgets for browsing data types (where applicable).

For general methods: https://epsproc.readthedocs.io/en/dev/demos/ePSproc_class_demo_161020.html

In [1]:
# Quick hack to override default HTML template
# NOT required in some JLab versions.
# https://stackoverflow.com/a/63777508
# https://stackoverflow.com/questions/21971449/how-do-i-increase-the-cell-width-of-the-jupyter-ipython-notebook-in-my-browser
from IPython.core.display import display, HTML
display(HTML("<style>.container { width:100% !important; }</style>"))

Load alignment data

Now with ADM class.

In [2]:
from epsproc.classes.alignment import ADM
from pathlib import Path

dataPath = Path('~/ePS/N2O/alignment/Wigner D polyatomic normalized')
ADMtype = '.txt'

ADMin = ADM(fileBase=dataPath.expanduser(), ext = ADMtype)

ADMin.loadData(keyType='setADMsT', normType='wignerDpoly')
* sparse not found, sparse matrix forms not available. 
* natsort not found, some sorting functions not available. 
* Setting plotter defaults with epsproc.basicPlotters.setPlotters(). Run directly to modify, or change options in local env.
* Set Holoviews with bokeh.
* pyevtk not found, VTK export not available. 
Scanning /home/paul/ePS/N2O/alignment/Wigner D polyatomic normalized for ePS jobs.
Found ePS output files in subdirs: [PosixPath('/home/paul/ePS/N2O/alignment/Wigner D polyatomic normalized/A200'), PosixPath('/home/paul/ePS/N2O/alignment/Wigner D polyatomic normalized/A400'), PosixPath('/home/paul/ePS/N2O/alignment/Wigner D polyatomic normalized/A600'), PosixPath('/home/paul/ePS/N2O/alignment/Wigner D polyatomic normalized/A800')]

*** Scanning dir
/home/paul/ePS/N2O/alignment/Wigner D polyatomic normalized/A200
Found 6 .txt file(s)


*** Scanning dir
/home/paul/ePS/N2O/alignment/Wigner D polyatomic normalized/A400
Found 6 .txt file(s)


*** Scanning dir
/home/paul/ePS/N2O/alignment/Wigner D polyatomic normalized/A600
Found 6 .txt file(s)


*** Scanning dir
/home/paul/ePS/N2O/alignment/Wigner D polyatomic normalized/A800
Found 6 .txt file(s)

Set self.norm from self.norms['wignerDpoly'].
Found t-index /home/paul/ePS/N2O/alignment/time.txt
Files from self.fileDict read OK, outputs: self.dataDict and self.data.
In [3]:
# import epsproc as ep

# ep.setADMs
In [4]:
ADMin.plot(width=1000)
# ADMin.plot(xlim=(30,50), width=800)  # Auto-stack plus pass args & zoom in on specific region (note slider will reset region with interactive zoom)

Load matrix elements

In [5]:
# Plotters
# from epsproc.plot import hvPlotters

# Multijob class dev code
from epsproc.classes.multiJob import ePSmultiJob

import warnings
# warnings.filterwarnings('once')   # Skip repeated numpy deprecation warnings in current build (xr15 env)
warnings.filterwarnings('ignore')   # Skip repeated numpy deprecation warnings in current build (xr15 env)
In [6]:
# # Scan for subdirs, based on existing routine in getFiles()

# fileBase = Path('/home/paul/ePS/OCS/OCS_survey')  # Data dir on Stimpy

fileBase = Path('~/fock-mount/globalhome/eps/N2O/N2O_valence').expanduser() # Data dir on Jake
In [7]:
# TODO: fix orb label here, currently relies on (different) fixed format

data = ePSmultiJob(fileBase, verbose = 0)

data.scanFiles()
# data.jobsSummary()
*** Warning: Missing records, expected 32, found 24.
*** Warning: Found 8 blank sets of matrix elements, symmetries ['A2']
*** Warning: Missing records, expected 32, found 24.
*** Warning: Found 8 blank sets of matrix elements, symmetries ['A2']
*** Warning: Missing records, expected 32, found 24.
*** Warning: Found 8 blank sets of matrix elements, symmetries ['A2']
*** Warning: Missing records, expected 32, found 24.
*** Warning: Found 8 blank sets of matrix elements, symmetries ['A2']
*** Warning: Missing records, expected 32, found 24.
*** Warning: Found 8 blank sets of matrix elements, symmetries ['A2']
*** Warning: Missing records, expected 32, found 24.
*** Warning: Found 8 blank sets of matrix elements, symmetries ['A2']
*** Warning: Missing records, expected 32, found 24.
*** Warning: Found 8 blank sets of matrix elements, symmetries ['A2']
*** Warning: Missing records, expected 32, found 24.
*** Warning: Found 8 blank sets of matrix elements, symmetries ['A2']

Compute AF

Define field(s)

Using EfiledPol class, set various ellipticities and fields $(E_x,E_y)$. For MF calcs, compute for all polarization geometries corresponding to fields aligned along $(x,y,z)$ molecular axes.

Note default case assumes $z$-axis alignment, and $E_y$ for the field plots here is reoriented along the alignment axis in the AF calcs. See E-field pol docs for details and control over geometries.

18/05/24: debugging for alignment... in this case RX is not used in calcs, so need to ROTATE FIELD TERMS prior to PAD calcs.

In [8]:
from epsproc.efield.epol import EfieldPol
import numpy as np
import matplotlib.pyplot as plt

# Mulitple ellipticities and rotations
# For fields, set with format = [amplitude,azimuth (0,pi), ellipticity (-pi/4,pi/4)]
states = 3

# angles = np.linspace(0, np.pi, states)  # For range of angles
angles = np.zeros(states)  # no rotation

maxEll = 0.5  # Set max ellipticity to use (0 - 1)
ellipticities = np.linspace(0,maxEll*np.pi/4, states)   # Set for 0 - max ellipticity
ell = np.c_[np.ones(states),angles,ellipticities]
labels = (ellipticities/(np.pi/4) * 100).round(2)  # Set labels at %age ellipticity

# Set fields
Eell_multi = EfieldPol(ell=ell, labels = labels)

# Plot fields
Eell_multi.plot(figsize=(6,6), draw_arrow=False)
plt.legend(labels, loc='upper right')
Set field from ell.
[[1.         0.         0.        ]
 [1.         0.         0.19634954]
 [1.         0.         0.39269908]]
Out[8]:
<matplotlib.legend.Legend at 0x7fa07c443150>
In [9]:
# Optional - set field orientation for PAD calcs. If not set defaults to Ey>z-axis rotation.
# Eell_multi.setOrientation
Eell_multi.setOrientation()
Set pol state data to self.YLM and self.YLMrot, and orientations to self.RX (mapping=exy).
In [10]:
import epsproc as ep
ep.setPolGeoms
Out[10]:
<function epsproc.sphCalc.setPolGeoms(eulerAngs=None, quat=None, labels=None, vFlag=2, defaultMap='canonical')>
In [11]:
from epsproc.geomFunc.geomUtils import EfieldPolConfig
ep, p, RX, EPRX, EfieldPol = EfieldPolConfig(Eell_multi)
Set parameters to `self.epDict` and `self.epXR`.
Set geomCalc.EPR() results to `self.EPRX`.

TO DO May 2024: E-FIELD ROTATION... calcs below seem to be for xpol case otherwise (XS show opposite alignment dependence to previous calcs)

  • UPDATE 22/05/24 - test case below for z-pol, working OK.
  • UPDATE 24/05/24 - now mostly implemented in main class, but still used test case in calcs below.
In [54]:
# Test EPRX setting from rotated case - currently missing...
# UPDATE 24/05/24 - now mostly implemented in main class, but still used test case in calcs below.
from copy import deepcopy 
Etest = deepcopy(Eell_multi)

# Test replacing epDict with rotation (subselection)
subselection = Eell_multi.YLMrot.swap_dims({"Euler":"Labels"}).unstack('BLM').sel(Labels='z').squeeze()
Etest.epDict = {'ep':subselection.values,
                'p':subselection.m.values,
               'RX':Etest.RX}
Etest.epDict
Out[54]:
{'ep': array([[ 3.69778549e-32+1.11022302e-16j, -1.00000000e+00+0.00000000e+00j,
         -3.69778549e-32+1.11022302e-16j],
        [ 4.75249489e-17+1.37949690e-01j, -9.80785280e-01+0.00000000e+00j,
          3.06309843e-17-1.37949690e-01j],
        [ 9.32235407e-17+2.70598050e-01j, -9.23879533e-01+0.00000000e+00j,
          6.00848371e-17-2.70598050e-01j]]),
 'p': array([-1,  0,  1]),
 'RX': <xarray.DataArray (Euler: 3)>
 array([quaternion(1, -0, 0, 0),
        quaternion(0.707106781186548, -0, 0, 0.707106781186547),
        quaternion(0.5, -0.5, 0.5, 0.5)], dtype=quaternion)
 Coordinates:
   * Euler    (Euler) MultiIndex
   - P        (Euler) float64 0.0 1.571 1.571
   - T        (Euler) float64 0.0 0.0 1.571
   - C        (Euler) float64 0.0 0.0 0.0
     Labels   (Euler) <U32 'x' 'y' 'z'
 Attributes:
     dataType:  Euler
     mapping:   exy}
In [ ]:
Etest.calcEPR()
Set geomCalc.EPR() results to `self.EPRX`.

AF calc

In [57]:
# Set ADMs to use for calc - set for specific T and downsample

# Subselection, note temperature is set by dataKey here
temp = '10K'
trange = [38,42]
# ADMin.subsetADMs(dataKey = temp, trange=[35,45],tStep = 5)
ADMin.subsetADMs(dataKey = temp, trange=trange,tStep = 5)

# Plot subselection
ADMin.plot(keys='ADM')

# Set to main data structure for calcs
data.data['ADM'] = ADMin.data['ADM']
tpoints= data.data['ADM']['ADM'].t.size
Selecting 16 points
Set subset data to `self.data['ADM']['ADM']`
In [58]:
# Basic routine (no grouping)
thres = 1e-5
# data.AFBLM(AKQS = data.data['ADM']['ADM'].real, selDims = {'Type':'L'}, thres=1e-2) # OK for 41 t-points (x2 downsample), but missing some orbs and t-points in output!
# data.AFBLM(AKQS = data.data['ADM']['ADM'].real, selDims = {'Type':'L'}, thres=thres) # OK for 41 t-points (x2 downsample), still some missing regions for thres=1e-2
                                                                                       # mostly contiguous for thres = 1e-3,1e-4

# EfieldInput = Eell_multi
EfieldInput = Etest   # Testing frame rotation...
    
# With pol...
data.AFBLM(AKQS = data.data['ADM']['ADM'].real, EfieldPol = EfieldInput,
           selDims = {'Type':'L'}, thres=thres)   

# For thres=1e-3, 3 pol states, 41 t-points, requires ~ 50Gb RAM/10 mins. Some dicontinuities
# May need grouping for larger calcs.

# Thres = 1e-4, 3 pol states, 16 t-points, similar requirements

# Testing 22/05/24 - implementation of field frame rotation for EPRX

# Save full class with Pickle
# TODO: GENERAL DEBUG FOR ACCIDENTAL FUNCTION PASSING HERE!!!!
import pickle
outfile = f'N2O_AFBLM_polDep_{temp}_t{trange[0]}-{trange[1]}_tp{tpoints}_{thres}_frameRot_220524.pickle'
with open(outfile, 'wb') as handle:
#     data.data['ADM']['plots']['ADM']['pData'].attrs['pTypeDetails'] = []  # UGH, this breaks pickle unless removed.
    pickle.dump(data.data, handle, protocol=pickle.HIGHEST_PROTOCOL)
    print(f'Saved data.data with pickle, file: {outfile}')
Saved data.data with pickle, file: N2O_AFBLM_polDep_10K_t38-42_tp16_1e-05_frameRot_220524.pickle
In [ ]:
# # Load data
# thres = 1e-5
# # infile = f'N2O_AFBLM_{temp}_{thres}_220323.pickle'
# # infile = 'N2O_AFBLM_10K_0.0001_220323.pickle'
# infile = 'N2O_AFBLM_10K_1e-05_220323.pickle'

# import pickle
# with open(infile, 'rb') as handle:
#     dataIn = pickle.load(handle)
    
# data.data = dataIn

Plots

NOTE: interactive plots. Roll over plots for values and tool options. For heatmaps use the "box select" tool on the histogram at the side to change the colour mapping scale.

Remarks:

  • Some unphysical spikes in values <5eV, these are regions with small cross-sections, and are currently filtered out in these plots.
  • General patterns seem to be simlar to R-matrix results, as expected, although absolute Blm values seem larger...? Might be a normalisation difference here, TBC.

Cross-sections vs polarization

Note not too much change here, aside from a general drop in the features and loss of contrast with ellipticity.

In [ ]:
# v2 with pkg code...

# hvTest = data.BLMplot(backend='hv', xDim = 't', hvType='heatmap', addHist = False, addADMs = False, XS=True, renderPlot=False, returnPlot=True)
# data.BLMplot(backend='hv', xDim = 't', hvType='heatmap', addHist = True, addADMs = False, XS=True, clim=(-1,2))
In [60]:
# Old code - better control
from epsproc.plot import hvPlotters
import numpy as np

# Set data - use existing plot routine but skip line outs (quite slow, replotted at end of notebook)
data.BLMplot(backend='hv', xDim = 't', renderPlot=False)

# Heatmaps for cross-sections
xrAF = data.plots['BLMplot']['XR'].copy()
Etype = 'Eke'

# Set opts to match sizes - should be able to link plots or set gridspace to handle this?
hvPlotters.setPlotDefaults(fSize = [750,300], imgSize = 600)
cmap = 'coolwarm'  # See http://holoviews.org/user_guide/Colormaps.html

# Get cross-sections
XS = np.abs(xrAF.XSrescaled)  # Should be in MB
XS.name = 'XS/MB'
hvXS = hvPlotters.hv.Dataset(XS.fillna(0))

# Plot heatmap + ADMs
(hvXS.to(hvPlotters.hv.HeatMap, kdims=['t',Etype]).opts(cmap=cmap).hist()  + data.data['ADM']['ADM'].unstack().squeeze().real.hvplot.line(x='t').overlay('K')).cols(1)
BLMplot set data and plots to self.plots['BLMplot']
WARNING:param.HeatMapPlot13975983: Due to internal constraints, when aspect and width/height is set, the bokeh backend uses those values as frame_width/frame_height instead. This ensures the aspect is respected, but means that the plot might be slightly larger than anticipated. Set the frame_width/frame_height explicitly to suppress this warning.
Out[60]:

Cross-sections vs polarization (%age change)

As above, but plot as %age change relative to linear pol case.

In [76]:
# %age
# Filter out small XS regions?
# Filter out small XS regions?
XSfiltered = XS.where(XS > 0.01)
XSPC = ((XSfiltered-XSfiltered.sel(pol=0)) / XSfiltered.sel(pol=0)) * 100

hvDS = hvPlotters.hv.Dataset(XSPC.fillna(0).squeeze(drop=True))

# hvDS = hvPlotters.hv.Dataset(xrAF.unstack('BLM').fillna(0).squeeze(drop=True))

# Plot heatmap + ADMs
(hvDS.select(l=[0], m=0, pol=[25,50]).to(hvPlotters.hv.HeatMap, kdims=['t',Etype]).opts(cmap=cmap, clim=(-25,25)).hist() + data.data['ADM']['ADM'].unstack().squeeze().real.hvplot.line(x='t').overlay('K')).cols(1)  #.overlay(['l','t']).layout('Orb').cols(1)
WARNING:param.HeatMapPlot58726027: Due to internal constraints, when aspect and width/height is set, the bokeh backend uses those values as frame_width/frame_height instead. This ensures the aspect is respected, but means that the plot might be slightly larger than anticipated. Set the frame_width/frame_height explicitly to suppress this warning.
Out[76]:

AF-$\beta_{L,M}$

Plots show heat-maps and line-outs for all $\beta_{L,M}$. For the line-outs ignore unphysical features where the XS is low, but these are filtered out in the heat-maps.

In [65]:
# Heatmap for l=2,4,6
# NOTE - clipped cmap to physical values with clim=(-1,2), but some spikes.

# BLM = np.abs(xrAF.XSrescaled)  # Should be in MB
# XS.name = 'XS/MB'

# Filter out small XS regions?
xrAFfiltered = xrAF.where(np.abs(xrAF.XSrescaled) > 0.01)
hvDS = hvPlotters.hv.Dataset(xrAFfiltered.unstack('BLM').fillna(0).squeeze(drop=True))

# hvDS = hvPlotters.hv.Dataset(xrAF.unstack('BLM').fillna(0).squeeze(drop=True))

# Plot heatmap + ADMs
(hvDS.select(l=[2,4,6], m=0).to(hvPlotters.hv.HeatMap, kdims=['t',Etype]).opts(cmap=cmap, clim=(-0.5,1)).hist() + data.data['ADM']['ADM'].unstack().squeeze().real.hvplot.line(x='t').overlay('K')).cols(1)  #.overlay(['l','t']).layout('Orb').cols(1)
WARNING:param.HeatMapPlot57713066: Due to internal constraints, when aspect and width/height is set, the bokeh backend uses those values as frame_width/frame_height instead. This ensures the aspect is respected, but means that the plot might be slightly larger than anticipated. Set the frame_width/frame_height explicitly to suppress this warning.
Out[65]:
In [62]:
# Plot some results - line-outs
# Example with post-plotter subselection for faster plotting...

# Create HV object, but don't plot
data.BLMplot(dataType='AFBLM', xDim='pol', thres = 1e-2, backend='hv', width=700,  ylim=(-1.5, 2.5), 
             renderPlot=False)

# Replot from Holoviews dataset with selectors
# Note this may need hv or hvPlotters to be loaded
from epsproc.plot import hvPlotters
xDim = 't'
# data.plots['BLMplot']['hvDS'].select(Eke=[1.1,10.1,20.1]).select(Orb='orb9_P').to(hvPlotters.hv.Curve, kdims=xDim).overlay(['l', 'm','pol'])
# data.plots['BLMplot']['hvDS'].select(Eke=[1.1,10.1,20.1]).to(hvPlotters.hv.Curve, kdims=xDim).overlay(['l', 'm'])
data.plots['BLMplot']['hvDS'].to(hvPlotters.hv.Curve, kdims=xDim).opts(ylim=(-1.5,2.5), width=1200).overlay(['l', 'm'])
BLMplot set data and plots to self.plots['BLMplot']
Out[62]:
In [64]:
# Replot...
data.plots['BLMplot']['hvDS'].select(Orb='orb9_P').to(hvPlotters.hv.Curve, kdims=xDim).opts(ylim=(-1.5,2.5), width=1200).overlay(['l', 'm']).layout(['pol']).cols(1)
Out[64]:

AF-$\beta_{L,M}$ - %age changes relative to linear pol case

Normalised %age differences from linearly pol case ($\epsilon=0$), i.e. plot shows $\bar{\beta_{LM}}^{\epsilon} = (\beta_{LM}^{\epsilon} - \beta_{LM}^{\epsilon=0})/\beta_{LM}^{\epsilon = 0}) * 100$.

Note here that the changes are typically:

  • <10% for 25% ellipticity case, aside from around t=39.5ps for orbs 8 & 9 (although worse at higher Ekes for orb 9).
  • Larger, maybe ~15-30%, for 50% ellipticity case, but worse over the main revival features, and for orb 9.
  • Exact changes are quite sensitive to Eke and alignment/time.
In [71]:
# %age
# Filter out small XS regions?
xrAFPC = ((xrAFfiltered-xrAFfiltered.sel(pol=0)) / xrAFfiltered.sel(pol=0)) * 100

hvDS = hvPlotters.hv.Dataset(xrAFPC.unstack('BLM').fillna(0).squeeze(drop=True))

# hvDS = hvPlotters.hv.Dataset(xrAF.unstack('BLM').fillna(0).squeeze(drop=True))

# Plot heatmap + ADMs
(hvDS.select(l=[2,4,6], m=0, pol=[25,50]).to(hvPlotters.hv.HeatMap, kdims=['t',Etype]).opts(cmap=cmap, clim=(-25,25)).hist() + data.data['ADM']['ADM'].unstack().squeeze().real.hvplot.line(x='t').overlay('K')).cols(1)  #.overlay(['l','t']).layout('Orb').cols(1)
WARNING:param.HeatMapPlot58604803: Due to internal constraints, when aspect and width/height is set, the bokeh backend uses those values as frame_width/frame_height instead. This ensures the aspect is respected, but means that the plot might be slightly larger than anticipated. Set the frame_width/frame_height explicitly to suppress this warning.
Out[71]:
In [ ]:
# Line-outs
# Note this is quite slow to render
# data.BLMplot(backend='hv', xDim = 't', ylim=(-1,2), filterXS=0.01)
In [ ]:
# hvDS.select(l=[2,4,6], m=0)

Versions

Code

In [77]:
# print(data.jobInfo['ePolyScat'][0])
# print('Run: ' + jobInfo['Starting'][0].split('at')[1])
In [78]:
import scooby
scooby.Report(additional=['epsproc', 'xarray', 'jupyter', 'holoviews', 'pandas'])
Out[78]:
Fri May 24 11:09:03 2024 EDT
OS Linux CPU(s) 64 Machine x86_64
Architecture 64bit Environment Jupyter
Python 3.7.10 | packaged by conda-forge | (default, Feb 19 2021, 16:07:37) [GCC 9.3.0]
epsproc 1.3.2-dev xarray 0.15.0 jupyter Version unknown
holoviews 1.14.2 pandas 1.2.3 numpy 1.21.6
scipy 1.6.1 IPython 7.21.0 matplotlib 3.3.4
scooby 0.5.6
In [79]:
# Check current Git commit for local ePSproc version
!git -C {Path(ep.__file__).parent} branch
!git -C {Path(ep.__file__).parent} log --format="%H" -n 1
/bin/bash: -c: line 0: syntax error near unexpected token `('
/bin/bash: -c: line 0: `git -C {Path(ep.__file__).parent} branch'
/bin/bash: -c: line 0: syntax error near unexpected token `('
/bin/bash: -c: line 0: `git -C {Path(ep.__file__).parent} log --format="%H" -n 1'
In [80]:
# Check current remote commits
!git ls-remote --heads https://github.com/phockett/ePSproc
1e28825260d558625d1dae6f7aa637513246ebbc	refs/heads/3d-AFPAD-dev
18901ac6056324d6a2674396939fdcc373d35395	refs/heads/dependabot/pip/notes/envs/envs-versioned/idna-3.7
9d9eb4e1a20d4ff77d07af2ac782ba18c26e5dcc	refs/heads/dependabot/pip/notes/envs/envs-versioned/jinja2-3.1.4
226759a58ebe96bf1a6df60ccd5efb0c449af3a7	refs/heads/dependabot/pip/notes/envs/envs-versioned/pillow-10.3.0
de0e271701949602ce7f170a9665e37b27d2401c	refs/heads/dependabot/pip/notes/envs/envs-versioned/requests-2.32.0
4ff0ed84a1df2a3de4258ba7e49db1e47e6ac596	refs/heads/dependabot/pip/notes/envs/envs-versioned/scipy-1.11.1
b50b0b946a1a7cb5b22c95d1e4cee120b22e6874	refs/heads/dependabot/pip/notes/envs/envs-versioned/tqdm-4.66.3
fd9c621f0c91e05ffcb097f59e9d8d8b43c5fc23	refs/heads/dependabot/pip/scipy-1.11.1
7e4270370d66df44c334675ac487c87d702408da	refs/heads/dev
1c0b8fd409648f07c85f4f20628b5ea7627e0c4e	refs/heads/master
69cd89ce5bc0ad6d465a4bd8df6fba15d3fd1aee	refs/heads/numba-tests
ea30878c842f09d525fbf39fa269fa2302a13b57	refs/heads/revert-9-master
baf0be0c962e8ab3c3df57c8f70f0e939f99cbd7	refs/heads/testDev

Notes

24/05/24

  • Fixed frame rotations, now for z-pol case as required.
  • Updated plots + added %age change heatmaps.

18/05/24

Version with polarization dependence.

22/03/24

Alignment frame calcs preliminary:

Note all plots are interactive, mouse-over for data points, and use toolbars for zoom/selection, and widgets for browsing data types (where applicable).

For general methods: https://epsproc.readthedocs.io/en/dev/demos/ePSproc_class_demo_161020.html

22/03/24

v1, quick run based on previous OCS code plus a few recent function updates.

TODO:

  • Testing with alternative polarization states.
  • More careful tests/checks in low-XS regions (currently just filter out, but see BLM spikes in a few cases without XS filter applied).
  • More careful comparison with R-matrix results.
  • AF-PAD plots, grids should work here...

Scratch

In [ ]:
break
In [ ]:
# Compute AFBLMs for aligned case
keys = data._keysCheck(None)
keys = list(set(keys) - set(['ADM']))


#*************** Throw everything in method - breaks for large datasets (RAM issues)
# data.AFBLM(keys = keys, AKQS = ADMs, selDims = {'Type':'L'})  # NOTE THIS USES independently set ADMs!

# data.AFBLM(keys = keys, AKQS = data.data['ADM']['ADM'].real, selDims = {'Type':'L'}, thres=1e-3) # OK for 61 t-points (x2 downsample)
# data.AFBLM(keys = keys, AKQS = data.data['ADM']['ADM'].real, selDims = {'Type':'L'}, thres=1e-3, thresDims = ['Eke','t'])   # NEED TO ADD DIM CHECKING TO thresDims
# data.AFBLM(keys = keys, AKQS = data.data['ADM']['ADM'].real, selDims = {'Type':'L'}, thres=1e-4)   # 1e-4 working OK for 30 t-points (x4 downsample)
# data.AFBLM(keys = keys, AKQS = data.data['ADM']['ADM'].real, selDims = {'Type':'L'}, thres=1e-5)   # 1e-5 working OK for 16 t-points (x8 downsample)
# data.AFBLM(keys = keys, AKQS = data.data['ADM']['ADM'].real, selDims = {'Type':'L'}, thres=1e-6)   # 1e-6 working OK for 16 t-points (x8 downsample)
# data.AFBLM(keys = keys, AKQS = data.data['ADM']['ADM'].real, selDims = {'Type':'L'}, thres=None)   # FAILS for 16 t-points (x8 downsample) at 60Gb RAM on Jake (Swap file size issue????)
                                                                                                   # OK for 8 t-points (x16 downsample) at ~55Gb RAM peak on Jake.
# thres=1e-4)  BREAKS KERNEL #, thresDims=['Eke','t'])  # TODO: currently thersDims must be in matE only for AFBLM routine.

# 21/07/22 version - above only gives L=2 max, missing L=4,6. But bumping threshold to 1e-4 kills calculation...
# data.AFBLM(keys = keys,  selDims = {'Type':'L'})  # Default case... sets/uses ADMs per key
# UPDATE: testing with scale factor for ADMs, and forcing to real - might be better?


#*********** Using grouping to avoid memory issues 
#        QUITE slow with current code, but more robust
#        TODO: make this better with basis set recycle (cf. fitting code)
#
import pickle

def calcAFBLMGroup(data,ADMs,keys,AFBLMdict):
    """Wrap for XR groupby"""
    
    # Class routine - returns to main datastruture
    data.AFBLM(keys = keys, AKQS = ADMs, selDims = {'Type':'L'}, thres=None)  #.map(standardize)
    
    # Copy to new structure & restack
#     keys = data._keysCheck(keys)

#     AFBLMdict = {}
    # Restack data to lists for merge
    for key in keys:
        AFBLMdict[key]['AFBLMlist'].append(data.data[key]['AFBLM'].copy())
        
    return AFBLMdict
        

AFBLMdict = {k:{'AFBLMlist':[]} for k in keys}
    
# tBins = np.arange(38,39.1,0.5)   # Test range
tBins = np.arange(trange[0], trange[1] + 0.1, 0.5)
# trange

import time

for item in data.data['ADM']['ADM'].groupby_bins("t", tBins):
    start = time.time()
    print(f'Calculating for group: {item[0]}, {item[1].t.size} t-points.')
    AFBLMdict = calcAFBLMGroup(data, item[1], keys, AFBLMdict)
    end = time.time()
    print(f'Delta: {end - start}s')

# Concat XR lists
for key in keys:
    AFBLMdict[key]['full'] = xr.concat(AFBLMdict[key]['AFBLMlist'],"t")
    AFBLMdict[key]['full'].name = f'{key}_AFBLM'
    
    # Push back to main class
    data.data[key]['AFBLM'] = AFBLMdict[key]['full'].copy()
    
    # Save object with Pickle
    with open(f'OCS_{key}_AFBLM_220722.pickle', 'wb') as handle:
        print(f'Saving {key} with pickle')
        pickle.dump(AFBLMdict[key]['full'], handle, protocol=pickle.HIGHEST_PROTOCOL)
    
# Save full class with Pickle
# NOW GIVING ERRORS ON RERUN (although worked previously), AttributeError: Can't pickle local object 'plotTypeSelector.<locals>.<lambda>'
# NOT SURE WHERE THIS IS COMING FROM AS YET
# UPDATE: IN data.data['ADM']['plots']['ADM']['pData'].attrs['pTypeDetails']
# TODO: GENERAL DEBUG FOR ACCIDENTAL FUNCTION PASSING HERE!!!!
# import pickle
with open(f'OCS_AFBLM_220722.pickle', 'wb') as handle:
    data.data['ADM']['plots']['ADM']['pData'].attrs['pTypeDetails'] = []  # UGH, this breaks pickle unless removed.
    pickle.dump(data, handle, protocol=pickle.HIGHEST_PROTOCOL)
    print(f'Saved data (full class) with pickle')