UMN CDMS Wiki archive
start › cdms › k100 › run_summary › run_54 › psd_confusion

In order to study noise PSDs more closely and control more factors (for example, the cuts used to remove pulses), Nick and I worked on Root scripts separate from the processing code that do essentially the same thing to produce noise PSDs from random traces. Nick originally mined the processing code to write the original script.

There are a few understandable and mostly cosmetic differences between the code we have produced and the cdmsbats code:

  • Cuts used. I wrote a simple algorithm for removing pulses - cdmsbats uses a few cuts combined. Since cdmsbats stores the traces not rejected I can reconstruct the cdmsbats cut and use the exact same cut in my code for comparison purposes.
  • Scaling. The configuration script we've been using for cdmsbats assumes certain values for R_feedback, G_loop, and G_driver. For some reason the G_driver values are set to 20 for all phonon channels - in recent data they've actually been 16 for RevC.1, 15 for RevC. At any rate these are known and can be accounted for.
  • Binning. The PSD from a trace (or the average from many traces) is a series of values corresponding to frequencies 0, f_sampling/N_samples, 2*f_sampling/N_samples, … f_sampling/2. In other words the first value corresponds to DC, the final value to the Nyquist frequency, and the step size is f_sampling/N_samples. The number of values in the PSD is N_samples/2+1. The final PSD is written to a histogram, and cdmsbats creates N_samples/2+1 bins between a range of 0 to f_Nyquist. This is wrong, in that the bin separation is not the correct value. Nick chose a full range of 0-binwidth/2 to f_Nyquist+binwidth/2, which gives correct spacing and centers each bin on the correct frequency.
  • DC bin: for some reason cdmsbats sets the DC bin to zero. I have not found where this occurs in the code.

But there is a much stranger difference between the outputs of cdmsbats and my code. Below is an example of the two:

As can be seen there is strong deviation in the high frequencies. It is more clearly seen when the frequency axis is linear:

Here it's clear that in the central region, my PSD is a sort of mirror image of the cdmsbats version reflected across the middle bin.

The cdmsbats version is “cleaner” in that that there are fewer strong peaks in the middle. My version seems to reflect the cdmsbats peaks but in at least one case my version has an additional non-reflected peak.

At low frequencies the agreement is very good (I corrected for the scaling and used the cdmsbats cut but I didn't correct the binning):

At high frequencies the agreement is also good:

With my cut algorithm, the low-frequency tail is higher, which may mean I'm not cutting pulses as effectively:

Studying the code I confirmed that cdmsbats constructs the PSDs in the same way that my code does, essentially following the formula

(although the 2 is not included in the DC bin or the Nyquist bin). The FFT of each raw pulse is created using the same Root tool.

But my search began and ended at a routine called NoiseBuilder::BuildAveragePSD in the file cdmsbats_Prod/BatNoise/NoiseBuilder. This is the function that creates the PSDs but I did not find out how the raw traces are imported into this function or how the final PSD histogram is constructed. So the differences could be related to some modification (e.g. filtering) of the raw traces before calculating the PSD or some manipulations of the PSD result before the final histogram is related. (The latter seems to be the only possible explanation for why the DC bin is dropped by cdmsbats.)

As for the raw traces, Nick and I get them using the BatViewer application, which is used to view pulses from raw data and can also be used to save them to Root files. The noise processing in cdmsbats must use something similar. As mentioned above cdmsbats stores to file the traces that it uses to create the PSDs (i.e. those not rejected by cuts). I compared cdmsbats-stored traces to those saved using BatViewer, to see signs of any filtering that cdmsbats might be doing (assuming that it saves the pulses after such filtering). There is, indeed, a difference:

General trends are the same but there are differences in detail. Listing the sample values reveals a pattern:

sample cdmsbats ADC BatViewer ADC
1 2031 2040
2 2040 2031
3 2043 2026
4 2026 2043
5 2034 2045
6 2045 2034
7 2048 2020
8 2020 2048
9 2046 2046
10 2046 2046
11 2029 2026
12 2026 2029
13 2022 2011
14 2011 2022
15 2039 2034
16 2034 2039
17 2022 2029
18 2029 2022
19 2055 2038

In comparison to the cdmsbats noise processing output trace, in the BatViewer trace every two consecutive values are swapped. Correcting the BatViewer pulse shows that it is identical with the cdmsbats noise pulse:

Is this consecutive-pair swapping an intentional filtering or a mistake in the code reading raw trace data (either the BatViewer version or whatever version the cdmsbats noise processing utilizes)? In cdmsbats_Prod/BatCommon/datareader/PulseData.cxx there may be a clue in the function PulseData::ReadRawPulseRecord:

 // ==== ADC values are paired to make one word, separate them now ===
 for(int pairItr = 1; pairItr <= fNADCBins/2; pairItr++)
 {
    uint32_t twinBinValues = buffer[11+pairItr];
    if(fFlipBytes) twinBinValues = EndianHelper::Swap4ByteWord(twinBinValues);
    uint16_t adc1 = twinBinValues & 0x0000ffff;
    uint16_t adc2 = (twinBinValues & 0xffff0000) >> 16;
 //       printf("word = %#x", twinBinValues);
 //       printf(", adc1 = %#x", adc1);
 //       printf(", adc2 = %#x", adc2);
 //       cout <<", bins " << (pairItr*2)-2 <<" and " << (pairItr*2)-1 << endl;
    fPulseVector.push_back(adc1);
    fPulseVector.push_back(adc2);
 }

Perhaps one version of the data reading code is incorrectly ordering the two halves of the “word” in the raw data. I performed a simple test calculating a PSD from a test time series with a pure sinusoid, and found that if you pair-swap the samples you do indeed get a second peak reflected across the center of the PSD.

By performing a pair-swap on the BatViewer pulses and feeding them into my PSD code I was able to exactly recreate the cdmsbats results:

Conclusions:

  1. The cdmsbats noise processing bins its PSDs wrong. Not a big deal really - it is almost certainly irrelevant to any real use of the PSDs such as filtering.
  2. BatViewer probably reads raw data incorrectly, pair-swapping consecutive samples.