3.3.2. pci.api.gobs module

The gobs (short for geospatial objects) module contains various objects that represent different types of geospatial data. These objects include rasters, bitmap masks, control points, look-up tables, metadata and more.

3.3.2.1. Data Types

class pci.api.gobs.DataType((object)self, (uint_)bits_per_pixel[, (bool)is_signed=True[, (bool)is_float=False[, (bool)is_complex=False]]])None

Bases: Boost.Python.instance

T

property bits_per_pixel

Number of bits per pixel

property is_complex

True for complex data, False otherwise

property is_float

True for floating point data, False otherwise

property is_signed

True for signed data, False otherwise

property name

DataType name

Instead of creating your own DataType object, you can use one of the following objects. These objects represent all of the DataType supported objects supported for .pix files by the pci.api.datasource.Dataset class:

pci.api.gobs.DT_8U

8-bit unsigned integer

pci.api.gobs.DT_8S

8-bit signed integer (not supported in PIX files)

pci.api.gobs.DT_16U

16-bit unsigned integer

pci.api.gobs.DT_16S

16-bit signed integer

pci.api.gobs.DT_32U

32-bit unsigned integer

pci.api.gobs.DT_32S

32-bit signed integer

pci.api.gobs.DT_32R

32-bit floating point

pci.api.gobs.DT_64U

64-bit unsigned integer

pci.api.gobs.DT_64S

32-bit signed integer

pci.api.gobs.DT_64R

64-bit floating point

pci.api.gobs.DT_C16S

16-bit complex signed integer

pci.api.gobs.DT_C32S

32-bit complex signed integer

pci.api.gobs.DT_C32R

32-bit complex floating point

pci.api.gobs.DT_C64R

64-bit complex floating point

Additional data types may be supported by other file formats.

3.3.2.2. Raster

class pci.api.gobs.RasterInfo((object)self, (uint_)width, (uint_)height, (uint_)chans_count, (DataType)datatype)None

Bases: Boost.Python.instance

This class represents the size and type of a raster. Create by specifying dimensions width by height, with chans_count channels of type datatype.

__init__( (object)self, (IRasterReader)reader) -> None

property chans_count

number of channels in the raster

property datatype

DataType of the raster.

property height

raster height

property width

raster width

class pci.api.gobs.RasterContext((object)self, (uint_)x_offset, (uint_)y_offset, (uint_)x_margin, (uint_)y_margin)None

Bases: Boost.Python.instance

This class represents information about the margin and position of a raster. Create by specifying the offset of the upper left corner as x_offset by y_offset and the margin size as x_margin by y_margin.

property x_margin

X margin size

property x_offset

X offset of the upper left corner

property y_margin

Y margin size

property y_offset

Y offset of the upper left corner

class pci.api.gobs.Raster((object)self, (RasterInfo)info, (RasterContext)context)None

Bases: pci.api.gobs.RasterInfo, pci.api.gobs.RasterContext

This class represents a raster. Create by specifying info and context. The raster data can be accessed using the data member variable.

For more information and best practices for accessing raster data see.

property chans_count

number of channels in the raster

property data

A numpy.ndarray containing the raster data. The raster data array is of dimensions (width+2*x_margin, height+2*y_margin, chans_count) The first element, i.e. data[0, 0, 0] , corresponds to the first element of the raster data buffer. In other words, if the Raster contains margins, then first element will correspond to the pixel at (-x_margin, -y_margin, 0) of the raster.

Similarly, the top left (non-margin) pixel, at (0, 0, 0), can be accessed at data[x_margin, y_margin, 0]

1
2
3
4
5
6
7
8
r = pci.api.gobs.Raster(info, context)
margin_from_data = r.data[0, 0, 0]
margin_from_get_pixel = r.get_pixel(-r.x_margin, -r.y_margin, 0)
assert margin_from_data == margin_from_get_pixel

tl_from_data = r.data[r.x_margin, r.y_margin, 0]
tl_from_get_pixel = r.get_pixel(0, 0, 0)
assert tl_from_data == tl_from_get_pixel
property datatype

DataType of the raster.

get_pixel((Raster)self, (int_)x, (int_)y, (uint_)chan) → object :

Get the pixel specified by x, y, chan. The returned pixel type will correspond to the datatype of the Raster.

Note

This function may be slow, it is preferred to use Raster.data directly.

property height

raster height

set_pixel((Raster)self, (int_)x, (int_)y, (uint_)chan, (object)value) → None :

Set the pixel specified by x, y, chan to value.

Note

This function may be slow, it is preferred to use Raster.data directly.

property width

raster width

property x_margin

X margin size

property x_offset

X offset of the upper left corner

property y_margin

Y margin size

property y_offset

Y offset of the upper left corner

3.3.2.2.1. Arrays and raster data

The Raster class allows the raster data to be viewed as a numpy.ndarray using Raster.data.

The pixels in this array are stored as band interleaved by pixel (BIP). This is similar to a 2-D array of pixels packed in column-major order. For more information about BIP, see the corresponding topic in the technical reference.

The following example demonstrates how the data is packed in the array. In this example, a raster with two columns, four rows, and three channels is created, and each pixel is populated with a value that indicates its column, row, and channel. For example, the value 123 represents the pixel at the first column, the second row, and the third channel (using a 1-based index). The array is then flattened (converted to a 1-D array), which shows exactly the sequence of how these values are stored in memory.

Finally, the strides attirbute indicates the number of bytes to step get to the next value for each dimension. That is, in the example below, to get from pixel (0,0,0) to pixel (1,0,0), you must go forward 6 bytes in memory. To get from pixel (0,0,0) to pixel (0,1,0), you must go forward 12 bytes. To get from pixel (0,0,0) to pixel (0,0,1), you must go forward 2 bytes.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
>>> from pci.api import gobs
>>>
>>> info = gobs.RasterInfo(2,4,3, gobs.DT_32R)
>>> context = gobs.RasterContext(0,0,0,0)
>>> r = gobs.Raster(info, context)
>>> d = r.data
>>>
>>> for col in range(2):
...    for row in range(4):
...      for chan in range(3):
...           d[col,row,chan] = 100*(col+1) + 10*(row+1) + (chan+1)
...
>>>
>>> d          # the pixel for values all three channels for (row, col):
array([[[111, 112, 113],                  # at (0,0)
        [121, 122, 123],                  # at (1,0)
        [131, 132, 133],                  # at (2,0)
        [141, 142, 143]],                 # at (3,0)

       [[211, 212, 213],                  # at (0,1)
        [221, 222, 223],                  # at (1,1)
        [231, 232, 233],                  # at (2,1)
        [241, 242, 243]]], dtype=int16)   # at (3,1)
>>>
>>> print(d[0])  # print the first column
[[111 112 113]
 [121 122 123]
 [131 132 133]
 [141 142 143]]
>>>
>>> print(d[1])  # print the second column
[[211 212 213]
 [221 222 223]
 [231 232 233]
 [241 242 243]]
>>>
>>> d.flatten()
array([111, 112, 113, 121, 122, 123, 131, 132, 133, 141, 142, 143, 211,
       212, 213, 221, 222, 223, 231, 232, 233, 241, 242, 243], dtype=int16)
>>>
>>> d.strides
(6L, 12L, 2L)

You can also use a numpy.ndarray to create a Raster. If your array is packed as BIP, like the Raster.data array, you can directly use this data as a Raster by using the array_to_raster() function. However, if your array is not packed as BIP, you must make a copy of the data using the copy_array_to_raster() function to create an Raster. You can check if your array is BIP using the is_bip().

The following example show how to create an array that will be BIP, and, therefore, able to share its data with a Raster:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
>>> import numpy
>>> from pci.api import gobs
>>>
>>> datatype = numpy.uint16
>>> width = 640
>>> height = 480
>>> chans = 3
>>> shape = (width, height, chans)
>>> itemsize = numpy.dtype(datatype).itemsize
>>> strides = (chans*itemsize, chans*itemsize*width, itemsize)
>>> arr = numpy.ndarray(shape=shape, dtype=datatype, strides=strides)
>>>
>>> print(gobs.is_bip(arr))
True
pci.api.gobs.is_bip((object)array) → bool :

Return True if the data array is packed as Band Interleaved Pixel (or BIP), and can therefore be used directly to create a Raster without copying (using array_to_raster()). Return False if the data is not packed as BIP, and therefore must be copied to create an array (using copy_array_to_raster()), or if a Raster cannot be created from array.

pci.api.gobs.array_to_raster((object)array[, (RasterContext)context=<RasterContext offset=(0, 0) margins=(0, 0)>]) → Raster :

Create an Raster using the data in array, context specifies the RasterContext for the resulting raster. The resulting raster directly uses the data in array so any changes to the raster or the array will show up in both, because they both use the same underlying data.

pci.api.gobs.copy_array_to_raster((object)array[, (RasterContext)context=<RasterContext offset=(0, 0) margins=(0, 0)>]) → Raster :

Create an Raster using a copy of the data in array, context specifies the RasterContext for the resulting raster. The resulting raster uses a copy of the data in array so any changes to the raster or the array will not affect each other, because they use different copies of the underlying data.

3.3.2.3. Mask

This section includes objects for creating and using bitmap masks. The Mask class represents a bitmap mask, which can be built by using an IMaskBuilder implementation. The CoordinateMaskBuilder builds a mask based on a series of coordinates, and the DecisionMaskBuilder class builds a mask based on an IMaskDecision implementation. Classes that implement the IMaskDecision interface analyze raster data and determine which pixels are valid.

class pci.api.gobs.Mask((object)self, (RasterInfo)info, (RasterContext)context)None

Bases: pci.api.gobs.RasterInfo, pci.api.gobs.RasterContext

A class provides repesenting a bitmap mask. An object of this type cannot be created directly from python. To create a Mask, you must create it using a IMaskBuilder.

property chans_count

number of channels in the raster

property datatype

DataType of the raster.

get_raster((Mask)self) → Raster :

Rasterize the mask and return it as a Raster with data of type DT_8U.

property height

raster height

property is_all_invalid

True if the whole mask is invalid, False otherwise.

is_valid((Mask)self, (int_)col, (int_)row) → bool :

check if the specified pixel is valid

set_value((Mask)self, (int_)x, (int_)y, (bool)value) → None :

Set the value of the mask pixel at x, y.

property width

raster width

property x_margin

X margin size

property x_offset

X offset of the upper left corner

property y_margin

Y margin size

property y_offset

Y offset of the upper left corner

class pci.api.gobs.BkgdRule

Bases: Boost.Python.enum

Rule for checking if a pixel is background value.

For ALL_CHAN, check if all channels are invalid, for ANY_CHAN, check if any channels is invalid.

class pci.api.gobs.IMaskDecision

Bases: Boost.Python.instance

Abstract class representing a method of evaluating if a pixel is valid. IMaskDecision is used by DecisionMaskBuilder to build a Mask.

class pci.api.gobs.MaskDecision((object)self, (RasterInfo)info, (float)background_val)None

Bases: pci.api.gobs.IMaskDecision

Class that evaluates a pixel to be invalid if any channel equals background_val. Create by specifying the info for the Raster being evaluated.

class pci.api.gobs.BkgdMaskerSingleVal((object)self, (float)value, (BkgdRule)rule)None

Bases: pci.api.gobs.MaskDecision

IMaskDecision implementation to find background pixels in an image by comparing each channel with a provided background value. Construct by specifying the background value as value, and the BkgdRule as rule when evaluating the data.

set_raster_info((BkgdMaskerSingleVal)self, (RasterInfo)info) → None :

Specify The info for the Raster being evaluated.

class pci.api.gobs.BkgdMaskerSingleStack((object)self, (VecDouble)values, (BkgdRule)rule)None

Bases: pci.api.gobs.MaskDecision

IMaskDecision implementation to find background pixels in an image by comparing each channel with its corresponding entry in a provided list of background values. Construct by specifying the list of background values as values, with one entry per channel, and the BkgdRule as rule used when evaluating the data.

set_raster_info((BkgdMaskerSingleStack)self, (RasterInfo)info) → None :

Specify The info for the Raster being evaluated.

class pci.api.gobs.BkgdMaskerSingleSubset((object)self, (VecDouble)values, (VecUInt)indexes, (BkgdRule)rule)None

Bases: pci.api.gobs.MaskDecision

IMaskDecision implementation to find background pixels in an image by comparing each of a subset of channels with its corresponding entry in a provided list of background valuesConstruct by specifying the lists of background values as values and indexes, with one value per channel index, and the BkgdRule as rule used when evaluating the data.

__init__( (object)arg1, (object)values, (BkgdRule)rule) -> None

set_raster_info((BkgdMaskerSingleSubset)self, (RasterInfo)info) → None :

Specify The info for the Raster being evaluated.

class pci.api.gobs.IMaskBuilder

Bases: Boost.Python.instance

This class provides an interface to create a Mask for a specified Raster.

build_mask((IMaskBuilder)self, (Raster)raster) → Mask :

Build a mask for the given raster.

class pci.api.gobs.DecisionMaskBuilder((object)arg1, (IMaskDecision)mask_decision)None

Bases: pci.api.gobs.IMaskBuilder

This class creates a Mask based on an IMaskDecision, specified by mask_decision.

build_mask((IMaskBuilder)self, (Raster)raster) → Mask :

Build a mask for the given raster.

class pci.api.gobs.CoordinateMaskBuilder((object)arg1)None

Bases: pci.api.gobs.IMaskBuilder

This class creates a Mask based on a specified list of valid coordinates.

add_valid_coordinate((CoordinateMaskBuilder)self, (int_)row, (int_)col) → None :

Add a valid coordinate at row, col to use when building the Mask.

build_mask((IMaskBuilder)self, (Raster)raster) → Mask :

Build a mask for the given raster.

3.3.2.4. Control points

class pci.api.gobs.ControlPointType

Bases: Boost.Python.enum

Specifies the type of ControlPoint. CHECK specifies checkpoint, CONTROL specifies GCPs, and TIE specifies tiepoints.

CHECK = pci.api.gobs.ControlPointType.CHECK
CONTROL = pci.api.gobs.ControlPointType.CONTROL
TIE = pci.api.gobs.ControlPointType.TIE
class pci.api.gobs.GroundLocation((object)self)None

Bases: Boost.Python.instance

Specifies the location on ground where a control point is located. Ground locations are expressed in the coordinate system of the ControlPointContainer in which they are contained.

get_coord((GroundLocation)self, (uint_)axis) → float :

Get the ground coordinate specified by axis. The 3 axes x, y and z correspond to axis 0, 1 and 2 respectively.

get_coords((GroundLocation)self) → tuple :

Get a 3-element tuple of the ground coordinates of the ground location. The 3 elements represent x, y and z respectively.

get_covariance((GroundLocation)self, (uint_)col, (uint_)row) → float :

Get the covariance matrix coefficient, at index col, row. Note: These are in squared units.

get_stddev((GroundLocation)self, (uint_)index) → float :

Get the standard deviation (square root of variance) at index from the covariance matrix.

set_coord((GroundLocation)self, (uint_)axis, (float)coord) → None :

Set the coordinate value, coord for the specified axis, where the x, y and z axes are represented by 0, 1, and 2 respectively.

set_coords((GroundLocation)self, (float)x, (float)y, (float)z) → None :

Set the x, y and z coordinates of the ground location.

set_covariance((GroundLocation)self, (uint_)col, (uint_)row, (float)cov) → None :

Set the covariance matrix coefficient, cov, at index col, row. Note: These are in squared units.

set_stddev((GroundLocation)self, (uint_)index, (float)stddev) → None :

Set the standard deviation, stddev at index. The standard deviation is converted (squared) to variance and stored in the covariance matrix.

property x

The x coordinate of the ground location.

property y

The y coordinate of the ground location.

property z

The z coordinate of the ground location.

class pci.api.gobs.ImageLocation((object)self)None

Bases: Boost.Python.instance

Specifies the location in an image where a control point is located. Image locations are expressed in the raster coordinates.

property col

The column coordinate of the image location.

get_coord((ImageLocation)self, (uint_)axis) → float :

Get the image coordinate specified by axis. The 2 axes are col and row respectively.

get_coords((ImageLocation)self) → tuple :

Get a 2-element tuple of the image coordinates of the image location. The 2 elements represent col and row respectively.

get_covariance((ImageLocation)self, (uint_)col, (uint_)row) → float :

Get the covariance matrix coefficient, at index col, row. Note: These are in squared units.

get_stddev((ImageLocation)self, (uint_)index) → float :

Get the standard deviation (square root of variance) at index from the covariance matrix.

property row

The row coordinate of the image location.

set_coord((ImageLocation)self, (uint_)axis, (float)coord) → None :

Set the coordinate value, coord for the specified axis, where the col and row axes are represented by 0 and 1 respectively.

set_coords((ImageLocation)self, (float)col, (float)row) → None :

Set the col and row coordinates of the image location.

set_covariance((ImageLocation)self, (uint_)col, (uint_)row, (float)cov) → None :

Set the covariance matrix coefficient, cov, at index col, row. Note: These are in squared units.

set_stddev((ImageLocation)self, (uint_)index, (float)stddev) → None :

Set the standard deviation, stddev at index. The standard deviation is converted (squared) to variance and stored in the covariance matrix.

class pci.api.gobs.ControlPoint((object)self, (uint_)id)None

Bases: Boost.Python.instance

This class aggregates all information about a given control point.

property ground_location

The ground location for the control point.

property id

The ID of the control point.

property image_locations

A list of image locations for the control point.

property is_active

True if this point is active, False otherwise.

property name

The name of the control point.

property type

The ControlPointType of the control point.

class pci.api.gobs.ControlPointContainer((object)self)None

Bases: Boost.Python.instance

A container that holds control points metadata about the points.

property crs

The coordinate system of all control points

property points

The list of control points held by this container.

3.3.2.5. Metadata

class pci.api.gobs.MetadataMap((object)self)None

Bases: Boost.Python.instance

A string-string map for holding metadata. MetadataMap can be indexed like a python dict. You can iterate over a MetadataMap in a for loop. Unlike a dict, iterating over a MetadataMap iterates over pairs, not just the keys.

For example, the following code …

1
2
3
4
5
6
7
8
import pci.api.gobs
mmap = pci.api.gobs.MetadataMap()
mmap['one'] = 'first'
mmap['two'] = 'second'
mmap['three'] = 'third'

for entry in m:
    print(entry)

… will produce the following result

(one, first)
(three, third)
(two, second)

Note that, like a dict, the order of iteration cannot be guaranteed.

class pci.api.gobs.HistoryEvent

Bases: Boost.Python.instance

This class is a record of an event in the history of a data element.

property action_type

The type of history action.

property details

The details of history action.

property end_time

A datetime.datetime of the end time of the event.

property id

The integer ID of the event

property start_time

A datetime.datetime of the start time of the event.

3.3.2.6. Lookup table (LUT)

class pci.api.gobs.LUT((object)self, (LUTEntryVec)entries)None

Bases: Boost.Python.instance

This class represents a look-up table. Create by specifying a list of LUT entries.

New in version 2016.

property entries

all LUT entries

property entry_count

The number of entries

get_value((LUT)self, (float)input_value) → float :

Get the output value for the specified input_value. If input_value doesn’t correspond to an input value in the table, the returned value will be determined by linear interpolation.

get_value_by_index((LUT)self, (int)index) → float :

Get the output value for the specified entry.

property input_value_range

min/max input values

class pci.api.gobs.LUTEntry((object)self, (float)input, (float)output)None

Bases: Boost.Python.instance

A tuple representing the input and corresponding output values in a LUT. Create by specifying input and output values.

New in version 2016.

property input

The float input value

property output

The float output value corresponding to input

pci.api.gobs.is_classic_lut((LUT)lut) → bool :

Return True if lut can be written as is (without having to interpolate values) to a classic LUT segment, False otherwise.

3.3.2.7. Pseudocolor table (PCT)

class pci.api.gobs.PCT((object)self, (PCTEntryVec)entries)None

Bases: Boost.Python.instance

This class represents a pseudo-colour table. Create by specifying a list of PCT entries.

New in version 2016.

property entries

all PCT entries

property entry_count

The number of entries

get_value((PCT)self, (float)input_value) → RGB8 :

Get the output value for the specified input_value. If input_value doesn’t correspond to an input value in the table, the returned value will be determined by linear interpolation.

get_value_by_index((PCT)self, (int)index) → RGB8 :

Get the output value for the specified entry.

property input_value_range

min/max input values

class pci.api.gobs.PCTEntry((object)self, (float)input, (RGB8)output)None

Bases: Boost.Python.instance

A tuple representing the input and corresponding output values in a PCT. Create by specifying input and output values.

New in version 2016.

property input

The float input value

property output

The RGB8 output value corresponding to input

class pci.api.gobs.RGB8((object)self, (int)r, (int)g, (int)b)None

Bases: Boost.Python.instance

This class represents an RGB tuple of unsigned 8-bit value. Create by specifying r, g, and b values.

New in version 2016.

r

Red

g

Green

b

Blue

pci.api.gobs.is_classic_pct((PCT)pct) → bool :

Return True if pct can be written as is (without having to interpolate values) to a classic PCT segment, False otherwise.

3.3.2.8. Vectors

New in version 2018.

class pci.api.gobs.Shape((object)arg1, (object)vertices)object

Bases: Boost.Python.instance

This class to represents a shape from a vector segment. Create by specifying the vertices of the shape.

  • a single point (a point is a 3 entry sequence of doubles)

  • a 2D Array of points

  • a sequence of points

  • a sequence of sequence of points

  • a sequence 2D arrays

  • an empty list

New in version 2018.

property area

The area of the shape if it is a polygon. If not a polygon, the area is 0. The area of holes is subtracted from the total area. The z component of the shape is ignored when computing area

property extents

A VecDouble of the x and y extents of this Shape. The entries in this are [min_x, min_y, max_x, max_y]

property length

Get the combined 2D length of all rings of a shape (for polygons, this is the perimeter). The length of holes is added to the total length. The z component of the shape is ignored when computing length.

property orientation

The PolygonOrientation of this shape

reorient((Shape)self, (PolygonOrientation)orientation) → bool :

Reorganize the vertices in this Shape so that it is oriented as orientation. If this Shape is not a polygon, no reorientation is performed. If, after processing, the Shape is a Polygon oriented as orientation, True is returned, False otherwise.

property vertices

A tuple of numpy.ndarray representing the vertices in the Shape. Each entry in this tuple represents a ring of this shape. The ndarray is an array of triplets representing the x, y and z of each vertex. If the Shape has no vertices, then the tuple will be empty.

pci.api.gobs.ring_orientation((object)vertices) → PolygonOrientation :

Get the orientation of the ring specified by vertices. This parameter must be a numpy array like one of the rings obtained from Shape.vertices.

class pci.api.gobs.ShapeContainer((object)arg1)None

Bases: Boost.Python.instance

A sequence of Shape, this class behaves similar to a list but it can only contain Shape.

class pci.api.gobs.FieldType

Bases: Boost.Python.enum

Specifies the data type of a Field.

  • eFieldTypeNone - The value of the Field is None.

  • eFieldTypeFloat - The type of the Field is a single-precision float.

  • eFieldTypeDouble - The type of the Field is a double-precision float.

  • eFieldTypeString - The type of the Field is a string.

  • eFieldTypeInteger - The type of the Field is a 32 bit integer.

  • eFieldTypeCountedInt - The type of the Field is a list of 32 bit integers.

New in version 2018.

class pci.api.gobs.Field((object)arg1, (object)value)object

Bases: Boost.Python.instance

This class encapsulates any of the supported vector attribute field types. The object has a field type and a value of this specified type. Construct by specifying value, which can be any of the supported types.

New in version 2018.

property type

The FieldType of this Field.

property value

The value of this field. The value will be of the type specified by Field.type.

class pci.api.gobs.Record((object)arg1)None

Bases: Boost.Python.instance

A sequence of Field, this class behaves similar to a list but it can only contain Field.

New in version 2018.

class pci.api.gobs.FieldDefinition((object)arg1, (string_)name, (string_)desc[, (string_)format=''[, (FieldType)field_type=pci.api.gobs.FieldType.eFieldTypeNone[, (Field)default=<gobs.Field value=None>[, (Field)no_data=<gobs.Field value=None>]]]])None

Bases: Boost.Python.instance

Class to hold name, description, type, format, default value and no data value for a Field

New in version 2018.

property default

The default value of the Field

property desc

The description of the Field

property format

The Field format as a format string suitable for use the str % operator.

property name

The name of the Field

property no_data

The no data value of the Field

property type

The data type of the Field

class pci.api.gobs.RecordDefinition((object)arg1)None

Bases: Boost.Python.instance

A sequence of FieldDefinition, this class behaves similar to a list but it can only contain FieldDefinition.

New in version 2018.