Keys and Parameters

The library offers a flexible and typesafe means to create Parameters to store values like primitive types, collection types or domain specific types.

A Parameter is a Key and Value where the Value must be from a set of defined primitive types including binary data. The Value of a Parameter is always considered to be an Array of the type (i.e. if a single value is stored it is at array location 0). A Parameter is immutable; a modification to an existing Parameter will return a new instance.

A Value can also have Units, which must be of the defined types. See Units for more information. At this time Units are informational only–no calculation or conversion support is provided. Some systems may provide a key value with different units, and receiver can inspect the Units to make a decision on how to handle the value.

A ParameterSet is a Set of Parameter. Various other message types include a ParameterSet (e.g. Setup, Event). A key is unique in a ParameterSet since it is a Set.

How to Create a Parameter

  • choose an appropriate KeyType from the tables below for your language(Scala/Java).
  • calling the make method on KeyType and supplying a String keyName will return a suitably typed Key instance.
  • explore the overloaded set and -> methods, which will allow you to store values of the based on chosen KeyType. e.g. JKeyTypes.BooleanKey will allow storing only java.lang.Boolean values.

Primitive Datatypes

Primitive Scala KeyType Java KeyType
Boolean KeyType.BooleanKey JKeyTypes.BooleanKey
Character KeyType.CharKey JKeyTypes.JCharKey
Byte KeyType.ByteKey JKeyTypes.ByteKey
Short KeyType.ShortKey JKeyTypes.ShortKey
Long KeyType.LongKey JKeyTypes.LongKey
Int KeyType.IntKey JKeyTypes.IntKey
Float KeyType.FloatKey JKeyTypes.FloatKey
Double KeyType.DoubleKey JKeyTypes.DoubleKey
String KeyType.StringKey JKeyTypes.StringKey
Timestamp KeyType.TimestampKey JKeyTypes.TimestampKey
Scala
//declare keyname
val s1: String = "encoder"

//making 3 keys
val k1: Key[Boolean] = KeyType.BooleanKey.make(s1)
val k2: Key[Short]   = KeyType.ShortKey.make("RandomKeyName")
val k3: Key[String]  = KeyType.StringKey.make(s1)

//storing a single value
val booleanParam: Parameter[Boolean] = k1.set(true)

//storing multiple values
val paramWithShorts1: Parameter[Short] = k2.set(1, 2, 3, 4)
val paramWithShorts2: Parameter[Short] = k2 -> (1, 2, 3, 4)
val paramWithShorts3: Parameter[Short] = k2 -> Array[Short](1, 2, 3, 4)

//associating units
val weekDays: Array[String]            = Array("Sunday", "Monday", "Tuesday")
val paramWithUnits1: Parameter[String] = k3.set(weekDays, Units.day)
val paramWithUnits2: Parameter[String] = k3 -> weekDays withUnits Units.day

//deault unit is NoUnits
assert(booleanParam.units === Units.NoUnits)

//set units explicitly on an existing Parameter
val paramWithUnits3: Parameter[Short] = paramWithShorts1.withUnits(Units.meter)

//retrieve values from Parameter
val allValues: Array[Short] = paramWithShorts1.values

//retrieve just top value
val head: Short = paramWithShorts1.head
Java
//making 3 keys
String keyName = "encoder";
Key<Boolean> k1 = JKeyType.BooleanKey().make(keyName);
Key<Short> k2 = JKeyType.ShortKey().make(keyName);
Key<String> k3 = JKeyType.StringKey().make(keyName);

//storing a single value
Parameter<Boolean> booleanParam = k1.set(true);

//storing multiple values
Short[] shortArray = {1, 2, 3, 4};
Parameter<Short> paramWithManyShorts1 = k2.set(shortArray);
Parameter<Short> paramWithManyShorts2 = k2.set((short) 1, (short) 2, (short) 3, (short) 4);

//associating units
String[] weekDays = {"Sunday", "Monday", "Tuesday"};
Parameter<String> paramWithUnits1 = k3.set(weekDays, JUnits.day);
Parameter<String> paramWithUnits2 = k3.set(weekDays).withUnits(JUnits.day);

//deault unit is NoUnits
boolean hasDefaultUnit = booleanParam.units() == JUnits.NoUnits; //true

//set units explicitly on an existing Parameter
Parameter<Short> paramWithUnits3 = paramWithManyShorts1.withUnits(JUnits.meter);

//retrieve values from Parameter
Short[] allValues = (Short[]) paramWithManyShorts1.values();

//retrieve just top value
Short head = paramWithManyShorts1.head();

Arrays

Primitive Scala KeyType Java KeyType
ByteArray KeyType.ByteArrayKey JKeyTypes.ByteArrayKey
ShortArray KeyType.ShortArrayKey JKeyTypes.ShortArrayKey
LongArray KeyType.LongArrayKey JKeyTypes.LongArrayKey
IntArray KeyType.IntArrayKey JKeyTypes.IntArrayKey
FloatArray KeyType.FloatArrayKey JKeyTypes.FloatArrayKey
DoubleArray KeyType.DoubleArrayKey JKeyTypes.DoubleArrayKey
Scala
//make some arrays
val arr1: Array[Double] = Array(1.0, 2.0, 3.0, 4.0, 5.0)
val arr2: Array[Double] = Array(10.0, 20.0, 30.0, 40.0, 50.0)

//keys
val filterKey: Key[ArrayData[Double]] = KeyType.DoubleArrayKey.make("filter")

//Store some values using helper class ArrayData
val p1: Parameter[ArrayData[Double]] = filterKey.set(ArrayData(arr1), ArrayData(arr2))
val p2: Parameter[ArrayData[Double]] = filterKey -> ArrayData(arr1 ++ arr2) withUnits Units.liter

//add units to existing parameters
val p1AsCount = p1.withUnits(Units.count)

//default unit is NoUnits
assert(p1.units === Units.NoUnits)

//retrieving values
val head: Array[Double]                 = p1.head.data.toArray
val allValues: Array[ArrayData[Double]] = p1.values
Java
//make some arrays
Double[] arr1 = {1.0, 2.0, 3.0, 4.0, 5.0};
Double[] arr2 = {10.0, 20.0, 30.0, 40.0, 50.0};

//keys
Key<ArrayData<Double>> filterKey = JKeyType.DoubleArrayKey().make("filter");

//Store some values using helper method in ArrayData
Parameter<ArrayData<Double>> p1 = filterKey.set(ArrayData.fromJavaArray(arr1), ArrayData.fromJavaArray(arr2));
Parameter<ArrayData<Double>> p2 = filterKey.set(ArrayData.fromJavaArray(arr2)).withUnits(JUnits.liter);

//add units to existing parameters
Parameter<ArrayData<Double>> p1AsCount = p1.withUnits(JUnits.count);

//default unit is NoUnits
boolean bDefaultUnit = JUnits.NoUnits == p1.units();

//retrieving values
List<Double> head = p1.head().jValues();
List<ArrayData<Double>> listOfArrayData = p1.jValues();
Double[] arrayOfDoubles = (Double[]) p2.jValues().get(0).values();

Matrices

Primitive Scala KeyType Java KeyType
ByteMatrix KeyType.ByteMatrixKey JKeyTypes.ByteMatrixKey
ShortMatrix KeyType.ShortMatrixKey JKeyTypes.ShortMatrixKey
LongMatrix KeyType.LongMatrixKey JKeyTypes.LongMatrixKey
IntMatrix KeyType.IntMatrixKey JKeyTypes.IntMatrixKey
FloatMatrix KeyType.FloatMatrixKey JKeyTypes.FloatMatrixKey
DoubleMatrix KeyType.DoubleMatrixKey JKeyTypes.DoubleMatrixKey
Scala
//make some arrays
val m1: Array[Array[Byte]] = Array(Array[Byte](1, 2, 3), Array[Byte](4, 5, 6), Array[Byte](7, 8, 9))
val m2: Array[Array[Byte]] = Array(Array[Byte](1, 2, 3, 4, 5), Array[Byte](10, 20, 30, 40, 50))

//keys
val encoderKey: Key[MatrixData[Byte]] = KeyType.ByteMatrixKey.make("encoder")

//Store some values using helper class MatrixData
val p1: Parameter[MatrixData[Byte]] = encoderKey.set(MatrixData.fromArrays(m1))
val p2: Parameter[MatrixData[Byte]] = encoderKey.set(m1, m2) withUnits Units.liter

//add units to existing parameters
val p1AsLiter = p1.withUnits(Units.liter)

//default unit is NoUnits
assert(p1.units === Units.NoUnits)

//retrieving values
val head: Array[Array[Byte]]           = p1.head.data.map(_.toArray).toArray
val allValues: Array[MatrixData[Byte]] = p1.values
Java
//make some arrays
Byte[][] m1 = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
Byte[][] m2 = {{1, 2, 3, 4, 5}, {10, 20, 30, 40, 50}};

//keys
Key<MatrixData<Byte>> encoderKey = JKeyType.ByteMatrixKey().make("encoder");

//Store some values using helper method in ArrayData
Parameter<MatrixData<Byte>> p1 = encoderKey.set(
        MatrixData.fromJavaArrays(Byte.class, m1),
        MatrixData.fromJavaArrays(Byte.class, m2));
Parameter<MatrixData<Byte>> p2 = encoderKey.set(
        MatrixData.fromJavaArrays(Byte.class, m2)
).withUnits(JUnits.liter);

//add units to existing parameters
Parameter<MatrixData<Byte>> p1AsLiter = p1.withUnits(JUnits.liter);

//default unit is NoUnits
boolean bDefaultUnit = JUnits.NoUnits == p1.units();

//retrieving values
MatrixData<Byte> head = p1.head();
List<MatrixData<Byte>> matrixData1 = p1.jValues();
List<MatrixData<Byte>> matrixData2 = p2.jValues();

Domain Specific Types

Primitive Scala KeyType Java KeyType
Choice KeyType.ChoiceKey JKeyTypes.ChoiceKey
RaDec KeyType.RaDecKey JKeyTypes.RaDecKey
Struct KeyType.StructKey JKeyTypes.StructKey

Choice

A key for a choice item similar to an enumeration.

Scala
//Choice
val choices = Choices.from("A", "B", "C")

//keys
val choice1Key: GChoiceKey = ChoiceKey.make("mode", choices)
val choice2Key: GChoiceKey = ChoiceKey.make(
  "mode-reset",
  Choices.fromChoices(Choice("c"), Choice("b"), Choice("a"))
)

//store values
val p1: Parameter[Choice] = choice1Key
  .set(Array(Choice("A")))
  .withUnits(Units.foot)
val p2: Parameter[Choice] = choice2Key.set(Array(Choice("c")))

//add units
val paramWithFoot = p1.withUnits(Units.foot)

//default unit is NoUnits
assert(p2.units === Units.NoUnits)

//retrieving values
val head: Choice          = p1.head
val values: Array[Choice] = p2.values
Java
//Choice
final Choices choices = Choices.from("A", "B", "C");

//keys
GChoiceKey choice1Key = JKeyType.ChoiceKey().make("mode", choices);
GChoiceKey choice2Key = JKeyType.ChoiceKey().make(
        "mode-reset",
        Choices.fromChoices(
                new Choice("c"),
                new Choice("b"),
                new Choice("a")));

//store values
Parameter<Choice> p1 = choice1Key.set(new Choice("A")).withUnits(JUnits.foot);
Parameter<Choice> p2 = choice2Key.set(new Choice("c"));

//add units
Parameter<Choice> paramWithFoot = p1.withUnits(JUnits.foot);

//default unit is NoUnits
boolean bDefaultUnit = JUnits.NoUnits == p2.units();

//retrieving values
Choice head = p1.head();
List<Choice> values = p2.jValues();

RaDec

Holds Ra(Right Ascension) and Dec(Declination) values

Note

This version of the radec parameter is a placeholder for testing. A more complete version will be added once details of positions are better defined.

Scala
//RaDec
val raDec1: RaDec = RaDec(1.0, 2.0)
val raDec2: RaDec = RaDec(3.0, 4.0)

//keys
val raDecKey: Key[RaDec] = KeyType.RaDecKey.make("raDecKey")

//store values
val p1: Parameter[RaDec] = raDecKey.set(raDec1)
val p2: Parameter[RaDec] = raDecKey -> Array(raDec1, raDec2)

//add units
val paramWithDegree = p1.withUnits(Units.degree)

//default unit is NoUnits
assert(p2.units === Units.NoUnits)

//retrieving values
val head: RaDec          = p1.head
val values: Array[RaDec] = p2.values
Java
//RaDec
RaDec raDec1 = new RaDec(1.0, 2.0);
RaDec raDec2 = new RaDec(3.0, 4.0);

//keys
Key<RaDec> raDecKey = JKeyType.RaDecKey().make("raDecKey");

//store values
Parameter<RaDec> p1 = raDecKey.set(raDec1);
Parameter<RaDec> p2 = raDecKey.set(raDec1, raDec2).withUnits(JUnits.degree);

//add units
Parameter<RaDec> paramWithDegree = p1.withUnits(JUnits.degree);

//default unit is NoUnits
boolean bDefaultUnit = JUnits.NoUnits == p1.units();

//retrieving values
RaDec head = p1.head();
List<RaDec> values = p2.jValues();

Struct

Stores a set of Parameters for telescope and instrument control. Lot of utility functions available for store, add, remove, list Keys and Paramete

Scala
//keys
val skey: Key[Struct] = StructKey.make("myStruct")

val ra    = KeyType.StringKey.make("ra")
val dec   = KeyType.StringKey.make("dec")
val epoch = KeyType.DoubleKey.make("epoch")

//initialize struct
val struct1: Struct = Struct().madd(ra.set("12:13:14.1"), dec.set("32:33:34.4"), epoch.set(1950.0))
val struct2: Struct = Struct().madd(dec.set("32:33:34.4"), ra.set("12:13:14.1"), epoch.set(1970.0))

//make parameters
val p1: Parameter[Struct] = skey.set(struct1)
val p2: Parameter[Struct] = skey.set(struct1, struct2)

//add units
val paramWithLightYear = p1.withUnits(Units.lightyear)

//default unit is NoUnits
assert(p2.units === Units.NoUnits)

//retrieving values
val head: Struct          = p1.head
val values: Array[Struct] = p2.values

//get individual keys
val firstKey: Option[Parameter[String]]  = struct1.get(KeyType.StringKey.make("ra"))
val secondKey: Option[Parameter[String]] = struct1.get("dec", KeyType.StringKey)
val thirdKey: Option[Parameter[Double]]  = struct1.get("epoch", KeyType.DoubleKey)

//access parameter using 'parameter' or 'apply' method
assert(struct1.parameter(ra) === struct1(ra))

//remove a parameter and verify it doesn't exist
val mutated1: Struct = struct1.remove(ra) //using key
val mutated2         = struct1.remove(firstKey.get)
assert(mutated1.exists(ra) === false)
assert(mutated2.exists(ra) === false)

//find out missing keys
val missingKeySet: Set[String] = mutated1.missingKeys(ra, dec, epoch, KeyType.FloatKey.make("missingKey"))
assert(missingKeySet === Set("ra", "missingKey"))
Java
//keys
Key<Struct> skey = JKeyType.StructKey().make("myStruct");

Key<String> ra = JKeyType.StringKey().make("ra");
Key<String> dec = JKeyType.StringKey().make("dec");
Key<Double> epoch = JKeyType.DoubleKey().make("epoch");

//initialize struct
Struct struct1 = new Struct().madd(
        ra.set("12:13:14.1"),
        dec.set("32:33:34.4"),
        epoch.set(1950.0));
Struct struct2 = new Struct().madd(
        dec.set("32:33:34.4"),
        ra.set("12:13:14.1"),
        epoch.set(1970.0));

//make parameters
Parameter<Struct> p1 = skey.set(struct1);
Parameter<Struct> p2 = skey.set(struct1, struct2);

//add units
Parameter<Struct> paramWithLightYear = p1.withUnits(JUnits.lightyear);

//default unit is NoUnits
boolean bDefaultUnit = JUnits.NoUnits == p1.units();

//retrieving values
Struct head = p1.head();
List<Struct> structs = p2.jValues();

//get individual keys
Optional<Parameter<String>> firstKey = struct1.jGet(JKeyType.StringKey().make("ra"));
Optional<Parameter<String>> secondKey = struct1.jGet("dec", JKeyType.StringKey());
Optional<Parameter<Double>> thirdKey = struct1.jGet("epoch", JKeyType.DoubleKey());

//access parameter using 'parameter' and 'apply' method
boolean bSuccess = struct1.parameter(ra) == struct1.apply(ra);

//remove a parameter and verify it doesn't exist
Struct mutated1 = struct1.remove(ra); //using key
Struct mutated2 = struct1.remove(firstKey.get());

//find out missing keys
Set<String> missingKeySet = mutated1.jMissingKeys(ra, dec, epoch, JKeyType.StringKey().make("someRandomKey"));
List<String> expectedMissingKeys = Arrays.asList("ra", "someRandomKey");

Source Code for Examples