Skip to content

Commit f34bf7a

Browse files
authored
Merge pull request #40 from ToFuProject/Issue033_PolynomialBck
background `linear` => `poly` (deg = 2)
2 parents ac5b070 + 29fb9df commit f34bf7a

14 files changed

+138
-76
lines changed

spectrally/_class00_plot.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ def plot_axvlines(
267267
# if ne_scale is None:
268268
# ne_scale = 'log'
269269
# if Te_scale is None:
270-
# Te_scale = 'linear'
270+
# Te_scale = 'poly'
271271

272272
# return
273273

@@ -506,4 +506,4 @@ def plot_dominance_map(
506506
)
507507
508508
return dax
509-
"""
509+
"""

spectrally/_class01_SpectralModel.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,15 @@ def add_spectral_model(
6161
'key': {'ref': k0, k1: [c0, c1], k2: [c0, c1]}
6262
6363
Available function types for dmodel are:
64-
- 'linear': typically a linear background
64+
- 'poly': typically a polynomial background
6565
- 'exp': typically an exponential background
6666
- 'gauss': typically a doppler-broadened line
6767
- 'lorentz': ypically a natural-broadened line
6868
- 'pvoigt': typically a doppler-and-natural broadened line
6969
7070
dconstraints holds a dict of constraints groups.
7171
Each group is a dict with a 'ref' variable
72-
Other variables (keys) are compued as linear functions of 'ref'
72+
Other variables (keys) are compued as poly functions of 'ref'
7373
7474
Parameters
7575
----------

spectrally/_class01_check_model.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def _dmodel_err(key, dmodel):
101101
pstr = ", ".join([f"'{tpar[0]}': {tpar[1]}" for tpar in lpar])
102102
stri = f"\t- 'f{ii}': " + "{" + f"'type': '{k0}', {pstr}" + "}"
103103

104-
if k0 == 'linear':
104+
if k0 == 'poly':
105105
lstr.append("\t# background-oriented")
106106
elif k0 == 'gauss':
107107
lstr.append("\t# spectral lines-oriented")
@@ -183,7 +183,7 @@ def _check_dmodel(
183183
# check key
184184

185185
if isinstance(k0, int):
186-
if typ in ['linear', 'exp']:
186+
if typ in ['poly', 'exp']:
187187
k1 = f'bck{ibck}'
188188
ibck += 1
189189
else:

spectrally/_class01_display_models.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ def _get_xx(xx, ftype):
140140
# set if None
141141
# -------------
142142

143-
lbck = ['linear', 'exp_lamb']
143+
lbck = ['poly', 'exp_lamb']
144144
llines = ['gauss', 'lorentz', 'pvoigt', 'voigt']
145145
lpulse = ['pulse_exp', 'pulse_gauss', 'lognorm']
146146

@@ -201,12 +201,13 @@ def _get_dpar_xfree(ftype, xx):
201201
# xfree
202202
# ---------------
203203

204-
if ftype == 'linear':
204+
if ftype == 'poly':
205205

206-
a1 = -1/Dx
207-
a0 = 2 - a1 * x0
206+
a0 = 1
207+
a1 = -0.2
208+
a2 = -1
208209

209-
xfree = np.r_[a0, a1]
210+
xfree = np.r_[a0, a1, a2]
210211

211212
elif ftype == 'exp_lamb':
212213

spectrally/_class01_dparams.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ def _get_scale(
184184
# bck
185185
# ------------
186186
187-
if typ == 'linear':
187+
if typ == 'poly':
188188
189189
if var == 'c0':
190190
pass
@@ -614,4 +614,4 @@ def fit12d_dscales(dscales=None, dinput=None):
614614
indbs=dinput['valid']['indbs'],
615615
)
616616
return dscales
617-
"""
617+
"""

spectrally/_class01_fit_func_1d.py

+21-6
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ def func(
4949
# for pulses
5050
lamb00 = lamb[0]
5151
lambD = lamb[-1] - lamb[0]
52+
lambm = 0.5*(lamb[-1] + lamb[0])
5253

5354
# iok
5455
if iok is not None:
@@ -75,16 +76,22 @@ def func(
7576
x_full = c2.dot(x_free**2) + c1.dot(x_free) + c0
7677

7778
# ------------------
78-
# sum all linear
79+
# sum all poly
7980

80-
kfunc = 'linear'
81+
kfunc = 'poly'
8182
if dind.get(kfunc) is not None:
8283

8384
a0 = x_full[dind[kfunc]['a0']['ind']][:, None]
8485
a1 = x_full[dind[kfunc]['a1']['ind']][:, None]
86+
a2 = x_full[dind[kfunc]['a2']['ind']][:, None]
8587

8688
ind = dind['func'][kfunc]['ind']
87-
val[ind, ...] = a0 + lamb * a1
89+
lamb_rel = (lamb - lambm) / lambD
90+
val[ind, ...] = (
91+
a0
92+
+ a1 * lamb_rel
93+
+ a2 * lamb_rel**2
94+
)
8895

8996
# --------------------
9097
# sum all exponentials
@@ -426,6 +433,7 @@ def func(
426433
# for pulses
427434
lamb00 = lamb[0]
428435
lambD = lamb[-1] - lamb[0]
436+
lambm = 0.5*(lamb[-1] + lamb[0])
429437

430438
# iok
431439
if iok is not None:
@@ -453,11 +461,13 @@ def func(
453461
x_full = c2.dot(x_free**2) + c1.dot(x_free) + c0
454462

455463
# -------
456-
# linear
464+
# poly
457465

458-
kfunc = 'linear'
466+
kfunc = 'poly'
459467
if dind.get(kfunc) is not None:
460468

469+
lamb_rel = (lamb - lambm) / lambD
470+
461471
vind = dind['jac'][kfunc].get('a0')
462472
if vind is not None:
463473
ival, ivar = vind['val'], vind['var']
@@ -466,7 +476,12 @@ def func(
466476
vind = dind['jac'][kfunc].get('a1')
467477
if vind is not None:
468478
ival, ivar = vind['val'], vind['var']
469-
val[:, ival] = lamb * scales[None, ival]
479+
val[:, ival] = lamb_rel * scales[None, ival]
480+
481+
vind = dind['jac'][kfunc].get('a2')
482+
if vind is not None:
483+
ival, ivar = vind['val'], vind['var']
484+
val[:, ival] = lamb_rel**2 * scales[None, ival]
470485

471486
# --------
472487
# exp_lamb

spectrally/_class01_model_dict.py

+8-6
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
_LMODEL_ORDER = [
1919
# background
20-
'linear', 'exp_lamb', # 'exp_E',
20+
'poly', 'exp_lamb', # 'exp_E',
2121
# spectral lines
2222
'gauss', 'lorentz', 'pvoigt', 'voigt',
2323
# pulse shape
@@ -38,13 +38,15 @@
3838
# -------------------
3939

4040
# -----------
41-
# linear
41+
# poly
4242

43-
'linear': {
44-
'var': ['a0', 'a1'],
45-
'description': 'straight line',
43+
'poly': {
44+
'var': ['a0', 'a1', 'a2'],
45+
'description': 'polynomial (up to deg = 2)',
4646
'expressions': {
47-
'main': r"$a_0 + a_1\lambda$",
47+
'main': r"$\left\{ \begin{array}{ll} a_0 + a_1\frac{\lambda - <\lambda>}{\Delta\lambda} + a_2\left(\frac{\lambda - <\lambda>}{\Delta\lambda}\right)^2\\ <\lambda> = \frac{\lambda[0] + \lambda[-1]}{2} \\ \Delta\lambda = \lambda[-1] - \lambda[0]\end{array} \right.$",
48+
'argmax': r"$\lambda_{max} = <\lambda> - \frac{a_1}{2a_2}\Delta\lambda$",
49+
'max': r"$f(\lambda_{max}) = a_0 - \frac{a_1^2}{4a_2}$",
4850
},
4951
},
5052

spectrally/_class01_moments.py

+11-2
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ def func(
216216
# prepare
217217

218218
lambD = lamb[-1] - lamb[0]
219+
lambm = 0.5*(lamb[0] + lamb[-1])
219220

220221
# ----------
221222
# initialize
@@ -268,13 +269,14 @@ def func(
268269
dout[kfunc][kvar] = extract(kfunc, kvar)
269270

270271
# ------------------
271-
# sum all linear
272+
# sum all poly
272273

273-
kfunc = 'linear'
274+
kfunc = 'poly'
274275
if dind.get(kfunc) is not None:
275276

276277
a0 = dout[kfunc]['a0']
277278
a1 = dout[kfunc]['a1']
279+
a2 = dout[kfunc]['a2']
278280

279281
# integral
280282
if lamb is not None:
@@ -283,6 +285,13 @@ def func(
283285
+ a1 * (lamb[-1]**2 - lamb[0]**2)/2
284286
)
285287

288+
# argmax, max
289+
dout[kfunc]['argmax'] = np.full(a0.shape, np.nan)
290+
dout[kfunc]['max'] = np.full(a1.shape, np.nan)
291+
iok = a2 != 0
292+
dout[kfunc]['argmax'][iok] = lambm - lambD * a1[iok]/(2*a2[iok])
293+
dout[kfunc]['max'][iok] = a0[iok] - a1[iok]**2 / (4*a2[iok])
294+
286295
# --------------------
287296
# sum all exponentials
288297

spectrally/_class01_show.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ def get_available_spectral_model_functions(
239239
for kf in lkeys:
240240

241241
# use case
242-
if kf == 'linear':
242+
if kf == 'poly':
243243
use = 'bck'
244244
elif kf == 'gauss':
245245
use = 'lines'

spectrally/_class02_x0_scale_bounds.py

+45-16
Original file line numberDiff line numberDiff line change
@@ -177,22 +177,39 @@ def _get_scales_bounds(
177177
ldins = [(dscales, scales), (dbounds_low, bounds0), (dbounds_up, bounds1)]
178178

179179
# ------------------
180-
# all linear
180+
# all poly
181181
# ------------------
182182

183-
kfunc = 'linear'
183+
kfunc = 'poly'
184184
if dind.get(kfunc) is not None:
185185

186186
a1max = (data_max - data_min) / lambD
187187

188+
# -------
189+
# a0
190+
191+
kvar = 'a0'
192+
vind = dind['jac'][kfunc].get(kvar)
193+
if vind is not None:
194+
ival, ivar = vind['val'], vind['var']
195+
scales[ival] = max(np.abs(data_max), np.abs(data_min))
196+
bounds0[ival] = -10.
197+
bounds1[ival] = 10.
198+
199+
for ii, (din, val) in enumerate(ldins):
200+
_update_din_from_user(
201+
din, kfunc, kvar, val,
202+
scales=None if ii == 0 else scales
203+
)
204+
188205
# -------
189206
# a1
190207

191208
kvar = 'a1'
192209
vind = dind['jac'][kfunc].get(kvar)
193210
if vind is not None:
194211
ival, ivar = vind['val'], vind['var']
195-
scales[ival] = a1max
212+
scales[ival] = max(np.abs(data_max), np.abs(data_min))
196213
bounds0[ival] = -10.
197214
bounds1[ival] = 10.
198215

@@ -203,16 +220,13 @@ def _get_scales_bounds(
203220
)
204221

205222
# -------
206-
# a0
223+
# a2
207224

208-
kvar = 'a0'
225+
kvar = 'a2'
209226
vind = dind['jac'][kfunc].get(kvar)
210227
if vind is not None:
211228
ival, ivar = vind['val'], vind['var']
212-
scales[ival] = max(
213-
np.abs(data_min - a1max*lamb[0]),
214-
np.abs(data_max + a1max*lamb[0]),
215-
)
229+
scales[ival] = max(np.abs(data_max), np.abs(data_min))
216230
bounds0[ival] = -10.
217231
bounds1[ival] = 10.
218232

@@ -703,13 +717,28 @@ def _get_x0(
703717
ldins = [(dx0, x0)]
704718

705719
# ------------------
706-
# all linear
720+
# all poly
707721
# ------------------
708722

709-
kfunc = 'linear'
723+
kfunc = 'poly'
710724
if dind.get(kfunc) is not None:
711725

712-
a1max = ((data_max - data_min) / lambD) / 10
726+
# a1max = ((data_max - data_min) / lambD) / 10
727+
728+
# -------
729+
# a0
730+
731+
kvar = 'a0'
732+
vind = dind['jac'][kfunc].get(kvar)
733+
if vind is not None:
734+
ival, ivar = vind['val'], vind['var']
735+
x0[ival] = data_mean / scales[ival]
736+
737+
for ii, (din, val) in enumerate(ldins):
738+
_update_din_from_user(
739+
din, kfunc, kvar, val,
740+
scales=scales,
741+
)
713742

714743
# -------
715744
# a1
@@ -718,7 +747,7 @@ def _get_x0(
718747
vind = dind['jac'][kfunc].get(kvar)
719748
if vind is not None:
720749
ival, ivar = vind['val'], vind['var']
721-
x0[ival] = a1max / scales[ival]
750+
x0[ival] = 0. / scales[ival]
722751

723752
for ii, (din, val) in enumerate(ldins):
724753
_update_din_from_user(
@@ -727,13 +756,13 @@ def _get_x0(
727756
)
728757

729758
# -------
730-
# a0
759+
# a2
731760

732-
kvar = 'a0'
761+
kvar = 'a2'
733762
vind = dind['jac'][kfunc].get(kvar)
734763
if vind is not None:
735764
ival, ivar = vind['val'], vind['var']
736-
x0[ival] = np.abs(data_min - a1max*lamb[0]) / scales[ival]
765+
x0[ival] = 0. / scales[ival]
737766

738767
for ii, (din, val) in enumerate(ldins):
739768
_update_din_from_user(

spectrally/tests/_hxr_pulses.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ def main(
9797
coll.add_spectral_model(
9898
key='sm_exp',
9999
dmodel={
100-
'bck': 'linear',
100+
'bck': 'poly',
101101
'pulse': 'pulse_exp',
102102
},
103103
dconstraints={
@@ -109,7 +109,7 @@ def main(
109109
coll.add_spectral_model(
110110
key='sm_gauss',
111111
dmodel={
112-
'bck': 'linear',
112+
'bck': 'poly',
113113
'pulse': 'pulse_gauss',
114114
},
115115
dconstraints={
@@ -121,7 +121,7 @@ def main(
121121
coll.add_spectral_model(
122122
key='sm_lognorm',
123123
dmodel={
124-
'bck': 'linear',
124+
'bck': 'poly',
125125
'pulse': 'lognorm',
126126
},
127127
dconstraints={

0 commit comments

Comments
 (0)