"""Provides pre-sized figures with one set of primary axes.
@@ -267,7 +174,7 @@ Source code for tp.axes.one
axes
axes.
function
- function to add a pre-posistioned legend.
+ function to add a pre-positioned legend.
"""
if isinstance ( style , str ): style = [ style ]
@@ -382,7 +289,7 @@ Source code for tp.axes.one
axes
axes.
function
- function to add a pre-posistioned legend.
+ function to add a pre-positioned legend.
"""
if isinstance ( style , str ): style = [ style ]
@@ -418,13 +325,13 @@ Source code for tp.axes.one
"""
if custom :
- legend = ax . legend ( loc = "center left" , bbox_to_anchor = ( 1.75 , 0.5 ),
- * args , ** kwargs )
+ legend = ax [ 1 ] . legend ( loc = "center left" , bbox_to_anchor = ( 1.75 , 0.5 ),
+ * args , ** kwargs )
else :
handles , labels = tp . axes . legend . consolidate ( ax )
- legend = ax . legend ( loc = "center left" , bbox_to_anchor = ( 1.75 , 0.5 ),
- handles = handles , labels = labels ,
- * args , ** kwargs )
+ legend = ax [ 1 ] . legend ( loc = "center left" , bbox_to_anchor = ( 1.75 , 0.5 ),
+ handles = handles , labels = labels ,
+ * args , ** kwargs )
return legend
@@ -447,7 +354,7 @@ Source code for tp.axes.one
axes
axes.
function
- function to add a pre-posistioned legend.
+ function to add a pre-positioned legend.
"""
if isinstance ( style , str ): style = [ style ]
@@ -483,13 +390,13 @@ Source code for tp.axes.one
"""
if custom :
- legend = ax . legend ( loc = "center left" , bbox_to_anchor = ( 1 , 0.5 ),
- * args , ** kwargs )
+ legend = ax [ 1 ] . legend ( loc = "center left" , bbox_to_anchor = ( 1 , 0.5 ),
+ * args , ** kwargs )
else :
handles , labels = tp . axes . legend . consolidate ( ax )
- legend = ax . legend ( loc = "center left" , bbox_to_anchor = ( 1 , 0.5 ),
- handles = handles , labels = labels ,
- * args , ** kwargs )
+ legend = ax [ 1 ] . legend ( loc = "center left" , bbox_to_anchor = ( 1 , 0.5 ),
+ handles = handles , labels = labels ,
+ * args , ** kwargs )
return legend
@@ -512,7 +419,7 @@ Source code for tp.axes.one
axes
axes.
function
- function to add a pre-posistioned legend.
+ function to add a pre-positioned legend.
"""
if isinstance ( style , str ): style = [ style ]
@@ -565,7 +472,7 @@ Source code for tp.axes.one
axes
axes.
function
- function to add a pre-posistioned legend.
+ function to add a pre-positioned legend.
"""
if isinstance ( style , str ): style = [ style ]
@@ -646,7 +553,7 @@ Source code for tp.axes.one
axes
axes.
function
- function to add a pre-posistioned legend.
+ function to add a pre-positioned legend.
"""
if isinstance ( style , str ): style = [ style ]
@@ -684,46 +591,30 @@ Source code for tp.axes.one
-
-
-
-
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/docs/_modules/tp/axes/three.html b/docs/_modules/tp/axes/three.html
index fb43608..f102f63 100644
--- a/docs/_modules/tp/axes/three.html
+++ b/docs/_modules/tp/axes/three.html
@@ -1,72 +1,30 @@
-
-
-
-
- tp.axes.three — ThermoPlotter 1.0.0 documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ tp.axes.three — ThermoPlotter 1.0.0 documentation
+
-
-
-
+
-
-
-
-
+
-
-
-
+
-
-
-
-
-
-
+
ThermoPlotter
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
Source code for tp.axes.three
"""Provides pre-sized figures with three sets of axes.
@@ -644,46 +551,30 @@ Source code for tp.axes.three
-
-
-
-
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/docs/_modules/tp/axes/two.html b/docs/_modules/tp/axes/two.html
index 3f12b10..24e860f 100644
--- a/docs/_modules/tp/axes/two.html
+++ b/docs/_modules/tp/axes/two.html
@@ -1,72 +1,30 @@
-
-
-
-
-
tp.axes.two — ThermoPlotter 1.0.0 documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
tp.axes.two — ThermoPlotter 1.0.0 documentation
+
-
-
-
+
-
-
-
-
+
-
-
-
+
-
-
-
-
-
-
+
ThermoPlotter
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
Source code for tp.axes.two
"""Provides pre-sized figures with two sets of axes.
@@ -381,46 +288,30 @@ Source code for tp.axes.two
-
-
-
-
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/docs/_modules/tp/calculate.html b/docs/_modules/tp/calculate.html
index 1a445bf..b178960 100644
--- a/docs/_modules/tp/calculate.html
+++ b/docs/_modules/tp/calculate.html
@@ -1,72 +1,30 @@
-
-
-
-
-
tp.calculate — ThermoPlotter 1.0.0 documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
tp.calculate — ThermoPlotter 1.0.0 documentation
+
-
-
-
+
-
-
-
-
+
-
-
-
+
-
-
-
-
-
-
+
ThermoPlotter
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
Source code for tp.calculate
"""Calculates stuff.
+Uses tp units by default, but can read the tprc.yaml to customise.
+
Functions
---------
@@ -172,8 +81,14 @@ Source code for tp.calculate
sorts and cumulates.
lorentzian:
lorentzian curve.
+ lifetime:
+ particle lifetime.
+ mfp:
+ particle mean free path.
be_occupation:
boson occupation.
+ dfdde:
+ derivative of the Fermi-Dirac distribution.
power_factor:
power factor.
zt:
@@ -187,10 +102,18 @@ Source code for tp.calculate
adds zt to dictionary.
kl_fromdict:
adds lattice thermal conductivity for target ZT to dictionary.
+
+ to_tp:
+ converts quantities to tp defaults from tprc.yaml.
+ from_tp:
+ converts quantities from tp defaults from tprc.yaml.
+ interpolate:
+ shrinks to smallest data size and interpolates.
"""
import numpy as np
import tp
+from scipy.constants import physical_constants
[docs] def cumulate ( x , y ):
"""Sorts by x and cumulates y.
@@ -245,17 +168,84 @@
Source code for tp.calculate
return 0.5 * fwhm / ( np . pi * (( x - x0 ) ** 2 + ( 0.5 * fwhm ) ** 2 ))
-
[docs] def be_occupation ( frequency , temperature = 300. ):
+
[docs] def lifetime ( gamma , use_tprc = True ):
+
"""Calculates lifetime from imaginary self-energy (Gamma).
+
+
Arguments
+
---------
+
+
gamma : array-like or float
+
frequencies (by default in THz).
+
+
use_tprc : bool, optional
+
use custom unit conversions. Default: True.
+
+
Returns
+
-------
+
+
np.array
+
lifetimes (by default in s).
+
"""
+
+
if use_tprc :
+
gamma = to_tp ( 'gamma' , gamma )
+
+
with np . errstate ( divide = 'ignore' , invalid = 'ignore' ):
+
lifetime = np . reciprocal ( np . multiply ( 2e12 * 2 * np . pi , gamma ))
+
lifetime = np . where ( np . isinf ( lifetime ), np . nan , lifetime )
+
+
if use_tprc :
+
lifetime = from_tp ( 'lifetime' , lifetime )
+
+
return lifetime
+
+
[docs] def mfp ( gamma , group_velocity , use_tprc = True ):
+
"""
+
Calculates mean free path from imaginary self-energy (Gamma) and
+
group velocity.
+
+
Arguments
+
---------
+
+
gamma : array-like or float
+
frequencies (by default in THz).
+
group_velocity : array-like or float
+
group velocities (by default in m s-1).
+
+
use_tprc : bool, optional
+
use custom unit conversions. Default: True.
+
+
Returns
+
-------
+
+
array-like
+
mean free paths (by default in m).
+
"""
+
+
if use_tprc :
+
group_velocity = to_tp ( 'group_velocity' , group_velocity )
+
+
tau = lifetime ( gamma , use_tprc = use_tprc )
+
mfp = np . multiply ( np . transpose ([ tau ,] * 3 , ( 1 , 2 , 3 , 0 )), group_velocity )
+
+
if use_tprc :
+
mfp = from_tp ( 'mean_free_path' , mfp )
+
+
return mfp
+
+
[docs] def be_occupation ( frequency , temperature , use_tprc = True ):
"""Calculates Bose-Einstein occupation.
Arguments
---------
frequency : array-like or float
-
frequencies in THz.
+
frequencies (by default in THz).
+
temperature : array-like or float
+
temperature (by default in K).
-
temperature : float, optional
-
temperature in K. Default: 300.
+
use_tprc : bool, optional
+
use custom unit conversions. Default: True.
Returns
-------
@@ -264,53 +254,121 @@
Source code for tp.calculate
occupations.
"""
- import scipy.constants as con
+ hbar = physical_constants [ 'Planck constant over 2 pi in eV s' ][ 0 ]
+ kb = physical_constants [ 'Boltzmann constant in eV/K' ][ 0 ]
- hbar = con . physical_constants [ 'Planck constant over 2 pi in eV s' ][ 0 ]
- kb = con . physical_constants [ 'Boltzmann constant in eV/K' ][ 0 ]
+ if use_tprc :
+ frequency = to_tp ( 'frequency' , frequency )
+ temperature = to_tp ( 'temperature' , temperature )
frequency = np . array ( frequency )
- occupation = np . expm1 (( frequency * 1e12 * hbar ) / ( kb * temperature )) ** - 1
+ occupation = np . expm1 ( np . divide . outer ( kb * temperature ,
+ frequency * 1e12 * hbar ) ** - 1 ) ** - 1
+
+ if use_tprc :
+ occupation = from_tp ( 'occupation' , occupation )
return occupation
-
[docs] def power_factor ( conductivity , seebeck ):
+
[docs] def dfdde ( energy , fermi_level , temperature , doping , amset_order = False ,
+
use_tprc = True ):
+
"""Derivative of the Fermi-Dirac distribution.
+
+
Arguments
+
---------
+
+
energy : array-like
+
energies per band and k-point (by default in eV).
+
fermi_level : array-like
+
fermi level per temperature and dopant (by default in eV).
+
temperature : array-like
+
temperatures (by default in K).
+
doping : array-like
+
doping concentrations (by default in cm-3).
+
+
amset_order : bool, optional
+
doping index before temperature index. Default: False.
+
use_tprc : bool, optional
+
use custom unit conversions. Default: True.
+
+
Returns
+
-------
+
+
np.array
+
derivative of the Fermi-Dirac distribution.
+
"""
+
+
kb = physical_constants [ 'Boltzmann constant in eV/K' ][ 0 ]
+
+
if use_tprc :
+
energy = to_tp ( 'energy' , energy )
+
fermi_level = to_tp ( 'energy' , fermi_level )
+
temperature = to_tp ( 'temperature' , temperature )
+
doping = to_tp ( 'doping' , doping )
+
+
kbt = np . multiply ( kb , temperature )
+
de = - np . subtract . outer ( fermi_level , energy )
+
if amset_order :
+
weights = - 0.25 / np . cosh ( 0.5 * de / kbt [ None , :, None , None ]) ** 2
+
weights = weights / kbt [ None , :, None , None ]
+
else :
+
weights = - 0.25 / np . cosh ( 0.5 * de / kbt [:, None , None , None ]) ** 2
+
weights = weights / kbt [:, None , None , None ]
+
+
return weights
+
+
[docs] def power_factor ( conductivity , seebeck , use_tprc = True ):
"""Calculates power factor.
Arguments
---------
conductivity : array-like
-
conductivities.
+
conductivities (by default in S m-1).
seebeck : array-like
-
seebeck coefficients.
+
seebeck coefficients (by default in muV K-1).
+
+
use_tprc : bool, optional
+
use custom unit conversions. Default: True.
Returns
-------
np.array
-
power factors.
+
power factors (by default in W m-1 K-2).
"""
-
return np . multiply ( conductivity , 1e-12 * np . square ( seebeck ))
+
if use_tprc :
+
conductivity = to_tp ( 'conductivity' , conductivity )
+
seebeck = to_tp ( 'seebeck' , seebeck )
+
+
pf = np . multiply ( conductivity , 1e-12 * np . square ( seebeck ))
+
+
if use_tprc :
+
pf = from_tp ( 'power_factor' , pf )
+
+
return pf
[docs] def zt ( conductivity , seebeck , electronic_thermal_conductivity ,
-
lattice_thermal_conductivity , temperature ):
+
lattice_thermal_conductivity , temperature , use_tprc = True ):
"""Calculates ZT.
Arguments
---------
conductivity : array-like
-
conductivities.
+
conductivities (by default in S m-1).
seebeck : array-like
-
seebeck coefficients.
+
seebeck coefficients (by default in muV K-1).
electronic_thermal_conductivity : array-like
-
electronic thermal conductivities.
+
electronic thermal conductivities (by default in W m-1 K-1).
lattice_thermal_conductivity : array-like
-
lattice thermal conductivities by temperature.
+
lattice thermal conductivities (by default in W m-1 K-1).
temperature : array-like
-
temperatures.
+
temperatures (by default in K).
+
+
use_tprc : bool, optional
+
use custom unit conversions. Default: True.
Returns
-------
@@ -319,44 +377,87 @@
Source code for tp.calculate
ZT.
"""
- pf = power_factor ( conductivity , seebeck )
- zt = np . multiply ( pf , np . array ( temperature )[:, None ]) / \
- np . add ( electronic_thermal_conductivity ,
- np . array ( lattice_thermal_conductivity )[:, None ])
+ pf = power_factor ( conductivity , seebeck , use_tprc = use_tprc )
+
+ if use_tprc :
+ pf = to_tp ( 'power_factor' , pf )
+ electronic_thermal_conductivity = to_tp (
+ 'electronic_thermal_conductivity' , electronic_thermal_conductivity )
+ lattice_thermal_conductivity = to_tp ( 'lattice_thermal_conductivity' ,
+ lattice_thermal_conductivity )
+ temperature = to_tp ( 'temperature' , temperature )
+
+ if np . ndim ( pf ) == 1 :
+ zt = np . multiply ( pf , np . array ( temperature )) / \
+ np . add ( electronic_thermal_conductivity ,
+ np . array ( lattice_thermal_conductivity ))
+ elif np . ndim ( pf ) == 2 :
+ zt = np . multiply ( pf , np . array ( temperature )[:, None ]) / \
+ np . add ( electronic_thermal_conductivity ,
+ np . array ( lattice_thermal_conductivity )[:, None ])
+ elif np . ndim ( pf ) == 3 :
+ zt = np . multiply ( pf , np . array ( temperature )[:, None , None ]) / \
+ np . add ( electronic_thermal_conductivity ,
+ np . array ( lattice_thermal_conductivity )[:, : 3 , : 3 ])
+ elif np . ndim ( pf ) == 4 :
+ zt = np . multiply ( pf , np . array ( temperature )[:, None , None , None ]) / \
+ np . add ( electronic_thermal_conductivity ,
+ np . array ( lattice_thermal_conductivity )[:, None , : 3 , : 3 ])
+ else :
+ raise Exception ( 'Unexpectedly dimensionous electrical properties! \n '
+ 'Abort!' )
+
+ if use_tprc :
+ zt = from_tp ( 'zt' , zt )
return zt
-
[docs] def kl ( conductivity , seebeck , electronic_thermal_conductivity , zt , temperature ):
+
[docs] def kl ( conductivity , seebeck , electronic_thermal_conductivity , zt , temperature ,
+
use_tprc = True ):
"""Calculates lattice thermal conductivity.
Arguments
---------
conductivity : array-like
-
conductivities.
+
conductivities (by default in S m-1).
seebeck : array-like
-
seebeck coefficients.
+
seebeck coefficients (by default in muV K-1).
electronic_thermal_conductivity : array-like
-
electronic thermal conductivities.
+
electronic thermal conductivities (by default in W m-1 K-1).
zt : array-like
zt.
temperature : array-like
-
temperatures.
+
temperatures (by default in K).
+
+
use_tprc : bool, optional
+
use custom unit conversions. Default: True.
Returns
-------
np.array
-
lattice thermal conductivity.
+
lattice thermal conductivities (by default in W m-1 K-1).
"""
-
pf = power_factor ( conductivity , seebeck )
+
pf = power_factor ( conductivity , seebeck , use_tprc = use_tprc )
+
+
if use_tprc :
+
pf = to_tp ( 'power_factor' , pf )
+
electronic_thermal_conductivity = to_tp (
+
'electronic_thermal_conductivity' , electronic_thermal_conductivity )
+
zt = to_tp ( 'zt' , zt )
+
temperature = to_tp ( 'temperature' , temperature )
+
mid = np . divide ( pf * np . array ( temperature )[:, None ], zt )
kl = np . subtract ( mid , electronic_thermal_conductivity )
+
if use_tprc :
+
kl = from_tp ( 'lattice_thermal_conductivity' , kl )
+
return kl
-
[docs] def power_factor_fromdict ( data ):
+
[docs] def power_factor_fromdict ( data , use_tprc = True ):
"""Convenience wrapper to calculate power factor from a dictionary.
Arguments
@@ -365,25 +466,31 @@
Source code for tp.calculate
data : dict
dictionary containing:
- conductivity array-like
- conductivities.
+ conductivity : array-like
+ conductivities (by default in S m-1).
seebeck : array-like
- seebeck coefficients.
+ seebeck coefficients (by default in muV K-1).
+
+ use_tprc : bool, optional
+ use custom unit conversions. Default: True.
Returns
-------
dict
- dictionary with power factors.
+ dictionary with power factors (by default in W m-1 K-2).
"""
data [ 'power_factor' ] = power_factor ( data [ 'conductivity' ],
- data [ 'seebeck' ])
- data [ 'meta' ][ 'units' ][ 'power_factor' ] = tp . settings . units ()[ 'power_factor' ]
+ data [ 'seebeck' ], use_tprc = use_tprc )
+ data [ 'meta' ][ 'units' ][ 'power_factor' ] = \
+ tp . settings . units ( use_tprc = use_tprc )[ 'power_factor' ]
+ data [ 'meta' ][ 'dimensions' ][ 'power_factor' ] = \
+ tp . settings . dimensions ()[ 'power_factor' ]
return data
-
[docs] def zt_fromdict ( data ):
+
[docs] def zt_fromdict ( data , use_tprc = True ):
"""Convenience wrapper to calculate ZT from a dictionary.
Arguments
@@ -393,15 +500,20 @@
Source code for tp.calculate
dictionary containing:
conductivity : array-like
- conductivities.
+ conductivities (by default in S m-1).
seebeck : array-like
- seebeck coefficients.
+ seebeck coefficients (by default in muV K-1).
electronic_thermal_conductivity : array-like
- electronic thermal conductivities.
+ electronic thermal conductivities (by default
+ in W m-1 K-1).
lattice_thermal_conductivity : array-like
- lattice thermal conductivities by temperature.
+ lattice thermal conductivities (by default
+ in W m-1 K-1).
temperature : array-like
- temperatures in K.
+ temperatures (by default in K).
+
+ use_tprc : bool, optional
+ use custom unit conversions. Default: True.
Returns
-------
@@ -413,12 +525,13 @@ Source code for tp.calculate
data [ 'zt' ] = zt ( data [ 'conductivity' ], data [ 'seebeck' ],
data [ 'electronic_thermal_conductivity' ],
data [ 'lattice_thermal_conductivity' ],
- data [ 'temperature' ])
- data [ 'meta' ][ 'units' ][ 'zt' ] = tp . settings . units ()[ 'zt' ]
+ data [ 'temperature' ], use_tprc = use_tprc )
+ data [ 'meta' ][ 'units' ][ 'zt' ] = tp . settings . units ( use_tprc = use_tprc )[ 'zt' ]
+ data [ 'meta' ][ 'dimensions' ][ 'zt' ] = tp . settings . dimensions ()[ 'zt' ]
return data
-[docs] def kl_fromdict ( data ):
+
[docs] def kl_fromdict ( data , use_tprc = True ):
"""Convenience wrapper to calculate k_latt from a dictionary.
Arguments
@@ -428,73 +541,171 @@
Source code for tp.calculate
dictionary containing:
conductivity : array-like
- conductivities.
+ conductivities (by default in S m-1).
seebeck : array-like
- seebeck coefficients.
+ seebeck coefficients (by default in muV K-1).
electronic_thermal_conductivity : array-like
- electronic thermal conductivities.
+ electronic thermal conductivities (by default
+ in W m-1 K-1).
zt : array-like
- ZT.
+ zt.
temperature : array-like
- temperatures in K.
+ temperatures (by default in K).
+
+ use_tprc : bool, optional
+ use custom unit conversions. Default: True.
Returns
-------
dict
- dictionary with lattice thermal conductivities.
+ dictionary with lattice thermal conductivities (by default
+ in W m-1 K-1).
"""
q = 'lattice_thermal_conductivity'
data [ q ] = kl ( data [ 'conductivity' ], data [ 'seebeck' ],
data [ 'electronic_thermal_conductivity' ], data [ 'zt' ],
- data [ 'temperature' ])
- data [ 'meta' ][ 'units' ][ q ] = tp . settings . units ()[ q ]
+ data [ 'temperature' ], use_tprc = use_tprc )
+ data [ 'meta' ][ 'units' ][ q ] = tp . settings . units ( use_tprc = use_tprc )[ q ]
+ data [ 'meta' ][ 'dimensions' ][ q ] = tp . settings . dimensions ()[ q ]
return data
+
+
[docs] def to_tp ( name , value ):
+
"""Converts quantity to tp default units using tprc.yaml.
+
+
Arguments
+
---------
+
+
value : array-like
+
values to be converted.
+
name : str
+
name in tprc.yaml.
+
+
Returns
+
-------
+
+
np.array
+
converted values.
+
"""
+
+
conversions = tp . settings . conversions ()
+
if name in conversions and conversions [ name ] is not None :
+
value = np . divide ( value , conversions [ name ])
+
+
return value
+
+
[docs] def from_tp ( name , value ):
+
"""Converts quantity from tp default units using tprc.yaml.
+
+
Arguments
+
---------
+
+
value : array-like
+
values to be converted.
+
name : str
+
name in tprc.yaml.
+
+
Returns
+
-------
+
+
np.array
+
converted values.
+
"""
+
+
conversions = tp . settings . conversions ()
+
if name in conversions and conversions [ name ] is not None :
+
value = np . multiply ( value , conversions [ name ])
+
+
return value
+
+
[docs] def interpolate ( data1 , data2 , dependent , keys1 , keys2 , axis1 = 0 , axis2 = 0 ,
+
kind = 'linear' ):
+
"""Shrinks datasets to smallest common size and interpolates.
+
+
Arguments
+
---------
+
+
data(1,2) : dict
+
input data.
+
dependent : str
+
variable to interpolate against.
+
keys(1,2) : array-like or str
+
data keys to interpolate
+
axis(1,2) : int, optional
+
axis of the dependent variable wrt the keys. Default: 0.
+
kind : str, optional
+
interpolation kind
+
+
Returns
+
-------
+
+
dict
+
shrunk data1
+
dict
+
shrunk and interpolated data2
+
"""
+
# Future: could be rewritten to auto-detect axis like resolve
+
+
from copy import deepcopy
+
from scipy.interpolate import interp1d
+
+
data1 = deepcopy ( data1 )
+
data2 = deepcopy ( data2 )
+
+
if isinstance ( keys1 , str ):
+
keys1 = [ keys1 ]
+
if isinstance ( keys2 , str ):
+
keys2 = [ keys2 ]
+
+
dmin = np . nanmax ([ data1 [ dependent ][ 0 ], data2 [ dependent ][ 0 ]])
+
dmax = np . nanmin ([ data1 [ dependent ][ - 1 ], data2 [ dependent ][ - 1 ]])
+
index1 = np . where (( data1 [ dependent ] <= dmax ) & ( data1 [ dependent ] >= dmin ))[ 0 ]
+
index2 = np . where (( data2 [ dependent ] <= dmax ) & ( data2 [ dependent ] >= dmin ))[ 0 ]
+
+
data1 [ dependent ] = np . array ( data1 [ dependent ])[ index1 ]
+
for key in keys1 :
+
data1 [ key ] = np . swapaxes ( data1 [ key ], 0 , axis1 )
+
data1 [ key ] = np . array ( data1 [ key ])[ index1 ]
+
data1 [ key ] = np . swapaxes ( data1 [ key ], 0 , axis1 )
+
+
data2 [ dependent ] = np . array ( data2 [ dependent ])[ index2 ]
+
for key in keys2 :
+
data2 [ key ] = np . swapaxes ( data2 [ key ], 0 , axis2 )
+
data2 [ key ] = np . array ( data2 [ key ])[ index2 ]
+
interp = interp1d ( data2 [ dependent ], data2 [ key ], kind = kind , axis = 0 )
+
data2 [ key ] = interp ( data1 [ dependent ])
+
data2 [ key ] = np . swapaxes ( data2 [ key ], 0 , axis2 )
+
+
return data1 , data2
-
-
-
-
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/docs/_modules/tp/data/load.html b/docs/_modules/tp/data/load.html
index b44d80f..0a481bc 100644
--- a/docs/_modules/tp/data/load.html
+++ b/docs/_modules/tp/data/load.html
@@ -1,72 +1,30 @@
-
-
-
-
-
tp.data.load — ThermoPlotter 1.0.0 documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
tp.data.load — ThermoPlotter 1.0.0 documentation
+
-
-
-
+
-
-
-
-
+
-
-
-
+
-
-
-
-
-
-
+
ThermoPlotter
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
Source code for tp.data.load
"""Data loading tools.
Loads data from codes into a dictionary, with units and array structures
-standardised. Also adds a ``meta`` subdictionary, which contains units
-and the data source.
+standardised. Also adds a ``meta`` subdictionary, which contains units,
+array dimensions and the data source.
Functions
---------
@@ -187,8 +94,8 @@ Source code for tp.data.load
import tp
from tp import settings
-[docs] def amset ( filename , quantities = [ 'temperature' , 'doping' , 'seebeck' ,
-
'conductivity' , 'electronic_thermal_conductivity' ]):
+
[docs] def amset ( filename , quantities = [ 'seebeck' , 'conductivity' ,
+
'electronic_thermal_conductivity' ], doping = 'n' ):
"""Loads AMSET transport data.
Includes unit conversion and outputs units (see tp.settings).
@@ -203,9 +110,14 @@
Source code for tp.data.load
filename : str
filepath.
- quantites : dict, optional
- values to extract. Default: temperature, doping, seebeck,
- conductivity, electronic_thermal_conductivity.
+ quantites : str or list, optional
+ values to extract. Accepts AMSET keys and power_factor.
+ Loads dependent properties. Default: seebeck, conductivity,
+ electronic_thermal_conductivity.
+
+ doping : str, optional
+ doing type (n or p). If there is more than one, defaults to
+ n, else this is ignored.
Returns
-------
@@ -218,63 +130,101 @@ Source code for tp.data.load
# name conversions and abbreviations
- conversions = settings . amset_conversions ()
+ aconversions = settings . amset_conversions ()
+ conversions = settings . conversions ()
anames = settings . to_amset ()
tnames = settings . to_tp ()
units = settings . units ()
+ dimensions = settings . dimensions ()
if isinstance ( quantities , str ): quantities = quantities . split ()
quantities = [ anames [ q ] if q in anames else q for q in quantities ]
- # list of quantities dependant on doping, temperature and scattering
- hasdope = [ 'fermi_levels' , 'conductivity' , 'seebeck' ,
- 'electronic_thermal_conductivity' , 'mobility' ]
- hastemp = [ 'fermi_levels' , 'conductivity' , 'seebeck' ,
- 'electronic_thermal_conductivity' , 'mobility' ]
- hastype = [ 'mobility' ]
-
- # add dependant variables
- if 'doping' not in quantities :
- for q in quantities :
- if q in hasdope :
- quantities . append ( 'doping' )
- break
- if 'temperatures' not in quantities :
- for q in quantities :
- if q in hastemp :
- quantities . append ( 'temperatures' )
- break
+ # quantities derived from those in the file
+ derived = { 'power_factor' : [ 'conductivity' , 'seebeck' ]}
+
+ # add dependent variables
+ for d in [ 'doping' , 'temperatures' ]:
+ if d not in quantities :
+ for q in quantities :
+ if q in tnames :
+ q = tnames [ q ]
+ if q in dimensions and \
+ ( d in dimensions [ q ] or ( d in tnames and tnames [ d ] in dimensions [ q ])):
+ quantities . append ( d )
+ break
+ for q in derived :
+ if q in quantities :
+ for q2 in derived [ q ]:
+ if q2 not in quantities :
+ quantities . append ( q2 )
# load data
with open ( filename ) as f :
data = json . load ( f )
- data2 = { 'meta' : { 'electronic_source' : 'amset' ,
- 'units' : {}}}
+ if 'doping' in quantities :
+ d = np . array ( data [ 'doping' ])
+ if ( d < 0 ) . all ():
+ doping = 'n'
+ di = np . where ( d < 0 )[ 0 ]
+ elif ( d > 0 ) . all ():
+ doping = 'p'
+ di = np . where ( d > 0 )[ 0 ]
+ elif doping == 'n' :
+ di = np . where ( d < 0 )[ 0 ]
+ elif doping == 'p' :
+ di = np . where ( d > 0 )[ 0 ]
+
+ data2 = { 'meta' : { 'doping_type' : doping ,
+ 'electronic_source' : 'amset' ,
+ 'units' : {},
+ 'dimensions' : {}}}
for q in quantities :
+ if q in derived :
+ continue
+ qs = [ * list ( data ), * list ( derived )]
assert q in data , \
' {} unrecognised. Quantity must be in {} or {} .' . format ( q ,
- ', ' . join ( list ( data )[: - 1 ]), list ( data )[ - 1 ])
+ ', ' . join ( qs [: - 1 ]), qs [ - 1 ])
q2 = tnames [ q ] if q in tnames else q
# compatibility with previous version
if isinstance ( data [ q ], dict ) and 'data' in data [ q ]:
data2 [ q2 ] = data [ q ][ 'data' ]
else :
data2 [ q2 ] = data [ q ]
- if q in hasdope and q in hastemp :
+ if q2 in dimensions and 'doping' in dimensions [ q2 ]:
# temperature index first for consistency with other codes
- if q in hastype :
+ # With the latest version of resolve, this is unneccessary
+ # Should it be removed?
+ if 'stype' in dimensions [ q2 ]:
for t in data2 [ q2 ]:
- data2 [ q2 ][ t ] = np . swapaxes ( data2 [ q2 ][ t ], 0 , 1 )
+ data2 [ q2 ][ t ] = np . array ( data2 [ q2 ][ t ])[ di ]
+ if 'temperature' in dimensions [ q2 ]:
+ data2 [ q2 ][ t ] = np . swapaxes ( data2 [ q2 ][ t ], 0 , 1 )
else :
- data2 [ q2 ] = np . swapaxes ( data2 [ q2 ], 0 , 1 )
- if q in hastype :
- if 'scattering_labels' not in data2 :
- data2 [ 'scattering_labels' ] = data [ q ] . keys ()
+ data2 [ q2 ] = np . array ( data2 [ q2 ])[ di ]
+ if 'temperature' in dimensions [ q2 ]:
+ data2 [ q2 ] = np . swapaxes ( data2 [ q2 ], 0 , 1 )
+ if q2 in dimensions and 'stype' in dimensions [ q2 ]:
+ if 'stype' not in data2 :
+ data2 [ 'stype' ] = list ( data [ q ] . keys ())
# for consistency with the format in the mesh data
- data2 [ q2 ] = [ data2 [ q2 ][ l ] for l in data2 [ 'scattering_labels' ]]
+ data2 [ q2 ] = [ data2 [ q2 ][ l ] for l in data2 [ 'stype' ]]
if q2 in units :
data2 [ 'meta' ][ 'units' ][ q2 ] = units [ q2 ]
+ if q2 in dimensions :
+ data2 [ 'meta' ][ 'dimensions' ][ q2 ] = dimensions [ q2 ]
+
+ if 'doping' in data2 :
+ data2 [ 'doping' ] = np . array ( data2 [ 'doping' ])[ di ]
+
+ for c in aconversions :
+ if c in data2 :
+ data2 [ c ] = np . multiply ( data2 [ c ], aconversions [ c ])
+
+ if 'power_factor' in quantities :
+ data2 = tp . calculate . power_factor_fromdict ( data2 )
for c in conversions :
if c in data2 :
@@ -282,13 +232,13 @@ Source code for tp.data.load
-[docs] def amset_mesh ( filename , quantities = [ 'temperature' , 'doping' ,
-
'scattering_rates' , 'scattering_labels' ], spin = 'avg' ):
+
[docs] def amset_mesh ( filename , quantities = 'scattering_rates' , doping = 'n' ,
+
spin = 'avg' ):
"""Loads AMSET mesh data.
-
Includes unit conversion and outputs units (see tp.settings).
-
Swaps temperature and doping indices so temperature is first, for
-
consistency with other codes.
+
Can also weight rates. Includes unit conversion and outputs units
+
(see tp.settings). Swaps temperature and doping indices so
+
temperature is first, for consistency with other codes.
Arguments
---------
@@ -296,11 +246,19 @@
Source code for tp.data.load
filename : str
filepath.
- quantites : dict, optional
+ quantites : str or list, optional
values to extract. Accepts AMSET keys, without spin
channels, which are dealt with in the spin variable.
- Default: temperature, doping, scattering_rates,
- scattering_labels.
+ Also accepts ibz_weights, the weights of the irreducible
+ k-points, fd_weights, the weights of the energies wrt the
+ derivative of the Fermi-Dirac distribution, and
+ weighted_rates, scattering_rates weighted by fd_weights
+ and averaged over kpoints. Loads dependent properties.
+ Default: scattering_rates.
+
+ doping : str, optional
+ doing type (n or p). If there is more than one, defaults to
+ n, else this is ignored.
spin : str, optional
spin. Accepts up, down or avg. If avg and there is only one
@@ -317,77 +275,164 @@ Source code for tp.data.load
# name conversions and abbreviations
- conversions = settings . amset_conversions ()
+ aconversions = settings . amset_conversions ()
+ conversions = settings . conversions ()
anames = settings . to_amset ()
tnames = settings . to_tp ()
units = settings . units ()
+ dimensions = settings . dimensions ()
if isinstance ( quantities , str ): quantities = quantities . split ()
quantities = [ anames [ q ] if q in anames else q for q in quantities ]
- # list of quantities dependant on doping and temperature
- hasdope = [ 'fermi_levels' , 'scattering_rates' ]
- hastemp = [ 'fermi_levels' , 'scattering_rates' ]
- hastype = [ 'scattering_rates' ]
+ # list of abbriviations and dependent quantites
+ subs = { 'weights' : [ 'ibz_weights' , 'fd_weights' ]}
hasspin = [ 'energies' , 'vb_index' , 'scattering_rates' , 'velocities' ]
- # add dependant variables
+ for i in range ( len ( quantities )):
+ if quantities [ i ] in subs :
+ quantities [ i ] = subs [ quantities [ i ]]
- if 'doping' not in quantities :
- for q in quantities :
- if q in hasdope :
- quantities . append ( 'doping' )
- break
- if 'temperatures' not in quantities :
- for q in quantities :
- if q in hastemp :
- quantities . append ( 'temperatures' )
- break
- if 'scattering_labels' not in quantities :
- for q in quantities :
- if q in hastype :
- quantities . append ( 'scattering_labels' )
- break
+ quantities = list ( np . ravel ( quantities ))
+
+ # add dependent variables
+
+ for d in [ 'doping' , 'ir_kpoints' , 'temperatures' , 'scattering_labels' ]:
+ if d not in quantities :
+ for q in quantities :
+ if q in tnames :
+ q = tnames [ q ]
+ if q in dimensions and \
+ ( d in dimensions [ q ] or ( d in tnames and tnames [ d ] in dimensions [ q ])):
+ quantities . append ( d )
+ break
# load data
- data = h5py . File ( filename , 'r' )
-
- if spin in [ 'avg' , 'average' ]:
- if 'energies_up' in data and 'energies_down' in data :
- spin = 'avg'
- elif 'energies_up' in data :
- spin = 'up'
- elif 'energies_down' in data :
- spin = 'down'
- data2 = { 'meta' : { 'electronic_source' : 'amset' ,
- 'spin' : spin ,
- 'units' : {}}}
- for q in quantities :
- q2 = tnames [ q ] if q in tnames else q
- if q in hasspin :
- if spin == 'avg' :
- data2 [ q2 ] = np . average ([ data [ ' {} _up' . format ( q )],
- data [ ' {} _down' . format ( q )]], axis = 0 )
- elif spin in [ 'up' , 'down' ]:
- data2 [ q2 ] = data [ ' {} _ {} ' . format ( q , spin )]
- else :
- raise Exception ( 'spin must be up or down or avg' )
+ def resolve_spin ( data , q , spin ):
+ """Resolves spin in AMSET.
+
+ Either returns the up or down value, or averages them.
+
+ Arguments
+ ---------
+
+ data : dict
+ data dictionary from AMSET.
+ q : str
+ quantity to resolve
+ spin : str
+ spin to use. Must be up, down or average.
+
+ Returns
+ -------
+
+ array
+ resolved data
+ """
+
+ if spin in [ 'avg' , 'average' ]:
+ resolved = np . average ([ data [ ' {} _up' . format ( q )][()],
+ data [ ' {} _down' . format ( q )][()]], axis = 0 )
+ elif spin in [ 'up' , 'down' ]:
+ resolved = data [ ' {} _ {} ' . format ( q , spin )][()]
else :
- data2 [ q2 ] = data [ q ]
- if q in hasdope and q in hastemp :
- # temperature in first index for consistency with other codes
- if q in hastype :
- data2 [ q2 ] = np . swapaxes ( data2 [ q2 ], 1 , 2 )
- else :
- data2 [ q2 ] = np . swapaxes ( data2 [ q2 ], 0 , 1 )
- if q2 in units :
- data2 [ 'meta' ][ 'units' ][ q2 ] = units [ q2 ]
+ raise Exception ( 'spin must be up or down or average' )
+
+ return resolved
+
+ with h5py . File ( filename , 'r' ) as f :
+ if 'doping' in quantities :
+ d = np . array ( f [ 'doping' ][()])
+ if ( d < 0 ) . all ():
+ doping = 'n'
+ di = np . where ( d < 0 )[ 0 ]
+ elif ( d > 0 ) . all ():
+ doping = 'p'
+ di = np . where ( d > 0 )[ 0 ]
+ elif doping == 'n' :
+ di = np . where ( d < 0 )[ 0 ]
+ elif doping == 'p' :
+ di = np . where ( d > 0 )[ 0 ]
+
+ if spin in [ 'avg' , 'average' ]:
+ if 'energies_up' in f and 'energies_down' in f :
+ spin = 'avg'
+ elif 'energies_up' in f :
+ spin = 'up'
+ elif 'energies_down' in f :
+ spin = 'down'
+
+ data = { 'meta' : { 'doping_type' : doping ,
+ 'electronic_source' : 'amset' ,
+ 'spin' : spin ,
+ 'units' : {},
+ 'dimensions' : {}}}
+ for q in quantities :
+ q2 = tnames [ q ] if q in tnames else q
+ if q in hasspin :
+ data [ q2 ] = resolve_spin ( f , q , spin )
+ elif q in f :
+ data [ q2 ] = f [ q ][()]
+ elif q not in [ 'ibz_weights' , 'fd_weights' , 'weighted_rates' ]:
+ raise Exception ( ' {} unrecognised. Quantity must be {} , '
+ 'ibz_weights, fd_weights weighted_rates'
+ '' . format ( q , ', ' . join ( f )))
+ if q in [ 'ibz_weights' , 'weighted_rates' ]:
+ _ , data [ 'ibz_weights' ] = np . unique ( f [ 'ir_to_full_kpoint_mapping' ],
+ return_counts = True )
+ if q in [ 'fd_weights' , 'weighted_rates' ]:
+ e = resolve_spin ( f , 'energies' , spin )
+ data [ 'fd_weights' ] = - tp . calculate . dfdde ( e , f [ 'fermi_levels' ],
+ f [ 'temperatures' ],
+ f [ 'doping' ],
+ amset_order = True )
+ if q == 'weighted_rates' :
+ rates = resolve_spin ( f , 'scattering_rates' , spin )
+ rates [ rates > 1e20 ] = 1e15
+ data [ 'total_weights' ] = data [ 'fd_weights' ] * data [ 'ibz_weights' ]
+ data [ 'normalised_weights' ] = data [ 'total_weights' ] / \
+ np . sum ( data [ 'total_weights' ],
+ axis = ( 2 , 3 ))[:,:, None , None ]
+ data [ q2 ] = rates * data [ 'normalised_weights' ]
+ data [ q2 ] = data [ q2 ] . sum ( axis = ( 3 , 4 ))
+
+ for q2 in data :
+ q = anames [ q2 ] if q2 in anames else q2
+ if q2 in dimensions and 'doping' in dimensions [ q2 ]:
+ # temperature in first index for consistency with other codes
+ if 'stype' in dimensions [ q ]:
+ if 'temperature' in dimensions [ q ]:
+ data [ q2 ] = np . swapaxes ( data [ q2 ], 1 , 2 )
+ data [ q2 ] = np . array ( data [ q2 ])[:,:, di ]
+ else :
+ data [ q2 ] = np . array ( data [ q2 ])[:, di ]
+ else :
+ if 'temperature' in dimensions [ q ]:
+ data [ q2 ] = np . swapaxes ( data [ q2 ], 0 , 1 )
+ data [ q2 ] = np . array ( data [ q2 ])[:, di ]
+ else :
+ data [ q2 ] = np . array ( data [ q2 ])[ di ]
+ if q2 in units :
+ data [ 'meta' ][ 'units' ][ q2 ] = units [ q2 ]
+ if q2 in dimensions :
+ data [ 'meta' ][ 'dimensions' ][ q2 ] = dimensions [ q2 ]
+
+ if 'doping' in data :
+ data [ 'doping' ] = np . array ( data [ 'doping' ])[ di ]
+
+ if 'stype' in data :
+ data [ 'stype' ] = \
+ [ l . decode ( 'UTF-8' ) for l in data [ 'stype' ]]
+
+ for c in aconversions :
+ if c in data :
+ data [ c ] = np . multiply ( data [ c ], aconversions [ c ])
for c in conversions :
- if c in data2 :
- data2 [ c ] = np . multiply ( data2 [ c ], conversions [ c ])
+ if c in data :
+ data [ c ] = np . multiply ( data [ c ], conversions [ c ])
- return data2
+ return data
[docs] def boltztrap ( filename , quantities = [ 'temperature' , 'doping' , 'seebeck' ,
'conductivity' , 'electronic_thermal_conductivity' ], doping = 'n' ):
@@ -401,7 +446,7 @@
Source code for tp.data.load
filename : str
filepath.
- quantites : dict, optional
+ quantites : str or list, optional
values to extract. Accepts boltztrap.hdf5 keys.
Default: temperature, doping, seebeck, conductivity,
electronic_thermal_conductivity.
@@ -422,62 +467,66 @@ Source code for tp.data.load
assert doping in [ 'n' , 'p' ], 'doping must be n or p'
- conversions = settings . boltztrap_conversions ()
+ bconversions = settings . boltztrap_conversions ()
+ conversions = settings . conversions ()
bnames = settings . to_boltztrap ()
tnames = settings . to_tp ()
units = settings . units ()
+ dimensions = settings . boltztrap_dimensions ()
if isinstance ( quantities , str ): quantities = quantities . split ()
quantities = [ bnames [ q ] if q in bnames else q for q in quantities ]
- # list of quantities dependant on doping and temperature
- hasdope = [ 'average_eff_mass' , 'conductivity' , 'fermi_level' , 'seebeck' ,
- 'power_factor' , 'electronic_thermal_conductivity' ]
- hastemp = [ 'average_eff_mass' , 'conductivity' , 'fermi_level' , 'seebeck' ,
- 'power_factor' , 'electronic_thermal_conductivity' ]
+ # add dependent variables
- # add dependant variables
-
- if 'doping' not in quantities :
- for q in quantities :
- if q in hasdope :
- quantities . append ( 'doping' )
- break
- if 'temperature' not in quantities :
- for q in quantities :
- if q in hastemp :
- quantities . append ( 'temperature' )
- break
+ for d in [ 'doping' , 'temperature' ]:
+ if d not in quantities :
+ for q in quantities :
+ if q in tnames :
+ q = tnames [ q ]
+ if q in dimensions and \
+ ( d in dimensions [ q ] or ( d in tnames and tnames [ d ] in dimensions [ q ])):
+ quantities . append ( d )
+ break
# load data
- data = h5py . File ( filename , 'r' )
+ with h5py . File ( filename , 'r' ) as f :
+ data = { 'meta' : { 'doping_type' : doping ,
+ 'electronic_source' : 'boltztrap' ,
+ 'units' : {},
+ 'dimensions' : {}}}
+ for q in quantities :
+ assert q in f , ' {} unrecognised. Quantity must be in {} or {} .' . format (
+ q , ', ' . join ( list ( f )[: - 1 ]), list ( f )[ - 1 ])
+ q2 = tnames [ q ] if q in tnames else q
+ if q2 in dimensions and 'dtype' in dimensions [ q2 ]:
+ data [ q2 ] = f [ q ][ doping ][()]
+ dimensions [ q2 ] . remove ( 'dtype' )
+ else :
+ data [ q2 ] = f [ q ][()]
+ if q2 in units :
+ data [ 'meta' ][ 'units' ][ q2 ] = units [ q2 ]
+ if q2 in dimensions :
+ data [ 'meta' ][ 'dimensions' ][ q2 ] = dimensions [ q2 ]
- data2 = { 'meta' : { 'electronic_source' : 'boltztrap' ,
- 'units' : {}}}
- for q in quantities :
- assert q in data , ' {} unrecognised. Quantity must be in {} or {} .' . format (
- q , ', ' . join ( list ( data )[: - 1 ]), list ( data )[ - 1 ])
- q2 = tnames [ q ] if q in tnames else q
- data2 [ q2 ] = data [ q ]
- if q in hasdope : data2 [ q2 ] = data2 [ q2 ][ doping ]
- if q2 in units :
- data2 [ 'meta' ][ 'units' ][ q2 ] = units [ q2 ]
+ for c in bconversions :
+ if c in data :
+ data [ c ] = np . multiply ( data [ c ], bconversions [ c ])
for c in conversions :
- if c in data2 :
- data2 [ c ] = np . multiply ( data2 [ c ], conversions [ c ])
+ if c in data :
+ data [ c ] = np . multiply ( data [ c ], conversions [ c ])
- return data2
+ return data
-
[docs] def phono3py ( filename , quantities = [ 'kappa' , 'temperature' ],
-
write_lifetime = False , write_mfp = False , write_occupation = False ):
+
[docs] def phono3py ( filename , quantities = [ 'kappa' , 'temperature' ]):
"""Loads Phono3py data.
-
Can also calculate lifetimes, mean free paths and occupations, which
-
can be written to a file.
-
Includes unit conversions and outputs units for all the data (see
-
tp.settings). Also corrects mode_kappa for different phono3py
-
versions.
+
Can also calculate lifetimes, mean free paths and occupations.
+
Includes unit conversions and outputs units and index order for all
+
the data (see tp.settings). Also corrects mode_kappa for different
+
phono3py versions. Also converts the default 6x1 direction matrices
+
into 3x3 ones for compatability with other codes.
Arguments
---------
@@ -485,18 +534,9 @@
Source code for tp.data.load
filename : str
filepath.
- quantities : list, optional
+ quantities : str or list, optional
values to extract. Accepts Phono3py keys, lifetime,
mean_free_path and occupation. Default: kappa, temperature.
- write_lifetime : bool, optional
- write lifetimes to a new hdf5 file if in quantites.
- Default: False.
- write_mfp : bool, optional
- write mean free paths to a new hdf5 file if in quantities.
- Default: False.
- write_occupation : bool, optional
- write occupations to a new hdf5 file if in quantities.
- Default: False.
Returns
-------
@@ -509,97 +549,117 @@ Source code for tp.data.load
# name conversions and abbreviations
- conversions = settings . phono3py_conversions ()
+ pconversions = settings . phono3py_conversions ()
+ conversions = settings . conversions ()
pnames = settings . to_phono3py ()
tnames = settings . to_tp ()
units = settings . units ()
+ dimensions = settings . dimensions ()
if isinstance ( quantities , str ): quantities = quantities . split ()
quantities = [ pnames [ q ] if q in pnames else q for q in quantities ]
- subs = { 'dispersion' : 'qpoint' ,
- 'waterfall' : 'frequency' ,
+ subs = { 'dispersion' : [ 'qpoint' ],
+ 'waterfall' : [ 'frequency' ],
'wideband' : [ 'frequency' , 'gamma' , 'qpoint' ]}
- hast = [ 'gamma' , 'heat_capacity' , 'kappa' , 'lifetime' ,
- 'mean_free_path' , 'mode_kappa' , 'occupation' ]
+
+ # quantities derived from those in the file
+ derived = { 'lifetime' : [ 'gamma' ],
+ 'mean_free_path' : [ 'gamma' , 'group_velocity' ],
+ 'occupation' : [ 'frequency' ]}
+
for i in range ( len ( quantities )):
if quantities [ i ] in subs :
quantities [ i ] = subs [ quantities [ i ]]
+ for q in derived :
+ if q in quantities :
+ for q2 in derived [ q ]:
+ if q2 not in quantities :
+ quantities . append ( q2 )
quantities = list ( np . ravel ( quantities ))
- # add dependant variables
+ # add dependent variables
- if 'temperature' not in quantities :
- for q in quantities :
- if q in hast :
- quantities . append ( 'temperature' )
- break
+ for d in [ 'temperature' , 'qpoint' ]:
+ if d not in quantities :
+ for q in quantities :
+ if q in tnames :
+ q = tnames [ q ]
+ if q in dimensions and d in dimensions [ q ]:
+ quantities . append ( d )
+ break
# load and calculate data
- data = h5py . File ( filename , 'r' )
-
- data2 = { 'meta' : { 'kappa_source' : 'phono3py' ,
- 'units' : {}}}
- for q in quantities :
- assert q in data or q in [ 'lifetime' , 'mean_free_path' , 'occupation' ], \
- ' {} unrecognised. Quantity must be {} , lifetime, mean_free_path ' \
- 'or occupation' . format ( q , ', ' . join ( data ))
- q2 = tnames [ q ] if q in tnames else q
- if q in data :
- data2 [ q2 ] = data [ q ][()]
- elif q in [ 'lifetime' , 'mean_free_path' ]:
- data2 [ 'lifetime' ] = np . reciprocal ( np . multiply ( 2 , data [ 'gamma' ][()]))
- data2 [ 'lifetime' ] = np . where ( np . isinf ( data2 [ 'lifetime' ]), 0 ,
- data2 [ 'lifetime' ])
- if q == 'mean_free_path' :
- data2 [ q ] = np . multiply ( np . transpose ([ data2 [ 'lifetime' ],] * 3 ,
- ( 1 , 2 , 3 , 0 )),
- data [ 'group_velocity' ][()])
- elif q == 'occupation' :
- from tp.calculate import be_occupation as occupation
- data2 [ q ] = [ occupation ( data [ 'frequency' ][()], t )
- for t in data [ 'temperature' ][()]]
- if q2 in units :
- data2 [ 'meta' ][ 'units' ][ q2 ] = units [ q2 ]
-
- # write calculated data (loath to mess with original file)
- for write , q in zip ([ write_lifetime , write_mfp , write_occupation ],
- [ 'lifetime' , 'mean_free_path' , 'occupation' ]):
- if write and q in quantities :
- data3 = h5py . File ( ' {} - {} ' . format ( q , filename ), 'w' )
- for q2 in [ q , 'temperature' , 'qpoint' ]:
- data3 . create_dataset ( q2 , np . shape ( data2 [ q2 ]), data = data2 [ q2 ])
- data3 . close ()
-
- # check mode_kappa and correct for certain phono3py versions
- if 'mode_kappa' in data2 :
- try :
- k = round ( data [ 'kappa' ][ - 1 ][ 0 ], 3 )
- mk = round ( data [ 'mode_kappa' ][ - 1 ][:,:, 0 ] . sum ( axis = 1 ) . sum (), 3 )
- if k != mk :
- raise Exception ( 'The sum of mode_kappa does not equal kappa. \n '
- 'kappa= {:.3f} ; sum(mode_kappa)= {:.3f} .' . format (
- k , mk ))
- except Exception :
- mk2 = np . divide ( data [ 'mode_kappa' ], np . prod ( data [ 'mesh' ][:]))
- k = round ( data [ 'kappa' ][ - 1 ][ 0 ], 3 )
- mk = round ( mk2 [ - 1 ][:,:, 0 ] . sum ( axis = 1 ) . sum (), 3 )
- if k != mk :
- raise Exception ( 'Mode kappa has been divided by the mesh, but '
- 'the sum of mode_kappa does not equal kappa. \n '
- 'kappa= {:.3f} ; sum(mode_kappa)= {:.3f} .' . format (
- k , mk ))
- else :
- data2 [ 'mode_kappa' ] = np . divide ( data2 [ 'mode_kappa' ],
- np . prod ( data [ 'mesh' ][()][:]))
-
- data . close ()
+ with h5py . File ( filename , 'r' ) as f :
+ data = { 'meta' : { 'kappa_source' : 'phono3py' ,
+ 'units' : {},
+ 'dimensions' : {}}}
+ for q in quantities :
+ q2 = tnames [ q ] if q in tnames else q
+ if q2 in units :
+ data [ 'meta' ][ 'units' ][ q2 ] = units [ q2 ]
+ if q2 in dimensions :
+ data [ 'meta' ][ 'dimensions' ][ q2 ] = dimensions [ q2 ]
+ if q in derived :
+ continue
+ qs = [ * list ( f ), * list ( derived )]
+ assert q in f , \
+ ' {} unrecognised. Quantity must be in {} or {} .' . format ( q ,
+ ', ' . join ( qs [: - 1 ]), qs [ - 1 ])
+ data [ q2 ] = f [ q ][()]
+ for i , d in enumerate ( dimensions [ q2 ]):
+ if d == 6 :
+ data [ q2 ] = np . moveaxis ( data [ q2 ], i , 0 )
+ data [ q2 ] = [[ data [ q2 ][ 0 ], data [ q2 ][ 5 ], data [ q2 ][ 4 ]],
+ [ data [ q2 ][ 5 ], data [ q2 ][ 1 ], data [ q2 ][ 3 ]],
+ [ data [ q2 ][ 4 ], data [ q2 ][ 3 ], data [ q2 ][ 2 ]]]
+ data [ q2 ] = np . moveaxis ( data [ q2 ], 0 , i + 1 )
+ data [ q2 ] = np . moveaxis ( data [ q2 ], 0 , i + 1 )
+ dimensions [ q2 ][ i ] = 3
+ dimensions [ q2 ] . insert ( i , 3 )
+
+ # check mode_kappa and correct for certain phono3py versions
+ if 'mode_kappa' in data :
+ try :
+ k = round ( f [ 'kappa' ][()][ - 1 ][ 0 ], 3 )
+ mk = round ( f [ 'mode_kappa' ][()][ - 1 ][:,:, 0 ] . sum ( axis = 1 ) . sum (), 3 )
+ if k != mk :
+ raise ValueError ( 'The sum of mode_kappa does not equal kappa. \n '
+ 'kappa= {:.3f} ; sum(mode_kappa)= {:.3f} .' . format (
+ k , mk ))
+ except ValueError :
+ mk2 = np . divide ( f [ 'mode_kappa' ][()], np . prod ( f [ 'mesh' ][()][:]))
+ k = round ( f [ 'kappa' ][()][ - 1 ][ 0 ], 3 )
+ mk = round ( mk2 [ - 1 ][:,:, 0 ] . sum ( axis = 1 ) . sum (), 3 )
+ if k != mk :
+ raise ValueError ( 'Mode kappa has been divided by the mesh, but '
+ 'the sum of mode_kappa does not equal kappa. \n '
+ 'kappa= {:.3f} ; sum(mode_kappa)= {:.3f} .' . format (
+ k , mk ))
+ else :
+ data [ 'mode_kappa' ] = np . divide ( data [ 'mode_kappa' ],
+ np . prod ( f [ 'mesh' ][()][:]))
+
+ for c in pconversions :
+ if c in data :
+ data [ c ] = np . multiply ( data [ c ], pconversions [ c ])
+
+ if 'lifetime' in quantities or 'mean_free_path' in quantities :
+ data [ 'lifetime' ] = tp . calculate . lifetime ( data [ 'gamma' ], use_tprc = False )
+ if 'mean_free_path' in quantities :
+ data [ 'mean_free_path' ] = tp . calculate . mfp ( data [ 'gamma' ],
+ data [ 'group_velocity' ],
+ use_tprc = False )
+ if 'occupation' in quantities :
+ data [ 'occupation' ] = tp . calculate . be_occupation ( data [ 'frequency' ],
+ data [ 'temperature' ],
+ use_tprc = False )
for c in conversions :
- if c in data2 :
- data2 [ c ] = np . multiply ( data2 [ c ], conversions [ c ])
+ if c in data :
+ data [ c ] = np . multiply ( data [ c ], conversions [ c ])
- return data2
+ return data
[docs] def phonopy_dispersion ( filename , xdata = None ):
"""Loads phonopy dispersion, and can scale the x values.
@@ -627,6 +687,9 @@
Source code for tp.data.load
import yaml
+ pconversions = settings . phonopy_conversions ()
+ conversions = settings . conversions ()
+
# load data
with open ( filename , 'r' ) as f :
@@ -650,11 +713,8 @@ Source code for tp.data.load
else :
d1 = d2
- conversions = settings . phonopy_conversions ()
- if 'frequency' in conversions :
- eigs *= conversions [ 'frequency' ]
-
units = tp . settings . units ()
+ dimensions = settings . dimensions ()
data2 = { 'x' : x ,
'qpoint' : qp ,
'frequency' : eigs ,
@@ -662,7 +722,16 @@ Source code for tp.data.load
'tick_label' : ticks ,
'meta' :
{ 'phonon_dispersion_source' : 'phonopy' ,
- 'units' : { 'frequency' : units [ 'frequency' ]}}}
+ 'units' : { 'frequency' : units [ 'frequency' ]},
+ 'dimensions' : { 'frequency' : dimensions [ 'frequency' ]}}}
+
+ for c in pconversions :
+ if c in data2 :
+ data2 [ c ] = np . multiply ( data2 [ c ], pconversions [ c ])
+
+ for c in conversions :
+ if c in data2 :
+ data2 [ c ] = np . multiply ( data2 [ c ], conversions [ c ])
return data2
@@ -698,14 +767,14 @@ Source code for tp.data.load
# load data
data = np . transpose ( np . loadtxt ( filename ))
+ pconversions = settings . phonopy_conversions ()
+ conversions = settings . conversions ()
units = tp . settings . units ()
+ dimensions = settings . dimensions ()
data2 = { 'frequency' : data [ 0 ],
'meta' : { 'phonon_dos_source' : 'phonopy' ,
- 'units' : { 'frequency' : units [ 'frequency' ]}}}
-
- conversions = settings . phonopy_conversions ()
- if 'frequency' in conversions :
- data2 [ 'frequency' ] *= conversions [ 'frequency' ]
+ 'units' : { 'frequency' : units [ 'frequency' ]},
+ 'dimensions' : { 'frequency' : dimensions [ 'frequency' ]}}}
if atoms is None :
from pymatgen.io.vasp.inputs import Poscar
@@ -738,6 +807,14 @@ Source code for tp.data.load
data2 [ 'total' ] = np . sum ( data [ 1 :], axis = 0 )
+ for c in pconversions :
+ if c in data2 :
+ data2 [ c ] = np . multiply ( data2 [ c ], pconversions [ c ])
+
+ for c in conversions :
+ if c in data2 :
+ data2 [ c ] = np . multiply ( data2 [ c ], conversions [ c ])
+
return data2
[docs] def get_path ( yamldata ):
@@ -748,7 +825,7 @@
Source code for tp.data.load
Arguments
---------
- yamldata : str
+ yamldata : dict
raw phonopy dispersion data (i.e. from yaml.safe_load).
Returns
@@ -776,46 +853,30 @@ Source code for tp.data.load
-
-
-
-
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/docs/_modules/tp/data/resolve.html b/docs/_modules/tp/data/resolve.html
index b83fbd2..ee35d23 100644
--- a/docs/_modules/tp/data/resolve.html
+++ b/docs/_modules/tp/data/resolve.html
@@ -1,72 +1,30 @@
-
-
-
-
-
tp.data.resolve — ThermoPlotter 1.0.0 documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
tp.data.resolve — ThermoPlotter 1.0.0 documentation
+
-
-
-
+
-
-
-
-
+
-
-
-
+
-
-
-
-
-
-
+
ThermoPlotter
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
Source code for tp.data.resolve
"""Resolves quantities by temperature and/ or direction.
-Reads specfic named variables. May need to be split by data origin in
-future.
+Reads variables and selects specific conditions. Requires
+['meta']['dimensions'] subdictionaries provided by tp load modules.
Functions
---------
- resolve:
- currently for Phono3py, AMSET and BoltzTraP.
+ resolve
"""
import numpy as np
import tp.settings
-from tp.data import aniso
+import warnings
+from copy import deepcopy
+
+[docs] def resolve ( data , quantities , ** kwargs ):
+
"""Selects particular values of arbitrary quantities.
-
[docs] def resolve ( data , quantities , temperature = None , direction = None ):
-
"""Selects temperature and/or direction.
+
Requires the meta/dimensions dictionaries found in later versions
+
of tp. Currently cannot accept dictionary keys (e.g. dtype='n') if
+
they are not in the 0th index.
Arguments
---------
data : dict
-
data.
+
data with meta/dimensions dictionaries and quantities.
quantities : array-like or str
quantities to resolve
-
temperature : float, optional
-
temperature to select. Default: None.
-
direction : str, optional
-
direction to resolve, accepts x-z/, a-c, average/ avg or
-
normal/ norm. Default: None.
+
kwargs
+
dimesions to resolve. Rounds to nearest available value.
+
Common options include:
+
+
direction
+
direction to resolve, accepts x-z/, a-c,
+
average/ avg or normal/ norm.
+
dtype
+
n or p
+
stype
+
codes from amset, e.g. IMP, or overall
+
doping
+
concentration, not to be confused with dtype
+
temperature
Returns
-------
@@ -203,108 +123,135 @@
Source code for tp.data.resolve
resolved data.
"""
- data = dict ( data ) # sever the link to enable the original data to be reused
-
- # variables resolved by temperature and direction
- hast = [ 'average_eff_mass' , 'conductivity' ,
- 'electronic_thermal_conductivity' , 'fermi_level' , 'gamma' ,
- 'heat_capacity' , 'lattice_thermal_conductivity' , 'lifetime' ,
- 'mean_free_path' , 'mode_kappa' , 'occupation' , 'power_factor' ,
- 'seebeck' , 'velocities_product' , 'zt' ]
- iso = { 'average_eff_mass' : aniso . matrix_three ,
- 'conductivity' : aniso . matrix_three ,
- 'electronic_thermal_conductivity' : aniso . matrix_three ,
- 'group_velocity' : aniso . three ,
- 'gv_by_gv' : aniso . three ,
- 'lattice_thermal_conductivity' : aniso . two ,
- 'mean_free_path' : aniso . four ,
- 'mesh' : aniso . one ,
- 'mode_kappa' : aniso . four ,
- 'power_factor' : aniso . matrix_three ,
- 'qpoint' : aniso . two ,
- 'seebeck' : aniso . matrix_three ,
- 'velocities_product' : aniso . matrix_two ,
- 'zt' : aniso . matrix_three }
-
- # temperature resolution
-
- if temperature is not None and 'temperature' in data :
- ti = np . abs ( np . array ( data [ 'temperature' ]) - temperature ) . argmin ()
- data [ 'meta' ][ 'temperature' ] = data [ 'temperature' ][ ti ]
-
- iso [ 'average_eff_mass' ] = aniso . matrix_two
- iso [ 'conductivity' ] = aniso . matrix_two
- iso [ 'electronic_thermal_conductivity' ] = aniso . matrix_two
- iso [ 'lattice_thermal_conductivity' ] = aniso . one
- iso [ 'mean_free_path' ] = aniso . three
- iso [ 'mode_kappa' ] = aniso . three
- iso [ 'power_factor' ] = aniso . matrix_two
- iso [ 'seebeck' ] = aniso . matrix_two
- iso [ 'velocities_product' ] = aniso . matrix_one
- iso [ 'zt' ] = aniso . matrix_two
- if direction is not None :
- data [ 'meta' ][ 'direction' ] = direction
-
- # direction resolution
-
- tnames = tp . settings . to_tp ()
+ data = deepcopy ( data ) # sever the link to enable the original data to be reused
+ if 'meta' not in data or 'dimensions' not in data [ 'meta' ]:
+ raise Exception ( 'data must have a meta subdictionary with a '
+ 'dimensions subdictionary.' )
if isinstance ( quantities , str ):
quantities = quantities . split ()
- quantities2 = []
- for i in quantities :
- if i not in quantities2 :
- quantities2 . append ( i )
- for q in quantities2 :
- q2 = tnames [ q ] if q in tnames else q
- if temperature is not None and q2 in hast :
- data [ q ] = data [ q ][ ti ]
- if direction is not None and q2 in iso :
- data [ q ] = iso [ q2 ]( data [ q ], direction )
+ direction = { 'a' : 0 , 'b' : 1 , 'c' : 2 ,
+ 'x' : 0 , 'y' : 1 , 'z' : 2 }
+
+ # make sure dictionaries are dealt with first
+ keys , vals = [], []
+ for key , val in kwargs . items ():
+ if isinstance ( val , str ) and key != 'direction' :
+ keys . insert ( 0 , key )
+ vals . insert ( 0 , val )
+ else :
+ keys . append ( key )
+ vals . append ( val )
+
+ for q in quantities :
+ if q not in data [ 'meta' ][ 'dimensions' ]:
+ warnings . warn ( ' {} not in dimensions. Skipping.' . format ( q ))
+ continue
+ for key , val in zip ( keys , vals ):
+ if val is None :
+ continue
+ if key != 'direction' :
+ if key not in data and key not in [ 'dtype' , 'stype' ]:
+ warnings . warn ( ' {} not in data. Skipping.' . format ( key ))
+ continue
+ if key not in data [ 'meta' ][ 'dimensions' ][ q ]:
+ continue
+ if isinstance ( val , str ):
+ data [ 'meta' ][ key ] = val
+ for i , d in enumerate ( data [ 'meta' ][ 'dimensions' ][ q ]):
+ if d == key :
+ if i == 0 :
+ del data [ 'meta' ][ 'dimensions' ][ q ][ i ]
+ data [ q ] = data [ q ][ val ]
+ data [ 'meta' ][ key ] = val
+ break
+ else :
+ warnings . warn ( 'Does not currently work '
+ 'unless strings are in '
+ 'the 0th index.' )
+ break
+ elif isinstance ( val , ( int , float , list , np . ndarray )):
+ if isinstance ( val , ( int , float )):
+ index = np . abs ( np . subtract ( data [ key ], val )) . argmin ()
+ else :
+ index = np . sqrt ( np . sum ( np . square (
+ np . subtract ( data [ key ], val )), axis = 1 )) . argmin ()
+ data [ 'meta' ][ key ] = data [ key ][ index ]
+ for i , d in enumerate ( data [ 'meta' ][ 'dimensions' ][ q ]):
+ if d == key :
+ del data [ 'meta' ][ 'dimensions' ][ q ][ i ]
+ data [ q ] = np . moveaxis ( data [ q ], i , 0 )
+ data [ q ] = data [ q ][ index ]
+ data [ 'meta' ][ key ] = data [ key ][ index ]
+ break
+ else : # if key == 'direction':
+ while True :
+ for i , d in enumerate ( data [ 'meta' ][ 'dimensions' ][ q ]):
+ if d in [ 3 , 6 ]:
+ del data [ 'meta' ][ 'dimensions' ][ q ][ i ]
+ data [ q ] = np . moveaxis ( data [ q ], i , 0 )
+ if val in direction :
+ data [ q ] = data [ q ][ direction [ val ]]
+ elif val in [ 'avg' , 'average' ]:
+ if len ( data [ 'meta' ][ 'dimensions' ][ q ]) > i and \
+ data [ 'meta' ][ 'dimensions' ][ q ][ i ] == 3 :
+ # if this is a 3x3 array
+ del data [ 'meta' ][ 'dimensions' ][ q ][ i ]
+ data [ q ] = np . moveaxis ( data [ q ], i + 1 , 1 )
+ data [ q ] = np . average ([ data [ q ][ 0 ][ 0 ],
+ data [ q ][ 1 ][ 1 ],
+ data [ q ][ 2 ][ 2 ]],
+ axis = 0 )
+ else :
+ # if this is a 3x1 or 6x1 array
+ data [ q ] = np . average ( data [ q ][: 3 ], axis = 0 )
+ elif val in [ 'norm' , 'normal' ]:
+ if data [ 'meta' ][ 'dimensions' ][ q ][ i ] == 3 :
+ # if this is a 3x3 array
+ del data [ 'meta' ][ 'dimensions' ][ q ][ i ]
+ data [ q ] = np . moveaxis ( data [ q ], i + 1 , 1 )
+ data [ q ] = np . square ( data [ q ][ 0 ][ 0 ]) \
+ + np . square ( data [ q ][ 1 ][ 1 ]) \
+ + np . square ( data [ q ][ 2 ][ 2 ])
+ data [ q ] = np . sqrt ( data [ q ])
+ else :
+ # if this is a 3x1 or 6x1 array
+ data [ q ] = np . square ( data [ q ][ 0 ]) \
+ + np . square ( data [ q ][ 1 ]) \
+ + np . square ( data [ q ][ 2 ])
+ data [ q ] = np . sqrt ( data [ q ])
+ data [ 'meta' ][ key ] = val
+ break
+ else :
+ break
return data
-
-
-
-
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/docs/_modules/tp/data/run.html b/docs/_modules/tp/data/run.html
index a6ef631..751fd97 100644
--- a/docs/_modules/tp/data/run.html
+++ b/docs/_modules/tp/data/run.html
@@ -1,72 +1,30 @@
-
-
-
-
-
tp.data.run — ThermoPlotter 1.0.0 documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
tp.data.run — ThermoPlotter 1.0.0 documentation
+
-
-
-
+
-
-
-
-
+
-
-
-
+
-
-
-
-
-
-
+
ThermoPlotter
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
Source code for tp.data.run
"""Code running tools.
@@ -172,12 +79,14 @@ Source code for tp.data.run
"""
import numpy as np
+import os
+import shutil
import tp
[docs] def boltztrap ( tmax = 1001 , tstep = 50 , tmin = None , doping = np . logspace ( 18 , 21 , 17 ),
ke_mode = 'boltzmann' , vasprun = 'vasprun.xml' , kpoints = None ,
relaxation_time = 1e-14 , lpfac = 10 , run = True , analyse = True ,
-
output = 'boltztrap.hdf5' , ** kwargs ):
+
output = 'boltztrap.hdf5' , run_dir = '.' , clean = False , ** kwargs ):
"""Runs BoltzTraP from a VASP density of states (DoS).
Runs quicker and more robustly than the pymatgen from_files version,
@@ -229,6 +138,10 @@
Source code for tp.data.run
analyse BoltzTraP. Default: True.
output : str, optional
output hdf5 filename. Default: boltztrap.hdf5.
+ run_dir : str, optional
+ path to run boltztrap in. Default: current directory.
+ clean : bool, optional
+ remove boltztrap directory post-run. Default: False.
kwargs
passed to pymatgen.electronic.structure.boltztrap.BoltztrapRunner.
@@ -296,8 +209,8 @@ Source code for tp.data.run
# check inputs
- for name , value in zip ([ 'run' , 'analyse' ],
- [ run , analyse ]):
+ for name , value in zip ([ 'run' , 'analyse' , 'clean' ],
+ [ run , analyse , clean ]):
assert isinstance ( value , bool ), ' {} must be True or False' . format ( name )
ke_mode = ke_mode . lower ()
@@ -305,6 +218,8 @@ Source code for tp.data.run
assert ke_mode in ke_modes , 'ke_mode must be {} or {} .' . format (
', ' . join ( ke_modes [: - 1 ]), ke_modes [ - 1 ])
+ run_dir = os . path . abspath ( run_dir )
+
tmax += tstep
tmin = tstep if tmin is None else tmin
temperature = np . arange ( tmin , tmax , tstep )
@@ -319,31 +234,29 @@ Source code for tp.data.run
btr = BoltztrapRunner ( bs , nelect , doping = list ( doping ), tmax = tmax ,
tgrid = tstep , soc = soc , lpfac = lpfac , ** kwargs )
print ( 'Running Boltztrap...' , end = '' )
- btr_dir = btr . run ( path_dir = '.' )
+ btr_dir = btr . run ( path_dir = run_dir )
print ( 'Done.' )
except BoltztrapError :
bs = vr . get_band_structure ( line_mode = True , kpoints_filename = kpoints )
nelect = vr . parameters [ 'NELECT' ]
btr = BoltztrapRunner ( bs , nelect , doping = list ( doping ), tmax = tmax ,
tgrid = tstep , soc = soc , lpfac = lpfac , ** kwargs )
- btr_dir = btr . run ( path_dir = '.' )
+ btr_dir = btr . run ( path_dir = run_dir )
print ( 'Done.' )
-
"""
Detects whether the BoltzTraP build on this computer writes the
doping concentrations correctly, and if it doesn't, writes them.
"""
- with open ( 'boltztrap/boltztrap.outputtrans' , 'r' ) as f :
+ with open ( os . path . join ( btr_dir , 'boltztrap.outputtrans' ), 'r' ) as f :
line = f . readlines ()[ - 2 ]
if len ( line ) >= 23 and line [: 23 ] == ' Calling FermiIntegrals' :
with open ( os . path . join ( btr_dir , 'boltztrap.outputtrans' ), 'a' ) as f :
for i , x in enumerate ( np . concatenate (( doping , - doping ))):
f . write (
'Doping level number {} n = {} carriers/cm3 \n ' . format ( i , x ))
-
else :
- btr_dir = 'boltztrap'
+ btr_dir = os . path . join ( run_dir , 'boltztrap' )
if analyse : # run boltztrap from boltztrap directory -> hdf5 file
print ( 'Analysing Boltztrap...' , end = '' )
@@ -398,7 +311,8 @@ Source code for tp.data.run
data [ 'seebeck' ][ d ] = np . multiply ( s [ d ], 1e6 )
data [ 'power_factor' ][ d ] = tp . calculate . power_factor (
data [ 'conductivity' ][ d ],
- data [ 'seebeck' ][ d ])
+ data [ 'seebeck' ][ d ],
+ use_tprc = False )
if ke_mode == 'boltztrap' :
data [ 'electronic_thermal_conductivity' ][ d ] = \
k [ d ] * relaxation_time \
@@ -416,50 +330,38 @@ Source code for tp.data.run
tp . data . save . hdf5 ( data , output )
+ if clean :
+ shutil . rmtree ( btr_dir )
+ os . remove ( os . path . join ( run_dir , 'boltztrap.out' ))
+
return
-
-
-
-
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/docs/_modules/tp/data/save.html b/docs/_modules/tp/data/save.html
index 80c13ff..7fb9aec 100644
--- a/docs/_modules/tp/data/save.html
+++ b/docs/_modules/tp/data/save.html
@@ -1,72 +1,30 @@
-
-
-
-
- tp.data.save — ThermoPlotter 1.0.0 documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ tp.data.save — ThermoPlotter 1.0.0 documentation
+
-
-
-
+
-
-
-
-
+
-
-
-
+
-
-
-
-
-
-
+
ThermoPlotter
-
-
-
-
-
+
+
+
+
+
Source code for tp.data.save
+"""Utilities to save data
+Functions:
+ phono3py: save calculated properties to hdf5.
+ zt: save zt to hdf5 and highlights to yaml.
+ kappa_target: save kappa to hdf5.
+ cumkappa: save cumkappa to text.
+ hdf5: save nested dictionaries to hdf5 (up to depth 3).
+ prompt: prompt before overwriting input
+"""
+import h5py
+import numpy as np
+from scipy.interpolate import interp1d , interp2d
+from sys import exit
+import tp
+import yaml
+[docs] def phono3py ( filename , quantities , output = 'tp-phono3py' , force = False ):
+
"""Save calculated properties to hdf5.
+
Also saves dependent properties (temperature etc.) and metadata.
+
Arguments
+
---------
+
filename : str
+
filepath.
+
quantities : str or list
+
values to save. Accepts any phonop3y properties, but only
+
lifetime, mean_free_path and/ or occupation are recommended.
+
output : str, optional
+
output filename (no extension). Default: tp-phono3py.
+
force : bool, optional
+
force overwrite input file. Default: False.
+
Returns
+
-------
+
none
+
instead writes to hdf5.
+
"""
+
if not force :
+
prompt ( filename , ' {} .hdf5' . format ( output ))
+
hdf5 ( tp . data . load . phono3py ( filename , quantities ), ' {} .hdf5' . format ( output ))
+
return
+[docs] def zt ( efile , kfile = None , direction = 'avg' , doping = 'n' , tinterp = None ,
+
dinterp = None , kind = 'linear' , output = 'tp-zt' , force = False ):
+
"""Save ZT to hdf5 and highlights to yaml.
+
Also saves temperature and doping and metadata.
+
Arguments
+
---------
+
efile : str
+
electronic data filepath.
+
+
kfile : str
+
phononic data filepath.
+
direction : str, optional
+
crystal direction, accepts x-z/ a-c or average/ avg.
+
Default: average.
+
doping : str, optional
+
doping type for BoltzTraP. Must be n or p. Default: n.
+
+
tinterp : int, optional
+
density of interpolation for temperature. None turns it off.
+
Default: 200.
+
dinterp : int, optional
+
density of interpolation for doping. None turns it off.
+
Default: 200.
+
kind : str, optional
+
interpolation kind. Default: linear.
+
+
output : str, optional
+
output filename (no extension). Default: tp-zt.
+
force : bool, optional
+
force overwrite input file. Default: False.
-
+
Returns
+
-------
-
+
none
+
instead writes to hdf5, yaml and stdout.
+
"""
-
-
-
-
-
-
-
Source code for tp.data.save
-"""Utility to save to hdf5"""
+ if not force :
+ for f in [ efile , kfile ]:
+ prompt ( f , [ ' {} .hdf5' . format ( output ), ' {} .yaml' . format ( output )])
+
+ try :
+ edata = tp . data . load . amset ( efile )
+ except UnicodeDecodeError :
+ edata = tp . data . load . boltztrap ( efile , doping = doping )
+
+ equants = [ 'conductivity' , 'seebeck' , 'electronic_thermal_conductivity' ]
+ ltc = 'lattice_thermal_conductivity'
+ edata = tp . data . resolve . resolve ( edata , equants , direction = direction )
+
+ if kfile is not None :
+ kdata = tp . data . load . phono3py ( kfile )
+ kdata = tp . data . resolve . resolve ( kdata , ltc , direction = direction )
+ edata , kdata = tp . calculate . interpolate ( edata , kdata , 'temperature' ,
+ equants , ltc , kind = 'cubic' )
+ edata [ ltc ] = kdata [ ltc ]
+ edata [ 'meta' ][ 'kappa_source' ] = kdata [ 'meta' ][ 'kappa_source' ]
+ else : # if lattice thermal conductivity not supplied, set to 1 W m-1 K-1
+ edata [ ltc ] = np . ones ( len ( edata [ 'temperature' ]))
+ edata [ 'meta' ][ 'kappa_source' ] = 'Set to 1 W m^-1 K^-1'
+ edata = tp . calculate . zt_fromdict ( edata )
+
+ ztdata = { 'meta' : { ** edata [ 'meta' ],
+ 'original_temperature' : np . array (
+ edata [ 'temperature' ]) . tolist (),
+ 'original_doping' : np . array (
+ edata [ 'doping' ]) . tolist ()}}
+ # interpolation of zt (if applicable)
+ if tinterp is not None or dinterp is not None :
+ if tinterp is None :
+ ztdata [ 'temperature' ] = np . array ( edata [ 'temperature' ]) . tolist ()
+ else :
+ ztdata [ 'temperature' ] = np . linspace ( edata [ 'temperature' ][ 0 ],
+ edata [ 'temperature' ][ - 1 ],
+ tinterp ) . tolist ()
+ if dinterp is None :
+ ztdata [ 'doping' ] = np . array ( edata [ 'doping' ]) . tolist ()
+ else :
+ ztdata [ 'doping' ] = np . geomspace ( edata [ 'doping' ][ 0 ],
+ edata [ 'doping' ][ - 1 ],
+ dinterp ) . tolist ()
+
+ ztinterp = interp2d ( edata [ 'doping' ], edata [ 'temperature' ], edata [ 'zt' ],
+ kind = kind )
+ ztdata [ 'zt' ] = ztinterp ( ztdata [ 'doping' ],
+ ztdata [ 'temperature' ]) . tolist ()
+ else :
+ ztdata [ 'zt' ] = np . array ( edata [ 'zt' ]) . tolist ()
+ ztdata [ 'temperature' ] = np . array ( edata [ 'temperature' ]) . tolist ()
+ ztdata [ 'doping' ] = np . array ( edata [ 'doping' ]) . tolist ()
+
+ hdf5 ( ztdata , ' {} .hdf5' . format ( output ))
+
+ # highlights
+ ydata = { 'meta' : ztdata [ 'meta' ],
+ 'max' : {}}
+
+ # max zt and corresponding temperature and doping
+ maxindex = np . where ( np . round ( ztdata [ 'zt' ], 10 ) \
+ == np . round ( np . amax ( ztdata [ 'zt' ]), 10 ))
+ ydata [ 'max' ][ 'zt' ] = ztdata [ 'zt' ][ maxindex [ 0 ][ 0 ]][ maxindex [ 1 ][ 0 ]]
+ ydata [ 'max' ][ 'temperature' ] = ztdata [ 'temperature' ][ maxindex [ 0 ][ 0 ]]
+ ydata [ 'max' ][ 'doping' ] = ztdata [ 'doping' ][ maxindex [ 1 ][ 0 ]]
+
+ # max zt per temperature and corresponding doping
+ maxindices = [( i , np . where ( np . round ( zt , 10 ) \
+ == np . round ( np . amax ( zt ), 10 ))[ 0 ][ 0 ]) \
+ for i , zt in enumerate ( ztdata [ 'zt' ])]
+ ydata [ 'zt' ] = [ ztdata [ 'zt' ][ i ][ j ] for i , j in maxindices ]
+ ydata [ 'temperature' ] = ztdata [ 'temperature' ]
+ ydata [ 'doping' ] = [ ztdata [ 'doping' ][ i ] for _ , i in maxindices ]
+
+ with open ( ' {} .yaml' . format ( output ), 'w' ) as f :
+ yaml . dump ( ydata , f , default_flow_style = False )
+
+ print ( 'Max ZT in the {} direction of {:.2f} at {:.0f} K, {:.2e} carriers cm^-3' . format (
+ direction ,
+ ydata [ 'max' ][ 'zt' ],
+ ydata [ 'max' ][ 'temperature' ],
+ ydata [ 'max' ][ 'doping' ]))
-import h5py
-import numpy as np
+ return
+
+
[docs] def kappa_target ( filename , zt = 2 , direction = 'avg' , doping = 'n' , tinterp = None ,
+
dinterp = None , kind = 'linear' , output = 'tp-kappa-target' ,
+
force = False ):
+
"""Save target kappa_l to hdf5.
+
+
Also saves temperature and doping and metadata.
+
+
Arguments
+
---------
+
+
filename : str
+
data filepath.
+
+
zt : float, optional
+
target ZT. Default: 2.
+
direction : str, optional
+
crystal direction, accepts x-z/ a-c or average/ avg.
+
Default: average.
+
doping : str, optional
+
doping type for BoltzTraP. Must be n or p. Default: n.
+
+
tinterp : int, optional
+
density of interpolation for temperature. None turns it off.
+
Default: 200.
+
dinterp : int, optional
+
density of interpolation for doping. None turns it off.
+
Default: 200.
+
kind : str, optional
+
interpolation kind. Default: linear.
+
+
output : str, optional
+
output filename (no extension). Default: tp-kappa-target.
+
force : bool, optional
+
force overwrite input file. Default: False.
+
+
Returns
+
-------
+
+
none
+
instead writes to hdf5.
+
"""
+
+
if not force :
+
prompt ( filename , ' {} .hdf5' . format ( output ))
+
+
try :
+
data = tp . data . load . amset ( filename )
+
except UnicodeDecodeError :
+
data = tp . data . load . boltztrap ( filename , doping = doping )
+
data = tp . data . resolve . resolve ( data , [ 'conductivity' , 'seebeck' ,
+
'electronic_thermal_conductivity' ],
+
direction = direction )
+
data [ 'zt' ] = zt
+
+
data = tp . calculate . kl_fromdict ( data )
+
+
kdata = { 'meta' : { ** data [ 'meta' ],
+
'original_temperature' : data [ 'temperature' ],
+
'original_doping' : data [ 'doping' ]}}
+
# interpolation of kl (if applicable)
+
if tinterp is not None or dinterp is not None :
+
if tinterp is None :
+
kdata [ 'temperature' ] = data [ 'temperature' ]
+
else :
+
kdata [ 'temperature' ] = np . linspace ( data [ 'temperature' ][ 0 ],
+
data [ 'temperature' ][ - 1 ],
+
tinterp )
+
if dinterp is None :
+
kdata [ 'doping' ] = data [ 'doping' ]
+
else :
+
kdata [ 'doping' ] = np . geomspace ( data [ 'doping' ][ 0 ],
+
data [ 'doping' ][ - 1 ], dinterp )
+
+
kinterp = interp2d ( data [ 'doping' ], data [ 'temperature' ],
+
data [ 'electronic_thermal_conductivity' ], kind = kind )
+
kdata [ 'lattice_thermal_conductivity' ] = kinterp ( kdata [ 'doping' ],
+
kdata [ 'temperature' ])
+
else :
+
kdata [ 'lattice_thermal_conductivity' ] = \
+
data [ 'lattice_thermal_conductivity' ]
+
kdata [ 'temperature' ] = data [ 'temperature' ]
+
kdata [ 'doping' ] = data [ 'doping' ]
+
+
hdf5 ( kdata , ' {} .hdf5' . format ( output ))
+
+
return
+
+
[docs] def cumkappa ( filename , mfp = False , temperature = 300 , direction = 'avg' ,
+
output = 'tp-cumkappa' , extension = 'dat' , force = False ):
+
"""Saves cumulated lattice thermal conductivity against frequency or mfp.
+
+
Saves in normal units and percent to a dat file.
+
+
Arguments
+
---------
+
+
filename : str
+
data filepath
+
+
mfp : bool, optional
+
calculate against mean free path not frequency. Default: False.
+
temperature : float or int, optional
+
temperature in K. Default: 300.
+
direction : str, optional
+
crystal direction, accepts x-z/ a-c or average/ avg.
+
Default: average.
+
+
output : str, optional
+
output filename (no extension). Default: tp-kappa-target.
+
extension : str or list, optional
+
output filetype. Must be dat and/ or csv. Default: dat.
+
force : bool, optional
+
force overwrite input file. Default: False.
+
+
Returns
+
-------
+
+
none
+
instead writes to dat.
+
"""
+
+
if isinstance ( extension , str ):
+
extension = [ extension ]
+
csv , dat = False , False
+
for e in extension :
+
if e == 'csv' :
+
if not csv :
+
csv = True
+
else :
+
print ( 'Ignoring duplicate extension csv.' )
+
elif e == 'dat' :
+
if not dat :
+
dat = True
+
else :
+
print ( 'Ignoring duplicate extension dat.' )
+
else :
+
raise Exception ( 'Extension must be dat and/ or csv.' )
+
+
quantity = 'mean_free_path' if mfp else 'frequency'
+
data = tp . data . load . phono3py ( filename , [ 'mode_kappa' , quantity ])
+
data = tp . data . resolve . resolve ( data , [ 'mode_kappa' , quantity ],
+
temperature = temperature , direction = direction )
+
k = np . ravel ( data [ 'mode_kappa' ])
+
q = np . ravel ( data [ quantity ])
+
q , k = tp . calculate . cumulate ( q , k )
+
p = k / np . nanmax ( k ) * 100
+
+
units = tp . settings . units ()
+
header = ' {} ( {} ) cum_kappa_ {d} ( {} ) cum_kappa_ {d} (%)' . format ( quantity ,
+
units [ quantity ], units [ 'mode_kappa' ], d = direction )
+
if csv :
+
np . savetxt ( ' {} .csv' . format ( output ), np . transpose ([ q , k , p ]),
+
header = header , delimiter = ',' )
+
if dat :
+
np . savetxt ( ' {} .dat' . format ( output ), np . transpose ([ q , k , p ]),
+
header = header , delimiter = ' ' )
+
+
return
[docs] def hdf5 ( data , output ):
"""Saves to hdf5.
@@ -188,67 +427,97 @@
Source code for tp.data.save
instead writes to file.
"""
- datafile = h5py . File ( output , 'w' )
+ with h5py . File ( output , 'w' ) as f :
+ for key in data . keys ():
+ if isinstance ( data [ key ], dict ):
+ group = f . create_group ( key )
+ for k in data [ key ] . keys ():
+ if isinstance ( data [ key ][ k ], dict ):
+ group2 = group . create_group ( k )
+ for k2 in data [ key ][ k ] . keys ():
+ if isinstance ( data [ key ][ k ][ k2 ], list ) and \
+ len ( data [ key ][ k ][ k2 ]) != 0 and \
+ isinstance ( data [ key ][ k ][ k2 ][ 0 ], str ):
+ ds = group2 . create_dataset ( k2 , ( len ( data [ key ][ k ][ k2 ]),),
+ dtype = h5py . string_dtype ())
+ ds = data [ key ][ k ][ k2 ]
+ else :
+ group2 [ k2 ] = data [ key ][ k ][ k2 ]
+ else :
+ group [ k ] = data [ key ][ k ]
+ else :
+ f . create_dataset ( key , np . shape ( data [ key ]), data = data [ key ])
- for key in data . keys ():
- if isinstance ( data [ key ], dict ):
- group = datafile . create_group ( key )
- for k in data [ key ] . keys ():
- if isinstance ( data [ key ][ k ], dict ):
- group2 = group . create_group ( k )
- for k2 in data [ key ][ k ] . keys ():
- group2 [ k2 ] = data [ key ][ k ][ k2 ]
- else :
- group [ k ] = data [ key ][ k ]
- else :
- datafile . create_dataset ( key , np . shape ( data [ key ]), data = data [ key ])
+ return
-
datafile . close ()
+
[docs] def prompt ( filename , output ):
+
"""Prompts before overwrite.
+
+
Arguments
+
---------
+
+
filename : str
+
input filename.
+
output : str or list
+
output filename(s).
+
+
Returns
+
-------
+
+
none
+
"""
+
+
if isinstance ( output , str ):
+
output = [ output ]
+
if filename in output :
+
tries = 3
+
while True :
+
print ( 'Warning: this will overwrite {} . Continue?' . format ( filename ))
+
cont = input ( '[y/n]' ) . lower ()
+
if cont in [ 'y' , 'ye' , 'yes' ]:
+
print ( 'Continuing...' )
+
break
+
elif cont in [ 'n' , 'no' ]:
+
print ( 'Aborting!' )
+
exit ()
+
else :
+
tries -= 1
+
if tries == 2 :
+
print ( 'Invalid response. 2 tries remain.' )
+
elif tries == 1 :
+
print ( 'Invalid response. 1 try remains.' )
+
else :
+
print ( 'Invalid response. Aborting!' )
+
exit ()
return
-
-
-
-
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/docs/_modules/tp/plot/colour.html b/docs/_modules/tp/plot/colour.html
index 5abbee5..e613221 100644
--- a/docs/_modules/tp/plot/colour.html
+++ b/docs/_modules/tp/plot/colour.html
@@ -1,72 +1,30 @@
-
-
-
-
-
tp.plot.colour — ThermoPlotter 1.0.0 documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
tp.plot.colour — ThermoPlotter 1.0.0 documentation
+
-
-
-
+
-
-
-
-
+
-
-
-
+
-
-
-
-
-
-
+
ThermoPlotter
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
Source code for tp.plot.colour
"""Colour scheme and colourmap generators.
@@ -186,6 +93,7 @@ Source code for tp.plot.colour
colour converter.
"""
+from wsgiref.simple_server import WSGIRequestHandler
from matplotlib.colors import ListedColormap
import matplotlib as mpl
import matplotlib.pyplot as plt
@@ -257,7 +165,7 @@ Source code for tp.plot.colour
cmax2 = np . array ( rgb2array ( cmax , alpha ))
cnorm = ( cmid2 [: 3 ] - cmin2 [: 3 ]) / ( cmax2 [: 3 ] - cmin2 [: 3 ])
# pythagoras
- midpoint = np . sqrt ((( 1 - cnorm [ 0 ]) ** 2 + ( 1 - cnorm [ 1 ]) ** 2 + ( 1 - cnorm [ 2 ]) ** 2 ) / 3 )
+ midpoint = np . sqrt (( cnorm [ 0 ] ** 2 + cnorm [ 1 ] ** 2 + cnorm [ 2 ] ** 2 ) / 3 )
x = [ 0 , midpoint , 1 ]
y = [ cmin2 , cmid2 , cmax2 ]
colours = []
@@ -452,46 +360,30 @@ Source code for tp.plot.colour
-
-
-
-
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/docs/_modules/tp/plot/frequency.html b/docs/_modules/tp/plot/frequency.html
index 45296cf..2e62468 100644
--- a/docs/_modules/tp/plot/frequency.html
+++ b/docs/_modules/tp/plot/frequency.html
@@ -1,72 +1,30 @@
-
-
-
-
-
tp.plot.frequency — ThermoPlotter 1.0.0 documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
tp.plot.frequency — ThermoPlotter 1.0.0 documentation
+
-
-
-
+
-
-
-
-
+
-
-
-
+
-
-
-
-
-
-
+
ThermoPlotter
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
Source code for tp.plot.frequency
"""Functions which plot phonon frequency on the x-axis.
@@ -185,8 +92,8 @@ Source code for tp.plot.frequency
add_density:
density of phonon modes for a property vs frequency.
- format_waterfall
- formatting for the waterfall and density plots
+ format_waterfall:
+ formatting for the waterfall and density plots.
"""
import matplotlib as mpl
@@ -205,11 +112,16 @@ Source code for tp.plot.frequency
filename = ' {} /.config/tprc.yaml' . format ( os . path . expanduser ( "~" ))
with open ( filename , 'r' ) as f :
conf = yaml . safe_load ( f )
-except Exception :
+except yaml . parser . ParserError :
+ warnings . warn ( 'Failed to read ~/.config/tprc.yaml' )
+ conf = None
+except FileNotFoundError :
conf = None
-[docs] def add_dos ( ax , data , total = False , main = True , invert = False , scale = False ,
-
colour = 'tab10' , fill = True , fillalpha = 0.2 , line = True , ** kwargs ):
+
[docs] def add_dos ( ax , data , projected = True , total = False , totallabel = 'Total' ,
+
main = True , invert = False , scale = False , colour = 'tab10' ,
+
totalcolour = None , fill = True , fillalpha = 0.2 , line = True ,
+
linestyle = '-' , marker = None , ** kwargs ):
"""Adds a phonon density of states (DoS) to a set of axes.
Arguments
@@ -220,8 +132,13 @@
Source code for tp.plot.frequency
data : dict
DoS data.
+ projected : bool, optional
+ plot atom-projected DoS. Default: True.
total : bool, optional
plot total DoS. Default: False
+ totallabel : str, optional
+ label for the total line. Other labels are taken directly
+ from the input dictionary. Default: Total.
main : bool, optional
set ticks, labels, limits. Default: True.
@@ -233,14 +150,27 @@ Source code for tp.plot.frequency
colour : dict or list or str or colourmap, optional
RGB colours per atom as a dictionary or a list in POSCAR
- order. Can instead provide a colourmap or colourmap name.
- Default: tab10.
+ order, with total as the last colour. Can instead provide a
+ colourmap or colourmap name, which don't include a total
+ colour. If not projected, can specify a single total colour.
+ Total colour is overridden by totalcolour. Default: tab10.
+ totalcolour : str, optional
+ colour for the total line. Overrides specifying as part of
+ colour. Default: black.
fill : bool, optional
fill below lines. Default: True.
fillalpha : float, optional
fill alpha scaled to 0-1. Default: 0.2.
line : bool, optional
plot lines. Default: True.
+ linestyle : dict or list or str, optional
+ linestyle or dictionary of linestyles per atom and total, or
+ list in POSCAR order, with total as the last linestyle.
+ Default: -.
+ marker : dict or list or str or tuple, optional
+ marker or dictionary of markers per atom and total, or list
+ in POSCAR order, with total as the last marker.
+ Default: None.
kwargs
keyword arguments passed to matplotlib.pyplot.fill_between.
@@ -273,6 +203,7 @@ Source code for tp.plot.frequency
[ total , main , invert , scale , fill , line ]):
assert isinstance ( value , bool ), ' {} must be True or False.' . format ( name )
assert fill or line , 'fill or line or both must be True.'
+ assert projected or total , 'projected or total or both must be True.'
assert isinstance ( fillalpha , ( float , int )) and fillalpha >= 0 \
and fillalpha <= 1 , \
'fillalpha must be a float/ integer between 0 and 1.'
@@ -280,11 +211,9 @@ Source code for tp.plot.frequency
# data scaling
data = dict ( data )
- f = data [ 'frequency' ]
- del data [ 'frequency' ]
+ f = data . pop ( 'frequency' )
if 'meta' in data : del data [ 'meta' ]
- if not total :
- del data [ 'total' ]
+ if not total : del data [ 'total' ]
if scale :
axscale = [ 0 , 100 ] if main else None
@@ -292,73 +221,152 @@ Source code for tp.plot.frequency
data = tp . plot . utilities . scale_to_axis ( ax , data , scale = axscale ,
axis = axis )
if total :
- totaldata = data [ 'total' ]
- del data [ 'total' ]
+ totaldata = data . pop ( 'total' )
# colours
- # Tries to read the colour as a colourmap name, then colourmap
+ # If projected, tries to read the colour as a colourmap name, then colourmap
# object, then list of colours, then dictionary, and converts it
- # into a dictionary if necessary.
-
- if not isinstance ( colour , dict ):
- if not isinstance ( colour , list ):
- try :
- cmap = plt . cm . get_cmap ( colour )( np . linspace ( 0 , 1 , len ( data )))
- except Exception :
- cmap = colour ( np . linspace ( 0 , 1 , len ( data )))
+ # into a dictionary if necessary. If not projected, colour can be a single
+ # colour for the total. The total colour is found first from totalcolour,
+ # otherwise it can be specified in the dictionary under total or as the
+ # last list item, or defaults to black.
+
+ if not projected :
+ if totalcolour is not None :
+ colour = { 'total' : totalcolour }
+ elif isinstance ( colour , dict ) and 'total' in colour :
+ pass
+ elif isinstance ( colour , list ):
+ if len ( colour ) == 1 :
+ colour = { 'total' : colour [ 0 ]}
+ elif len ( colour ) > len ( data ):
+ colour = { 'total' : colour [ len ( data )]}
else :
- cmap = colour
- colour = {}
+ colour = { 'total' : colour }
+ else :
+ if not isinstance ( colour , dict ):
+ if not isinstance ( colour , list ):
+ try :
+ cmap = plt . cm . get_cmap ( colour )( np . linspace ( 0 , 1 , len ( data )))
+ except ValueError :
+ cmap = colour ( np . linspace ( 0 , 1 , len ( data )))
+ else :
+ cmap = colour
+ colour = {}
+ for i , c in enumerate ( data ):
+ colour [ c ] = cmap [ i ]
+ if len ( cmap ) > len ( data ):
+ colour [ 'total' ] = cmap [ len ( data )]
+
+ if total and 'total' not in colour :
+ if totalcolour is not None :
+ colour [ 'total' ] = totalcolour
+ else :
+ colour [ 'total' ] = '#000000'
+
+ markers = {}
+ if isinstance ( marker , ( str , tuple )) or marker is None :
+ if not projected :
+ markers [ 'total' ] = marker
+ else :
+ marker = [ marker ]
+ if isinstance ( marker , list ):
+ while len ( marker ) < len ( data ):
+ marker . append ( marker [ - 1 ])
for i , c in enumerate ( data ):
- colour [ c ] = cmap [ i ]
-
- if total and 'total' not in colour :
- colour [ 'total' ] = '#000000'
- fillcolour = {}
- for c in colour :
- if isinstance ( colour [ c ], str ):
- colour [ c ] = tp . plot . colour . rgb2array ( colour [ c ])
- if fill :
- fillcolour [ c ] = list ( colour [ c ])
- fillcolour [ c ][ 3 ] = fillalpha
+ markers [ c ] = marker [ i ]
+ if len ( marker ) > len ( data ):
+ markers [ 'total' ] = marker [ len ( data ) + 1 ]
+ elif isinstance ( marker , dict ):
+ markers = marker
+ else :
+ raise Exception ( 'marker must be a dict, list, str, tuple or None' )
+ if total not in markers :
+ markers [ 'total' ] = None
+
+ linestyles = {}
+ if isinstance ( linestyle , str ):
+ if not projected :
+ linestyles [ 'total' ] = linestyle
+ else :
+ linestyle = [ linestyle ]
+ if isinstance ( linestyle , list ):
+ while len ( linestyle ) < len ( data ):
+ linestyle . append ( linestyle [ - 1 ])
+ for i , c in enumerate ( data ):
+ linestyles [ c ] = linestyle [ i ]
+ if len ( linestyle ) > len ( data ):
+ linestyles [ 'total' ] = linestyle [ len ( data ) + 1 ]
+ if isinstance ( linestyle , dict ):
+ linestyles = linestyle
+ if total not in linestyles :
+ linestyles [ 'total' ] = '-'
# plotting
if total :
if invert :
if fill and line :
- ax . fill_between ( totaldata , f , facecolor = fillcolour [ 'total' ], linewidth = 0 )
- ax . plot ( totaldata , f , label = 'Total' , color = colour [ 'total' ], ** kwargs )
+ ax . fill_between ( totaldata , f , facecolor = colour [ 'total' ],
+ linewidth = 0 , alpha = fillalpha )
+ ax . plot ( totaldata , f , label = totallabel , color = colour [ 'total' ],
+ linestyle = linestyles [ 'total' ], marker = markers [ 'total' ],
+ ** kwargs )
elif fill and not line :
- ax . fill_between ( totaldata , f , label = 'Total' , facecolor = fillcolour [ 'total' ],
- linewidth = 0 )
+ ax . fill_between ( totaldata , f , label = totallabel ,
+ facecolor = colour [ 'total' ], linewidth = 0 ,
+ alpha = fillalpha )
else :
- ax . plot ( totaldata , f , label = 'Total' , color = colour [ 'total' ], ** kwargs )
+ ax . plot ( totaldata , f , label = totallabel , color = colour [ 'total' ],
+ linestyle = linestyles [ 'total' ], marker = markers [ 'total' ],
+ ** kwargs )
else :
- if fill :
- ax . fill_between ( f , totaldata , label = 'Total' , facecolor = fillcolour [ 'total' ],
- linewidth = 0 )
- if line :
- ax . plot ( f , totaldata , label = 'Total' , color = colour [ 'total' ], ** kwargs )
-
- for key in data :
- if invert :
if fill and line :
- ax . fill_between ( data [ key ], f , facecolor = fillcolour [ key ], linewidth = 0 )
- ax . plot ( data [ key ], f , label = key , color = colour [ key ], ** kwargs )
+ ax . fill_between ( f , totaldata , facecolor = colour [ 'total' ],
+ linewidth = 0 , alpha = fillalpha )
+ ax . plot ( f , totaldata , label = totallabel , color = colour [ 'total' ],
+ linestyle = linestyles [ 'total' ], marker = markers [ 'total' ],
+ ** kwargs )
elif fill and not line :
- ax . fill_between ( data [ key ], f , label = key , facecolor = fillcolour [ key ], linewidth = 0 )
+ ax . fill_between ( f , totaldata , label = totallabel ,
+ facecolor = colour [ 'total' ], linewidth = 0 ,
+ alpha = fillalpha )
else :
- ax . plot ( data [ key ], f , label = key , color = colour [ key ], ** kwargs )
- else :
- if fill and line :
- ax . fill_between ( f , data [ key ], facecolor = fillcolour [ key ], linewidth = 0 )
- ax . plot ( f , data [ key ], color = colour [ key ], label = key , ** kwargs )
- elif fill and not line :
- ax . fill_between ( f , data [ key ], label = key , facecolor = fillcolour [ key ], linewidth = 0 )
+ ax . plot ( f , totaldata , label = totallabel , color = colour [ 'total' ],
+ linestyle = linestyles [ 'total' ], marker = markers [ 'total' ],
+ ** kwargs )
+ if projected :
+ for key in data :
+ if invert :
+ if fill and line :
+ ax . fill_between ( data [ key ], f , facecolor = colour [ key ],
+ linewidth = 0 , alpha = fillalpha )
+ ax . plot ( data [ key ], f , label = key , color = colour [ key ],
+ linestyle = linestyles [ key ], marker = markers [ key ],
+ ** kwargs )
+ elif fill and not line :
+ ax . fill_between ( data [ key ], f , label = key ,
+ facecolor = colour [ key ], linewidth = 0 ,
+ alpha = fillalpha )
+ else :
+ ax . plot ( data [ key ], f , label = key , color = colour [ key ],
+ linestyle = linestyles [ key ], marker = markers [ key ],
+ ** kwargs )
else :
- ax . plot ( f , data [ key ], label = key , color = colour [ key ], ** kwargs )
-
+ if fill and line :
+ ax . fill_between ( f , data [ key ], facecolor = colour [ key ],
+ linewidth = 0 , alpha = fillalpha )
+ ax . plot ( f , data [ key ], color = colour [ key ], label = key ,
+ linestyle = linestyles [ key ], marker = markers [ key ],
+ ** kwargs )
+ elif fill and not line :
+ ax . fill_between ( f , data [ key ], label = key ,
+ facecolor = colour [ key ], linewidth = 0 ,
+ alpha = fillalpha )
+ else :
+ ax . plot ( f , data [ key ], label = key , color = colour [ key ],
+ linestyle = linestyles [ key ], marker = markers [ key ],
+ ** kwargs )
# axes formatting
@@ -380,43 +388,68 @@ Source code for tp.plot.frequency
-[docs] def add_cum_kappa ( ax , data , temperature = 300 , direction = 'avg' , main = True ,
-
invert = False , scale = False , colour = '#000000' , fill = False ,
-
fillcolour = 0.2 , line = True , ** kwargs ):
+
[docs] def add_cum_kappa ( ax , data , temperature = 300 , direction = 'avg' , label = None ,
+
main = True , invert = False , scale = False , colour = None ,
+
fill = False , fillcolour = 0.2 , line = True , linestyle = '-' ,
+
marker = None , ** kwargs ):
"""Cumulates and plots kappa against frequency.
+
Can plot data from multiple data dictionaries and directions.
+
Colour, linestyle etc. are looped, so if you have two datasets and
+
two directions, but only specify two colours, the first will apply
+
to the first direction in both datasets, whereas if you want one for
+
the first dataset and one for the second, you would repeat the first
+
colour twice and the second twice too.
+
Arguments
---------
ax : axes
axes to plot on.
-
data : dict
-
Phono3py data including mode_kappa and frequency.
+
data : dict or list
+
(list of sets of) Phono3py data including:
temperature : float, optional
temperature in K (finds nearest). Default: 300.
-
direction : str, optional
-
direction from anisotropic data, accepts x-z/ a-c or
-
average/ avg. Default: average
+
+
mode_kappa: array-like
+
frequency and q-point decomposed lattice thermal
+
conductivity.
+
frequency : array-like
+
frequencies.
+
temperature : array-like
+
temperature.
+
+
direction : str or list, optional
+
(list of) direction(s) from anisotropic data, accepts x-z/ a-c or
+
average/ avg. Default: average.
+
label : str, optional
+
(list of) legend label(s). Defaults to $\mathregular{\kappa_l}$
+
if there is only one line plotted, or direction if there are
+
more.
main : bool, optional
set ticks, labels, limits. Default: True.
invert : bool, optional
plot frequency on y axis. Default: False.
scale : bool, optional
-
if main, scale to percent. If not main, scale to axis
-
limits. Default: True.
+
if main, scale to percent, else scale to axis limits.
+
Default: True.
-
colour : str, optional
-
RGB line colour. Default: #000000.
+
colour : str or list, optional
+
(list of) RGB line colour(s). Default: default colour cycle.
fill : bool, optional
fill below lines. Default: False.
-
fillcolour : int or str, optional
+
fillcolour : int or str or list, optional
if a float from 0-1 and colour in #RRGGBB format, sets
fill colour opacity. Otherwise treats it as a colour.
Default: 0.2.
line : bool, optional
plot lines. Default: True.
+
linestyle : str or list, optional
+
(list of) linestyle(s). Default: "-".
+
marker : str or list, optional
+
(list of) markers. Default: None.
kwargs
keyword arguments passed to matplotlib.pyplot.fill_between
@@ -424,9 +457,8 @@
Source code for tp.plot.frequency
Defaults are defined below, which are overridden by those in
``~/.config/tprc.yaml``, both of which are overridden by
arguments passed to this function.
- Defaults:
+ Default:
- label: $\mathregular{\kappa_l}$
rasterized: False
Returns
@@ -438,8 +470,7 @@ Source code for tp.plot.frequency
# defaults
- defkwargs = { 'label' : '$\mathregular{\kappa_l}$' ,
- 'rasterized' : False }
+ defkwargs = { 'rasterized' : False }
if conf is None or 'frequency_cum_kappa_kwargs' not in conf or \
conf [ 'frequency_cum_kappa_kwargs' ] is None :
@@ -456,79 +487,129 @@ Source code for tp.plot.frequency
# data formatting and calculation
- data = tp . resolve . resolve ( data , 'mode_kappa' , temperature = temperature ,
- direction = direction )
- k = np . ravel ( data [ 'mode_kappa' ])
- f = np . ravel ( data [ 'frequency' ])
+ if isinstance ( direction , str ):
+ direction = [ direction ]
+ if isinstance ( data , dict ):
+ data = [ data ]
+ if colour is None :
+ colour = plt . rcParams [ 'axes.prop_cycle' ] . by_key ()[ 'color' ]
+ elif isinstance ( colour , str ):
+ colour = [ colour ]
+ if fillcolour is None :
+ fillcolour = plt . rcParams [ 'axes.prop_cycle' ] . by_key ()[ 'color' ]
+ elif isinstance ( fillcolour , ( str , float , int )):
+ fillcolour = [ fillcolour ]
+ if isinstance ( linestyle , str ):
+ linestyle = [ linestyle ]
+ if marker is None or isinstance ( marker , str ):
+ marker = [ marker ]
+ if label is None :
+ if len ( data ) == 1 and len ( direction ) == 1 :
+ label = [ '$\mathregular{\kappa_l}$' ]
+ else :
+ label = direction
+ elif isinstance ( label , str ):
+ label = [ label ]
- f , k = tp . calculate . cumulate ( f , k )
- np . savetxt ( 'cumkappa-frequency- {:.0f} K- {} .dat' . format (
- data [ 'meta' ][ 'temperature' ], direction ),
- np . transpose ([ f , k ]), header = 'Frequency(THz) k_l(Wm-1K-1)' )
- f = np . append ( f , 100 * f [ - 1 ])
- k = np . append ( k , k [ - 1 ])
+ fmax , kmax = None , None
+ i = 0
- if scale :
- axscale = [ 0 , 100 ] if main else None
- axis = 'x' if invert else 'y'
- k = tp . plot . utilities . scale_to_axis ( ax , k , scale = axscale , axis = axis )
+ for dat in data :
+ for d in direction :
+ data2 = tp . data . resolve . resolve ( dat , 'mode_kappa' ,
+ temperature = temperature , direction = d )
+ k = np . ravel ( data2 [ 'mode_kappa' ])
+ f = np . ravel ( data2 [ 'frequency' ])
- # colour
- # Tries to read the colour as an rgb code, then alpha value.
-
- if fill :
- try :
- fillcolour2 = tp . plot . colour . rgb2array ( colour , fillcolour )
- except Exception :
- if isinstance ( colour , list ) and \
- isinstance ( fillcolour , ( float , int )) and fillcolour >= 0 and \
- fillcolour <= 1 :
- fillcolour2 = list ( colour )
- if len ( colour ) == 3 :
- fillcolour2 . append ( fillcolour )
- elif len ( colour ) == 4 :
- fillcolour2 [ 3 ] = fillcolour
- else :
- fillcolour2 = fillcolour
+ f , k = tp . calculate . cumulate ( f , k )
- # plotting
+ if fmax is None or fmax < f [ - 1 ]:
+ fmax = f [ - 1 ]
+ if kmax is None or kmax < k [ - 1 ]:
+ kmax = 100 if main and scale else k [ - 1 ]
- if fill and line :
- if invert :
- ax . plot ( k , f , color = colour , ** kwargs )
- ax . fill_between ( k , f , facecolor = fillcolour2 , linewidth = 0 )
- else :
- ax . plot ( f , k , color = colour , ** kwargs )
- ax . fill_between ( f , k , facecolor = fillcolour2 )
+ f = np . append ( f , 100 * f [ - 1 ])
+ k = np . append ( k , k [ - 1 ])
+
+ if scale :
+ axscale = [ 0 , 100 ] if main else None
+ axis = 'x' if invert else 'y'
+ k = tp . plot . utilities . scale_to_axis ( ax , k , scale = axscale , axis = axis )
+
+ colour1 = colour [ i % len ( colour )]
+ fillcolour1 = fillcolour [ i % len ( fillcolour )]
+ linestyle1 = linestyle [ i % len ( linestyle )]
+ marker1 = marker [ i % len ( marker )]
+ label1 = "$ {} $" . format ( label [ i % len ( label )])
+
+ # colour
+ # Tries to read the colour as an rgb code, then alpha value.
+
+ if fill :
+ try :
+ fillcolour2 = tp . plot . colour . rgb2array ( colour1 , fillcolour1 )
+ except ValueError :
+ if isinstance ( colour1 , list ) and \
+ isinstance ( fillcolour1 , ( float , int )) and \
+ fillcolour1 >= 0 and fillcolour1 <= 1 :
+ fillcolour2 = colour1
+ if len ( colour1 ) == 3 :
+ fillcolour2 . append ( fillcolour1 )
+ elif len ( colour1 ) == 4 :
+ fillcolour2 [ 3 ] = fillcolour1
+ else :
+ fillcolour2 = fillcolour1
+
+ # plotting
+
+ if fill and line :
+ if invert :
+ ax . plot ( k , f , color = colour1 , linestyle = linestyle1 ,
+ marker = marker1 , label = label1 , ** kwargs )
+ ax . fill_between ( k , f , facecolor = fillcolour2 , linewidth = 0 )
+ else :
+ ax . plot ( f , k , color = colour1 , linestyle = linestyle1 ,
+ marker = marker1 , label = label1 , ** kwargs )
+ ax . fill_between ( f , k , facecolor = fillcolour2 )
+
+ elif fill and not line :
+ if invert :
+ ax . fill_between ( k , f , facecolor = fillcolour2 , ** kwargs )
+ else :
+ ax . fill_between ( f , k , facecolor = fillcolour2 , ** kwargs )
- elif fill and not line :
- if invert :
- ax . fill_between ( k , f , facecolor = fillcolour2 , ** kwargs )
else :
- ax . fill_between ( f , k , facecolor = fillcolour2 , ** kwargs )
+ if invert :
+ ax . plot ( k , f , color = colour1 , linestyle = linestyle1 ,
+ marker = marker1 , label = label1 , ** kwargs )
+ else :
+ ax . plot ( f , k , color = colour1 , linestyle = linestyle1 ,
+ marker = marker1 , label = label1 , ** kwargs )
- else :
- if invert :
- ax . plot ( k , f , color = colour , ** kwargs )
- else :
- ax . plot ( f , k , color = colour , ** kwargs )
+ i += 1
# axes formatting
if main :
if invert :
axlabels = tp . settings . inverted_labels ()
- ax . set_xlabel ( axlabels [ 'cumulative_kappa' ])
+ if scale :
+ ax . set_xlabel ( axlabels [ 'cumulative_percent' ])
+ else :
+ ax . set_xlabel ( axlabels [ 'cumulative_kappa' ])
ax . tick_params ( axis = 'y' , labelleft = False )
- ax . set_xlim ( 0 , k [ - 2 ])
- ax . set_ylim ( 0 , f [ - 2 ])
+ ax . set_xlim ( 0 , kmax )
+ ax . set_ylim ( 0 , fmax )
else :
axlabels = tp . settings . labels ()
- ax . set_ylabel ( axlabels [ 'cumulative_kappa' ])
+ if scale :
+ ax . set_ylabel ( axlabels [ 'cumulative_percent' ])
+ else :
+ ax . set_ylabel ( axlabels [ 'cumulative_kappa' ])
ax . set_xlabel ( axlabels [ 'frequency' ])
- ax . set_ylim ( 0 , k [ - 2 ])
- ax . set_xlim ( 0 , f [ - 2 ])
+ ax . set_ylim ( 0 , kmax )
+ ax . set_xlim ( 0 , fmax )
tp . plot . utilities . set_locators ( ax , x = 'linear' , y = 'linear' )
@@ -552,7 +633,7 @@ Source code for tp.plot.frequency
y-axis quantity. Accepts frequency, gamma, group_velocity,
gv_by_gv, heat_capacity, lifetime, mean_free_path,
mode_kappa, occupation or ph_ph_strength.
-
+
xquantity : str, optional
x-axis quantity. Accepts frequency, gamma, group_velocity,
gv_by_gv, heat_capacity, lifetime, mean_free_path,
@@ -569,10 +650,11 @@ Source code for tp.plot.frequency
invert : bool, optional
invert x- and y-axes. Default: False.
- colour : colourmap or str or array-like, optional
+ colour : colourmap or str or array-like or dict, optional
colourmap or colourmap name or list of colours (one for
- each band or one for each point) or a single colour.
- Default: viridis.
+ each band or one for each point) or two colours for a linear
+ colourmap or a dictionary with cmin and cmax keys or a
+ single colour. Default: viridis.
kwargs
keyword arguments passed to matplotlib.pyplot.scatter.
@@ -633,15 +715,16 @@ Source code for tp.plot.frequency
# colour
# Tries to read as a colourmap name or colourmap object or list of
# colours (of varying formats), one per band, and assigns
- # appropriately. Otherwise leaves as is, which is appropriate for
- # a single colour or colour per point.
+ # appropriately, or just two colours generate a linear colourmap, or
+ # a dictionary with cmin and cmax keys. Otherwise leaves as is,
+ # which is appropriate for a single colour or colour per point.
s = np . shape ( data [ xquantity ])
try :
colour = mpl . cm . get_cmap ( colour )
colours = [ colour ( i ) for i in np . linspace ( 0 , 1 , s [ 1 ])]
colours = np . tile ( colours , ( s [ 0 ], 1 ))
- except Exception :
+ except ValueError :
if isinstance ( colour , mpl . colors . ListedColormap ):
colours = [ colour ( i ) for i in np . linspace ( 0 , 1 , s [ 1 ])]
colours = np . tile ( colours , ( s [ 0 ], 1 ))
@@ -649,12 +732,20 @@ Source code for tp.plot.frequency
colour = tp . plot . colour . skelton ()
colours = [ colour ( i ) for i in np . linspace ( 0 , 1 , s [ 1 ])]
colours = np . tile ( colours , ( s [ 0 ], 1 ))
- elif ( isinstance ( colour , list ) or isinstance ( colour , np . ndarray ) and
- len ( colour ) == s [ 1 ]):
- if np . ndim ( colour ) == 1 :
- colours = np . tile ( colour , s [ 0 ])
- elif np . ndim ( colour ) == 2 :
- colours = np . tile ( colour , ( s [ 0 ], 1 ))
+ elif isinstance ( colour , list ) or isinstance ( colour , np . ndarray ):
+ if len ( colour ) == s [ 1 ]:
+ if np . ndim ( colour ) == 1 :
+ colours = np . tile ( colour , s [ 0 ])
+ elif np . ndim ( colour ) == 2 :
+ colours = np . tile ( colour , ( s [ 0 ], 1 ))
+ elif len ( colour ) == 2 :
+ colour = tp . plot . colour . linear ( cmin = colour [ 0 ], cmax = colour [ 1 ])
+ colours = [ colour ( i ) for i in np . linspace ( 0 , 1 , s [ 1 ])]
+ colours = np . tile ( colours , ( s [ 0 ], 1 ))
+ elif isinstance ( colour , dict ):
+ colour = tp . plot . colour . linear ( ** colour )
+ colours = [ colour ( i ) for i in np . linspace ( 0 , 1 , s [ 1 ])]
+ colours = np . tile ( colours , ( s [ 0 ], 1 ))
else :
colours = colour
@@ -718,8 +809,10 @@ Source code for tp.plot.frequency
invert : bool, optional
invert x- and y-axes. Default: False.
- colour : colormap or str, optional
- colourmap or colourmap name. Default: viridis.
+ colour : colourmap or str or array-like or dict, optional
+ colourmap or colourmap name or #rrggbb highlight colour or
+ highlight, min, max colours in that order, or dictionary
+ with cmid and cmin and/or cmax keys. Default: viridis.
cmin : float, optional
colour scale minimum. Default: display 99 % data.
cmax : float, optional
@@ -793,20 +886,7 @@ Source code for tp.plot.frequency
y = np . abs ( np . ravel ( data [ quantity ]))
c = np . abs ( np . ravel ( data [ projected ]))
- # colour
- # Reads a colourmap or colourmap name.
-
- try :
- cmap = copy ( mpl . cm . get_cmap ( colour ))
- except Exception :
- if isinstance ( colour , mpl . colors . ListedColormap ):
- cmap = copy ( colour )
- elif isinstance ( colour , str ) and colour == 'skelton' :
- cmap = tp . plot . colour . skelton ()
- else :
- raise Exception ( 'Unrecognised colour argument. '
- 'Expected a colourmap or colourmap name.' )
-
+ cmap = tp . plot . utilities . parse_colours ( colour )
cnorm , extend = tp . plot . utilities . colour_scale ( c , projected , cmap , cmin ,
cmax , cscale , unoccupied )
@@ -870,10 +950,10 @@ Source code for tp.plot.frequency
invert : bool, optional
invert x- and y-axes. Default: False.
- colour : colourmap or str or array-like, optional
- colourmap or colourmap name. A single #rrggbb colour can be
- given to generate a custom uniform colourmap.
- Default: Blues.
+ colour : colourmap or str or array-like or dict, optional
+ colourmap or colourmap name or #rrggbb highlight colour or
+ highlight, min, max colours in that order, or dictionary
+ with cmid and cmin and/or cmax keys. Default: Blues.
kwargs
keyword arguments passed to matplotlib.pyplot.scatter.
@@ -927,25 +1007,11 @@ Source code for tp.plot.frequency
idx = z . argsort ()
x_dens , y_dens , z_dens = x [ idx ], y [ idx ], z [ idx ]
- # colour
- # Tries to read as a colourmap or colourmap name, or uses a single
- # #rrggbb colour as the highlight colour for a tp.plot.colour.uniform.
-
- try :
- colours = mpl . cm . get_cmap ( colour )
- except Exception :
- if isinstance ( colour , mpl . colors . ListedColormap ):
- colours = colour
- else :
- try :
- colours = tp . plot . colour . uniform ( colour )
- except Exception :
- raise Exception ( 'colour must be a colourmap, colourmap'
- 'name or single #rrggbb colour.' )
+ cmap = tp . plot . utilities . parse_colours ( colour )
# plotting
- ax . scatter ( x_dens , y_dens , c = z_dens , cmap = colour , ** kwargs )
+ ax . scatter ( x_dens , y_dens , c = z_dens , cmap = cmap , ** kwargs )
# axes formatting
@@ -1023,46 +1089,30 @@ Source code for tp.plot.frequency
-
-
-
-
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/docs/_modules/tp/plot/heatmap.html b/docs/_modules/tp/plot/heatmap.html
index d7ff706..9615f06 100644
--- a/docs/_modules/tp/plot/heatmap.html
+++ b/docs/_modules/tp/plot/heatmap.html
@@ -1,72 +1,30 @@
-
-
-
-
- tp.plot.heatmap — ThermoPlotter 1.0.0 documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ tp.plot.heatmap — ThermoPlotter 1.0.0 documentation
+
-
-
-
+
-
-
-
-
+
-
-
-
+
-
-
-
-
-
-
+
ThermoPlotter
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
Source code for tp.plot.heatmap
"""Heatmap plotters.
@@ -180,11 +87,14 @@ Source code for tp.plot.heatmap
kappa_l needed to reach a given ZT.
"""
+from copy import copy
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
+import os
import tp
import warnings
+import yaml
from scipy.interpolate import interp1d , interp2d
warnings . filterwarnings ( 'ignore' , module = 'matplotlib' )
@@ -193,13 +103,16 @@ Source code for tp.plot.heatmap
filename = ' {} /.config/tprc.yaml' . format ( os . path . expanduser ( "~" ))
with open ( filename , 'r' ) as f :
conf = yaml . safe_load ( f )
-except Exception :
+except yaml . parser . ParserError :
+ warnings . warn ( 'Failed to read ~/.config/tprc.yaml' )
+ conf = None
+except FileNotFoundError :
conf = None
[docs] def add_heatmap ( ax , x , y , c , xinterp = None , yinterp = None , kind = 'linear' ,
xscale = 'linear' , yscale = 'linear' , cscale = 'linear' , xmin = None ,
xmax = None , ymin = None , ymax = None , cmin = None , cmax = None ,
-
colour = 'viridis' , ** kwargs ):
+
colour = 'viridis' , undercolour = None , overcolour = None , ** kwargs ):
"""Adds a heatmap to a set of axes.
Formats limits, parses extra colourmap options, makes sure data
@@ -243,9 +156,14 @@
Source code for tp.plot.heatmap
cmax : float, optional
override colour scale maximum. Default: None.
- colour : colourmap or str or array-like, optional
- colourmap or colourmap name; or key RGB colour to generate a
- uniform colour map. Default: viridis.
+ colour : colourmap or str or array-like or dict, optional
+ colourmap or colourmap name or highlight colour or
+ highlight, min, max colours in that order, or dictionary
+ with mid and min and/or max keys. Default: Blues.
+ undercolour : str or array-like, optional
+ colour for values under cmin. Default: None.
+ overcolour : str or array-like, optional
+ colour for values over cmax. Default: None.
kwargs
keyword arguments passed to matplotlib.pyplot.pcolormesh.
@@ -254,7 +172,7 @@ Source code for tp.plot.heatmap
arguments passed to this function.
Defaults:
- rasterized: False
+ rasterized: True
Returns
-------
@@ -265,7 +183,7 @@ Source code for tp.plot.heatmap
# defaults
- defkwargs = { 'rasterized' : False }
+ defkwargs = { 'rasterized' : True }
if conf is None or 'heatmap_kwargs' not in conf or \
conf [ 'heatmap_kwargs' ] is None :
@@ -278,14 +196,14 @@ Source code for tp.plot.heatmap
x = np . array ( x )
y = np . array ( y )
c = np . array ( c )
- if xmin is None : xmin = x [ 0 ]
- if xmax is None : xmax = x [ - 1 ]
- if ymin is None : ymin = y [ 0 ]
- if ymax is None : ymax = y [ - 1 ]
+ if xmin is None : xmin = np . nanmin ( x )
+ if xmax is None : xmax = np . nanmax ( x )
+ if ymin is None : ymin = np . nanmin ( y )
+ if ymax is None : ymax = np . nanmax ( y )
xi = np . where (( x >= xmin ) & ( x <= xmax ))[ 0 ]
yi = np . where (( y >= ymin ) & ( y <= ymax ))[ 0 ]
- x = x [ xi ]
y = y [ yi ]
+ x = x [ xi ]
try :
c = c [ np . ix_ ( xi , yi )]
@@ -297,12 +215,12 @@ Source code for tp.plot.heatmap
extend = 'neither'
if cmin is None :
- cmin = np . amin ( c )
- elif cmin > np . amin ( c ):
+ cmin = np . nanmin ( c )
+ elif cmin > np . nanmin ( c ):
extend = 'min'
if cmax is None :
- cmax = np . amax ( c )
- elif cmax < np . amax ( c ):
+ cmax = np . nanmax ( c )
+ elif cmax < np . nanmax ( c ):
if extend == 'min' :
extend = 'both'
else :
@@ -317,16 +235,26 @@ Source code for tp.plot.heatmap
# #rrggbb colour as the highlight colour for a tp.plot.colour.uniform.
try :
- colours = mpl . cm . get_cmap ( colour )
- except Exception :
+ colours = copy ( mpl . cm . get_cmap ( colour ))
+ except ValueError :
if isinstance ( colour , mpl . colors . ListedColormap ):
colours = colour
+ elif isinstance ( colour , str ):
+ colours = tp . plot . colour . uniform ( colour )
+ elif isinstance ( colour , list ):
+ colours = tp . plot . colour . uniform ( * colour )
+ elif isinstance ( colour , dict ):
+ colours = tp . plot . colour . uniform ( ** colour )
else :
- try :
- colours = tp . plot . colour . uniform ( colour )
- except Exception :
- raise Exception ( 'colour must be a colourmap, colourmap'
- 'name or single #rrggbb colour.' )
+ raise Exception ( 'colour must be a colourmap, colourmap '
+ 'name, single #rrggbb highlight colour or '
+ 'highlight, min, max #rrggbb colours in '
+ 'that order, or a dictionary with mid and '
+ 'min and/or max keys.' )
+ if undercolour is not None :
+ colours . set_under ( undercolour )
+ if overcolour is not None :
+ colours . set_over ( overcolour )
# data interpolation
@@ -338,7 +266,11 @@ Source code for tp.plot.heatmap
if yinterp is not None :
if yscale == 'linear' : y = np . linspace ( y [ 0 ], y [ - 1 ], yinterp )
if yscale == 'log' : y = np . geomspace ( y [ 0 ], y [ - 1 ], yinterp )
+ x = np . array ( x )
+ y = np . array ( y )
c = cinterp ( x , y )
+ else :
+ c = np . transpose ( c )
# ensure all data is shown
if len ( x ) == len ( c [ 0 ]):
@@ -355,7 +287,6 @@ Source code for tp.plot.heatmap
y . append ( y [ - 1 ] ** 2 / y [ - 2 ])
# plotting
-
heat = ax . pcolormesh ( x , y , c , cmap = colours , norm = cnorm , ** kwargs )
cbar = plt . colorbar ( heat , extend = extend )
@@ -370,11 +301,10 @@ Source code for tp.plot.heatmap
[docs] def add_ztmap ( ax , data , kdata = None , direction = 'avg' , xinterp = 200 ,
yinterp = 200 , kind = 'linear' , xmin = None , xmax = None , ymin = None ,
-
ymax = None , cmin = None , cmax = None , colour = 'viridis' ,
-
output = 'zt.hdf5' , ** kwargs ):
+
ymax = None , cmin = None , cmax = None , colour = 'viridis' , ** kwargs ):
"""Convenience wrapper for plotting ZT heatmaps.
-
Calculates ZT and writes to hdf5, plots and formats labels etc.
+
Calculates ZT, plots and formats labels etc.
Arguments
---------
@@ -390,8 +320,8 @@
Source code for tp.plot.heatmap
temperature. Ignored if zt in data, if not ignored and None,
defaults to 1 at all temperatures.
direction : str, optional
- direction from anisotropic data, accepts x-z/ a-c or
- average/ avg. Default: average.
+ crystal direction, accepts x-z/ a-c or average/ avg.
+ Default: average.
xinterp : int, optional
density of interpolation. None turns it off. Default: 200.
@@ -416,12 +346,6 @@ Source code for tp.plot.heatmap
colourmap or colourmap name; or key colour or min and max
RGB colours to generate a colour map. Default: viridis.
- output : str, optional
- output filename to write to. Only writes if ZT has been
- within this function. Set to None to not write. Can be
- loaded with h5py.File to put back into this function.
- Default: zt.hdf5.
-
kwargs
keyword arguments passed to matplotlib.pyplot.pcolormesh.
Defaults are defined below, which are overridden by those in
@@ -429,7 +353,7 @@ Source code for tp.plot.heatmap
arguments passed to this function.
Defaults:
- rasterized: False
+ rasterized: True
Returns
-------
@@ -437,12 +361,10 @@ Source code for tp.plot.heatmap
colourbar
colourbar.
"""
-
- import h5py
-
+
# defaults
- defkwargs = { 'rasterized' : False }
+ defkwargs = { 'rasterized' : True }
if conf is None or 'ztmap_kwargs' not in conf or \
conf [ 'ztmap_kwargs' ] is None :
@@ -450,61 +372,38 @@ Source code for tp.plot.heatmap
else :
kwargs = { ** defkwargs , ** conf [ 'ztmap_kwargs' ], ** kwargs }
+ ltc = 'lattice_thermal_conductivity'
+ equants = [ 'conductivity' , 'seebeck' , 'electronic_thermal_conductivity' ]
+
# data formatting
if 'zt' in data :
- if np . ndim ( data [ 'zt' ]) == 4 :
- data = tp . data . resolve ( data , 'zt' , direction )
- else :
- data = dict ( data )
+ data = tp . data . resolve . resolve ( data , 'zt' , direction )
else :
- if np . ndim ( data [ 'conductivity' ]) == 4 :
- data = tp . data . resolve . resolve ( data , [ 'conductivity' , 'seebeck' ,
- 'electronic_thermal_conductivity' ],
- direction = direction )
- else :
- data = dict ( data )
+ data = tp . data . resolve . resolve ( data , equants , direction = direction )
if 'meta' not in data :
data [ 'meta' ] = {}
if kdata is not None :
- kdata = tp . data . resolve . resolve ( kdata ,
- 'lattice_thermal_conductivity' ,
- direction = direction )
-
- # scale to smallest data set (don't extrapolate)
- # interpolation takes care of it if data is smaller than kdata
- tindex = np . where (( data [ 'temperature' ] <= kdata [ 'temperature' ][ - 1 ])
- & ( data [ 'temperature' ] >= kdata [ 'temperature' ][ 0 ]))
- data [ 'temperature' ] = np . array ( data [ 'temperature' ])[ tindex [ 0 ]]
- data [ 'conductivity' ] = np . array ( data [ 'conductivity' ])[ tindex [ 0 ]]
- data [ 'electronic_thermal_conductivity' ] = \
- np . array ( data [ 'electronic_thermal_conductivity' ])[ tindex [ 0 ]]
- data [ 'seebeck' ] = np . array ( data [ 'seebeck' ])[ tindex [ 0 ]]
-
- kinterp = interp1d ( kdata [ 'temperature' ],
- kdata [ 'lattice_thermal_conductivity' ],
- kind = 'cubic' )
- data [ 'lattice_thermal_conductivity' ] = kinterp ( data [ 'temperature' ])
- data [ 'meta' ][ 'kappa_source' ] = kdata [ 'meta' ][ 'kappa_source' ]
+ kdata = tp . data . resolve . resolve ( kdata , ltc , direction = direction )
+ data , kdata = tp . calculate . interpolate ( data , kdata , 'temperature' ,
+ equants , ltc , kind = 'cubic' )
+ data [ ltc ] = kdata [ ltc ]
+
else : # if no kappa_lat, set to 1
- data [ 'lattice_thermal_conductivity' ] = np . ones (
- len ( data [ 'temperature' ]))
+ data [ ltc ] = np . ones ( len ( data [ 'temperature' ]))
data [ 'meta' ][ 'kappa_source' ] = 'Set to 1 W m^-1 K^-1'
- data = tp . calculate . zt_fromdict ( data )
-
- if output is not None :
- tp . data . save . hdf5 ( data , output )
+ data = tp . calculate . zt_fromdict ( data , use_tprc = True )
# plotting
cbar = add_heatmap ( ax , data [ 'temperature' ], list ( np . abs ( data [ 'doping' ])),
- data [ 'zt' ], xinterp = xinterp ,
- yinterp = yinterp , kind = kind , yscale = 'log' , xmin = xmin ,
- xmax = xmax , ymin = ymin , ymax = ymax , cmin = cmin , cmax = cmax ,
- colour = colour , ** kwargs )
+ data [ 'zt' ], xinterp = xinterp , yinterp = yinterp , kind = kind ,
+ yscale = 'log' , xmin = xmin , xmax = xmax , ymin = ymin ,
+ ymax = ymax , cmin = cmin , cmax = cmax , colour = colour ,
+ ** kwargs )
# axes formatting
@@ -518,7 +417,7 @@ Source code for tp.plot.heatmap
[docs] def add_kappa_target ( ax , data , zt = 2 , direction = 'avg' , xinterp = 200 ,
yinterp = 200 , kind = 'linear' , xmin = None , xmax = None ,
ymin = None , ymax = None , cmin = 0 , cmax = None , colour = 'viridis' ,
-
output = 'target-kl.hdf5' , ** kwargs ):
+
negativecolour = 'grey' , ** kwargs ):
"""Plots a heatmap of k_latt required for a target ZT
Calculates lattice thermal conductivity, plots and formats labels
@@ -536,8 +435,8 @@
Source code for tp.plot.heatmap
zt : float, optional
target ZT. Default: 2.
direction : str, optional
- direction from anisotropic data, accepts x-z/ a-c or
- average/ avg. Default: average.
+ crystal direction, accepts x-z/ a-c or average/ avg.
+ Default: average.
xinterp : int, optional
density of interpolation. None turns it off. Default: 200.
@@ -561,10 +460,8 @@ Source code for tp.plot.heatmap
colour : colourmap or str or array-like, optional
colourmap or colourmap name; or key colour or min and max
RGB colours to generate a colour map. Default: viridis.
-
- output : str, optional
- output filename to write to. Set to None to not write.
- Default: target-kl.hdf5.
+ negativecolour : str or array-like, optional
+ colour for values under cmin. Default: grey.
kwargs
keyword arguments passed to matplotlib.pyplot.pcolormesh.
@@ -573,7 +470,7 @@ Source code for tp.plot.heatmap
arguments passed to this function.
Defaults:
- rasterized: False
+ rasterized: True
Returns
-------
@@ -584,7 +481,7 @@ Source code for tp.plot.heatmap
# defaults
- defkwargs = { 'rasterized' : False }
+ defkwargs = { 'rasterized' : True }
if conf is None or 'kappa_target_kwargs' not in conf or \
conf [ 'kappa_target_kwargs' ] is None :
@@ -592,77 +489,58 @@ Source code for tp.plot.heatmap
else :
kwargs = { ** defkwargs , ** conf [ 'kappa_target_kwargs' ], ** kwargs }
+ ltc = 'lattice_thermal_conductivity'
+ equants = [ 'conductivity' , 'seebeck' , 'electronic_thermal_conductivity' ]
# data formatting
- data = tp . data . resolve . resolve ( data , [ 'conductivity' , 'seebeck' ,
- 'electronic_thermal_conductivity' ],
- direction = direction )
+ data = tp . data . resolve . resolve ( data , equants , direction = direction )
data [ 'zt' ] = zt
- data = tp . calculate . kl_fromdict ( data )
-
- if output is not None :
- tp . data . save . hdf5 ( data , output )
+ data = tp . calculate . kl_fromdict ( data , use_tprc = False )
# plotting
cbar = add_heatmap ( ax , data [ 'temperature' ], list ( np . abs ( data [ 'doping' ])),
- data [ 'lattice_thermal_conductivity' ],
- xinterp = xinterp , yinterp = yinterp , kind = kind ,
+ data [ ltc ], xinterp = xinterp , yinterp = yinterp , kind = kind ,
yscale = 'log' , xmin = xmin , xmax = xmax , ymin = ymin ,
- ymax = ymax , cmin = cmin , cmax = cmax , colour = colour , ** kwargs )
+ ymax = ymax , cmin = cmin , cmax = cmax , colour = colour ,
+ undercolour = negativecolour , ** kwargs )
# axes formatting
labels = tp . settings . labels ()
ax . set_xlabel ( labels [ 'temperature' ])
ax . set_ylabel ( labels [ 'doping' ])
- cbar . set_label ( labels [ 'lattice_thermal_conductivity' ])
+ cbar . set_label ( labels [ ltc ])
return cbar
-
-
-
-
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/docs/_modules/tp/plot/mfp.html b/docs/_modules/tp/plot/mfp.html
index 2492053..54956ae 100644
--- a/docs/_modules/tp/plot/mfp.html
+++ b/docs/_modules/tp/plot/mfp.html
@@ -1,72 +1,30 @@
-
-
-
-
- tp.plot.mfp — ThermoPlotter 1.0.0 documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ tp.plot.mfp — ThermoPlotter 1.0.0 documentation
+
-
-
-
+
-
-
-
-
+
-
-
-
+
-
-
-
-
-
-
+
ThermoPlotter
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
Source code for tp.plot.mfp
"""Function for plotting mean free path on the x-axis.
@@ -178,8 +85,10 @@ Source code for tp.plot.mfp
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
+import os
import tp.settings
import warnings
+import yaml
from tp.data import resolve
warnings . filterwarnings ( 'ignore' , module = 'matplotlib' )
@@ -188,23 +97,33 @@ Source code for tp.plot.mfp
filename = ' {} /.config/tprc.yaml' . format ( os . path . expanduser ( "~" ))
with open ( filename , 'r' ) as f :
conf = yaml . safe_load ( f )
-except Exception :
+except yaml . parser . ParserError :
+ warnings . warn ( 'Failed to read ~/.config/tprc.yaml' )
+ conf = None
+except FileNotFoundError :
conf = None
[docs] def add_cum_kappa ( ax , data , kmin = 1 , temperature = 300 , direction = 'avg' ,
-
xmarkers = None , ymarkers = None , add_xticks = False ,
-
add_yticks = False , main = True , scale = False , colour = '#000000' ,
-
fill = False , fillcolour = 0.2 , line = True , markerkwargs = {},
-
** kwargs ):
+
label = None , xmarkers = None , ymarkers = None , add_xticks = False ,
+
add_yticks = False , main = True , scale = False , colour = None ,
+
fill = False , fillcolour = 0.2 , line = True , linestyle = '-' ,
+
marker = None , markerkwargs = {}, ** kwargs ):
"""Cumulates and plots kappa against mean free path.
+
Can plot data from multiple data dictionaries and directions.
+
Colour, linestyle etc. are looped, so if you have two datasets and
+
two directions, but only specify two colours, the first will apply
+
to the first direction in both datasets, whereas if you want one for
+
the first dataset and one for the second, you would repeat the first
+
colour twice and the second twice too.
+
Arguments
---------
ax : axes
axes to plot on.
data : dict
-
Phono3py-like data including:
+
(list of sets of) Phono3py data including:
mode_kappa: array-like
frequency and q-point decomposed lattice thermal
@@ -220,8 +139,12 @@
Source code for tp.plot.mfp
temperature : float, optional
temperature in K (finds nearest). Default: 300.
direction : str, optional
- direction from anisotropic data, accepts x-z/ a-c or
- average/ avg. Default: average
+ (list of) direction(s) from anisotropic data, accepts x-z/ a-c or
+ average/ avg. Default: average.
+ label : str, optional
+ (list of) legend label(s). Defaults to $\mathregular{\kappa_l}$
+ if there is only one line plotted, or direction if there are
+ more.
xmarkers : array-like, optional
mark kappa at certain mean free paths.
@@ -240,16 +163,20 @@ Source code for tp.plot.mfp
if main, scale to percent. If not main, scale to axis
limits. Default: False.
- colour : str, optional
- #RRGGBB line colour. Default: #000000.
+ colour : str or list, optional
+ (list of) RGB line colour(s). Default: default colour cycle.
fill : bool, optional
fill below lines. Default: False.
- fillcolour : int or str, optional
+ fillcolour : int or str or list, optional
if a float from 0-1 and colour in #RRGGBB format, sets
fill colour opacity. Otherwise treats it as a colour.
Default: 0.2.
line : bool, optional
plot lines. Default: True.
+ linestyle : str or list, optional
+ (list of) linestyle(s). Default: "-".
+ marker : str or list, optional
+ (list of) markers. Default: None.
markerkwargs : dict, optional
keyword arguments for the markers, passed to
@@ -268,9 +195,8 @@ Source code for tp.plot.mfp
Defaults are defined below, which are overridden by those in
``~/.config/tprc.yaml``, both of which are overridden by
arguments passed to this function.
- Defaults:
+ Default:
- label: $\mathregular{\kappa_l}$
rasterized: False
Returns
@@ -284,8 +210,7 @@ Source code for tp.plot.mfp
# defaults
- defkwargs = { 'label' : '$\mathregular{\kappa_l}$' ,
- 'rasterized' : False }
+ defkwargs = { 'rasterized' : False }
if conf is None or 'mfp_cum_kappa_kwargs' not in conf or \
conf [ 'mfp_cum_kappa_kwargs' ] is None :
@@ -304,73 +229,130 @@ Source code for tp.plot.mfp
# data formatting and calculation
- data = resolve . resolve ( data , [ 'mode_kappa' , 'mean_free_path' ],
- temperature = temperature , direction = direction )
- k = np . ravel ( data [ 'mode_kappa' ])
- mfp = np . abs ( np . ravel ( data [ 'mean_free_path' ]))
-
- mfp , k = cumulate ( mfp , k )
- np . savetxt ( 'cumkappa-mfp- {:.0f} K- {} .dat' . format (
- data [ 'meta' ][ 'temperature' ], direction ),
- np . transpose ([ mfp , k ]), header = 'mfp(m) k_l(Wm-1K-1)' )
- mfp = np . append ( mfp , 100 * mfp [ - 1 ])
- k = np . append ( k , k [ - 1 ])
-
- # percentage output
-
- if scale :
- axscale = [ 0 , 100 ] if main else None
- k , _ = tp . plot . utilities . scale_to_axis ( ax , k , scale = axscale )
-
- # colour
- # Tries to read the colour as an rgb code, then alpha value.
-
- if fill :
- try :
- fillcolour2 = tp . plot . colour . rgb2array ( colour , fillcolour )
- except Exception :
- if isinstance ( colour , list ) and \
- isinstance ( fillcolour , ( float , int )) and fillcolour >= 0 and \
- fillcolour <= 1 :
- fillcolour2 = list ( colour )
- if len ( colour ) == 3 :
- fillcolour2 . append ( fillcolour )
- elif len ( colour ) == 4 :
- fillcolour2 [ 3 ] = fillcolour
+ if isinstance ( direction , str ):
+ direction = [ direction ]
+ if isinstance ( data , dict ):
+ data = [ data ]
+ if colour is None :
+ colour = plt . rcParams [ 'axes.prop_cycle' ] . by_key ()[ 'color' ]
+ elif isinstance ( colour , str ):
+ colour = [ colour ]
+ if fillcolour is None :
+ fillcolour = plt . rcParams [ 'axes.prop_cycle' ] . by_key ()[ 'color' ]
+ elif isinstance ( fillcolour , ( str , float , int )):
+ fillcolour = [ fillcolour ]
+ if isinstance ( linestyle , str ):
+ linestyle = [ linestyle ]
+ if marker is None or isinstance ( marker , str ):
+ marker = [ marker ]
+ if label is None :
+ if len ( data ) == 1 and len ( direction ) == 1 :
+ label = [ '$\mathregular{\kappa_l}$' ]
+ else :
+ label = direction
+ elif isinstance ( label , str ):
+ label = [ label ]
+
+ mfpmin , mfpmax , kmax = None , None , None
+ xticks , yticks = [], []
+ i = 0
+
+ for dat in data :
+ for d in direction :
+ data2 = resolve . resolve ( dat , [ 'mode_kappa' , 'mean_free_path' ],
+ temperature = temperature , direction = d )
+ k = np . ravel ( data2 [ 'mode_kappa' ])
+ mfp = np . abs ( np . ravel ( data2 [ 'mean_free_path' ]))
+
+ mfp , k = cumulate ( mfp , k )
+
+ mindex = next ( x [ 0 ] for x in enumerate ( np . ma . masked_invalid ( k ) . compressed ()) if x [ 1 ] > kmin * k [ - 1 ] / 100 )
+ if mfpmin is None or mfpmin > mfp [ mindex ]:
+ mfpmin = mfp [ mindex ]
+ if mfpmax is None or mfpmax < mfp [ - 1 ]:
+ mfpmax = np . nanmax ( mfp )
+ if kmax is None or kmax < k [ - 1 ]:
+ kmax = 100 if main and scale else np . nanmax ( k [ - 1 ])
+
+ mfp = np . append ( mfp , 100 * mfp [ - 1 ])
+ k = np . append ( k , k [ - 1 ])
+
+ # percentage output
+
+ if scale :
+ axscale = [ 0 , 100 ] if main else None
+ k = tp . plot . utilities . scale_to_axis ( ax , k , scale = axscale )
+
+ colour1 = colour [ i % len ( colour )]
+ fillcolour1 = fillcolour [ i % len ( fillcolour )]
+ linestyle1 = linestyle [ i % len ( linestyle )]
+ marker1 = marker [ i % len ( marker )]
+ if label is not None :
+ label1 = "$ {} $" . format ( label [ i % len ( label )])
else :
- fillcolour2 = colour
-
- # plotting
+ label1 = None
+
+ # colour
+ # Tries to read the colour as an rgb code, then alpha value.
+
+ if fill :
+ try :
+ fillcolour2 = tp . plot . colour . rgb2array ( colour1 , fillcolour1 )
+ except ValueError :
+ if isinstance ( colour1 , list ) and \
+ isinstance ( fillcolour1 , ( float , int )) and \
+ fillcolour1 >= 0 and fillcolour1 <= 1 :
+ fillcolour2 = colour1
+ if len ( colour1 ) == 3 :
+ fillcolour2 . append ( fillcolour1 )
+ elif len ( colour1 ) == 4 :
+ fillcolour2 [ 3 ] = fillcolour1
+ else :
+ fillcolour2 = fillcolour1
+
+ # plotting
+
+ if fill and line :
+ ax . plot ( mfp , k , color = colour1 , linestyle = linestyle1 ,
+ marker = marker1 , label = label1 , ** kwargs )
+ ax . fill_between ( mfp , k , facecolor = fillcolour2 , edgecolor = colour )
+
+ elif fill and not line :
+ ax . fill_between ( mfp , k , facecolor = fillcolour2 , ** kwargs )
- if fill and line :
- ax . plot ( mfp , k , color = colour , ** kwargs )
- ax . fill_between ( mfp , k , facecolor = fillcolour2 , edgecolor = colour )
+ else :
+ ax . plot ( mfp , k , color = colour1 , linestyle = linestyle1 ,
+ marker = marker1 , label = label1 , ** kwargs )
- elif fill and not line :
- ax . fill_between ( mfp , k , facecolor = fillcolour2 , ** kwargs )
+ if xmarkers is not None or ymarkers is not None :
+ xtick , ytick = add_markers ( ax , mfp , k , xmarkers , ymarkers ,
+ ** markerkwargs )
+ xticks . append ( xtick )
+ yticks . append ( ytick )
- else :
- ax . plot ( mfp , k , color = colour , ** kwargs )
+ i += 1
# axes formatting
if main :
- mindex = next ( x [ 0 ] for x in enumerate ( k ) if x [ 1 ] > kmin * k [ - 2 ] / 100 )
axlabels = tp . settings . labels ()
- ax . set_ylabel ( axlabels [ 'cumulative_kappa' ])
+ if scale :
+ ax . set_ylabel ( axlabels [ 'cumulative_percent' ])
+ else :
+ ax . set_ylabel ( axlabels [ 'cumulative_kappa' ])
ax . set_xlabel ( axlabels [ 'mean_free_path' ])
- ax . set_ylim ( 0 , k [ - 2 ])
- ax . set_xlim ( mfp [ mindex ], mfp [ - 2 ])
+ ax . set_ylim ( 0 , kmax )
+ ax . set_xlim ( mfpmin , mfpmax )
tp . plot . utilities . set_locators ( ax , x = 'log' , y = 'linear' )
- if xmarkers is not None or ymarkers is not None :
- add_markers ( ax , mfp , k , xmarkers , ymarkers , add_xticks , add_yticks ,
- ** markerkwargs )
+ if add_xticks :
+ ax . set_xticks ( np . append ( ax . get_xticks (), xticks ))
+ if add_yticks :
+ ax . set_yticks ( np . append ( ax . get_yticks (), yticks ))
return
-[docs] def add_markers ( ax , x , y , xmarkers = None , ymarkers = None , add_xticks = False ,
-
add_yticks = False , ** kwargs ):
+
[docs] def add_markers ( ax , x , y , xmarkers = None , ymarkers = None , ** kwargs ):
"""Adds marker lines linking a linear plot to the axes.
Arguments
@@ -387,12 +369,6 @@
Source code for tp.plot.mfp
where on the x axis to mark.
ymarkers : array-like, int or float, optional
where on the y axis to mark.
- add_xticks : bool, optional
- add x_ticks for each marker. Doesn't work on log axes.
- Default: False.
- add_yticks : bool, optional
- add y_ticks for each marker. Doesn't work on log axes.
- Default: False.
kwargs
keyword arguments passed to matplotlib.pyplot.plot.
@@ -408,8 +384,10 @@ Source code for tp.plot.mfp
Returns
-------
- None
- adds plot directly to ax.
+ list
+ added x locations.
+ list
+ added y locations.
"""
from scipy.interpolate import interp1d
@@ -426,12 +404,7 @@ Source code for tp.plot.mfp
else :
kwargs = { ** defkwargs , ** conf [ 'marker_kwargs' ], ** kwargs }
- # get limits
-
- xlim = ax . get_xlim ()
- ylim = ax . get_ylim ()
- xticks = ax . get_xticks ()
- yticks = ax . get_yticks ()
+ xticks , yticks = [], []
# plot x
@@ -442,8 +415,8 @@ Source code for tp.plot.mfp
for m in range ( len ( xmarkers )):
ax . plot ([ xmarkers [ m ], xmarkers [ m ], 0 ],
[ 0 , xmarky [ m ], xmarky [ m ]], ** kwargs )
- xticks = np . append ( xticks , xmarkers )
- yticks = np . append ( yticks , xmarky )
+ xticks . append ( xmarkers )
+ yticks . append ( xmarky )
# plot y
@@ -454,58 +427,37 @@ Source code for tp.plot.mfp
for m in range ( len ( ymarkers )):
ax . plot ([ ymarkx [ m ], ymarkx [ m ], 0 ],
[ 0 , ymarkers [ m ], ymarkers [ m ]], ** kwargs )
- yticks = np . append ( yticks , ymarkers )
- xticks = np . append ( xticks , ymarkx )
+ yticks . append ( ymarkers )
+ xticks . append ( ymarkx )
- if add_xticks :
- ax . set_xticks ( xticks )
- if add_yticks :
- ax . set_yticks ( yticks )
-
- return
+ return xticks , yticks
-
-
-
-
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/docs/_modules/tp/plot/phonons.html b/docs/_modules/tp/plot/phonons.html
index d9ad9e4..d7e7f98 100644
--- a/docs/_modules/tp/plot/phonons.html
+++ b/docs/_modules/tp/plot/phonons.html
@@ -1,72 +1,30 @@
-
-
-
-
- tp.plot.phonons — ThermoPlotter 1.0.0 documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ tp.plot.phonons — ThermoPlotter 1.0.0 documentation
+
-
-
-
+
-
-
-
-
+
-
-
-
+
-
-
-
-
-
-
+
ThermoPlotter
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
Source code for tp.plot.phonons
"""Tools for dealing with phonon dispersions.
@@ -207,12 +114,15 @@ Source code for tp.plot.phonons
filename = ' {} /.config/tprc.yaml' . format ( os . path . expanduser ( "~" ))
with open ( filename , 'r' ) as f :
conf = yaml . safe_load ( f )
-except Exception :
+except yaml . parser . ParserError :
+ warnings . warn ( 'Failed to read ~/.config/tprc.yaml' )
+ conf = None
+except FileNotFoundError :
conf = None
[docs] def add_dispersion ( ax , data , sdata = None , bandmin = None , bandmax = None , main = True ,
label = None , colour = '#800080' , linestyle = 'solid' ,
-
xmarkkwargs = {}, ** kwargs ):
+
marker = None , xmarkkwargs = {}, ** kwargs ):
"""Adds a phonon band structure to a set of axes.
Labels, colours and linestyles can be given one for the whole
@@ -256,6 +166,8 @@
Source code for tp.plot.phonons
Default: #800080.
linestyle : str or array-like, optional
linestyle(s) ('-', '--', '.-', ':'). Default: solid.
+ marker : str or array-like, optional
+ marker(s). Default: None.
xmarkkwargs : dict, optional
keyword arguments for x markers passed to
@@ -315,9 +227,9 @@ Source code for tp.plot.phonons
colour = tile_properties ( colour , bandmin , bandmax )
linestyle = tile_properties ( linestyle , bandmin , bandmax )
+ marker = tile_properties ( marker , bandmin , bandmax )
# prevents unintentionally repeated legend entries
-
label2 = []
if isinstance ( label , str ):
label2 . extend ([ '$\mathregular{{ {} }}$' . format ( label )])
@@ -349,7 +261,7 @@ Source code for tp.plot.phonons
for n in range ( len ( f [ 0 ])):
ax . plot ( x , f [:, n ], color = colour [ n ], linestyle = linestyle [ n ],
- label = label2 [ n ], ** kwargs )
+ marker = marker [ n ], label = label2 [ n ], ** kwargs )
# axes formatting
@@ -362,7 +274,8 @@ Source code for tp.plot.phonons
[docs] def add_multi ( ax , data , bandmin = None , bandmax = None , main = True , label = None ,
-
colour = 'winter_r' , linestyle = 'solid' , xmarkkwargs = {}, ** kwargs ):
+
colour = 'winter_r' , linestyle = 'solid' , marker = None ,
+
xmarkkwargs = {}, ** kwargs ):
"""Adds multiple phonon band structures to a set of axes.
Scales the x-scales to match.
@@ -394,12 +307,17 @@
Source code for tp.plot.phonons
label : array-like, optional
legend labels. Default: None
- colour : colourmap or str or array-like, optional
- colourmap or colourmap name or list of colours. Note [r,g,b]
- format colours should be enclosed in and additional [],
- i.e. [[[r,g,b]],...]. Default: winter_r.
+ colour : colourmap or str or array-like or dict, optional
+ colourmap or colourmap name or list of colours, one for each
+ dispersion or a min and max colour to generate a linear
+ colourmap between or a dictionary with cmin and cmax
+ keys. Note [r,g,b] format colours should be enclosed in
+ and additional [], i.e. [[[r,g,b]],...].
+ Default: winter_r.
linestyle : str or array-like, optional
linestyle(s) ('-', '--', '.-', ':'). Default: solid.
+ marker : str or array-like, optional
+ marker(s). Default: None.
xmarkkwargs : dict, optional
keyword arguments for x markers passed to
@@ -448,12 +366,18 @@ Source code for tp.plot.phonons