| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636 | using System.Collections.Generic;using OTSDataType;using System;using System.Drawing;using static OTSDataType.otsdataconst;using OTSModelSharp.ImageProcess;using OTSModelSharp.ServiceInterface;using System.Threading;namespace OTSModelSharp{    // enum and struct used for send message to App    public enum ENUM_MSG_TYPE    {        MTHREADSTATUS = 1001,        MSAMPLESTATUS = 1002,        MSAMPLERESULT = 1003    };    public enum MSAMPLE_RET    {        BSE_DATA = 0,        FIELD_DATA = 1,        START_MSR_FIELD = 2    };    public struct SMSR_COMPLETE_DATA    {        public OTS_MSR_THREAD_STATUS MsrStatus;        public string csMsrStartTime;        public int iMsrCompleteSampleCount;        public int iMsrCompleteFieldCount;        public int iParticleCount;        public TimeSpan MsrUsedTime;        public string csMsrEndTime;    };    public struct STMThreadStatus    {        public OTS_MSR_THREAD_STATUS iMsrStatu;        //OTS_MSR_THREAD_STATUS        public string csMsrStartTime;   //MSR_START_TIME        public string csMsrEndTime;     //MSR_END_TIME        public SMSR_COMPLETE_DATA SMsrCompleteData;    };    public struct STMSampleStatus    {        public OTS_MSR_SAMPLE_STATUS iMsrSampleStatu;    //OTS_MSR_SAMPLE_STATUS        public string cSampleName;        public string csSampleMsrStartTime;        public List<PointF> BCompleteFieldList;    };    public struct STMSampleResultData    {        public MSAMPLE_RET iRetDataType;                 //ENUM_MEASURE_SAMPLE_RESULT        public struct RBSEDATA        {            public System.Drawing.Point pos;            public int iBSEDataHeight;            public int iBSEDataWidth;            public byte[] lpBSEData;        };        public struct SAMPLEFIELDDATA        {            public System.Drawing.Point FieldPos;            public int iMeasureFieldCount;            public int iCompleteFieldCount;            public int iSParticleCount;     // Field particle count            public TimeSpan TUsedTime;        };        public struct StartToMsrField        {            public System.Drawing.Point FieldPos;        };        public RBSEDATA BSEData;        public SAMPLEFIELDDATA SFieldData;        public StartToMsrField SMsrField;    };    public  struct ST_MSTMsg    {          public ENUM_MSG_TYPE iMsgType;      public   STMThreadStatus STMThreadStu;      public   STMSampleStatus STMSampleStu;      public   STMSampleResultData STMSampleRetData;    };        public class CMeasure    {              private const string UNTITLED_FILE_NAME = "Untitled";        public delegate void   ProgressEventHandler(ST_MSTMsg msg);        public event ProgressEventHandler ProgressEvent;        COTSMsrPrjResultData m_pProjData;        List< COTSSample> m_listMeasurableSamples=new List<COTSSample>();        string m_strWorkingFolder;        CMsrThreadStatus m_ThreadStatus;                     SemController m_SemController;// there is no correspondense clr,so use this instead temporarilly        protected static NLog.Logger loger = NLog.LogManager.GetCurrentClassLogger();       public SortedDictionary<string, CSmplMeasure> mapSmplMsr = new SortedDictionary<string, CSmplMeasure>();//use this map to hold all the smplMeasure object         public List<COTSSample> GetListMeasurableSamples()        {            return m_listMeasurableSamples;        }        public void SetListMeasurableSamples(List<COTSSample> value)        {            m_listMeasurableSamples = value;        }        public CMeasure()        {                     m_strWorkingFolder = "";            m_ThreadStatus = new CMsrThreadStatus();            m_SemController = SemController.GetSEMController();                   }               public COTSMsrPrjResultData GetProjResultData()        {            return m_pProjData;        }        public ISemController GetSEMController()        {            // get SEM, scanner and x-ray controller via hardware manager            return m_SemController;        }             public CMsrThreadStatus GetMsrThreadStatus() { return m_ThreadStatus; }       public  void Init(COTSMsrPrjResultData a_pProjMgrFile)        {            m_pProjData = a_pProjMgrFile;                       SetListMeasurableSamples(a_pProjMgrFile.GetSampleList());            return ;        }        void ThreadOver()        {                      DateTime timeEnd = m_ThreadStatus.GetEndTime();             ST_MSTMsg MsrMsg = new ST_MSTMsg();            MsrMsg.iMsgType = ENUM_MSG_TYPE.MTHREADSTATUS;                    MsrMsg.STMThreadStu.iMsrStatu = m_ThreadStatus.GetStatus();                    MsrMsg.STMThreadStu.csMsrEndTime = timeEnd.ToString("yyyy-MM-dd HH:mm:ss");            ProgressEvent(MsrMsg);                          }        void ThreadOverWithoutDisConnect()        {            DateTime timeEnd = m_ThreadStatus.GetEndTime();            ST_MSTMsg MsrMsg = new ST_MSTMsg();            MsrMsg.iMsgType = ENUM_MSG_TYPE.MTHREADSTATUS;            MsrMsg.STMThreadStu.iMsrStatu = m_ThreadStatus.GetStatus();                      MsrMsg.STMThreadStu.csMsrEndTime = timeEnd.ToString("yyyy-MM-dd HH:mm:ss");            ProgressEvent(MsrMsg);                }        void SetWorkingFolderStrAndSaveCurrentSettings()        {            // get project file pathname            string  strSettingFilePathName = m_pProjData.GetPathName();            strSettingFilePathName.Trim();            if (strSettingFilePathName == "")            {                loger .Error("SetWorkingFolderStr: project file pathname is an empty string");                return ;            }            else if (strSettingFilePathName==UNTITLED_FILE_NAME)            {                loger .Error ("SetWorkingFolderStr: project file pathname is an invalid string");                return ;            }            // working folder string             m_strWorkingFolder = FileHelper.GetFolderName(strSettingFilePathName);            m_pProjData.Save();            return ;        }       public void SendMessageToMeasureApp(ST_MSTMsg msg)        {            ProgressEvent(msg);        }        public bool IsMeasureStopped()        {            return m_ThreadStatus.GetStatus() == OTS_MSR_THREAD_STATUS.STOPPED;        }        public bool  IsMeasureRunning() { return m_ThreadStatus.GetStatus() == OTS_MSR_THREAD_STATUS.INPROCESS; }        public bool  IsMeasureFailed() { return m_ThreadStatus.GetStatus() == OTS_MSR_THREAD_STATUS.FAILED; }        public bool  IsMeasureCompleted() { return m_ThreadStatus.GetStatus() == OTS_MSR_THREAD_STATUS.COMPLETED; }        public   void DoMeasure()        {            // start measurement, creat thread measure status class, let the main thread know that measurement started            m_ThreadStatus.SetStartTime(System.DateTime.Now);            DateTime timeStart = m_ThreadStatus.GetStartTime();                         ST_MSTMsg MsgMsrStart=new ST_MSTMsg();            MsgMsrStart.iMsgType  = ENUM_MSG_TYPE.MTHREADSTATUS;            MsgMsrStart.STMThreadStu.iMsrStatu = OTS_MSR_THREAD_STATUS.INPROCESS;            MsgMsrStart.STMThreadStu.csMsrStartTime = timeStart.ToShortDateString();            ProgressEvent (MsgMsrStart);            loger.Info("Measurement started!");            // connect hardware            loger.Info("Connect SEM!");            if (!m_SemController.Connect())            {                loger .Error("DoMeasure: failed to connect hardware.");                m_ThreadStatus.SetStatus(OTS_MSR_THREAD_STATUS.FAILED);                            m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);                ThreadOver();                return;            }            // set working directory which is the same directory of the setting file            SetWorkingFolderStrAndSaveCurrentSettings();                         List <string >  listMeasuredSamples = m_ThreadStatus.GetCompletedSamples();            // got through measure list            foreach (var pSample in GetListMeasurableSamples())            {// check and break if stop button is clicked                 if (m_ThreadStatus.GetStatus()== OTS_MSR_THREAD_STATUS.STOPPED )                {                    // stop button clicked                    loger .Info("DoMeasure: stop button is clicked.");                                       // record end time                    m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);                    ThreadOver();                    return;                }                if (m_ThreadStatus.GetStatus() == OTS_MSR_THREAD_STATUS.PAUSED)                {                    // stop button clicked                    loger.Info("DoMeasure: stop button is clicked.");                    // record end time                    m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);                    while (m_ThreadStatus.GetStatus() == OTS_MSR_THREAD_STATUS.PAUSED)                    {                        Thread.Sleep(300);                    }                    //return;                }                if (!pSample.GetSwitch())                {                    continue;                }                var sta = pSample.GetMsrStatus().GetStatus();                if (sta == OTS_MSR_SAMPLE_STATUS.SUCCESSED || sta == OTS_MSR_SAMPLE_STATUS.STOPPED)                {                    continue;                                }                             CSmplMeasure pSmplMeasure;                if (!mapSmplMsr.ContainsKey(pSample.GetName()))                {// create a sample measure object for the sample                    switch (m_pProjData.m_nPackId)                    {                        case OTS_SysType_ID.IncA:                            pSmplMeasure = new CSmplMeasureInclution(m_strWorkingFolder, pSample);                            break;                        case OTS_SysType_ID.CleannessA:                            pSmplMeasure = new CSmplMeasureCleanliness(m_strWorkingFolder, pSample);                            break;                        default:                            pSmplMeasure = new CSmplMeasureInclution(m_strWorkingFolder, pSample);                            break;                    }                                                                                 // set measure thread                    pSmplMeasure.SetMsrThread(this);                    mapSmplMsr[pSample.GetName()] = pSmplMeasure;                }                else                {                    pSmplMeasure = mapSmplMsr[pSample.GetName()];                    pSample.GetMsrStatus().SetStatus(OTS_MSR_SAMPLE_STATUS.INPROCESS);                    m_ThreadStatus.SetStatus(OTS_MSR_THREAD_STATUS.INPROCESS);                }                               pSmplMeasure.DoMeasureForOneSample();                           // check if measurement is successful                if (pSample.GetMsrStatus().GetStatus() == OTS_MSR_SAMPLE_STATUS.PAUSED)                {// record end time                    m_ThreadStatus.SetStatus(OTS_MSR_THREAD_STATUS.PAUSED);                    m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);                    // update thread measure status class, let the main thread know that this sample measurement stopped                    ST_MSTMsg MsgSmpStop = new ST_MSTMsg();                    MsgSmpStop.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;                    MsgSmpStop.STMThreadStu.iMsrStatu = OTS_MSR_THREAD_STATUS.PAUSED;                    MsgSmpStop.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.PAUSED;                    MsgSmpStop.STMThreadStu.csMsrEndTime = DateTime.Now.ToShortDateString();                    MsgSmpStop.STMThreadStu.iMsrStatu = OTS_MSR_THREAD_STATUS.PAUSED;                    ProgressEvent(MsgSmpStop);                    ThreadOver();                    return;                }else if (pSample.GetMsrStatus().GetStatus() == OTS_MSR_SAMPLE_STATUS.STOPPED)                {// record end time                    m_ThreadStatus.SetStatus(OTS_MSR_THREAD_STATUS.STOPPED);                    m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);                    // update thread measure status class, let the main thread know that this sample measurement stopped                    ST_MSTMsg MsgSmpStop = new ST_MSTMsg();                     MsgSmpStop.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;                    MsgSmpStop.STMThreadStu.iMsrStatu= OTS_MSR_THREAD_STATUS.STOPPED;                    MsgSmpStop.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.STOPPED;                    MsgSmpStop.STMThreadStu.csMsrEndTime = DateTime .Now .ToShortDateString();                    MsgSmpStop.STMThreadStu.iMsrStatu= OTS_MSR_THREAD_STATUS.STOPPED;                    ProgressEvent(MsgSmpStop);                    ThreadOver();                    break;                }			    else if (pSample.GetMsrStatus().GetStatus() == OTS_MSR_SAMPLE_STATUS.FAILED)			    {                    // measurement failed                    m_ThreadStatus.SetStatus(OTS_MSR_THREAD_STATUS.FAILED);                // record end time                    m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);                // update thread measure status class, let the main thread know that this sample measurement failed                ST_MSTMsg MsgSmpFailed=new ST_MSTMsg();                               MsgSmpFailed.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;				MsgSmpFailed.STMSampleStu.iMsrSampleStatu =  OTS_MSR_SAMPLE_STATUS.FAILED;                                                     ProgressEvent(MsgSmpFailed);                ThreadOver();				  return;			    }                              // update thread measure status class, let the main thread know that this sample measurement successes                ST_MSTMsg MsgSmpSuccess = new ST_MSTMsg();                MsgSmpSuccess.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;                MsgSmpSuccess.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.SUCCESSED;                ProgressEvent(MsgSmpSuccess);                // continue to the next sample                listMeasuredSamples.Add(pSample.GetName());            }            // measurement completed            m_ThreadStatus.SetStatus(OTS_MSR_THREAD_STATUS.COMPLETED);            // record end time            m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);            ThreadOver();	}        //public bool DoReMeasure(List<Particle> particles, int imgscanspeed_index, int xrayscanmode_index, int scantime_count)        //{        //    // got through measure list        //    foreach (var pSample in m_listMeasurableSamples)        //    {        //        // check and break if stop button is clicked         //        if (m_ThreadStatus.GetStatus() == OTS_MSR_THREAD_STATUS.STOPPED)        //        {        //            // stop button clicked        //            loger.Info("DoMeasure: stop button is clicked.");        //            // record end time        //            m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);        //            ThreadOver();        //            return false;        //        }        //        CSmplMeasure pSmplMeasure;        //        // create a sample measure object for the sample        //        switch (m_pProjData.m_nPackId)        //        {        //            case OTS_SysType_ID.IncA:        //                pSmplMeasure = new CSmplMeasureInclution(m_strWorkingFolder, pSample);        //                break;        //            case OTS_SysType_ID.CleannessA:        //                pSmplMeasure = new CSmplMeasureCleanliness(m_strWorkingFolder, pSample);        //                break;        //            default:        //                pSmplMeasure = new CSmplMeasureInclution(m_strWorkingFolder, pSample);        //                break;        //        }        //        // set measure thread        //        pSmplMeasure.SetMsrThread(this);        //        pSmplMeasure.DoMeasureForOneSample();        //    }        //    // measurement completed        //    m_ThreadStatus.SetStatus(OTS_MSR_THREAD_STATUS.COMPLETED);        //    // record end time        //    m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);        //    ThreadOver();        //    return true;        //}        // hole preview        public  void DoHolePreview()        {            // start measurement, creat thread measure status class, let the main thread know that measurement started            // set measure status to in-process            //record time            m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.START);            DateTime timeStart = m_ThreadStatus.GetStartTime();              ST_MSTMsg MsgMsrStart = new ST_MSTMsg();                      MsgMsrStart.iMsgType = ENUM_MSG_TYPE.MTHREADSTATUS;            MsgMsrStart.STMThreadStu.iMsrStatu =OTS_MSR_THREAD_STATUS.INPROCESS;                     SendMessageToMeasureApp(MsgMsrStart);            // connect hardware            if (!m_SemController.Connect())            {                // failed to connect hardware                                SetMsrLoopStatus(otsdataconst.OTS_MSR_THREAD_STATUS.FAILED);                m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);                ThreadOverWithoutDisConnect();            }            var a_pMeasureArea = m_pProjData.GetWorkingSample().GetMsrDomain();            COTSSample pSampleHole = CreateHoleSample(a_pMeasureArea);            var sample = m_pProjData.GetWorkingSample();            // create a sample measure object for the sample            CSmplMeasure pSmplMeasure = new CSmplMeasure(m_strWorkingFolder, sample);                      // set measure thread            pSmplMeasure.SetMsrThread(this);            // update thread measure status class, let the main thread know that this sample measurement starts            // set working folder string            pSmplMeasure.SetSample(sample);            pSmplMeasure.SetHolePreviewSample(pSampleHole);            pSmplMeasure.SetWorkingFolder(m_strWorkingFolder);            // do measure            pSmplMeasure.DoHolePreview();            // check if measurement is successful            if (pSampleHole.GetMsrStatus().GetStatus() == OTS_MSR_SAMPLE_STATUS.STOPPED)            {                // record end time                m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);                // measurement stopped                SetMsrLoopStatus(otsdataconst.OTS_MSR_THREAD_STATUS.STOPPED);                // update thread measure status class, let the main thread know that this sample measurement stopped                ST_MSTMsg MsgSmpStop = new ST_MSTMsg();                           MsgSmpStop.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;                MsgSmpStop.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.STOPPED;                          SendMessageToMeasureApp(MsgSmpStop);                ThreadOverWithoutDisConnect();                return;            }            else if (pSampleHole.GetMsrStatus().GetStatus() == OTS_MSR_SAMPLE_STATUS.FAILED)            {                // measurement failed                SetMsrLoopStatus(otsdataconst.OTS_MSR_THREAD_STATUS.FAILED);                // record end time                m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);                // update thread measure status class, let the main thread know that this sample measurement failed                ST_MSTMsg MsgSmpFailed = new ST_MSTMsg();                          MsgSmpFailed.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;                MsgSmpFailed.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.FAILED;                           SendMessageToMeasureApp(MsgSmpFailed);                ThreadOverWithoutDisConnect();                return;            }            // record end time            m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);            // update thread measure status class, let the main thread know that this sample measurement successes            ST_MSTMsg MsgSmpSuccess = new ST_MSTMsg();                     MsgSmpSuccess.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;            MsgSmpSuccess.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.SUCCESSED;                     SendMessageToMeasureApp(MsgSmpSuccess);            // measurement completed            SetMsrLoopStatus(otsdataconst.OTS_MSR_THREAD_STATUS.COMPLETED);            // record end time            m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);            ThreadOverWithoutDisConnect();        }      public  COTSSample CreateHoleSample(CDomain a_pMsrArea)        {                        COTSSample pHoleSample = new COTSSample();            pHoleSample.SetMsrDomain(a_pMsrArea);                       // get min magnification            CSEMStageData pSEMStageData = m_pProjData.GetSEMStageData();            double dMinMag = pSEMStageData.GetMinMag();            // get scan field size 100            int nScanFieldSize100 = pSEMStageData.GetScanFieldSize100();            // get working distance            double dWorkingDistance = 0.0;            if (!GetSEMWorkingDistanceFromHW(ref dWorkingDistance))            {                return null;            }            CSEMDataMsr poSEMDataMsr = new CSEMDataMsr();            poSEMDataMsr.SetScanFieldSize100(nScanFieldSize100);            poSEMDataMsr.SetWorkingDistance(dWorkingDistance);            poSEMDataMsr.SetMagnification(dMinMag);            pHoleSample.SetSEMDataMsr(poSEMDataMsr);            // Set image scan param            COTSImgScanPrm poImageScanParam = new COTSImgScanPrm();            poImageScanParam.SetStopMode(((int)OTS_MEASURE_STOP_MODE.CoverMode).ToString());            poImageScanParam.SetStartImageMode(OTS_GET_IMAGE_MODE.FROM_CENTER);            poImageScanParam.SetScanImageSpeed(OTS_IMAGE_SCANSPEED_OPTIONS.low);            //poImageScanParam.SetImagePixelSize(OTS_FIVE_TIES_OPTIONS.TIE1);            CSampleParam poMsrParams = pHoleSample.GetMsrParams();            poImageScanParam.SetImageResulotion(GetListMeasurableSamples()[0].GetMsrParams().GetImageScanParam().GetImageResulotion());//由于各样品分辨率应该一致,故此处没有读取选取的特定样品孔样品            poMsrParams.SetImageScanParam(poImageScanParam);            pHoleSample.SetMsrParams(poMsrParams);            poMsrParams.GetImageProcessParam().SetOverlapParam(GetListMeasurableSamples()[0].GetMsrParams().GetImageProcessParam().GetOverlapParam());            return pHoleSample;        }      public  bool GetSEMWorkingDistanceFromHW(ref double a_dWorkingDistance)        {            m_SemController.GetWorkingDistance(ref a_dWorkingDistance);            return true;        }            // measure status       public void SetMsrLoopStatus(otsdataconst.OTS_MSR_THREAD_STATUS a_nMsrLoopStatus)        {                          m_ThreadStatus.SetStatus( a_nMsrLoopStatus);                    }        }}
 |