Bias Steps and Bias Group Maps
Bias steps are when we take small steps in the detector bias voltage and measure the detector response. These are a fantastic tool for calibrating detectors and can be used to estimate detector parameters such as resistance, responsivity, effective time constant, and can also be used to quickly generate a bias-group mapping.
Usage
Generating a Bias Group Map
To generate a bias-group map, use the function take_bgmap
from the
bias_steps module. This will run the bias-steps function with parameters
optimal for generating a bias-group map, will create a bgmap file, and
save the filepath to the device cfg. This function returns a bias
step analysis object.
import sodetlib.operations as ops
bsa = ops.take_bgmap(S, cfg)
To generate the bgmap, this function will set detectors to superconducting
and play a series of small bias-steps. Because the detectors are
superconducting, we expect a very clear bias-group correlation, and we expect
the estimated resistance to be very small.
By default, channels will be “unassigned” from the bgmap if the bg-correlation
factor is less than 0.9 or if the estimated resistance is larger than 10 mOhms
to avoid picking up crosstalk channels.
These cuts can be modified by setting the corresponding keyword arguments manually
in the analysis_kwargs
parameter, for example:
from sodetlib.operations import bias_steps
analysis_kwargs = {
'assignment_thresh': 0.5,
'R0_thresh': 5e-3
}
bsa = bias_steps.take_bgmap(S, cfg, analysis_kwargs=analysis_kwargs)
The bgmap file stores key metadata along with information about which channels were run to produce the map, the bias-group assignments of each channel, and the polarity of each channel, or whether the squid response steps in the same or opposite direction of the bias current. The bgmap file contains:
- meta:
Dictionary of metadata returned by the
get_metadata
funciton insodetlib.util
- sid:
Session-id of bgmap data
- bands:
Array containing the smurf-band number for each channel
- channels:
Array containing the smurf-channel number for each channel
- bgmap:
Array containing the assigned bias group of each channel. This will be
-1
if unassigned.
- polarity:
Array containing the polarity of the channel with respect to the bias line. This will be
+1
if the signal steps in the same direction as \(\Delta V\) and-1
if the signal steps in the opposite direction.
To load a bgmap for a set of channels, you can use the load_bgmap
function.
import sodetlib as sdl
sid = sdl.take_g3_data(S, 30)
am = sdl.load_session(cfg.stream_id, sid)
bgmap, polarity = sdl.load_bgmap(
am.ch_info.band, am.ch_info.channel, cfg.dev.exp['bgmap_file']
)
Running Bias Steps
The sodetlib function take_bias_steps
can be used to take bias steps and
run the analysis to calculate the detector parameters mentioned above. The
default parameters should be good enough for the full analysis, for example,
one can simply run
from sodetlib.operations.bias_steps import take_bias_steps
bsa = take_bias_steps(S, cfg)
If all goes well, the returned object bsa
is a fully analyzed instance of
the BiasStepAnalysis class. This means that all the detector parameter
fields (such as R0
, I0
, Pj
, tau_eff
etc.) exist and can be
examined. If the analysis failed for whatever reason, the BiasStepAnalysis
class will still be returned, however most of the derived parameters will not
exist as attributes. However the axis manager will still be loaded (bsa.am
)
so you can use that to investigate why the analysis may have failed.
You can re-run the analysis without retaking the data by running
bsa.run_analysis()
Sometimes playing with the analysis keywords (see the API for more details) will give you better results.
Running in Low Current Mode
It is possible to run this function in low-current-mode, which might be desirable if switching to high-current-mode is causing excess heating for whatever reason. Since the low-current-mode has a bias-line filter which increases the signal decay time, in order to get an accurate reading of the TES resistance / responsivity you need to increase the step_duration to at least a couple of seconds. This will make the function take much longer (~2-3 minutes) so this mode of operation may not be as useful. For example, this should work:
bsa = take_bias_steps(
S, cfg, high_current_mode=False, step_duration=2,
nsteps=5, analysis_kwargs={'step_window': 2}
)
How it works
Data Taking
With the default parameters, the take_bias_steps
function will play
nsteps
on each of the specified bias groups one at a time.
Generating the Bias Group Map
To generate the bias group assignment for a given channel, we measure the TES
change in phase \(\Delta \Phi\) in response to the sweep bias steps. We add
\(\pm \Delta \Phi\) for each of the “sweep steps” on a given bias group,
where we use + if it’s a rising step and - for a falling step. If a channel has
a strong dependence on a particular bias group, the TES responses will co-add
and give you a large summed response, and if there is no dependence on a bias
group the rising and falling edges will cancel, even if there is a global trend
resulting in a small summed response. For a given channel, the summed responses
for each bias group are normalized such that they all add to 1, giving us a
“normalized correlation factor” (stored in the bg_corr
array).
When there is a very clear correlation, (like if the detector is
superconducting), there will be one bias group with a correlation value close
to 1 and the rest will be close to 0. If it is less clear, for instance if the
detectors are in transition and there is a non-linear trend in the detector
timestream (from heating for example), the maximum correlation factor will be
smaller (like 0.3-0.9) but the maximum will usually still give you the correct
bias group. If the maximum correlation factor is less than the
assignment_thresh
value, the channel is unassigned from all bias groups.
Note
A channel that is perfectly uncorrelated to all bias groups will have a
correlation factor of 1/NBiasGroups for each bias-group. Though this is not
optimal for determining which bias groups are not connected to any
bias-line, an additional cut is made after calculating the TES resistance,
which is a better metric for determining which channels should be left
unassigned. Any channel that has an estimated resistance larger than the
R0_thresh
parameter will be considered noise or crosstalk and unassigned
from all bias-groups.
Estimating Detector Parameters
First, the detector responses for each of the steps taken are averaged to give us a “mean response” that has a large signal-to-noise ratio and can be used for fitting and DC calculations.
There are two methods of calculating the DC detector parameters, one that assumes the detector is well into transition and that the bias power is constant over the step, and the other that assumes the detector is out of the transition (either super-conducting or normal), and \(R_\mathrm{TES}\) is constant over the step.
The BiasStepAnalysis determines which method should be used based on the bias
voltage level. If the transition
parameter is set to be a tuple (V0, V1),
then the analysis will use the transition method whenever V0 < Vbias < V1.
The parameter can also be set to true/false, which will force the analysis
to use the transition calculation.
In Transition
In the transition, it is assumed that the ratio of \(dI_\mathrm{rat} = \frac{dI_\mathrm{TES}}{dI_\mathrm{bias}}\) is negative due to the loop gain being larger than 1. See Michael Niemack’s thesis (Section 4.3.1) and Emily Grace’s thesis (Section 4.2.4) for the derivation. The bias power, TES current, and TES resistance are then given by
Out of transition
Outside of the transition, we assume that \(dI_\mathrm{rat} > 0\), and using the assumption that R is constant over the step, we have:
API
Take Bias Steps
- sodetlib.operations.bias_steps.take_bgmap(S, cfg, bgs=None, dc_voltage=0.3, step_voltage=0.01, step_duration=0.05, nsteps=20, high_current_mode=True, hcm_wait_time=0, analysis_kwargs=None, dacs='pos', use_waveform=True, show_plots=True, g3_tag=None, enable_compression=False)
Function to easily create a bgmap. This will set all bias group voltages to 0 (since this is best for generating the bg map), and run bias-steps with default parameters optimal for creating a bgmap.
- Parameters
(SmurfControl) (S) – Pysmurf control instance
(DetConfig) (cfg) – Detconfig instance
int (bgs () – Bias groups to run steps on, defaulting to all 12. It is recommended that this isn’t modified unless necessary to create a full bg-map.
list – Bias groups to run steps on, defaulting to all 12. It is recommended that this isn’t modified unless necessary to create a full bg-map.
optional) – Bias groups to run steps on, defaulting to all 12. It is recommended that this isn’t modified unless necessary to create a full bg-map.
(float) (hcm_wait_time) – Step voltage in Low-current-mode units. (i.e. this will be divided by the high-low-ratio before running the steps in high-current mode)
(float) – Duration in seconds of each step
(int) (nsteps) – Number of steps to run
(bool) (high_current_mode) – If true, switches to high-current-mode. If False, leaves in LCM which runs through the bias-line filter, so make sure you extend the step duration to be like >2 sec or something
(float) – Time to wait after switching to high-current-mode.
dacs (str) – Which group of DACs to play bias-steps on. Can be ‘pos’, ‘neg’, or ‘both’
use_waveform (bool) – If True will use the waveform generator instead of stepping DAC’s manually.
(dict (analysis_kwargs) – Keyword arguments to be passed to the BiasStepAnalysis run_analysis function.
optional) – Keyword arguments to be passed to the BiasStepAnalysis run_analysis function.
g3_tag (string, optional) – Tag to attach to g3 stream.
enable_compression (bool, optional) – If True, will tell the smurf-streamer to compress G3Frames. Defaults to False because this dominates frame-processing time for high data-rate streams.
- sodetlib.operations.bias_steps.take_bias_steps(S, cfg, bgs=None, step_voltage=0.05, step_duration=0.05, nsteps=20, high_current_mode=True, hcm_wait_time=3, run_analysis=True, analysis_kwargs=None, dacs='pos', use_waveform=True, channel_mask=None, g3_tag=None, stream_subtype='bias_steps', enable_compression=False)
Takes bias step data at the current DC voltage. Assumes bias lines are already in low-current mode (if they are in high-current this will not run correction). This function runs bias steps and returns a BiasStepAnalysis object, which can be used to easily view and re-analyze data.
This function will first run a “bias group sweep”, running multiple steps on each bias-line one at a time. This data is used to generate a bgmap. After, <nsteps> bias steps are played on all channels simultaneously.
- Parameters
S (SmurfControl) – Pysmurf control instance
cfg (DetConfig) – Detconfig instance
bgs (int, list, optional) – Bias groups to run steps on, defaulting to all 12. Note that the bias-group mapping generated by the bias step analysis will be restricted to the bgs set here so if you only run with a small subset of bias groups, the map might not be correct.
step_voltage (float) – Step voltage in Low-current-mode units. (i.e. this will be divided by the high-low-ratio before running the steps in high-current mode)
step_duration (float) – Duration in seconds of each step
nsteps (int) – Number of steps to run
high_current_mode (bool) – If true, switches to high-current-mode. If False, leaves in LCM which runs through the bias-line filter, so make sure you extend the step duration to be like >2 sec or something
hcm_wait_time (float) – Time to wait after switching to high-current-mode.
dacs – str Which group of DACs to play bias-steps on. Can be ‘pos’, ‘neg’, or ‘both’
run_analysis (bool) – If True, will attempt to run the analysis to calculate DC params and tau_eff. If this fails, the analysis object will still be returned but will not contain all analysis results.
analysis_kwargs (dict, optional) – Keyword arguments to be passed to the BiasStepAnalysis run_analysis function.
channel_mask – np.ndarray, optional Mask containing absolute smurf-channels to write to disk
g3_tag – string, optional Tag to attach to g3 stream.
stream_subtype – optional, string Stream subtype for this operation. This will default to ‘bias_steps’.
enable_compression – bool, optional If True, will tell the smurf-streamer to compress G3Frames. Defaults to False because this dominates frame-processing time for high data-rate streams.
BiasStepAnalysis
The BiasStepAnalysis is the class containing all info pertaining to the bias
steps and analysis. It contains smurf parameters required to run the analysis
(such as S.high_low_current_ratio
, etc.), and analysis products.
Any analysis product that is per-detector will be stored in an array that is
nchans
long, where nchans
is the number of channels being read out at
the time, and is indexed by the “readout channel number” (or index of the
channel in the axis-manager). The mapping from readout channel to absolute
smurf channel number (band * 512 + channel
) can be found in the
bsa.abs_chans
attribute.
- class sodetlib.operations.bias_steps.BiasStepAnalysis(S=None, cfg=None, bgs=None, run_kwargs=None)
Container to manage analysis of bias steps taken with the take_bias_steps function. The main function is
run_analysis
and will do a series of analysis procedures to create a biasgroup map and calculate DC detector parameters and tau_eff:Loads an axis manager with all the data
Finds locations of step edges for each bias group
Creates a bg map using the isolated bg step responses
Gets detector responses of each step and aligns them based on the time of the step
Computes DC params R0, I0, Pj, Si from step responses
Fits exponential to the average step response and estimates tau_eff.
Most analysis inputs and products will be saved to a npy file so they can be loaded and re-analyzed easily on another computer like simons1.
To load data from an saved step file, you can run:
bsa = BiasStepAnalysis.load(<path>)
- tunefile
Path of the tunefile loaded by the pysmurf instance
- Type
path
- high_low_current_ratio
Ratio of high to low current
- Type
float
- R_sh
Shunt resistance loaded into pysmurf at time of creation
- Type
float
- pA_per_phi0
pA_per_phi0, as loaded in pysmurf at time of creation
- Type
float
- rtm_bit_to_volt
Conversion between bias dac bit and volt
- Type
float
- bias_line_resistance
Bias line resistance loaded in pysmurf at time of creation
- Type
float
- high_current_mode
If high-current-mode was used
- Type
bool
- stream_id
stream_id of the streamer this was run on.
- Type
string
- sid
Session-id of streaming session
- Type
int
- start, stop
start and stop time of all steps
- Type
float
- edge_idxs
Array containing indexes (wrt axis manager) of bias group steps for each bg
- Type
array(ints) of shape (nbgs, nsteps)
- edge_signs
Array of signs of each step, denoting whether step is rising or falling
- Type
array(+/-1) of shape (nbgs, nsteps)
- bg_corr
Bias group correlation array, stating likelihood that a given channel belongs on a given bias group determined from the isolated steps
- Type
array (float) of shape (nchans, nbgs)
- bgmap
Map from readout channel to assigned bias group. -1 means not assigned (that the assignment threshold was not met for any of the 12 bgs)
- Type
array (int) of shape (nchans)
- abs_chans
Array of the absolute smurf channel number for each channel in the axis manager.
- Type
array (int) of shape (nchans)
- resp_times
Shared timestamps for each of the step responses in <step_resp> and <mean_resp> with respect to the bg-step location, with the step occuring at t=0.
- Type
array (float) shape (nbgs, npts)
- mean_resp
Step response averaged accross all bias steps for a given channel in Amps.
- Type
array (float) shape (nchans, npts)
- step_resp
Each individual step response for a given channel in amps
- Type
array (float) shape (nchans, nsteps, npts)
- Ibias
DC bias current of each bias group (amps)
- Type
array (float) shape (nbgs)
- Vbias
DC bias voltage of each bias group (volts in low-current mode)
- dIbias
Step current for each bias group (amps)
- Type
array (float) shape (nbgs)
- dVbias
Step voltage for each bias group (volts in low-current mode)
- Type
array (float) shape (nbgs)
- dItes
Array of tes step heigh for each channel (amps)
- Type
array (float) shape (nchans)
- R0
Computed TES resistances for each channel (ohms)
- Type
array (float) shape (nchans)
- I0
Computed TES currents for each channel (amps)
- Type
array (float) shape (nchans)
- Pj
Bias power computed for each channel
- Type
array (float) shape (nchans)
- Si
Responsivity computed for each channel
- Type
array (float) shape (nchans)
- step_fit_tmin
Time after bias step to start fitting exponential (sec)
- Type
float
- step_fit_popts
Optimal fit parameters (A, tau, b) for the exponential fit of each channel
- Type
array (float) of shape (nchans, 3)
- step_fit_pcovs
Fit covariances for each channel
- Type
array (float) shape (nchans, 3, 3)
- tau_eff
Tau_eff for each channel (sec). Same as step_fit_popts[:, 1].
- Type
array (float) shape (nchans)
- R_n_IV
Array of normal resistances for each channel pulled from IV in the device cfg.
- Type
array (float) shape (nchans)
- Rfrac
Rfrac of each channel, determined from R0 and the channel’s normal resistance.
- Type
array (float) shape (nchans)
- run_analysis(create_bg_map=False, assignment_thresh=0.3, save_bg_map=True, arc=None, base_dir='/data/so/timestreams', step_window=0.03, fit_tmin=0.0015, transition=None, R0_thresh=0.03, save=False, bg_map_file=None)
Runs the bias step analysis.
- Parameters
create_bg_map (bool) – If True, will create a bg map from the step data. If False, will use the bgmap from the device cfg
assignment_thresh (float) – Correlation threshold for which channels should be assigned to particular bias groups.
save_bg_map (bool) – If True, will save the created bgmap to disk and set it as the bgmap path in the device cfg.
arc (optional, G3tSmurf) – G3tSmurf archive. If specified, will attempt to load axis-manager using archive instead of sid.
base_dir (optiional, str) – Base directory where timestreams are stored. Defaults to /data/so/timestreams.
step_window (float) – Time after the bias step (in seconds) to use for the analysis.
fit_tmin (float) – tmin used for the fit
transition – (tuple, bool, optional) Range of voltage bias values (in low-cur units) where the “in-transition” resistance calculation should be used. If True, or False, will use in-transition or normal calc for all channels. Will default to
cfg.dev.exp['transition_range']
or (1, 8) if that does not exist or if self._cfg is not set.R0_thresh (float) – Any channel with resistance greater than R0_thresh will be unassigned from its bias group under the assumption that it’s crosstalk
save (bool) – If true will save the analysis to a npy file.
bg_map_file (optional, path) – If create_bg_map is false and this file is not None, use this file to load the bg_map.
References
Below are some valuable references for information on bias steps and their uses:
Daniel Becker’s thesis (Chapter 6)
Michael Niemack’s thesis (Section 4.3.1)
Emily Grace’s thesis (Section 4.2.4)