diff --git a/ApplicationServer/AppServerPipe.cs b/ApplicationServer/AppServerPipe.cs index a9ec779..f03f639 100644 --- a/ApplicationServer/AppServerPipe.cs +++ b/ApplicationServer/AppServerPipe.cs @@ -6,6 +6,9 @@ namespace WorkflowServer { + /// + /// Class is used to communicate and run processing workflows on data received from the client. + /// internal class AppServerPipe { public event EventHandler PipeConnected; @@ -23,8 +26,6 @@ internal class AppServerPipe private ProcessMs2ScansDelegate? Ms2Delegate { get; set; } // static class with processing workflows? public AppServerPipe(NamedPipeServerStream pipeServer, - StreamWriter sw, - StreamReader sr, int ms1ScanQueueThreshold, int ms2ScanQueueThreshold, ProcessMs1ScansDelegate ms1Delegate = null, @@ -39,83 +40,55 @@ public AppServerPipe(NamedPipeServerStream pipeServer, Ms2Delegate = ms2Delegate; } + /// + /// Begins the server connection; starts the async buffer reader; connects event handler methods to events. + /// public void StartServer() { PipeConnected += (obj, sender) => { Console.WriteLine("Pipe client connected. Sent from event."); }; - // delegate for processing needs to be used as a function. - ProcessMs1ScansDelegate ms1Del = (o, scans) => - { - // select highest m/z from the scans and send a singlescandataobject back to client - List mzPrecursors = new(); - foreach (var sc in scans.ListSsdo) - { - double max = sc.YArray.Max(); - int posX = Array.IndexOf(sc.YArray, max); - mzPrecursors.Add(sc.XArray[posX]); - } - - foreach (var mz in mzPrecursors) - { - SingleScanDataObject ssdoTemp = new() - { - ScanOrder = 2, - ScanNumber = 10, - PrecursorScanNumber = 3, - MzPrecursor = 15, - XArray = new double[] { 0, 0 }, - YArray = new double[] { 0, 0 } - }; - string temp = JsonConvert.SerializeObject(ssdoTemp); - byte[] buffer = Encoding.UTF8.GetBytes(temp); - byte[] length = BitConverter.GetBytes(buffer.Length); - byte[] finalBuffer = length.Concat(buffer).ToArray(); - PipeServer.Write(finalBuffer, 0, finalBuffer.Length); - PipeServer.WaitForPipeDrain(); - } - - }; - + PipeDataReceived += HandleDataReceived; - Ms1ScanQueueThresholdReached += ms1Del.Invoke; + Ms1ScanQueueThresholdReached += Ms1Delegate.Invoke; Ms2ScanQueueThresholdReached += Ms2Delegate.Invoke; Ms1ProcessingCompleted += (object? obj, ProcessingCompletedEventArgs sender) => { - + Console.WriteLine("Ms1 Processing Completed"); }; Ms2ProcessingCompleted += (object? obj, ProcessingCompletedEventArgs sender) => { - byte[] buffer = Encoding.UTF8.GetBytes("15"); - var taskResult = new ValueTask(); - taskResult = PipeServer.WriteAsync(buffer); - buffer = null; + + Console.WriteLine("Ms2 Processing Completed."); }; var connectionResult = PipeServer.BeginWaitForConnection(Connected, null); // wait for the connection to occur before proceeding. connectionResult.AsyncWaitHandle.WaitOne(); connectionResult.AsyncWaitHandle.Close(); - var serializer = new JsonSerializer(); StartReaderAsync(); - while (PipeServer.IsConnected) - { - - } } + /// + /// Used to determine which queue scan that was received from server should go into. + /// + /// + /// + /// private void HandleDataReceived(object? obj, PipeEventArgs eventArgs) { // convert pipeeventargs to single scan data object SingleScanDataObject ssdo = eventArgs.ToSingleScanDataObject(); if (ssdo == null) throw new ArgumentException("single scan data object is null"); + // TODO: refactor and make handling more robust downstream. if (ssdo.ScanOrder == 1) { ScanQueueMS1.Enqueue(ssdo); if (ScanQueueMS1.Count == Ms1ScanQueueThreshold) { + // method raises event OnMs1QueueThresholdReached(ScanQueueMS1); } } @@ -124,32 +97,51 @@ private void HandleDataReceived(object? obj, PipeEventArgs eventArgs) ScanQueueMS2.Enqueue(ssdo); if (ScanQueueMS2.Count == Ms2ScanQueueThreshold) { + // method raises handler OnMs2QueueThresholdReached(ScanQueueMS2); } - } + } // TODO: Handle scan order > 2. Console.WriteLine("\n"); } + /// + /// Triggers event that begins processing of Ms1 queue. + /// + /// private void OnMs1QueueThresholdReached(Queue queue) { Ms1ScanQueueThresholdReached?.Invoke(this, new ScanQueueThresholdReachedEventArgs(queue.DequeueChunk(Ms1ScanQueueThreshold))); } + /// + /// Triggers event that begins processing of Ms2 queue. + /// + /// private void OnMs2QueueThresholdReached(Queue queue) { Ms2ScanQueueThresholdReached?.Invoke(this, new ScanQueueThresholdReachedEventArgs(queue.DequeueChunk(Ms2ScanQueueThreshold))); } + /// + /// Callback method used to wait for client pipe connection. + /// + /// private void Connected(IAsyncResult ar) { OnConnection(); PipeServer.EndWaitForConnection(ar); } - private void OnConnection() { PipeConnected?.Invoke(this, EventArgs.Empty); } - + /// + /// Begins asynchronous buffer reading. Converts the first four bytes into the integer size of the object contained in the rest of the buffer. + /// Then creates the buffer of that size and reads the data into the buffer. + /// + /// DO NOT MODIFY OR THINK ABOUT + /// MODIFYING THIS METHOD UNLESS YOU 100% KNOW WHAT IT DOES AND WHAT YOU ARE CHANGING. + /// + /// The Action delegate determines what is done with the byte buffer that is received. private void StartByteReaderAsync(Action packetReceived) { byte[] byteDataLength = new byte[sizeof(int)]; @@ -169,11 +161,20 @@ private void StartByteReaderAsync(Action packetReceived) }); }); } - + /// + /// Starts the reader asynchronously and triggers the PipeDataReceived event when data is received from the pipe. + /// public void StartReaderAsync() { StartByteReaderAsync((b) => PipeDataReceived?.Invoke(this, new PipeEventArgs(b))); } + + private void SendScanToClient(object obj, ProcessingCompletedEventArgs sender) + { + byte[] buffer = sender.Ssdo.CreateSerializedSingleScanDataObject(); + PipeServer.WriteAsync(buffer, 0, buffer.Length); + PipeServer.WaitForPipeDrain(); + } } } diff --git a/ApplicationServer/Program.cs b/ApplicationServer/Program.cs index c7b2ba4..e94f88c 100644 --- a/ApplicationServer/Program.cs +++ b/ApplicationServer/Program.cs @@ -1,9 +1,9 @@ using System.IO.Pipes; -using ClientServerCommunication; -using Data; +using ClientServerCommLibrary; using InstrumentControl; using Newtonsoft; using Newtonsoft.Json; +using WorkflowServer; namespace ApplicationServer { @@ -11,7 +11,38 @@ public class Program { public static void Main(string[] args) { + NamedPipeServerStream pipe = new NamedPipeServerStream("test", PipeDirection.InOut,5, + PipeTransmissionMode.Byte, PipeOptions.Asynchronous); + ProcessMs1ScansDelegate ms1Del = (obj, ev) => + { + //Console.WriteLine(ev.ListSsdo.First().MaxX); + }; + ProcessMs2ScansDelegate ms2Del = (obj, ev) => + { + //Console.WriteLine(ev.ListSsdo.First().PrecursorScanNumber); + }; + AppServerPipe appPipe = new(pipe, 1, 1, ms1Del, ms2Del); + + bool connectedBool = false; + appPipe.PipeConnected += (obj, ev) => + { + connectedBool = true; + }; + appPipe.PipeDataReceived += (obj, ev) => + { + var scan = ev.ToSingleScanDataObject(); + Console.WriteLine(scan.MaxX); + }; + appPipe.StartServer(); + while (connectedBool) + { + //appPipe.PipeDataReceived += (obj, ev) => + //{ + // var scan = ev.ToSingleScanDataObject(); + // Console.WriteLine(scan.MaxX.ToString()); + //}; + } } } } \ No newline at end of file diff --git a/ApplicationServer/Properties/launchSettings.json b/ApplicationServer/Properties/launchSettings.json index 5570a64..9c95913 100644 --- a/ApplicationServer/Properties/launchSettings.json +++ b/ApplicationServer/Properties/launchSettings.json @@ -1,8 +1,7 @@ { "profiles": { "ApplicationServer": { - "commandName": "Project", - "commandLineArgs": "simple Server" + "commandName": "Project" } } } \ No newline at end of file diff --git a/ApplicationServer/ScanQueue/ScanQueue.cs b/ApplicationServer/ScanQueue/ScanQueue.cs index 3c887ab..23fc130 100644 --- a/ApplicationServer/ScanQueue/ScanQueue.cs +++ b/ApplicationServer/ScanQueue/ScanQueue.cs @@ -1,4 +1,5 @@ -using Data; +using ClientServerCommLibrary; + namespace ApplicationServer { diff --git a/ApplicationServer/ScanQueue/ThresholdReachedEventArgs.cs b/ApplicationServer/ScanQueue/ThresholdReachedEventArgs.cs index 658e006..76d4b7f 100644 --- a/ApplicationServer/ScanQueue/ThresholdReachedEventArgs.cs +++ b/ApplicationServer/ScanQueue/ThresholdReachedEventArgs.cs @@ -1,4 +1,4 @@ -using Data; +using ClientServerCommLibrary; namespace ApplicationServer { diff --git a/ApplicationServer/WorkflowServer.csproj b/ApplicationServer/WorkflowServer.csproj index 65865a5..e205882 100644 --- a/ApplicationServer/WorkflowServer.csproj +++ b/ApplicationServer/WorkflowServer.csproj @@ -9,6 +9,7 @@ + diff --git a/Client/IScanTranslator.cs b/Client/IScanTranslator.cs new file mode 100644 index 0000000..f793add --- /dev/null +++ b/Client/IScanTranslator.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using ClientServerCommLibrary; + +namespace Client +{ + public abstract class ScanTranslator + { + public abstract void Translate(SingleScanDataObject ssdo); + } +} diff --git a/Client/InstrumentClient.csproj b/Client/InstrumentClient.csproj index e9ec032..affd4ff 100644 --- a/Client/InstrumentClient.csproj +++ b/Client/InstrumentClient.csproj @@ -1,5 +1,6 @@  + Debug @@ -12,6 +13,8 @@ 512 true true + + x64 @@ -47,6 +50,9 @@ ..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll + + ..\packages\NUnit.3.13.3\lib\net45\nunit.framework.dll + False ..\..\..\..\..\..\Thermo\Instruments\TNG\OrbitrapFusionLumos\3.3\System\Programs\Spectrum-1.0.dll @@ -73,9 +79,13 @@ + + + + @@ -90,11 +100,13 @@ {0e9b5801-5167-44cc-90d3-c8caf1df8f6a} ClientServerCommLibrary - - {6b34249b-a513-4a4a-9ed5-cb633bcab646} - Data - + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + \ No newline at end of file diff --git a/Client/InstrumentClientPipe.cs b/Client/InstrumentClientPipe.cs index b5fcc99..a6bda36 100644 --- a/Client/InstrumentClientPipe.cs +++ b/Client/InstrumentClientPipe.cs @@ -5,9 +5,11 @@ using System.Threading.Tasks; using ClientServerCommLibrary; using System.IO.Pipes; +using System.Runtime.Remoting.Channels; using Microsoft.Win32; + namespace InstrumentClient { public class ClientPipe @@ -99,27 +101,25 @@ private void StartByteReaderAsync(Action packetReceived) #region Client to Instrument Methods public void BeginInstrumentConnection(IInstrument instr) { - bool instrReadyToReceiveScan = false; instr.OpenInstrumentConnection(); - instr.InstrumentConnected += (obj, sender) => { InstrumentConnectedBool = true; }; - instr.InstrumentDisconnected += (obj, sender) => { InstrumentConnectedBool = false; }; - instr.ReadyToReceiveScan += (obj, sender) => { instrReadyToReceiveScan = true; }; - instr.ScanReceived += (obj, sender) => - { - // send scan to the server. - }; - - ScanQueueThresholdReached += (obj, sender) => + instr.InstrumentReadyToReceiveScan += (obj, sender) => { - // send the scan to the instrument + // check if queue contains anything and send scan action if it does. + if (ScanInstructionsQueue.Count > 0) + { + instr.SendScanAction(ScanInstructionsQueue.Dequeue()); + } }; - // enter instrument main routine: - while (InstrumentConnectedBool) - { - - } + instr.ScanReceived += SendScanToServer; } #endregion + + private void SendScanToServer(object obj, ScanReceivedEventArgs sender) + { + byte[] buffer = sender.Ssdo.CreateSerializedSingleScanDataObject(); + PipeClient.WriteAsync(buffer, 0, buffer.Length); + PipeClient.WaitForPipeDrain(); + } } } diff --git a/Client/InstrumentInterfaces/IInstrument.cs b/Client/InstrumentInterfaces/IInstrument.cs index d583988..2d96dc5 100644 --- a/Client/InstrumentInterfaces/IInstrument.cs +++ b/Client/InstrumentInterfaces/IInstrument.cs @@ -1,8 +1,5 @@ -using ClientServerCommunication; +using ClientServerCommLibrary; using System; -using Data; -using Thermo.Interfaces.InstrumentAccess_V1.MsScanContainer; -using ScanInstructions = Data.ScanInstructions; namespace InstrumentClient { @@ -15,24 +12,30 @@ public interface IInstrument // send action (Ms1 scan, SIM scan, boxcar scan, etc.) to instrument // open instrument connection // close instrument connection + + /// + /// Used for explicitly gaining access to the last received instrument scan without requiring an event. + /// + /// Returns SingleScanDataObject. SingleScanDataObject GetLastScan(); void SendScanAction(SingleScanDataObject ssdo); void OpenInstrumentConnection(); void CloseInstrumentConnection(); - void GetSystemState(); + string GetSystemState(int stateOrMode); void CancelAcquisition(); void PauseAcquisition(); void ResumeAcquisition(); - void StartAcquisition(); + void StartAcquisition(string rawFileName); void StartMethodAcquistion(string methodFilePath, string methodName, string outputFileName, string sampleName, double timeInMinutes); void InstrumentOn(); void InstrumentOff(); - void InstrumentStandby(); + void InstrumentStandby(); + void GetScanPossibleParameters(); event EventHandler InstrumentConnected; event EventHandler InstrumentDisconnected; - event EventHandler ScanReceived; - event EventHandler ReadyToReceiveScan; + event EventHandler ScanReceived; + event EventHandler InstrumentReadyToReceiveScan; } } \ No newline at end of file diff --git a/Client/InstrumentInterfaces/Thermo/DataHandling/InstrumentSettingEnums.cs b/Client/InstrumentInterfaces/Thermo/DataHandling/InstrumentSettingEnums.cs new file mode 100644 index 0000000..01104e2 --- /dev/null +++ b/Client/InstrumentInterfaces/Thermo/DataHandling/InstrumentSettingEnums.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Client +{ + internal class InstrumentSettingEnums + { + public enum InstrumentSettings + { + // common + FirstMass, + LastMass, + Analyzer, + ScanType, + SourceCIDEnergy, + SrcRFLens, + Polarity, + DataType, + IsolationMode, + AGCTarget, + MaxIT, + Microscans, + + // detector resolutions + OrbitrapResolution, + ScanRate, + + // ms1 is only defined by the common settings + + // ms2 only + CollisionEnergy, + IsolationWidth, + ActivationType, + ChargeStates, + ActivationQ, + PrecursorMass, + ReactionTime, + ReagentMaxIT, + ReagentAGCTarget + } + + + public enum Analyzer + { + IonTrap, + Orbitrap + } + public enum ScanType + { + Full, + SIM, + MSn + } + public enum Polarity + { + Postive, + Negative + } + public enum DataType + { + Centroid, + Profile + } + public enum IsolationMode + { + None, + Quadrupole, + IonTrap + } + + } +} diff --git a/Client/InstrumentInterfaces/Thermo/DataHandling/MsScanExtensions.cs b/Client/InstrumentInterfaces/Thermo/DataHandling/MsScanExtensions.cs index 9f733d9..968763d 100644 --- a/Client/InstrumentInterfaces/Thermo/DataHandling/MsScanExtensions.cs +++ b/Client/InstrumentInterfaces/Thermo/DataHandling/MsScanExtensions.cs @@ -2,7 +2,7 @@ using Thermo.Interfaces.InstrumentAccess_V1.MsScanContainer; using System.Collections.Generic; using System.Linq; -using Data; +using ClientServerCommLibrary; namespace InstrumentClient { public static class MsScanExtensions @@ -79,8 +79,7 @@ public static SingleScanDataObject ConvertToSingleScanDataObject(this IMsScan sc YArray = scan.Centroids.Select(c => c.Intensity).ToArray(), TotalIonCurrent = 1E6, MinX = scan.GetValueFromHeaderDict("FirstMass"), - MaxX = scan.GetValueFromHeaderDict("LastMass"), - Resolution = scan.GetValueFromHeaderDict("") + MaxX = scan.GetValueFromHeaderDict("LastMass") }; return sso; } diff --git a/Client/InstrumentInterfaces/Thermo/DataHandling/ThermoTribridSsdoMapping.cs b/Client/InstrumentInterfaces/Thermo/DataHandling/ThermoTribridSsdoMapping.cs new file mode 100644 index 0000000..e3849af --- /dev/null +++ b/Client/InstrumentInterfaces/Thermo/DataHandling/ThermoTribridSsdoMapping.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Client +{ + public static class ThermoTribridSsdoMapping + { + public static readonly Dictionary TrbridToSsdoMapping = new Dictionary + { + // key = ssdo; value = Tribrid + {"FirstMass", "FirstMass"}, + {"LastMass", "LastMass"}, + {"AnalyzerType", "Analyzer"}, + {"ScanType", "ScanType"}, + {"SourceEnergy", "SourceCIDEnergy"}, + {"SrcRFLens", "SrcRFLens"}, + {"Polarity", "Polarity"}, + {"DataType", "DataType"}, + {"IsolationType", "IsolationMode"}, + {"AgcTarget", "AGCTarget"}, + {"MaxIt", "MaxIT"}, + {"Microscans", "Microscans"}, + {"OrbitrapResolution", "OrbitrapResolution"}, + {"IonTrapScanRate", "ScanRate"}, + {"CollisionEnergy", "CollisionEnergy"}, + {"IsolationWidth", "IsolationWidth"}, + {"ActivationType", "ActivationType"}, + {"ChargeStates", "ChargeStates"}, + {"ActivationQ", "ActivationQ"}, + {"PrecursorMass", "PrecursorMass"}, + {"ReactionTime", "ReactionTime"}, + {"ReagentMaxIT", "ReagentMaxIT"}, + {"ReagentAGCTarget", "ReagentAGCTarget"} + }; + } +} diff --git a/Client/InstrumentInterfaces/Thermo/InterfaceImplementations/ThermoQE.cs b/Client/InstrumentInterfaces/Thermo/InterfaceImplementations/ThermoQE.cs index 3ea819a..4ac51a9 100644 --- a/Client/InstrumentInterfaces/Thermo/InterfaceImplementations/ThermoQE.cs +++ b/Client/InstrumentInterfaces/Thermo/InterfaceImplementations/ThermoQE.cs @@ -3,7 +3,8 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -using ClientServerCommunication; +using ClientServerCommLibrary; + namespace InstrumentClient { @@ -11,6 +12,16 @@ internal class ThermoQE : IInstrument { public ClientPipe PipeClient { get; set; } + public SingleScanDataObject GetLastScan() + { + throw new NotImplementedException(); + } + + public void SendScanAction(SingleScanDataObject ssdo) + { + throw new NotImplementedException(); + } + public void OpenInstrumentConnection() { throw new System.NotSupportedException(); @@ -21,6 +32,62 @@ public void CloseInstrumentConnection() throw new NotSupportedException(); } + public string GetSystemState(int stateOrMode) + { + throw new NotImplementedException(); + } + + public void CancelAcquisition() + { + throw new NotImplementedException(); + } + + public void PauseAcquisition() + { + throw new NotImplementedException(); + } + + public void ResumeAcquisition() + { + throw new NotImplementedException(); + } + + public void StartAcquisition(string rawFileName) + { + throw new NotImplementedException(); + } + + public void StartMethodAcquistion(string methodFilePath, string methodName, string outputFileName, string sampleName, + double timeInMinutes) + { + throw new NotImplementedException(); + } + + public void InstrumentOn() + { + throw new NotImplementedException(); + } + + public void InstrumentOff() + { + throw new NotImplementedException(); + } + + public void InstrumentStandby() + { + throw new NotImplementedException(); + } + + public void GetScanPossibleParameters() + { + throw new NotImplementedException(); + } + + public event EventHandler InstrumentConnected; + public event EventHandler InstrumentDisconnected; + public event EventHandler ScanReceived; + public event EventHandler InstrumentReadyToReceiveScan; + public void MsScanReadyToSend(MsScanReadyToSendEventArgs scanEventArgs) { throw new NotImplementedException(); diff --git a/Client/InstrumentInterfaces/Thermo/InterfaceImplementations/ThermoTribrid.cs b/Client/InstrumentInterfaces/Thermo/InterfaceImplementations/ThermoTribrid.cs index 696d006..c4b6d15 100644 --- a/Client/InstrumentInterfaces/Thermo/InterfaceImplementations/ThermoTribrid.cs +++ b/Client/InstrumentInterfaces/Thermo/InterfaceImplementations/ThermoTribrid.cs @@ -1,6 +1,8 @@ using System; using System.Runtime; using System.Collections.Generic; +using System.Diagnostics; +using System.IO; using System.Threading; using ClientServerCommLibrary; using Thermo.Interfaces.FusionAccess_V1; @@ -10,48 +12,91 @@ using Thermo.Interfaces.InstrumentAccess_V1.MsScanContainer; using Thermo.TNG.Factory; using System.Linq; -using Data; -using System.Threading.Tasks; -using Newtonsoft.Json; +using System.Text; using Thermo.Interfaces.InstrumentAccess_V1.Control.Acquisition.Modes; using Thermo.Interfaces.InstrumentAccess_V1.Control.Acquisition.Workflow; using Thermo.Interfaces.InstrumentAccess_V1.Control.Scans; -using ScanInstructions = ClientServerCommunication.ScanInstructions; -using SingleScanDataObject = Data.SingleScanDataObject; namespace InstrumentClient { public class ThermoTribrid : IInstrument - { - public ClientPipe PipeClient { get; set; } - public static IScans MScan { get; set; } + { + // IScans contains CanAcceptNextCustomScan and PossibleParametersChanged. public string InstrumentId { get; private set; } public string InstrumentName { get; private set; } + // InstAccessContainer contains MessagesArrived, ServiceConnectionChanged. public static IFusionInstrumentAccessContainer InstAccessContainer { get; private set; } + // InstAccess contains ContactClosureChanged, AcquisitionErrorsArrived, + // ConnectionChanged. public static IFusionInstrumentAccess InstAccess { get; private set; } + // MsScanContainer contains events MsScanArrived public static IFusionMsScanContainer MsScanContainer { get; private set; } + // InstAcq contains events AcquisitionStreamClosing, AcquisitionStreamOpening, + // StateChanged public static IAcquisition InstAcq { get; private set; } public static IControl InstControl { get; private set; } // Private Properties private int SystemState { get; set; } + private static IScans MScan { get; set; } // Constructors public ThermoTribrid() { - InstAccessContainer = Factory.Create(); + InstAccessContainer = Factory.Create(); } #region OpenInstrumentConnection public SingleScanDataObject GetLastScan() { - throw new NotImplementedException(); + IMsScan scan = MsScanContainer.GetLastMsScan(); + return scan.ConvertToSingleScanDataObject(); } public void SendScanAction(SingleScanDataObject ssdo) { - throw new NotImplementedException(); + if (ssdo.ScanInstructions.ScanType == null) + throw new ArgumentException("ScanAction type is invalid! (property was null)"); + + //switch (ssdo.ScanInstructions.ScanType) + ////{ + //// case (ScanInstructions.CustomScan): + //// SendRepeatingScan(); + //// break; + //// case (ScanType.RepeatingScan): + //// SendCustomScan(); + //// break; + //} + } + + private IDictionary SsdoToDictionary(SingleScanDataObject ssdo) + { + Dictionary valuesDict = new Dictionary(); + + // create an ssdo property to Thermo instrument value name. + + + return valuesDict; } + private void CreateRepeatingScan(SingleScanDataObject ssdo) + { + IRepeatingScan rscan = MScan.CreateRepeatingScan(); + + } + private void SendRepeatingScan() + { + + } + private void CreateCustomScan(SingleScanDataObject ssdo) + { + + } + + private void SendCustomScan() + { + + } + public void OpenInstrumentConnection() { InstAccessContainer.StartOnlineAccess(); @@ -70,50 +115,132 @@ private void GetInstAccess() InstrumentId = InstAccess.InstrumentId.ToString(); InstrumentName = InstAccess.InstrumentName; MsScanContainer = InstAccess.GetMsScanContainer(0); + MScan = InstControl.GetScans(false); InstAccessContainer.ServiceConnectionChanged += (o, s) => { }; InstAccessContainer.MessagesArrived += (o, s) => { }; InstAcq.AcquisitionStreamClosing += (o, s) => { }; InstAcq.AcquisitionStreamOpening += (o, s) => { }; - InstAcq.StateChanged += (o, s) => { }; - // instacq systemstate also contains an enum, where each value corresponds to the acquisition state + InstAcq.StateChanged += (o, s) => + { + EventHandler handler = SystemStateChanged; + if (handler != null) + { + handler(this, s); + } + }; + + // instacq.systemstate also contains an enum, where each value corresponds to the acquisition state // of the system. Could potentially use this as a read-back for the client. // InstAcq.State.SystemState - MsScanContainer.MsScanArrived += (o, s) => { }; - + MsScanContainer.MsScanArrived += (o, s) => + { + // convert to single scan data object and raise this.ScanReceived + var ssdo = s.GetScan().ConvertToSingleScanDataObject(); + EventHandler handler = ScanReceived; + if (handler != null) + { + handler(this, new ScanReceivedEventArgs(ssdo)); + } + }; + + MScan.CanAcceptNextCustomScan += (o, s) => + { + EventHandler handler = InstrumentReadyToReceiveScan; + if (handler != null) + { + handler(this, EventArgs.Empty); + } + }; } #endregion #region - public void GetSystemState() + public string GetSystemState(int stateOrMode) { - + if (stateOrMode > 2 || stateOrMode < 0) + throw new ArgumentException("Integer selection is outside of bounds."); + + switch (stateOrMode) + { + case 0: + return Enum.GetName(typeof(InstrumentState), InstAcq.State.SystemState); + case 1: + return Enum.GetName(typeof(SystemMode), InstAcq.State.SystemMode); + case 2: + { + StringBuilder sb = new StringBuilder(); + sb.AppendLine(Enum.GetName(typeof(InstrumentState), InstAcq.State.SystemState)); + sb.AppendLine(Enum.GetName(typeof(SystemMode), InstAcq.State.SystemMode)); + return sb.ToString(); + }; + } + throw new ArgumentException("Error: State and Mode unable to be found."); } public void CancelAcquisition() { - throw new NotImplementedException(); + InstAcq.CancelAcquisition(); } public void PauseAcquisition() { - throw new NotImplementedException(); + if (InstAcq.CanPause) + { + InstAcq.Pause(); + } + // todo: add handling for the case where InstAcq.CanPause is false. } public void ResumeAcquisition() { - throw new NotImplementedException(); + if (InstAcq.CanResume) + { + InstAcq.Resume(); + } + // todo: add handling for case where CanResume == false. } - public void StartAcquisition() + public void StartAcquisition(string rawFileName) { - throw new NotImplementedException(); + var acquisition = CreateTuneAcquisition(rawFileName); + InstAcq.StartAcquisition(acquisition); + } + + private IAcquisitionWorkflow CreateTuneAcquisition(string rawFileName) + { + var acquisition = InstAcq.CreatePermanentAcquisition(); + if (rawFileName != null) acquisition.RawFileName = rawFileName; + return acquisition; } public void StartMethodAcquistion(string methodFilePath, string methodName, string outputFileName, string sampleName, double timeInMinutes) { - throw new NotImplementedException(); + var method = CreateMethodAcquisition(methodFilePath, 5, AcquisitionContinuation.Standby, + waitForContactClosure: true, methodName, outputFileName, sampleName, timeInMinutes); + InstAcq.StartAcquisition(method); + } + private IAcquisitionMethodRun CreateMethodAcquisition(string methodFilePath, + int singleProcessingDelay, AcquisitionContinuation continuation, + bool waitForContactClosure, string methodName, + string rawFileName, string sampleName, + double timeInMinutes) + { + var methodAcquisition = InstAcq.CreateMethodAcquisition(methodFilePath); + // note: you can set the single processing delay. The instrument will wait + // the number of milliseconds you set before it starts the next scan. + // this needs to be set in the implementation of the interface because I'm not sure if + // anything besides Thermo will have this setting. + methodAcquisition.SingleProcessingDelay = singleProcessingDelay; + // set the default behavior of inter-acquisition time to put the instrument on standby. + methodAcquisition.Continuation = continuation; + methodAcquisition.WaitForContactClosure = waitForContactClosure; + methodAcquisition.MethodName = methodName; + methodAcquisition.RawFileName = rawFileName; + methodAcquisition.SampleName = sampleName; + methodAcquisition.Duration = TimeSpan.FromMinutes(timeInMinutes); + return methodAcquisition; } #endregion @@ -124,14 +251,7 @@ public void CloseInstrumentConnection() InstAccessContainer.Dispose(); } #endregion - // enter main loop is obsolete because of the client pipe restructuring. - #region SendScanAction - - #endregion - - #region GetLastScan - #endregion public void InstrumentOn() { @@ -150,42 +270,43 @@ public void InstrumentStandby() InstAcq.SetMode(sbMode); } + public void GetScanPossibleParameters() + { + throw new NotImplementedException(); + } + public event EventHandler InstrumentConnected; public event EventHandler InstrumentDisconnected; - public event EventHandler ScanReceived; - public event EventHandler ReadyToReceiveScan; + public event EventHandler ScanReceived; + public event EventHandler InstrumentReadyToReceiveScan; + // TODO: Change from StateChangedEventArgs to a Custom Class that doesn't use a + // thermo-based class. + public event EventHandler SystemStateChanged; - public void StartMethodAcquisition(string methodFilePath, string methodName, - string outputFileName, string sampleName, double timeInMinutes) - { - var method = CreateMethodAcquisition(methodFilePath, 5, AcquisitionContinuation.Standby, - waitForContactClosure: true, methodName, outputFileName, sampleName, timeInMinutes); - InstAcq.StartAcquisition(method); - } + } - private IAcquisitionMethodRun CreateMethodAcquisition(string methodFilePath, - int singleProcessingDelay, AcquisitionContinuation continuation, - bool waitForContactClosure, string methodName, - string rawFileName, string sampleName, - double timeInMinutes) + public class ScanReceivedEventArgs : EventArgs + { + public SingleScanDataObject Ssdo { get; set; } + public ScanReceivedEventArgs(SingleScanDataObject ssdo) { - var methodAcquisition = InstAcq.CreateMethodAcquisition(methodFilePath); - // note: you can set the single processing delay. The instrument will wait - // the number of milliseconds you set before it starts the next scan. - // this needs to be set in the implementation of the interface because I'm not sure if - // anything besides Thermo will have this setting. - methodAcquisition.SingleProcessingDelay = singleProcessingDelay; - // set the default behavior of inter-acquisition time to put the instrument on standby. - methodAcquisition.Continuation = continuation; - methodAcquisition.WaitForContactClosure = waitForContactClosure; - methodAcquisition.MethodName = methodName; - methodAcquisition.RawFileName = rawFileName; - methodAcquisition.SampleName = sampleName; - methodAcquisition.Duration = TimeSpan.FromMinutes(timeInMinutes); - return methodAcquisition; + Ssdo = ssdo; } + } + public enum ConnectionState + { + Connected = 1, + Disconnected = 0 + } + public class InstrumentConnectionStateEventArgs : EventArgs + { + public ConnectionState ConnectionStatus { get; set; } + public InstrumentConnectionStateEventArgs(ConnectionState connection) + { + ConnectionStatus = connection; + } } } diff --git a/Client/InstrumentInterfaces/Thermo/ThermoScanTranslator/ThermoTribridScanTranslator.cs b/Client/InstrumentInterfaces/Thermo/ThermoScanTranslator/ThermoTribridScanTranslator.cs new file mode 100644 index 0000000..6b5fe54 --- /dev/null +++ b/Client/InstrumentInterfaces/Thermo/ThermoScanTranslator/ThermoTribridScanTranslator.cs @@ -0,0 +1,58 @@ +using System; +using System.CodeDom; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; +using System.Text; +using System.Threading.Tasks; +using ClientServerCommLibrary; + +namespace Client +{ + public class ThermoTribridScanTranslator : ScanTranslator + { + public Dictionary InstrumentCompatibleScanInstructions { get; private set; } + public override void Translate(SingleScanDataObject ssdo) + { + throw new NotImplementedException(); + } + private Dictionary TranslateSsdo(SingleScanDataObject ssdo) + { + var result = new Dictionary(); + PropertyInfo[] properties = typeof(ScanInstructions).GetProperties(); + + foreach (PropertyInfo property in properties) + { + // set result key by matching the property name to the constant dictionary key + // and returning the value. + string newKey = ThermoTribridSsdoMapping.TrbridToSsdoMapping[property.Name]; + var propType = property.GetType(); + string valConvertToString = String.Empty; + + switch (propType.Name) + { + case nameof(Double): + break; + case nameof(Int32): + break; + case nameof(Enum): + break; + } + + } + + return result; + } + private static string GetEnumString(T enumOfType) where T : Enum + { + var enumType = typeof(T); + if (enumType == typeof(OrbitrapResolution)) + { + var temp = (int)Enum.Parse(typeof(OrbitrapResolution), enumOfType.ToString()); + return temp.ToString(); + } + return Enum.Parse(typeof(T), enumOfType.ToString()).ToString(); + } + } +} diff --git a/Client/MsScanReadyToSendEventArgs.cs b/Client/MsScanReadyToSendEventArgs.cs index 38024a3..c61ead5 100644 --- a/Client/MsScanReadyToSendEventArgs.cs +++ b/Client/MsScanReadyToSendEventArgs.cs @@ -3,8 +3,8 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -using Data; using System.Runtime; +using ClientServerCommLibrary; namespace InstrumentClient { diff --git a/Client/Program.cs b/Client/Program.cs index e27bd5e..40f7816 100644 --- a/Client/Program.cs +++ b/Client/Program.cs @@ -6,8 +6,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -using ClientServerCommunication; -using Data; +using ClientServerCommLibrary; namespace InstrumentClient { @@ -22,7 +21,7 @@ public static void Main(string[] args) ClientPipe clientPipe = new ClientPipe(pipeClient); - string instrumentType = args[0]; + string instrumentType = "tribrid"; IInstrumentFactory factory = null; switch (instrumentType) @@ -41,54 +40,15 @@ public static void Main(string[] args) { clientPipe.ConnectClientToServer(); clientPipe.BeginInstrumentConnection(instrumentApi); + } catch (Exception e) { Console.WriteLine(e); throw; } - finally - { - pipeClient.Dispose(); - } + pipeClient.Close(); } - - - //static void Main(string[] args) - //{ - // // fire up the pipe client - // string serverPipeName = args[0]; - // string pipeName = args[1]; - // ClientPipe clientPipe = new ClientPipe(serverPipeName, pipeName, - // p => p.StartByteReaderAsync()); - - // string instrumentType = args[2]; - // IInstrumentFactory factory = null; - // switch (instrumentType) - // { - // case "qe": - // factory = new ThermoQEFactory(); - // break; - // case "tribrid": - // factory = new ThermoTribridFactory(); - // break; - // } - - // try - // { - // IInstrument instrumentApi = factory?.CreateInstrumentApi(); - // instrumentApi.OpenInstrumentConnection(); - // instrumentApi.PipeClient = clientPipe; - // instrumentApi?.EnterMainLoop(); - // } - // catch (Exception e) - // { - // Console.WriteLine(e); - // } - // Console.ReadLine(); - //} - //// TODO: Write method to query what type of instrument is attached. - - + } } diff --git a/Client/ScanInstructionEventArgs.cs b/Client/ScanInstructionEventArgs.cs index ba2cf72..da51bcd 100644 --- a/Client/ScanInstructionEventArgs.cs +++ b/Client/ScanInstructionEventArgs.cs @@ -3,13 +3,13 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -using Data; +using ClientServerCommLibrary; namespace InstrumentClient { public class ScanInstructionsEventArgs : EventArgs { - public Data.ScanInstructions ScanInstructions { get; set; } + public ScanInstructions ScanInstructions { get; set; } public ScanInstructionsEventArgs(ScanInstructions scanInstructions) { ScanInstructions = scanInstructions; diff --git a/Client/packages.config b/Client/packages.config index bc2a97e..d3acfa9 100644 --- a/Client/packages.config +++ b/Client/packages.config @@ -1,4 +1,5 @@  + \ No newline at end of file diff --git a/ClientServerCommunication/ClientServerCommLibrary.csproj b/ClientServerCommunication/ClientServerCommLibrary.csproj index ea0d257..ac29bec 100644 --- a/ClientServerCommunication/ClientServerCommLibrary.csproj +++ b/ClientServerCommunication/ClientServerCommLibrary.csproj @@ -6,10 +6,7 @@ - - - - + diff --git a/ClientServerCommunication/PipeEventArgs.cs b/ClientServerCommunication/PipeEventArgs.cs index 9c76d82..9648c8e 100644 --- a/ClientServerCommunication/PipeEventArgs.cs +++ b/ClientServerCommunication/PipeEventArgs.cs @@ -7,6 +7,9 @@ namespace ClientServerCommLibrary { + /// + /// Class used to pass buffer sent from client to server or server to client. + /// public class PipeEventArgs : EventArgs { public byte[] Buffer; diff --git a/ClientServerCommunication/ProcessingCompletedEventArgs.cs b/ClientServerCommunication/ProcessingCompletedEventArgs.cs index dcfa035..dd72b05 100644 --- a/ClientServerCommunication/ProcessingCompletedEventArgs.cs +++ b/ClientServerCommunication/ProcessingCompletedEventArgs.cs @@ -6,8 +6,12 @@ namespace ClientServerCommLibrary { + /// + /// Used to pass a single scan data object from the workflow to the + /// method used to communicate with the client. + /// public class ProcessingCompletedEventArgs : EventArgs { - + public SingleScanDataObject Ssdo { get; set; } } } diff --git a/ClientServerCommunication/ScanInstructions.cs b/ClientServerCommunication/ScanInstructions.cs index 263adea..c20f129 100644 --- a/ClientServerCommunication/ScanInstructions.cs +++ b/ClientServerCommunication/ScanInstructions.cs @@ -1,12 +1,50 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; +using System.Runtime.InteropServices; +using System.Security.Permissions; using System.Text; using System.Threading.Tasks; -namespace ClientServerCommunication + +namespace ClientServerCommLibrary { + // TODO: Turn into a partial class for improved organization + [Serializable] public class ScanInstructions { + #region ThermoTribrid Settings + public double? FirstMass { get; set; } + public double? LastMass { get; set; } + public AnalyzerType? AnalyzerType { get; set; } + public ScanType? ScanType { get; set; } + public double? SourceEnergy { get; set; } + public double? SrcRFLens { get; set; } + public Polarity? Polarity { get; set; } + public DataType? DataType { get; set; } + public IsolationType? IsolationType { get; set; } + public double? AgcTarget { get; set; } + public double? MaxIt { get; set; } + public int? Microscans { get; set; } + public OrbitrapResolution? OrbitrapResolution { get; set; } + public IonTrapScanRate? IonTrapScanRate { get; set; } + public double? CollisionEnergy { get; set; } + public double? IsolationWidth { get; set; } + public ActivationType? ActivationType { get; set; } + public string ChargeStates { get; private set; } + public double? ActivationQ { get; set; } + public double? PrecursorMass { get; set; } + public double? ReactionTime { get; set; } + public double? ReagentMaxIT { get; set; } + public double? ReagentAGCTarget { get; set; } + public void SetChargeStates(int[] chargeStates) + { + ChargeStates = string.Join(",", chargeStates); + } + #endregion + + } + } diff --git a/ClientServerCommunication/ScanQueueThresholdReachedEventArgs.cs b/ClientServerCommunication/ScanQueueThresholdReachedEventArgs.cs index ed434c4..8e98064 100644 --- a/ClientServerCommunication/ScanQueueThresholdReachedEventArgs.cs +++ b/ClientServerCommunication/ScanQueueThresholdReachedEventArgs.cs @@ -6,6 +6,9 @@ namespace ClientServerCommLibrary { + /// + /// Class used to pass scans when the scan queue threshold is triggered. + /// public class ScanQueueThresholdReachedEventArgs : EventArgs { public IEnumerable ListSsdo { get; set; } diff --git a/ClientServerCommunication/SingleScanDataObject.cs b/ClientServerCommunication/SingleScanDataObject.cs index fd857d2..1a4e2cd 100644 --- a/ClientServerCommunication/SingleScanDataObject.cs +++ b/ClientServerCommunication/SingleScanDataObject.cs @@ -1,11 +1,13 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Security.Permissions; using System.Text; using System.Threading.Tasks; namespace ClientServerCommLibrary { + // TODO: Write validation methods for SingleScanDataObject [Serializable] public class SingleScanDataObject { @@ -15,6 +17,10 @@ public class SingleScanDataObject public double? MzPrecursor { get; set; } public double[] XArray { get; set; } public double[] YArray { get; set; } + public double TotalIonCurrent { get; set; } + public double MinX { get; set; } + public double MaxX { get; set; } + public ScanInstructions ScanInstructions { get; set; } public SingleScanDataObject() { @@ -38,5 +44,98 @@ public SingleScanDataObject(int scanOrder, int scanNumber, PrecursorScanNumber = precursorScanNumber; MzPrecursor = mzPrecursor; } + public void SetScanInstructions(ScanInstructions si, string instrument) + { + if (!ValidateScanInstructionsForInstrument(si, instrument)) + { + throw new ArgumentException( + "Invalid scan instructions for instrument type: {0}", + instrument); + } + SetScanInstructions(si); + } + private void SetScanInstructions(ScanInstructions si) + { + ScanInstructions = si; + } + // TODO: Check that the required fields are correctly set. Will probably require a static dictionary to check against. + private bool ValidateScanInstructionsForInstrument(ScanInstructions si, string instrument) + { + return true; + } + } + + public enum IsolationType + { + Quadropole, + IonTrap + } + + public enum AnalyzerType + { + Quadropole, + TOF, + Orbitrap, + IonTrap + } + + public enum CustomScanType + { + RepeatingScan, + CustomScan + } + + public enum InstrumentType + { + ThermoTribrid, + ThermoQE, + WatersTOF, + BrukerTOF + } + + public enum ScanType + { + Full, + SIM, + MSn + } + + public enum Polarity + { + Positive, + Negative + } + + public enum DataType + { + Profile, + Centroid + } + public enum OrbitrapResolution : int + { + X_7500 = 7500, + X_15000 = 15000, + X_30000 = 30000, + X_50000 = 50000, + X_60000 = 60000, + X_120000 = 120000, + X_240000 = 240000, + X_500000 = 500000 + } + public enum IonTrapScanRate + { + Normal, + Enhanced, + Zoom, + Rapid, + Turbo + } + public enum ActivationType + { + CID, + HCD, + ETD, + EThcD, + ETciD } } diff --git a/ClientServerCommunication/SingleScanDataObjectExtensions.cs b/ClientServerCommunication/SingleScanDataObjectExtensions.cs index 1209b49..6651347 100644 --- a/ClientServerCommunication/SingleScanDataObjectExtensions.cs +++ b/ClientServerCommunication/SingleScanDataObjectExtensions.cs @@ -1,5 +1,4 @@ using System.Text; -using Data; using Newtonsoft.Json; diff --git a/ClientServerCommunication/SsdoExtensions.cs b/ClientServerCommunication/SsdoExtensions.cs new file mode 100644 index 0000000..3428ecd --- /dev/null +++ b/ClientServerCommunication/SsdoExtensions.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Newtonsoft.Json; + +namespace ClientServerCommLibrary +{ + public static class SsdoExtensions + { + public static byte[] CreateSerializedSingleScanDataObject(this SingleScanDataObject ssdo) + { + byte[] buffer = SerializeAndCreateBuffer(ssdo); + int buffLength = buffer.Length; + byte[] lenghtInByteFormat = BitConverter.GetBytes(buffLength); + + // combine the two arrays + byte[] resultBuffer = new byte[lenghtInByteFormat.Length + buffLength]; + Buffer.BlockCopy(lenghtInByteFormat, 0, resultBuffer, 0, lenghtInByteFormat.Length); + Buffer.BlockCopy(buffer, 0, resultBuffer, lenghtInByteFormat.Length, buffLength); + return resultBuffer; + } + private static byte[] SerializeAndCreateBuffer(T obj) + { + string jsonString = JsonConvert.SerializeObject(obj); + return Encoding.UTF8.GetBytes(jsonString); + } + } + +} diff --git a/InstrumentClientTests/InstrumentClientTests.csproj b/InstrumentClientTests/InstrumentClientTests.csproj new file mode 100644 index 0000000..aea379a --- /dev/null +++ b/InstrumentClientTests/InstrumentClientTests.csproj @@ -0,0 +1,24 @@ + + + + net6.0 + enable + enable + + false + + + + + + + + + + + + + + + + diff --git a/InstrumentClientTests/UnitTest1.cs b/InstrumentClientTests/UnitTest1.cs new file mode 100644 index 0000000..a38b612 --- /dev/null +++ b/InstrumentClientTests/UnitTest1.cs @@ -0,0 +1,87 @@ +using System.Reflection; +using System.Security.Cryptography.X509Certificates; +using InstrumentClient; +using ClientServerCommLibrary; +namespace InstrumentClientTests +{ + public class Tests + { + [SetUp] + public void Setup() + { + } + + [Test] + public void TestGetEnum() + { + var orbiResTest = OrbitrapResolution.X_120000; + var expected = 120000; + string result = String.Empty; + var enumType = typeof(OrbitrapResolution); + if (enumType == typeof(OrbitrapResolution)) + { + var temp = (int)Enum.Parse(typeof(OrbitrapResolution), orbiResTest.ToString()); + result = temp.ToString(); + } + + Assert.That(expected.ToString(), Is.EqualTo(result)); + } + + [Test] + [TestCase(AnalyzerType.IonTrap, "IonTrap")] + [TestCase(ScanType.Full, "Full")] + [TestCase(Polarity.Negative, "Negative")] + [TestCase(DataType.Centroid, "Centroid")] + [TestCase(IsolationType.IonTrap, "IonTrap")] + [TestCase(OrbitrapResolution.X_30000, "X_30000")] + [TestCase(IonTrapScanRate.Enhanced, "Enhanced")] + [TestCase(ActivationType.ETD, "ETD")] + public void TestGetEnumPart2(T enumTest, object expectedVal) + { + var result = Enum.Parse(typeof(T), enumTest.ToString()).ToString(); + Assert.That(result, Is.EqualTo(expectedVal)); + + } + + [Test] + [TestCase(AnalyzerType.IonTrap, "IonTrap")] + [TestCase(ScanType.Full, "Full")] + [TestCase(Polarity.Negative, "Negative")] + [TestCase(DataType.Centroid, "Centroid")] + [TestCase(IsolationType.IonTrap, "IonTrap")] + [TestCase(OrbitrapResolution.X_30000, "30000")] + [TestCase(IonTrapScanRate.Enhanced, "Enhanced")] + [TestCase(ActivationType.ETD, "ETD")] + public void TestGetEnumString(T enumTest, object expectedVal) where T: Enum + { + var result = GetEnumString(enumTest); + Assert.That(result, Is.EqualTo(expectedVal)); + } + + private static string GetEnumString(T enumOfType) where T : Enum + { + var enumType = typeof(T); + if (enumType == typeof(OrbitrapResolution)) + { + var temp = (int)Enum.Parse(typeof(OrbitrapResolution), enumOfType.ToString()); + return temp.ToString(); + } + return Enum.Parse(typeof(T), enumOfType.ToString()).ToString(); + } + + [Test] + public void TestTranslateSsdo() + { + SingleScanDataObject ssdo = new SingleScanDataObject(); + ScanInstructions si = new ScanInstructions(); + ssdo.ScanInstructions = si; + ssdo.ScanInstructions.ScanType = ScanType.Full; + + PropertyInfo[] properties = typeof(ScanInstructions).GetProperties(); + foreach(PropertyInfo property in properties) + { + var result = property.GetValue(ssdo.ScanInstructions); + } + } + } +} \ No newline at end of file diff --git a/InstrumentClientTests/Usings.cs b/InstrumentClientTests/Usings.cs new file mode 100644 index 0000000..cefced4 --- /dev/null +++ b/InstrumentClientTests/Usings.cs @@ -0,0 +1 @@ +global using NUnit.Framework; \ No newline at end of file diff --git a/InstrumentControl.sln b/InstrumentControl.sln index 1f79597..2a4a484 100644 --- a/InstrumentControl.sln +++ b/InstrumentControl.sln @@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.2.32516.85 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Data", "Data\Data.csproj", "{6B34249B-A513-4A4A-9ED5-CB633BCAB646}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowServer", "ApplicationServer\WorkflowServer.csproj", "{7989657B-6BE1-42AC-A77A-EBE537AAB710}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClientServerCommLibrary", "ClientServerCommunication\ClientServerCommLibrary.csproj", "{0E9B5801-5167-44CC-90D3-C8CAF1DF8F6A}" @@ -13,16 +11,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProcessStarter", "ProcessSt EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InstrumentClient", "Client\InstrumentClient.csproj", "{2920D894-D01A-44AE-B2B7-EB7626782147}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InstrumentClientTests", "InstrumentClientTests\InstrumentClientTests.csproj", "{94F6C9E6-402B-4E6A-98FC-4AB817EE0453}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {6B34249B-A513-4A4A-9ED5-CB633BCAB646}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6B34249B-A513-4A4A-9ED5-CB633BCAB646}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6B34249B-A513-4A4A-9ED5-CB633BCAB646}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6B34249B-A513-4A4A-9ED5-CB633BCAB646}.Release|Any CPU.Build.0 = Release|Any CPU {7989657B-6BE1-42AC-A77A-EBE537AAB710}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7989657B-6BE1-42AC-A77A-EBE537AAB710}.Debug|Any CPU.Build.0 = Debug|Any CPU {7989657B-6BE1-42AC-A77A-EBE537AAB710}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -39,6 +35,10 @@ Global {2920D894-D01A-44AE-B2B7-EB7626782147}.Debug|Any CPU.Build.0 = Debug|Any CPU {2920D894-D01A-44AE-B2B7-EB7626782147}.Release|Any CPU.ActiveCfg = Release|Any CPU {2920D894-D01A-44AE-B2B7-EB7626782147}.Release|Any CPU.Build.0 = Release|Any CPU + {94F6C9E6-402B-4E6A-98FC-4AB817EE0453}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {94F6C9E6-402B-4E6A-98FC-4AB817EE0453}.Debug|Any CPU.Build.0 = Debug|Any CPU + {94F6C9E6-402B-4E6A-98FC-4AB817EE0453}.Release|Any CPU.ActiveCfg = Release|Any CPU + {94F6C9E6-402B-4E6A-98FC-4AB817EE0453}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/ProcessStarter/ProcessStarter.csproj b/ProcessStarter/ProcessStarter.csproj index 74abf5c..1aa4277 100644 --- a/ProcessStarter/ProcessStarter.csproj +++ b/ProcessStarter/ProcessStarter.csproj @@ -7,4 +7,8 @@ enable + + + + diff --git a/ProcessStarter/Program.cs b/ProcessStarter/Program.cs index 1688821..b0736b1 100644 --- a/ProcessStarter/Program.cs +++ b/ProcessStarter/Program.cs @@ -9,10 +9,10 @@ static void Main(string[] args) //string serverPath = args[0]; //string clientPath = args[1]; - string serverCommands = "Server"; - string clientCommands = ". Server tribrid"; + string serverCommands = @""; + string clientCommands = @"tribrid"; ProcessStartInfo serverProcessStartInfo = new( - @"C:\Users\Orbitrap Lumos\source\repos\InstrumentControl\ApplicationServer\bin\Debug\net6.0\ApplicationServer.exe") + @"C:\Users\Orbitrap Lumos\source\repos\InstrumentControl\ApplicationServer\bin\Debug\net6.0\WorkflowServer.exe") { Arguments = serverCommands }; @@ -25,6 +25,7 @@ static void Main(string[] args) Process.Start(serverProcessStartInfo); Process.Start(clientProcessStartInfo); Console.ReadLine(); + } } } \ No newline at end of file