sodetlib 0.6.1rc1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,551 @@
1
+ import numpy as np
2
+ import sodetlib as sdl
3
+ import time
4
+ import matplotlib.pyplot as plt
5
+ from sodetlib.operations.iv import IVAnalysis
6
+ from sodetlib.operations import bias_steps, iv
7
+ np.seterr(all="ignore")
8
+
9
+
10
+ def bias_to_volt_arr(S, cfg, biases, bias_groups=None, overbias=True):
11
+ """
12
+ Biases detectors using an array of voltages.
13
+
14
+ Args
15
+ -----
16
+ S : SmurfControl
17
+ Pysmurf instance
18
+ cfg : DetConfig
19
+ det config instance
20
+ biases : np.ndarray
21
+ This must be an array of length 12, with the ith element being the
22
+ voltage bias of bias group i. Note that the bias of any bias group
23
+ that is not active, or not specified in the ``bias_groups`` parameter
24
+ will be ignored.
25
+ bias_groups : list
26
+ List of bias groups to bias. If None, this will default to the active
27
+ bgs specified in the device cfg.
28
+ overbias : bool
29
+ If true, will overbias specified bias lines. If false, will set bias
30
+ voltages without overbiasing detectors.
31
+ """
32
+ if bias_groups is None:
33
+ bias_groups = cfg.dev.exp['active_bgs']
34
+ bias_groups = np.atleast_1d(bias_groups)
35
+
36
+ _biases = S.get_tes_bias_bipolar_array()
37
+ for bg in bias_groups:
38
+ _biases[bg] = biases[bg]
39
+
40
+ S.log(f"Target biases: ")
41
+ for bg in bias_groups:
42
+ S.log(f"BG {bg}: {biases[bg]:.2f}")
43
+
44
+ if overbias:
45
+ sdl.overbias_dets(S, cfg, bias_groups=bias_groups)
46
+
47
+ S.set_tes_bias_bipolar_array(biases)
48
+ return
49
+
50
+
51
+ sdl.set_action()
52
+ def bias_to_rfrac(S, cfg, rfrac=None, bias_groups=None, iva=None,
53
+ overbias=True, Rn_range=(5e-3, 12e-3), math_only=False):
54
+ """
55
+ Biases detectors in their superconducting transitions to a specified fraction
56
+ of their normal resistance ("rfrac"). This function will choose TES bias
57
+ voltages for each bias-group that either (a) are the median bias voltage
58
+ achieving the specified rfrac value, or (b) maximizes the number of channels
59
+ that will be placed in the allowable rfrac range.
60
+
61
+ Args
62
+ ----
63
+ S : SmurfControl
64
+ Pysmurf instance
65
+ cfg : DetConfig
66
+ Detconfig instance
67
+ rfrac : float or 2-tuple
68
+ If float, target rfrac value. If tuple, range of allowable rfracs.
69
+ bias_groups : list, optional
70
+ Bias groups to bias. Defaults to active bgs in device cfg.
71
+ iva : IVAnalysis, optional
72
+ IVAnalysis object. If this is passed, will use it to determine
73
+ bias voltages. Defaults to using value in device cfg.
74
+ overbias_voltage : float
75
+ Voltage to use to overbias detectors
76
+ overbias_wait : float
77
+ Time (sec) to wait at overbiased voltage
78
+ Rn_range : tuple
79
+ A "reasonable" range for the TES normal resistance. This will
80
+ be cut on when determining which IVs should be used to determine
81
+ the optimal bias-voltage.
82
+ math_only : bool
83
+ If this is set, will not actually over-bias voltages, and will
84
+ just return the target biases.
85
+
86
+ Returns
87
+ ----------
88
+ biases : np.ndarray
89
+ Array of Smurf bias voltages. Note that this includes all smurf
90
+ bias lines (all 15 of them), but only voltages for the requested
91
+ bias-groups will have been modified.
92
+ """
93
+ if bias_groups is None:
94
+ bias_groups = cfg.dev.exp['active_bgs']
95
+ bias_groups = np.atleast_1d(bias_groups)
96
+
97
+ if iva is None:
98
+ iva = IVAnalysis.load(cfg.dev.exp['iv_file'])
99
+
100
+ if rfrac is None:
101
+ rfrac = cfg.dev.exp['rfrac']
102
+ rfrac = np.atleast_1d(rfrac)
103
+
104
+ if len(rfrac) not in [1,2]:
105
+ raise ValueError(
106
+ f"`rfrac` specified as {rfrac} but must be either float or 2-tuple")
107
+ biases = S.get_tes_bias_bipolar_array()
108
+
109
+ Rfrac = (iva.R.T / iva.R_n).T
110
+ if len(rfrac) == 2:
111
+ in_range = (rfrac[0] < Rfrac) & (Rfrac < rfrac[1])
112
+
113
+ for bg in bias_groups:
114
+ m = (iva.bgmap == bg)
115
+ m = m & (Rn_range[0] < iva.R_n) & (iva.R_n < Rn_range[1])
116
+
117
+ if not m.any():
118
+ continue
119
+
120
+ if len(rfrac) == 1:
121
+ target_biases = []
122
+ for rc in np.where(m)[0]:
123
+ target_idx = np.nanargmin(np.abs(Rfrac[rc] - rfrac[0]))
124
+ target_biases.append(iva.v_bias[target_idx])
125
+ biases[bg] = np.median(target_biases)
126
+ else:
127
+ nchans_in_range = np.sum(in_range[m, :], axis=0)
128
+ target_idx = np.nanargmax(nchans_in_range)
129
+ biases[bg] = iva.v_bias[target_idx]
130
+
131
+ if math_only:
132
+ return biases
133
+
134
+ S.log(f"Target biases: ")
135
+ for bg in bias_groups:
136
+ S.log(f"BG {bg}: {biases[bg]:.2f}")
137
+
138
+ if overbias:
139
+ sdl.overbias_dets(S, cfg, bias_groups=bias_groups)
140
+
141
+ S.set_tes_bias_bipolar_array(biases)
142
+
143
+ return biases
144
+
145
+
146
+ bias_to_rfrac_range = bias_to_rfrac
147
+
148
+
149
+
150
+ sdl.set_action()
151
+ def biasstep_rebias(
152
+ S, cfg, target_percentage_rn=0.5, bias_groups=None,
153
+ show_plots=True, make_plots=True, g3_tag=None):
154
+
155
+ """
156
+ re-bias detectors by taking bias_steps.
157
+
158
+ Args
159
+ -----
160
+ S : SmurfControl
161
+ Pysmurf instance
162
+ cfg : DetConfig
163
+ det config instance
164
+ target_percentage_rn : float
165
+ this is the target percentage rn for the script to bias to, numbers should be
166
+ between 0.3 and 0.7 for general usage.
167
+ bias_groups : list
168
+ List of bias groups to bias. If None, this will default to the active
169
+ bgs specified in the device cfg.
170
+ make_plots : bool
171
+ If this is set to False, the script will still apply the bias-voltage but will not
172
+ generate plots
173
+ show_plots : bool
174
+ If this is set to False, the script will not show plots
175
+ g3_tag : str
176
+ User settable tag for g3 streams
177
+
178
+ Returns
179
+ ----------
180
+ bsa_final :
181
+ analysis result of the last biasstep taken with the re-biased bais voltage
182
+ vbias_estimate_final :
183
+ final bias_voltages calculated and applied by the script
184
+ """
185
+ if bias_groups is None:
186
+ bias_groups = cfg.dev.exp['active_bgs']
187
+ bias_groups = np.atleast_1d(bias_groups)
188
+
189
+ bs_kwargs = dict(g3_tag=g3_tag, stream_subtype='biasstep_rebias')
190
+
191
+ ## take the initial biasstep
192
+ S.log("taking the first biasstep")
193
+ S.log(f"Initial dc biases {S.get_tes_bias_bipolar_array()}")
194
+ bsa_0 = bias_steps.take_bias_steps(S, cfg, **bs_kwargs)
195
+ if make_plots:
196
+ fig, ax = bias_steps.plot_Rfrac(bsa_0)
197
+ fname = sdl.make_filename(S, 'intial_Rfrac.png', plot=True)
198
+ fig.savefig(fname)
199
+ S.pub.register_file(fname, 'biasstep_rfrac', format='png', plot=True)
200
+ if not show_plots:
201
+ plt.close(fig)
202
+
203
+
204
+ ## load IV analysis result so can use dynamic step size
205
+ iva = iv.IVAnalysis.load(bsa_0.meta['iv_file'])
206
+
207
+ repeat_biasstep = False
208
+ ## check for script failue
209
+ for bl in bias_groups:
210
+ mask_bg = np.where(bsa_0.bgmap==bl)[0]
211
+ per_bl_R0 = bsa_0.R0[mask_bg]
212
+ if np.isnan(np.nanmedian(per_bl_R0)):
213
+ ## the yield is very low, could it be the biasstep analysis script failed? repeat again
214
+ repeat_biasstep = True
215
+ S.log("the biasstep script might have failed, going to repeat the measurement")
216
+
217
+ if repeat_biasstep:
218
+ S.log("retaking biasstep due to failure")
219
+ bsa_0 = bias_steps.take_bias_steps(S, cfg, **bs_kwargs)
220
+ repeat_biasstep = False
221
+
222
+ percentage_rn_0 = bsa_0.R0/bsa_0.R_n_IV
223
+ ## add in checks if detectors are SC
224
+ bg_overbias_needed = []
225
+ overbias_needed = False
226
+ for bl in bias_groups:
227
+ mask_bg = np.where(bsa_0.bgmap==bl)[0]
228
+ per_bl_percentage_rn_0 = percentage_rn_0[mask_bg]
229
+ ## mask for SC
230
+ mask_sc = np.where((per_bl_percentage_rn_0 < 0.1) & (per_bl_percentage_rn_0 > -0.1))
231
+ ## if more than 10 percent of the detectors are SC
232
+ if len(mask_sc[0]) > 0.1*len(mask_bg):
233
+ bg_overbias_needed.append(bl)
234
+ overbias_needed = True
235
+
236
+ ## add in check if detectors are normal, hence we should increase the drop step
237
+ bg_detectors_normal = []
238
+ drop_from_normal = False
239
+ for bl in bias_groups:
240
+ mask_bg = np.where(bsa_0.bgmap==bl)[0]
241
+ per_bl_percentage_rn_0 = percentage_rn_0[mask_bg]
242
+ ## mask for normal
243
+ mask_normal = np.where((per_bl_percentage_rn_0 > 0.9) | (per_bl_percentage_rn_0 < -0.9))
244
+ ## if more than half of the detectors are normal
245
+ if len(mask_normal[0]) > 0.5*len(mask_bg):
246
+ bg_detectors_normal.append(bl)
247
+ drop_from_normal = True
248
+
249
+
250
+ if overbias_needed:
251
+ S.log(f"some BL: {bg_overbias_needed} are stuck in SC, going to over bias them, this takes about 5mins")
252
+ previous_dc_biases = S.get_tes_bias_bipolar_array()
253
+
254
+ sdl.overbias_dets(S, cfg, bias_groups=bg_overbias_needed)
255
+ ##force wait for UFM to reach equalibrium
256
+ sleep_time = cfg.dev.exp["overbias_sleep_time_sec"]
257
+ time.sleep(sleep_time)
258
+ safe_dc_biases = previous_dc_biases.copy()
259
+ for replace_bg in bg_overbias_needed:
260
+ try:
261
+ safe_dc_biases[replace_bg] = cfg.dev.bias_groups[replace_bg]["testbed_100mK_bias_voltage"]
262
+ except KeyError:
263
+ mask_bg = np.where(bsa_0.bgmap==replace_bg)[0]
264
+ v_norm_bl = np.nanmedian(iva.v_bias[iva.idxs[[mask_bg], 1]])
265
+ safe_dc_biases[replace_bg] = v_norm_bl
266
+
267
+
268
+ S.set_tes_bias_bipolar_array(safe_dc_biases)
269
+ bsa_0 = bias_steps.take_bias_steps(S, cfg, **bs_kwargs)
270
+ if make_plots:
271
+ fig, ax = bias_steps.plot_Rfrac(bsa_0)
272
+ fname = sdl.make_filename(S, 'post_overbiasing_Rfrac.png', plot=True)
273
+ fig.savefig(fname)
274
+ S.pub.register_file(fname, 'biasstep_rfrac', format='png', plot=True)
275
+ if not show_plots:
276
+ plt.close(fig)
277
+
278
+ ## add in check if detectors are normal now
279
+ percentage_rn_0 = bsa_0.R0/bsa_0.R_n_IV
280
+ drop_from_normal = False
281
+ for bl in bg_overbias_needed:
282
+ mask_bg = np.where(bsa_0.bgmap==bl)[0]
283
+ per_bl_percentage_rn_0 = percentage_rn_0[mask_bg]
284
+ ## mask for normal
285
+ mask_normal = np.where((per_bl_percentage_rn_0 > 0.9) | (per_bl_percentage_rn_0 < -0.9))
286
+ ## if more than half of the detectors are normal
287
+ if len(mask_normal[0]) > 0.5*len(mask_bg):
288
+ bg_detectors_normal.append(bl)
289
+ drop_from_normal = True
290
+
291
+ ## drop normal detector into transition first
292
+ while drop_from_normal:
293
+ S.log(f"some biaslines are still in normal state: {bg_detectors_normal}")
294
+ percentage_rn_0 = bsa_0.R0/bsa_0.R_n_IV
295
+ S.log("droping detectors from normal to transition")
296
+ previous_dc_biases_dfn = S.get_tes_bias_bipolar_array()
297
+
298
+ S.log(f"current tes bias voltages are: {previous_dc_biases_dfn}")
299
+ for bl in bg_detectors_normal:
300
+ mask_bg = np.where(bsa_0.bgmap==bl)[0]
301
+ v_sc = iva.v_bias[iva.idxs[[mask_bg], 0]]
302
+ v_norm = iva.v_bias[iva.idxs[[mask_bg], 1]]
303
+ v_spread = np.nanmedian(v_norm) - np.nanmedian(v_sc)
304
+ if previous_dc_biases_dfn[bl] > v_spread:
305
+ previous_dc_biases_dfn[bl] = previous_dc_biases_dfn[bl] - 0.5 * v_spread
306
+ else:
307
+ previous_dc_biases_dfn[bl] = previous_dc_biases_dfn[bl] - 0.3 * v_spread
308
+ bg_detectors_normal.remove(bl)
309
+ S.log(f'biasline {bl} is approching 0 voltage, a confirmation new IV curve is recommended')
310
+
311
+ S.set_tes_bias_bipolar_array(previous_dc_biases_dfn)
312
+ S.log(f"applying: {previous_dc_biases_dfn}")
313
+ S.log(f"waiting 10s for dissipation of UFM local heating")
314
+ time.sleep(10)
315
+ bsa_0 = bias_steps.take_bias_steps(S, cfg, **bs_kwargs)
316
+ percentage_rn_0 = bsa_0.R0/bsa_0.R_n_IV
317
+ drop_from_normal = False
318
+ for bl in bg_detectors_normal:
319
+ mask_bg = np.where(bsa_0.bgmap==bl)[0]
320
+ per_bl_percentage_rn_0 = percentage_rn_0[mask_bg]
321
+ ## mask for normal
322
+ mask_normal = np.where((per_bl_percentage_rn_0 > 0.9) | (per_bl_percentage_rn_0 < -0.9))
323
+ ## if more than half of the detectors are normal
324
+ if len(mask_normal[0]) > 0.5*len(mask_bg):
325
+ drop_from_normal = True
326
+ else:
327
+ bg_detectors_normal.remove(bl)
328
+ for bl in bg_detectors_normal:
329
+ if previous_dc_biases_dfn[bl] < 0.5:
330
+ bg_detectors_normal.remove(bl)
331
+
332
+
333
+
334
+
335
+ ##preparing for the 2nd step
336
+ initial_dc_biases = S.get_tes_bias_bipolar_array()
337
+ new_bias_voltage = initial_dc_biases.copy()
338
+
339
+
340
+
341
+
342
+ for bl in bias_groups:
343
+ mask_bg = np.where(bsa_0.bgmap==bl)[0]
344
+
345
+ per_bl_percentage_rn_0 = percentage_rn_0[mask_bg]
346
+
347
+ med_per_bl_percentage_rn = np.nanmedian(per_bl_percentage_rn_0)
348
+
349
+ ## use the latest IV to decide the step size, might be tricky to get a good step size in field
350
+ v_sc = iva.v_bias[iva.idxs[[mask_bg], 0]]
351
+ v_norm = iva.v_bias[iva.idxs[[mask_bg], 1]]
352
+ v_spread = np.nanmedian(v_norm) - np.nanmedian(v_sc)
353
+ ## take 15% of the spread as the step size, so the next biasstep will be taken from 0.25 ~ 0.75 percent Rn after considering the spread
354
+ delta_dc_bias = 0.15 * v_spread
355
+
356
+
357
+ ## if the current bias point is below 50% Rn, increase V_biaa
358
+ if med_per_bl_percentage_rn < 0.5:
359
+ new_bias_voltage[bl] = initial_dc_biases[bl] + delta_dc_bias
360
+ if med_per_bl_percentage_rn >= 0.5:
361
+ new_bias_voltage[bl] = initial_dc_biases[bl] - delta_dc_bias
362
+
363
+ S.log(f"applying new voltage for 2nd biasstep {new_bias_voltage}")
364
+ S.set_tes_bias_bipolar_array(new_bias_voltage)
365
+
366
+ ## taking the second bias step
367
+ S.log("taking the 2nd biasstep")
368
+ bsa_1 = bias_steps.take_bias_steps(S, cfg, **bs_kwargs)
369
+ if make_plots:
370
+ fig, ax = bias_steps.plot_Rfrac(bsa_1)
371
+ fname = sdl.make_filename(S, '2nd_Rfrac.png', plot=True)
372
+ fig.savefig(fname)
373
+ S.pub.register_file(fname, 'biasstep_rfrac', format='png', plot=True)
374
+ if not show_plots:
375
+ plt.close(fig)
376
+
377
+ ## check for script failue
378
+ for bl in bias_groups:
379
+ mask_bg = np.where(bsa_1.bgmap==bl)[0]
380
+ per_bl_R0 = bsa_1.R0[mask_bg]
381
+ if np.isnan(np.nanmedian(per_bl_R0)):
382
+ ## the yield is very low, could it be the biasstep analysis script failed? repeat again
383
+ repeat_biasstep = True
384
+ S.log("the biasstep script might have failed, going to repeat the measurement")
385
+
386
+ if repeat_biasstep:
387
+ bsa_1 = bias_steps.take_bias_steps(S, cfg, **bs_kwargs)
388
+ repeat_biasstep = False
389
+
390
+ percentage_rn_1 = bsa_1.R0/bsa_1.R_n_IV
391
+
392
+ target_percentage_rn_array = target_percentage_rn * np.ones(len(percentage_rn_0))
393
+ ## getting result from the previous 2
394
+ v0 = np.zeros(bsa_0.bgmap.shape[0])
395
+ for bl in range(12):
396
+ mask_bl = np.where(bsa_0.bgmap==bl)[0]
397
+ v0[mask_bl] = initial_dc_biases[bl]
398
+
399
+ v1 = np.zeros(bsa_1.bgmap.shape[0])
400
+ for bl in range(12):
401
+ mask_bl = np.where(bsa_1.bgmap==bl)[0]
402
+ v1[mask_bl] = new_bias_voltage[bl]
403
+ ## deciding the new bias point
404
+ vbias_estimate_array = (v0*(target_percentage_rn_array-percentage_rn_1) + v1*(percentage_rn_0 - target_percentage_rn_array)) / (percentage_rn_0 - percentage_rn_1)
405
+
406
+ vbias_estimate = initial_dc_biases.copy()
407
+ for bl in bias_groups:
408
+ mask_bg = np.where(bsa_0.bgmap==bl)[0]
409
+
410
+ per_bl_vbias_estimate = vbias_estimate_array[mask_bg]
411
+ med_per_bl_vbias_estimate = np.nanmedian(per_bl_vbias_estimate)
412
+ if np.isnan(med_per_bl_vbias_estimate):
413
+ med_per_bl_vbias_estimate = (np.nanmedian(v1[mask_bg]) + np.nanmedian(v0[mask_bg]))/2
414
+ vbias_estimate[bl] = med_per_bl_vbias_estimate
415
+
416
+ S.log("applying the new bias voltages")
417
+ S.set_tes_bias_bipolar_array(vbias_estimate)
418
+ S.log(f"applying {vbias_estimate}")
419
+ S.log("taking the final biasstep")
420
+ bsa_2 = bias_steps.take_bias_steps(S, cfg, **bs_kwargs)
421
+
422
+ ## check for script failue
423
+ for bl in bias_groups:
424
+ mask_bg = np.where(bsa_2.bgmap==bl)[0]
425
+ per_bl_R0 = bsa_2.R0[mask_bg]
426
+ if np.isnan(np.nanmedian(per_bl_R0)):
427
+ ## the yield is very low, could it be the biasstep analysis script failed? repeat again
428
+ repeat_biasstep = True
429
+ S.log("the biasstep script might have failed, going to repeat the measurement")
430
+
431
+ if repeat_biasstep:
432
+ bsa_2 = bias_steps.take_bias_steps(S, cfg, **bs_kwargs)
433
+ repeat_biasstep = False
434
+
435
+ if make_plots:
436
+ fig, ax = bias_steps.plot_Rfrac(bsa_2)
437
+ fname = sdl.make_filename(S, 'rebiased_Rfrac.png', plot=True)
438
+ fig.savefig(fname)
439
+ S.pub.register_file(fname, 'biasstep_rfrac', format='png', plot=True)
440
+ if not show_plots:
441
+ plt.close(fig)
442
+
443
+
444
+ S.log("confirming if the current result is close to the target")
445
+ percentage_rn_confirm = bsa_2.R0/bsa_2.R_n_IV
446
+ succeeded_bl = []
447
+ un_succeeded_bl = []
448
+ for bl in bias_groups:
449
+ mask_bg = np.where(bsa_2.bgmap==bl)[0]
450
+ per_bl_percentage_rn_confirm = np.nanmedian(percentage_rn_confirm[mask_bg])
451
+ if per_bl_percentage_rn_confirm > target_percentage_rn - 0.05 and per_bl_percentage_rn_confirm < target_percentage_rn + 0.05:
452
+ succeeded_bl.append(bl)
453
+ else:
454
+ un_succeeded_bl.append(bl)
455
+ S.log(f"succeeded bl: {succeeded_bl}")
456
+ S.log(f"unsucceeded bl: {un_succeeded_bl}")
457
+
458
+ if len(un_succeeded_bl)==0:
459
+ bsa_final = bsa_2
460
+ vbias_estimate_final = vbias_estimate
461
+
462
+
463
+ if len(un_succeeded_bl)!=0:
464
+ extra_step_bias_voltage = vbias_estimate.copy()
465
+ S.log("fine tunning unsucceeded bl")
466
+ for bl in un_succeeded_bl:
467
+ mask_bg = np.where(bsa_2.bgmap==bl)[0]
468
+ per_bl_percentage_rn_confirm = percentage_rn_confirm[mask_bg]
469
+ med_per_bl_percentage_confirm = np.nanmedian(per_bl_percentage_rn_confirm)
470
+
471
+ ## use the latest IV to decide the step size, might be tricky to get a good step size in field
472
+ v_sc = iva.v_bias[iva.idxs[[mask_bg], 0]]
473
+ v_norm = iva.v_bias[iva.idxs[[mask_bg], 1]]
474
+ v_spread = np.nanmedian(v_norm) - np.nanmedian(v_sc)
475
+ ## take 15% of the spread as the step size, so the next biasstep will be taken from 0.25 ~ 0.75 percent Rn after considering the spread
476
+ delta_dc_bias = 0.15 * v_spread
477
+ ## if the current bias point is below 50% Rn, increase V_biaa
478
+ if med_per_bl_percentage_confirm < 0.5:
479
+ extra_step_bias_voltage[bl] = vbias_estimate[bl] + delta_dc_bias
480
+ if med_per_bl_percentage_confirm >= 0.5:
481
+ extra_step_bias_voltage[bl] = vbias_estimate[bl] - delta_dc_bias
482
+
483
+ S.log(f"applying new voltage for extra step biasstep {extra_step_bias_voltage}")
484
+ S.set_tes_bias_bipolar_array(extra_step_bias_voltage)
485
+
486
+ ## taking the extra bias step
487
+ S.log("taking the extra biasstep")
488
+ bsa_extra = bias_steps.take_bias_steps(S, cfg, **bs_kwargs)
489
+
490
+ ## check for script failue
491
+ for bl in bias_groups:
492
+ mask_bg = np.where(bsa_extra.bgmap==bl)[0]
493
+ per_bl_R0 = bsa_extra.R0[mask_bg]
494
+ if np.isnan(np.nanmedian(per_bl_R0)):
495
+ ## the yield is very low, could it be the biasstep analysis script failed? repeat again
496
+ repeat_biasstep = True
497
+ S.log("the biasstep script might have failed, going to repeat the measurement")
498
+
499
+ if repeat_biasstep:
500
+ bsa_extra = bias_steps.take_bias_steps(S, cfg, **bs_kwargs)
501
+ repeat_biasstep = False
502
+
503
+ if make_plots:
504
+ fig, ax = bias_steps.plot_Rfrac(bsa_extra)
505
+ fname = sdl.make_filename(S, '3rd_Rfrac.png', plot=True)
506
+ fig.savefig(fname)
507
+ S.pub.register_file(fname, 'biasstep_rfrac', format='png', plot=True)
508
+ if not show_plots:
509
+ plt.close(fig)
510
+
511
+ percentage_rn_extra = bsa_extra.R0/bsa_extra.R_n_IV
512
+
513
+ ## getting result from the previous 2
514
+ v0 = np.zeros(bsa_2.bgmap.shape[0])
515
+ for bl in range(12):
516
+ mask_bl = np.where(bsa_2.bgmap==bl)[0]
517
+ v0[mask_bl] = vbias_estimate[bl]
518
+
519
+ v1 = np.zeros(bsa_extra.bgmap.shape[0])
520
+ for bl in range(12):
521
+ mask_bl = np.where(bsa_extra.bgmap==bl)[0]
522
+ v1[mask_bl] = extra_step_bias_voltage[bl]
523
+ ## deciding the new bias point
524
+ vbias_estimate_array_extra = (v0*(target_percentage_rn_array-percentage_rn_extra) + v1*(percentage_rn_confirm - target_percentage_rn_array)) / (percentage_rn_confirm - percentage_rn_extra)
525
+
526
+ vbias_estimate_final = initial_dc_biases.copy()
527
+ for bl in bias_groups:
528
+ mask_bg = np.where(bsa_2.bgmap==bl)[0]
529
+
530
+ per_bl_vbias_estimate = vbias_estimate_array_extra[mask_bg]
531
+ med_per_bl_vbias_estimate = np.nanmedian(per_bl_vbias_estimate)
532
+ if np.isnan(med_per_bl_vbias_estimate):
533
+ med_per_bl_vbias_estimate = (np.nanmedian(v1[mask_bg]) + np.nanmedian(v0[mask_bg]))/2
534
+ vbias_estimate_final[bl] = med_per_bl_vbias_estimate
535
+
536
+
537
+ S.log("applying the new bias voltages")
538
+ S.set_tes_bias_bipolar_array(vbias_estimate_final)
539
+ S.log(f"applying {vbias_estimate_final}")
540
+ S.log("taking the final biasstep")
541
+ bsa_final = bias_steps.take_bias_steps(S, cfg, **bs_kwargs)
542
+ if make_plots:
543
+ fig, ax = bias_steps.plot_Rfrac(bsa_final)
544
+ fname = sdl.make_filename(S, 'rebiased_Rfrac_2.png', plot=True)
545
+ fig.savefig(fname)
546
+ S.pub.register_file(fname, 'biasstep_rfrac', format='png', plot=True)
547
+ if not show_plots:
548
+ plt.close(fig)
549
+
550
+
551
+ return bsa_final,vbias_estimate_final