Solo Predictor Example Connection Code: Difference between revisions

From Eigenvector Research Documentation Wiki
Jump to navigation Jump to search
imported>Jeremy
No edit summary
 
(12 intermediate revisions by 4 users not shown)
Line 1: Line 1:
__TOC__
__TOC__
The following provides some standard code pieces which can be used to make connections to Solo_Predictor. These examples may not be appropriate for all applications (e.g. none of these examples are asynchronous calls. They all 'block' the program execution until Solo_Predictor returns a result.) In addition, additional error checking and input/output parsing is required in most cases. Lots of other code examples can be found on the web by searching for sockets and the language of interest.
The following provides some standard code pieces which can be used to make connections to Solo_Predictor using HTTP (Hypertext Transfer Protocol) requests or low-level sockets directly. These examples may not be appropriate for all applications (e.g. none of these examples are asynchronous calls. They all 'block' the program execution until Solo_Predictor returns a result.) In addition, additional error checking and input/output parsing is required in most cases.


==Examples using HTTP==
===Matlab – HTTP Connection===
Matlab script demonstrating how a client program can communicate with Solo_Predictor (acting as the server) using the HTTP protocol. The script sends a message and retrieve the response. HTTP client code is much simpler than the sockets examples shown below.
<pre>
% Load and view a data file
msg = 'input=''C:/eigenu_dm/datafolder/spectrum1.spc'';:xml;input;';   
% Create the request string   
serverIPAddress  = '127.0.0.1';
serverPort      = '2211';
httpstr          = ['http://', serverIPAddress, ':', serverPort, '/?'];
httpURL          = sprintf('http://%s:%s/?%s', serverIPAddress, serverPort, urlencode(msg));
% Make HTTP request and read response as text 
webData = webread(httpURL);
disp(sprintf('Response is: \n%s\n', webData));
</pre>
===Java – HTTP Connection===
Here is an example in Java demonstrating how a client program can communicate with Solo_Predictor (acting as the server) using the HTTP protocol. The program sends a message and retrieves the response using the java.net.HttpURLConnection class.
<pre>
package sp_client;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
public class HttpClient {
private final String USER_AGENT = "Mozilla/5.0";
// HTTP GET request
private void sendGet() throws Exception {
String url = "http://127.0.0.1:2211/?:version";
String msg = ":plain;data=\'C:/Proj1/datafolder/spectrum1.spc\';"
  + "model = \'C:/Proj1/modelfolder/plsmodel.mat\';"
  + "pred = data | model;pred.prediction;";
msg = URLEncoder.encode(msg, StandardCharsets.UTF_8.toString());
url = "http://127.0.0.1:2211/?" + msg;
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// optional default is GET
con.setRequestMethod("GET");
//add request header
con.setRequestProperty("User-Agent", USER_AGENT);
int responseCode = con.getResponseCode();
System.out.println("\nSending 'GET' request to URL : " + url);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
//print result
System.out.println(response.toString());
}
public static void main(String[] args) throws Exception {
HttpClient http = new HttpClient();
// Send Http GET request
http.sendGet();
}
}
</pre>
===Python – HTTP Connection===
An example in Python demonstrating how a client program can communicate with Solo_Predictor (acting as the server) using the HTTP protocol. The program sends a message and retrieves the response using the Python "requests" library.
<pre>
import requests
#r = requests.get('http://127.0.0.1:2211/?:version')    # simple test of connectivity
r = requests.get('http://127.0.0.1:2211/?:plain; data = \'C:/Proj1/datafolder/spectrum1.spc\';model = \'C:/Proj1/modelfolder/plsmodel.mat\'; pred = data | model; pred.prediction;')
print('status_code = ', r.status_code)
prediction_result = r.text    # reads content of the response, which should be 20.18080
</pre>
===Web Browser - HTTP Connection===
Finally, the same HTTP request can be conveniently sent from a web browser, for example Firefox or Chrome, using the URL:
<pre>
:xml;data = 'C:/Proj1/datafolder/spectrum1.spc';model = 'C:/Proj1/modelfolder/plsmodel.mat'; pred = data | model; pred.prediction;
</pre>
The error status is also included in the response and will include an error message if an error occurred. This can be a very convenient means of quickly testing a command.
==Examples using Sockets==
===C# - Socket Connection===
===C# - Socket Connection===


The following C-sharp example expects three variables: ServerIP as a string indicating the server's IP address, Port as an integer giving the server's port number, and command as a string command to send. It returns Solo_Predictor's output in a variable called outputString. This code requires the following "using" declarations:
The example code expects three variables: ServerIP as a string indicating the server's IP address, Port as an integer giving the server's port number, and command as a string command to send. It returns Solo_Predictor's output in a variable called outputString. This code requires the following "using" declarations:


  using System;
  using System;
Line 10: Line 118:
  using System.ComponentModel;
  using System.ComponentModel;


Note that no object or function declarations are given in this code but would generally be required. This function also sets the ReceiveTimeout property on the socket to 2000 milliseconds. This setting can be adjusted as required by the application. The total time of most calls to Solo_Predict is 1/2 second or less (testing on a moderately featured system in 2007 indicated application of a PLS model to a 200 point vector took an average of 0.2 seconds including I/O overhead.)
Note that no object or function declarations are given in this code but would generally be required. This function also sets the ReceiveTimeout property on the socket to 2000 milliseconds. This setting can be adjusted as required by the application. The total time of most calls to Solo_Predict is 1/2 second or less (testing application of a PLS model to a 200 point vector took an average of 0.2 seconds including I/O overhead.)


<pre>
<pre>
Line 17: Line 125:
{
{
   //make connection to server
   //make connection to server
   socketForServer = new TcpClient(ServerIO,Port);
   socketForServer = new TcpClient(ServerIP,Port);
}
}
catch
catch
Line 44: Line 152:
}
}
networkStream.Close();  // tidy up
networkStream.Close();  // tidy up
</pre>
===VB – ActiveX===
See the [[EigenvectorTools#Visual_Basic|EigenvectorTools Visual Basic example]].
===VBA - ActiveX===
The following is a short example in Visual Basic for Applications (VBA) runable from Excel to call into Solo_Predictor passing data, loading an optional calibration transfer model, then loading a prediction model (regression is assumed here) and applying it.
<pre>
Function predict(data As Variant, Optional model As String = "", Optional caltransfer As String = "") As Variant
    'INPUTS:
    '  data = array of numerical values to pass to Solo_Predictor
    '  model = filename (or XML) containing model to make prediction from (e.g. MAT file with single variable)
    '  caltransfer = filename (or XML) containing calibration transfer model to apply to data prior to model
    'OUTPUTS:
    'Outputs is the string returned from Solo_Predictor. If string starts with "ERROR" then an error occurred as
    'described in the remainder of the string. Otherwise, the string represents a space-delimited string of numbers
    'including:  prediction(s) from the model, reduced T^2 from the model, reduced Q from the model.
    'The last two elements of
    Dim solo As Object
    Dim status As Integer
    Dim msg As String
    Dim out As String
    Dim response
    predict = Null  'what to return if we fail
    'start up solo
    Set solo = CreateObject("EigenvectorToolsV6.Application")
    solo.automation = True  'turn on automation
    solo.socket = False      'turn OFF sockets
    status = solo.startApp
    If status = 0 Then
        'started (apparently) try sending blank command to get response
        status = solo.sendCommand(":version")
    End If
    If status <> 0 Then
        predict = "ERROR:" + solo.lastResponse
        Return
    End If
 
    'truly started- do analysis
    'create script to send to Solo_Predictor
    msg = ":plain;"    'define output format
 
    'pass data as text
    msg = msg + "data='["
    For k = 0 To UBound(data)
        msg = msg + Str(data(k)) + " "
    Next k
    msg = msg + "]';"
 
    If caltransfer <> "" Then
        'load and apply calibration transfer model (if supplied)
        msg = msg + "xfer='" + caltransfer + "';"
        msg = msg + "data = data|xfer;"
    End If
 
    If model <> "" Then
        'load and apply model
        msg = msg + "model='" + model + "';"  'load model
        msg = msg + "pred = data|model;"  'apply model
        msg = msg + "pred.prediction;"    'get predictions
        msg = msg + "pred.T2;"            'get reduced T^2 (1=95% limit)
        msg = msg + "pred.Q;"            'get reduced Q (1=95% limit)
    Else
        'no model? just return data
        msg = msg + "data;"
    End If
 
    status = solo.sendCommand(msg)
    If status <> 0 Then
        predict = "ERROR:" + solo.lastResponse
        Return
    End If
 
    'get last response
    out = solo.lastResponse
    If (StrComp(Left(out, 5), "error", vbTextCompare) = 0) Then
        'found error - just return string
        predict = out
        Return
    End If
 
    'no error - extract values
    Dim V As Variant
    Dim temp As String
    temp = ""
    While temp <> out
        temp = out
        out = Replace(out, "  ", " ") 'keep replacing double spaces with single
    Wend  'until we aren't making changes anymore
    V = Split(out, " ")  'split into array
 
    'convert to double
    Dim dout() As Double
    ReDim dout(0 To UBound(V))
    For j = 0 To UBound(V)
        dout(j) = Val(V(j))
    Next j
    predict = dout
End Function
Sub test()
    'Example of how to call predict and handle the outputs
    Dim data As Variant
    Dim result As Variant
    Dim junk
    'fake data - could load from spreadsheet instead 
    data = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)
    'make prediction using model specified as second input
    result = predict(data, "C:\testfolder\testmodel.mat")
    If VarType(result) = vbString Then
        'error occurred, show error
        junk = MsgBox(result, vbOKOnly, "Result of prediction")
    Else
        'got results, show them (could be put into Excel spreadsheet instead)
        For j = 0 To UBound(result)
            junk = MsgBox(result(j), vbOKOnly, "Result of prediction")
        Next j
    End If
 
End Sub
</pre>
</pre>


Line 182: Line 159:


<pre>
<pre>
import java.io.\*;
import java.io.*;
import java.net.\*;
import java.net.*;
 
% Example of how to set parameters. The msg command simply retrieves the loaded dataset in this simple example.
% srv  = java.lang.String('127.0.0.1');
% port = 2211;
% msg  = 'input=''C:\Data\proj1\spectrum1.spc'';:xml;input;';


%Create socket connection and socket reader and writers
%Create socket connection and socket reader and writers
Line 201: Line 183:
%wait for reply ready
%wait for reply ready
starttime = now;
starttime = now;
while \~clientIn.ready
while ~clientIn.ready
   if (now-starttime)>60/60/60/24;
   if (now-starttime)>60/60/60/24;
     error('No response from server')
     error('No response from server')

Latest revision as of 14:17, 23 September 2022

The following provides some standard code pieces which can be used to make connections to Solo_Predictor using HTTP (Hypertext Transfer Protocol) requests or low-level sockets directly. These examples may not be appropriate for all applications (e.g. none of these examples are asynchronous calls. They all 'block' the program execution until Solo_Predictor returns a result.) In addition, additional error checking and input/output parsing is required in most cases.

Examples using HTTP

Matlab – HTTP Connection

Matlab script demonstrating how a client program can communicate with Solo_Predictor (acting as the server) using the HTTP protocol. The script sends a message and retrieve the response. HTTP client code is much simpler than the sockets examples shown below.

% Load and view a data file
msg = 'input=''C:/eigenu_dm/datafolder/spectrum1.spc'';:xml;input;';    

% Create the request string     
serverIPAddress  = '127.0.0.1';
serverPort       = '2211';
httpstr          = ['http://', serverIPAddress, ':', serverPort, '/?'];
httpURL          = sprintf('http://%s:%s/?%s', serverIPAddress, serverPort, urlencode(msg));

% Make HTTP request and read response as text  
webData = webread(httpURL);

disp(sprintf('Response is: \n%s\n', webData));

Java – HTTP Connection

Here is an example in Java demonstrating how a client program can communicate with Solo_Predictor (acting as the server) using the HTTP protocol. The program sends a message and retrieves the response using the java.net.HttpURLConnection class.

package sp_client;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

public class HttpClient {
	private final String USER_AGENT = "Mozilla/5.0";

	// HTTP GET request
	private void sendGet() throws Exception {

		String url = "http://127.0.0.1:2211/?:version";
		String msg = ":plain;data=\'C:/Proj1/datafolder/spectrum1.spc\';"
				   + "model = \'C:/Proj1/modelfolder/plsmodel.mat\';"
				   + "pred = data | model;pred.prediction;";
		msg = URLEncoder.encode(msg, StandardCharsets.UTF_8.toString());
		url = "http://127.0.0.1:2211/?" + msg;

		URL obj = new URL(url);
		HttpURLConnection con = (HttpURLConnection) obj.openConnection();

		// optional default is GET
		con.setRequestMethod("GET");
		//add request header
		con.setRequestProperty("User-Agent", USER_AGENT);

		int responseCode = con.getResponseCode();
		System.out.println("\nSending 'GET' request to URL : " + url);
		System.out.println("Response Code : " + responseCode);

		BufferedReader in = new BufferedReader(
				new InputStreamReader(con.getInputStream()));
		String inputLine;
		StringBuffer response = new StringBuffer();

		while ((inputLine = in.readLine()) != null) {
			response.append(inputLine);
		}
		in.close();

		//print result
		System.out.println(response.toString());
	}

	public static void main(String[] args) throws Exception {
		HttpClient http = new HttpClient();

		// Send Http GET request
		http.sendGet();
	}
}

Python – HTTP Connection

An example in Python demonstrating how a client program can communicate with Solo_Predictor (acting as the server) using the HTTP protocol. The program sends a message and retrieves the response using the Python "requests" library.

import requests

#r = requests.get('http://127.0.0.1:2211/?:version')    # simple test of connectivity
r = requests.get('http://127.0.0.1:2211/?:plain; data = \'C:/Proj1/datafolder/spectrum1.spc\';model = \'C:/Proj1/modelfolder/plsmodel.mat\'; pred = data | model; pred.prediction;')

print('status_code = ', r.status_code)

prediction_result = r.text    # reads content of the response, which should be 20.18080

Web Browser - HTTP Connection

Finally, the same HTTP request can be conveniently sent from a web browser, for example Firefox or Chrome, using the URL:

:xml;data = 'C:/Proj1/datafolder/spectrum1.spc';model = 'C:/Proj1/modelfolder/plsmodel.mat'; pred = data | model; pred.prediction;

The error status is also included in the response and will include an error message if an error occurred. This can be a very convenient means of quickly testing a command.

Examples using Sockets

C# - Socket Connection

The example code expects three variables: ServerIP as a string indicating the server's IP address, Port as an integer giving the server's port number, and command as a string command to send. It returns Solo_Predictor's output in a variable called outputString. This code requires the following "using" declarations:

using System;
using System.Net.Sockets;
using System.ComponentModel;

Note that no object or function declarations are given in this code but would generally be required. This function also sets the ReceiveTimeout property on the socket to 2000 milliseconds. This setting can be adjusted as required by the application. The total time of most calls to Solo_Predict is 1/2 second or less (testing application of a PLS model to a 200 point vector took an average of 0.2 seconds including I/O overhead.)

TcpClient socketForServer;
try
{
  //make connection to server
  socketForServer = new TcpClient(ServerIP,Port);
}
catch
{
  outputString  = "ERROR: Failed to connect to server";
  return;
}
//get stream and stream reader/writer
NetworkStream networkStream = socketForServer.GetStream();
System.IO.StreamReader streamReader = new System.IO.StreamReader(networkStream);
System.IO.StreamWriter streamWriter = new System.IO.StreamWriter(networkStream);
 
try
{
  //send command to server
  streamWriter.WriteLine(command);
  streamWriter.Flush();
  //wait for and retrieve response
  string outputString;
  socketForServer.ReceiveTimeout = 2000;
  outputString = streamReader.ReadToEnd();
}
catch
{
  outputString = "ERROR: Exception reading from Server";
}
networkStream.Close();  // tidy up

Matlab – Socket Connection

This code example runs in Matlab and makes use of Java commands to create a socket connection, send a message, and retrieve the response. It assumes that an input message exists in the variable msg as a string command to send and the server ip and port are in the variables srv and port.

import java.io.*;
import java.net.*;

% Example of how to set parameters. The msg command simply retrieves the loaded dataset in this simple example.
% srv  = java.lang.String('127.0.0.1');
% port = 2211;
% msg  = 'input=''C:\Data\proj1\spectrum1.spc'';:xml;input;';

%Create socket connection and socket reader and writers
clientSocket = java.net.Socket(srv,port);
iStream_client = clientSocket.getInputStream;
iReader_client = InputStreamReader(iStream_client);
outStream_client = clientSocket.getOutputStream;

%create buffers for socket
clientOut = PrintWriter(outStream_client, true);
clientIn = BufferedReader(iReader_client);

%send message to Solo_Predictor
clientOut.println(java.lang.String(msg));
clientOut.flush;

%wait for reply ready
starttime = now;
while ~clientIn.ready
  if (now-starttime)>60/60/60/24;
    error('No response from server')
  end
end

%read in reply and store in cell array
rcv = {};
while clientIn.ready;
  rcv{end+1} = char(readLine(clientIn));
end

%concatenate string reply with linefeeds
if length(rcv)>1;
  rcv = sprintf('%s\n',rcv{:});
else
  rcv = rcv{1};
end