The Statistics Collector is a table that records data from the model. The Statistics Collector listens to events in the model and writes data in its table cells when those events occur. You can configure which events the Statistics Collector listens to, as well as the data that it writes with those events. You can use the table data in a chart, or you can export the data from FlexSim.
The Statistics Collector can be accessed from the Toolbox. A model can have any number of Statistics Collectors.
The Statistics Collector is a table, similar to a Global Table; it is a table that is accessible in the toolbox, and you can write custom values in that table. However, Global Tables are generally used to store input data, or data that the model uses to determine its behavior. Statistics Collectors, on the other hand, record data about the model's behavior as it runs. You can think of Global Tables as input tables and Statistics Collectors as output tables.
The Statistics Collector is an observer of the model. When you use a Statistics Collector, you specify what events you want to observe, and what to record when those events happen. Then, as the model runs, the Statistics Collector will listen for the specified events to happen, and update the table when those events occur.
The following subsections describe the basic logic of the Statistics Collector. The last subsection (Visualizing the Statistics Collector as a Flowchart) shows two flowcharts. One shows the logic that executes if an observed event fires. The other shows the logic that executes if the table is accessed. It may be helpful to read these subsections, view the flowcharts, and then read these subsections again.
In order to add rows to the table, you must specify events to listen to. For example, the following Statistics Collector listens to two events:
Whenever an event in this list occurs, the Statistics Collector
creates an entity called data
. This entity
has information about the event such as which object
fired the event, and the name of the event. You can also
assign labels to this entity. In the previous example,
the event parameters item and port
are assigned to data
as label values.
Each event also specifies a row value.
The Statistics Collector maps each row value to a row.
If there is not yet a row for the given row value, then the
Statistics Collector will add a row for that value.
In the previous example, the event uses
data.item
as the row value. This means that
whenever an item enters the Queue, the Statistics Collector
will make sure there is a row in the table for that item.
In addition, the row value given by the event is assigned
to the data
entity's rowValue
property.
In summary, when and event occurs, it produces a row value. If the Statistics Collector doesn't have a row for that row value, it will add a row to its table. The new row is then tied to the row value. In this example, the row value is a flowitem. However, the row value can be any Variant value. More information can be found in the Row Values section.
In order to add columns to the table, you specify them directly in the Statistics Collector, using the Columns tab. For example, the following Statistics Collector would have two columns:
When you add a column, you need to specify a name. You also need to specify what value to write in the column when the column is updated. The Row Add Value specifies the value that the column should write when a new row is added. When an event produces a row value that doesn't have a row, the Statistics Collector will make a new row, and fill all columns with their Row Add Value.
In this example, the Row Add Value for the Type column is set to
data.rowValue.Type
. Recall that in this example,
data.rowValue
is a flowitem. So when the row
is added, the Type column will record the value of the Type
label on the flowitem for that row.
You can update values in the table in three ways. The first way is by defining a Row Add Value. This allows you to write a value when the Statistics Collector adds a row, as discussed in the previous section.
The second way is by connecting an event to one or more columns. When the event occurs, the Statistics Collector will assert a row for the event's row value. Then, the Statistics Collector will visit each of the connected columns on that row, and write the value specified in the Event Value field. In the following example, the "Processor1 - On Exit" event is connected to the Staytime column:
In this example, when the "Processor1 - On Exit" event occurs, the
Statistics Collector will assert a row for the row value, writing
the Row Add Value for each
column if a row is added. Then, on that same row,
the Statistics Collector will write the
Event Value for each connected column.
In this example, the event is connected to the Staytime column,
which is set to data.Staytime
.
The third way you can update a column is by changing the Update Timing of the column. There are two options for the Update timing:
By default, when the Statistics Collector adds a new row, the row will be added at the end of the table. However, you can specify a custom sort order. To do this, you can add one or more Sort Values:
The previous example demonstrates that you can access the row value during the sort step. However, there are some important rules about Sort Values:
When an event occurs, you can optionally specify that the event should finish the row for its row value, after the event has added or updated that row. If an event finishes a row, then two things happen to that row:
Because the Statistics Collector runs logic in response to events, it can be helpful to see that logic as a flowchart. The following flowchart is made with Process Flow activities, where each type of activity has as specific meaning:
data
entity as a token moving through the flowchart.
If one of the Statistics Collector's events occurs, this flow approximates the logic:
If something accesses the Statistics Collector's table, this flow approximates the logic:
This section describes the different kinds of row values that can be returned from an event's Row Values property, and how they might be used in a Statistics Collector.
The most common kind of row values are number values, text values, or node values. The Statistics Collector will make one row per unique text, number, or node value.
If an event's Row Values
field returns an array, the Statistics Collector
will extract every element of that array as an
individual row value.
In this way, you can have a single event add and/or
update multiple rows. For example,
[1, 2, 3]
will assert one row
for the values 1, 2, and 3.
However, and array of a single
value will only update one row;
1 == [1]
for row values.
In some cases, it can take several values to describe a row value. For example, you may want to create a table that has one row per Fixed Resource per SKU (a label on items flowing through the Fixed Resource). In this case, the row value is a composite value of Fixed Resource and SKU.
You can accomplish this using an array. However, since the Statistics Collector uses an array to mean multiple row values, you must put the array inside an array. For example, if an event returns a row value like this:
[[current, data.item.SKU]]
then the Statistics Collector will take each element of the outer
array as a row value. This leaves the inner array as the row value.
The Statistics Collector will make one row per unique array,
where every element of the array must match.
You can access elements of that array in later fields with
array syntax: data.rowValue[1]
You can return a null value as the row value from an event. This will always add a new row to the Statistics Collector, and that row will always be finished after the event.
To understand enumerated values, you need to first
recall how the Statistics Collector uses the
data
entity. Whenever one of the events
in the Statistics Collector occurs, the
data
entity is created. In addition,
the Statistics Collector sets the following properties
on the data
entity:
data.group
- If a single event listens
to all objects in a group, this property
will be set to that group. Otherwise, it is empty.data.eventNode
- This value
is set to the node that fired the event. This value
is also known as current
.data.processFlowInstance
- If an event
is listening to an activity in an instanced flow,
this property is set to the instance caused the event.
This property is also known as instance
.
All events set these three properties. You can return the following from any event as the row value:
data.enumerate()
This method returns a special value. When the Statistics Collector sees this special value as the row value, it asserts one row per unique combination of
[data.group, current, instance]
It also sets
data.rowValue
to current
.
There is a difference between using current
as the row value and using data.enumerate()
.
While both cases set data.rowValue
to be the same value in the end, rows made with
data.enumerate()
also remember the
instance and group used to make the row.
This difference is important when using columns that
update when accessed and need the instance
value.
For example, suppose you want to see the average content of
a Delay activity in an instanced flow for each instance.
When you access the table, there is no event, and so
normal rows cannot access current
,
instance
, or data.group
.
However, since enumerated rows remember these values,
you can use them in code like the following:
getstat(data.rowValue, "Content", STAT_CURRENT, instance)
For information on events, see the Event Listening page.
The Statistics Collector has the following events:
This event fires when a new row is added to the Statistics Collector, after the row is sorted, and after the Row Add Values have been set.
It has the following parameters:
Event Parameter | Type | Explanation |
---|---|---|
Row Number | int | The row number of the new row |
Row Value | Variant | The value associated with the new row |
This event fires when one of the events that the Statistics Collector listens to updates one or more columns on a given row.
It has the following parameters:
Event Parameter | Type | Explanation |
---|---|---|
Row Number | int | The row number of the new row |
Row Value | Variant | The value associated with the new row |
Columns Updated | Array | An array containing one value per column. If the nth column was updated, then the nth value of the array will be 1. Otherwise, the value will be zero. |
Previous Values | Array | An array containing one value per column. If the nth column was updated, then the nth value of the array will contain the value that was in the table before the update. Otherwise, the value is undefined, and should not be used. |
This event fires when an event finishes a row. Any columns updated by the event will be updated before this event fires.
It has the following parameters:
Event Parameter | Type | Explanation |
---|---|---|
Row Number | int | The row number of the finished row |
Row Value | Variant | The value associated with the finished row |
This event fires when the Statistics Collector needs to add
a new row, but has not actually added the row yet. The trigger
associated with this event is often used to initialize
row labels on the data
entity.
This event has no parameters.
This event fires when the Statistics Collector is about
to update any columns connected to an event. The trigger
associated with this event is often used to update
row labels on the data
entity.
It has the following parameters:
Event Parameter | Type | Explanation |
---|---|---|
Event Added Row | int | If the event that is currently causing an update also added the row, this value is true. |
Event Finishes Row | int | If the event that is currently causing an update will also finish the row, this value is true. |
The Statistics Collector has three tabs with various properties. The properties in these tabs will be explained in more detail in next sections.
The Events Tab has the following properties:
On the left of the Events Tab is the
Event List. You can use
the Add button
or Sampler button
to add events to this list.
You can use the
Duplicate button
to dupliate the selected event.
You can use the Remove
button
to remove the selected event.
You can use the Up
and Down
buttons
to reorder the events in the list.
Every event allows you to specify the following properties:
data
entity as part of this event.
The the following subsections describe the different kinds of events that you can listen to or create with the Statistics Collector, and the properties of each kind of event.
The example below shows an example of this kind of event:
The Statistics Collector can listen to the events of any 3D Object or Process Flow Activity. For example, you could listen to the On Entry of a Processor, or the On Content Change of a Queue. If you listen to a Process Flow Activity in an instanced flow, the Statistics Collector will listen to that activity for all instances attached to the flow.
When you listen to one of these kinds of events,
you will have the option of assigning the event
Parameters
as labels on the data
entity.
This kind of event also has a Condition property. After the Parameters are assigned, the Statistics Collector will evaluate the Condition. If the condition value is false, then the event will not proceed any further in the process, and will not update the table.
This kind of event also allows you to specify
Additional Labels
on the data
entity. These labels
are assigned after the Condition is evaluated.
The example below shows an example of this kind of event:
If you need to listen to many objects of the same type, you can listen to a Group of objects. The Statistics Collector will listen to all objects in the group.
As with Standard Events, this object allows you to assign event Parameters, define a Condition, and specify Additional Labels.
The example below shows an example of this kind of event:
If you listen to a Tracked Variable, or if you listen to an object event with the word "Change" in it, then you are listening to a Tracked Variable event.
When you listen to a Tracked Variable Event, you can specify a Change Rule. The Change Rule is like a Condition; if the change that happened doesn't match the Change Rule, then the event won't update the table.
Depending on which Change Rule you use, you may also need to specify a Change Value. This is a value related to the Change Rule. If the Change Rule has the word "Value" in its name, then the Change Value is is used.
In addition to the Change Rule, you can specify an addition Condition, as well as Additional Parameters.
The example below shows an example of this kind of event:
The Statistics Collector can create a Timer event and listen to that, rather than listening to events in the model. There are two main ways to use a timer event. The first way is to create a timer event that does not repeat, and fires when the model begins. This kind of timer event usually creates all the rows the table is expected to have. The second way to use a timer event is with a repeating schedule. This allows you to update or gather data at regular intervals.
To use a Timer event, you first specify the First Time value. This is a duration in model units. The timer will not begin firing until this time. You can also choose to fire this event when the model is reset, by returning a value that is less than 0.
Next, you can specify whether the timer event is Repeating. If it is repeating, you will also need to specify the Repeat Interval. This is a duration in model units. The timer will repeat every Repeat Interval after the First Time.
You can optionally define a custom Tick Pattern. Most users do not need this option. You can use the tick pattern to fire the timer event multiple times. You can do this by returning an array of values from the Tick Pattern property. For each value in the array, the Statistics Collector will execute the timer event that many model units since the First Time or since the last Repeat Interval occurred.
This event also allows you to assign
Additional Labels to the
data
entity.
The example below shows an example of this kind of event:
The Enumerate Event, like the Timer Event, is an event that the Statistics Collector creates for itself, rather than listening to some other object in the model. This kind of event fires when the model is reset.
To use this event, you can specify a list of
Objects
. These objects can
be 3D Objects, Groups, Process Flow Activities,
TrackedVariables, or any other treenode value.
This event also allows you to
assign Additional Labels
to the data
entity.
This event does not allow you to specify your own
Row Values.
Instead, the Enumerate event creates row values
for all objects in the
Objects list.
If the object is a Group, then the Statistics Collector
will make a row value for each object in the group.
If the object is an Activity in an instanced Process Flow,
the Statistics Collector will make one row value for
each instance of the activity. All row values are
created using the
data.enumerate()
method. For more information,
see the
Enumerated Values section.
The example below shows an example of this kind of event:
This kind of event is almost identical to a Standard Event, but instead of specifying a specific object or group to listen to, you can specify a Requirement. When the Statistics Collector is creating its listeners, it will search through the entire model. It will pass each object into the Requirement property, and listen to those objects that return a true value. In this particular example, the Statistics Collector is listening to the OnExit of all Processor objects.
The Event Sampler next to the Event property allows you to sample an object like the objects you expect the requirement to find.
As with Standard Events, this object allows you to assign event Parameters, define a Condition, and specify Additional Labels.
The example below shows an example of this kind of event:
Most events allow you to listen to something that is present when the model is reset. Transient events allow you to listen to objects that are created later, as part of the model run. For example, you might want to listen to TrackedVariable label changes on a token. Or you might want to listen to a flowitem's OnEntering event, which fires whenever the flowitem moves to new objects. Neither of these objects exist when the model is reset.
It can be helpful to contrast Transient Events with the other kinds of events. When all other kinds of event fire, they expose a Row Value. When this kind of event fires, it exposes a Transient object. In the previous example, the Transient object is a flowitem.
To use a Transient event, you also need to configure the event you want to listen to on the Transient object. You can use the Edit transient object event... button to open a popup, like the one shown here:
This popup allows you to edit the Event, Parameters and Condition of the event for the Transient object. You must use the Event Sampler to sample an event from an object like the transient object you expect to listen to.
Transient events are more complicated than other event types because they really listen to two events: the event where the Transient object is identified, and the event fired later by the Transient object. Here are some tips about how Transient events work:
data
entity, those label values will be
available when the Transient object event fires later.
The Columns Tab allows you to add columns to the Statistics Collector. The Columns Tab has the following properties:
The Column list allows you to add, duplicate, remove,
and reorder columns, using the
,
,
,
and
buttons. You can select a column in the list to
edit the properties of that column.
The Name property sets the name of the column, as it will appear in the table. Each name should be unique.
The Row Add Value property specifies the value to write when a row is added to the table.
The Event Value property specifies the value to write when an event connected to this column occurs. If no events are connected to this column, you don't need to specify this value.
The Value property is only available if the column is set to update when the value is accessed.
If you add a Column Set, rather than a single column,
then you can specify the Set Values
property. This property should return an Array of name/value
pairs. For each name/value pair, the Statistics Collector
will add a column with that name. In addition, the value
will be available through data.colValue
.
For example, if you have a group of Queue objects, you could make one column per Queue with the following code:
/**Custom Code*/
StatisticsCollector collector = ownerobject(c);
Array queues = Group("Queues").toFlatArray();
Array result;
for (int i = 1; i <= queues.length; i++) {
result.push([queues[i].name, queues[i]]);
}
return result;
Note that the name of each column is set to the name of the queue,
and that the value of each column is the queue. This
means that
data.colValue
will be the Queue corresponding to the column.
The Update Timing option allows you to set whether the column is updated by events or by accessing the table. This option is described in the Updating Values section.
The Storage Type of a column determines what type of value can be recorded in that column, and how much memory that value will require. The following list describes each option:
If a column stores a number value (not a text value), then you can specify a Display Format. The display format you choose depends on the kinds of value stored in the column. There are four possible options:
%
symbol.Use this box to specify the index type of the value. If you specify an option other than None, then an index will be added to the column, or to all columns of the Column Set. An index can greatly improve query performance. For more information, see the SQL Queries topic.
You can use this area to connect events to columns. This area shows the list of all events. You can select an event in the list to connect columns to it.
There are two ways to connect an event to a column. The first way is By direct links. If you choose this option, you can check the box next to each column you want this event to update. This is the most common way to connect events and columns.
The second way to connect events and columns is
By column requirement.
To use this way, you specify a code callback.
This callback is called for each column in the Statistics Collector.
The data
entity is available, with the following
properties set:
data.colNum
data.colName
data.colValue
The Row Options tab has the following properties:
The Row Sorting area allows you to specify a list of Sort Values. As rows are added to the Statistics Collector, they will be sorted by the first Sort Value, then by the second Sort Value, and so on. For each Sort Value, you can specify whether the value is ordered Ascending (A-Z) or Descending (Z-A).
If you are not sorting rows, you can optionally choose to reuse finished rows. This means that when the Statistics Collector adds a row, it will first check if there is a finished row. If so, the row value will be assigned to that row instead of to a new row.
This option is generally only used where another Statistics Collector will listen to this Statistics Collector. By reusing the rows, this intermediate collector can minimize memory usage.
This property applies when a row is finished. When this box is cleared, the Statistics Collector will forget the row value and destroy and labels associated with that row. If this box is checked, however, the Statistics Collector will simply disconnect the row value and the labels from the current row, rather than discarding them.
The On Warmup property specifies the actions the Statistics Collector will take at the model's Warmup Time. There are five possible options:
The Triggers tab allows you to specify logic for each of the Statistics Collector's Triggers. This tab is identical to the Triggers tab of other objects in FlexSim. For more information, see the Triggers Tab topic.
The Labels tab allows you to add labels to the Statistics Collector object. It is identical to the Labels tab of other FlexSim objects. For more information, see the Labels Tab topic.
The General tab has the following properties:
This property specifies a condition for all events. This property is evaluated immediately when an event occurs. If the condition returns a 0, or any other false value, then the event won't update the table.
This property only applies if one or more of the events for this Statistics Collector involve Process Flow Activities in Task Executor or Fixed Resource process flows. By default, this option specifies that the Statistics Collector should listen to all instances of that activity. In order to listen to fewer instances, you can use the sampler to set this value to a single object, or to a Group of objects. The Statistics Collector will only listen to the instance objects specified by this property. The remove button will reset this property to the default of All Instances.
This property applies to columns that use the Object format. The Object format displays a path to each object, and this property controls the maximum number of names that can appear in that path. If this property is 0, then the full path will be shown. If it is 1, then only the name of the object will be shown. If this property is 2, then the parent's name and the object's name will be shown as a partial path. As the value increases, the path will include nodes higher in the tree.
If this box is checked, then this Statistics Collector will store its table data on the hard drive, in an internal file. Memory (RAM) use for the data table will be limited to 5 MB.
Click this button to open a view of the data table for this Statistics Collector.
Click this button to open a table-based view. The table in this view shows the row value for each row of the Statistics Collector. If the row was enumerated, then this table will also show the group and instance associated with the row. Active rows show
You can use this button to save a CSV file of this Statistics Collector's data table.
This list shows all the dashboard charts that are drawing data from this Statistics Collector. If no charts require this collector, the list will be empty.
Click this button to open the Properties window of the selected chart in the Connected Dashboard Charts list.