import numpy as np
from qubic.lib.Instrument.Qacquisition import QubicAcquisition
from qubic.lib.Instrument.Qinstrument import QubicInstrument
[docs]
class QubicNoise:
# gives Qubic noise for one band
def __init__(self, d, band, sampling, scene, rng_noise, duration, comm=None, size=1):
if band != 150 and band != 220:
raise TypeError("Unknown band '{}'.".format(band))
self.rng_noise = rng_noise
self.seed_photon = rng_noise.integers(10000000)
self.seed_detector = rng_noise.integers(10000000)
self.dict = d.copy()
self.dict["TemperatureAtmosphere150"] = None
self.dict["TemperatureAtmosphere220"] = None
self.dict["EmissivityAtmosphere150"] = None
self.dict["EmissivityAtmosphere220"] = None
self.dict["comm"] = comm
self.dict["nprocs_instrument"] = size
self.dict["nprocs_sampling"] = 1
self.dict["band"] = int(band)
self.dict["filter_nu"] = int(band) * 1e9
self.dict["nf_sub"] = 1
self.dict["nf_recon"] = 1
self.dict["period"] = 1
self.dict["type_instrument"] = ""
self.dict["effective_duration"] = duration
# get_pointing(self.dict) and QubicScene(self.dict) don't depend on the params modified here, they can be computed outside the class
self.acq = QubicAcquisition(QubicInstrument(self.dict), sampling, scene, self.dict)
print(f"Duration at {band} GHz is {duration} yrs")
[docs]
def get_noise(self, det_noise, pho_noise):
if det_noise:
n = self.detector_noise()
else:
n = np.zeros((len(self.acq.instrument), len(self.acq.sampling)))
if pho_noise:
n += self.photon_noise()
return n
[docs]
def photon_noise(self, wpho=1):
if wpho == 0:
return np.zeros((len(self.acq.instrument), len(self.acq.sampling)))
else:
return wpho * self.acq.get_noise(det_noise=False, photon_noise=True, seed=self.seed_photon)
[docs]
def detector_noise(self, wdet=1):
if wdet == 0:
return np.zeros((len(self.acq.instrument), len(self.acq.sampling)))
else:
return wdet * self.acq.get_noise(det_noise=True, photon_noise=False, seed=self.seed_detector)
[docs]
class QubicTotNoise:
### Gives Qubic noise for all bands: for UWB, they are coadded; for DB it returns two values
### For MB, it returns only the 150 band noise
def __init__(self, d, sampling, scene):
# we ask for the sampling and scene, as they are already determined when the noise is called
self.type = d["instrument_type"]
self.d = d
self.sampling = sampling
self.scene = scene
self.detector_nep = d["detector_nep"]
if self.type == "DB": # this will later be implemented at a dictionary level!
self.band_used = [150, 220]
self.duration = [d["effective_duration150"], d["effective_duration220"]]
elif self.type == "UWB":
self.band_used = [150, 220]
self.duration = [d["effective_duration150"], d["effective_duration220"]]
elif self.type == "MB": # MonoBand will be the 150 GHz band until further modifications
self.band_used = [150]
self.duration = [d["effective_duration150"]]
else:
raise ValueError("Instrument type {} is not implemented.".format(self.type))
# # if only one duration is given, then it means that both focal planes (if they are two) observed for the same time
# if isinstance(duration, (int, float)):
# self.duration = [duration] * len(self.band_used)
# else:
# if self.type == "UWB" and (duration[0] != duration[1]):
# raise TypeError("The duration for bands 150 and 220 has to be the same for the UWB instrument.")
# self.duration = duration
[docs]
def total_noise(self, wdet, wpho150, wpho220, seed_noise=None):
rng_noise = np.random.default_rng(seed=seed_noise) # The way the randomness is treated is NOT GOOD, if doing more than one run (in parallel for example)
wpho = np.array([wpho150, wpho220])
npho = []
ndet = []
for i, band in enumerate(self.band_used):
QnoiseBand = QubicNoise(
self.d,
band,
self.sampling,
self.scene,
rng_noise=rng_noise,
duration=self.duration[i],
comm=self.d["comm"],
size=self.d["nprocs_instrument"],
)
pho = QnoiseBand.photon_noise(wpho[i])
det = QnoiseBand.detector_noise(wdet)
npho.append(pho)
ndet.append(det)
if self.type == "UWB":
return ndet[0] + npho[0] + npho[1]
elif self.type == "DB":
return np.r_[ndet[0] + npho[0], ndet[1] + npho[1]]
elif self.type == "MB":
return ndet[0] + npho[0]
else:
raise TypeError("Can't build noise for instrument type = {}.".format(self.type))