"""All analog voltages have to go through an ADC at some point to enter the digital world. Often ADCs appear asmulti-channel devices that sample several channels at once. Thus the ADC itself and its channels are representedby seperate classes. The :class:`ADC` class provides a :func:`ADC.measure` function to sample all channels at oncewhile the :class:`ADCChannel` provides a :func:`ADCChannel.measure` method to extract only a single channel from theADC."""from__future__importannotationsfromatomiq.components.primitivesimportComponent,Measurablefromartiq.experimentimportkernelfromartiq.language.typesimportTFloat,TArray,TInt32,TStr,TBoolimportnumpyasnp
[docs]classADC(Component,Measurable):"""An analog-to-ditigal converter (ADC) with multiple channels Many ADCs come with multiple channels that are always sampled together. This class represents such ADCs Args: num_chan: Number of channels the ADC has. """kernel_invariants={"num_chan"}def__init__(self,num_chan:TInt32,*args,**kwargs):Component.__init__(self,*args,**kwargs)self.num_chan=num_chanMeasurable.__init__(self,[f"voltage{i}"foriinrange(self.num_chan)])def_build(self):self.current_sample=np.zeros(self.num_chan,dtype=float)self.current_sample_sum=np.zeros(self.num_chan,dtype=float)@kerneldef_measure(self,target_arr:TArray(TFloat))->TArray(TFloat):raiseNotImplementedError("Implement measure method")
[docs]@kernel(flags={"fast-math"})defmeasure(self,samples:TInt32=1,channel:TStr="")->TArray(TFloat):""" Measures all channels and returns the mean for a given number of subsequent samples. This method advances the timeline by samples * sampling_time Args: samples: number of samples to take and average """# current_sample_sum = np.zeros(self.num_chan, dtype=float)foriinrange(samples):self.current_sample_sum+=self._measure(self.current_sample)self.current_sample_sum/=float(samples)ifchannel=="":returnself.current_sample_sumelse:foriinrange(len(self.channels)):ifself.channels[i]==channel:returnnp.array([self.current_sample_sum[i]])returnnp.array([-1.0])
[docs]classADCChannel(Component,Measurable):kernel_invariants={"adc_device","channel"}def__init__(self,adc_device:ADC,channel:TInt32,*args,**kwargs):"""A single channel of a (possibly multichannel) ADC Args: adc_device: The ADC the channel belongs to channel: The number of the channel """Component.__init__(self,*args,**kwargs)self.adc_device=adc_deviceself.channel=channelMeasurable.__init__(self,["voltage"])