4.2. Excited state wavepacket: density matrices and spatial distributions (updated version)#

From the simulated electronic wavepacket, we can analyse the properties in density matrix and real-space representations.


From prior work and data:

4.2.1. Imports#

# Load packages
# Main functions used herein from qbanalysis.hyperfine
from qbanalysis.hyperfine import *
import numpy as np
from epsproc.sphCalc import setBLMs

from pathlib import Path

dataPath = Path('/tmp/xe_analysis')
# dataTypes = ['BLMall', 'BLMerr', 'BLMerrCycle']   # Read these types, should just do dir scan here.

# # Read from HDF5/NetCDF files
# # TO FIX: this should be identical to loadFinalDataset(dataPath), but gives slightly different plots - possibly complex/real/abs confusion?
# dataDict = {}
# for item in dataTypes:
#     dataDict[item] = IO.readXarray(fileName=f'Xe_dataset_{item}.nc', filePath=dataPath.as_posix()).real
#     dataDict[item].name = item

# Read from raw data files
from qbanalysis.dataset import loadFinalDataset
dataDict = loadFinalDataset(dataPath)

# Use Pandas and load Xe local data (ODS)
# These values were detemermined from the experimental data as detailed in ref. [4].
from qbanalysis.dataset import loadXeProps
xeProps = loadXeProps()

# Load adv. fit data
from qbanalysis.dataset import loadAdvFit

xePropsFit, xeParamsFit, paramsUDict = loadAdvFit()
2025-06-03 16:53:20.365 | INFO     | qbanalysis.config:<module>:11 - PROJ_ROOT path is: /home/runner/work/Quantum-Beat_Photoelectron-Imaging_Spectroscopy_of_Xe_in_the_VUV/Quantum-Beat_Photoelectron-Imaging_Spectroscopy_of_Xe_in_the_VUV
* 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. 
* pyshtools not found, SHtools functions not available. If required, run "pip install pyshtools" or "conda install -c conda-forge pyshtools" to install.
2025-06-03 16:53:41.118 | INFO     | qbanalysis.hyperfine:<module>:31 - Using uncertainties modules, Sympy maths functions will be forced to float outputs.
2025-06-03 16:53:41.193 | INFO     | qbanalysis.dataset:loadDataset:268 - Loaded data cpBasex_results_cycleSummed_rot90_quad1_ROI_results_with_FT_NFFT1024_hanningWindow_270717.mat.
2025-06-03 16:53:41.238 | INFO     | qbanalysis.dataset:loadDataset:268 - Loaded data cpBasex_results_allCycles_ROIs_with_FTs_NFFT1024_hanningWindow_270717.mat.
2025-06-03 16:53:41.555 | INFO     | qbanalysis.dataset:loadFinalDataset:244 - Processed data to Xarray OK.
2025-06-03 16:53:41.584 | INFO     | qbanalysis.dataset:loadXeProps:71 - Loaded Xe data from /home/runner/work/Quantum-Beat_Photoelectron-Imaging_Spectroscopy_of_Xe_in_the_VUV/Quantum-Beat_Photoelectron-Imaging_Spectroscopy_of_Xe_in_the_VUV/dataLocal/Xe_data_table_fixedFractions.ods.

**Xe measured level splittings and the hyperfine constants.**
Statistical uncertainty estimates are given for the measurements. (See manuscript for details).
/opt/hostedtoolcache/Python/3.10.11/x64/lib/python3.10/site-packages/xarray/core/concat.py:500: FutureWarning: unique with argument that is not not a Series, Index, ExtensionArray, or np.ndarray is deprecated and will raise in a future version.
  common_dims = tuple(pd.unique([d for v in vars for d in v.dims]))
/home/runner/work/Quantum-Beat_Photoelectron-Imaging_Spectroscopy_of_Xe_in_the_VUV/Quantum-Beat_Photoelectron-Imaging_Spectroscopy_of_Xe_in_the_VUV/qbanalysis/dataset.py:82: FutureWarning: DataFrame.applymap has been deprecated. Use DataFrame.map instead.
  tidied = rawXeHyperfineResults.applymap(lambda x: x.replace(' ','') if isinstance(x, str) else x)
/home/runner/work/Quantum-Beat_Photoelectron-Imaging_Spectroscopy_of_Xe_in_the_VUV/Quantum-Beat_Photoelectron-Imaging_Spectroscopy_of_Xe_in_the_VUV/qbanalysis/dataset.py:87: FutureWarning: DataFrame.applymap has been deprecated. Use DataFrame.map instead.
  tidied[uList] = tidied[uList].applymap(lambda x: ufloat_fromstr(x))  # OK
A/MHz B/MHz Splitting/cm−1
Isotope I F F′
129 0.5 0.5 1.5 -5723+/-9 nan+/-nan 0.2863+/-0.0005
131 1.5 1.5 0.5 1697+/-30 -8+/-7 0.0855+/-0.0010
2.5 1.5 1697+/-30 -8+/-7 0.1411+/-0.0029
0.5 1697+/-30 -8+/-7 0.2276+/-0.0029
2025-06-03 16:53:41.647 | INFO     | qbanalysis.dataset:loadAdvFit:123 - Loaded Xe adv. fit data from /home/runner/work/Quantum-Beat_Photoelectron-Imaging_Spectroscopy_of_Xe_in_the_VUV/Quantum-Beat_Photoelectron-Imaging_Spectroscopy_of_Xe_in_the_VUV/dataLocal/xeAdvFit.h5.
# v2 pkg
from qbanalysis.adv_fitting import * 

# Recalc model with uncertainties & plot...
# NOTE: currently doesn't include uncertainties on t-coord.
# TODO: add labels and fix ledgend in layout
from qbanalysis.plots import plotFinalDatasetBLMt
plotOpts = {'width':800}
calcDict = calcAdvFitModel(paramsUDict, xePropsFit=xePropsFit, dataDict=dataDict)
2025-06-03 16:53:41.666 | INFO     | qbanalysis.basic_fitting:<module>:21 - Using uncertainties modules, Sympy maths functions will be forced to float outputs.
2025-06-03 16:53:41.667 | INFO     | qbanalysis.adv_fitting:<module>:29 - Using uncertainties modules, Sympy maths functions will be forced to float outputs.
/opt/hostedtoolcache/Python/3.10.11/x64/lib/python3.10/site-packages/xarray/core/concat.py:500: FutureWarning: unique with argument that is not not a Series, Index, ExtensionArray, or np.ndarray is deprecated and will raise in a future version.
  common_dims = tuple(pd.unique([d for v in vars for d in v.dims]))
/opt/hostedtoolcache/Python/3.10.11/x64/lib/python3.10/site-packages/xarray/core/concat.py:500: FutureWarning: unique with argument that is not not a Series, Index, ExtensionArray, or np.ndarray is deprecated and will raise in a future version.
  common_dims = tuple(pd.unique([d for v in vars for d in v.dims]))
/opt/hostedtoolcache/Python/3.10.11/x64/lib/python3.10/site-packages/xarray/core/concat.py:500: FutureWarning: unique with argument that is not not a Series, Index, ExtensionArray, or np.ndarray is deprecated and will raise in a future version.
  common_dims = tuple(pd.unique([d for v in vars for d in v.dims]))
/opt/hostedtoolcache/Python/3.10.11/x64/lib/python3.10/site-packages/xarray/core/concat.py:500: FutureWarning: unique with argument that is not not a Series, Index, ExtensionArray, or np.ndarray is deprecated and will raise in a future version.
  common_dims = tuple(pd.unique([d for v in vars for d in v.dims]))
/opt/hostedtoolcache/Python/3.10.11/x64/lib/python3.10/site-packages/xarray/core/concat.py:500: FutureWarning: unique with argument that is not not a Series, Index, ExtensionArray, or np.ndarray is deprecated and will raise in a future version.
  common_dims = tuple(pd.unique([d for v in vars for d in v.dims]))
/opt/hostedtoolcache/Python/3.10.11/x64/lib/python3.10/site-packages/xarray/core/concat.py:500: FutureWarning: unique with argument that is not not a Series, Index, ExtensionArray, or np.ndarray is deprecated and will raise in a future version.
  common_dims = tuple(pd.unique([d for v in vars for d in v.dims]))
Hide code cell content
# # Hide future warnings from Xarray concat for fitting on some platforms
# import warnings
# # warnings.filterwarnings('ignore')  # ALL WARNINGS
# # warnings.filterwarnings('ignore', category=DeprecationWarning)
# warnings.filterwarnings('ignore', category=FutureWarning)

4.2.2. Density matrix from electronic wavepacket#

In this case, use packaged code to compute density matrix from wavepacket description, expanded in spherical tensors \(T_{K,Q}\). Results identical to legacy case, but output in general Xarray format, and interactive plots available. For further details see the ePSproc docs, and further introductory material in Quantum Metrology with Photoelectrons Vol. 3.

# Compute density matrix pmm from quantum beat
pmmFromQuantumBeat(calcDict)

# Results output to calcDict, keys ['pmm'] and ['pmmUn'] for 
# uncertainities split version (note this is a dataset)
calcDict['pmm']['131Xe']
Set denDims={'JM': ['J', 'M'], 'JpMp': ['Jp', 'Mp']}. Pass directly for more control.
Set sphDims={'KQ': ['K', 'Q']}. Pass directly for more control.
['J', 'Jp']
['M', 'Mp']
['J', 'Jp', 'K', 'M', 'Mp', 'Q']
Set denDims={'JM': ['J', 'M'], 'JpMp': ['Jp', 'Mp']}. Pass directly for more control.
Set sphDims={'KQ': ['K', 'Q']}. Pass directly for more control.
['J', 'Jp']
['M', 'Mp']
['J', 'Jp', 'K', 'M', 'Mp', 'Q']
<xarray.DataArray '131Xe' (K: 2, Q: 1, t: 97, JM: 15, JpMp: 15)>
array([[[[[nan+/-nan, nan+/-nan, nan+/-nan, ..., nan+/-nan, nan+/-nan,
           nan+/-nan],
          [nan+/-nan, nan+/-nan, nan+/-nan, ..., nan+/-nan, nan+/-nan,
           nan+/-nan],
          [nan+/-nan, nan+/-nan, 0.1924500897298752+/-0, ...,
           nan+/-nan, nan+/-nan, nan+/-nan],
          ...,
          [nan+/-nan, nan+/-nan, nan+/-nan, ...,
           0.08606629658238701+/-0, nan+/-nan, nan+/-nan],
          [nan+/-nan, nan+/-nan, nan+/-nan, ..., nan+/-nan, nan+/-nan,
           nan+/-nan],
          [nan+/-nan, nan+/-nan, nan+/-nan, ..., nan+/-nan, nan+/-nan,
           nan+/-nan]],

         [[nan+/-nan, nan+/-nan, nan+/-nan, ..., nan+/-nan, nan+/-nan,
           nan+/-nan],
          [nan+/-nan, nan+/-nan, nan+/-nan, ..., nan+/-nan, nan+/-nan,
           nan+/-nan],
          [nan+/-nan, nan+/-nan, 0.1924500897298752+/-0, ...,
           nan+/-nan, nan+/-nan, nan+/-nan],
...
           nan+/-nan],
          [nan+/-nan, nan+/-nan, nan+/-nan, ..., nan+/-nan, nan+/-nan,
           nan+/-nan]],

         [[nan+/-nan, nan+/-nan, nan+/-nan, ..., nan+/-nan, nan+/-nan,
           nan+/-nan],
          [nan+/-nan, nan+/-nan, nan+/-nan, ..., nan+/-nan, nan+/-nan,
           nan+/-nan],
          [nan+/-nan, nan+/-nan, nan+/-nan, ...,
           -0.19766741441042557+/-0.01214118648721737, nan+/-nan,
           nan+/-nan],
          ...,
          [nan+/-nan, nan+/-nan,
           -0.19766741441042557+/-0.01214118648721737, ...,
           0.10565767732189638+/-0.00648973715772812, nan+/-nan,
           nan+/-nan],
          [nan+/-nan, nan+/-nan, nan+/-nan, ..., nan+/-nan, nan+/-nan,
           nan+/-nan],
          [nan+/-nan, nan+/-nan, nan+/-nan, ..., nan+/-nan, nan+/-nan,
           nan+/-nan]]]]], dtype=object)
Coordinates:
  * K        (K) int8 0 2
  * Q        (Q) int8 0
  * t        (t) float64 -70.0 -60.0 -50.0 -40.0 ... 860.0 870.0 880.0 890.0
  * JM       (JM) MultiIndex
  - J        (JM) int8 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2
  - M        (JM) int8 2 1 0 -1 -2 2 1 0 -1 -2 2 1 0 -1 -2
  * JpMp     (JpMp) MultiIndex
  - Jp       (JpMp) int8 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2
  - Mp       (JpMp) int8 -2 -1 0 1 2 -2 -1 0 1 2 -2 -1 0 1 2
Attributes:
    dataType:       Density Matrix
    long_name:      Density Matrix
    units:          arb
    harmonics:      {'dtype': 'Complex harmonics', 'kind': 'complex', 'normTy...
    abundance:      0.212324+/-0.000030
    states:         {'JFlist': array([[1, 1.5, 1.5, 1.6903325033069923e-24+/-...
    uncertainties:  True
    density:        {'denDims': {'JM': ['J', 'M'], 'JpMp': ['Jp', 'Mp']}, 'sp...
# pmmPkgDS = splitUncertaintiesToDataset(pmmPkg)
# pmmDS

# Plot lmplot style
# daPlot, daPlotpd, legendList, gFig = ep.lmPlot(pmmDS['denMat'], xDim=xDim, pType = 'r')

# pmm style with HVplot routine (note may be slow for many t-steps)
# This will produce interactive plot with widgets
isoKey = '131Xe'

from epsproc.calc import density
density.matPlot(calcDict['pmmUn'][isoKey][isoKey].sel({'t':slice(0,200,2)}), kdims=['JM','JpMp'])
WARNING:param.HeatMapPlot00707: 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.

4.2.3. Spatial distributions#

Expand from \(T_{K,Q}\) parameters.

The spatial representation of the ensemble can be defined in terms of the state multipoles - hence the name - by expanding in a suitable basis, usually the spherical harmonics. For example, for a single angular momentum state \(J\), this is given by (Eqn. 4.101 in Blum):

\[\begin{split} W(\theta,\phi)=\left(\frac{1}{4\pi}\right)^{1/2}\sum_{KQ}(-1)^{J}(2J+1)^{1/2}\left(\begin{array}{ccc} J & J & K\\ 0 & 0 & 0 \end{array}\right)\left\langle T(J)_{KQ}^{\dagger}\right\rangle Y_{KQ}(\theta,\phi) \end{split}\]

4.2.3.1. Spatial distributions for \(^{129}Xe\)#

# Compute W from main function - pass dict and isoKey.
isoKey = '129Xe'
W = calcW(calcDict, isoKey=isoKey)
2025-06-03 16:55:52.919 | INFO     | qbanalysis.hyperfine:calcW:472 - calcDict passed, processing TKQ from calcDict['modelDict'][129Xe], J=1.
2025-06-03 16:55:53.046 | INFO     | qbanalysis.hyperfine:calcW:459 - TKQ Xarray data passed, processing TKQ from with J=1.
# With current ePSproc code need to:
#  - Remove uncertainities from data.
#  - Use only (l,m) labels
#  - Pass facetDim
#
# TODO: improve general dim handling in sphPlot. May have this in class wrappers already (not ePSproc, but maybe PEMtk).

# %matplotlib inline
import epsproc as ep
plotData = W
# plotData = plotData['131Xe'].sel(t=slice(40,120))  # Slice over t   {'t':slice(0,200,2)}
# plotData = plotData['131Xe'].sel(t=[40,70,130])  # Set some t values to match legacy plots
plotData = plotData.sel(t=[40,70,130])
# plotData = plotData.unstack().rename({"K":"l","Q":"m"}).stack({'BLM':('l','m')})
surfs = ep.sphFromBLMPlot(plotData, backend='pl', plotFlag=True, facetDim='t')
*** sphPlot no dataType set. Trying anyway. Set data.attrs['dataType'] for more control.
Using default sph betas.
Sph plots: 
Plotting with facetDims=t, pType=a with backend=pl.
*** Plotting for [1,1,0]
*** Plotting for [1,2,1]
*** Plotting for [1,3,2]
/opt/hostedtoolcache/Python/3.10.11/x64/lib/python3.10/site-packages/xarray/core/concat.py:500: FutureWarning: unique with argument that is not not a Series, Index, ExtensionArray, or np.ndarray is deprecated and will raise in a future version.
  common_dims = tuple(pd.unique([d for v in vars for d in v.dims]))

4.2.3.2. Spatial distributions for \(^{131}Xe\)#

# Compute W from main function - pass dict and isoKey.
isoKey = '131Xe'
W = calcW(calcDict, isoKey=isoKey)
2025-06-03 16:55:53.280 | INFO     | qbanalysis.hyperfine:calcW:472 - calcDict passed, processing TKQ from calcDict['modelDict'][131Xe], J=1.
2025-06-03 16:55:53.590 | INFO     | qbanalysis.hyperfine:calcW:459 - TKQ Xarray data passed, processing TKQ from with J=1.
# With current ePSproc code need to:
#  - Remove uncertainities from data.
#  - Use only (l,m) labels
#  - Pass facetDim
#
# TODO: improve general dim handling in sphPlot. May have this in class wrappers already (not ePSproc, but maybe PEMtk).

# %matplotlib inline
plotData = W
# plotData = plotData['131Xe'].sel(t=slice(40,120))  # Slice over t   {'t':slice(0,200,2)}
# plotData = plotData['131Xe'].sel(t=[40,70,130])  # Set some t values to match legacy plots
plotData = plotData.sel(t=[40,70,130])
# plotData = plotData.unstack().rename({"K":"l","Q":"m"}).stack({'BLM':('l','m')})
surfs = ep.sphFromBLMPlot(plotData, backend='pl', plotFlag=True, facetDim='t')
*** sphPlot no dataType set. Trying anyway. Set data.attrs['dataType'] for more control.
Using default sph betas.
Sph plots: 
Plotting with facetDims=t, pType=a with backend=pl.
*** Plotting for [1,1,0]
*** Plotting for [1,2,1]
*** Plotting for [1,3,2]
/opt/hostedtoolcache/Python/3.10.11/x64/lib/python3.10/site-packages/xarray/core/concat.py:500: FutureWarning:

unique with argument that is not not a Series, Index, ExtensionArray, or np.ndarray is deprecated and will raise in a future version.

4.2.4. Versions#

import scooby
scooby.Report(additional=['qbanalysis','pemtk','epsproc', 'holoviews', 'hvplot', 'xarray', 'matplotlib', 'bokeh', 'sympy', 'pandas','uncertainties'])
Tue Jun 03 16:55:53 2025 UTC
OS Linux (Ubuntu 24.04) CPU(s) 4 Machine x86_64 Architecture 64bit
RAM 15.6 GiB Environment Jupyter File system ext4
Python 3.10.11 (main, Sep 30 2024, 21:36:13) [GCC 13.2.0]
qbanalysis 0.0.1 pemtk Module not found epsproc 1.3.2.dev0 holoviews 1.20.2
hvplot 0.11.3 xarray 2022.3.0 matplotlib 3.5.3 bokeh 3.7.3
sympy 1.11.1 pandas 2.2.3 uncertainties 3.2.3 numpy 1.23.5
scipy 1.15.3 IPython 8.37.0 scooby 0.10.1
# # Check current Git commit for local ePSproc version
# from pathlib import Path
# !git -C {Path(qbanalysis.__file__).parent} branch
# !git -C {Path(qbanalysis.__file__).parent} log --format="%H" -n 1
# # Check current remote commits
# !git ls-remote --heads https://github.com/phockett/qbanalysis
# Check current Git commit for local code version
import qbanalysis
!git -C {Path(qbanalysis.__file__).parent} branch
!git -C {Path(qbanalysis.__file__).parent} log --format="%H" -n 1
* master
4dc763f8848565a5c3d947470fb3eb687d07ba5d
# Check current remote commits
!git ls-remote --heads https://github.com/phockett/Quantum-Beat_Photoelectron-Imaging_Spectroscopy_of_Xe_in_the_VUV
4dc763f8848565a5c3d947470fb3eb687d07ba5d	refs/heads/master
2ff23ede221ac1a0ae8b5351c6c505a6ecd1b65d	refs/heads/uncertainties