Mock power dataset

[1]:
import pandas as pd
import numpy as np
[2]:
import os
import sys
from radiocalibrationtoolkit import *
[INFO] LFmap: Import successful.
[3]:
# This ensures Plotly output works in multiple places:
# plotly_mimetype: VS Code notebook UI
# notebook: "Jupyter: Export to HTML" command in VS Code
# See https://plotly.com/python/renderers/#multiple-renderers
import plotly.io as pio
pio.renderers.default = "plotly_mimetype+notebook"
[4]:
piko = 1e-12
[5]:
# read HW response
hw_file_path = "./antenna_setup_files/HardwareProfileList_realistic.xml"
# hw_file_path = "./antenna_setup_files/HardwareProfileList_flat.xml"

hw_dict = read_hw_file(hw_file_path, interp_args={"fill_value": "extrapolate"})

hw_reponse_1 = hw_dict["RResponse"]["LNA"]
hw_reponse_2 = hw_dict["RResponse"]["digitizer"]
hw_reponse_3 = hw_dict["RResponse"]["cable_fromLNA2digitizer"]
hw_reponse_4 = hw_dict["RResponse"]["impedance_matching_EW"]

# merge all hw responses to one function
def hw_response_func(x):
    return dB2PowerAmp(
        hw_reponse_1(x) + hw_reponse_2(x) + hw_reponse_3(x) + hw_reponse_4(x)
    )


# impedance function
impedance_func = hw_dict["IImpedance"][
    "antenna_EW"
]

# read sidereal voltage square spectral density
sidereal_voltage2_density_DF = pd.read_csv(
    "./voltage2_density/voltage2_density_Salla_EW_GSM16.csv",
    # "./voltage2_density/voltage2_density_isoAnt_GSM16.csv",
    index_col=0,
)
sidereal_voltage2_density_DF.columns = sidereal_voltage2_density_DF.columns.astype(
    float
)
<?xml version="1.0" encoding="iso-8859-1"?>
<Element HardwareProfileList at 0x7fa19afe2300>
[6]:
def hw_response_func(x):
    return dB2PowerAmp(
        hw_reponse_1(x) + hw_reponse_2(x) + hw_reponse_3(x) + hw_reponse_4(x)
    )
[7]:
mock_trace_generator = Mock_trace_generator(
    sidereal_voltage2_density_DF=sidereal_voltage2_density_DF,
    hw_response_func=hw_response_func,
    impedance_func=impedance_func,
    voltage2ADC=2048,
    time_trace_size=2048,
    sampling_frequency_MHz=250,
)
freq_MHz_bins = mock_trace_generator.get_frequency_bins()
[8]:
additional_noise = 5e-4*piko
number_of_traces = 5000
mock_traces_DF = mock_trace_generator.generate_mock_trace(
    number_of_traces,
    # temp_celsius=30,
    additional_noise=additional_noise,
    # nbi={"67.25": 1},
    # nbi_err=0.3,
    rounding=True
)
100%|███████████████████████████████████████| 5000/5000 [03:11<00:00, 26.14it/s]
[9]:
# system parameters
sampling_frequency_MHz = 250
N = mock_traces_DF.columns[2:].size
ADC2Volts = 1/2048
trace_time_length_sec = N/(sampling_frequency_MHz*1e+6)
[10]:
# FFT to spectra
spectra_df = time_trace_df_2_spectra_df(mock_traces_DF, DSC=2, sampling_frequency_MHz=250)

The power \(P_s\) within band from \(f\) to \(f+\delta f\) is calculated using the following formula:

\begin{equation} P_s = 2\frac{1}{T} \sum_{k=f}^{f+\delta f} \frac{|X(k)|^2}{R(f)} \Delta f \end{equation}

where \(\Delta t\) is the sampling time, \(T\) is the time trace length, \(N\) number of samples, \(f_s\) sampling frequency and \(R\) the impedance,

and \(X(k)\) is defined as

\begin{equation} X(k) = X(k)_{DFT} \Delta t = \frac{X(k)_{DFT}}{fs} \end{equation}

meaning that \(X(k)_{DFT}\) is direct output using discrete Fourier transform on the time trace. Furthermore, this relations hold:

\begin{equation} \Delta f = \frac{fs}{N} = \frac{1}{N\Delta t} = \frac{1}{T} \end{equation}

[11]:
# use the formula, create the integrand first
integrand_df = ((spectra_df* ADC2Volts / (sampling_frequency_MHz*1e+6))**2).divide(
    impedance_func(spectra_df.columns.values)
)

# integrate
mock_power_unbinned_DF = (2 / trace_time_length_sec) *integrate_spectral_density(
    integrand_df,
    # integrated_MHz_bands=np.linspace(0, 125, 126),
    integrated_MHz_bands=np.linspace(30, 81, 52),
    integrating_method='on_discontinuous_function',
)
[12]:
mock_power_unbinned_DF = pd.concat((mock_traces_DF.iloc[:,:2], mock_power_unbinned_DF), axis=1)
[13]:
mock_power_DF = bin_df_rows(mock_power_unbinned_DF, binning_column='lst', bins=list(range(25)))
mock_power_DF.index.name = 'lst'
mock_power_DF = mock_power_DF.drop(['temp_c', 'lst'], axis=1)
[14]:
fig = px.imshow(
    mock_power_DF.T * 1e12, width=600, aspect="cube", color_continuous_scale="jet"
)
fig.update_layout(
    title='<b>Mock power dataset: {} mock traces</b>'.format(number_of_traces),
    xaxis=dict(title="<b>LST</b>", tickprefix="<b>", ticksuffix="</b>", dtick=2),
    yaxis=dict(
        title="<b>frequency [MHz]</b>",
        tickprefix="<b>",
        ticksuffix="</b>",
        range=(30, 80),
        tick0=0,
        dtick=10,
        autorange=False,
    ),
    coloraxis=dict(
        colorbar=dict(
            title=dict(
                text="<b>power [pW]</b>",
                side="right",
            ),
        tickprefix="<b>",
        ticksuffix="</b>",
        ),
    ),
    font=dict(
        # family=font,
        size=20,
        color="black",
    ),
)
fig.update_layout(
    coloraxis=dict(colorbar=dict(title=dict(text="<b>Power [pW]</b>", side="right"))
 ,cmin=0, cmax=20))
fig.show()
[15]:
# mock_power_DF.to_csv('./mock_power_dataset-{}.csv'.format(number_of_traces))
# mock_power_DF.to_csv('./mock_power_dataset-{}_fixed_temp_30C_norounding_flathwgain_isoant.csv'.format(number_of_traces))
# mock_power_DF.to_csv('./mock_power_dataset-{}_fixed_temp_30C_norounding_flathwgain_isoant_extranoise.csv'.format(number_of_traces))
# mock_power_DF.to_csv('./mock_power_dataset-{}_fixed_temp_30C_rounded_flathwgain_isoant.csv'.format(number_of_traces))

# mock_power_DF.to_csv('./mock_power_dataset-{}_fixed_temp_30C_norounding_realhwgain_realant.csv'.format(number_of_traces))
# mock_power_DF.to_csv('./mock_power_dataset-{}_fixed_temp_30C_rounded_realhwgain_realant.csv'.format(number_of_traces))
[ ]:

[ ]: