API structure#
This topic explores the foundational structure of PySTK, providing you with an understanding of its organization and key components. It covers topics such as the use of packages and namespaces, the available data types, common coding patterns, how exceptions are handled, and the event-driven mechanisms that enable interactions. Understanding these elements can help you navigate PySTK effectively.
Packages and namespaces#
Packages and namespaces are fundamental to the organization and structure of PySTK. Packages contain groups of modules, while namespaces manage and avoid name conflicts by defining the scope of variables, functions, and classes.
Data types#
Data types form the building blocks for handling and processing information
with PySTK. This section describes the more complex data types used with PySTK
beyond the basic Python data types such as float
, int
,
str
, and bool
.
Type hints#
Most argument and return types are specified using type hints with Python’s
typing
library. In the case that more than one type is possible
(such as an argument that may be a str
or a float
),
typing.Any
is used as the type hint. In those situations, consulting
the documentation for that method is advised. Type hints that are STK
interfaces may represent objects that are subclasses of that interface.
Enumerations#
Enumerations enable you to define a set of named constant values. Enumeration
classes are located in the STK Object Model modules (for
example—stkobjects
). Most inherit from Python’s
enum.IntEnum
class while a few inherit from enum.IntFlag
and may
be combined using the bitwise OR operator to select multiple options from within the
enumeration.
from ansys.stk.core.graphics import CylinderFillOptions
# CylinderFillOptions inherits from enum.IntFlag and may be combined
# using the `|` operator
cyl_fill = CylinderFillOptions.BOTTOM_CAP | CylinderFillOptions.TOP_CAP
Arrays#
Arrays are used to store and manipulate collections of items in Python. Many
PySTK methods return arrays or take them as input. In PySTK, array values are
represented using the list
class.
from ansys.stk.core.stkutil import ExecuteMultipleCommandsMode
connect_cmds = ["GetStkVersion /", "New / Scenario ExampleScenario"]
results = root.execute_multiple_commands(connect_cmds, ExecuteMultipleCommandsMode.CONTINUE_ON_ERROR)
first_message = results.item(0)
also_first_message = results[0]
for message in results:
print(message.count)
STK interfaces and classes#
The STK object model is comprised of programming interfaces that are
implemented by Python classes located in the provided modules. With few
exceptions, classes returned from PySTK methods inherit from one or more
interfaces. You may immediately access any method from the inherited
interfaces without casting, although in some situations casting may improve
IDE auto-complete feature results. These classes have a reference to an STK
object; this reference is removed upon calling del()
on the Python class.
Because these classes are references to STK objects, you cannot
create them directly from Python; objects must be returned from PySTK methods.
# STKObjectRoot root: STK Object Model Root
from ansys.stk.core.utilities.exceptions import STKRuntimeError
from ansys.stk.core.stkobjects import Facility, STKObjectType
try:
# this facility is not a valid STK reference
my_facility_attempt = Facility()
my_facility_attempt.height_above_ground = 123.4
except STKRuntimeError as e:
print(e)
# this facility represents a valid STK object
facility = Facility(root.current_scenario.children.new(STKObjectType.FACILITY, "facility1"))
facility.height_above_ground = 123.4
Collections#
Collections enable you to store, organize, and manipulate groups of related
items. Many PySTK interfaces represent collections of items; such interfaces
have the word “Collection” as part of their name. These classes have an
item()
method that may be used to get an indexed item from the collection,
but they also support Python indexing and iteration.
from ansys.stk.core.stkutil import ExecuteMultipleCommandsMode
connect_cmds = ["GetStkVersion /", "New / Scenario ExampleScenario"]
results = root.execute_multiple_commands(connect_cmds, ExecuteMultipleCommandsMode.CONTINUE_ON_ERROR)
first_message = results.item(0)
also_first_message = results[0]
for message in results:
print(message.count)
Multiple return values#
Some methods in PYSTK return multiple values rather than returning one list. The multiple values are returned as a tuple.
# Facility facility: Facility Object
(x, y, z) = facility.position.query_cartesian()
Colors#
The colors
module contains the Color
,
ColorRGBA
, and Colors
classes used by PySTK.
Class name |
Description |
---|---|
|
Represents an opaque color constructed from RGB values in the range |
|
Represents a variably translucent, 4-channel color constructed from RGBA values in the range |
|
Contains an assortment of named colors as well as factory methods to create |
from ansys.stk.core.stkobjects import STKObjectType
from ansys.stk.core.utilities.colors import Color, Colors
facility = root.current_scenario.children.new(STKObjectType.FACILITY, "facility1")
facility.graphics.color = Colors.Blue
facility.graphics.color = Color.from_rgb(127, 255, 212)
(r, g, b) = facility.graphics.color.get_rgb()
Certain methods require a list of 4-channel RGBA color values for defining
per-vertex colors on a geometry. Such a list should be constructed in Python
as a list of Color
and/or ColorRGBA
objects. Color
objects always have
alpha=255
(fully opaque), whereas alpha
may be specified when using the
ColorRGBA
class. An example of these usages is provided below.
from ansys.stk.core.utilities.colors import Colors, ColorRGBA
manager = root.current_scenario.scene_manager
point = manager.initializers.point_batch_primitive.initialize()
lla_pts = [39.88, -75.25, 0, 38.85, -77.04, 0, 37.37, -121.92, 0]
colors = [Colors.Red, ColorRGBA(Colors.Blue, 127), Colors.from_rgba(0, 255, 0, 127)]
point.set_cartographic_with_colors("Earth", lla_pts, colors)
Coding patterns#
This section provides coding patterns that are commonly used when developing with PySTK.
Strategy pattern#
This section provides information on the strategy pattern as it relates to PySTK. The strategy pattern enables you to delegate behavior to different strategies that can be selected at runtime. It is useful when you need to vary the behavior of certain components, such as authentication methods or request handling strategies, without altering the objects that use them.
gRPC call batching#
Making multiple network calls can introduce latency, especially when those calls are made sequentially. gRPC call batching is used to optimize the performance of gRPC-based communication by combining multiple requests into a single batch. This reduces the overhead of multiple round trips, improves performance, and enhances scalability.
Calling the application-level method new_grpc_call_batcher
returns an object
of type GrpcCallBatcher
.
This feature is provided as an option to reduce the communication over the
gRPC server in performance-critical applications. API calls may be batched
together and sent to STK in one remote procedure call if no return value is
needed from the calls.
Activating batching causes the normal API exception behavior to be altered. Exceptions from one command may appear asynchronously. Therefore, it is not recommended to use call batching while building and debugging, but rather as a performance optimization.
Only calls that do not return a value may be batched together, such as set-property requests and methods without a return value. Any method that has a return value (including get-property requests) automatically execute any previously batched commands before the method with a return value is executed.
Therefore, to reduce the number of remote API requests and improve performance, code must be organized to group together commands that do not have a return value. Call chaining interrupts a batch request because of the get-property command within the chain.
Events#
Events are mechanisms that enable you to respond to specific changes or actions occurring within an STK scenario or the application itself. Events enable you to automate responses to particular triggers, such as when a scenario reaches a certain time, when an object’s state changes, or when specific conditions are met during a simulation.
Using events, you can build more dynamic and interactive simulations by attaching custom Python functions or scripts that are executed automatically when predefined conditions are satisfied. For instance, you might want to log specific data whenever a satellite enters a certain region or when a communication link is established between two objects. Events enable you to hook into STK processes and respond in real-time, streamlining workflows and enhancing your scenario’s capabilities.
You can access events directly in applicable parent objects, as displayed in the table below.
Event interface |
Parent object |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Events are accessed through the subscribe()
method on the parent object,
which returns an event handler subscribed to events on the queried object. You
can add or remove event callbacks in the event handler using the +=
and -=
operators. These operators change the callbacks that get executed by the event
but do not affect whether the handler remains subscribed. The event handler
should be unsubscribed using the unsubscribe()
method when event handling is
no longer needed. Refer to the following example for using
IStkObjectRootEvents
.
# STKObjectRoot root: STK Object Model Root
def on_scenario_new_custom_callback(path: str):
print(f"Scenario {path} has been created.")
stk_object_root_events = root.subscribe()
stk_object_root_events.on_scenario_new += on_scenario_new_custom_callback
root.new_scenario("ExampleScenario")
# callback should be executed now
# remove the callback from the handler
stk_object_root_events.on_scenario_new -= on_scenario_new_custom_callback
# all finished with events, unsubscribe
stk_object_root_events.unsubscribe()
The STK desktop application user interface might become unresponsive to user input when Python has event subscribers, and STK tries to call back into the Python interpreter to notify of an event. That callback relies on the Windows message loop to be dispatched. To work around this issue, Windows messages need to be dispatched through the Windows message queue. This can be accomplished in different ways depending on the type of Python script that is executing (console or user interface), and on the type of user interface library being used. For instance, if you use the tkinter user interface library, a simple way of accomplishing this with this library is to create a tkinter window while using the desktop application user interface. No action is needed if Python is used only for automation. The following script is an example showing this issue.
from ansys.stk.core.stkdesktop import STKDesktop
from ansys.stk.core.stkobjects import STKObjectType
def on_stk_object_added_custom_callback(path: str):
print(f"{path} has been added.")
stk = STKDesktop.start_application(visible=True)
root = stk.root
root.new_scenario("ExampleScenario")
stk_object_root_events = root.subscribe()
stk_object_root_events.on_stk_object_added += on_stk_object_added_custom_callback
scenario = root.current_scenario
# on_stk_object_added_custom_callback is successfully called when the next line is executed
facility = scenario.children.new(STKObjectType.FACILITY, "Exton")
# Now switch control to the desktop application and create another facility.
# The user interface becomes unresponsive.
# Now open a tkinter window that processing Windows messages.
from tkinter import Tk
window = Tk()
window.mainloop()
# Switch control to the desktop application and create another facility.
# The user interface is responsive and the event callback is successful.