The Strip Instrument Database

Introduction

Every simulator of a scientific experiment needs an «instrument database», i.e., a way to access the specification of the instrument to be simulated. The kind of information stored in this database is the following:

  • How many detectors are present in the instrument, and what are their characteristics in terms of noise and placement on the focal plane;
  • What is the response of the optical elements, i.e., the so-called beam function;
  • Which frequencies can be measured by each detector (the so-called bandpass);
  • Ect.

Stripeline implements an instrument database using YAML files and two data structures, Detector and Horn, plus some functions to easily access the information in them.

The following example initializes an object of type InstrumentDB with the values referred to the standard STRIP instrument:


julia> db = InstrumentDB()
InstrumentDB(55 horns, 66 detectors)

This command loads the YAML files provided in the Stripeline repository and initializes the db object. As db is a struct, its field can be accessed with the usual dot notation. The two fields in db are focalplane and detectors. They are both dictionaries, associating horn names to Horn objects and detectors IDs to Detector objects, respectively:

julia> db.focalplane["I0"]
Horn I0, module 0 (indigo), STRIP31:
    Orientation: [0.0000, 0.0000, 1.0000]
    FWHM (X/Y): 0.3470 × 0.3440 °
    Spillover: 0.016704 (main), 0.013964 (sub)
    Cross-polarization: 44.53 dB
    Directivity: 54.76 dBi
    Ellipticity: 1.0080

julia> db.detectors[2]
Detector STRIP02 (Q band):
    Center frequency: 43.39 ± 0.13 GHz
    Bandwidth: 7.58 ± 0.87 GHz
    Noise temperature: 31.5 ± 3.92 K
    Knee frequency: 90.0 ± 40.0 mHz (Q), 70.0 ± 40.0 mHz (U)

A number of high-level functions ease the access of the fields in a InstrumentDB object:

  • detector returns a Detector structure, containing the details of a polarimeter;
  • bandpass returns a BandshapeInfo structure, containing the shape of the bandpass of a detector;
  • spectrum returns a SpectrumInfo
  • fknee_hz returns the knee frequency of the 1/f noise for the I, Q, and U signals, adapted to the brightness temperature of the load being observed by the detector;
  • tnoise returns the noise temperature for the I, Q, and U components.

The structure Detector uses three structures to organize its data in a hierarchical way:

All these structures know how to show themselves on the REPL:

julia> db.detectors[2].bandshape
Bandshape:
    Center frequency: 43.39 ± 0.13 GHz
    Bandwidth: 7.58 ± 0.87 GHz
    Frequency range: [38.00, 50.00] GHz (121 points)
    Test ID: [355, 356]
    Analysis ID: 89

julia> db.detectors[2].spectrum
Noise spectrum:
    Slope: I = 0.8585 ± 0.0000, Q = 0.6420 ± 0.0030, U = 0.3680 ± 0.0030
    Knee frequency: I = 0.0 ± 0.0 mHz, Q = 90.0 ± 40.0 mHz, U = 70.0 ± 40.0 mHz
    White noise: Q = 5.0 ± 1.0 mK^2 Hz, U = 2.6 ± 0.6 mK^2 Hz
    System brightness temperature: 20.0 K
    Test ID: 357
    Analysis ID: 15

julia> db.detectors[2].tnoise
Noise temperature:
    Tnoise: 31.5 ± 3.9 K
    Estimates: [26.7, 27.1, 27.6, 28.2, 30.1, 31.1, 32.0, 33.6, 34.0, 35.1, 36.2, 39.7] K
    Test IDs: []
    Analysis IDs: [105, 106]

Some of them have the ability to be plotted using Plots.jl:

julia> using Plots

julia> plot(db.detectors[2].bandshape)
Plot{Plots.GRBackend() n=1}

For more information about the fields in the structures listed above, as well as their meaning, keep reading.

Structures

Stripeline.InstrumentDBType

STRIP instrument database

The "database" contains information about feed horns and polarimeters:

  • The field focalplane is a dictionary (mapping) associating the string identifying a horn (e.g., I0) with a Horn structure;

  • The field detectors is a dictionary associating the ID of the polarimeter (e.g., 2 stands for STRIP02) with a Detector structure.

You should usually create an object of this kind using the default constructor, which parses a set of YAML files containing the real parameters of the instrument.

Examples

julia> db = InstrumentDB();

julia> print("Number of horns in the database: $(length(keys(db.focalplane)))")
Number of horns in the database: 55

julia> print("Number of polarimeters in the database: $(length(keys(db.detectors)))")
Number of polarimeters in the database: 66

Visualization

You can produce a table describing the contents of the instrument database using show and passing text/markdown as MIME type:

db = InstrumentDB()
show(stdout, MIME("text/markdown"), db)

The table can be converted to other formats (HTML, LaTeX, Microsoft Word, …) using commonly-available tools, e.g., Pandoc.

source
Stripeline.HornType

Information about a STRIP horn

This structure holds a number of parameters relative to each feed horn in the STRIP focal plane.

You should initialize Horn objects via the InstrumentDB constructor, which loads their definition from a STRIP instrument database in YAML format.

FieldTypeMeaning
nameStringName of the horn, e.g., I0
idIntUnique number of the horn, starting from 1
polidIntUnique ID of the polarimeter associated with the horn
polarizeridIntUnique ID of the polarizer+OMT associated with the horn
moduleidIntNumber of the horn within the module, from 0 to 6
colorStringName of the color associated with the module
orientationArray{Float64}3D vector containing the orientation of the horn in the sky
fwhm_x_degFloat64FWHM of the beam along the X axis, in degrees
fwhm_y_degFloat64FWHM of the beam along the Y axis, in degrees
main_spilloverFloat64Main reflector spillover
sub_spilloverFloat64Sub-reflector spillover
xpd_dbFloat64Cross-polarization, in dB
directivity_dbiFloat64Directivity, in dBi
ellipticityFloat64Ellipticity
source
Stripeline.DetectorType

Information about a STRIP detector

This structure holds information about a STRIP polarimeter.

You should initialize Detector objects via the InstrumentDB constructor, which loads their definition from a local STRIP instrument database.

FieldTypeMeaning
idIntInteger ID of the polarimeter, e.g., 2 for STRIP02
nameStringFull name of the polarimeter, e.g., STRIP02
bandStringBand: it can either be Q or W
bandshapeBandshapeInfoInformation about the bandpass response
spectrumSpectrumInfoInformation about the noise spectrum (white noise and 1/f noise)
tnoiseNoiseTemperatureInfoInformation about the noise temperature
source
Stripeline.BandshapeInfoType
BandshapeInfo

Information about the spectral band response of a polarimeter.

FieldTypeMeaning
center_frequency_hzFloat64Estimate for the center frequency, in Hz
center_frequency_err_hzFloat64Estimated error on the center frequency, in Hz
bandwidth_hzFloat64Estimated bandwidth, in Hz
bandwidth_err_hzFloat64Estimated error on the bandwidth, in Hz
lowest_frequency_hzFloat64Lowest frequency of the bandshape in response, in Hz
highest_frequency_hzFloat64Highest frequency of the bandshape in response, in Hz
num_of_frequenciesIntNumber of samples in response
bandshapeArray{Float64,1}Profile of the bandshape (pure numbers)
bandshape_errorArray{Float64,1}Estimated error on the profile of the bandshape
test_idArray{Int,1}ID of the unit-level test used to characterize the bandshape
analysis_idIntID of the unit-level analysis used to characterize the bandshape

You can plot a BandshapeInfo object by importing Plots and using plot:

db = InstrumentDB()
plot(bandpass(db, "I0"), show_error = true)

The following keywords are recognized in the call to plot:

  • show_error (default: true): include an error bar.
  • show_centerfreq (default: false): include a vertical bar showing the position of the center frequency
source
Stripeline.bandshapeFunction
bandshape(bandinfo::BandshapeInfo) -> Tuple{Array{Float64, 1}, Array{Float64, 1}}
bandshape(db::InstrumentDB, polid::Integer) -> Tuple{Array{Float64, 1}, Array{Float64, 1}}
bandshape(db::InstrumentDB, horn_name::AbstractString) -> Tuple{Array{Float64, 1}, Array{Float64, 1}}

Return a pair (ν_hz, B, Berr) containing the shape of the bandpass in bandinfo (first form), or the bandpass taken from the instrument database (second and third form). The two elements of the tuple (ν_hz, B) are two arrays of the same length containing the frequencies (in Hz) and the bandpass response at the same frequency (pure number), and they are suitable to be plotted, like in the following example:

db = InstrumentDB()
x, y, err = bandshape(db, "G2")
plot(x, y, ribbon=(err, err))   # Plot the bandpass and the error bar

However, it is easier just to use plot on a BandshapeInfo object.

source
Stripeline.SpectrumInfoType
SpectrumInfo

Information about the noise spectrum of the output of a polarimeter.

FieldTypeMeaning
slope_iFloat64The slope ($\alpha$) of the 1/f component of the noise in the I signal
slope_i_errFloat64Error associated with the value of slope_i
slope_qFloat64Same as slope_i, but for the Q signal
slope_q_errFloat64Error associated with the value of slope_q
slope_uFloat64Same as slope_i, but for the U signal
slope_u_errFloat64Error associated with the value of slope_u
fknee_i_hzFloat64Knee frequency of the I signal, in Hz
fknee_i_err_hzFloat64Error associated with the value of fknee_i_hz
fknee_q_hzFloat64Knee frequency of the Q signal, in Hz
fknee_q_err_hzFloat64Error associated with the value of fknee_q_hz
fknee_u_hzFloat64Knee frequency of the U signal, in Hz
fknee_u_err_hzFloat64Error associated with the value of fknee_u_hz
wn_i_k2_hzFloat64White noise level for the I signal, in K^2 Hz
wn_i_err_k2_hzFloat64Error associated with the value of wn_i_k2_hz
wn_q_k2_hzFloat64White noise level for the Q signal, in K^2 Hz
wn_q_err_k2_hzFloat64Error associated with the value of wn_q_k2_hz
wn_u_k2_hzFloat64White noise level for the U signal, in K^2 Hz
wn_u_err_k2_hzFloat64Error associated with the value of wn_u_k2_hz
i_fit_parameters_k2_hzVector{Float32}Fit coefficients for the I spectrum in K²/Hz, or nothing
q_fit_parameters_k2_hzVector{Float32}Fit coefficients for the Q spectrum in K²/Hz, or nothing
u_fit_parameters_k2_hzVector{Float32}Fit coefficients for the U spectrum in K²/Hz, or nothing
pwr_cov_matrix_k2Symmetric{4}Covariance matrix of the signals Q1, Q2, U1, U2 (PWR) in K² or nothing
dem_cov_matrix_k2Symmetric{4}Covariance matrix of the signals Q1, Q2, U1, U2 (DEM) in K² or nothing
iqu_cov_matrix_k2Symmetric{3}Covariance matrix of I = ∑PWR / 4, Q = (Q1 + Q2) / 2, U = (U1 + U2) / 2
load_temperature_kFloat64System brightness temperature used during the tests (in K)
test_idIntID of the unit-level test used to characterize the bandshape
analysis_idIntID of the unit-level analysis used to characterize the bandshape

You can quickly plot the theoretical shape of the noise power spectrum using plot on a SpectrumInfo object.

source
Stripeline.NoiseTemperatureInfoType
NoiseTemperatureInfo

Information about the noise temperature of a polarimeter. This structure is used for the field tnoise of the Detector struct.

FieldTypeMeaning
tnoise_kFloat64Noise temperature computed from tnoise_values_k, in K
tnoise_err_kFloat64Error associated with tnoise_k, computed from tnoise_values_k
test_idsArray{Int,1}List of unit-level test IDs used to estimate the noise temperature
analysis_idsArray{Int,1}List of unit-level analysis report IDs used to estimate the noise temperature
values_kArray{Float64,1}List of noise temperatures estimated from the tests
source
Stripeline.oof_noise_k2_hzFunction
oof_noise_k2_hz(fit_coeffs::Union{Vector{Float64}, Nothing}, nu)

Compute the amount of power (in K²/Hz) associated with 1/f noise, given a set of fitting coefficients for the function $f(\nu) = \nu^a e^b + e^c$. This is the same as noise_k2_hz, but it returns the 1/f part only.

The fitting coefficients are usually taken from a SpectrumInfo structure, namely in the three fields i_fit_parameters_k2_hz, q_fit_parameters_k2_hz, and u_fit_parameters_k2_hz.

source
Stripeline.white_noise_k2_hzFunction
white_noise_k2_hz(fit_coeffs::Union{Vector{Float64}, Nothing}, nu)

Compute the amount of power (in K²/Hz) associated with white noise, given a set of fitting coefficients for the function $f(\nu) = \nu^a e^b + e^c$. This is the same as noise_k2_hz, but it returns the white noise part only.

The fitting coefficients are usually taken from a SpectrumInfo structure, namely in the three fields i_fit_parameters_k2_hz, q_fit_parameters_k2_hz, and u_fit_parameters_k2_hz.

source
Stripeline.noise_k2_hzFunction
noise_k2_hz(fit_coeffs::Union{Vector{Float64}, Nothing}, nu)

Compute the amount of power (in K²/Hz) associated with 1/f plus white noise, given a set of fitting coefficients for the function $f(\nu) = \nu^a e^b + e^c$. This is the kind of function fitted by the code that analyzed the unit-test data.

The fitting coefficients are usually taken from a SpectrumInfo structure, namely in the three fields i_fit_parameters_k2_hz, q_fit_parameters_k2_hz, and u_fit_parameters_k2_hz.

To compute the 1/f and white noise parts separately, you can use oof_noise_k2_hz and white_noise_k2_hz.

source

High-level access functions

Stripeline.detectorFunction
detector(db::InstrumentDB, polid::Integer) -> Detector
detector(db::InstrumentDB, horn_name::AbstractString) -> Detector

Return a Detector structure, taken from the instrument database. If the form with polid is used, polid is the progressive number of the polarimeter; e.g., for STRIP02, polid == 2. In the second form, you pass the string identifying the horn on the focal plane, e.g., I0, W3, etc.

db = InstrumentDB()
pol1 = detector(db, 16)   # Get information about STRIP16
pol2 = detector(db, "V4") # Get information about the detector connected to horn V4
source
Stripeline.bandpassFunction
bandpass(db::InstrumentDB, polid::Integer) -> BandshapeInfo
bandpass(db::InstrumentDB, horn_name::AbstractString) -> BandshapeInfo

Return a pair (ν_hz, B) containing the bandpass B for the horn with the specified ID (polid) or associated to some horn (horn_name). To understand how polid and horn_name work, see the documentation for detector.

The two elements of the tuple (ν_hz, B) are two arrays of the same length containing the frequencies (in Hz) and the bandpass response at the same frequency (pure number).

db = InstrumentDB()
x, y = bandpass(db, "G2")
plot(x, y)   # Plot the bandpass

See also bandshape.

source
Stripeline.spectrumFunction
spectrum(db::InstrumentDB, polid::Integer) -> SpectrumInfo
spectrum(db::InstrumentDB, horn_name::AbstractString) -> SpectrumInfo

Return a SpectrumInfo object, taken from the instrument database. The meaning of the parameters polid and horn_name is explained in the documentation for detector.

source
Stripeline.fknee_hzFunction
fknee_hz(db::InstrumentDB, polid::Integer; tsys_k = missing) -> Tuple{Float64, Float64, Float64}
fknee_hz(db::InstrumentDB, horn_name::AbstractString; tsys_k = missing) -> Tuple{Float64, Float64, Float64}

Return the knee frequency for the selected detector, taken from the instrument database. The meaning of the parameters polid and horn_name is explained in the documentation for detector.

If tsys_k is specified, the system temperature is rescaled to the desired temperature of the load feeding the polarimeter, so that the 1/f component of the noise remains unchanged but the white noise plateau raises/lowers by an appropriate amount. Otherwise, the function returns the raw frequency taken from the instrument database.

source
Stripeline.tnoiseFunction
tnoise(db::InstrumentDB, polid::Integer) -> NoiseTemperatureInfo
tnoise(db::InstrumentDB, horn_name::AbstractString) -> NoiseTemperatureInfo

Return a NoiseTemperatureInfo object, taken from the instrument database. The meaning of the parameters polid and horn_name is explained in the documentation for detector.

source

Loading custom databases

It is not needed to load the default instrument database, as Stripeline provides a number of additional functions to build mock databases from dictionaries.

Stripeline.defaultdbfolderFunction
defaultdbfolder()

Return a string containing the (local) full path to the YAML files containing the reference instrument DB.

source
Stripeline.parsefpdictFunction
parsefpdict(fpdict)

Return a dictionary associating an horn name (e.g., I0) to a Horn object containing information about some horn in the STRIP focal plane. The information are parsed from fpdict, which should be a dictionary loaded from a YAML file. The default YAML file to be used is located in the folder returned by defaultdbfolder and is usually named strip_focal_plane.yaml

source
Stripeline.parsedetdictFunction
parsedetdict(detdict)

Return a dictionary associating an integer number to a Detector object containing information about the STRIP detector with the corresponding number. The information are parsed from detdict, which should be a dictionary loaded from a YAML file. The default YAML file to be used is located in the folder returned by defaultdbfolder and is usually named strip_detectors.yaml

source