Example #1
0
 /* This is a convenient way to add a block, if you're using standard demodulation
  * configurations. This method is thread-safe.
  */
 public void AddBlock(Block b, string[] demodulationConfigs)
 {
     log("Adding block " + b.Config.Settings["cluster"] + " - " + b.Config.Settings["clusterIndex"]);
     BlockDemodulator blockDemodulator = new BlockDemodulator();
     foreach (string dcName in demodulationConfigs)
     {
         DemodulationConfig dc = DemodulationConfig.GetStandardDemodulationConfig(dcName, b);
         DemodulatedBlock dBlock = blockDemodulator.DemodulateBlockNL(b, dc);
         blockStore.AddDBlock(dBlock);
     }
 }
        public TOFChannelSet TOFDemodulateBlock(Block b, int detectorIndex, bool allChannels)
        {
            // *** 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);
            bool[,] stateSigns = new bool[numStates, numStates];
            // make a BlockDemodulator just to use its stateSign code
            // They should probably share a base class.
            BlockDemodulator bd = new BlockDemodulator();
            for (uint i = 0; i < numStates; i++)
            {
                for (uint j = 0; j < numStates; j++)
                {
                    stateSigns[i, j] = (bd.stateSign(j, i) == 1);
                }
            }

            TOFChannelSet tcs = new TOFChannelSet();
            // By setting all channels to false only a limited number of channels are analysed,
            // namely those required to extract the edm (and the correction term). This speeds
            // up the execution enormously when the BlockTOFDemodulator is used by the
            // BlockDemodulator for calculating the non-linear channel combinations.
            //int[] channelsToAnalyse;
            List<int> channelsToAnalyse;
            if (allChannels)
            {
                //channelsToAnalyse = new int[numStates];
                channelsToAnalyse = new List<int>();
                //for (int i = 0; i < numStates; i++) channelsToAnalyse[i] = i;
                for (int i = 0; i < numStates; i++) channelsToAnalyse.Add(i);
            }
            else
            {
                // just the essential channels - this code is a little awkward because, like
                // so many bits of the analysis code, it was added long after the original
                // code was written, and goes against some assumptions that were made back then!
                int bIndex = modNames.IndexOf("B");
                int dbIndex = modNames.IndexOf("DB");
                int eIndex = modNames.IndexOf("E");
                int rf1fIndex = modNames.IndexOf("RF1F");
                int rf2fIndex = modNames.IndexOf("RF2F");
                int rf1aIndex = modNames.IndexOf("RF1A");
                int rf2aIndex = modNames.IndexOf("RF2A");
                int lf1Index = modNames.IndexOf("LF1");
                int lf2Index = modNames.IndexOf("LF2");

                int sigChannel = 0;
                int bChannel = (1 << bIndex);
                int dbChannel = (1 << dbIndex);
                int ebChannel = (1 << eIndex) + (1 << bIndex);
                int edbChannel = (1 << eIndex) + (1 << dbIndex);
                int dbrf1fChannel = (1 << dbIndex) + (1 << rf1fIndex);
                int dbrf2fChannel = (1 << dbIndex) + (1 << rf2fIndex);
                int brf1fChannel = (1 << bIndex) + (1 << rf1fIndex);
                int brf2fChannel = (1 << bIndex) + (1 << rf2fIndex);
                int edbrf1fChannel = (1 << eIndex) + (1 << dbIndex) + (1 << rf1fIndex);
                int edbrf2fChannel = (1 << eIndex) + (1 << dbIndex) + (1 << rf2fIndex);
                int ebdbChannel = (1 << eIndex) + (1 << bIndex) + (1 << dbIndex);
                int rf1fChannel = (1 << rf1fIndex);
                int rf2fChannel = (1 << rf2fIndex);
                int erf1fChannel = (1 << eIndex) + (1 << rf1fIndex);
                int erf2fChannel = (1 << eIndex) + (1 << rf2fIndex);
                int rf1aChannel = (1 << rf1aIndex);
                int rf2aChannel = (1 << rf2aIndex);
                int dbrf1aChannel = (1 << dbIndex) + (1 << rf1aIndex);
                int dbrf2aChannel = (1 << dbIndex) + (1 << rf2aIndex);
                int lf1Channel = (1 << lf1Index);
                int dblf1Channel = (1 << dbIndex) + (1 << lf1Index);

                channelsToAnalyse = new List<int>() { sigChannel, bChannel, dbChannel, ebChannel, edbChannel, dbrf1fChannel,
                    dbrf2fChannel, brf1fChannel, brf2fChannel, edbrf1fChannel, edbrf2fChannel, ebdbChannel,
                    rf1fChannel, rf2fChannel, erf1fChannel, erf2fChannel, rf1aChannel, rf2aChannel, dbrf1aChannel,
                    dbrf2aChannel, lf1Channel, dblf1Channel,
                };

                if (lf2Index != -1) // Index = -1 if "LF2" not found
                {
                    int lf2Channel = (1 << lf2Index);
                    channelsToAnalyse.Add(lf2Channel);
                    int dblf2Channel = (1 << dbIndex) + (1 << lf2Index);
                    channelsToAnalyse.Add(dblf2Channel);
                }

                //channelsToAnalyse = new int[] { bChannel, dbChannel, ebChannel, edbChannel, dbrf1fChannel,
                //    dbrf2fChannel, brf1fChannel, brf2fChannel, edbrf1fChannel, edbrf2fChannel, ebdbChannel,
                //    rf1fChannel, rf2fChannel, erf1fChannel, erf2fChannel, rf1aChannel, rf2aChannel, dbrf1aChannel,
                //    dbrf2aChannel, lf1Channel, dblf1Channel, lf2Channel, dblf2Channel
                //};
            }

            foreach (int channel in channelsToAnalyse)
            {
                // generate the Channel
                TOFChannel tc = new TOFChannel();
                TOF tOn = new TOF();
                TOF tOff = new TOF();
                for (int i = 0; i < blockLength; i++)
                {
                    if (stateSigns[channel, switchStates[i]]) tOn += ((TOF)((EDMPoint)(b.Points[i])).Shot.TOFs[detectorIndex]);
                    else tOff += ((TOF)((EDMPoint)(b.Points[i])).Shot.TOFs[detectorIndex]);
                }
                tOn /= (blockLength / 2);
                tOff /= (blockLength / 2);
                tc.On = tOn;
                tc.Off = tOff;
                // This "if" is to take care of the case of the "SIG" channel, for which there
                // is no off TOF.
                if (tc.Off.Length != 0) tc.Difference = tc.On - tc.Off;
                else tc.Difference = tc.On;

                // add the Channel to the ChannelSet
                List<string> usedSwitches = new List<string>();
                for (int i = 0; i < modNames.Count; i++)
                    if ((channel & (1 << i)) != 0) usedSwitches.Add(modNames[i]);
                string[] channelName = usedSwitches.ToArray();
                // the SIG channel has a special name
                if (channel == 0) channelName = new string[] {"SIG"};
                tcs.AddChannel(channelName, tc);
            }
            // ** add the special channels **

            // extract the TOFChannels that we need.
            TOFChannel c_eb = (TOFChannel)tcs.GetChannel(new string[] { "E", "B" });
            TOFChannel c_edb = (TOFChannel)tcs.GetChannel(new string[] {"E", "DB"});
            TOFChannel c_dbrf1f = (TOFChannel)tcs.GetChannel(new string[] { "DB", "RF1F" });
            TOFChannel c_dbrf2f = (TOFChannel)tcs.GetChannel(new string[] { "DB", "RF2F" });
            TOFChannel c_b = (TOFChannel)tcs.GetChannel(new string[] { "B" });
            TOFChannel c_db = (TOFChannel)tcs.GetChannel(new string[] { "DB" });
            TOFChannel c_sig = (TOFChannel)tcs.GetChannel(new string[] { "SIG" });

            TOFChannel c_brf1f = (TOFChannel)tcs.GetChannel(new string[] { "B", "RF1F" });
            TOFChannel c_brf2f = (TOFChannel)tcs.GetChannel(new string[] { "B", "RF2F" });
            TOFChannel c_edbrf1f = (TOFChannel)tcs.GetChannel(new string[] { "E", "DB", "RF1F" });
            TOFChannel c_edbrf2f = (TOFChannel)tcs.GetChannel(new string[] { "E", "DB", "RF2F" });
            TOFChannel c_ebdb= (TOFChannel)tcs.GetChannel(new string[] { "E", "B", "DB" });

            TOFChannel c_rf1f = (TOFChannel)tcs.GetChannel(new string[] { "RF1F" });
            TOFChannel c_rf2f = (TOFChannel)tcs.GetChannel(new string[] { "RF2F" });

            TOFChannel c_erf1f = (TOFChannel)tcs.GetChannel(new string[] { "E", "RF1F" });
            TOFChannel c_erf2f = (TOFChannel)tcs.GetChannel(new string[] { "E", "RF2F" });

            TOFChannel c_rf1a = (TOFChannel)tcs.GetChannel(new string[] { "RF1A" });
            TOFChannel c_rf2a = (TOFChannel)tcs.GetChannel(new string[] { "RF2A" });
            TOFChannel c_dbrf1a = (TOFChannel)tcs.GetChannel(new string[] { "DB", "RF1A" });
            TOFChannel c_dbrf2a = (TOFChannel)tcs.GetChannel(new string[] { "DB", "RF2A" });

            TOFChannel c_lf1 = (TOFChannel)tcs.GetChannel(new string[] { "LF1" });
            TOFChannel c_dblf1 = (TOFChannel)tcs.GetChannel(new string[] { "DB", "LF1" });

            TOFChannel c_lf2;
            TOFChannel c_dblf2;
            if (modNames.IndexOf("LF2") == -1) // Index = -1 if "LF2" not found
            {
                TOF tofTemp = new TOF();
                TOFChannel tcTemp = new TOFChannel();
                // For many blocks there is no LF2 channel (and hence switch states).
                // To get around this problem I will populate the TOFChannel with "SIG"
                // It will then be obvious in the analysis when LF2 takes on real values.
                for (int i = 0; i < blockLength; i++)
                {
                    tofTemp += ((TOF)((EDMPoint)(b.Points[i])).Shot.TOFs[detectorIndex]);
                }
                tofTemp /= (blockLength / 2);

                tcTemp.On = tofTemp;
                tcTemp.Off = tofTemp;
                tcTemp.Difference = tofTemp;

                c_lf2 = tcTemp;
                c_dblf2 = tcTemp;
            }
            else
            {
                c_lf2 = (TOFChannel)tcs.GetChannel(new string[] { "LF2" });
                c_dblf2 = (TOFChannel)tcs.GetChannel(new string[] { "DB", "LF2" });
            }

            // work out some intermediate terms for the full, corrected edm. The names
            // refer to the joint power of c_db and c_b in the term.
            TOFChannel squaredTerms = (((c_db * c_db) - (c_dbrf1f * c_dbrf1f) - (c_dbrf2f * c_dbrf2f)) * c_eb)
                                        - (c_b * c_db * c_edb);

            // this is missing the term /beta c_db c_ebdb at the moment, mainly because
            // I've no idea what beta should be.
            TOFChannel linearTerms = (c_b * c_dbrf1f * c_edbrf1f) + (c_b * c_dbrf2f * c_edbrf2f)
                - (c_db * c_brf1f * c_edbrf1f) - (c_db * c_brf2f * c_edbrf2f);

            TOFChannel preDenominator = (c_db * c_db * c_db)
                + (c_dbrf1f * c_edb * c_edbrf1f) + (c_dbrf1f * c_edb * c_edbrf1f)
                + (c_dbrf2f * c_edb * c_edbrf2f) + (c_dbrf2f * c_edb * c_edbrf2f)
                - c_db * (
                    (c_dbrf1f * c_dbrf1f) + (c_dbrf2f * c_dbrf2f) + (c_edb * c_edb)
                        + (c_edbrf1f * c_edbrf1f) + (c_edbrf2f * c_edbrf2f)
                    );

            // it's important when working out the non-linear channel
            // combinations to always keep them dimensionless. If you
            // don't you'll run into trouble with integral vs. average
            // signal.
            TOFChannel edmDB = c_eb / c_db;
            tcs.AddChannel(new string[] { "EDMDB" }, edmDB);

            // The corrected edm channel. This should be proportional to the edm phase.
            TOFChannel edmCorrDB = (squaredTerms + linearTerms) / preDenominator;
            tcs.AddChannel(new string[] { "EDMCORRDB" }, edmCorrDB);

            // It's useful to have an estimate of the size of the correction. Here
            // we return the difference between the corrected edm channel and the
            // naive guess, edmDB.
            TOFChannel correctionDB = edmCorrDB - edmDB;
            tcs.AddChannel(new string[] { "CORRDB" }, correctionDB);

            // The "old" correction that just corrects for the E-correlated amplitude change.
            // This is included in the dblocks for debugging purposes.
            TOFChannel correctionDB_old = (c_edb * c_b) / (c_db * c_db);
            tcs.AddChannel(new string[] { "CORRDB_OLD" }, correctionDB_old);

            TOFChannel edmCorrDB_old = edmDB - correctionDB_old;
            tcs.AddChannel(new string[] { "EDMCORRDB_OLD" }, edmCorrDB_old);

            // Normalised RFxF channels.
            TOFChannel rf1fDB = c_rf1f / c_db;
            tcs.AddChannel(new string[] { "RF1FDB" }, rf1fDB);

            TOFChannel rf2fDB = c_rf2f / c_db;
            tcs.AddChannel(new string[] { "RF2FDB" }, rf2fDB);

            // And RFxF.DB channels, again normalised to DB. The naming of these channels is quite
            // unfortunate, but it's just tough.
            TOFChannel rf1fDBDB = c_dbrf1f / c_db;
            tcs.AddChannel(new string[] { "RF1FDBDB" }, rf1fDBDB);

            TOFChannel rf2fDBDB = c_dbrf2f / c_db;
            tcs.AddChannel(new string[] { "RF2FDBDB" }, rf2fDBDB);

            // Normalised RFxAchannels.
            TOFChannel rf1aDB = c_rf1a / c_db;
            tcs.AddChannel(new string[] { "RF1ADB" }, rf1aDB);

            TOFChannel rf2aDB = c_rf2a / c_db;
            tcs.AddChannel(new string[] { "RF2ADB" }, rf2aDB);

            // And RFxA.DB channels, again normalised to DB. The naming of these channels is quite
            // unfortunate, but it's just tough.
            TOFChannel rf1aDBDB = c_dbrf1a / c_db;
            tcs.AddChannel(new string[] { "RF1ADBDB" }, rf1aDBDB);

            TOFChannel rf2aDBDB = c_dbrf2a / c_db;
            tcs.AddChannel(new string[] { "RF2ADBDB" }, rf2aDBDB);

            // the E.RFxF channels, normalized to DB
            TOFChannel erf1fDB = c_erf1f / c_db;
            tcs.AddChannel(new string[] { "ERF1FDB" }, erf1fDB);

            TOFChannel erf2fDB = c_erf2f / c_db;
            tcs.AddChannel(new string[] { "ERF2FDB" }, erf2fDB);

            // the E.RFxF.DB channels, normalized to DB, again dodgy naming convention.
            TOFChannel erf1fDBDB = c_edbrf1f / c_db;
            tcs.AddChannel(new string[] { "ERF1FDBDB" }, erf1fDBDB);

            TOFChannel erf2fDBDB = c_edbrf2f / c_db;
            tcs.AddChannel(new string[] { "ERF2FDBDB" }, erf2fDBDB);

            // the LF1 channel, normalized to DB
            TOFChannel lf1DB = c_lf1 / c_db;
            tcs.AddChannel(new string[] { "LF1DB" }, lf1DB);

            TOFChannel lf1DBDB = c_dblf1 / c_db;
            tcs.AddChannel(new string[] { "LF1DBDB" }, lf1DBDB);

            // the LF2 channel, normalized to DB
            TOFChannel lf2DB = c_lf2 / c_db;
            tcs.AddChannel(new string[] { "LF2DB" }, lf2DB);

            TOFChannel lf2DBDB = c_dblf2 / c_db;
            tcs.AddChannel(new string[] { "LF2DBDB" }, lf2DBDB);

            TOFChannel bDB = c_b / c_db;
            tcs.AddChannel(new string[] { "BDB" }, bDB);

            // we also need to extract the rf-step induced phase shifts. These come out in the
            // B.RFxF channels, but like the edm, need to be corrected. I'm going to use just the
            // simplest level of correction for these.

            TOFChannel brf1fCorrDB = (c_brf1f / c_db) - ((c_b * c_dbrf1f) / (c_db * c_db));
            tcs.AddChannel(new string[] { "BRF1FCORRDB" }, brf1fCorrDB);

            TOFChannel brf2fCorrDB = (c_brf2f / c_db) - ((c_b * c_dbrf2f) / (c_db * c_db));
            tcs.AddChannel(new string[] { "BRF2FCORRDB" }, brf2fCorrDB);

            //Some extra channels for various shot noise calculations, these are a bit weird

            tcs.AddChannel(new string[] { "SIGNL" }, c_sig);

            tcs.AddChannel(new string[] { "ONEOVERDB" }, 1/c_db);

            TOFChannel dbSigNL = new TOFChannel();
            dbSigNL.On = c_db.On/c_sig.On;
            dbSigNL.Off = c_db.Off/c_sig.On;;
            dbSigNL.Difference = c_db.Difference / c_sig.Difference;
            tcs.AddChannel(new string[] { "DBSIG" }, dbSigNL);

            TOFChannel dbdbSigSigNL = dbSigNL * dbSigNL;
            tcs.AddChannel(new string[] { "DBDBSIGSIG" }, dbdbSigSigNL);

            TOFChannel SigdbdbNL = new TOFChannel();
            SigdbdbNL.On = c_sig.On / ( c_db.On* c_db.On);
            SigdbdbNL.Off = c_sig.On / ( c_db.Off * c_db.Off);
            SigdbdbNL.Difference = c_sig.Difference / (c_db.Difference * c_db.Difference);
            tcs.AddChannel(new string[] { "SIGDBDB" }, SigdbdbNL);
            return tcs;
        }
Example #3
0
        // Somewhere for SirCachealot to store test results that's accessible by Mathematica.
        // Makes debugging easier and is needed as a workaround for the constant Mathematica
        // NET/Link errors.
        //        public TOFChannelSetGroup ChanSetGroup;
        // workarounds for NET/Link bugs
        //public TOFChannelSet GetAveragedChannelSet(bool eSign, bool bSign, bool rfSign)
        //{
        //    return ChanSetGroup.AverageChannelSetSignedByMachineState(eSign, bSign, rfSign);
        //}
        //public void LoadChannelSetGroup(string path)
        //{
        //    BinaryFormatter bf = new BinaryFormatter();
        //    FileStream fs = new FileStream(path, FileMode.Open);
        //    ChanSetGroup = (TOFChannelSetGroup)bf.Deserialize(fs);
        //    fs.Close();
        //}
        public void Test1()
        {
            BlockSerializer bs = new BlockSerializer();
            Block b = bs.DeserializeBlockFromZippedXML(
                "C:\\Users\\jony\\Files\\Data\\SEDM\\v3\\2009\\October2009\\01Oct0900_0.zip", "block.xml");

            BlockDemodulator bd = new BlockDemodulator();

            DemodulatedBlock db = bd.DemodulateBlockNL(b,
                DemodulationConfig.GetStandardDemodulationConfig("cgate11Fixed", b));

            //JsonSerializer serializer = new JsonSerializer();
            //using (StreamWriter sw = new StreamWriter("c:\\Users\\jony\\Desktop\\test.json"))
            //using (JsonWriter writer = new JsonTextWriter(sw))
            //{
            //    serializer.Serialize(writer, b.Config);
            //}

            //bs.SerializeBlockAsJSON("c:\\Users\\jony\\Desktop\\test.json", b);
        }
Example #4
0
        public TOFChannelSet TOFDemodulateBlock(Block b, int detectorIndex, bool allChannels)
        {
            // *** 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);

            bool[,] stateSigns = new bool[numStates, numStates];
            // make a BlockDemodulator just to use its stateSign code
            // They should probably share a base class.
            BlockDemodulator bd = new BlockDemodulator();

            for (uint i = 0; i < numStates; i++)
            {
                for (uint j = 0; j < numStates; j++)
                {
                    stateSigns[i, j] = (bd.stateSign(j, i) == 1);
                }
            }

            TOFChannelSet tcs = new TOFChannelSet();
            // By setting all channels to false only a limited number of channels are analysed,
            // namely those required to extract the edm (and the correction term). This speeds
            // up the execution enormously when the BlockTOFDemodulator is used by the
            // BlockDemodulator for calculating the non-linear channel combinations.
            //int[] channelsToAnalyse;
            List <int> channelsToAnalyse;

            if (allChannels)
            {
                //channelsToAnalyse = new int[numStates];
                channelsToAnalyse = new List <int>();
                //for (int i = 0; i < numStates; i++) channelsToAnalyse[i] = i;
                for (int i = 0; i < numStates; i++)
                {
                    channelsToAnalyse.Add(i);
                }
            }
            else
            {
                // just the essential channels - this code is a little awkward because, like
                // so many bits of the analysis code, it was added long after the original
                // code was written, and goes against some assumptions that were made back then!
                int bIndex    = modNames.IndexOf("B");
                int dbIndex   = modNames.IndexOf("DB");
                int eIndex    = modNames.IndexOf("E");
                int rf1fIndex = modNames.IndexOf("RF1F");
                int rf2fIndex = modNames.IndexOf("RF2F");
                int rf1aIndex = modNames.IndexOf("RF1A");
                int rf2aIndex = modNames.IndexOf("RF2A");
                int lf1Index  = modNames.IndexOf("LF1");
                int lf2Index  = modNames.IndexOf("LF2");

                int bChannel       = (1 << bIndex);
                int dbChannel      = (1 << dbIndex);
                int ebChannel      = (1 << eIndex) + (1 << bIndex);
                int edbChannel     = (1 << eIndex) + (1 << dbIndex);
                int dbrf1fChannel  = (1 << dbIndex) + (1 << rf1fIndex);
                int dbrf2fChannel  = (1 << dbIndex) + (1 << rf2fIndex);
                int brf1fChannel   = (1 << bIndex) + (1 << rf1fIndex);
                int brf2fChannel   = (1 << bIndex) + (1 << rf2fIndex);
                int edbrf1fChannel = (1 << eIndex) + (1 << dbIndex) + (1 << rf1fIndex);
                int edbrf2fChannel = (1 << eIndex) + (1 << dbIndex) + (1 << rf2fIndex);
                int ebdbChannel    = (1 << eIndex) + (1 << bIndex) + (1 << dbIndex);
                int rf1fChannel    = (1 << rf1fIndex);
                int rf2fChannel    = (1 << rf2fIndex);
                int erf1fChannel   = (1 << eIndex) + (1 << rf1fIndex);
                int erf2fChannel   = (1 << eIndex) + (1 << rf2fIndex);
                int rf1aChannel    = (1 << rf1aIndex);
                int rf2aChannel    = (1 << rf2aIndex);
                int dbrf1aChannel  = (1 << dbIndex) + (1 << rf1aIndex);
                int dbrf2aChannel  = (1 << dbIndex) + (1 << rf2aIndex);
                int lf1Channel     = (1 << lf1Index);
                int dblf1Channel   = (1 << dbIndex) + (1 << lf1Index);

                channelsToAnalyse = new List <int>()
                {
                    bChannel, dbChannel, ebChannel, edbChannel, dbrf1fChannel,
                    dbrf2fChannel, brf1fChannel, brf2fChannel, edbrf1fChannel, edbrf2fChannel, ebdbChannel,
                    rf1fChannel, rf2fChannel, erf1fChannel, erf2fChannel, rf1aChannel, rf2aChannel, dbrf1aChannel,
                    dbrf2aChannel, lf1Channel, dblf1Channel,
                };

                if (lf2Index != -1) // Index = -1 if "LF2" not found
                {
                    int lf2Channel = (1 << lf2Index);
                    channelsToAnalyse.Add(lf2Channel);
                    int dblf2Channel = (1 << dbIndex) + (1 << lf2Index);
                    channelsToAnalyse.Add(dblf2Channel);
                }

                //channelsToAnalyse = new int[] { bChannel, dbChannel, ebChannel, edbChannel, dbrf1fChannel,
                //    dbrf2fChannel, brf1fChannel, brf2fChannel, edbrf1fChannel, edbrf2fChannel, ebdbChannel,
                //    rf1fChannel, rf2fChannel, erf1fChannel, erf2fChannel, rf1aChannel, rf2aChannel, dbrf1aChannel,
                //    dbrf2aChannel, lf1Channel, dblf1Channel, lf2Channel, dblf2Channel
                //};
            }

            foreach (int channel in channelsToAnalyse)
            {
                // generate the Channel
                TOFChannel tc   = new TOFChannel();
                TOF        tOn  = new TOF();
                TOF        tOff = new TOF();
                for (int i = 0; i < blockLength; i++)
                {
                    if (stateSigns[channel, switchStates[i]])
                    {
                        tOn += ((TOF)((EDMPoint)(b.Points[i])).Shot.TOFs[detectorIndex]);
                    }
                    else
                    {
                        tOff += ((TOF)((EDMPoint)(b.Points[i])).Shot.TOFs[detectorIndex]);
                    }
                }
                tOn   /= (blockLength / 2);
                tOff  /= (blockLength / 2);
                tc.On  = tOn;
                tc.Off = tOff;
                // This "if" is to take care of the case of the "SIG" channel, for which there
                // is no off TOF.
                if (tc.Off.Length != 0)
                {
                    tc.Difference = tc.On - tc.Off;
                }
                else
                {
                    tc.Difference = tc.On;
                }

                // add the Channel to the ChannelSet
                List <string> usedSwitches = new List <string>();
                for (int i = 0; i < modNames.Count; i++)
                {
                    if ((channel & (1 << i)) != 0)
                    {
                        usedSwitches.Add(modNames[i]);
                    }
                }
                string[] channelName = usedSwitches.ToArray();
                // the SIG channel has a special name
                if (channel == 0)
                {
                    channelName = new string[] { "SIG" }
                }
                ;
                tcs.AddChannel(channelName, tc);
            }
            // ** add the special channels **

            // extract the TOFChannels that we need.
            TOFChannel c_eb      = (TOFChannel)tcs.GetChannel(new string[] { "E", "B" });
            TOFChannel c_edb     = (TOFChannel)tcs.GetChannel(new string[] { "E", "DB" });
            TOFChannel c_dbrf1f  = (TOFChannel)tcs.GetChannel(new string[] { "DB", "RF1F" });
            TOFChannel c_dbrf2f  = (TOFChannel)tcs.GetChannel(new string[] { "DB", "RF2F" });
            TOFChannel c_b       = (TOFChannel)tcs.GetChannel(new string[] { "B" });
            TOFChannel c_db      = (TOFChannel)tcs.GetChannel(new string[] { "DB" });
            TOFChannel c_brf1f   = (TOFChannel)tcs.GetChannel(new string[] { "B", "RF1F" });
            TOFChannel c_brf2f   = (TOFChannel)tcs.GetChannel(new string[] { "B", "RF2F" });
            TOFChannel c_edbrf1f = (TOFChannel)tcs.GetChannel(new string[] { "E", "DB", "RF1F" });
            TOFChannel c_edbrf2f = (TOFChannel)tcs.GetChannel(new string[] { "E", "DB", "RF2F" });
            TOFChannel c_ebdb    = (TOFChannel)tcs.GetChannel(new string[] { "E", "B", "DB" });

            TOFChannel c_rf1f = (TOFChannel)tcs.GetChannel(new string[] { "RF1F" });
            TOFChannel c_rf2f = (TOFChannel)tcs.GetChannel(new string[] { "RF2F" });

            TOFChannel c_erf1f = (TOFChannel)tcs.GetChannel(new string[] { "E", "RF1F" });
            TOFChannel c_erf2f = (TOFChannel)tcs.GetChannel(new string[] { "E", "RF2F" });

            TOFChannel c_rf1a   = (TOFChannel)tcs.GetChannel(new string[] { "RF1A" });
            TOFChannel c_rf2a   = (TOFChannel)tcs.GetChannel(new string[] { "RF2A" });
            TOFChannel c_dbrf1a = (TOFChannel)tcs.GetChannel(new string[] { "DB", "RF1A" });
            TOFChannel c_dbrf2a = (TOFChannel)tcs.GetChannel(new string[] { "DB", "RF2A" });

            TOFChannel c_lf1   = (TOFChannel)tcs.GetChannel(new string[] { "LF1" });
            TOFChannel c_dblf1 = (TOFChannel)tcs.GetChannel(new string[] { "DB", "LF1" });

            TOFChannel c_lf2;
            TOFChannel c_dblf2;

            if (modNames.IndexOf("LF2") == -1) // Index = -1 if "LF2" not found
            {
                TOF        tofTemp = new TOF();
                TOFChannel tcTemp  = new TOFChannel();
                // For many blocks there is no LF2 channel (and hence switch states).
                // To get around this problem I will populate the TOFChannel with "SIG"
                // It will then be obvious in the analysis when LF2 takes on real values.
                for (int i = 0; i < blockLength; i++)
                {
                    tofTemp += ((TOF)((EDMPoint)(b.Points[i])).Shot.TOFs[detectorIndex]);
                }
                tofTemp /= (blockLength / 2);

                tcTemp.On         = tofTemp;
                tcTemp.Off        = tofTemp;
                tcTemp.Difference = tofTemp;

                c_lf2   = tcTemp;
                c_dblf2 = tcTemp;
            }
            else
            {
                c_lf2   = (TOFChannel)tcs.GetChannel(new string[] { "LF2" });
                c_dblf2 = (TOFChannel)tcs.GetChannel(new string[] { "DB", "LF2" });
            }



            // work out some intermediate terms for the full, corrected edm. The names
            // refer to the joint power of c_db and c_b in the term.
            TOFChannel squaredTerms = (((c_db * c_db) - (c_dbrf1f * c_dbrf1f) - (c_dbrf2f * c_dbrf2f)) * c_eb)
                                      - (c_b * c_db * c_edb);

            // this is missing the term /beta c_db c_ebdb at the moment, mainly because
            // I've no idea what beta should be.
            TOFChannel linearTerms = (c_b * c_dbrf1f * c_edbrf1f) + (c_b * c_dbrf2f * c_edbrf2f)
                                     - (c_db * c_brf1f * c_edbrf1f) - (c_db * c_brf2f * c_edbrf2f);

            TOFChannel preDenominator = (c_db * c_db * c_db)
                                        + (c_dbrf1f * c_edb * c_edbrf1f) + (c_dbrf1f * c_edb * c_edbrf1f)
                                        + (c_dbrf2f * c_edb * c_edbrf2f) + (c_dbrf2f * c_edb * c_edbrf2f)
                                        - c_db * (
                (c_dbrf1f * c_dbrf1f) + (c_dbrf2f * c_dbrf2f) + (c_edb * c_edb)
                + (c_edbrf1f * c_edbrf1f) + (c_edbrf2f * c_edbrf2f)
                );

            // it's important when working out the non-linear channel
            // combinations to always keep them dimensionless. If you
            // don't you'll run into trouble with integral vs. average
            // signal.
            TOFChannel edmDB = c_eb / c_db;

            tcs.AddChannel(new string[] { "EDMDB" }, edmDB);

            // The corrected edm channel. This should be proportional to the edm phase.
            TOFChannel edmCorrDB = (squaredTerms + linearTerms) / preDenominator;

            tcs.AddChannel(new string[] { "EDMCORRDB" }, edmCorrDB);

            // It's useful to have an estimate of the size of the correction. Here
            // we return the difference between the corrected edm channel and the
            // naive guess, edmDB.
            TOFChannel correctionDB = edmCorrDB - edmDB;

            tcs.AddChannel(new string[] { "CORRDB" }, correctionDB);

            // The "old" correction that just corrects for the E-correlated amplitude change.
            // This is included in the dblocks for debugging purposes.
            TOFChannel correctionDB_old = (c_edb * c_b) / (c_db * c_db);

            tcs.AddChannel(new string[] { "CORRDB_OLD" }, correctionDB_old);

            TOFChannel edmCorrDB_old = edmDB - correctionDB_old;

            tcs.AddChannel(new string[] { "EDMCORRDB_OLD" }, edmCorrDB_old);

            // Normalised RFxF channels.
            TOFChannel rf1fDB = c_rf1f / c_db;

            tcs.AddChannel(new string[] { "RF1FDB" }, rf1fDB);

            TOFChannel rf2fDB = c_rf2f / c_db;

            tcs.AddChannel(new string[] { "RF2FDB" }, rf2fDB);

            // And RFxF.DB channels, again normalised to DB. The naming of these channels is quite
            // unfortunate, but it's just tough.
            TOFChannel rf1fDBDB = c_dbrf1f / c_db;

            tcs.AddChannel(new string[] { "RF1FDBDB" }, rf1fDBDB);

            TOFChannel rf2fDBDB = c_dbrf2f / c_db;

            tcs.AddChannel(new string[] { "RF2FDBDB" }, rf2fDBDB);

            // Normalised RFxAchannels.
            TOFChannel rf1aDB = c_rf1a / c_db;

            tcs.AddChannel(new string[] { "RF1ADB" }, rf1aDB);

            TOFChannel rf2aDB = c_rf2a / c_db;

            tcs.AddChannel(new string[] { "RF2ADB" }, rf2aDB);

            // And RFxA.DB channels, again normalised to DB. The naming of these channels is quite
            // unfortunate, but it's just tough.
            TOFChannel rf1aDBDB = c_dbrf1a / c_db;

            tcs.AddChannel(new string[] { "RF1ADBDB" }, rf1aDBDB);

            TOFChannel rf2aDBDB = c_dbrf2a / c_db;

            tcs.AddChannel(new string[] { "RF2ADBDB" }, rf2aDBDB);

            // the E.RFxF channels, normalized to DB
            TOFChannel erf1fDB = c_erf1f / c_db;

            tcs.AddChannel(new string[] { "ERF1FDB" }, erf1fDB);

            TOFChannel erf2fDB = c_erf2f / c_db;

            tcs.AddChannel(new string[] { "ERF2FDB" }, erf2fDB);

            // the E.RFxF.DB channels, normalized to DB, again dodgy naming convention.
            TOFChannel erf1fDBDB = c_edbrf1f / c_db;

            tcs.AddChannel(new string[] { "ERF1FDBDB" }, erf1fDBDB);

            TOFChannel erf2fDBDB = c_edbrf2f / c_db;

            tcs.AddChannel(new string[] { "ERF2FDBDB" }, erf2fDBDB);

            // the LF1 channel, normalized to DB
            TOFChannel lf1DB = c_lf1 / c_db;

            tcs.AddChannel(new string[] { "LF1DB" }, lf1DB);

            TOFChannel lf1DBDB = c_dblf1 / c_db;

            tcs.AddChannel(new string[] { "LF1DBDB" }, lf1DBDB);

            // the LF2 channel, normalized to DB
            TOFChannel lf2DB = c_lf2 / c_db;

            tcs.AddChannel(new string[] { "LF2DB" }, lf2DB);

            TOFChannel lf2DBDB = c_dblf2 / c_db;

            tcs.AddChannel(new string[] { "LF2DBDB" }, lf2DBDB);

            TOFChannel bDB = c_b / c_db;

            tcs.AddChannel(new string[] { "BDB" }, bDB);

            // we also need to extract the rf-step induced phase shifts. These come out in the
            // B.RFxF channels, but like the edm, need to be corrected. I'm going to use just the
            // simplest level of correction for these.

            TOFChannel brf1fCorrDB = (c_brf1f / c_db) - ((c_b * c_dbrf1f) / (c_db * c_db));

            tcs.AddChannel(new string[] { "BRF1FCORRDB" }, brf1fCorrDB);

            TOFChannel brf2fCorrDB = (c_brf2f / c_db) - ((c_b * c_dbrf2f) / (c_db * c_db));

            tcs.AddChannel(new string[] { "BRF2FCORRDB" }, brf2fCorrDB);

            return(tcs);
        }
    }