from atomiq.components.primitives import Component, Measurable
from atomiq.components.electronics.adc import ADCChannel
from atomiq.components.basics.calibration import Calibration
from artiq.experiment import kernel
from artiq.language.types import TBool, TFloat, TInt32
[docs]
class Photodiode(Component, Measurable):
"""Abstract class to represent a photodiode as a device to measure light power
"""
def __init__(self, *args, **kwargs):
Component.__init__(self, *args, **kwargs)
Measurable.__init__(self, ["power"])
[docs]
@kernel
def measure(self) -> TFloat:
return self._measure()
[docs]
@kernel
def get_power(self) -> TFloat:
return self.measure()
@kernel
def _measure(self) -> TFloat:
raise NotImplementedError("Implement get_power for your photodiode " + self.identifier)
[docs]
class AnalogPhotodiode(Photodiode):
"""An analog photodiode that gives a voltage proportional to the incidend light power.
Args:
adc_channel: The ADC channel that reads the analog voltage of the photodiode
"""
kernel_invariants = {"adc_channel"}
def __init__(self, adc_channel: ADCChannel, *args, **kwargs):
Photodiode.__init__(self, *args, **kwargs)
self.adc_channel = adc_channel
[docs]
@kernel
def get_power(self, samples: TInt32 = 1, cached: TBool = False) -> TFloat:
return self._measure(samples=samples, cached=cached)
@kernel
def _measure(self, samples: TInt32 = 1, cached: TBool = False) -> TFloat:
return self.adc_channel.measure(samples=samples, cached=cached)
[docs]
class CalibratedPhotodiode(AnalogPhotodiode):
"""An analog photodiode with a power calibration
Args:
adc_channel: The ADC channel that reads the analog voltage of the photodiode
calibration: calibration of the photodiode
"""
kernel_invariants = {"calibration"}
def __init__(self, calibration: Calibration, *args, **kwargs):
AnalogPhotodiode.__init__(self, *args, **kwargs)
self.calibration = calibration
@kernel
def _measure(self, samples: TInt32 = 1, cached: TBool = False) -> TFloat:
""" Get the power incident to the photodiode.
Args:
samples: number of samples to take and average before returning the result (default 1)
cached: If true, the result of the last measurement is returned, otherwise new measurements are taken
(default False)
Returns:
TFloat: Result of the measurement (possibly averaged over several samples)
"""
return self.calibration.transform(self.adc_channel.measure(samples=samples, cached=cached))