def calc_asd(frame, ts_key, asd_key='ASD', units='temperature'): if frame.type == core.G3FrameType.Scan and \ ts_key in frame.keys(): if units == 'temperature': # 1/rt(2) for uK rtHz to uK rtsec units_factor = (core.G3Units.microkelvin * np.sqrt(core.G3Units.sec) * np.sqrt(2.)) elif units == 'current': # rt(2) because `dfmux.ConvertTimestreamUnits` converts to pA_RMS # when using current units (see spt3g_software/calibration/python/noise_analysis.py) # for more info on this annoying convention. units_factor = (core.G3Units.amp*1e-12 / np.sqrt(core.G3Units.Hz)) / np.sqrt(2.) asd_integral_key = asd_key + '_integral' frame[asd_integral_key] = core.G3MapDouble() frame[asd_key] = core.G3MapVectorDouble() ts = frame[ts_key] psds, freqs = dftutils.get_psd_of_ts_map(ts, pad=False, window_function=windows.boxcar) for bolo in psds.keys(): frame[asd_key][bolo] = np.sqrt(psds[bolo]) / units_factor for bolo in psds.keys(): frame[asd_integral_key][bolo] = np.sum(np.array(psds[bolo])[(freqs>0.01) & (freqs<0.5)]) frame[asd_key]['frequency'] = freqs
def fit_asd(frame, asd_key='InputPSD', params_key='PSDFitParams', min_freq=0, max_freq=60, params0=(200**2, 10**2, 2, 400**2, 0.01), readout_model=False): if frame.type == core.G3FrameType.Scan and asd_key in frame.keys(): for group in frame[asd_key].keys(): if group != 'frequency': if params_key not in frame.keys(): frame[params_key] = core.G3MapVectorDouble() f = np.array(frame[asd_key]['frequency']) / core.G3Units.Hz asd = np.array(frame[asd_key][group]) try: if readout_model: par, cov = curve_fit(full_readout_model, f[(f>min_freq) & (f<max_freq)], asd[(f>min_freq) & (f<max_freq)], bounds=([0, 0, 0], [np.inf, np.inf, np.inf]), p0=params0) else: par, cov = curve_fit(noise_model, f[(f>min_freq) & (f<max_freq)], asd[(f>min_freq) & (f<max_freq)], bounds=([0, 0, 0, 0, 0], [np.inf, np.inf, np.inf, np.inf, 0.1]), p0=params0) except: par = [] # except RuntimeError: # par = [] frame[params_key][group] = par
def _write_precal(self, writer, dets, noise): """Write the calibration frame at the start of an observation. This frame nominally contains "preliminary" values for the detectors. For simulations, this contains the true detector offsets and noise properties. """ qname = "detector_offset" f = core3g.G3Frame(core3g.G3FrameType.Calibration) # Add a vector map for quaternions f[qname] = core3g.G3MapVectorDouble() for k, v in dets.items(): f[qname][k] = core3g.G3VectorDouble(v) if noise is not None: kfreq = "noise_stream_freq" kpsd = "noise_stream_psd" kindx = "noise_stream_index" dstr = "noise_detector_streams" dwt = "noise_detector_weights" f[kfreq] = core3g.G3MapVectorDouble() f[kpsd] = core3g.G3MapVectorDouble() f[kindx] = core3g.G3MapInt() f[dstr] = core3g.G3MapVectorInt() f[dwt] = core3g.G3MapVectorDouble() nse_dets = list(noise.detectors) nse_keys = list(noise.keys) st = dict() wts = dict() for d in nse_dets: st[d] = list() wts[d] = list() for k in nse_keys: f[kfreq][k] = core3g.G3VectorDouble(noise.freq(k).tolist()) f[kpsd][k] = core3g.G3VectorDouble(noise.psd(k).tolist()) f[kindx][k] = int(noise.index(k)) for d in nse_dets: wt = noise.weight(d, k) if wt > 0: st[d].append(noise.index(k)) wts[d].append(wt) for d in nse_dets: f[dstr][d] = core3g.G3VectorInt(st[d]) f[dwt][d] = core3g.G3VectorDouble(wts[d]) writer(f) return
def __call__(self, f): if f.type == core.G3FrameType.Scan: self.detrend_vals = core.G3MapVectorDouble() super().__call__(f) if f.type == core.G3FrameType.Scan: f[self.info] = self.detrend_vals
def UnpackTrackerPointingData(f): ''' Extracts tracker registers relevant to online and offline pointing. Calibration values (offsets and multiplicative constants) are from gcp/control/conf/spt/cal. ''' if f.type != core.G3FrameType.GcpSlow: return t = TrackerPointing() t.time = [tm for tm in f['antenna0']['tracker']['utc'][0]] t.scu_temp = numpy.asarray(f['antenna0']['scu']['temp']) t.features = core.IntVector([f['array']['frame']['features'].value]) t.encoder_off_x = numpy.asarray( [f['antenna0']['tracker']['encoder_off'][0]], dtype=numpy.double) t.encoder_off_y = numpy.asarray( [f['antenna0']['tracker']['encoder_off'][1]], dtype=numpy.double) t.tilts_x = numpy.asarray(f['antenna0']['tracker']['tilt_xy_avg'][0], dtype=numpy.double) t.tilts_y = numpy.asarray(f['antenna0']['tracker']['tilt_xy_avg'][1], dtype=numpy.double) t.refraction = numpy.asarray(f['antenna0']['tracker']['refraction'][0], dtype=numpy.double) t.horiz_mount_x = numpy.asarray(f['antenna0']['tracker']['horiz_mount'][0]) t.horiz_mount_y = numpy.asarray(f['antenna0']['tracker']['horiz_mount'][1]) t.horiz_off_x = numpy.asarray(f['antenna0']['tracker']['horiz_off'][0]) t.horiz_off_y = numpy.asarray(f['antenna0']['tracker']['horiz_off'][1]) t.linsens_avg_l1 = numpy.asarray( f['antenna0']['tracker']['linear_sensor_avg'][0]) t.linsens_avg_l2 = numpy.asarray( f['antenna0']['tracker']['linear_sensor_avg'][1]) t.linsens_avg_r1 = numpy.asarray( f['antenna0']['tracker']['linear_sensor_avg'][2]) t.linsens_avg_r2 = numpy.asarray( f['antenna0']['tracker']['linear_sensor_avg'][3]) t.telescope_temp = numpy.asarray( [f['array']['weather']['airTemperature'].value]) t.telescope_pressure = numpy.asarray( [f['array']['weather']['pressure'].value]) f['TrackerPointing'] = t p = core.G3MapVectorDouble() p['tilts'] = numpy.asarray(f['antenna0']['tracker']['tilts'], dtype=numpy.double) p['flexure'] = numpy.asarray(f['antenna0']['tracker']['flexure'], dtype=numpy.double) p['fixedCollimation'] = numpy.asarray( f['antenna0']['tracker']['fixedCollimation'], dtype=numpy.double) f['OnlinePointingModel'] = p
def average_asd(frame, ts_key, avg_psd_key='AverageASD', bolo_props=None, wiring_map=None, units='temperature', average_per_wafer=True, average_per_band=True, average_per_squid=False): if frame.type == core.G3FrameType.Scan and \ ts_key in frame.keys() and bolo_props is not None: bolo_tgroups = get_template_groups(bolo_props, wiring_map=wiring_map, per_band = average_per_band, per_wafer = average_per_wafer, per_squid = average_per_squid, include_keys = True) pixel_tgroups = get_template_groups(bolo_props, per_band = True, per_pixel = True, per_wafer = True, include_keys=True) if units == 'temperature': # 1/rt(2) for uK rtHz to uK rtsec units_factor = (core.G3Units.microkelvin * np.sqrt(core.G3Units.sec) * np.sqrt(2.)) elif units == 'current': # rt(2) because `dfmux.ConvertTimestreamUnits` converts to pA_RMS # when using current units (see spt3g_software/calibration/python/noise_analysis.py) # for more info on this annoying convention. units_factor = (core.G3Units.amp*1e-12 / np.sqrt(core.G3Units.Hz)) / np.sqrt(2.) frame[avg_psd_key] = core.G3MapVectorDouble() ts = frame[ts_key] psds, freqs = dftutils.get_psd_of_ts_map(ts, pad=False, window_function=windows.boxcar) n_pairs = {} for group_key, bolonames in bolo_tgroups.items(): for bolo in bolonames: # pair-sum/diff are keyed by pixel name, while timestreams are # keyed by bolo name; need to handle both possibilities here. pixel_name = [k for k in pixel_tgroups.keys() if bolo in pixel_tgroups[k]][0] psd_key = None if bolo in frame[ts_key].keys(): psd_key = bolo elif pixel_name in frame[ts_key].keys(): psd_key = pixel_name if psd_key is not None: f_pg = freqs psd_pg = psds[psd_key] asd_pg = np.sqrt(psd_pg) / units_factor # cut psds that are not finite or are zero if np.all(np.isfinite(asd_pg) & (asd_pg>0)): if group_key not in frame[avg_psd_key].keys(): n_pairs[group_key] = 0 frame[avg_psd_key][group_key] = asd_pg else: frame[avg_psd_key][group_key] += asd_pg n_pairs[group_key] += 1 frame[avg_psd_key]['frequency'] = f_pg for group_key in n_pairs.keys(): frame[avg_psd_key][group_key] /= float(n_pairs[group_key])