@@ -699,21 +699,25 @@ def dac(self, expanded=False, return_res=64, inplace=False):
699699
700700 return p_signal
701701
702- def calc_adc_params (self ):
702+ def calc_adc_gain_baseline (self , ch , minvals , maxvals ):
703703 """
704- Compute appropriate adc_gain and baseline parameters for adc
705- conversion, given the physical signal and the fmts.
704+ Compute adc_gain and baseline parameters for a given channel.
706705
707706 Parameters
708707 ----------
709- N/A
708+ ch: int
709+ The channel that the adc_gain and baseline are being computed for.
710+ minvals: list
711+ The minimum values for each channel.
712+ maxvals: list
713+ The maximum values for each channel.
710714
711715 Returns
712716 -------
713- adc_gains : list
714- List of calculated `adc_gain` values for each channel.
715- baselines : list
716- List of calculated `baseline` values for each channel.
717+ adc_gain : float
718+ Calculated `adc_gain` value for a given channel.
719+ baseline : int
720+ Calculated `baseline` value for a given channel.
717721
718722 Notes
719723 -----
@@ -728,86 +732,125 @@ def calc_adc_params(self):
728732 int32 `baseline` values, but does not consider over/underflow
729733 for calculated float `adc_gain` values.
730734
735+ """
736+ # Get the minimum and maximum (valid) storage values
737+ dmin , dmax = _digi_bounds (self .fmt [ch ])
738+ # add 1 because the lowest value is used to store nans
739+ dmin = dmin + 1
740+
741+ pmin = minvals [ch ]
742+ pmax = maxvals [ch ]
743+
744+ # Figure out digital samples used to store physical samples
745+
746+ # If the entire signal is NAN, gain/baseline won't be used
747+ if pmin == np .nan :
748+ adc_gain = 1
749+ baseline = 1
750+ # If the signal is just one value, store one digital value.
751+ elif pmin == pmax :
752+ if pmin == 0 :
753+ adc_gain = 1
754+ baseline = 1
755+ else :
756+ # All digital values are +1 or -1. Keep adc_gain > 0
757+ adc_gain = abs (1 / pmin )
758+ baseline = 0
759+ # Regular varied signal case.
760+ else :
761+ # The equation is: p = (d - b) / g
762+
763+ # Approximately, pmax maps to dmax, and pmin maps to
764+ # dmin. Gradient will be equal to, or close to
765+ # delta(d) / delta(p), since intercept baseline has
766+ # to be an integer.
767+
768+ # Constraint: baseline must be between +/- 2**31
769+ adc_gain = (dmax - dmin ) / (pmax - pmin )
770+ baseline = dmin - adc_gain * pmin
771+
772+ # Make adjustments for baseline to be an integer
773+ # This up/down round logic of baseline is to ensure
774+ # there is no overshoot of dmax. Now pmax will map
775+ # to dmax or dmax-1 which is also fine.
776+ if pmin > 0 :
777+ baseline = int (np .ceil (baseline ))
778+ else :
779+ baseline = int (np .floor (baseline ))
780+
781+ # After baseline is set, adjust gain correspondingly.Set
782+ # the gain to map pmin to dmin, and p==0 to baseline.
783+ # In the case where pmin == 0 and dmin == baseline,
784+ # adc_gain is already correct. Avoid dividing by 0.
785+ if dmin != baseline :
786+ adc_gain = (dmin - baseline ) / pmin
787+
788+ # Remap signal if baseline exceeds boundaries.
789+ # This may happen if pmax < 0
790+ if baseline > MAX_I32 :
791+ # pmin maps to dmin, baseline maps to 2**31 - 1
792+ # pmax will map to a lower value than before
793+ adc_gain = (MAX_I32 ) - dmin / abs (pmin )
794+ baseline = MAX_I32
795+ # This may happen if pmin > 0
796+ elif baseline < MIN_I32 :
797+ # pmax maps to dmax, baseline maps to -2**31 + 1
798+ adc_gain = (dmax - MIN_I32 ) / pmax
799+ baseline = MIN_I32
800+
801+ return adc_gain , baseline
802+
803+ def calc_adc_params (self ):
804+ """
805+ Compute appropriate adc_gain and baseline parameters for adc
806+ conversion, given the physical signal and the fmts.
807+
808+ Parameters
809+ ----------
810+ N/A
811+
812+ Returns
813+ -------
814+ adc_gains : list
815+ List of calculated `adc_gain` values for each channel.
816+ baselines : list
817+ List of calculated `baseline` values for each channel
818+
731819 """
732820 adc_gains = []
733821 baselines = []
734822
735- if np .where (np .isinf (self .p_signal ))[0 ].size :
736- raise ValueError ("Signal contains inf. Cannot perform adc." )
823+ if self .p_signal is not None :
824+ if np .where (np .isinf (self .p_signal ))[0 ].size :
825+ raise ValueError ("Signal contains inf. Cannot perform adc." )
737826
738- # min and max ignoring nans, unless whole channel is NAN.
739- # Should suppress warning message.
740- minvals = np .nanmin (self .p_signal , axis = 0 )
741- maxvals = np .nanmax (self .p_signal , axis = 0 )
827+ # min and max ignoring nans, unless whole channel is NAN.
828+ # Should suppress warning message.
829+ minvals = np .nanmin (self .p_signal , axis = 0 )
830+ maxvals = np .nanmax (self .p_signal , axis = 0 )
742831
743- for ch in range (np .shape (self .p_signal )[1 ]):
744- # Get the minimum and maximum (valid) storage values
745- dmin , dmax = _digi_bounds (self .fmt [ch ])
746- # add 1 because the lowest value is used to store nans
747- dmin = dmin + 1
832+ for ch in range (np .shape (self .p_signal )[1 ]):
833+ adc_gain , baseline = self .calc_adc_gain_baseline (ch , minvals , maxvals )
834+ adc_gains .append (adc_gain )
835+ baselines .append (baseline )
748836
749- pmin = minvals [ch ]
750- pmax = maxvals [ch ]
837+ elif self .e_p_signal is not None :
838+ minvals = []
839+ maxvals = []
840+ for ch in self .e_p_signal :
841+ minvals .append (min (x for x in ch if not math .isnan (x )))
842+ maxvals .append (max (x for x in ch if not math .isnan (x )))
751843
752- # Figure out digital samples used to store physical samples
844+ if any (x == math .inf for x in minvals ) or any (x == math .inf for x in maxvals ):
845+ raise ValueError ("Signal contains inf. Cannot perform adc." )
753846
754- # If the entire signal is NAN, gain/baseline won't be used
755- if pmin == np .nan :
756- adc_gain = 1
757- baseline = 1
758- # If the signal is just one value, store one digital value.
759- elif pmin == pmax :
760- if pmin == 0 :
761- adc_gain = 1
762- baseline = 1
763- else :
764- # All digital values are +1 or -1. Keep adc_gain > 0
765- adc_gain = abs (1 / pmin )
766- baseline = 0
767- # Regular varied signal case.
768- else :
769- # The equation is: p = (d - b) / g
770-
771- # Approximately, pmax maps to dmax, and pmin maps to
772- # dmin. Gradient will be equal to, or close to
773- # delta(d) / delta(p), since intercept baseline has
774- # to be an integer.
775-
776- # Constraint: baseline must be between +/- 2**31
777- adc_gain = (dmax - dmin ) / (pmax - pmin )
778- baseline = dmin - adc_gain * pmin
779-
780- # Make adjustments for baseline to be an integer
781- # This up/down round logic of baseline is to ensure
782- # there is no overshoot of dmax. Now pmax will map
783- # to dmax or dmax-1 which is also fine.
784- if pmin > 0 :
785- baseline = int (np .ceil (baseline ))
786- else :
787- baseline = int (np .floor (baseline ))
788-
789- # After baseline is set, adjust gain correspondingly.Set
790- # the gain to map pmin to dmin, and p==0 to baseline.
791- # In the case where pmin == 0 and dmin == baseline,
792- # adc_gain is already correct. Avoid dividing by 0.
793- if dmin != baseline :
794- adc_gain = (dmin - baseline ) / pmin
795-
796- # Remap signal if baseline exceeds boundaries.
797- # This may happen if pmax < 0
798- if baseline > MAX_I32 :
799- # pmin maps to dmin, baseline maps to 2**31 - 1
800- # pmax will map to a lower value than before
801- adc_gain = (MAX_I32 ) - dmin / abs (pmin )
802- baseline = MAX_I32
803- # This may happen if pmin > 0
804- elif baseline < MIN_I32 :
805- # pmax maps to dmax, baseline maps to -2**31 + 1
806- adc_gain = (dmax - MIN_I32 ) / pmax
807- baseline = MIN_I32
808-
809- adc_gains .append (adc_gain )
810- baselines .append (baseline )
847+ for ch , _ in enumerate (self .e_p_signal ):
848+ adc_gain , baseline = self .calc_adc_gain_baseline (ch , minvals , maxvals )
849+ adc_gains .append (adc_gain )
850+ baselines .append (baseline )
851+
852+ else :
853+ raise Exception ('Must supply p_signal or e_p_signal to calc_adc_params' )
811854
812855 return (adc_gains , baselines )
813856
0 commit comments