1414
1515
1616from . import _xray_thin_target_integrated as _mod
17+ from ._xray_thin_target_integrated_cases import _DCASES_PRE
1718
1819
1920TupleDict = tuple [dict ]
3435
3536# DSCALES
3637_DSCALES = {
37- 'E_ph' : 'linear ' ,
38+ 'E_ph' : 'log ' ,
3839 'E_e0' : 'log' ,
3940 'theta' : 'linear' ,
4041}
4142
4243
43- # ANISOTROPY CASES
44- _DCASES = {
45- 0 : {
46- 'E_e0_eV' : 20e3 ,
47- 'E_ph_eV' : 10e3 ,
48- 'color' : 'r' ,
49- 'marker' : '*' ,
50- 'ms' : 14 ,
51- },
52- 1 : {
53- 'E_e0_eV' : 100e3 ,
54- 'E_ph_eV' : 50e3 ,
55- 'color' : 'c' ,
56- 'marker' : '*' ,
57- 'ms' : 14 ,
58- },
59- 2 : {
60- 'E_e0_eV' : 100e3 ,
61- 'E_ph_eV' : 10e3 ,
62- 'color' : 'm' ,
63- 'marker' : '*' ,
64- 'ms' : 14 ,
65- },
66- 3 : {
67- 'E_e0_eV' : 1000e3 ,
68- 'E_ph_eV' : 10e3 ,
69- 'color' : (0.8 , 0.8 , 0 ),
70- 'marker' : '*' ,
71- 'ms' : 14 ,
72- },
73- 4 : {
74- 'E_e0_eV' : 10000e3 ,
75- 'E_ph_eV' : 10e3 ,
76- 'color' : (0. , 0.8 , 0.8 ),
77- 'marker' : '*' ,
78- 'ms' : 14 ,
79- },
80- 5 : {
81- 'E_e0_eV' : 1000e3 ,
82- 'E_ph_eV' : 50e3 ,
83- 'color' : (0.8 , 0. , 0.8 ),
84- 'marker' : '*' ,
85- 'ms' : 14 ,
86- },
44+ # ANISOTROPY CASES FORMATTING
45+ _DCASES_FORMAT = {
46+ 'E_e0_eV' : (int , float ),
47+ 'E_ph_eV' : (int , float ),
48+ 'color' : (str , tuple ),
49+ 'marker' : str ,
50+ 'ms' : (int , float ),
8751}
8852
8953
54+ # ANISOTROPY CASES DEFAULT
55+ _DCASES_CASE = 'standard'
56+
57+
9058# ####################################################
9159# ####################################################
9260# plot anisotropy
@@ -146,7 +114,6 @@ def plot_xray_thin_d2cross_ei_anisotropy(
146114 (
147115 E_e0_eV , E_ph_eV , theta_ph ,
148116 version ,
149- dcases ,
150117 dscales ,
151118 verb ,
152119 fontsize ,
@@ -175,6 +142,22 @@ def plot_xray_thin_d2cross_ei_anisotropy(
175142 verb = verb ,
176143 )
177144
145+ # -------------------
146+ # update from d2cross
147+ # -------------------
148+
149+ # if d2cross was provided
150+ theta_ph = d2cross ['theta_ph' ]['data' ].ravel ()
151+ E_ph_eV = d2cross ['E_ph' ]['data' ].ravel ()
152+ E_e0_eV = d2cross ['E_e0' ]['data' ].ravel ()
153+
154+ # dcases
155+ dcases = _check_dcases (
156+ dcases = dcases ,
157+ E_e0_eV = E_e0_eV ,
158+ E_ph_eV = E_ph_eV ,
159+ )
160+
178161 # --------------
179162 # prepare axes
180163 # --------------
@@ -205,14 +188,18 @@ def plot_xray_thin_d2cross_ei_anisotropy(
205188 theta_ph * 180 / np .pi ,
206189 axis = 0 ,
207190 )
191+ mean_log10 = np .full (mean .shape , np .nan )
192+ iok = np .isfinite (mean )
193+ iok [iok ] = mean [iok ] > 0.
194+ mean_log10 [iok ] = np .log10 (mean [iok ])
208195 mean_units = vv ['units' ]
209196
210197 # integral
211198 if dplot_mean is not False :
212199 im0 = ax .contour (
213200 E_e0_eV * 1e-3 ,
214201 E_ph_eV * 1e-3 ,
215- np . log10 ( mean ) .T ,
202+ mean_log10 .T ,
216203 levels = dplot_mean ['levels' ],
217204 colors = dplot_mean ['colors' ],
218205 )
@@ -315,7 +302,8 @@ def plot_xray_thin_d2cross_ei_anisotropy(
315302 )
316303
317304 # limits
318- ax .set_ylim (0 , ymax * 1e-3 )
305+ if dscales ['E_ph' ] == 'linear' :
306+ ax .set_ylim (0 , ymax * 1e-3 )
319307
320308 # ---------------
321309 # plot - cases
@@ -389,8 +377,6 @@ def _check_anisotropy(
389377 E_ph_eV = None ,
390378 theta_ph = None ,
391379 version = None ,
392- # selected cases
393- dcases = None ,
394380 # verb
395381 verb = None ,
396382 # scales
@@ -437,38 +423,6 @@ def _check_anisotropy(
437423 if version is None :
438424 version = _VERSION
439425
440- # ------------
441- # dcases
442- # ------------
443-
444- ddef = copy .deepcopy (_DCASES )
445- if dcases in [None , True ]:
446- dcases = ddef
447-
448- if dcases is not False :
449- for k0 , v0 in dcases .items ():
450- dcases [k0 ] = _check_anisotropy_dplot (
451- v0 ,
452- f'dcases[{ k0 } ]' ,
453- ddef [0 ],
454- )
455-
456- # update with indices
457- ie = np .argmin (np .abs (E_e0_eV - dcases [k0 ]['E_e0_eV' ]))
458- iph = np .argmin (np .abs (E_ph_eV - dcases [k0 ]['E_ph_eV' ]))
459- dcases [k0 ].update ({'ie' : ie , 'iph' : iph })
460-
461- # update with label
462- ee0 = E_e0_eV [ie ]
463- eph = E_ph_eV [iph ]
464- dcases [k0 ]['lab' ] = (
465- r"$E_{e0} / E_{ph}$ = "
466- + f"{ ee0 * 1e-3 :3.0f} / { eph * 1e-3 :3.0f} keV = "
467- + f"{ round (ee0 / eph , ndigits = 1 )} "
468- )
469- else :
470- dcases = {}
471-
472426 # -----------
473427 # verb
474428 # -----------
@@ -545,14 +499,76 @@ def _check_anisotropy(
545499 return (
546500 E_e0_eV , E_ph_eV , theta_ph ,
547501 version ,
548- dcases ,
549502 dscales ,
550503 verb ,
551504 fontsize ,
552505 dplot_forbidden , dplot_peaking , dplot_thetamax , dplot_mean ,
553506 )
554507
555508
509+ def _check_dcases (
510+ dcases = None ,
511+ E_e0_eV = None ,
512+ E_ph_eV = None ,
513+ ):
514+
515+ # --------------
516+ # dcases default
517+ # --------------
518+
519+ ddef = copy .deepcopy (_DCASES_FORMAT )
520+ if dcases in [None , True ]:
521+ dcases = _DCASES_CASE
522+
523+ # --------------
524+ # dcases from predefined
525+ # --------------
526+
527+ if isinstance (dcases , str ):
528+ lok = sorted (_DCASES_PRE .keys ())
529+ if dcases not in lok :
530+ lstr = [f"\t - { kk } " for kk in lok ]
531+ msg = (
532+ "Arg 'dcases' must be either:\n "
533+ "\t - dict of cases\n "
534+ "\t - a key to a predefined dict of cases\n "
535+ "Available predefined dcases:\n "
536+ + "\n " .join (lstr )
537+ )
538+ raise Exception (msg )
539+ dcases = copy .deepcopy (_DCASES_PRE [dcases ])
540+
541+ # --------------
542+ # generic check
543+ # --------------
544+
545+ if dcases is not False :
546+ for k0 , v0 in dcases .items ():
547+ dcases [k0 ] = _check_anisotropy_dplot (
548+ v0 ,
549+ f'dcases[{ k0 } ]' ,
550+ ddef ,
551+ )
552+
553+ # update with indices
554+ ie = np .argmin (np .abs (E_e0_eV - dcases [k0 ]['E_e0_eV' ]))
555+ iph = np .argmin (np .abs (E_ph_eV - dcases [k0 ]['E_ph_eV' ]))
556+ dcases [k0 ].update ({'ie' : ie , 'iph' : iph })
557+
558+ # update with label
559+ ee0 = E_e0_eV [ie ]
560+ eph = E_ph_eV [iph ]
561+ dcases [k0 ]['lab' ] = (
562+ r"$E_{e0} / E_{ph}$ = "
563+ + f"{ ee0 * 1e-3 :3.0f} / { eph * 1e-3 :3.0f} keV = "
564+ + f"{ round (ee0 / eph , ndigits = 1 )} "
565+ )
566+ else :
567+ dcases = {}
568+
569+ return dcases
570+
571+
556572def _check_anisotropy_dplot (din , dname , ddef ):
557573
558574 # -------------
@@ -569,7 +585,11 @@ def _check_anisotropy_dplot(din, dname, ddef):
569585 if din is not False :
570586 c0 = (
571587 isinstance (din , dict )
572- and all ([kk in ddef .keys () for kk in din .keys ()])
588+ and all ([
589+ kk in ddef .keys ()
590+ and isinstance (din [kk ], ddef [kk ])
591+ for kk in din .keys ()
592+ ])
573593 )
574594 if not c0 :
575595 lstr = [f"\t - ''{ k0 } ': { v0 } " for k0 , v0 in ddef .items ()]
@@ -604,19 +624,30 @@ def _get_peaking(data, x, axis=None):
604624 # ----------
605625
606626 integ = scpinteg .trapezoid (data , x = x , axis = axis )
607- shape_integ = tuple ([
608- 1 if ii == axis else ss
609- for ii , ss in enumerate (data .shape )
610- ])
611- data_n = data / integ .reshape (shape_integ )
627+ shape_integ = list (data .shape )
628+ shape_integ [axis ] = 1
629+
630+ data_n = np .full (data .shape , np .nan )
631+ iok = np .isfinite (integ )
632+ iok [iok ] = integ [iok ] > 0
633+ iokn = iok .nonzero ()
634+ sli0 = list (iokn )
635+ sli1 = list (iokn )
636+ sli0 .insert (axis , None )
637+ sli1 .insert (axis , slice (None ))
638+ data_n [tuple (sli1 )] = data [tuple (sli1 )] / integ [tuple (sli0 )]
612639
613640 # ----------
614641 # get average
615642 # ----------
616643
617644 shape_x = tuple ([- 1 if ii == axis else 1 for ii in range (data .ndim )])
618645 xf = x .reshape (shape_x )
619- x_avf = scpinteg .simpson (data_n * xf , x = x , axis = axis ).reshape (shape_integ )
646+ x_avf = scpinteg .trapezoid (
647+ data_n * xf ,
648+ x = x ,
649+ axis = axis ,
650+ ).reshape (shape_integ )
620651 std = np .sqrt (scpinteg .simpson (data_n * (xf - x_avf )** 2 , x = x , axis = axis ))
621652
622653 return integ / 180 , 1 / std
0 commit comments