예제 #1
0
        // This function gates the detector data first, and then demodulates the channels.
        // This means that it can give innacurate results for non-linear combinations
        // of channels that vary appreciably over the TOF. There's another, slower, function
        // DemodulateBlockNL that takes care of this.
        public DemodulatedBlock DemodulateBlock(Block b, DemodulationConfig config)
        {
            // *** copy across the metadata ***
            DemodulatedBlock db = new DemodulatedBlock();

            db.TimeStamp          = b.TimeStamp;
            db.Config             = b.Config;
            db.DemodulationConfig = config;

            // *** extract the gated detector data using the given config ***
            List <GatedDetectorData> gatedDetectorData = new List <GatedDetectorData>();
            int ind = 0;

            foreach (string d in b.detectors)
            {
                GatedDetectorExtractSpec gdes;
                config.GatedDetectorExtractSpecs.TryGetValue(d, out gdes);

                if (gdes != null)
                {
                    gatedDetectorData.Add(GatedDetectorData.ExtractFromBlock(b, gdes));
                    db.DetectorIndices.Add(gdes.Name, ind);
                    ind++;
                    db.DetectorCalibrations.Add(gdes.Name,
                                                ((TOF)((EDMPoint)b.Points[0]).Shot.TOFs[gdes.Index]).Calibration);
                }
            }

            //foreach (KeyValuePair<string, GatedDetectorExtractSpec> spec in config.GatedDetectorExtractSpecs)
            //{
            //    GatedDetectorExtractSpec gate = spec.Value;
            //    gatedDetectorData.Add(GatedDetectorData.ExtractFromBlock(b, gate));
            //    db.DetectorIndices.Add(gate.Name, ind);
            //    ind++;
            //    db.DetectorCalibrations.Add(gate.Name,
            //        ((TOF)((EDMPoint)b.Points[0]).Shot.TOFs[gate.Index]).Calibration);

            //}
            // ** normalise the top detector **
            gatedDetectorData.Add(
                gatedDetectorData[db.DetectorIndices["top"]] / gatedDetectorData[db.DetectorIndices["norm"]]);
            db.DetectorIndices.Add("topNormed", db.DetectorIndices.Count);

            // *** extract the point detector data ***
            List <PointDetectorData> pointDetectorData = new List <PointDetectorData>();

            foreach (string channel in config.PointDetectorChannels)
            {
                pointDetectorData.Add(PointDetectorData.ExtractFromBlock(b, channel));
                // for the moment all single point detector channels are set to have a calibration
                // of 1.0 .
                db.DetectorCalibrations.Add(channel, 1.0);
            }

            // *** build the list of detector data ***
            List <DetectorData> detectorData = new List <DetectorData>();

            for (int i = 0; i < gatedDetectorData.Count; i++)
            {
                detectorData.Add(gatedDetectorData[i]);
            }
            for (int i = 0; i < config.PointDetectorChannels.Count; i++)
            {
                detectorData.Add(pointDetectorData[i]);
                db.DetectorIndices.Add(config.PointDetectorChannels[i], i + gatedDetectorData.Count);
            }

            // calculate the norm FFT
            db.NormFourier = DetectorFT.MakeFT(gatedDetectorData[db.DetectorIndices["norm"]], kFourierAverage);

            // *** demodulate channels ***
            // ** build the list of modulations **
            List <string>   modNames     = new List <string>();
            List <Waveform> modWaveforms = new List <Waveform>();

            foreach (AnalogModulation mod in b.Config.AnalogModulations)
            {
                modNames.Add(mod.Name);
                modWaveforms.Add(mod.Waveform);
            }
            foreach (DigitalModulation mod in b.Config.DigitalModulations)
            {
                modNames.Add(mod.Name);
                modWaveforms.Add(mod.Waveform);
            }
            foreach (TimingModulation mod in b.Config.TimingModulations)
            {
                modNames.Add(mod.Name);
                modWaveforms.Add(mod.Waveform);
            }
            // ** work out the switch state for each point **
            int           blockLength = modWaveforms[0].Length;
            List <bool[]> wfBits      = new List <bool[]>();

            foreach (Waveform wf in modWaveforms)
            {
                wfBits.Add(wf.Bits);
            }
            List <uint> switchStates = new List <uint>(blockLength);

            for (int i = 0; i < blockLength; i++)
            {
                uint switchState = 0;
                for (int j = 0; j < wfBits.Count; j++)
                {
                    if (wfBits[j][i])
                    {
                        switchState += (uint)Math.Pow(2, j);
                    }
                }
                switchStates.Add(switchState);
            }
            // pre-calculate the state signs for each analysis channel
            // the first index selects the analysis channel, the second the switchState
            int numStates = (int)Math.Pow(2, modWaveforms.Count);

            int[,] stateSigns = new int[numStates, numStates];
            for (uint i = 0; i < numStates; i++)
            {
                for (uint j = 0; j < numStates; j++)
                {
                    stateSigns[i, j] = stateSign(j, i);
                }
            }

            // ** the following needs to be done for each detector **
            for (int detector = 0; detector < detectorData.Count; detector++)
            {
                DetectorChannelValues dcv = new DetectorChannelValues();
                for (int i = 0; i < modNames.Count; i++)
                {
                    dcv.SwitchMasks.Add(modNames[i], (uint)(1 << i));
                }
                // * divide the data up into bins according to switch state *
                List <List <double> > statePoints = new List <List <double> >(numStates);
                for (int i = 0; i < numStates; i++)
                {
                    statePoints.Add(new List <double>(blockLength / numStates));
                }
                for (int i = 0; i < blockLength; i++)
                {
                    statePoints[(int)switchStates[i]].Add(detectorData[detector].PointValues[i]);
                }

                // * calculate the channel values *
                int subLength = blockLength / numStates;
                double[,] channelValues = new double[numStates, subLength];
                for (int channel = 0; channel < numStates; channel++)
                {
                    for (int subIndex = 0; subIndex < subLength; subIndex++)
                    {
                        double chanVal = 0;
                        for (int i = 0; i < numStates; i++)
                        {
                            chanVal +=
                                stateSigns[channel, i] * statePoints[i][subIndex];
                        }
                        chanVal /= (double)numStates;
                        channelValues[channel, subIndex] = chanVal;
                    }
                }
                //* calculate the channel means *
                double[] channelMeans = new double[numStates];
                for (int channel = 0; channel < numStates; channel++)
                {
                    double total = 0;
                    for (int i = 0; i < subLength; i++)
                    {
                        total += channelValues[channel, i];
                    }
                    total /= blockLength / numStates;
                    channelMeans[channel] = total;
                }
                dcv.Values = channelMeans;

                //* calculate the channel errors *
                double[] channelErrors = new double[numStates];
                for (int channel = 0; channel < numStates; channel++)
                {
                    double total = 0;
                    for (int i = 0; i < subLength; i++)
                    {
                        total += Math.Pow(channelValues[channel, i] - channelMeans[channel], 2);
                    }
                    total /= subLength * (subLength - 1);
                    total  = Math.Sqrt(total);
                    channelErrors[channel] = total;
                }
                dcv.Errors = channelErrors;

                db.ChannelValues.Add(dcv);
            }

            return(db);
        }