using OINA.Extender; using OINA.Extender.Acquisition; using OINA.Extender.Acquisition.Ed; using OINA.Extender.Acquisition.Image; using OINA.Extender.Data; using OINA.Extender.Data.Ed; using OINA.Extender.Data.Image; using OINA.Extender.MicroscopeControl; using OINA.Extender.Processing; using OINA.Extender.Processing.Ed; using OINA.Extender.Processing.Quant; using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Text; using System.Threading; //显示弹出信息 using System.Windows.Forms; namespace Extender { enum OxfordControllerState { READY = 0, WORKING = 1, SUCCEEDED = 2, FAILED = 3, ABORT = 4 }; /// /// Enum EDSConst definition. /// enum EDSConst { MAX_XRAY_BATCH = 1024, XANA_CHANNELS = 2000, XANA_CHANNELS_MAX = 4192, MAX_AMPTIME_CONSTANTS = 10, MAX_EV_PER_CHANNELS = 5, MAX_ANALYZERS = 5, MAX_LEN_ANALYZER_NAME = 16 }; struct OxfordChord { public long m_nX; public long m_nY; public long m_nLength; }; enum OxfordCommand { //缩放 GetMagnification = 0, SetMagnification = 1, //焦距 GetWorkingDistance = 2, SetWorkingDistance = 3, //亮度 GetBrightness = 4, SetBrightness = 5, //对比度 GetContrast = 6, SetContrast = 7, //SEM电压 GetSEMVoltage = 8, SetSEMVoltage = 9, //样品台 GetStagePosition = 10, SetStagePosition = 11, GetStageAtX = 12, GetStageAtY = 13, GetStageAtZ = 14, GetStageAtT = 15, GetStageAtR = 16, SetStageGotoX = 17, SetStageGotoY = 18, SetStageGotoZ = 19, SetStageGotoT = 20, SetStageGotoR = 21, MoveStageXY = 22, //拍图 GrabImage = 23, //采集参数设置 SetImageAcquistionSetting = 24, //获取分辨率 GetImageStore = 25, //设置分辨率 SetImageStore = 26, //获取bitmap GetBitmap = 27, IsAcquiringSpectrum = 28, //X-ray //点采集 XrayPointCollectiong = 29, //面采集 XrayAreaCollectiong = 30, BeginMultipleAquisition=31, EndMultipleAquisition=32, BeginAreaModeMultipleAquisition = 33, EndAreaModeMultipleAquisition = 34, Exit =100, } public struct GrabImageParam { public GrabImageParam(string filename, short xoff, short yoff, short width, short height, short type) { this.filename = filename; this.xoff = xoff; this.yoff = yoff; this.width = width; this.height = height; this.type = type; } public string filename; public short xoff; public short yoff; public short width; public short height; public short type; } public class PointXrayParam { public PointXrayParam() { this.XrayData = new long[2000]; this.listElement=new Dictionary (); } public double dMilliSecondsTime; public double x; public double y; public long[] XrayData ; public Dictionary listElement; } public struct AreaXrayParam { public double dMilliSecondsTime; public List a_listChord; public long[] XrayData; public Dictionary a_listElement; } public struct MoveStageParam { public float x; public float y; } public class ExtenderWrapper : IExtenderControl { struct oxfordCommandData { public OxfordCommand commandType; public bool returnType; public MoveStageParam moveStagePrm; public GrabImageParam grabImgParam; public PointXrayParam pointXrayPrm; public AreaXrayParam areaXrayPrm; } private Thread controlThread; private oxfordCommandData currentCommand; private Extender myExtender=null; AutoResetEvent startEvent= new AutoResetEvent(false); AutoResetEvent endEvent = new AutoResetEvent(false); private NLog.Logger log; public ExtenderWrapper() { if (myExtender == null) { myExtender = new Extender(); } log = NLog.LogManager.GetCurrentClassLogger(); controlThread = new Thread(this.ControlerThread); //controlThread.IsBackground = true; controlThread.Start(); //Thread.Sleep(100);//wait untill the new thread has been started } public void CloseExtender() { if (myExtender != null) { myExtender.CloseExtender(); currentCommand.commandType = OxfordCommand.Exit; startEvent.Set(); controlThread.Join(); } } ~ExtenderWrapper() { this.CloseExtender(); } private void ControlerThread() { log.Info("myExtender has been initialized"); while (true) { while (true) { if (startEvent.WaitOne(0, true)) { break; } Thread.Sleep(50); Application.DoEvents(); } switch (currentCommand.commandType) { case OxfordCommand.MoveStageXY: { MoveStageParam p = currentCommand.moveStagePrm; if (myExtender.MoveStageXY(p.x, p.y)) { currentCommand.returnType = true; } else { currentCommand.returnType = false; } endEvent.Set(); } break; case OxfordCommand.GrabImage: { GrabImageParam p = currentCommand.grabImgParam; log.Info("begin:GrabImage:oxford thread 线程ID:" + Thread.CurrentThread.ManagedThreadId.ToString() ); if (myExtender.GrabImage(p.filename, p.xoff, p.yoff, p.width, p.height, p.type)) { currentCommand.returnType = true; log.Info("GrabImage:oxford thread return: " + currentCommand.returnType.ToString()); } else { currentCommand.returnType = false; log.Info("GrabImage:oxford thread return: " + currentCommand.returnType.ToString()); } endEvent.Set(); } break; case OxfordCommand.XrayPointCollectiong: { PointXrayParam p = currentCommand.pointXrayPrm; log.Info("线程:开始采集单点xray"); if (myExtender.XrayPointCollecting(p.dMilliSecondsTime, p.x, p.y, out p.XrayData,out p.listElement)) { currentCommand.pointXrayPrm = p; currentCommand.returnType = true; } else { log.Error("线程:采集单点xray失败"); currentCommand.returnType = false; } endEvent.Set(); } break; case OxfordCommand.XrayAreaCollectiong: { AreaXrayParam p = currentCommand.areaXrayPrm; log.Info("线程:开始线扫xray"); if (myExtender.XrayAreaCollectiong( p.dMilliSecondsTime, p.a_listChord,out p.XrayData, out p.a_listElement)) { currentCommand.areaXrayPrm = p; currentCommand.returnType = true; } else { log.Error("线程:失败线扫xray"); currentCommand.returnType = false; } endEvent.Set(); } break; case OxfordCommand.BeginMultipleAquisition: { myExtender.BeginMultipleAquisition(); endEvent.Set(); } break; case OxfordCommand.EndMultipleAquisition: { myExtender.EndMultipleAquisition(); endEvent.Set(); } break; case OxfordCommand.BeginAreaModeMultipleAquisition: { myExtender.BeginAreaModeMultipleAquisition(); endEvent.Set(); } break; case OxfordCommand.EndAreaModeMultipleAquisition: { myExtender.EndAreaModeMultipleAquisition(); endEvent.Set(); } break; case OxfordCommand.Exit: { endEvent.Set(); log.Info("receive exit command"); } break; } if (currentCommand.commandType == OxfordCommand.Exit) { log.Info("exiting the thread"); break; } } } public Bitmap GetBitmap() { return myExtender.GetBitmap(); } public float GetBrightness() { return myExtender.GetBrightness(); } public float GetContrast() { return myExtender.GetContrast(); } public int[] GetImageStore() { return myExtender.GetImageStore(); } public float GetMagnification() { return myExtender.GetMagnification(); } public float GetSEMVoltage() { return myExtender.GetSEMVoltage(); } public float GetStageAtR() { return myExtender.GetStageAtR(); } public float GetStageAtT() { return myExtender.GetStageAtT(); } public float GetStageAtX() { return myExtender.GetStageAtX(); } public float GetStageAtY() { return myExtender.GetStageAtY(); } public float GetStageAtZ() { return myExtender.GetStageAtZ(); } public float[] GetStagePosition() { return myExtender.GetStagePosition(); } public float GetWorkingDistance() { return myExtender.GetWorkingDistance(); } public bool GrabImage(string filename, short xoff, short yoff, short width, short height, short type) { currentCommand.grabImgParam =new GrabImageParam(filename, xoff, yoff, width, height, type); currentCommand.commandType = OxfordCommand.GrabImage; startEvent.Set(); while (true) { if (endEvent.WaitOne(0, false)) { break; } Thread.Sleep(100); Application.DoEvents(); } log.Info("GrabImage:oxford thread return: " + currentCommand.returnType.ToString()); if (currentCommand.returnType == true) { return true; } else { return false; } } public bool IsAcquiringSpectrum() { return myExtender.IsAcquiringSpectrum(); } public bool MoveStageXY(float x, float y) { currentCommand.moveStagePrm = new MoveStageParam(); currentCommand.moveStagePrm.x = x; currentCommand.moveStagePrm.y = y; currentCommand.commandType = OxfordCommand.MoveStageXY; startEvent.Set(); while (true) { if (endEvent.WaitOne(0, false)) { break; } } if (currentCommand.returnType == true) { return true; } else { return false; } } public bool SetBrightness(float set) { return myExtender.SetBrightness(set); } public bool SetContrast(float set) { return myExtender.SetContrast(set); } public bool SetImageAcquistionSetting(double a_dDwellTime, int a_nImageType, double a_dImageScanSize) { return myExtender.SetImageAcquistionSetting(a_dDwellTime, a_nImageType, a_dImageScanSize); } public bool SetImageStore(float set) { return myExtender.SetImageStore(set); } public bool SetMagnification(float set) { return myExtender.SetMagnification(set); } public bool SetSEMVoltage(float set) { return myExtender.SetSEMVoltage(set); } public bool SetStageGotoR(float set) { return myExtender.SetStageGotoR(set); } public bool SetStageGotoT(float set) { return myExtender.SetStageGotoT(set); } public bool SetStageGotoX(float set) { return myExtender.SetStageGotoX(set); } public bool SetStageGotoY(float set) { return myExtender.SetStageGotoY(set); } public bool SetStageGotoZ(float set) { return myExtender.SetStageGotoZ(set); } public bool SetStagePosition(float[] set) { return myExtender.SetStagePosition(set); } public bool SetWorkingDistance(float set) { return myExtender.SetWorkingDistance(set); } public bool XrayAreaCollectiong( double dMilliSecondsTime, List a_listChord, out long[] XrayData, out Dictionary a_listElement) { var p = new AreaXrayParam(); p = currentCommand.areaXrayPrm; p.dMilliSecondsTime = dMilliSecondsTime; p.a_listChord = a_listChord; currentCommand.areaXrayPrm = p; currentCommand.commandType = OxfordCommand.XrayAreaCollectiong; startEvent.Set(); while (true) { if (endEvent.WaitOne(0, false)) { break; } } if (currentCommand.returnType == true) { XrayData= currentCommand.areaXrayPrm.XrayData ; a_listElement= currentCommand.areaXrayPrm.a_listElement ; return true; } else { XrayData = p.XrayData; a_listElement = p.a_listElement; return false; } } public bool XrayPointCollecting(double dMilliSecondsTime, double x, double y, out long[] XrayData, out Dictionary a_listElement) { var p = new PointXrayParam(); p.dMilliSecondsTime = dMilliSecondsTime; p.x = x; p.y = y; currentCommand.pointXrayPrm = p; currentCommand.commandType = OxfordCommand.XrayPointCollectiong; startEvent.Set(); while (true) { if (endEvent.WaitOne(0, false)) { break; } Application.DoEvents(); } if (currentCommand.returnType == true) { XrayData= currentCommand.pointXrayPrm.XrayData ; a_listElement= currentCommand.pointXrayPrm.listElement ; return true; } else { XrayData = p.XrayData; a_listElement = p.listElement; return false; } } public void BeginMultipleAquisition() { currentCommand.commandType = OxfordCommand.BeginMultipleAquisition; startEvent.Set(); while (true) { if (endEvent.WaitOne(0, false)) { break; } Application.DoEvents(); } } public void EndMultipleAquisition() { currentCommand.commandType = OxfordCommand.EndMultipleAquisition; startEvent.Set(); while (true) { if (endEvent.WaitOne(0, false)) { break; } Application.DoEvents(); } } public void BeginAreaModeMultipleAquisition() { currentCommand.commandType = OxfordCommand.BeginAreaModeMultipleAquisition; startEvent.Set(); while (true) { if (endEvent.WaitOne(0, false)) { break; } Application.DoEvents(); } } public void EndAreaModeMultipleAquisition() { currentCommand.commandType = OxfordCommand.EndAreaModeMultipleAquisition; startEvent.Set(); while (true) { if (endEvent.WaitOne(0, false)) { break; } Application.DoEvents(); } } } public class Extender : IExtenderControl { //构造函数 public Extender() { InitMicroscopeController(); InitImageAcquisition(); InitXrayAcquistion(); } //结束 public void CloseExtender() { CloseMicroscopeController(); CloseImageAcquisition(); CloaseXrayAcquistion(); } #region 电镜控制、样品台 //控制电镜 private IMicroscopeController microscopeController = null; //电压 private double m_dHighVoltage; //放大倍数 private double m_dMagnification; //工作距离 private double m_dWorkingDistance; //亮度 private double m_dBirghtness; //对比度 private double m_dContrast; //BeamOn private bool m_bBeamOn; //FilamentOn private bool m_bFilamentOn; //样品台位置 private double m_dStageX; private double m_dStageY; private double m_dStageZ; private double m_dStageR; private double m_dStageT; private double m_dStageXMax; public double StageXMax { get { return this.m_dStageXMax; } set { this.m_dStageXMax = value; } } private double m_dStageXMin; public double StageXMin { get { return this.m_dStageXMin; } set { this.m_dStageXMin = value; } } private double m_dStageYMax; public double StageYMax { get { return this.m_dStageYMax; } set { this.m_dStageYMax = value; } } private double m_dStageYMin; public double StageYMin { get { return this.m_dStageYMin; } set { this.m_dStageYMin = value; } } private double m_dStageZMax; public double StageZMax { get { return this.m_dStageZMax; } set { this.m_dStageZMax = value; } } private double m_dStageZMin; public double StageZMin { get { return this.m_dStageZMin; } set { this.m_dStageZMin = value; } } private double m_dStageTMax; public double StageTMax { get { return this.m_dStageTMax; } set { this.m_dStageTMax = value; } } private double m_dStageTMin; public double StageTMin { get { return this.m_dStageTMin; } set { this.m_dStageTMin = value; } } private double m_dStageRMax; public double StageRMax { get { return this.m_dStageRMax; } set { this.m_dStageRMax = value; } } private double m_dStageRMin; public double StageRMin { get { return this.m_dStageRMin; } set { this.m_dStageRMin = value; } } //控制电镜初始化 void InitMicroscopeController(float a_fStageXMin = 0, float a_fStageXMax = 130, float a_fStageYMin = 0, float a_fStageYMax = 130, float a_fStageZMin = 0, float a_fStageZMax = 40, float a_fStageTMin = 0, float a_fStageTMax = 90, float a_fStageRMin = 0, float a_fStageRMax = 360) { this.microscopeController = AcquireFactory.CreateMicroscopeControl(); this.microscopeController.ColumnChange += this.OnMicroscopeColumnChange; this.microscopeController.StageChange += this.OnMicroscopeStageChange; this.microscopeController.ColumnConnected += this.OnMicroscopeColumnConnected; this.microscopeController.StageConnected += this.OnMicroscopeStageConnected; this.microscopeController.ChangeCompleted += this.OnMicroscopeChangeCompleted; ReadMicroscopeColumn(); ReadStage(); StageXMax = a_fStageXMax; StageXMin = a_fStageXMin; StageYMax = a_fStageYMax; StageYMin = a_fStageYMin; StageZMax = a_fStageZMax; StageZMin = a_fStageZMin; StageTMax = a_fStageTMax; StageTMin = a_fStageTMin; StageRMax = a_fStageRMax; StageRMin = a_fStageRMin; } //控制电镜释放 void CloseMicroscopeController() { this.microscopeController.ColumnChange -= this.OnMicroscopeColumnChange; this.microscopeController.StageChange -= this.OnMicroscopeStageChange; this.microscopeController.ColumnConnected -= this.OnMicroscopeColumnConnected; this.microscopeController.StageConnected -= this.OnMicroscopeStageConnected; this.microscopeController.ChangeCompleted -= this.OnMicroscopeChangeCompleted; } //读取当前的电镜控制值 private void ReadMicroscopeColumn() { var columnCapabilities = this.microscopeController.ColumnCapabilities; var columnConditions = this.microscopeController.ColumnConditions; if (columnCapabilities.Magnification.CanRead) { m_dMagnification = columnConditions.Magnification; } if (columnCapabilities.WorkingDistance.CanRead) { m_dWorkingDistance = columnConditions.WorkingDistance; } if (columnCapabilities.HighVoltage.CanRead) { m_dHighVoltage = columnConditions.HighVoltage; } if (columnCapabilities.Brightness.CanRead) { m_dBirghtness = columnConditions.Brightness; } if (columnCapabilities.Contrast.CanRead) { m_dContrast = columnConditions.Contrast; } if (columnCapabilities.BeamOn.CanRead) { m_bBeamOn = Convert.ToBoolean(columnConditions.BeamOn); } if (columnCapabilities.FilamentOn.CanRead) { m_bFilamentOn = Convert.ToBoolean(columnConditions.FilamentOn); } } //读取样品台位置 private void ReadStage() { var stageCapabilities = this.microscopeController.StageCapabilities; var stageConditions = this.microscopeController.StageConditions; if (stageCapabilities.StageX.CanRead) { this.m_dStageX = stageConditions.StageX; } if (stageCapabilities.StageY.CanRead) { this.m_dStageY = stageConditions.StageY; } if (stageCapabilities.StageZ.CanRead) { this.m_dStageZ = stageConditions.StageZ; } if (stageCapabilities.StageT.CanRead) { this.m_dStageT = stageConditions.StageT; } if (stageCapabilities.StageR.CanRead) { this.m_dStageR = stageConditions.StageR; } } //电镜控制改变事件 private void OnMicroscopeColumnChange(object sender, EventArgs e) { //MessageBox.Show("电镜控制改变ColumnChange"); ReadMicroscopeColumn(); } //样品台控制改变事件 private void OnMicroscopeStageChange(object sender, EventArgs e) { //MessageBox.Show("样品控制改变StageChange"); ReadStage(); } //列控制连接或断开时的事件 private void OnMicroscopeColumnConnected(object sender, EventArgs e) { //MessageBox.Show("电镜控制连接ColumnConnected"); } //样品台控制连接或断开时的事件 private void OnMicroscopeStageConnected(object sender, EventArgs e) { //MessageBox.Show("样品台连接StageConnected"); ReadStage(); } //样品台控制、电镜控制、外围控制的事件改变完成 private void OnMicroscopeChangeCompleted(object sender, EventArgs e) { //MessageBox.Show("电镜控制完成ChangeCompleted"); ReadMicroscopeColumn(); ReadStage(); } //电镜控制 //电压 //放大倍数 //工作距离 //亮度 //对比度 //BeamOn //FilamentOn //缩放 public float GetMagnification() { return (float)m_dMagnification; } public Boolean SetMagnification(float set) { Dictionary columnDictionary = new Dictionary { { Column.Magnification, (double)set } }; this.microscopeController.SetColumnConditions(columnDictionary); return true; } //焦距 public float GetWorkingDistance() { return (float)m_dWorkingDistance; } public Boolean SetWorkingDistance(float set) { Dictionary columnDictionary = new Dictionary { { Column.WorkingDistance, (double)set } }; this.microscopeController.SetColumnConditions(columnDictionary); return true; } //亮度 public float GetBrightness() { return (float)m_dBirghtness; } public Boolean SetBrightness(float set) { Dictionary columnDictionary = new Dictionary { { Column.Brightness, (double)set } }; this.microscopeController.SetColumnConditions(columnDictionary); return true; } //对比度 public float GetContrast() { return (float)m_dContrast; } public Boolean SetContrast(float set) { Dictionary columnDictionary = new Dictionary { { Column.Contrast, (double)set } }; this.microscopeController.SetColumnConditions(columnDictionary); return true; } //SEM电压 public float GetSEMVoltage() { return (float)m_dHighVoltage; } public Boolean SetSEMVoltage(float set) { Dictionary columnDictionary = new Dictionary { { Column.HighVoltage, (double)set } }; this.microscopeController.SetColumnConditions(columnDictionary); return true; } //样品台 public float[] GetStagePosition() { float[] ret = new float[5]; ret[0] = (float)m_dStageX; ret[1] = (float)m_dStageY; ret[2] = (float)m_dStageZ; ret[3] = (float)m_dStageT; ret[4] = (float)m_dStageR; return ret; } public Boolean SetStagePosition(float[] set) { double stageX = (double)set[0]; if (stageX > StageXMax || stageX < StageXMin) { return false; } double stageY = (double)set[1]; if (stageY > StageYMax || stageY < StageYMin) { return false; } double stageZ = (double)set[2]; if (stageZ > StageZMax || stageZ < StageZMin) { return false; } double stageT = (double)set[3]; if (stageT > StageTMax || stageT < StageTMin) { return false; } double stageR = (double)set[4]; if (stageR > StageRMax || stageR < StageRMin) { return false; } var stageDictionary = new Dictionary { { Stage.StageX, (double)stageX }, { Stage.StageY, (double)stageY }, { Stage.StageZ, (double)stageZ }, { Stage.StageT, (double)stageT }, { Stage.StageR, (double)stageR } }; this.microscopeController.SetStageConditions(stageDictionary); return true; } public float GetStageAtX() { return (float)m_dStageX; } public float GetStageAtY() { return (float)m_dStageY; } public float GetStageAtZ() { return (float)m_dStageZ; } public float GetStageAtT() { return (float)m_dStageT; } public float GetStageAtR() { return (float)m_dStageR; } public Boolean SetStageGotoX(float set) { double stageX = (double)set; if (stageX > StageXMax || stageX < StageXMin) { return false; } var stageDictionary = new Dictionary { { Stage.StageX, (double)stageX } }; this.microscopeController.SetStageConditions(stageDictionary); return true; } public Boolean SetStageGotoY(float set) { double stageY = (double)set; if (stageY > StageYMax || stageY < StageYMin) { return false; } var stageDictionary = new Dictionary { { Stage.StageY, (double)stageY } }; this.microscopeController.SetStageConditions(stageDictionary); return true; } public Boolean SetStageGotoZ(float set) { double stageZ = (double)set; if (stageZ > StageZMax || stageZ < StageZMin) { return false; } var stageDictionary = new Dictionary { { Stage.StageZ, (double)stageZ } }; this.microscopeController.SetStageConditions(stageDictionary); return true; } public Boolean SetStageGotoT(float set) { double stageT = (double)set; if (stageT > StageTMax || stageT < StageTMin) { return false; } var stageDictionary = new Dictionary { { Stage.StageT, (double)stageT } }; this.microscopeController.SetStageConditions(stageDictionary); return true; } public Boolean SetStageGotoR(float set) { double stageR = (double)set; if (stageR > StageRMax || stageR < StageRMin) { return false; } var stageDictionary = new Dictionary { { Stage.StageR, (double)stageR } }; this.microscopeController.SetStageConditions(stageDictionary); return true; } public Boolean MoveStageXY(float x, float y) { double stageX = (double)x; if (stageX > StageXMax || stageX < StageXMin) { return false; } double stageY = (double)y; if (stageY > StageYMax || stageY < StageYMin) { return false; } var stageDictionary = new Dictionary { { Stage.StageX, (double)stageX }, { Stage.StageY, (double)stageY } }; this.microscopeController.SetStageConditions(stageDictionary); return true; } #endregion #region 拍图 /// /// IImageAcquisitionController object /// private IImageAcquisitionController imageAcquisitionController = null; /// /// IImageSettings object /// private IImageAcquisitionSettings imageAcquisitionSettings = null; //图像扫描尺寸 public double[] ImageScanSize = { 32, 64, 128, 256, 512, 1024, 4096, 8192 }; private byte[] m_ImageBit = null; private long m_nImageWidth = 0; private long m_nImageHeight = 0; private double m_dImagePixelsize = 0;//it will be initialized when we get an image from the EDS. bool m_bAcquistionDone = false; private Bitmap m_Bitmap = null; void InitImageAcquisition() { imageAcquisitionController = AcquireFactory.CreateImageServer(); imageAcquisitionSettings = AcquireFactory.CreateImageSettings(); //imageAcquisitionSettings. imageAcquisitionController.ExperimentStarted += this.OnImageExperimentStarted; imageAcquisitionController.ExperimentFinished += this.OnImageExperimentFinished; } //控制电镜释放 void CloseImageAcquisition() { imageAcquisitionController.ExperimentStarted -= this.OnImageExperimentStarted; imageAcquisitionController.ExperimentFinished -= this.OnImageExperimentFinished; } /// /// OnImageExperimentStarted /// private void OnImageExperimentStarted(object sender, AcquisitionStartedEventArgs e) { NLog.Logger log = NLog.LogManager.GetCurrentClassLogger(); log.Info("拍图开始事件!"); } //int m_nState; /// /// OnImageExperimentFinished /// private void OnImageExperimentFinished(object sender, AcquisitionFinishedEventArgs e) { IElectronImage electronImage = e.Value[0]; if (!ReadImageData(electronImage, out m_ImageBit, out m_nImageWidth, out m_nImageHeight,out m_dImagePixelsize)) { MessageBox.Show("图像采集完成,获取图像像素失败!"); } if (m_ImageBit != null && m_ImageBit.Length == m_nImageWidth * m_nImageHeight) { m_bAcquistionDone = true; } } bool ReadImageData(IElectronImage a_electronImage, out Byte[] a_pImageBits, out long a_nImageHeight, out long a_nImageWidth,out double a_nPixelSize) { a_nImageHeight = 0; a_nImageWidth = 0; a_nPixelSize = 0; a_pImageBits = null; if (a_electronImage == null) { return false; } a_nImageHeight = a_electronImage.Height; a_nImageWidth = a_electronImage.Width; a_nPixelSize = a_electronImage.PixelSize; int nBytesPerPixel = a_electronImage.BytesPerPixel; long nImageSize = a_nImageHeight * a_nImageWidth; long nBufferSize = nImageSize * nBytesPerPixel; Byte[] imageData = new Byte[nBufferSize]; a_electronImage.GetData(imageData); a_pImageBits = new Byte[nImageSize]; // default, oxford will return short image, we need to convert to byte if (nBytesPerPixel == 2) { int nBSEValue = 0; for (int i = 0; i < nImageSize; ++i) { nBSEValue = imageData[0 + i * nBytesPerPixel] + imageData[1 + i * nBytesPerPixel] * 255; a_pImageBits[i] = (Byte)(nBSEValue / 128.0 + 0.5); } } else { string msg = string.Format("image byte per pixel other than 2({0}), image convert may wrong", nBytesPerPixel); MessageBox.Show(msg); int nOffset = nBytesPerPixel - 1; for (int i = 0; i < nImageSize; ++i) { a_pImageBits[i] = imageData[nOffset + i * nBytesPerPixel]; } } return true; } void AcquisitionParamInit() { m_ImageBit = null; m_nImageWidth = 0; m_nImageHeight = 0; m_bAcquistionDone = false; Bitmap m_Bitmap = null; } //a_dDwellTime : 1~100000之间的数 //a_sImageType : 1: SE, 2: Bse //a_dImageScanSize : 图像分辨率,图像的高 public bool SetImageAcquistionSetting(double a_dDwellTime, int a_nImageType, double a_dImageScanSize) { IImageSettings imageSettings = imageAcquisitionSettings.ImageSettings; IImageCapabilities imageCapabilities = imageAcquisitionSettings.ImageCapabilities; IImageScanSettings scanSettings = imageAcquisitionSettings.ScanSettings; if (a_dDwellTime > imageCapabilities.MaximumImageDwellMicroseconds) { imageSettings.DwellTimeMicroSeconds = imageCapabilities.MaximumImageDwellMicroseconds; } if (a_dDwellTime < imageCapabilities.MinimumImageDwellMicroseconds) { imageSettings.DwellTimeMicroSeconds = imageCapabilities.MinimumImageDwellMicroseconds; } else { imageSettings.DwellTimeMicroSeconds = a_dDwellTime; } imageSettings.InputSources.ToList().ForEach(i => imageSettings.EnableInputSource(i.Key, false)); imageSettings.EnableInputSource((ImageInputSources)a_nImageType, true); if (!ImageScanSize.Contains(a_dImageScanSize)) { MessageBox.Show("图像尺寸输入无效"); return false; } var pixelSize = 1d / a_dImageScanSize; scanSettings.AcquisitionRegion.CreateFullFieldRegion(pixelSize); return true; } ////拍图 public Boolean GrabImage(String filename, short xoff, short yoff, short width, short height, short type) { SetImageAcquistionSetting(1, 1, 1024); AcquisitionParamInit(); try { int lastingTime = 0; NLog.Logger log = NLog.LogManager.GetCurrentClassLogger(); //imageAcquisitionController.BeginMultipleAcquisition(); IEnumerable images = imageAcquisitionController.StartAcquisition(imageAcquisitionSettings); log.Info("拍图开始 startAcquisition 完成"); images.ToList().ForEach(i => { i.Label = string.Format(@"Code example image - {0:HH:mm:ss} - {1}", DateTime.Now, i.InputSource.ToString()); }); while (true) { if (m_bAcquistionDone) { // 图像对象 m_Bitmap = ToGrayBitmap(m_ImageBit, (int)m_nImageHeight, (int)m_nImageWidth); switch (Path.GetExtension(filename)) { case ".bmp": m_Bitmap.Save(filename, System.Drawing.Imaging.ImageFormat.Bmp); break; case ".jpg": m_Bitmap.Save(filename, System.Drawing.Imaging.ImageFormat.Jpeg); break; case ".gif": m_Bitmap.Save(filename, System.Drawing.Imaging.ImageFormat.Gif); break; case ".tif": m_Bitmap.Save(filename, System.Drawing.Imaging.ImageFormat.Tiff); break; case ".png": m_Bitmap.Save(filename, System.Drawing.Imaging.ImageFormat.Png); break; default: break; } break; } Application.DoEvents(); Thread.Sleep(100); lastingTime += 100; if (lastingTime > EDSColletionTimeOut*6) { return false; } } } catch (InvalidSettingsException settingsException) { var sb = new StringBuilder(@"Invalid settings have been supplied: "); sb.AppendLine(); settingsException.ValidationResults.ValidationErrors.ToList().ForEach(ve => sb.AppendFormat("{0}{1}", Environment.NewLine, ve)); MessageBox.Show(sb.ToString()); } catch (AcquisitionStartException startException) { string msg = string.Format(@"AcquisitionStartException: {0}", startException.Message); MessageBox.Show(msg); } return true; } /// /// 将一个byte的数组转换为8bit灰度位图 /// /// 数组 /// 图像宽度 /// 图像高度 /// 位图 Bitmap ToGrayBitmap(byte[] data, int width, int height) { // 申请目标位图的变量,并将其内存区域锁定 Bitmap bmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed); //BitmapData这部分内容 需要 using System.Drawing.Imaging; BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed); // 获取图像参数 // 扫描线的宽度 int stride = bmpData.Stride; // 显示宽度与扫描线宽度的间隙 int offset = stride - width; // 获取bmpData的内存起始位置 IntPtr iptr = bmpData.Scan0; // 用stride宽度,表示这是内存区域的大小 int scanBytes = stride * height; // 下面把原始的显示大小字节数组转换为内存中实际存放的字节数组 int posScan = 0; int posReal = 0;// 分别设置两个位置指针,指向源数组和目标数组 byte[] pixelValues = new byte[scanBytes]; //为目标数组分配内存 for (int x = 0; x < height; x++) { int startIndex = x * width; //// 下面的循环节是模拟行扫描 for (int y = 0; y < width; y++) { pixelValues[posScan++] = data[posReal++]; } posScan += offset; //行扫描结束,要将目标位置指针移过那段“间隙” } // 用Marshal的Copy方法,将刚才得到的内存字节数组复制到BitmapData中 System.Runtime.InteropServices.Marshal.Copy(pixelValues, 0, iptr, scanBytes); bmp.UnlockBits(bmpData); // 解锁内存区域 // 下面的代码是为了修改生成位图的索引表,从伪彩修改为灰度 ColorPalette tempPalette; using (Bitmap tempBmp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed)) { tempPalette = tempBmp.Palette; } for (int i = 0; i < 256; i++) { tempPalette.Entries[i] = Color.FromArgb(i, i, i); } bmp.Palette = tempPalette; return bmp; } //获取分辨率 public int[] GetImageStore() { int[] ImageStore = new int[8]; for (int i = 0; i < 8; i++) { ImageStore[i] = (int)ImageScanSize[i]; } return ImageStore; } //设置分辨率 public Boolean SetImageStore(float set) { IImageScanSettings scanSettings = imageAcquisitionSettings.ScanSettings; if (!ImageScanSize.Contains(set)) { MessageBox.Show("图像尺寸输入无效"); return false; } var pixelSize = 1d / (double)set; scanSettings.AcquisitionRegion.CreateFullFieldRegion(pixelSize); return true; } public Bitmap GetBitmap() { return m_Bitmap; } #endregion #region X-ray //控制器 private IEdSpectrumAcquisitionController EdSpectrumAcquisitionController = null; private IEdSpectrumSettings EdSpectrumSettings = null; private IEdSpectrumProcessing EdSpectrumProcessing = null; // Use the autoIdSettings to define elements that are known or elements that you want to exclude. They also list elements that cannot be identified private IAutoIdSettings autoIdSettings = null; private ISEMQuantSettings quantSettings = null; private IEdChordListAcquisitionController _edsChordListController = null; private OxfordControllerState m_nState; private IEdChordListSettings _edsChordListSetting; private int XRayChannelLength = 2000; private long[] m_XrayData = null; private bool m_bXrayDone = false; private int EDSColletionTimeOut=10000; private AutoResetEvent m_endControllerEvent; //当前feature的pixel数控制 private long m_nCollectedPixelCounts; private long m_nPixelNum; private List m_listElementResult; private OxfordXrayData[] m_pXrayDataList; const int g_nOxfordControllerProcessTime = 4; const int g_nOxfordControllerEnergyRange = 20; // feature计数控制 private long m_nXrayDataCount; private long m_nCollectedXrayCounts; /// /// List of EdSpectrum objects /// private Dictionary listElement = null; void InitXrayAcquistion() { EdSpectrumSettings = AcquireFactory.CreateEdSpectrumSettings(); EdSpectrumAcquisitionController = AcquireFactory.CreateEdSpectrumServer(); EdSpectrumProcessing = ProcessingFactory.CreateSpectrumProcessing(); // Use the autoIdSettings to define elements that are known or elements that you want to exclude. They also list elements that cannot be identified autoIdSettings = ProcessingFactory.CreateAutoIdSettings(); quantSettings = ProcessingFactory.CreateSEMQuantSettings(); EdSpectrumAcquisitionController.ExperimentFinished += this.OnEdSpectrumExperimentFinished; //EdSpectrumAcquisitionController.ExperimentStarted += this.OnEdSpectrumExperimentStarted; } void CloaseXrayAcquistion() { EdSpectrumAcquisitionController.ExperimentFinished -= this.OnEdSpectrumExperimentFinished; //EdSpectrumAcquisitionController.ExperimentStarted -= this.OnEdSpectrumExperimentStarted; } void SetXrayAcquisitionParam( double a_dMilliSecondsTime) { EdSpectrumSettings.EdSettings.AcquisitionMode = EdAcquireMode.LiveTime; // RealTime or LiveTime if (a_dMilliSecondsTime < 100) { a_dMilliSecondsTime = 100; } EdSpectrumSettings.EdSettings.AcquisitionTime = TimeSpan.FromMilliseconds(a_dMilliSecondsTime); EdSpectrumSettings.EdSettings.ProcessTime = 4; EdSpectrumSettings.EdSettings.EnergyRange = 20; EdSpectrumSettings.EdSettings.NumberOfChannels = 4096; // EdSpectrumSettings.ScanSettings.AcquisitionRegion.CreateFullFieldRegion(1.0 / 1024.0); } void SetAreaXrayAcquisitionParam(IEdChordListSettings EdSpectrumSettings, double a_dMilliSecondsTime) { EdSpectrumSettings.EdSettings.AcquisitionMode = EdAcquireMode.LiveTime; // RealTime or LiveTime if (a_dMilliSecondsTime < 100) { a_dMilliSecondsTime = 100; } EdSpectrumSettings.EdSettings.AcquisitionTime = TimeSpan.FromMilliseconds(a_dMilliSecondsTime); EdSpectrumSettings.EdSettings.ProcessTime = 4; EdSpectrumSettings.EdSettings.EnergyRange = 20; EdSpectrumSettings.EdSettings.NumberOfChannels = 4096; // EdSpectrumSettings.ScanSettings.AcquisitionRegion.CreateFullFieldRegion(1.0 / 1024.0); } void SetPointAcquistionRegion(double a_nX, double a_nY) { EdSpectrumSettings.ScanSettings.AcquisitionRegion.CreatePointRegion(new System.Windows.Point(a_nX, a_nY)); } void SetAreaAcquistionRegion(List a_nChords) { ChordList chordsList = null; chordsList = new ChordList(a_nChords, m_dImagePixelsize); EdSpectrumSettings.ScanSettings.AcquisitionRegion.CreateChordListRegion(chordsList); } void XrayParamInit() { m_XrayData = null; m_bXrayDone = false; } /// /// Called when IEdSpectrumAcquisitionController Experiment Starting. /// /// The sender. /// The instance containing the event data. private void OnEdSpectrumExperimentStarting(object sender, AcquisitionStartingEventArgs e) { } /// /// Called when IEdSpectrumAcquisitionController Experiment Started. /// /// The sender. /// The instance containing the event data. private void OnEdSpectrumExperimentStarted(object sender, AcquisitionStartedEventArgs e) { } private IEdChordListSettings GetChordlistSettings() { if(_edsChordListSetting == null) { _edsChordListSetting = AcquireFactory.CreateEdChordListSettings(); if (_edsChordListSetting!=null) { _edsChordListSetting.EdSettings.AcquisitionMode = EdAcquireMode.LiveTime; _edsChordListSetting.EdSettings.NumberOfChannels = 1024; _edsChordListSetting.EdSettings.ProcessTime = g_nOxfordControllerProcessTime; _edsChordListSetting.EdSettings.EnergyRange = g_nOxfordControllerEnergyRange; _edsChordListSetting.AutoIdSettings.SetKnownElement(79, true); _edsChordListSetting.NumberOfProcessingThreads = 1; } else { NLog.Logger log = NLog.LogManager.GetCurrentClassLogger(); log.Error("Create EDS chordlist setting failed."); } } return _edsChordListSetting; } private IEdChordListAcquisitionController CreateChordlistController() { if (_edsChordListController==null) { _edsChordListController = AcquireFactory.CreateEdChordListServer(); _edsChordListController.PixelProcessed += new EventHandler>(this.OnController_PixelProcessed); _edsChordListController.ExperimentFinished += new EventHandler(this.OnController_ExperimentFinished); var edsChordListSettings = GetChordlistSettings(); while (true) { if(_edsChordListController.IsEdHardwareReady(edsChordListSettings)) { if(edsChordListSettings.EdCapabilities.HasHardwareConnection) { break; } } } } return _edsChordListController; } struct Element { public int m_nAotomaticNo; public double m_dWeight; } private struct OxfordXrayData { public long m_nPosX; public long m_nPosY; public static readonly long[] m_pXrayData = new long[(int)EDSConst.XANA_CHANNELS]; public static readonly char[] vs =new char[1024]; public static readonly OxfordChord[] m_ChordList = new OxfordChord[1024]; public long m_nChordNum; public long m_nPixelNum; internal char[] m_strElementResult; } private void OnController_ExperimentFinished(Object sender,OINA.Extender.Acquisition.AcquisitionFinishedEventArgs e) { if(m_nCollectedXrayCounts== m_nXrayDataCount) { m_nState = OxfordControllerState.SUCCEEDED; } else { m_nState = OxfordControllerState.FAILED; } m_endControllerEvent.Set(); } /// /// /// /// /// private void OnController_PixelProcessed(object sender,EventArgse) { m_nCollectedPixelCounts = m_nCollectedPixelCounts++; //更新当前feature的元素成分 //获取单点的元素结果 var ie = e.Value.QuantStatus.Results.GetEnumerator(); while(ie.MoveNext()) { ISEMQuantResult result = ie.Current; if (result.WeightPercent!=0) { Element Quant = new Element(); Quant.m_nAotomaticNo = result.AtomicNumber; Quant.m_dWeight = result.WeightPercent; if (m_listElementResult==null) { m_listElementResult = new List { Quant }; } else { bool bFind = false; for (int i=0;i< m_listElementResult.Count;i++) { Element element= m_listElementResult[i]; if (Quant.m_nAotomaticNo== element.m_nAotomaticNo) { element.m_dWeight += Quant.m_dWeight; bFind = true; } } if (!bFind) { m_listElementResult.Add(Quant); } } } } //当前的chord数据中pixel没有采集完整 if(m_nCollectedPixelCounts==m_nPixelNum) { //形成quant数据 String Quant = ""; for (int i = 0; i < m_listElementResult.Count; i++) { Element result = m_listElementResult[i]; Quant += "Quant="; String strAoto=ElementProperties.GetElementSymbol(result.m_nAotomaticNo); Quant += strAoto; Quant += ","; Quant += "K-serials"; Quant += ","; String strWeight = (result.m_dWeight / Convert.ToDouble(m_nPixelNum)).ToString(); Quant += strWeight; Quant += "\n"; } String msg = Quant; char[] dst = m_pXrayDataList[m_nCollectedXrayCounts].m_strElementResult; for (int i=0;i /// Called when IEdSpectrumAcquisitionController Experiment Finished /// /// sender object /// The instance containing the event data. private void OnEdSpectrumExperimentFinished(object sender, AcquisitionFinishedEventArgs e) { IEdSpectrumAcquisitionController edSpectrumAcquisitionController = sender as IEdSpectrumAcquisitionController; NLog.Logger log = NLog.LogManager.GetCurrentClassLogger(); IEdSpectrum edSpectrum = e.Value; if (!ReadXrayData(edSpectrum, out m_XrayData, XRayChannelLength)) { MessageBox.Show("Xray采集完成,获取xray失败!"); } long nXraycount = 0; for (int i = 0; i < 2000; i++) { nXraycount += m_XrayData[i]; } //Quantify processing EdSpectrumProcessing.IdentifyElements(e.Value, autoIdSettings); // While it is possible to choose other elements, Oxygen is the only supported element by stoichiometry. quantSettings.CombinedElement = 8; quantSettings.Normalised = true; ISEMQuantStatus quantStatus = EdSpectrumProcessing.SEMQuantifySpectrum(e.Value, quantSettings);//(a_nChannelData, OIHelper::SEMQuantSettings); IEnumerable < ISEMQuantResult > Results = quantStatus.Results; //Get element result for single point //quantStatus.Results. var ie = Results.GetEnumerator(); listElement = new Dictionary(); while (ie.MoveNext()) { ISEMQuantResult result = ie.Current; if (result.WeightPercent != 0) { listElement.Add(ElementProperties.GetElementSymbol(result.AtomicNumber), result.WeightPercent ); } } if (m_XrayData != null && m_XrayData.Length == XRayChannelLength) { log.Info("xray 采集结束事件,采集成功 当前线程" + Thread.CurrentThread.ManagedThreadId.ToString()); log.Info("计数率为:" + nXraycount.ToString()); if (nXraycount < 5000) { log.Warn("计数率低于5000!"); } m_bXrayDone = true; } } bool ReadXrayData(IEdSpectrum a_spectrum, out long[] a_pSpectrumData, int a_nBufferSize) { a_pSpectrumData = new long[a_nBufferSize]; int[] xrayData = new int[a_spectrum.NumberOfChannels]; a_spectrum.GetChannelData(xrayData); double dZeroChannelValue = a_spectrum.ZeroChannelValue; int nChannelStart = 0; if (dZeroChannelValue < 0) // zero channel value should less than zero { nChannelStart = (int)(-dZeroChannelValue / a_spectrum.ChannelWidth + 0.5); } int nDataLength = (int)(a_spectrum.EnergyRange * 1000 / a_spectrum.ChannelWidth + 0.5); double dStep1 = 1.0 / nDataLength; double dStep2 = 1.0 / a_nBufferSize; for (int i = 0; i < nDataLength; ++i) { int nValue = xrayData[i + nChannelStart] > 0 ? xrayData[i + nChannelStart] : 0; double dBinPos = i * dStep1; long nLeftBin = (long)(dBinPos / dStep2); // calculate % into left bin double dLeft_Percent = (double)(nLeftBin + 1) - dBinPos / dStep2; // ((nLeftBin + 1)*dStep2 - dBinPos)/dStep2 // calculate data into the left bin long nValueToLeftBin = (long)((double)nValue * dLeft_Percent + 0.5); // put data into bins a_pSpectrumData[nLeftBin] += nValueToLeftBin; if ((nLeftBin + 1) < (long)a_nBufferSize) { a_pSpectrumData[nLeftBin + 1] += (nValue - nValueToLeftBin); } } return true; } /// /// Called when IEdSpectrum DataChanged /// /// Event source /// Event arguments private void OnDataChanged(object sender, EventArgs e) { } public bool IsAcquiringSpectrum() { return EdSpectrumAcquisitionController.IsAcquiring; } //点扫描 //X-ray public Boolean XrayPointCollecting(double dMilliSecondsTime, double x, double y, out long[] XrayData, out Dictionary a_listElement) { XrayParamInit(); XrayData = new long[XRayChannelLength]; a_listElement = new Dictionary(); SetXrayAcquisitionParam( dMilliSecondsTime); //SetPointAcquistionRegion(x*m_dImagePixelsize, y*m_dImagePixelsize); EdSpectrumSettings.ScanSettings.AcquisitionRegion.CreatePointRegion(new System.Windows.Point(x * m_dImagePixelsize, y * m_dImagePixelsize)); NLog.Logger log = NLog.LogManager.GetCurrentClassLogger(); log.Info("开始XrayStartAcquisition:t="+dMilliSecondsTime.ToString()+"pos="+"("+x.ToString()+","+y.ToString()+")"); if (EdSpectrumAcquisitionController.IsEdHardwareReady(EdSpectrumSettings)) { // Start spectrum acquisition try { m_bXrayDone = false; int lastingTime = 0; IEdSpectrum edSpectrum = EdSpectrumAcquisitionController.StartAcquisition(EdSpectrumSettings); edSpectrum.Label = string.Format(@"Point({0},{1})",x,y); while (true) { if (m_bXrayDone) { XrayData = m_XrayData; a_listElement =listElement; break; } Application.DoEvents(); Thread.Sleep(100); lastingTime += 100; if (lastingTime > EDSColletionTimeOut*3) { //EdSpectrumAcquisitionController.EndMultipleAcquisition(); log.Warn("XrayStartAcquisition 超时!"); return false; } } } catch (InvalidSettingsException invalidSettingsException) { string msg = string.Format(@"Invalid Settings Exception:{0}, {1}", invalidSettingsException.Message, invalidSettingsException.ValidationResults.ValidationErrors); MessageBox.Show(msg); } catch (AcquisitionStartException acquisitionStartException) { string msg = string.Format(@"Acquisition Start Exception:{0}",acquisitionStartException.Message); MessageBox.Show(msg); } } return true; } //面扫描 public Boolean XrayAreaCollectiong(double dMilliSecondsTime, List a_listChord, out long[] XrayData, out Dictionary a_listElement) { XrayParamInit(); XrayData = new long[XRayChannelLength]; a_listElement = new Dictionary(); SetXrayAcquisitionParam(dMilliSecondsTime); List Chords = new List(); foreach (Segment seg in a_listChord) { Chord chord = new Chord(seg.X, seg.Y, seg.Length); Chords.Add(chord); } SetAreaAcquistionRegion(Chords); // IEdSpectrumSettings.EdCapabilities will validate settings and hardware availability. if (EdSpectrumAcquisitionController.IsEdHardwareReady(EdSpectrumSettings)) { // This only used for multiple acquisition: // if this is the first acquisition, call BeginMultipleAcquisition // on the IEdSpectrumAcquisitionController to suppress external scan switching //if (m_bXrayDone) // EdSpectrumAcquisitionController.BeginMultipleAcquisition(); // Start spectrum acquisition try { int lastingTime = 0; IEdSpectrum edSpectrum = EdSpectrumAcquisitionController.StartAcquisition(EdSpectrumSettings); edSpectrum.Label = string.Format(@"chord"); while (true) { if (m_bXrayDone) { XrayData = m_XrayData; a_listElement = listElement; break; } Thread.Sleep(100); Application.DoEvents(); lastingTime += 100; if (lastingTime > EDSColletionTimeOut * 8) { return false; } } } catch (InvalidSettingsException invalidSettingsException) { string msg = string.Format(@"Invalid Settings Exception:{0}, {1}", invalidSettingsException.Message, invalidSettingsException.ValidationResults.ValidationErrors); MessageBox.Show(msg); } catch (AcquisitionStartException acquisitionStartException) { string msg = string.Format(@"Acquisition Start Exception:{0}", acquisitionStartException.Message); MessageBox.Show(msg); } } return true; } public void BeginMultipleAquisition() { EdSpectrumAcquisitionController.BeginMultipleAcquisition(); } public void EndMultipleAquisition() { EdSpectrumAcquisitionController.EndMultipleAcquisition(); } public void BeginAreaModeMultipleAquisition() { var controller = CreateChordlistController(); controller.BeginMultipleAcquisition(); } public void EndAreaModeMultipleAquisition() { var controller = CreateChordlistController(); controller.EndMultipleAcquisition(); } #endregion } }