Events

Events are the most basic type of asynchronous notification in TMT when an activity occurs somewhere in the TMT system and other components need to be notified. Each type of event has a unique purpose and unique information, but they all share same structural features. All events have EventInfo and a ParameterSet.

Note

The csw-params library offers out of the box support to serialize Events using Cbor, so that events can be produced and consumed by JVM (Java virtual machine) as well as Non-JVM applications.

For more on Cbor, refer to the technical doc.

EventTime

Each event includes its time of creation in UTC format. You can access that eventTime as follows:

Scala
sourceval source    = Prefix("iris.filter.wheel")
val eventName = EventName("temperatures")
val event     = SystemEvent(source, eventName)

// accessing eventTime
val eventTime = event.eventTime
Java
source
//apply returns current time in UTC UTCTime now = UTCTime.now(); //using constructor UTCTime anHourAgo = new UTCTime(Instant.now().minusSeconds(3600)); //return current time in UTC UTCTime currentTime = UTCTime.now(); //some past time using utility function UTCTime aDayAgo = new UTCTime(Instant.now().minusSeconds(86400));

System Event

SystemEvent is the type used to describe the majority of events in the system. An example is a demand that is the output of an algorithm in one component that is used as an input to another. SystemEvent is also used to publish internal state or status values of a component that may be of interest to other components in the system.

Scala
source// keys
val k1: Key[Int]    = KeyType.IntKey.make("encoder")
val k2: Key[Int]    = KeyType.IntKey.make("speed")
val k3: Key[String] = KeyType.StringKey.make("filter")
val k4: Key[Int]    = KeyType.IntKey.make("notUsed")

// prefixes
val ck1   = Prefix("wfos.red.filter")
val name1 = EventName("filterWheel")
val ck3   = Prefix("iris.imager.filter")
val name3 = EventName("status")

// parameters
val p1: Parameter[Int]    = k1.set(22)
val p2: Parameter[Int]    = k2.set(44)
val p3: Parameter[String] = k3.set("A", "B", "C", "D")

// Create SystemEvent using madd
val se1: SystemEvent = SystemEvent(ck1, name1).madd(p1, p2)
// Create SystemEvent using apply
val se2: SystemEvent = SystemEvent(ck3, name3, Set(p1, p2))
// Create SystemEvent and use add
val se3: SystemEvent = SystemEvent(ck3, name3).add(p1).add(p2).add(p3)

// access keys
val k1Exists: Boolean = se1.exists(k1) // true

// access Parameters
val p4: Option[Parameter[Int]] = se1.get(k1)

// access values
val v1: Array[Int] = se1(k1).values
val v2: Array[Int] = se2.parameter(k2).values
// k4 is missing
val missingKeys: Set[String] = se3.missingKeys(k1, k2, k3, k4)

// remove keys
val se4: SystemEvent = se3.remove(k3)

// add more than one parameters, using madd
val se5: SystemEvent = se4.madd(k3.set("X", "Y", "Z").withUnits(Units.day), k4.set(99, 100))
val paramSize: Int   = se5.size

// update existing key with set
val se6: SystemEvent = se5.add(k2.set(5, 6, 7, 8))
Java
source//keys
Key<Integer> k1 = JKeyType.IntKey().make("encoder", JUnits.encoder);
Key<Integer> k2 = JKeyType.IntKey().make("speed");
Key<String> k3 = JKeyType.StringKey().make("filter");
Key<Integer> k4 = JKeyType.IntKey().make("notUsed");

//prefixes
Prefix prefix1 = Prefix.apply(JSubsystem.WFOS, "red.filter");
EventName name1 = new EventName("filterWheel");
Prefix prefix2 = Prefix.apply(JSubsystem.IRIS, "imager.filter");
EventName name2 = new EventName("status");

//parameters
Parameter<Integer> p1 = k1.set(22);
Parameter<Integer> p2 = k2.set(44);
Parameter<String> p3 = k3.set("A", "B", "C", "D");

//Create SystemEvent using madd
SystemEvent se1 = new SystemEvent(prefix1, name1).madd(p1, p2);
//Create SystemEvent using add
SystemEvent se2 = new SystemEvent(prefix2, name2).add(p1).add(p2);
//Create SystemEvent and use add
SystemEvent se3 = new SystemEvent(prefix2, name2).add(p1).add(p2).add(p3);

//access keys
boolean k1Exists = se1.exists(k1); //true

//access Parameters
Optional<Parameter<Integer>> p4 = se1.jGet(k1);

//access values
List<Integer> v1 = se1.jGet(k1).orElseThrow().jValues();
List<Integer> v2 = se2.parameter(k2).jValues();
//k4 is missing
Set<String> missingKeys = se3.jMissingKeys(k1, k2, k3, k4);

//remove keys
SystemEvent se4 = se3.remove(k3);

Observe Event

ObserveEvent are standardized events used to describe an activities within the data acquisition process. These events are typically published by Science Detector Assemblies, which emit ObserveEvents during their exposures to signal the occurrence of specific activities/actions during the acquisition of data. Observe Events serve the following purposes in OSW:

  • Provide a TMT-standardized API for notification of activities in detector systems
  • Provide TMT-standardized events that can be used to synchronize and trigger actions in other parts of the distributed software system
  • Provide a standardized API to science and engineering detector systems to ease interfacing Sequencers
  • Provide TMT-standardized APIs that can be more easily used by user interface programs that must deal with many detector systems
  • Provide notification of actions that can be used to generate observatory efficiency metrics and time accounting

IR Science Detector Systems Observe Events

The Observe Events for IR science detector systems are based on the events proposed for the IRIS instrument at their PDR2. These events include Observe Events for actions.
A state and data event are defined to allow user interfaces and Sequencers to monitor and control with similar behavior across the observatory.

Observe Event Description Probable Publisher
observeStart Indicates the start of execution of actions related to an Observe command Instrument Sequencer or possibly OCS Sequencer
exposureStart Indicates the start of data acquisition that results in a file produced for DMS. This is a potential metadata event for DMS Detector Assembly or possibly Instrument Sequencer
exposureEnd Indicates the end of data acquisition that results in a file produced for DMS. This is a potential metadata event for DMS Detector Assembly or possibly Instrument Sequencer
readoutEnd Indicates that a readout that is part of a ramp has completed Detector HCD or possibly Detector Assembly
readoutFailed Indicates that a readout that is part of a ramp has failed indicating transfer failure or some other issue Detector HCD or possibly Detector Assembly
dataWriteStart Indicates that the instrument has started writing the exposure data file or transfer of exposure data to DMS. Detector Assembly or possibly Detector HCD
dataWriteEnd Indicates that the instrument has finished writing the exposure data file or transfer of exposure data to DMS. Detector Assembly or possibly Detector HCD
exposureAbort Indicates that a request was made to abort the exposure and it has completed. Normal data events should occur if data is recoverable. Abort should not fail Detector Assembly or possibly Detector HCD
observeEnd Indicates the end of execution of actions related to an Observe command Instrument Sequencer or possibly OCS Sequencer

Two additional standardized events are defined to enable uniform detector information for Sequencers and user interfaces. These events are also based on the IRIS design.

IR Detector Exposure State Event

An exposure state Observe Event called irDetectorExposureState is provided as a state variable to indicate the current state of the detector system. The Exposure State Event groups parameters that change relatively slowly, and this event should be published whenever any of the parameters changes. The Exposure State Event includes the following mandatory parameters, but a detector system may add additional parameters as well. (The parameters in this event are based on the IRIS PDR2 model files.)

Parameters Description
exposureId ExposureId is an identifier in ESW/DMS for a single exposure. The ExposureId follows the structure: 2020A-001-123-WFOS-IMG1-SCI0-0001 with an included ObsId or when no ObsId is present, in the standalone format: 20200706-190204-WFOS-IMG1-SCI0-0001 with a UTC time when the ExposureId is created.
exposureInProgress A Boolean indicating if detector system is acquiring an exposure • Delimited by exposureStart and exposureEnd. exposureInProgress should be false if abortInProgress is true (TBD)
abortInProgress Indicates that an abort has been requested and is underway
isAborted Indicates that an abort has occurred and is completed. abortInProgress should be false when isAborted is true. isAborted should be set to false with the next exposure
operationalState Enumeration indicating if the detector system is available and operational. READY, NOT_READY, BUSY, ERROR. READY indicates system can execute exposures. NOT_READY indicates system cannot execute exposures. BUSY indicates system is BUSY most likely acquiring data. ERROR indicates the detector system is in an error state. This could happen as a result of a command or a spontaneous failure. Corrective action is required.
errorMessage An optional parameter that can be included when the detector system is in the ERROR operationalState. This value should be cleared and removed from the state when the operationalState returns to READY

This event should be published whenever any of the state parameters change. Parameters such as errorMessage and isAborted should be cleared when a new exposure is started.

IR Detector Exposure Data Event

A second mandatory Observe Event named irDetectorExposureData contains fast-changing data about the internals of the current exposure. This data is useful for user interfaces and Sequencers. This event should be published at the read rate or 1 Hz (whichever is less) during an ongoing exposure.

Parameters Description
exposureId ExposureId is an identifier in ESW/DMS for a single exposure. The ExposureId follows the structure: 2020A-001-123-WFOS-IMG1-SCI0-0001 with an included ObsId or when no ObsId is present, in the standalone format: 20200706-190204-WFOS-IMG1-SCI0-0001 with a UTC time when the ExposureId is created.
readsInRamp The integer total number of reads in the ramp. Value should be constant during an exposure. (Note: for multi-array detectors, it is assumed that all arrays work with the same configuration).
readsComplete Integer number of current completed read from 1 to readsInRamp. Should be reset to 0 at the start of every ramp
rampsInExposure The integer total number of ramps in the current exposure. Value should be constant during an exposure
rampsComplete Integer number of completed ramp from 1 to rampsInExposure. Should be reset to 0 at the start of every exposure
exposureTime Length in seconds of the current exposure
remainingExposureTime Number of seconds remaining in current exposure • Should count down in seconds – no faster than 1 Hz

Optical Science Detector Systems

The first light CCD-based instrument WFOS is not as advanced as IRIS and information in this section is based on author experience. The specific events may change in detail, but it is expected that what is presented here is adequate.

Optical detectors are often larger and somewhat simpler to control at the electronics level than IR detectors. Optical detector systems for astronomy often include several CCDs forming a mosaic that together cover the focal plane and are viewed as a single image. All the detectors operate in unison as a single detector system.

Optical detectors need to have shutters to control when light is collected on the detector. CCD based detectors accumulate photons/charge while the shutter is open and are read out after the shutter closes. Some modes such as nod and shuffle require more detailed control of the detector and system. (This is not covered here because TMT has not mentioned any modes such as this. The design may need to be extended to handle other ways of using the CCD.)

The optical science detector system Observe Events are largely identical to the IR science detector Observe Events

Observe Event Description Probable Publisher
observeStart Indicates the start of execution of actions related to an Observe command Instrument Sequencer or possibly OCS Sequencer
prepareStart Indicates that the detector system is preparing to start an exposure Detector Assembly or possibly Instrument Sequencer
exposureStart Indicates the start of data acquisition that results in a file produced for DMS. This is a potential metadata event for DMS Detector Assembly or possibly Instrument Sequencer
exposureEnd Indicates the end of data acquisition that results in a file produced for DMS. This is a potential metadata event for DMS Detector Assembly or possibly Instrument Sequencer
readoutEnd Indicates that a readout that is part of a ramp has completed Detector HCD or possibly Detector Assembly
readoutFailed Indicates that a readout that is part of a ramp has failed indicating transfer failure or some other issue Detector HCD or possibly Detector Assembly
dataWriteStart Indicates that the instrument has started writing the exposure data file or transfer of exposure data to DMS. Detector Assembly or possibly Detector HCD
dataWriteEnd Indicates that the instrument has finished writing the exposure data file or transfer of exposure data to DMS. Detector Assembly or possibly Detector HCD
exposureAbort Indicates that a request was made to abort the exposure and it has completed. Normal data events should occur if data is recoverable. Abort should not fail Detector Assembly or possibly Detector HCD
observeEnd Indicates the end of execution of actions related to an Observe command Instrument Sequencer or possibly OCS Sequencer
Note

there is a question about whether observeStart and observeEnd are generated by the Instrument Sequencer or OCS Sequencer. Each observeStart and observeEnd is associated with an Observe command. If an instrument sequencer never receives more than one Observe, then the Observe Events can be published by the OCS Sequencer. Note that these events have required parameters, which are given in RD06

Two additional standardized events are defined to enable uniform detector information for Sequencers and user interfaces. These events are also based on the preceding sections.

Optical Detector Exposure State Event

An exposure state Observe Event called opticalDetectorExposureState is provided as a state variable to indicate the current state of the detector system. The Exposure State Event groups parameters that change relatively slowly, and this event should be published whenever any of its parameters changes. The Exposure State Event includes the following mandatory parameters (Table 3-4), but a detector system may add their own parameters as well. The optical and IR detector exposure state events are identical.

Parameters Description
exposureId ExposureId is an identifier in ESW/DMS for a single exposure. The ExposureId follows the structure: 2020A-001-123-WFOS-IMG1-SCI0-0001 with an included ObsId or when no ObsId is present, in the standalone format: 20200706-190204-WFOS-IMG1-SCI0-0001 with a UTC time when the ExposureId is created.
exposureInProgress A Boolean indicating if detector system is acquiring an exposure. Delimited by exposureStart and exposureEnd. exposureInProgress should be false if abortInProgress is true (TBD)
abortInProgress Indicates that an abort has been requested and is underway
isAborted Indicates that an abort has occurred and is completed. abortInProgress should be false when isAborted is true. isAborted should be set to false with the next exposure
operationalState Enumeration indicating if the detector system is available and operational. READY, NOT_READY, BUSY, ERROR. READY indicates system can execute exposures. NOT_READY indicates system cannot execute exposures. BUSY indicates system is BUSY most likely acquiring data. ERROR indicates the detector system is in an error state. This could happen as a result of a command or a spontaneous failure. Corrective action is required.
errorMessage An optional parameter that can be included when the detector system is in the ERROR operationalState. This value should be cleared and removed from the state when the operationalState returns to READY

This event is standardized to allow ESW user interfaces to have minimal, uniform information about the state of any Science Detector System.

Optical Detector Exposure Data Event

A second mandatory Observe Event named opticalDetectorExposureData event contains faster changing data about the internals of the current exposure. This data is useful for user interfaces and Sequencers. This event should be published at 1 Hz during an ongoing exposure. This event does not have much information compared to the IR use case and is primarily for tracking the remaining current exposure time in user interfaces or sequencers.

Parameters Description
exposureId ExposureId is an identifier in ESW/DMS for a single exposure. The ExposureId follows the structure: 2020A-001-123-WFOS-IMG1-SCI0-0001 with an included ObsId or when no ObsId is present, in the standalone format: 20200706-190204-WFOS-IMG1-SCI0-0001 with a UTC time when the ExposureId is created.
exposureTime Length in seconds of the current exposure
coaddsInExposure The integer total number of coadds in the current exposure. Value should be constant during an exposure
coaddsDone Integer number of completed coadds from 1 to coaddsInExposure. Should be reset to 0 at the start of every exposure.
remainingExposureTime Number of seconds remaining in current exposure • Should count down in seconds – no faster than 1 Hz

Wavefront Detector Systems

There are many detector systems in the TMT Software System that are not part of the science data chain. This section considers standardized events for wave front sensors and guider detectors that will need to be visualized by ESW user interfaces. The events described are made as simple as needed to enable this functionality.

Subsystem teams or TMT Systems Engineering will need to  
determine if the subsystem wavefront detector images or guide  
camera detector images need to be visualized or manipulated by  
ESW user interfaces. 

This Observe Event design is integrated with the ESW.VIZ subsystem (RD02), which allows systems to publish images on named streams in order to minimize impact on WFS and Guider Detector Systems. Within VIZ subsystems providing images can POST their images to a Transfer Service on a named stream. Other notes subscribe to the stream and receive the images when they are published.

The following are assumptions regarding WFS and Guider images in the TMT Software System.

  • WFS and Guider images do not rely on header/metadata collection by DMS. WFS and Guider images will have headers, but the images from WFS and guiders are transient and are not persisted by DMS. A detector system creating a WFS or Guider image will create the header metadata itself or read values from the CSW Event Service.
  • World Coordinate System for WFS and Guider images is determined independent of ESW or OSW. This is assumed because ESW has no way of determining the WCS parameters for WFS or Guider images. It is necessary that these systems create the WCS data themselves.
  • WFS and Guider images are transient and are not written to or transferred to the DMS as with science and calibration images. There are no requirements to automatically save images of this type unless specifically requested.
  • Some WFS/Guider images may occasionally be saved for diagnostic purposes. The DMS will allow blob data to be stored and associated with specific key-words. But these images would be in the Engineering Database and will not be in the science archive. These images would be captured and stored through the action of a user.
  • WFS and Guider images are not associated with observer observations or proposals. Science images are associated with science programs and observations. This is not needed for WFS and Guider images and isn’t supported.

A subsystem publishing an image to a VIZ stream indicates success or failure.

Observe Event Description Probable Publisher
publishSuccess Indicates the WFS or guider detector system has successfully published an image to VBDS VBDS Transfer Service or possibly Detector Assembly
publishFailed Indicates that a WFS or guider detector system has failed while publishing an image to VBDS Detector Assembly or possibly VBDS Transfer

WFS and Guider Detector Exposure State Event

An exposure state Observe Event called wfsDetectorExposureState is provided as a state variable to indicate the current state of the wavefront sensor or guider detector system. The Exposure State Event groups parameters that change relatively slowly, and this event should be published whenever any of its parameters changes.

The Exposure State Event includes the following mandatory parameters, but a detector system may add their own as well.

Parameters Description
exposureId ExposureId is an identifier in ESW/DMS for a single exposure. The ExposureId follows the structure: 2020A-001-123-WFOS-IMG1-SCI0-0001 with an included ObsId or when no ObsId is present, in the standalone format: 20200706-190204-WFOS-IMG1-SCI0-0001 with a UTC time when the ExposureId is created.
exposureInProgress A Boolean indicating if detector system is acquiring an exposure • Delimited by exposureStart and exposureEnd. exposureInProgress should be false if abortInProgress is true (TBD)
abortInProgress Indicates that an abort has been requested and is underway
isAborted Indicates that an abort has occurred and is completed. abortInProgress should be false when isAborted is true. isAborted should be set to false with the next exposure
operationalState Enumeration indicating if the detector system is available and operational. READY, NOT_READY, BUSY, ERROR. READY indicates system can execute exposures. NOT_READY indicates system cannot execute exposures. BUSY indicates system is BUSY most likely acquiring data. ERROR indicates the detector system is in an error state. This could happen as a result of a command or a spontaneous failure. Corrective action is required.
errorMessage An optional parameter that can be included when the detector system is in the ERROR operationalState. This value should be cleared and removed from the state when the operationalState returns to READY

This event is standardized to allow ESW user interfaces to have minimal, uniform information about the state of any WFS or Guider Detector system.

WFS and Guider Detector Exposure Data Event

At this time there is no WFS and Guider Detector Exposure Event. Any specific telemetry for these detector systems is available in their API model files and will not at this time be standardized.

Sequencers

Moving up from the acquisition of science detector data, it is necessary to have events that indicate activities for each observation and the acquisition process. The overall execution of an observation’s science Sequence is under the control of the master sequencer of ESW.OCS. During the acquisition process there may be additional OCS Sequencers that control the overall acquisition process. Regardless, the OCS Sequencer publishes Observe Events.

There are quite a few Observe Events related to the acquisition process as defined in the workflows (RD07) by the three phases:

  • Preset – moving the telescope and subsystems to point to the sky coordinates of the observation and configurating all the other subsystems needed for the observation.
  • Guide Star Acquisition – locking the telescope to the sky, closing loops, and delivering the telescope to the predefined hotspot needed for the science observation.
  • Science Target Acquisition – any additional adjustments specific to a science observation needed after the previous phase.

The following table shows the events related to the overall observation and its acquisition

Observe Event Description Probable Publisher
observationStart Indicates the start of execution of actions related to an observation including acquisition and science data acquisition OCS Sequencer
presetStart Indicates the start of the preset phase of acquisition OCS Sequencer
presetEnd Indicates the end of the preset phase of acquisition OCS Sequencer
guidestarAcqStart Indicates the start of locking the telescope to the sky with guide and WFS targets OCS Sequencer
guidestarAcqEnd Indicates the end of locking the telescope to the sky with guide and WFS targets OCS Sequencer
scitargetAcqStart Indicates the start of acquisition phase where science target is peaked up as needed after guidestar locking OCS Sequencer
offsetStart Indicates indicates the start of a telescope offset or dither OCS Sequencer
offsetEnd Indicates indicates the end of a telescope offset or dither OCS Sequencer
scitargetAcqEnd Indicates the end of acquisition phase where science target is centered as needed after guidestar locking OCS Sequencer
observeStart Indicates the start of execution of actions related to an Observe command OCS Sequencer
EXPOSURE OBSERVE EVENTS DISCUSSED IN IR Science Detector Systems Observe Events/Wavefront Detector Systems OCCUR HERE
observeEnd Indicates the end of execution of actions related to an Observe command OCS Sequencer
observationEnd Indicates the end of execution of actions related to an observation including acquisition and science data acquisition. OCS Sequencer
observePaused Indicates that a user has paused the current observation Sequence which will happen after the current step concludes OCS Sequencer
observeResumed Indicates that a user has resumed a paused observation Sequence OCS Sequencer
downtimeStart Indicates that something has occurred that interrupts the normal observing workflow and time accounting. This event will have a hint (TBD) that indicates the cause of the downtime for statistics. Examples are: weather, equipment or other technical failure, etc. Downtime is ended by the start of an observation or exposure OCS Sequencer
inputRequestStart Indicates the start of a request to the user for input OCS Sequencer
inputRequestEnd Indicates the end of a request for user input OCS Sequencer

Downtime Considerations

The downtimeStart Observe Event is provided to allow the operator to indicate that there is a problem that is hindering the normal observing workflow. The event includes a category that the downtime will be associated with. Common examples are weather or equipment failure. The categories and usage will be worked out at a later time. Sometimes metrics and statistics subtract the time associated with weather loss or technical failures. It is challenging to assign downtime algorithmically. We anticipate that the telescope observing assistant will assign a category through a user interface program provided by ESW.HCMS. The downtime will be started by the downtimeStart event and ended by the next observationStart or exposureStart event.

How to create any observe event

The following snippet shows how to create a observe event

Scala
sourceval obsId                         = ObsId("1234A-001-0123")
val prefix                        = Prefix("tcs.pk")
val wfsObserveEvent: ObserveEvent = WFSDetectorEvent.publishSuccess(prefix)
val irObserveEvent: ObserveEvent  = IRDetectorEvent.observeStart(prefix, obsId)
val opdObserveEvent: ObserveEvent = OpticalDetectorEvent.observeStart(prefix, obsId)
Java
source//prefixes
Prefix prefix1 = Prefix.apply(JSubsystem.TCS, "pk");
EventName name1 = new EventName("targetCoords");
Prefix prefix2 = Prefix.apply(JSubsystem.TCS, "cm");
EventName name2 = new EventName("guiderCoords");

//Key
Key<Coords.SolarSystemCoord> planets = JKeyType.SolarSystemCoordKey().make("planets", JUnits.NoUnits);

//values
Coords.SolarSystemCoord planet1 = new Coords.SolarSystemCoord(new Coords.Tag("solar1"), JCoords.Jupiter());
Coords.SolarSystemCoord planet2 =  new Coords.SolarSystemCoord(new Coords.Tag("solar2"), JCoords.Venus());

//parameters
Parameter<Coords.SolarSystemCoord> param = planets.set(planet1, planet2);
//events

ObserveEvent observeEvent = IRDetectorEvent.observeStart(prefix1, ObsId.apply("1234A-123-124"));

JSON Serialization

Events can be serialized to JSON. The library has provided JsonSupport helper class and methods to serialize Status, Observe and System events.

Scala
sourceimport play.api.libs.json.{JsValue, Json}

// key
val k1: Key[MatrixData[Double]] = DoubleMatrixKey.make("myMatrix")

val name1  = EventName("correctionInfo")
val prefix = Prefix("aoesw.rpg")

// values
val m1: MatrixData[Double] = MatrixData.fromArrays(
  Array(1.0, 2.0, 3.0),
  Array(4.1, 5.1, 6.1),
  Array(7.2, 8.2, 9.2)
)
// parameter
val i1: Parameter[MatrixData[Double]] = k1.set(m1)
// events
val observeEvent: ObserveEvent = IRDetectorEvent.observeStart(prefix, ObsId("1232A-123-123")).madd(i1)
val systemEvent: SystemEvent   = SystemEvent(prefix, name1).add(i1)

// json support - write
val observeJson: JsValue = JsonSupport.writeEvent(observeEvent)
val systemJson: JsValue  = JsonSupport.writeEvent(systemEvent)

// optionally prettify
val str: String = Json.prettyPrint(systemJson)

// construct command from string
val systemEventFromPrettyStr: SystemEvent = JsonSupport.readEvent[SystemEvent](Json.parse(str))

// json support - read
val observeEvent1: ObserveEvent = JsonSupport.readEvent[ObserveEvent](observeJson)
val systemEvent1: SystemEvent   = JsonSupport.readEvent[SystemEvent](systemJson)
Java
source//key
Key<MatrixData<Double>> k1 = JKeyType.DoubleMatrixKey().make("myMatrix");

//prefixes
Prefix prefix1 = Prefix.apply(JSubsystem.AOESW, "rpg");
EventName name1 = new EventName("correctionInfo");

//values
Double[][] doubles = {{1.0, 2.0, 3.0}, {4.1, 5.1, 6.1}, {7.2, 8.2, 9.2}};
MatrixData<Double> m1 = MatrixData.fromArrays(doubles);

//parameter
Parameter<MatrixData<Double>> i1 = k1.set(m1);


//events
ObserveEvent observeEvent = IRDetectorEvent.observeStart(prefix1, ObsId.apply("1234A-123-124"));
SystemEvent systemEvent = new SystemEvent(prefix1, name1).add(i1);

//json support - write
JsValue observeJson = JavaJsonSupport.writeEvent(observeEvent);
JsValue systemJson = JavaJsonSupport.writeEvent(systemEvent);

//optionally prettify
String str = Json.prettyPrint(systemJson);

//construct DemandState from string
SystemEvent statusFromPrettyStr = JavaJsonSupport.readEvent(Json.parse(str));

//json support - read
ObserveEvent observeEvent1 = JavaJsonSupport.readEvent(observeJson);
SystemEvent systemEvent1 = JavaJsonSupport.readEvent(systemJson);

Unique Key Constraint

By choice, a ParameterSet in either ObserveEvent or SystemEvent event will be optimized to store only unique keys. When using add or madd methods on events to add new parameters, if the parameter being added has a key which is already present in the paramSet, the already stored parameter will be replaced by the given parameter.

Note

If the Set is created by component developers and given directly while creating an event, then it will be the responsibility of component developers to maintain uniqueness with parameters based on key.

Here are some examples that illustrate this point:

Scala
source// keys
val encoderKey: Key[Int] = KeyType.IntKey.make("encoder")
val filterKey: Key[Int]  = KeyType.IntKey.make("filter")
val miscKey: Key[Int]    = KeyType.IntKey.make("misc")

// prefix
val prefix = Prefix("wfos.blue.filter")

val name1 = EventName("filterWheel")

// params
val encParam1 = encoderKey.set(1)
val encParam2 = encoderKey.set(2)

val encParam3    = encoderKey.set(3)
val filterParam1 = filterKey.set(1)
val filterParam2 = filterKey.set(2)

val filterParam3 = filterKey.set(3)

val miscParam1 = miscKey.set(100)
// StatusEvent with duplicate key via constructor
val systemEvent =
  SystemEvent(prefix, name1, Set(encParam1, encParam2, encParam3, filterParam1, filterParam2, filterParam3))
// four duplicate keys are removed; now contains one Encoder and one Filter key
val uniqueKeys1 = systemEvent.paramSet.toList.map(_.keyName)

// try adding duplicate keys via add + madd
val changedStatusEvent = systemEvent
  .add(encParam3)
  .madd(
    filterParam1,
    filterParam2,
    filterParam3
  )
// duplicate keys will not be added. Should contain one Encoder and one Filter key
val uniqueKeys2 = changedStatusEvent.paramSet.toList.map(_.keyName)

// miscKey(unique) will be added; encoderKey(duplicate) will not be added
val finalStatusEvent = systemEvent.madd(Set(miscParam1, encParam1))
// now contains encoderKey, filterKey, miscKey
val uniqueKeys3 = finalStatusEvent.paramSet.toList.map(_.keyName)
Java
source//keys
Key<Integer> encoderKey = JKeyType.IntKey().make("encoder", JUnits.encoder);
Key<Integer> filterKey = JKeyType.IntKey().make("filter");
Key<Integer> miscKey = JKeyType.IntKey().make("misc");

//prefix
Prefix prefix1 = Prefix.apply(JSubsystem.WFOS, "blue.filter");
EventName name1 = new EventName("filterWheel");

//params
Parameter<Integer> encParam1 = encoderKey.set(1);
Parameter<Integer> encParam2 = encoderKey.set(2);
Parameter<Integer> encParam3 = encoderKey.set(3);

Parameter<Integer> filterParam1 = filterKey.set(1);
Parameter<Integer> filterParam2 = filterKey.set(2);
Parameter<Integer> filterParam3 = filterKey.set(3);

Parameter<Integer> miscParam1 = miscKey.set(100);

//StatusEvent with duplicate key via madd
SystemEvent event = new SystemEvent(prefix1, name1).madd(
        encParam1,
        encParam2,
        encParam3,
        filterParam1,
        filterParam2,
        filterParam3);
//four duplicate keys are removed; now contains one Encoder and one Filter key
Set<String> uniqueKeys1 = event.jParamSet().stream().map(Parameter::keyName).collect(Collectors.toUnmodifiableSet());

//try adding duplicate keys via add + madd
SystemEvent changedEvent = event.add(encParam3).madd(filterParam1, filterParam2, filterParam3);
//duplicate keys will not be added. Should contain one Encoder and one Filter key
Set<String> uniqueKeys2 = changedEvent.jParamSet().stream().map(Parameter::keyName).collect(Collectors.toUnmodifiableSet());

//miscKey(unique) will be added; encoderKey(duplicate) will not be added
SystemEvent finalEvent = changedEvent.madd(miscParam1, encParam1);
//now contains encoderKey, filterKey, miscKey
Set<String> uniqueKeys3 = finalEvent.jParamSet().stream().map(Parameter::keyName).collect(Collectors.toUnmodifiableSet());