public void ConstructAsymmetryShotNoiseTOF() { for (int i = 0; i < points.Count; i++) { EDMPoint point = (EDMPoint)points[i]; Shot shot = point.Shot; TOF bottomScaled = (TOF)shot.TOFs[detectors.IndexOf("bottomProbeScaled")]; TOF top = (TOF)shot.TOFs[detectors.IndexOf("topProbeNoBackground")]; // Multiply TOFs by their calibrations bottomScaled *= bottomScaled.Calibration; top *= top.Calibration; // Need the total signal TOF for later calculations TOF total = bottomScaled + top; // Get background counts double topLaserBackground = (double)point.SinglePointData["TopDetectorBackground"] * bottomScaled.Calibration; double bottomLaserBackground = (double)point.SinglePointData["BottomDetectorBackground"] * top.Calibration; // Calculate the shot noise variance in the asymmetry detector TOF asymmetryVariance = bottomScaled * bottomScaled * top * 4.0 + bottomScaled * top * top * 4.0 + top * top * bottomLaserBackground * 8.0 + bottomScaled * bottomScaled * topLaserBackground * 8.0; asymmetryVariance /= total * total * total * total; shot.TOFs.Add(asymmetryVariance); } detectors.Add("asymmetryShotNoiseVariance"); }
// this function subtracts the background off a TOF signal // the background is taken as the mean of a background array of points public void SubtractBackgroundFromProbeDetectorTOFs() { for (int i = 0; i < points.Count; i++) { EDMPoint point = (EDMPoint)points[i]; Shot shot = point.Shot; TOF t = (TOF)shot.TOFs[0]; double bg = t.GatedMeanAndUncertainty(2800, 2900)[0]; TOF bgSubtracted = t - bg; // if value if negative, set to zero for (int j = 0; j < bgSubtracted.Length; j++) { if (bgSubtracted.Data[j] < 0) { bgSubtracted.Data[j] = 0.0; } } bgSubtracted.Calibration = t.Calibration; shot.TOFs.Add(bgSubtracted); point.SinglePointData.Add("BottomDetectorBackground", bg); } // give these data a name detectors.Add("bottomProbeNoBackground"); for (int i = 0; i < points.Count; i++) { EDMPoint point = (EDMPoint)points[i]; Shot shot = point.Shot; TOF t = (TOF)shot.TOFs[1]; double bg = t.GatedMeanAndUncertainty(3200, 3300)[0]; TOF bgSubtracted = t - bg; // if value if negative, set to zero for (int j = 0; j < bgSubtracted.Length; j++) { if (bgSubtracted.Data[j] < 0) { bgSubtracted.Data[j] = 0.0; } } bgSubtracted.Calibration = t.Calibration; shot.TOFs.Add(bgSubtracted); point.SinglePointData.Add("TopDetectorBackground", bg); } // give these data a name detectors.Add("topProbeNoBackground"); }
// this function adds a new set of detector data to the block, constructed // by normalising the PMT data to the norm data. The normalisation is done // by dividing the PMT tofs through by the integrated norm data. The integration // is done according to the provided GatedDetectorExtractSpec. //public void Normalise(GatedDetectorExtractSpec normGate) //{ // GatedDetectorData normData = GatedDetectorData.ExtractFromBlock(this, normGate); // double averageNorm = 0; // foreach (double val in normData.PointValues) averageNorm += val; // averageNorm /= normData.PointValues.Count; // for (int i = 0; i < points.Count; i++) // { // Shot shot = ((EDMPoint)points[i]).Shot; // TOF normedTOF = ((TOF)shot.TOFs[0]) / (normData.PointValues[i] * (1 / averageNorm)); // shot.TOFs.Add(normedTOF); // } // // give these data a name // detectors.Add("topNormed"); //} //// this function adds a new set of detector data to the block, constructed //// by calculating the asymmetry of the top and bottom detectors The integration //// is done according to the provided GatedDetectorExtractSpec. //public void Normalise(GatedDetectorExtractSpec normGate) //{ // GatedDetectorData normData = GatedDetectorData.ExtractFromBlock(this, normGate); // for (int i = 0; i < points.Count; i++) // { // Shot shot = ((EDMPoint)points[i]).Shot; // TOF normedTOF = ((TOF)shot.TOFs[0]) / (normData.PointValues[i] ); // shot.TOFs.Add(normedTOF); // } // // give these data a name // detectors.Add("topNormed"); //} // this function takes some of the single point data and adds it to the block shots as TOFs // with one data point in them. This allows us to use the same code to break all of the data // into channels. public void TOFuliseSinglePointData(string[] channelsToTOFulise) { foreach (string spv in channelsToTOFulise) { for (int i = 0; i < points.Count; i++) { EDMPoint point = (EDMPoint)points[i]; Shot shot = point.Shot; TOF spvTOF = new TOF((double)point.SinglePointData[spv]); shot.TOFs.Add(spvTOF); } // give these data a name detectors.Add(spv); } }
public List <string> GetPointDetectors() { EDMPoint point = (EDMPoint)points[0]; List <string> pointDetectorList = new List <string>(); foreach (string key in point.SinglePointData.Keys) { //XmlSerialisableHashtables have "dummy" as a default entry. if (key != "dummy") { pointDetectorList.Add(key); } } return(pointDetectorList); }
// TOF-ulise all the single point detectors public void TOFuliseSinglePointData() { EDMPoint point = (EDMPoint)points[0]; string[] pointDetectors = new string[point.SinglePointData.Keys.Count]; point.SinglePointData.Keys.CopyTo(pointDetectors, 0); foreach (string spv in pointDetectors) { if (spv != "dummy") // the hashtable has "dummy" as the default entry, but we don't want it { for (int i = 0; i < points.Count; i++) { EDMPoint pt = (EDMPoint)points[i]; Shot shot = pt.Shot; TOF spvTOF = new TOF((double)pt.SinglePointData[spv]); shot.TOFs.Add(spvTOF); } // give these data a name detectors.Add(spv); } } }
// this is the method that actually takes the data. It is called by Start() and shouldn't // be called directly public void Acquire() { // lock onto something that the front end can see Monitor.Enter(MonitorLockObject); scanMaster = new ScanMaster.Controller(); phaseLock = new EDMPhaseLock.MainForm(); hardwareController = new EDMHardwareControl.Controller(); // map modulations to physical channels MapChannels(); // map the analog inputs MapAnalogInputs(); Block b = new Block(); b.Config = config; b.SetTimeStamp(); foreach (ScannedAnalogInput channel in inputs.Channels) { b.detectors.Add(channel.Channel.Name); } try { // get things going AcquisitionStarting(); // enter the main loop for (int point = 0 ; point < (int)config.Settings["numberOfPoints"] ; point++) { // set the switch states and impose the appropriate wait times ThrowSwitches(point); // take a point Shot s; EDMPoint p; if (Environs.Debug) { // just stuff a made up shot in //Thread.Sleep(10); s = DataFaker.GetFakeShot(1900,50,10,3,3); ((TOF)s.TOFs[0]).Calibration = ((ScannedAnalogInput)inputs.Channels[0]).Calibration; p = new EDMPoint(); p.Shot = s; //Thread.Sleep(20); } else { // everything should be ready now so start the analog // input task (it will wait for a trigger) inputTask.Start(); // get the raw data double[,] analogData = inputReader.ReadMultiSample(inputs.GateLength); inputTask.Stop(); // extract the data for each scanned channel and put it in a TOF s = new Shot(); for (int i = 0 ; i < inputs.Channels.Count ; i++) { // extract the raw data double[] rawData = new double[inputs.GateLength]; for (int q = 0 ; q < inputs.GateLength ; q++) rawData[q] = analogData[i,q]; ScannedAnalogInput ipt = (ScannedAnalogInput)inputs.Channels[i]; // reduce the data double[] data = ipt.Reduce(rawData); TOF t = new TOF(); t.Calibration = ipt.Calibration; // the 1000000 is because clock period is in microseconds; t.ClockPeriod = 1000000 / ipt.CalculateClockRate(inputs.RawSampleRate); t.GateStartTime = inputs.GateStartTime; // this is a bit confusing. The chop is measured in points, so the gate // has to be adjusted by the number of points times the clock period! if (ipt.ReductionMode == DataReductionMode.Chop) t.GateStartTime += (ipt.ChopStart * t.ClockPeriod); t.Data = data; // the 1000000 is because clock period is in microseconds; t.ClockPeriod = 1000000 / ipt.CalculateClockRate(inputs.RawSampleRate); s.TOFs.Add(t); } p = new EDMPoint(); p.Shot = s; } // do the "SinglePointData" (i.e. things that are measured once per point) // We'll save the leakage monitor until right at the end. // keep an eye on what the phase lock is doing p.SinglePointData.Add("PhaseLockFrequency", phaseLock.OutputFrequency); p.SinglePointData.Add("PhaseLockError", phaseLock.PhaseError); // scan the analog inputs double[] spd; // fake some data if we're in debug mode if (Environs.Debug) { spd = new double[7]; spd[0] = 1; spd[1] = 2; spd[2] = 3; spd[3] = 4; spd[4] = 5; spd[5] = 6; spd[6] = 7; } else { singlePointInputTask.Start(); spd = singlePointInputReader.ReadSingleSample(); singlePointInputTask.Stop(); } hardwareController.UpdateLaserPhotodiodes(); p.SinglePointData.Add("ProbePD", hardwareController.probePDVoltage); p.SinglePointData.Add("PumpPD", hardwareController.probePDVoltage); hardwareController.UpdateMiniFluxgates(); p.SinglePointData.Add("MiniFlux1", hardwareController.miniFlux1Voltage); p.SinglePointData.Add("MiniFlux2", hardwareController.miniFlux2Voltage); p.SinglePointData.Add("MiniFlux3", hardwareController.miniFlux3Voltage); hardwareController.UpdatePiMonitor(); p.SinglePointData.Add("piMonitor", hardwareController.piFlipMonVoltage); hardwareController.ReadIMonitor(); p.SinglePointData.Add("NorthCurrent", hardwareController.NorthCurrent); p.SinglePointData.Add("SouthCurrent", hardwareController.SouthCurrent); // Hopefully the leakage monitors will have finished reading by now. // We join them, read out the data, and then launch another asynchronous // acquisition. [If this is the first shot of the block, the leakage monitor // measurement will have been launched in AcquisitionStarting() ]. //hardwareController.WaitForIMonitorAsync(); //p.SinglePointData.Add("NorthCurrent", hardwareController.NorthCurrent); //p.SinglePointData.Add("SouthCurrent", hardwareController.SouthCurrent); //hardwareController.UpdateIMonitorAsync(); // randomise the Ramsey phase // TODO: check whether the .NET rng is good enough // TODO: reference where this number comes from //double d = 2.3814 * (new Random().NextDouble()); //hardwareController.SetScramblerVoltage(d); b.Points.Add(p); // update the front end Controller.GetController().GotPoint(point, p); if (CheckIfStopping()) { // release hardware AcquisitionStopping(); // signal anybody waiting on the lock that we're done Monitor.Pulse(MonitorLockObject); Monitor.Exit(MonitorLockObject); return; } } } catch (Exception e) { // try and stop the experiment gracefully try { AcquisitionStopping(); } catch (Exception) {} // about the best that can be done at this stage Monitor.Pulse(MonitorLockObject); Monitor.Exit(MonitorLockObject); throw e; } AcquisitionStopping(); // hand the new block back to the controller Controller.GetController().AcquisitionFinished(b); // signal anybody waiting on the lock that we're done Monitor.Pulse(MonitorLockObject); Monitor.Exit(MonitorLockObject); }
public void GotPoint(int point, EDMPoint p) { // store the leakage measurements ready for the graph update northLeakages[leakageIndex] = (double)p.SinglePointData["NorthCurrent"]; southLeakages[leakageIndex] = (double)p.SinglePointData["SouthCurrent"]; leakageIndex++; if ((point % UPDATE_EVERY) == 0) { Shot data = p.Shot; mainWindow.TankLevel = point; TOF tof = (TOF)data.TOFs[0]; mainWindow.PlotTOF(0, tof.Data, tof.GateStartTime, tof.ClockPeriod); tof = (TOF)data.TOFs[1]; mainWindow.PlotTOF(1, tof.Data, tof.GateStartTime, tof.ClockPeriod); tof = (TOF)data.TOFs[2]; mainWindow.PlotTOF(2, tof.Data, tof.GateStartTime, tof.ClockPeriod); tof = (TOF)data.TOFs[5]; mainWindow.PlotTOF(3, tof.Data, tof.GateStartTime, tof.ClockPeriod); // update the leakage graphs mainWindow.AppendLeakageMeasurement(new double[]{northLeakages[0]}, new double[]{southLeakages[0]}); leakageIndex = 0; } }