2019-04-02 12:21:09 +02:00
2018-08-10 13:13:23 +02:00
2017-03-01 08:15:23 +01:00
2019-04-02 12:21:09 +02:00
2015-05-26 16:33:57 +02:00
2018-08-10 13:13:23 +02:00
2018-08-10 13:13:23 +02:00
2019-03-14 16:03:16 +01:00
2015-07-08 16:18:47 +02:00

Overview

This project provides a REST interface to execute queries on the databuffer.

Requirements

This project requires Java 8 or greater.

Deployment

This application runs in a docker container. Use the instructions provided by ch.psi.daq.install to install the application on a server.

Application Properties

Following files define and describe application properties:

It is possible to overwrite properties by defining new values in ${HOME}/.config/daq/queryrest.properties

Maven

Upload jar to the Maven repository (from ch.psi.daq.buildall):

./gradlew ch.psi.daq.queryrest:uploadArchives

DropIt

Upload jar DropIt (from ch.psi.daq.buildall):

./gradlew ch.psi.daq.queryrest:dropIt -x test

Local Instance

DAQLocal provides a local instance of the DAQ system for testing purposes (allowing users/developers to verify their code before they come to PSI to do their research and interact with the DAQ cluster).

REST Interface

The REST interface is accessible through https://data-api.psi.ch/sf.

Query Channel Names

Request

POST https://<host>:<port>/channels

Data

{
   "regex":"TRFCA|TRFCB",
   "backends":[
      "sf-databuffer"
   ],
   "ordering":"asc",
   "reload":true
}
Explanation

Example

Command

curl -L -H "Content-Type: application/json" -X POST -d '{"regex": "AMPLT|PHASE"}' https://data-api.psi.ch/sf/channels | python -m json.tool

Response

[
   {
      "backend":"sf-databuffer",
      "channels":[
         "Channel_01_AMPLT",
         "Channel_02_AMPLT",
         "Channel_03_PHASE"
      ]
   },
   {
      "backend":"sf-archiverappliance",
      "channels":[
         "Channel_01_AMPLT",
         "Channel_04_PHASE",
         "Channel_05_AMPLT"
      ]
   }
]

Channel Configurations

It is possible to query channel configurations like type etc..

The following configuration queries provide the latest known configuration of the channels (see here on how to query the channel configuration history).

Query Channel Configurations

Request

POST https://<host>:<port>/channels/config

Data

{
   "regex":"^SINEG.*PHASE$",
   "backends":[
      "sf-databuffer"
   ],
   "ordering":"none",
   "sourceRegex":"LLRF"
}
Explanation

Example

Command

curl -L -H "Content-Type: application/json" -X POST -d '{"regex": "AMPLT|PHASE|CAM"}' https://data-api.psi.ch/sf/channels/config | python -m json.tool

Response

[
   {
      "backend":"sf-databuffer",
      "channels":[
         {
            "name":"Channel_01_AMPLT",
            "type":"UInt16",
            "shape":[2048],
            "modulo":1,
            "offset":0,
            "backend":"sf-databuffer",
            "source":"tcp://SINEG01-CVME-LLRF1:20000"
         },
         {
            "name":"Channel_01_PHASE_AVG",
            "type":"Float64",
            "shape":[1],
            "modulo":1,
            "offset":0,
            "backend":"sf-databuffer",
            "source":"tcp://SINEG01-CVME-LLRF1:20000"
         }
      ]
   },
   {
      "backend":"sf-imagebuffer",
      "channels":[
         {
            "name":"Helges_CAM",
            "type":"UInt16",
            "shape":[1024,2048],
            "modulo":1,
            "offset":0,
            "backend":"sf-imagebuffer",
            "source":"tcp://HELGE_COMPI:9999"
         }
      ]
   }
]

Query Specific Channel Configuration

Request

POST https://<host>:<port>/channel/config

or

GET https://<host>:<port>/channel/config/{channel}

Data

{
   "name":"SINEG01-RCIR-PUP10:SIG-AMPLT",
   "backend":"sf-databuffer"
}
Explanation

Example

Command

curl -L -H "Content-Type: application/json" -X POST -d '{"name": "SINEG01-RCIR-PUP10:SIG-AMPLT", "backend":"sf-databuffer"}' https://data-api.psi.ch/sf/channel/config | python -m json.tool

or

curl -L -H "Content-Type: application/json" -X GET https://data-api.psi.ch/sf/channel/config/SINEG01-RCIR-PUP10:SIG-AMPLT | python -m json.tool

Response

{
	"name":"SINEG01-RCIR-PUP10:SIG-AMPLT",
	"type":"UInt16",
	"shape":[2048],
	"modulo":1,
	"offset":0,
	"backend":"sf-databuffer",
	"source":"tcp://SINEG01-CVME-LLRF1:20000"
}

Query Data

Request

POST https://<host>:<port>/query

Request body

A request is performed by sending a valid JSON object in the HTTP request body. The JSON query defines the channels to be queried, the range, and how the data should be aggregated (this is optional but highly recommended).

Data

{
   "channels":[
      "Channel_01"
   ],
   "range":{
      "startPulseId":0,
      "endPulseId":3
   },
   "ordering":"asc",
   "configFields":[
      "globalDate",
      "type"
   ],
   "eventFields":[
      "pulseId",
      "globalDate",
      "value"
   ],
   "aggregation":{
      "aggregationType":"value",
      "aggregations":[
         "min",
         "mean",
         "max"
      ],
      "nrOfBins":2
   },
   "response":{
      "format":"json",
      "compression":"none",
      "allowRedirect":true
   },
   "mapping":{
      "incomplete":"provide-as-is"
   },
   "valueTransformations":[
	   {
	      "pattern":"ImageChannel",
	      "backend":"sf-imagebuffer",
	      "sequence":[
	         ...
	      ]
	   },
	   {
	      "pattern":"WaveformChannel",
	      "backend":"sf-databuffer",
	      "sequence":[
	         ...
	      ]
	   }
	]	   
}
Explanation
  • channels: Array of channels to be queried (see here and here).
  • range: The range of the query (see here).
  • limit: An optional limit for the number of elements to retrieve. Limit together with aggregation does not make sense and thus is not supported.
  • ordering: The ordering of the data (see here).
  • configFields: Array of requested config fields (see here). Omitting this field disables the config query.
  • eventFields: Array of requested event fields (see here). Omitting this field results in a default set of event fields.
  • aggregation: Setting this attribute activates data aggregation (see here for its specification).
  • response: Specifies the format of the response of the requested data (see here). If this value is not set it defaults to JSON.
  • mapping: Activates a table like alignment of the response which allows a mapping of values belonging to the same pulse-id/global time (see here - usually left undefined).
  • valueTransformations: Provides the option to apply transformations to channel values (see here).

Define Channel Names

The simplest way to define channels is to use an array of channel name Strings.

"channels":[
	"Channel_02",
	"Channel_04"
]

The query interface will automatically select the backend which contains the channel (e.g., sf-databuffer for Channel_02 and sf-archiverappliance for Channel_04). In case name clashes exist, the query interface will use following order of priority: sf-databuffer, sf-imagebuffer, and then sf-archiverappliance.

It is also possible to explicitly define the backend to overcome name clashes.

"channels":[
   {
      "name":"Channel_01",
      "backend":"sf-archiverappliance"
   },
   {
      "name":"Channel_01",
      "backend":"sf-databuffer"
   }
]

Define Query Range

Queries are applied to a range. The following types of ranges are supported.

By Pulse-Id

"range":{
   "startPulseId":0,
   "startInclusive":true,
   "startExpansion":false,
   "endPulseId":100,
   "endInclusive":true,
   "endExpansion":false
}
  • startPulseId: The start pulse-id of the range request.
  • startInclusive: Defines if the start should be considered inclusive (values: true|false).
  • startExpansion: Expands the query start until the first entry before the defined start (values: true|false). Binning aggregations are expanded until the start of the bin of that entry.
  • endPulseId: The end pulse-id of the range request.
  • endInclusive: Defines if the end should be considered inclusive (values: true|false).
  • endExpansion: Expands the query end until the first entry after the defined end (values: true|false). Binning aggregations are expanded until the end of the bin of that entry.

By Date

"range":{
   "startDate":"2015-08-06T18:00:00.000",
   "startInclusive":true,
   "startExpansion":false,
   "endDate":"2015-08-06T18:59:59.999",
   "endInclusive":true,
   "endExpansion":false
}
  • startDate: The start date of the time range in the ISO8601 format (such as 1997-07-16T19:20:30.123+02:00 or 1997-07-16T19:20:30.123456789+02:00 (omitting +02:00 falls back to the server's time zone)).
  • startInclusive: Defines if the start should be considered inclusive (values: true|false).
  • startExpansion: Expands the query start until the first entry before the defined start (values: true|false). Binning aggregations are expanded until the start of the bin of that entry.
  • endDate: The end date of the time range.
  • endInclusive: Defines if the end should be considered inclusive (values: true|false).
  • endExpansion: Expands the query end until the first entry after the defined end (values: true|false). Binning aggregations are expanded until the end of the bin of that entry.

By Time

"range":{
   "startSeconds":"0.0",
   "startInclusive":true,
   "startExpansion":false,
   "endSeconds":"1.000999999",
   "endInclusive":true,
   "endExpansion":false
}
  • startSeconds: The start time of the range in seconds since midnight, January 1, 1970 UTC (the UNIX epoch) as a decimal value including fractional seconds.
  • startInclusive: Defines if the start should be considered inclusive (values: true|false).
  • startExpansion: Expands the query start until the first entry before the defined start (values: true|false). Binning aggregations are expanded until the start of the bin of that entry.
  • endSeconds: The end time of the range in seconds.
  • endInclusive: Defines if the end should be considered inclusive (values: true|false).
  • endExpansion: Expands the query end until the first entry after the defined end (values: true|false). Binning aggregations are expanded until the end of the bin of that entry.

Data Ordering

"ordering":"asc"
  • ordering: Defines the ordering of the requested data (values: asc|desc|none). Use none in case ordering does not matter (allows for server side optimizations).

Requested Fields

"configFields":[
   "pulseId",
   "globalDate",
   "type"
],
"eventFields":[
   "pulseId",
   "globalDate",
   "value"
]

It is possible to request the time in seconds (since midnight, January 1, 1970 UTC (the UNIX epoch) as a decimal value including fractional seconds - using fields globalSeconds and iocSeconds), in milliseconds (since midnight, January 1, 1970 UTC (the JAVA epoch) - using fields globalMillis and iocMillis) or as a ISO8601 formatted String - using fields globalDate and iocDate (such as 1997-07-16T19:20:30.123456789+02:00).

Data Aggregation

It is possible (and recommended) to aggregate queried data.

   "aggregation":{
      "aggregationType":"value",
      "aggregations":[
         "min",
         "mean",
         "max"
      ],
      "nrOfBins":2
   }
  • aggregationType: Specifies the type of aggregation (see here). The default type is value aggregation (e.g., sum([1,2,3])=6). Alternatively, it is possible to define index aggregation for multiple arrays in combination with binning (e.g., sum([1,2,3], [3,2,1]) = [4,4,4]).
  • aggregations: Array of requested aggregations (see here for possible values). These values will be added to the data array response.
  • extrema: Array of requested extrema (see here for possible values). These values will be added to the data array response.
  • nrOfBins: Activates data binning. Specifies the number of bins the pulse/time range should be divided into (e.g., "nrOfBins":2).
  • durationPerBin: Activates data binning. Specifies the duration per bin for time-range queries (using duration makes this binning strategy consistent between channel with different update frequencies). The duration is defined as a ISO-8601 duration (e.g., "durationPerBin":"PT1H" for 1 hour, "durationPerBin":"PT2S" for 2 seconds, "durationPerBin":"PT0.05S" for 50 milliseconds etc.). The resolution is in milliseconds and thus the minimal duration is 1 millisecond.
  • pulsesPerBin: Activates data binning. Specifies the number of pulses per bin for pulse-range queries (e.g., "pulsesPerBin":100 - using number of pulses makes this binning strategy consistent between channel with different update frequencies).

Response Format

It is possible to specify the response format the queried data should have.

"response":{
   "format":"json",
   "compression":"none",
   "allowRedirect":true
}
  • format: The format of the response (values: json|csv). Please note that csv does not support index and extrema aggregations.
  • compression: Responses can be compressed when transferred from the server (values: none|gzip). If compression is enabled, you have to tell curl that the data is compressed by defining the attribute --compressed so that it decompresses the data automatically.
  • allowRedirect: Defines it the central query rest server is allowed to redirect queries to the query rest server of the actual backend given that the query allows for it (values: true|false). Redirect needs to be enabled in curl using the -L option.

Value Mapping

It is possible to map values based on their pulse-id/global time. Setting this option activates a table like alignment of the response which differs from the standard response format.

"mapping":{
   "incomplete":"provide-as-is",
   "alignment":"by-pulse",
   "aggregations":["count","min","mean","max"]
}
  • incomplete: Defines how incomplete mappings should be handled (e.g., when the values of two channels should be mapped but these channels have different frequencies or one was not available at the specified query range (values: provide-as-is|drop|fill-null). provide-as-is provides the data as recorded, drop discards incomplete mappings, and fill-null fills incomplete mappings with a null string (simplifies parsing).
  • alignment: Defines how the events should be aligned to each other (values: by-pulse|by-time|none). In case alignment is undefined it will be selected based on the query type (query by pulse-id or by time). none will simply add one event of a channel after the other (independent of other channels).
  • aggregations: In case several events are mapped into the same bin (e.g. due to activated binning or duplicated pulse-ids) the values will be aggregated based on this parameter (in case it is undefined it will use the global/default aggregations).

Value Transformations

It is possible to apply transformations to values. These transformations are available as transformedValue in the response (the format/value of transformedValue can differ based on the transformation sequence).

"valueTransformations":[
   {
      "pattern":"ChannelNamePattern",
      "backend":"sf-databuffer",
      "sequence":[
         ...
      ]
   }
]

Value Transformation Operations

Image Resize

The following transformation sequence resizes images by the factor of 8, sets the value range to [400...4000], uses the temperature color model, and provides the image as a base64 encoded string.

"valueTransformations":[
   {
      "pattern":"Image",
      "backend":"sf-imagebuffer",
      "sequence":[
         {
            "imageResize":{
               "downScaleFactor":8,
               "valueAggregation":"first-value"
            },
            "valueFunctions":[
               {
                  "min":400.0,
                  "mapTo":400.0
               },
               {
                  "max":4000.0,
                  "mapTo":4000.0
               }
            ],
            "colorModel":{
               "modelType":"temperature",
               "nrOfColors":32,
               "colors":[
                  "#3B4CC0",
                  "#B40426"
               ]
            }
         },
         {
            "imageFormat":"png",
            "imageEncoder":"base64string"
         }
      ]
   }
]

Applying an image resize transformation has the advantage that the computation is done on the backend resulting in much less data transfer.

Value Sampling

The following transformation sequence resizes images by the factor of 4, filters all values below 200 (considers values below 200 as noise), and provides the image in the raw format.

This transformation could potentially also be used for other value forms than images.

"valueTransformations":[
   {
      "pattern":"Image",
      "backend":"sf-imagebuffer",
      "sequence":[
        "valueSampler":{
          "downSampleFactor":4,
          "valueAggregation":"first-value"
        },
        "valueFunctions":[
          {
            "min":200.0,
            "mapTo":0.0
          }
        ]
      ]
   }
]
  • valueSampler: The value sampling operation.

  • downSampleFactor: The downsample factor (e.g. a factor of 4 reduces a square of 4x4 pixels into one pixel or 4 elements of a waveform into on element).

  • valueAggregation: Defines how the values should be aggregated (values: first-value|max-value|mean-value). first-value uses the first value of the reduction area (very fast but signals might get lost), max-value uses the max value of the reduction area, and mean-value the mean value of the reduction area.

  • valueFunctions: Array of functions to be applied to values.

  • min: Map all values smaller than the defined values to the mapTo value. Allows to define a filter to eliminate noise (using "mapTo":0) or to set a lower value bound. In case mapTo is not defined it defaults to min.

  • max: Map all values bigger than the defined values to the mapTo value. Can be used to set a upper value bound. In case mapTo is not defined it defaults to max.

Applying a value sampling transformation has the advantage that the computation is done on the backend resulting in much less data transfer.

The response has the format '"transformedValue":{"shape":[width,height],"value":[value1,value2,...]}'.

Example Queries

The following examples build on waveform data (see below). They also work for scalars (consider it as a waveform of length = 1) and images (waveform of length = dimX * dimY).

Data Visualization

[
   {
      "channel":{
            "backend": "sf-databuffer",
            "name": "Channel_01"
      },
      "data":[
         {
            "iocSeconds":"0.000000000",
            "pulseId":0,
            "globalSeconds":"0.000000000",
            "shape":[
               4
            ],
            "value":[1,2,3,4]
         },
         {
            "iocSeconds":"0.010000000",
            "pulseId":1,
            "globalSeconds":"0.010000000",
            "shape":[
               4
            ],
            "value":[2,3,4,5]
         },
         {
            "iocSeconds":"0.020000000",
            "pulseId":2,
            "globalSeconds":"0.020000000",
            "shape":[
               4
            ],
            "value":[3,4,5,6]
         },
         {
            "iocSeconds":"0.030000000",
            "pulseId":3,
            "globalSeconds":"0.030000000",
            "shape":[
               4
            ],
            "value":[4,5,6,7]
         }
      ]
   },
   {
      "channel":{
            "backend": "sf-databuffer",
            "name": "Channel_02"
      },
      "data":[
         {
            "iocSeconds":"0.000000000",
            "pulseId":0,
            "globalSeconds":"0.000000000",
            "shape":[
               4
            ],
            "value":[1,2,3,4]
         },
         {
            "iocSeconds":"0.010000000",
            "pulseId":1,
            "globalSeconds":"0.010000000",
            "shape":[
               4
            ],
            "value":[2,3,4,5]
         },
         {
            "iocSeconds":"0.020000000",
            "pulseId":2,
            "globalSeconds":"0.020000000",
            "shape":[
               4
            ],
            "value":[3,4,5,6]
         },
         {
            "iocSeconds":"0.030000000",
            "pulseId":3,
            "globalSeconds":"0.030000000",
            "shape":[
               4
            ],
            "value":[4,5,6,7]
         }
      ]
   }
]

Query Examples

Query by Pulse-Id Range

{
   "range":{
      "startPulseId":0,
      "endPulseId":3
   },
   "channels":[
      "Channel_01"
   ]
}
Command
curl  -H "Content-Type: application/json" -X POST -d '{"range":{"startPulseId":0,"endPulseId":3},"channels":["Channel_01"]}' https://data-api.psi.ch/sf/query | python -m json.tool
Response

See JSON representation of the data above.

Query by Time Range

{
   "range":{
      "startSeconds":"0.0",
      "endSeconds":"0.030999999"
   },
   "channels":[
      "Channel_01"
   ]
}
Command
curl  -H "Content-Type: application/json" -X POST -d '{"range":{"startSeconds":"0.0","endSeconds":"0.030999999"},"channels":["Channel_01"]}' https://data-api.psi.ch/sf/query | python -m json.tool
Response

See JSON representation of the data above.

Query by Date Range

{
   "range":{
      "startDate":"1970-01-01T01:00:00.000",
      "endDate":"1970-01-01T01:00:00.030"
   },
   "channels":[
      "Channel_01"
   ]
}

The supported date format is ISO8601 (such as 1997-07-16T19:20:30.123+02:00 or 1997-07-16T19:20:30.123456789+02:00 (omitting +02:00 falls back to the server's time zone)).

Command
curl  -H "Content-Type: application/json" -X POST -d '{"range":{"startDate":"1970-01-01T01:00:00.000","endDate":"1970-01-01T01:00:00.030"},"channels":["Channel_01"]}' https://data-api.psi.ch/sf/query | python -m json.tool
Response

See JSON representation of the data above.

Querying Archiver Appliance

{
   "range":{
      "startSeconds":"0.0",
      "endSeconds":"0.030999999"
   },
   "channels":[
      {
	      "name": "Channel_01",
	      "backend":"sf-archiverappliance"
      },
      {
	      "name": "Channel_02",
	      "backend":"sf-archiverappliance"
      }
   ]
}

Archiver Appliance supports queries by time range and date range only (as it has no notion about pulse-id).

Command
curl  -H "Content-Type: application/json" -X POST -d '{"range":{"startSeconds":"0.0","endSeconds":"0.030999999"},"channels":[{"name": "Channel_01","backend":"sf-archiverappliance"}]}' https://data-api.psi.ch/sf/query | python -m json.tool
Response

See JSON representation of the data above.

Query Using Compression

{
    "response":{
        "compression":"gzip"
    },
    "range":{
        "startPulseId":0,
        "endPulseId":3
     },
     "channels":[
        "Channel_01"
     ]
}
Command (gzip)

The curl command has a --compressed option to decompress data automatically.

curl --compressed -H "Content-Type: application/json" -X POST -d '{"response":{"compression":"gzip"},"range":{"startPulseId":0,"endPulseId":3},"channels":["Channel_01"]}' https://data-api.psi.ch/sf/query | python -m json.tool

Querying for Specific Fields

Allows for server side optimizations since not all data needs to be retrieved.

{
   "eventFields":["pulseId","value"],
   "range":{
      "startPulseId":0,
      "endPulseId":3
   },
   "channels":[
      "Channel_01"
   ]
}
Command
curl  -H "Content-Type: application/json" -X POST -d '{"eventFields":["pulseId","value"],"range":{"startPulseId":0,"endPulseId":3},"channels":["Channel_01"]}' https://data-api.psi.ch/sf/query | python -m json.tool
Response
[
   {
      "channel":{
            "backend": "sf-databuffer",
            "name": "Channel_01"
      },
      "data":[
         {
            "pulseId":0,
            "value":[1,2,3,4]
         },
         {
            "pulseId":1,
            "value":[2,3,4,5]
         },
         {
            "pulseId":2,
            "value":[3,4,5,6]
         },
         {
            "pulseId":3,
            "value":[4,5,6,7]
         }
      ]
   }
]

Query CSV Format

{
    "response":{
        "format":"csv"
    },
    "range":{
        "startPulseId":0,
        "endPulseId":4
    },
    "channels":[
        "channel1",
        "channel2"
    ],
    "eventFields":[
        "channel",
        "pulseId",
        "iocSeconds",
        "globalSeconds",
        "shape",
        "eventCount",
        "value"
    ]
}
Command
curl -L -H "Content-Type: application/json" -X POST -d '{"response":{"format":"csv"},"range":{"startPulseId":0,"endPulseId":4},"channels":["channel1","channel2"],"eventFields":["channel","pulseId","iocSeconds","globalSeconds","shape","eventCount","value"]}' https://data-api.psi.ch/sf/query
Response

The response is in CSV.

channel;pulseId;iocSeconds;globalSeconds;shape;eventCount;value
testChannel1;0;0.000000000;0.000000000;[1];1;0
testChannel1;1;0.010000000;0.010000000;[1];1;1
testChannel1;2;0.020000000;0.020000000;[1];1;2
testChannel1;3;0.030000000;0.030000000;[1];1;3
testChannel1;4;0.040000000;0.040000000;[1];1;4
testChannel2;0;0.000000000;0.000000000;[1];1;0
testChannel2;1;0.010000000;0.010000000;[1];1;1
testChannel2;2;0.020000000;0.020000000;[1];1;2
testChannel2;3;0.030000000;0.030000000;[1];1;3
testChannel2;4;0.040000000;0.040000000;[1];1;4

Data Ordering

{
   "ordering":"desc",
   "eventFields":["pulseId","value"],
   "range":{
      "startPulseId":0,
      "endPulseId":3
   },
   "channels":[
      "Channel_01"
   ]
}

Use none in case ordering does not matter (allows for server side optimizations).

Command
curl  -H "Content-Type: application/json" -X POST -d '{"ordering":"desc","eventFields":["pulseId","value"],"range":{"startPulseId":0,"endPulseId":3},"channels":["Channel_01"]}' https://data-api.psi.ch/sf/query | python -m json.tool
Response
[
   {
      "channel":{
            "backend": "sf-databuffer",
            "name": "Channel_01"
      },
      "data":[
         {
            "pulseId":3,
            "value":[4,5,6,7]
         },
         {
            "pulseId":2,
            "value":[3,4,5,6]
         },
         {
            "pulseId":1,
            "value":[2,3,4,5]
         },
         {
            "pulseId":0,
            "value":[1,2,3,4]
         }
      ]
   }
]

Query Aggregated Values

{
   "aggregation":{
      "aggregationType":"value",
      "aggregations":["min","mean","max"]
   },
   "eventFields":["pulseId","value"],
   "range":{
      "startPulseId":0,
      "endPulseId":3
   },
   "channels":[
      "Channel_01"
   ]
}
Command
curl  -H "Content-Type: application/json" -X POST -d '{"aggregation":{"aggregationType":"value","aggregations":["min","mean","max"]},"eventFields":["pulseId","value"],"range":{"startPulseId":0,"endPulseId":3},"channels":["Channel_01"]}' https://data-api.psi.ch/sf/query | python -m json.tool
Response
[
   {
      "channel":{
            "backend": "sf-databuffer",
            "name": "Channel_01"
      },
      "data":[
         {
            "pulseId":0,
            "value":{
               "min":1.0,
               "max":4.0,
               "mean":2.5
            }
         },
         {
            "pulseId":1,
            "value":{
               "min":2.0,
               "max":5.0,
               "mean":3.5
            }
         },
         {
            "pulseId":2,
            "value":{
               "min":3.0,
               "max":6.0,
               "mean":4.5
            }
         },
         {
            "pulseId":3,
            "value":{
               "min":4.0,
               "max":7.0,
               "mean":5.5
            }
         }
      ]
   }
]

Illustration of array value aggregation:

Value Aggregation

Value Aggregation with Binning (nrOfBins)

{
   "aggregation":{
      "nrOfBins":2,
      "aggregationType":"value",
      "aggregations":["min","mean","max"]
   },
   "eventFields":["pulseId","value"],
   "range":{
      "startPulseId":0,
      "endPulseId":3
   },
   "channels":[
      "Channel_01"
   ]
}
Command
curl  -H "Content-Type: application/json" -X POST -d '{"aggregation":{"nrOfBins":2,"aggregationType":"value","aggregations":["min","mean","max"]},"eventFields":["pulseId","value"],"range":{"startPulseId":0,"endPulseId":3},"channels":["Channel_01"]}' https://data-api.psi.ch/sf/query | python -m json.tool
Response
[
   {
      "channel":{
            "backend": "sf-databuffer",
            "name": "Channel_01"
      },
      "data":[
         {
            "pulseId":0,
            "value":{
               "min":1.0,
               "max":5.0,
               "mean":3.0
            }
         },
         {
            "pulseId":2,
            "value":{
               "min":3.0,
               "max":7.0,
               "mean":5.0
            }
         }
      ]
   }
]

Illustration of array value aggregation with additional binning:

Value Aggregation with Binning

Value Aggregation with Binning (durationPerBin/pulsesPerBin)

durationPerBin specifies the duration per bin for time-range queries (using duration makes this binning strategy consistent between channel with different update frequencies). The duration is defined as a ISO-8601 duration (e.g., PT1H for 1 hour, PT2S for 2 seconds, PT0.05S for 50 milliseconds etc.). The resolution is in milliseconds and thus the minimal duration is 1 millisecond.

pulsesPerBin specifies the number of pulses per bin for pulse-range queries (using number of pulses makes this binning strategy consistent between channel with different update frequencies).

{
   "aggregation":{
      "pulsesPerBin":2,
      "aggregationType":"value",
      "aggregations":["min","mean","max"]
   },
   "eventFields":["globalMillis","value"],
   "range":{
      "startSeconds":"0.0",
      "endSeconds":"0.030000000"
   },
   "channels":[
      "Channel_01"
   ]
}
Command
curl  -H "Content-Type: application/json" -X POST -d '{"aggregation":{"pulsesPerBin":2,"aggregationType":"value","aggregations":["min","mean","max"]},"eventFields":["globalMillis","value"],"range":{"startSeconds":"0.0","endSeconds":"0.030000000"},"channels":["Channel_01"]}' https://data-api.psi.ch/sf/query | python -m json.tool
Response
[
   {
      "channel":{
            "backend": "sf-databuffer",
            "name": "Channel_01"
      },
      "data":[
         {
            "globalMillis":0,
            "value":{
               "min":1.0,
               "max":5.0,
               "mean":3.0
            }
         },
         {
            "globalMillis":20,
            "value":{
               "min":3.0,
               "max":7.0,
               "mean":5.0
            }
         }
      ]
   }
]

Illustration of array value aggregation with additional binning:

Value Aggregation with Binning

Index Aggregation

{
   "aggregation":{
      "pulsesPerBin":1,
      "aggregationType":"index",
      "aggregations":["min","mean","max","sum"]
   },
   "eventFields":["pulseId","value"],
   "range":{
      "startPulseId":0,
      "endPulseId":3
   },
   "channels":[
      "Channel_01"
   ]
}
Command
curl  -H "Content-Type: application/json" -X POST -d '{"aggregation":{"nrOfBins":1,"aggregationType":"index","aggregations":["min","max","mean","sum"]},"eventFields":["pulseId","value"],"range":{"startPulseId":0,"endPulseId":3},"channels":["Channel_01"]}' https://data-api.psi.ch/sf/query | python -m json.tool
Response
[
   {
      "channel":{
            "backend": "sf-databuffer",
            "name": "Channel_01"
      },
      "data":[
         {
            "pulseId":0,
            "value":[
               {
                  "min":1.0,
                  "max":4.0,
                  "mean":2.5,
                  "sum":10.0
               },
               {
                  "min":2.0,
                  "max":5.0,
                  "mean":3.5,
                  "sum":14.0
               },
               {
                  "min":3.0,
                  "max":6.0,
                  "mean":4.5,
                  "sum":18.0
               },
               {
                  "min":4.0,
                  "max":7.0,
                  "mean":5.5,
                  "sum":22.0
               }
            ]
         }
      ]
   }
]

Illustration of array index aggregation with additional with binning (several nrOfBins are also possible):

Index Aggregation with Binning

Query with Value Mapping

Maps values based on their pulse-id/global time. Please note that the response format differs in order to represent the value mapping. Lets assume for this query that Channel_02 only provides events for even pulse-ids.

{
   "eventFields":["pulseId","value"],
   "range":{
      "startPulseId":0,
      "endPulseId":3
   },
   "channels":[
      "Channel_01",
      "Channel_02"
   ],
   "mapping":{
      "incomplete":"provide-as-is"
   }
}
Command
curl  -H "Content-Type: application/json" -X POST -d '{"eventFields":["pulseId","value"],"range":{"startPulseId":0,"endPulseId":3},"channels":["Channel_01","Channel_02"],"mapping":{"incomplete":"provide-as-is"}}' https://data-api.psi.ch/sf/query | python -m json.tool
Response

With provide-as-is, the response will contain all available data. In case drop would be used, only events with even pulse-ids would be returned (assuming Channel_02 only provides events for even pulse-ids).

{
   "data":[
      [
         {
            "channel":"Channel_01",
            "backend":"sf-databuffer",
            "pulseId":0,
            "value":0
         },
         {
            "channel":"Channel_02",
            "backend":"sf-databuffer",
            "pulseId":0,
            "value":0
         }
      ],
      [
         {
            "channel":"Channel_01",
            "backend":"sf-databuffer",
            "pulseId":1,
            "value":1
         }
      ],
      [
         {
            "channel":"Channel_01",
            "backend":"sf-databuffer",
            "pulseId":2,
            "value":2
         },
         {
            "channel":"Channel_02",
            "backend":"sf-databuffer",
            "pulseId":2,
            "value":2
         }
      ],
      [
         {
            "channel":"Channel_01",
            "backend":"sf-databuffer",
            "pulseId":3,
            "value":3
         }
      ]
   ]
}

Query Channel Configuration History

Request

POST https://<host>:<port>/query/config

Request body

A request is performed by sending a valid JSON object in the HTTP request body. The JSON query defines the channels to be queried and the range.

Data

{
   "channels":[
      "Channel_01"
   ],
   "range":{
      "startPulseId":0,
      "endPulseId":3
   },
   "ordering":"asc",
   "configFields":[
      "pulseId",
      "globalDate",
      "type"
   ],
   "response":{
      "format":"json",
      "compression":"none",
      "allowRedirect":true
   }	   
}
Explanation

The query format is equivalent to the data query (see here for further explanations - be aware that the url is not equivalent).

Command
curl  -H "Content-Type: application/json" -X POST -d '{"range":{"startDate":"2017-01-01T01:00:00.000","endDate":"2017-11-01T01:00:00.030"},"channels":["Channel_01"]}' https://data-api.psi.ch/sf/query/config | python -m json.tool

Query Pulse-Id Time Mapping

Request

POST https://<host>:<port>/query/mapping

Request body

A request is performed by sending a valid JSON object in the HTTP request body. The JSON query defines the channels to be queried and the range. In case no channels are defined the global pulseId-time mapping will be queried (otherwise the channel specific mapping - e.g. some events might have been delete).

Data

{
   "channels":[
      "Channel_01"
   ],
   "range":{
      "startPulseId":0,
      "endPulseId":3
   },
   "ordering":"asc",
   "eventFields":[
      "pulseId",
      "globalDate"
   ],
   "response":{
      "format":"json",
      "compression":"none",
      "allowRedirect":true
   }	   
}
Explanation

The query format is equivalent to the data query (see here for further explanations - be aware that the url is not equivalent).

Command
curl  -H "Content-Type: application/json" -X POST -d '{"range":{"startDate":"2017-01-01T01:00:00.000","endDate":"2017-11-01T01:00:00.030"},"channels":["Channel_01"]}' https://data-api.psi.ch/sf/query/mapping | python -m json.tool

or

curl  -H "Content-Type: application/json" -X POST -d '{"range":{"startPulseId":4,"endPulseId":20},"eventFields":["pulseId","globalSeconds"]}' https://data-api.psi.ch/sf/query/mapping | python -m json.tool
Description
Copy of ch.psi.daq.queryrest from git.psi.ch. This contains the documentation of the GLS API.
Readme 1.6 MiB
Languages
Java 100%