Source code for microcalorimetry.math.unc_models

# -*- coding: utf-8 -*-
"""
This module contains functions that define uncertainty models for operating calorimeters.

These models can be used as part of the calculate eta function to apply uncertainty models
post correction.

Typically these uncertainty models are inherited from uncertiainties called out in
tech notes, papers, and internal memos.

"""

import numpy as np


[docs] def uA_24mm(f): """ Historical repeatability of NIST's 2.4 mm Type A uncertainty. Accepts frequency in GHz. Taken from the calorimeter matlab code "effcalc.m" on March 2026 Parameters ---------- f : array Frequency in GHz. Returns ------- unc : array Type A uncertainty same shape as f. """ out = f.copy() f_hi = f[f > 29.8] out[f <= 29.8] = 0.001 out[f > 29.8] = 7e-4 + 9e-6 * (f_hi - 24) ** 2 return out
def _unc_typeN( frequencies, RLead: float = 0, RThermistor: float = 200 ) -> tuple[np.array]: """ Get the uncertainties associated with the Type N calorimeter. This function is envoked by the underlying models. This function taken from pat of the effcalc.m matlab function on March 2026. Parameters ---------- frequencies : array Array of frequencies RLead : float, optional Lead resistance of the sensor. The default is 0. RThermistor :float , optional Resistance of the thermistor. The default is 200. Returns ------- uA : np.array Type A uncertainty. uB : np.array Type B uncertainty. Utot : np.array k = 2 total uncertainty. """ FreqAll = frequencies # URefFlag means the DC resistance was measured # calculate DCLoss multiplying factor from RLead epsDC = RLead / (2 * RThermistor) # equation(2) in CPEM 2010 paper # this makes efficiency appear too large and therefore to correct for it, # need to divide by 1 + epsDC(epsDC is positive) # gg = gg / (1 + epsDC) # include this effect in the correction factor # eta = eta_unc * gg uDCLoss50 = RLead / 400 / np.sqrt(3) UNotDC = 1.94e-3 U50 = np.sqrt(UNotDC**2 + (2 * uDCLoss50) ** 2) RefFreqPointer = FreqAll == 0.05 OtherFreqPointer = np.logical_not(RefFreqPointer) # get uncertainty as combination of the 50 MHz and general rule UtotNot50 = 2e-3 + 5.0e-5 * FreqAll + 4.8e-6 * FreqAll**2 Utot = UtotNot50 * OtherFreqPointer + U50 * RefFreqPointer # DC Loss uncertainty from Feb 2012 memo uDCLossNot50 = RLead / 400 / np.sqrt(3) # uDCLoss = uDCLossNot50 * OtherFreqPointer + uDCLoss50 * RefFreqPointer uDCLoss = uDCLossNot50 # determine uA # Type A nanovoltmeter uncertainties from Fred Clague that I am retaining, ue is from g # measurements and unVM is from standard runs # ue = 0.00016; unVM = 0.00015; # random uncertainty from Feb 2012 memo: # Random uncertainty at 0 GHz, 18 GHz, and freq where it goes from flat # to linear uRan0 = 0.00025 uRan18 = 0.0006 fBreak = 5 fNmax = 18 testN1 = FreqAll <= fBreak testN2 = np.logical_not(testN1) uRanm = (uRan18 - uRan0) / (fNmax - fBreak) uRanb = uRan18 - uRanm * fNmax uRanLin = uRanm * FreqAll + uRanb uRan = testN1 * uRan0 + testN2 * uRanLin # uncertainty in determining g for new calorimeters. It will be used with # the old calorimeter as well just to make things simpler. # ugsfit = 0.0005 / np.sqrt(3) # Next line is really reproducibility, not uA # uA = np.sqrt(ue**2 + unVM**2 + ugsfit ^ 2 + uRan**2 + uDCLoss**2) uA = np.sqrt(uRan**2 + uDCLoss**2) # The code originally calculated the type B uncertainties based on the # type A uncertainty and the total uncertainty. # So, if you increase uA, uB would decrease to keep Utot the same. # I want to assign higher uncertainties bases on less repeateable # dc connections.So, to estimate uB, I need to calculate the old # value of uA(from the 2012 memo). uDCLoss2012 = 0.00035 / np.sqrt(3) uA2012 = np.sqrt(uRan**2 + uDCLoss2012**2) # Removed special case for calorimeter N0 # k = 1, not independently specified in memo uB = np.sqrt((Utot / 2) ** 2 - uA2012**2) Utot = 2 * np.sqrt(uA**2 + uB**2) return uA, uB, Utot
[docs] def uA_CN(frequencies, RLead: float = 0, RThermistor: float = 200): """ Get the uncertainties associated with the Type N calorimeter. This function is envoked by the underlying models. This function taken from pat of the effcalc.m matlab function on March 2026. Parameters ---------- frequencies : array Array of frequencies RLead : float, optional Lead resistance of the sensor. The default is 0. RThermistor :float , optional Resistance of the thermistor. The default is 200. Returns ------- uA : np.array Type A uncertainty. uB : np.array Type B uncertainty. Utot : np.array k = 2 total uncertainty. """ uA, _, _ = _unc_typeN(frequencies, RLead, RThermistor) return uA
[docs] def uB_CN(frequencies, RLead: float = 0, RThermistor: float = 200): """ Get the uncertainties associated with the Type N calorimeter. This function is envoked by the underlying models. This function taken from pat of the effcalc.m matlab function on March 2026. Parameters ---------- frequencies : array Array of frequencies RLead : float, optional Lead resistance of the sensor. The default is 0. RThermistor :float , optional Resistance of the thermistor. The default is 200. Returns ------- uA : np.array Type A uncertainty. uB : np.array Type B uncertainty. Utot : np.array k = 2 total uncertainty. """ _, uB, _ = _unc_typeN(frequencies, RLead, RThermistor) return uB