Skip to Content
test
0 %
Change Point Detection example with Java
Details
// Explore More Tutorials

Change Point Detection example with Java

11/26/2018

Discover how to implement SAP Leonardo Machine Learning Foundation service in a Java program

You will learn

In this tutorial, you will learn how to quickly integrate the Time Series Change Point Detection SAP Leonardo Machine Learning Functional Services published from the SAP API Business Hub sandbox in a Java program.

The Time Series Change Point Detection service allows you to calculates and returns the probability of the change point for each data point in the provided univariate or multivariate time series.

You will then be able to substitute the Time Series Change Point Detection services with any other SAP Leonardo Machine Learning Functional Services that consumes images content.

For each API exposed in the SAP API Business Hub, you will be able to generate a code snippet which we will use in this tutorial.

This code snippet will be imported in a Java project built with the Eclipse IDE ™.

You can of course substitute the Eclipse IDE ™ with alternate tools and adapt the current tutorial steps.

In this tutorial, you will learn the basics of making API calls against the Machine Learning Functional Services published in SAP API Business Hub.


Step 1: Get The Code Snippet And the API key

In order to consume the Time Series Change Point Detection API SAP Leonardo Machine Learning Foundation service, you will first need to get the service URI, request and response parameters.

Go to https://api.sap.com/.

SAP API Business Hub

Then you will be able to search for the SAP Leonardo Machine Learning - Functional Services, then click on the package found.

SAP API Business Hub

Select Time Series Change Point Detection API.

SAP API Business Hub

You can also access the page directly from the following address:

As you can notice the API has only one resource (or service): /inference_sync.

SAP API Business Hub

Note: the term inference refers to the application phase (scoring) an existing model (as opposed to the training or inception phase) and sync for synchronous.

Now, click on the Code Snippet, then, select Java.

SAP API Business Hub

As you will notice, the generated code is missing the Java import statements along with the API_KEY, the request expected form data for the file content.

Click on the Copy and Close, then, save the code snippet in your favorite text editor.

When using any of the APIs outside of the SAP API Business Hub, an application key is needed in every request header of your calls.

To get to your API key, click on the Show API Key button.

SAP API Business Hub

You will be prompted to login if you are not yet.

Then, the following pop-up should appear. Click on the Copy Key and Close button and save it in a text editor.

SAP API Business Hub
Log on to answer question
Step 2: Analyze the service

As you can notice the API has only one resource (or service): /inference_sync.

Now click on the /inference_sync link to expand the section.

Note: the term inference refers to the application phase (scoring) an existing model (as opposed to the training or inception phase) and sync for synchronous.

As stated in the description, the service accepts either:

  • an archive file with a zip/tar extensions containing multiple text files
  • a text file
  • a text as input representing the series of data

The service returns a list of change point probabilities.

The supported text file formats is plain text only.

The input text, file, files or archive file will be sent as a FormData query parameter in the service request.

A series of options are also required for the following parameters:

  • separator: Values separator (the default value is the comma: “,”)
  • series_separator: Series separator for multivariate time series. (the default value is the colon: “:”)
Log on to answer question
Step 3: Start the Eclipse IDE

Now, you can start the Eclipse IDE and select your workspace (either the default, a new or an existing one).

If you don’t have the Eclipse IDE installed, you can download the latest version from the following link: Eclipse Downloads

You can pick either the Eclipse IDE for Java EE Developers or the Eclipse IDE for Java Developers.

By default the Java perspective should be Launched.

If not, use the menu bar and select Window > Perspective > Open Perspective > Java.

If the Java perspective is not listed, then use the Other… to open it.

You can also close the Welcome Page.

SAP API Business Hub
Log on to answer question
Step 4: Create a New Project in the Eclipse IDE

Using the menu bar, go to File > New > Java Project.

You can name your project the way you want, here we will call it ml-changepointdetection.

Click on Finish.

Note: make sure you pick JavaSE-1.8 as your project Execution Runtime JRE. This should help avoid coding compliance and runtime issues with the provided code.

Eclipse
Log on to answer question
Step 5: Create a New Java Class

Using the menu bar, go to File > New > Class.

Make sure that your source folder is ml-imageclassification/src.

You can name your Java class the way you want, here we will call it DemoChangePointDetection and put it in a demo package.

Check the public static void main(String[] arg) box in order to get the main function created.

Click on Finish.

Eclipse

The default code in your newly created class should be something this:

package demo;
public class DemoChangePointDetection {
  public static void main(String[] args) {
    // TODO Auto-generated method stub
  }
}

You can now paste the generated code snippet that was collected during step 1 and copy it in the body of the main function.

Make sure you replace the <API_KEY> token in the code by your API key (collected during step 2).

You can now Organize imports by using either the CTRL+SHIFT+O keyboard shortcut, the Source > Organize imports from the menu bar or by using a right-click in your code.

The following import will be added to your class:

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

Save your code.

Log on to answer question
Step 6: Process the input parameters as Form Data

Now can modify the code snippet to process the input series and send it as form data.

Replace the code below in the main function (around line 34):

  //sending POST request
  connection.setDoOutput(true);
  dataOut = new DataOutputStream(connection.getOutputStream());
  dataOut.writeBytes("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"options\"\r\n\r\nstring\r\n-----011000010111000001101001--");
  dataOut.flush();

  int responseCode = connection.getResponseCode();
  in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
  String inputLine;
  StringBuffer response = new StringBuffer();
  while ((inputLine = in.readLine()) != null) {
   response.append(inputLine);
  }

  //printing response
  System.out.println(response.toString());

by

  // sending POST request
  connection.setDoOutput(true);

  // read the input file name from user input
  Scanner scanner = new Scanner(System.in);
  // Reading from System.in

  String default_data = "93969.262,76604.444,50000.000,17364.818,-17364.818,-50000.000,-76604.444,-93969.262,-100000.000,-93969.262,-76604.444,-50000.000,-17364.818,17364.818,50000.000,76604.444,93969.262,100000.000";
  System.out.println("What is your series data : (example :" + default_data + ")");
  String data = scanner.nextLine();
  if (data == null || data.length() == 0) {
    data = default_data;
  }

  String default_separator = ",";
  System.out.println("What is your value separator (default: \"" + default_separator + "\") : ");
  String separator = scanner.nextLine();
  if (separator == null || separator.length() > 1 || separator.length() == 0) {
    separator = default_separator;
  }

  String default_series_separator = ":";
  System.out.println("What is your series separator (default: \"" + default_series_separator + "\") : ");
  String series_separator = scanner.nextLine();
  if (series_separator == null || series_separator.length() > 1 || series_separator.length() == 0) {
    series_separator = default_series_separator;
  }
  scanner.close();

  // prepare the constant for the form data
  String LINE_FEED = "\r\n";
  String SEPARATOR = "--";
  String BOUNDARY = "------Boundary" + new BigInteger(128, new SecureRandom()).toString(32);

  // set the form content as multipart
  connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);

  // write the form data content
  dataOut = new DataOutputStream(connection.getOutputStream());
  dataOut.writeBytes(SEPARATOR + BOUNDARY + LINE_FEED);
  dataOut.writeBytes("Content-Disposition: form-data; name=\"options\"" + LINE_FEED);
  dataOut.writeBytes(LINE_FEED);
  dataOut.writeBytes(
      "{ \"separator\" : \"" + separator + "\", \"series_separator\" : \"" + series_separator + "\" }");
  dataOut.writeBytes(LINE_FEED);
  dataOut.writeBytes(SEPARATOR + BOUNDARY + LINE_FEED);
  dataOut.writeBytes("Content-Disposition: form-data; name=\"texts\"" + LINE_FEED);
  dataOut.writeBytes(LINE_FEED);
  dataOut.writeBytes(data);

  // finish the form content
  dataOut.writeBytes(LINE_FEED);
  dataOut.writeBytes(SEPARATOR + BOUNDARY + SEPARATOR + LINE_FEED);
  dataOut.flush();
  dataOut.close();

  int responseCode = connection.getResponseCode();
  if (responseCode != 200) {
    in = new BufferedReader(new InputStreamReader(connection.getErrorStream()));
  } else {
    in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
  }
  String inputLine;
  StringBuffer response = new StringBuffer();
  while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
  }

  // printing response
  System.out.println(response.toString());

You can now Organize imports by using either the CTRL+SHIFT+O keyboard shortcut, the Source > Organize imports from the menu bar or by using a right-click in your code.

The following import will be added to your class:

import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Scanner;

Save your code.

You can now run the code by either pressing ALT + SHIFT + X , J or by clicking on the Run Run button.

Enter the relevant parameters as detailed in the console.

You can use your favorite spreadsheet tool to generate your series of data or use the default input provided.

Log on to answer question
Step 7: Solution

In case you had some issues in the previous steps, here is the full class code with a better displayed response.

Just remember to replace the <API_KEY> token in the code by your API key (collected during step 2).

package demo;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.SecureRandom;
import java.util.Scanner;

public class DemoChangePointDetection {

  public static void main(String[] args) {
    DataOutputStream dataOut = null;
    BufferedReader in = null;

    try {

      String url = "https://sandbox.api.sap.com/ml/changepointdetection/inference_sync";

      URL urlObj = new URL(url);
      HttpURLConnection connection = (HttpURLConnection) urlObj.openConnection();
      // setting request method
      connection.setRequestMethod("POST");

      // adding headers
      connection.setRequestProperty("content-type", "multipart/form-data; boundary=---011000010111000001101001");
      connection.setRequestProperty("Accept", "application/json");
      connection.setRequestProperty("APIKey", "<API_KEY>");

      connection.setDoInput(true);

      // sending POST request
      connection.setDoOutput(true);

      // read the input file name from user input
      Scanner scanner = new Scanner(System.in);
      // Reading from System.in

      String default_data = "93969.262,76604.444,50000.000,17364.818,-17364.818,-50000.000,-76604.444,-93969.262,-100000.000,-93969.262,-76604.444,-50000.000,-17364.818,17364.818,50000.000,76604.444,93969.262,100000.000";
      System.out.println("What is your series data : (example :    " + default_data + ")");
      String data = scanner.nextLine();
      if (data == null || data.length() == 0) {
        data = default_data;
      }

      String default_separator = ",";
      System.out.println("What is your value separator (default: \"" + default_separator + "\") : ");
      String separator = scanner.nextLine();
      if (separator == null || separator.length() > 1 || separator.length() == 0) {
        separator = default_separator;
      }

      String default_series_separator = ":";
      System.out.println("What is your series separator (default: \"" + default_series_separator + "\") : ");
      String series_separator = scanner.nextLine();
      if (series_separator == null || series_separator.length() > 1 || series_separator.length() == 0) {
        series_separator = default_series_separator;
      }
      scanner.close();

      // prepare the constant for the form data
      String LINE_FEED = "\r\n";
      String SEPARATOR = "--";
      String BOUNDARY = "------Boundary" + new BigInteger(128, new SecureRandom()).toString(32);

      // set the form content as multipart
      connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);

      // write the form data content
      dataOut = new DataOutputStream(connection.getOutputStream());
      dataOut.writeBytes(SEPARATOR + BOUNDARY + LINE_FEED);
      dataOut.writeBytes("Content-Disposition: form-data; name=\"options\"" + LINE_FEED);
      dataOut.writeBytes(LINE_FEED);
      dataOut.writeBytes(
          "{ \"separator\" : \"" + separator + "\", \"series_separator\" : \"" + series_separator + "\" }");
      dataOut.writeBytes(LINE_FEED);
      dataOut.writeBytes(SEPARATOR + BOUNDARY + LINE_FEED);
      dataOut.writeBytes("Content-Disposition: form-data; name=\"texts\"" + LINE_FEED);
      dataOut.writeBytes(LINE_FEED);
      dataOut.writeBytes(data);

      // finish the form content
      dataOut.writeBytes(LINE_FEED);
      dataOut.writeBytes(SEPARATOR + BOUNDARY + SEPARATOR + LINE_FEED);
      dataOut.flush();
      dataOut.close();

      int responseCode = connection.getResponseCode();
      if (responseCode != 200) {
        in = new BufferedReader(new InputStreamReader(connection.getErrorStream()));
      } else {
        in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
      }
      String inputLine;
      StringBuffer response = new StringBuffer();
      while ((inputLine = in.readLine()) != null) {
        response.append(inputLine);
      }

      // printing response
      String TAB = "\t";
      String QUOTE = "\"";
      String CR = "\r\n";
      System.out.println(response.toString()//
          .replace("  " + QUOTE + "", "" + TAB + "" + QUOTE + "")//
          .replace("  ", "" + TAB + "")//
          .replace("" + TAB + " ", "" + TAB + "")//
          .replace(", ", ",")//
          .replace(": {", ":{" + CR + "")//
          .replace(": [", ":[" + CR + "")//
          .replace(":" + CR + "" + TAB + "{", ": {")//
          .replace(":" + CR + "" + TAB + "[", ": [")///
          .replace("{" + TAB + "", "{" + CR + "" + TAB + "")//
          .replace("[" + TAB + "", "[" + CR + "" + TAB + "")//
          .replace("" + QUOTE + ",", "" + QUOTE + "," + CR + "")//
          .replace("," + TAB + "", "," + CR + "" + TAB + "")//
          .replace("" + QUOTE + "" + TAB + "", "" + QUOTE + "" + CR + "" + TAB + "")//
          .replace("" + TAB + " " + TAB + "", "" + TAB + "" + TAB + "")//
          .replace("" + TAB + " {", "" + TAB + "{")//
          .replace("" + TAB + " [", "" + TAB + "[")//
          .replace("]", "]" + CR + "")//
          .replace("}", "}" + CR + "")//
          .replace("]" + CR + "," + CR + "", "]," + CR + "")//
          .replace("}" + CR + "," + CR + "", "}," + CR + "")//
          .replace("[" + CR + "]", "[]")//
          .replace("{" + CR + "}", "{}")//
          .replaceAll("([0-9])(\t)", "$1" + CR + "$2"));
    } catch (Exception e) {
      // do something with exception
      e.printStackTrace();
    } finally {
      try {
        if (dataOut != null) {
          dataOut.close();
        }
        if (in != null) {
          in.close();
        }

      } catch (IOException e) {
        // do something with exception
        e.printStackTrace();
      }
    }
  }
}
Log on to answer question
Step 8: Validation

Provide an answer to the question below then click on Validate.

Based on the test you just completed and using the input example, what is the value of the very last
element in the predictions list?
×

Next Steps

Next Steps

Back to top