5.1  Class Object

5.1.1  Object properties

5.1.2  Object methods

+ (integer$)length(void)

Returns the size (e.g., length) of the receiving object.  This is equivalent to the length() (or size()) function; in other words, for any object x, the return value of the function call length(x) equals the return value of the class method call x.length().  This method is provided solely for syntactic convenience.  Note that +length() is a synonym for +size().

+ (void)methodSignature([Ns$ methodName = NULL])

Prints the method signature for the method specified by methodName, or for all methods supported by the receiving object if methodName is NULL (the default).

+ (void)propertySignature([Ns$ propertyName = NULL])

Prints the property signature for the property specified by propertyName, or for all properties supported by the receiving object if propertyName is NULL (the default).

+ (integer$)size(void)

Returns the size of the receiving object.  This is equivalent to the size() (or length()) function; in other words, for any object x, the return value of the function call size(x) equals the return value of the class method call x.size().  This method is provided solely for syntactic convenience.  Note that +length() is a synonym for +size().

– (void)str(void)

Prints the internal property structure of the receiving object; in particular, the element type of the object is printed, followed, on successive lines, by all of the properties supported by the object, their types, and a sample of their values.

5.2  Class DataFrame

(object<DataFrame>$)DataFrame(...)

The DataFrame constructor can be called in the same ways as the constructor for Dictionary (its superclass): with no parameters to make an empty DataFrame, with key-value pairs, with a singleton Dictionary (or a subclass of Dictionary, like DataFrame) to make a copy, or with a singleton string in JSON format.  See the Dictionary class for further documentation.

5.2.1  DataFrame properties

colNames => (string)

A vector containing all of the string column names in the DataFrame, in order.  This property is currently an alias for the Dictionary property allKeys.

dim => (integer)

A two-element vector containing the dimensions of the DataFrame.  The 0th element is the number of rows (as provided by nrow), and the 1st element is the number of columns (as provided by ncol).

ncol => (integer$)

The number of columns in the DataFrame; this will be equal to the length of colNames.

nrow => (integer$)

The number of rows in the DataFrame (i.e., the number of elements in a column).  This will be the same for every column, by definition.

5.2.2  DataFrame methods

– (void)cbind(object source, ...)

Adds all of the columns contained by source (which must be a Dictionary or a subclass of Dictionary such as DataFrame) to the receiver.  This method makes the target DataFrame wider, by adding new columns.  If source contains a column name that is already defined in the target, an error will result.  As always for DataFrame, the columns of the resulting DataFrame must all be the same length.

The source parameter may be a non-singleton vector containing multiple Dictionary objects, and additional Dictionary vectors may be supplied (thus the ellipsis in the signature).  Each Dictionary supplied will be added to the target, in the order supplied.

This method is similar to the Dictionary method addKeysAndValuesFrom(), which may be used instead if replacement of duplicate columns is desired.

– (void)rbind(object source, ...)

Appends all of the columns contained by source (which must be a Dictionary or a subclass of Dictionary such as DataFrame) to the receiver.  This method makes the DataFrame taller, by adding new rows.  If the source and target do not contain the same column names in the same order, an error will result.  As always for DataFrame, the columns of the resulting DataFrame must all be the same length.

The source parameter may be a non-singleton vector containing multiple Dictionary objects, and additional Dictionary vectors may be supplied (thus the ellipsis in the signature).  Each Dictionary supplied will be appended to the target, in the order supplied.

This method is similar to the Dictionary method appendKeysAndValuesFrom(), which may be used instead if one wishes the append to work even when the columns are in different orders, or other such situations.

– (*)subset(li rows, lis cols)

Returns the elements in the selected rows and columns of the target DataFrame.  The selection logic is identical to that for subsetRows() and subsetColumns(), respectively; in short, rows may be selected by integer indices or by a logical vector, and columns may be selected by integer indices, by a logical vector, or by a string vector of column names.

The first step performed by subset() is to produce a DataFrame that contains the selected rows and columns.  If that DataFrame contains more than one column, it is simply returned, and the behavior of subset() is identical to calling subsetRows() and subsetColumns() in sequence (in either order).  If, however, the resulting DataFrame contains only a single column, then subset() will return a vector containing the elements in that column – unlike the behavior of subsetRows() and subsetColumns(), which always return a DataFrame.  It is therefore a convenient way to get a single value, or multiple values from the same column, from a DataFrame.  (Note that the Dictionary method getValue() can also be used to get all of the values from a given DataFrame column.)

– (object<DataFrame>$)subsetColumns(lis index)

Returns a new DataFrame containing values for the selected columns of the target DataFrame.  The selection logic described below is similar to how the subset operator [] in Eidos works, selecting the columns of the target DataFrame.

The index parameter may be either integer, logical, or string; we will discuss the integer case first.  If index is a singleton integer, the returned DataFrame will contain the index’th column of the target (counting from the left, from 0).  If index is a non-singleton integer vector, the returned DataFrame will contains all of the selected columns, in the order that they are selected by index.  If any index value is out of range for the target DataFrame (such that the DataFrame does not have an index’th column), an error will result.  If the same column is specified more than once, unique column names will be automatically generated for the additional copies of the column.

If index is a string vector, the returned DataFrame will contain copies of the columns in the target named by index.  As with an integer vector, it is an error if a given column does not exist in the target; and unique column names will be generated for additional copies of a column.

Finally, if index is a logical vector, the length of index must be equal to the number of columns in the target.  In this case, the T values in index select the columns which will be included in the returned DataFrame.  The columns in the returned DataFrame will be in the same order as in the target.

– (object<DataFrame>$)subsetRows(li index, [logical$ drop = F])

Returns a new DataFrame containing values for selected rows of the target DataFrame.  The selection logic described below works exactly as the subset operator [] does in Eidos, selecting the rows of the target DataFrame.

The index parameter may be either integer or logical; we will discuss the integer case first.  If index is a singleton integer, the returned DataFrame will contain the index’th element of the value of each key of the target, under the same keys; this is a single row of the target DataFrame.  If index is a non-singleton integer vector, the returned DataFrame will contain the values for all of the selected rows, in the order that they are selected by index.  If any index value in index is out of range for the target DataFrame (such that that DataFrame does not have an index’th row), an error will result.

If index is logical, the length of index must be equal to the number of rows in the target.  In this case, the T values in index select the rows which will be included in the returned DataFrame.  The values of each column in the returned DataFrame will be in the same order as in the target.

If the values of index are such that no value for a given key is selected, the drop parameter controls the resulting behavior.  If drop is F (the default), the key will be included in the returned dictionary with a zero-length value of matching type, such as integer(0) or string(0).  If drop is T, the key will be omitted from the returned dictionary.

5.3  Class Dictionary

(object<Dictionary>$)Dictionary(...)

Creates a new Dictionary object.  Called without arguments, as Dictionary(), this creates a new empty Dictionary.

Alternatively, key-value pairs can be passed to set up the initial state of the new Dictionary.  These are set, sequentially, on the new Dictionary, just as setValue() would do.  For example, calling Dictionary("a", 0:3, "b", c("foo", "bar")) is equivalent to calling Dictionary() and then calling setValue("a", 0:3) and then setValue("b", c("foo", "bar")) on it; it is just a shorthand for convenience.

Another alternative is to call Dictionary() with a singleton Dictionary as its only argument; this creates a new Dictionary that is a copy of the Dictionary passed, containing the same keys and values.  This is equivalent to creating a new empty Dictionary and then calling addKeysAndValuesFrom() to copy key-value pairs over; it is just a shorthand for convenience.

A final alternative is to call Dictionary() with a singleton string as its only argument; this creates a new Dictionary from the string, assuming that it is a data archive in JSON format.  Note that a JSON string can be generated from the serialize() method of Dictionary; together with this way of creating a Dictionary, this provides the ability to persist arbitrary information to a string (perhaps a file on disk) and back again.  The recreated Dictionary should be identical to the original, except that zero length vectors such as integer(0), float(0), logical(0), and string(0) will all be serialized as "[]" and recreated as integer(0) since JSON does not provide a way to specify the type of a zero-length array.

5.3.1  Dictionary properties

allKeys => (string)

A vector containing all of the string keys that have been assigned values using setValue(), in sorted (alphabetical) order.

5.3.2  Dictionary methods

– (void)addKeysAndValuesFrom(object$ source)

Adds all of the key-value pairs contained by source (which must be a Dictionary or a subclass of Dictionary) to the receiver.  If the target already contains a key that is defined in source, the target’s value for that key will be replaced by the value in source (contrast this with appendKeysAndValuesFrom()).

– (void)appendKeysAndValuesFrom(object source)

Appends all of the key-value pairs contained by source (which must be a Dictionary or a subclass of Dictionary) to the receiver.  If the target already contains a key that is defined in source, the value from source will be appended to the target’s existing value, which must be of the same type (contrast this with addKeysAndValuesFrom()); if the target does not already contain a key that is defined in source, that key-value pair will simply be added to the target.

In the current implementation, it is an error for either of the values involved in an append to be a matrix or array; values in these Dictionary objects should be simple vectors.  This limitation preserves the future option to expand this method’s functionality to do smart things with matrices and arrays.

– (void)clearKeysAndValues(void)

Removes all key-value pairs from the receiver.

– (object<Dictionary>$)getRowValues(li index, [logical$ drop = F])

Returns a new Dictionary containing values for selected “rows” of the target Dictionary, allowing Dictionary to act similarly to a DataFrame.  See the subsetRows() method of class DataFrame for comparison; the main utility of getRowValues() is that it can be used on a Dictionary that has ragged “rows”.  The selection logic described below works similarly to the subset operator [] in Eidos, selecting the “rows” of the target Dictionary.

The index parameter may be either integer or logical; we will discuss the integer case first.  If index is a singleton integer, the returned Dictionary will contain the index’th element of the value of each key of the target, under the same keys; this is a single “row” of the target Dictionary.  If index is a non-singleton integer vector, the returned Dictionary will contain the values for all of the selected rows, in the order that they are selected by index.  If any index value in index is out of range for any key of the target Dictionary (such that that key does not have an index’th value), the returned dictionary will simply not have a value for that “row” of that key.

If index is logical, the T values in index select the “rows” which will be included in the returned Dictionary.  The values within each column in the returned Dictionary will be in the same order as in the target.  The length of index need not match any column of the Dictionary; excess “rows” beyond the length of index will not be selected, and excess values in index beyond the end of the longest “column” will have no effect.

If the values of index are such that no value for a given key is selected, the drop parameter controls the resulting behavior.  If drop is F (the default), the key will be included in the returned dictionary with a zero-length value of matching type, such as integer(0) or string(0).  If drop is T, the key will be omitted from the returned dictionary.

– (*)getValue(string$ key)

Returns the value previously set for the dictionary entry identifier key using setValue(), or NULL if no value has been set.

– (logical$)identicalContents(object$ x)

Returns T if the target Dictionary is equal to x in all respects – containing the same keys, with values that are identical in the sense defined by the identical() function in Eidos – or returns F otherwise.

Note that if Dictionary objects are contained, as values, by the dictionaries being tested for equality, they will be compared according to the standards of identical(), and must therefore actually be the same Dictionary object, shared by both dictionaries, for isEqual() to return T.

– (string)serialize([string$ format = "slim"])

Returns a serialized form of the dictionary’s contents as a string singleton or vector.  Four formats are supported at present, as chosen with the format parameter: "slim" and “json" produce a singleton string, whereas "csv" and "tsv" produce a string vector.  These serializations can be written to disk with writeFile() or writeTempFile(), written to the output stream with cat(), or used in any other way.

The default "slim" format is intended for simple, informal use where a very easily parseable string is desired.  For a simple dictionary containing only keys with singleton non-object values, this will be a semicolon-delimited string like "key1=value1;key2=value2;".  Values of type string will be quoted, and will be escaped with backslash escape sequences, including \\, \", \', \t, \r, and \n.  Values that are not singleton will be separated by spaces, such as "key1=1 2 3;", while values that are themselves dictionaries will be delimited by braces, such as "key1={key1=value1;key2=value2;};".  Keys, since they are also of type string, will be quoted and backslash-escaped if necessary, but simple keys that do not require that treatment will be serialized without quotes for simplicity.  No facility for parsing "slim" serializations back into Eidos is presently provided.

The "json" format, introduced in Eidos 2.7 (SLiM 3.7), provides serialization of the Dictionary into the standard JSON format, which may not be quite as brief or human-readable, but which can be used as a standard interchange format and read by the Dictionary() constructor in Eidos as well as by many other programs.  For example, a Dictionary with a key "key1" with integer value 1:3 and key "key2" with string value "value2" would produce the JSON serialization '{"key1":[1,2,3],"key2":["value2"]}', where the outer single quotes are not part of the serialization itself, but are indicating that the serialization is a string value.  Note that since all Eidos values are vectors, even singleton values are serialized into JSON as arrays by Eidos; the hope is that this will make automated parsing of these JSON strings easier, since the singleton case will not have to be special-cased.  For example, Dictionary("a", 1, "b", Dictionary("x", 2)) would be serialized into JSON as '{"a":[1],"b":[{"x":[2]}]}'.  Documentation on the JSON format can be found online.

The "csv" and "tsv" formats produce standard comma-separated value (CSV) or tab-separated value (TSV) data.  These formats are primarily intended for output from DataFrame, since that class is used to represent the sort of data tables that CSV/TSV are typically used for; but it may be used with Dictionary too, particularly if it is being used to represent a data table with ragged columns (missing values will just be skipped over, producing two commas or two tabs in sequence).  Values of type string will always be quoted, with double quotes (with a repeated double quote used to indicate the presence of a double quote inside a string value, as usual in CSV); values of other types never will.  Decimal points (not decimal commas, regardless of system localization) will always be used for float values, and will never be used for integer values.  Values of logical type will be serialized as TRUE or FALSE, without quotes.  A header line providing the names of the columns (i.e., the keys of the target Dictionary) will always be generated; those column names will also be quoted.  One string element will be generated for each row of the target, plus one string element for the header line; newlines will not be present in the resulting string vector unless newlines were present within the string values in the Dictionary.  The resulting data, if written to a file, should be readable in Eidos using readCSV() (as long as there are no ragged columns or missing values), as well as in other software such as R and Excel.

– (void)setValue(string$ key, * value)

Sets a value for the dictionary entry identifier key.  The value, which may be of any type, can be fetched later using getValue().  If value is of type object, the object class must internally be under retain-release memory management; among SLiM’s Eidos classes, only Chromosome, Mutation, and Substitution presently are (see the Eidos manual’s documentation for defineConstant() for further discussion).  Setting a key to a value of NULL removes that key from the dictionary.

5.4  Class Image

(object<Image>$)Image(...)

Creates a new Image object.  This can be called in a few different ways.

Passed a singleton string, as Image(string$ filePath), it creates a new Image from the PNG file at filePath.  If the file represents a grayscale image, an 8-bit grayscale (K) Image will be created; all other PNG files will yield a 24-bit color (RGB) Image.

Passed an integer or float vector, as Image(numeric matrix), it creates a new grayscale Image from the values in matrix, which must be a matrix as its name suggests.  If matrix is integer, its values must be in [0, 255], and will be used directly as 8-bit pixel values without translation; if matrix is float, its values must be in [0.0, 1.0], and will be translated into 8-bit pixel values.  The dimensions of the image, in pixels, will be equal to the dimensions of the matrix.  The orientation of the image will match that of the matrix, in the sense that the image will appear as the matrix does when printed in the Eidos console; internally this requires a transposition of values, as discussed further below.  For the integer case, the integerK property of the resulting image will recover the original matrix exactly; for the float case, the floatK property will only approximately recover the original matrix since the translation into 8-bit pixel values involves quantization, but values of 0.0 and 1.0 will be recovered exactly.

5.4.1  Image properties

width => (integer$)

The width of the image, in pixels.

height => (integer$)

The height of the image, in pixels.

isGrayscale => (logical$)

This flag is T if the image is grayscale, with only a K channel; it is F if the image is color, with R/G/B channels.

bitsPerChannel => (integer$)

The number of bits used to represent a single pixel, in one channel of the image.  At present this is always 8; grayscale (K) images are 8-bit, color (RGB) images are 24-bit.  It could be extended to support 16-bit channels in future.

integerR => (integer)

The red (R) channel of the image, represented as a 2D integer matrix.  Values will be in [0,255].  See the floatR property for an alternative representation.  If the image is grayscale, this property is unavailable.

integerG => (integer)

The green (G) channel of the image, represented as a 2D integer matrix.  Values will be in [0,255].  See the floatG property for an alternative representation.  If the image is grayscale, this property is unavailable.

integerB => (integer)

The blue (R) channel of the image, represented as a 2D integer matrix.  Values will be in [0,255].  See the floatB property for an alternative representation.  If the image is grayscale, this property is unavailable.

integerK => (integer)

The gray (K) channel of the image, represented as a 2D integer matrix.  Values will be in [0,255].  See the floatK property for an alternative representation.  If the image is color, this property is unavailable.

floatR => (float)

The red (R) channel of the image, represented as a 2D float matrix.  Values will be in [0,1], obtained by dividing the integerR layer by 255.  See the integerR property for an alternative representation.  If the image is grayscale, this property is unavailable.

floatG => (float)

The green (G) channel of the image, represented as a 2D float matrix.  Values will be in [0,1], obtained by dividing the integerG layer by 255.  See the integerG property for an alternative representation.  If the image is grayscale, this property is unavailable.

floatB => (float)

The blue (B) channel of the image, represented as a 2D float matrix.  Values will be in [0,1], obtained by dividing the integerB layer by 255.  See the integerB property for an alternative representation.  If the image is grayscale, this property is unavailable.

floatK => (float)

The gray (K) channel of the image, represented as a 2D float matrix.  Values will be in [0,1], obtained by dividing the integerK layer by 255.  See the integerK property for an alternative representation.  If the image is color, this property is unavailable.

5.4.2  Image methods

– (void)write(string$ filePath)

Writes the image to the given filesystem path filePath as PNG data.  It is suggested, but not required, that filePath should end in a .png or .PNG filename extension.  If the file cannot be written, an error will result.  At present, since bitsPerChannel is always 8, grayscale data will be written as an 8-bit grayscale PNG while color (RGB) data will be written as a 24-bit color PNG without alpha.