From fa911d2b1911449975cffeee57c03a0e96ff1e38 Mon Sep 17 00:00:00 2001 From: LukasK13 Date: Tue, 14 Jul 2020 12:01:28 +0200 Subject: [PATCH] Heterodyne output added. --- docs/source/developer/images/Sensor.pdf | Bin 185824 -> 186043 bytes .../source/developer/images/class_diagram.pdf | Bin 126494 -> 126658 bytes esbo_etc/classes/sensor/Heterodyne.py | 216 ++++++++++++------ 3 files changed, 142 insertions(+), 74 deletions(-) diff --git a/docs/source/developer/images/Sensor.pdf b/docs/source/developer/images/Sensor.pdf index c9592e7cfdceed22cdd24b9ff8165e465bc73184..e4c1092313e94496a1d1a16114b7eaf3b59b15e2 100644 GIT binary patch delta 19994 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 delta 19706 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 diff --git a/docs/source/developer/images/class_diagram.pdf b/docs/source/developer/images/class_diagram.pdf index dbfa86985c3ddd2d88c07f0cbf182eccc6463af2..080b711b77350f2fdb674ce61c40ed7d25812a05 100644 GIT binary patch delta 12143 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 Y&B?)$?0OC(iNwvv$%8~qEd`YRUu 1: - for i in range(exp_time.size): - self.__printDetails(t_sys, delta_nu, t_rms[i], t_signal, "t_exp=%.2f s: " % exp_time[i].value) - else: - self.__printDetails(t_sys, delta_nu, t_rms, t_signal, "t_exp=%.2f s: " % exp_time.value) - return snr + delta_nu = t_signal.wl.to(u.Hz, equivalencies=u.spectral()) / (t_signal.wl / self.__common_conf.wl_delta() + 1) + snr = [] + for exp_time_ in exp_time if exp_time.size > 1 else [exp_time]: + # Calculate the RMS background temperature + if self.__n_on is None: + t_rms = 2 * t_sys * self.__kappa / np.sqrt(exp_time_ * delta_nu) + else: + t_rms = t_sys * self.__kappa * np.sqrt(1 + 1 / np.sqrt(self.__n_on)) / np.sqrt(exp_time_ * delta_nu) + # Calculate the SNR + snr_ = t_signal / t_rms + snr.append(snr_.qty[line_ind]) + # Print details + self.__printDetails(t_sys.qty[line_ind], delta_nu[line_ind], t_rms.qty[line_ind], t_signal.qty[line_ind], + "t_exp=%.2f s: " % exp_time_.value) + self.__output(t_signal, t_background, t_rms, "texp_%.2f" % exp_time_.value, snr=snr_) + return u.Quantity(snr) if len(snr) > 1 else u.Quantity(snr[0]) @u.quantity_input(snr=u.dimensionless_unscaled) def calcExpTime(self, background: SpectralQty, signal: SpectralQty, obstruction: float, snr: u.Quantity) -> u.s: @@ -117,28 +120,32 @@ class Heterodyne(ASensor): """ # Calculate the signal and background temperatures t_signal, t_background = self.calcTemperatures(background, signal, obstruction) + line_ind = np.where(t_signal.wl == self.__lambda_line)[0][0] t_sys = 2 * (t_background + self.__receiver_temp) # Calculate the noise bandwidth - delta_nu = self.__lambda_line.to(u.Hz, equivalencies=u.spectral()) / ( - self.__lambda_line / self.__common_conf.wl_delta() + 1) - # Calculate the RMS background temperature - t_rms = t_signal / snr - # Calculate the exposure time - if self.__n_on is None: - exp_time = ((2 * t_sys * self.__kappa / t_rms) ** 2 / delta_nu).decompose() - else: - exp_time = ((t_sys * self.__kappa / t_rms) ** 2 * (1 + 1 / np.sqrt(self.__n_on)) / delta_nu).decompose() - # Print details - if snr.size > 1: - for i in range(snr.size): - self.__printDetails(t_sys, delta_nu, t_rms[i], t_signal, "SNR=%.2f: " % snr[i].value) - else: - self.__printDetails(t_sys, delta_nu, t_rms, t_signal, "SNR=%.2f: " % snr.value) - return exp_time + delta_nu = t_signal.wl.to(u.Hz, equivalencies=u.spectral()) / (t_signal.wl / self.__common_conf.wl_delta() + 1) + exp_time = [] + for snr_ in snr if snr.size > 1 else [snr]: + # Calculate the RMS background temperature + t_rms = t_signal / snr_ + # Calculate the exposure time + if self.__n_on is None: + exp_time_ = ((2 * t_sys * self.__kappa / t_rms) ** 2 / delta_nu) + else: + exp_time_ = ((t_sys * self.__kappa / t_rms) ** 2 * + (1 + 1 / np.sqrt(self.__n_on)) / delta_nu) + exp_time_ = SpectralQty(exp_time_.wl, exp_time_.qty.decompose()) + exp_time.append(exp_time_.qty[line_ind]) + # Print details + self.__printDetails(t_sys.qty[line_ind], delta_nu[line_ind], t_rms.qty[line_ind], t_signal.qty[line_ind], + "SNR=%.2f: " % snr_.value) + self.__output(t_signal, t_background, t_rms, "snr_%.2f" % snr_.value, exp_time=exp_time_) + return u.Quantity(exp_time) if len(exp_time) > 1 else u.Quantity(exp_time[0]) - @u.quantity_input(exp_time="time", snr=u.dimensionless_unscaled, target_brightness=u.mag) + # @u.quantity_input(exp_time="time", snr=u.dimensionless_unscaled, + # target_brightness=[u.mag, u.mag / u.sr]) def calcSensitivity(self, background: SpectralQty, signal: SpectralQty, obstruction: float, exp_time: u.Quantity, - snr: u.Quantity, target_brightness: u.Quantity) -> u.mag: + snr: u.Quantity, target_brightness: u.Quantity) -> [u.mag, u.mag / u.sr]: """ Calculate the sensitivity of the telescope detector combination. @@ -155,7 +162,7 @@ class Heterodyne(ASensor): snr : Quantity The SNR for which the sensitivity time shall be calculated. target_brightness : Quantity - The target brightness in magnitudes. + The target brightness in mag or mag / sr. Returns ------- @@ -164,26 +171,30 @@ class Heterodyne(ASensor): """ # Calculate the signal and background temperatures t_signal, t_background = self.calcTemperatures(background, signal, obstruction) + line_ind = np.where(t_signal.wl == self.__lambda_line)[0][0] t_sys = 2 * (t_background + self.__receiver_temp) # Calculate the noise bandwidth - delta_nu = self.__lambda_line.to(u.Hz, equivalencies=u.spectral()) / ( - self.__lambda_line / self.__common_conf.wl_delta() + 1) - # Calculate the RMS background temperature - if self.__n_on is None: - t_rms = 2 * t_sys * self.__kappa / np.sqrt(exp_time * delta_nu) - else: - t_rms = t_sys * self.__kappa * np.sqrt(1 + 1 / np.sqrt(self.__n_on)) / np.sqrt(exp_time * delta_nu) - # Calculate the limiting signal temperature - t_signal_lim = t_rms * snr - # Print details - if snr.size > 1: - for i in range(snr.size): - self.__printDetails(t_sys, delta_nu, t_rms[i], t_signal_lim[i], - "SNR=%.2f t_exp=%.2f s: " % (snr[i].value, exp_time[i].value)) - else: - self.__printDetails(t_sys, delta_nu, t_rms, t_signal_lim, - "SNR=%.2f t_exp=%.2f s: " % (snr.value, exp_time.value)) - return target_brightness - 2.5 * np.log10(t_signal_lim / t_signal) * u.mag + delta_nu = t_signal.wl.to(u.Hz, equivalencies=u.spectral()) / (t_signal.wl / self.__common_conf.wl_delta() + 1) + sensitivity = [] + for snr_, exp_time_ in zip(snr, exp_time) if snr.size > 1 else zip([snr], [exp_time]): + # Calculate the RMS background temperature + if self.__n_on is None: + t_rms = 2 * t_sys * self.__kappa / np.sqrt(exp_time_ * delta_nu) + else: + t_rms = t_sys * self.__kappa * np.sqrt(1 + 1 / np.sqrt(self.__n_on)) / np.sqrt(exp_time_ * delta_nu) + # Calculate the limiting signal temperature + t_signal_lim = t_rms * snr_ + # Calculate the sensitivity + signal_ratio = t_signal_lim / t_signal + sensitivity_ = SpectralQty(signal_ratio.wl, + target_brightness - 2.5 * np.log10(signal_ratio.qty) * target_brightness.unit) + sensitivity.append(sensitivity_.qty[line_ind]) + # Print details + self.__printDetails(t_sys.qty[line_ind], delta_nu[line_ind], t_rms.qty[line_ind], + t_signal_lim.qty[line_ind], "SNR=%.2f t_exp=%.2f s: " % (snr_.value, exp_time_.value)) + self.__output(t_signal, t_background, t_rms, "snr_%.2f_texp_%.2f" % (snr_.value, exp_time_.value), + sensitivity=sensitivity_) + return u.Quantity(sensitivity) if len(sensitivity) > 1 else u.Quantity(sensitivity[0]) @u.quantity_input(t_sys=u.K, delta_nu=u.Hz, t_rms=u.K, t_signal=u.K) def __printDetails(self, t_sys: u.Quantity, delta_nu: u.Quantity, t_rms: u.Quantity, @@ -214,6 +225,53 @@ class Heterodyne(ASensor): logger.info(prefix + "Antenna temperature: %1.2e K" % t_signal.value) logger.info("-------------------------------------------------------------------------------------------------") + @u.quantity_input(signal=u.electron, background=u.electron, read_noise=u.electron ** 0.5, dark=u.electron) + def __output(self, t_signal: SpectralQty, t_background: SpectralQty, t_rms: SpectralQty, + name: str, snr: SpectralQty = None, exp_time: SpectralQty = None, sensitivity: SpectralQty = None): + """ + Write the signal and the noise in electrons to files. + + Parameters + ---------- + t_signal : SpectralQty + The signal temperature in Kelvins. + t_background : SpectralQty + The background temperature in Kelvins. + t_rms : SpectralQty + The RMS noise temperature in Kelvins. + name : str + The name of the configuration. + snr : SpectralQty + The calculated signal-to-noise ratio per wavelength. + exp_time : SpectralQty + The calculated exposure time per wavelength. + sensitivity : SpectralQty + The calculated sensitivity per wavelength. + + Returns + ------- + """ + # Concatenate the paths + path = os.path.join(self.__common_conf.output.path, name) + try: + os.makedirs(path, exist_ok=True) + except FileExistsError: + logger.warning("Output directory '" + path + "' already exists.") + + res = QTable([t_signal.wl, t_signal.qty, t_background.qty, t_rms.qty], + names=('Wavelength [' + t_signal.wl.unit.to_string() + ']', + 'Signal Temperature [' + t_signal.qty.unit.to_string() + ']', + 'Background Temperature [' + t_background.qty.unit.to_string() + ']', + 'RMS Noise Temperature [' + t_rms.qty.unit.to_string() + ']'), + meta={'name': 'first table'}) + if snr is not None: + res['SNR [-]'] = snr.qty + if exp_time is not None: + res['Exposure Time [' + exp_time.qty.unit.to_string() + ']'] = exp_time.qty + if sensitivity is not None: + res['Sensitivity [' + sensitivity.qty.unit.to_string() + ']'] = sensitivity.qty + res.write(os.path.join(path, "result.csv"), format='ascii.csv', overwrite=True) + def calcTemperatures(self, background: SpectralQty, signal: SpectralQty, obstruction: float): """ Calculate the noise temperatures of the signal and the background radiation. @@ -229,32 +287,42 @@ class Heterodyne(ASensor): Returns ------- - t_signal : u.Quantity - The signal temperature in Kelvins. - t_background : u.Quantity - The background temperature in Kelvins. + t_signal : SpectralQty + The spectral signal temperature in Kelvins. + t_background : SpectralQty + The spectral signal temperature in Kelvins. """ logger.info("Calculating the system temperature.") - t_background = (background.rebin(self.__lambda_line).qty.to( - u.W / (u.m ** 2 * u.Hz * u.sr), equivalencies=u.spectral_density(self.__lambda_line)) * - self.__lambda_line ** 2 / (2 * k_B) * u.sr).decompose() + # Add desired wavelength to wavelength bins + wl_bins = np.sort(np.append(self.__common_conf.wl_bins(), self.__lambda_line)).view(u.Quantity) + signal = signal.rebin(wl_bins) + background = background.rebin(wl_bins) + t_background = SpectralQty(background.wl, background.qty.to(u.W / (u.m ** 2 * u.Hz * u.sr), + equivalencies=u.spectral_density( + background.wl))) + t_background = t_background * (t_background.wl ** 2 / (2 * k_B) * u.sr) + t_background = SpectralQty(t_background.wl, t_background.qty.decompose()) # Calculate the incoming photon current of the target logger.info("Calculating the signal temperature.") size = "extended" if signal.qty.unit.is_equivalent(u.W / (u.m ** 2 * u.nm * u.sr)) else "point" if size == "point": - signal = signal.rebin(self.__lambda_line).qty.to(u.W / (u.m ** 2 * u.Hz), - equivalencies=u.spectral_density(self.__lambda_line)) - t_signal = (signal * self.__aperture_efficiency * self.__common_conf.d_aperture() ** 2 * - np.pi / 4 / (2 * k_B) * self.__eta_fss).decompose() + signal = SpectralQty(signal.wl, signal.qty.to(u.W / (u.m ** 2 * u.Hz), + equivalencies=u.spectral_density(signal.wl))) + t_signal = signal * (self.__aperture_efficiency * self.__common_conf.d_aperture() ** 2 * + np.pi / 4 / (2 * k_B) * self.__eta_fss) + t_signal = SpectralQty(t_signal.wl, t_signal.qty.decompose()) else: - signal = signal.rebin(self.__lambda_line).qty.to(u.W / (u.m ** 2 * u.Hz * u.sr), - equivalencies=u.spectral_density(self.__lambda_line)) - t_signal = (signal * u.sr * self.__main_beam_efficiency * self.__lambda_line ** 2 / ( - 2 * k_B) * self.__eta_fss).decompose() - logger.debug("Signal temperature: %1.2e K" % t_signal.value) + signal = SpectralQty(signal.wl, signal.qty.to(u.W / (u.m ** 2 * u.Hz * u.sr), + equivalencies=u.spectral_density(signal.wl))) + t_signal = signal * (u.sr * self.__main_beam_efficiency * self.__lambda_line ** 2 / ( + 2 * k_B) * self.__eta_fss) + t_signal = SpectralQty(t_signal.wl, t_signal.qty.decompose()) + logger.debug("Spectral signal temperature") + logger.debug(t_signal) logger.debug("Target size: " + size) logger.debug("Obstruction: %.2f" % obstruction) - logger.debug("Background temperature: %1.2e K" % t_background.value) + logger.debug("Spectral background temperature") + logger.debug(t_background) return t_signal, t_background @staticmethod