A step.Object is one STEP data instance, while a step.Design is the collection of all instances in a file.

An EXPRESS schema describes the type of instances, which can be an ENTITY with attributes, or an AGGREGATE such as a list, set, or bag. An ENTITY instance has a file identifier (#123) while AGGREGATEs have no identifier because they only appear as values of attributes.

STEP instances often describe low-level atomic values, like a direction vector, or a property name, which are then combined in well-defined patterns to describe higher-level concepts like a workpiece, part feature, or machining workplan. The patterns are described in the "Application Reference Model (ARM)" section of the STEP standard.

The STEP Python interface recognizes these patterns when reading data and associates the graph of objects surrounding a root STEP instance as ARM attributes that are accessed exactly like the basic EXPRESS attributes. This greatly simplifies understanding and operations on STEP data sets.

An STEP file example is shown below. Each of the instances #50 to #62 below is a step.Object with attribute values shown in parenthesis. Instance #50 is the root of the higher level MILLING_MACHINE_FUNCTIONS ARM concept, so it will also have a through spindle coolant attribute with a value of 'through spindle coolant off', built from instances #51-#54, and similarly for chip removal and coolant.

 * Application object: MILLING_MACHINE_FUNCTIONS (#50)
 * THROUGH_SPINDLE_COOLANT: #50, #51, #52, #53, #54: [through spindle coolant off]
 * CHIP_REMOVAL: #50, #55, #56, #57, #58: [chip removal off]
 * COOLANT: #50, #59, #60, #61, #62: [coolant on]
#50=MACHINING_FUNCTIONS('','milling',' ',' ');
#51=ACTION_PROPERTY('through spindle coolant','',#50);
#54=DESCRIPTIVE_REPRESENTATION_ITEM('constant','through spindle coolant off');
#55=ACTION_PROPERTY('chip removal','',#50);
#58=DESCRIPTIVE_REPRESENTATION_ITEM('constant','chip removal off');
#62=DESCRIPTIVE_REPRESENTATION_ITEM('constant','coolant on');

Basic Operations

The Python repr() gives basic information about the step.Object. An ENTITY has the file identifier (#123) and the EXPRESS type. If it is the root of an ARM concept, that appears first. Some common entities (measures, units, points) include a summary of the underlying data rather than the EXPRESS type. AGGREGATEs include EXPRESS type and size. They have no file identifier because they only appear as values of attributes.

print (val)

# ENTITY instances
<step.Object #200 polyline> 
<step.Object #20 product_definition_shape>

# ENTITY instances, root of an ARM concept
<step.Object ARM WORKPLAN #1035 machining_workplan> 
<step.Object ARM WORKPIECE #19 product_definition>

# ENTITY instances for points, units, measures
<step.Object #897 MEASURE 25.4 mm>
<step.Object #683 UNIT deg>
<step.Object #198 POINT -0.109698, -0.0599282, 1>

# AGGREGATE lists, bags, sets.  Similar sequence for ARM data
<step.Object SetOfrepresentation_item size 1>
<step.ArmCollection size 10>

Attributes of an ENTITY are available as a dictionary or by the usual dot attribute syntax. The entity_id() function returns the file identifier. The step.type() and step.isinstance() functions follow the similarly-named Python builtins, but operate on the EXPRESS type of an object. The step.arm_type() function returns the ARM type for objects that are the root of an ARM concept or None otherwise.

print (LINE)
pprint (dict(LINE))  # pprint sorts keys

<step.Object #200 polyline>
{'name': 'starting line',
 'points': <step.Object ListOfcartesian_point size 3>}

print (exp type:, step.type(LINE))
print (is rep item:, step.isinstance(LINE, representation_item))
print (file id: #%d % LINE.entity_id())
print (name as att:, LINE.name)
print (name as sub:, LINE['name'])

exp type: polyline
is rep item: True
file id: #200
name as att: starting line
name as sub: starting line

Aggregates are Python sequences, and accept the len() and usual iterator and index operators. In the example below, the polyline has a list of cartesian point objects, and each point has a list of floating point coordinate values.

ARM attributes with multiple values use a ArmCollection sequence object that accepts the len() and usual iterator and index operators.

PT = LINE.points[0]
pprint (dict(PT)) 

{'coordinates': <step.Object ListOfdouble size 3>,
 'name': 'w'}

print (length:, len(PT.coordinates))
print (vals as tuple:, *PT.coordinates)
print (vals by index:, PT.coordinates[0], PT.coordinates[1])

length: 3
vals as tuple: 13412.0 -1486.0 0.0
vals by index: 13412.0 -1486.0

The EXPRESS SELECT union type is not used. Only the underlying value of the union appears. When the union holds a string or number, it appears as a tuple with a type name, like (2.0, 'length_measure').

STEP Files

The step.Design object contains all instances in a file. Reading a file with AptAPI.open_project() returns a design object with all ARM concepts recognized.

Within this collection, you can find object with the high level functions in AptAPI, ToleranceAPI or FinderAPI. You can also iterate over objects by EXPRESS type with a DesignCursor. The design can also be used as a dictionary with with the names (usually UUIDs) given to objects by the ANCHOR section in newer STEP files.

D = step.AptAPI.open_project(part123.stp)

# iterate over all entities
for obj in step.DesignCursor(D):
    print (entity #%d % obj.entity_id())

# iterate over just the representation items
for obj in step.DesignCursor(D, representation_item):
    print (rep item #%d, name %s % (obj.entity_id(), obj.name))

# get object by ANCHOR value from STEP file (P21e3)
obj = D['6db46031-4fab-4838-824b-91cea43922e4']

# print all of the UUID ANCHORs from STEP file
PP.pprint (dict(D))

{ '0098e447-15ab-44ac-b360-3d5fd4f7dcd3': <step.Object #7978 dimensional_location>,
  '04d1431a-9535-4ef6-a615-f00315a87548': <step.Object #8003 dimensional_location>,
  '09a905e5-da9c-44ab-aa9b-48689aafcd59': <step.Object #8018 dimensional_location>,
  '09c07753-38cf-4928-928f-4acd0e636247': <step.Object #7928 datum>,

Common STEP Objects

The following EXPRESS types and ARM concepts are a good starting place for understanding the contents of a STEP file. The sections below show an example of the repr() you might see from printing an object with print(OBJ), plus the contents of the dict(OBJ) of the object.

Find ARM Concept
Find EXPRESS Entity

ARM Workpiece

The root of an ARM Workpiece is a product_definition instance. This is the backbone of a STEP file and describes the individual products in an assembly.

Shape is largest and most complex property of a workpiece and is typically found through the its_geometry and its_related_geometry ARM attributes. Other ARM properties give information about material and administrative information like approvals and signoffs.

<step.Object ARM WORKPIECE #21 product_definition>
{'clamping_positions': <step.ArmCollection size 0>,
 'description': ' ',
 'formation': <step.Object #20 product_definition_formation_with_specified_source>,
 'frame_of_reference': <step.Object #3 product_definition_context>,
 'global_tolerance': None,
 'id': '7AJS9999-0001A_FOR_NC',
 'its_approvals': <step.ArmCollection size 0>,
 'its_bounding_geometry': None,
 'its_categories': <step.ArmCollection size 1>,
 'its_components': <step.ArmCollection size 0>,
 'its_constructive_models': <step.ArmCollection size 1>,
 'its_datestamps': <step.ArmCollection size 0>,
 'its_geometry': <step.Object #16 shape_representation>,
 'its_id': '7AJS9999-0001A_FOR_NC',
 'its_material': None,
 'its_orgs': <step.ArmCollection size 0>,
 'its_people': <step.ArmCollection size 0>,
 'its_rawpiece': None,
 'its_related_geometry': <step.ArmCollection size 0>,
 'its_security_classification': <step.ArmCollection size 0>,
 'its_styled_models': <step.ArmCollection size 0>,
 'its_timestamps': <step.ArmCollection size 0>,
 'product_approvals': <step.ArmCollection size 0>,
 'product_datestamps': <step.ArmCollection size 0>,
 'product_orgs': <step.ArmCollection size 0>,
 'product_people': <step.ArmCollection size 0>,
 'product_timestamps': <step.ArmCollection size 0>,
 'revision_approvals': <step.ArmCollection size 0>,
 'revision_datestamps': <step.ArmCollection size 0>,
 'revision_id': '',
 'revision_orgs': <step.ArmCollection size 0>,
 'revision_people': <step.ArmCollection size 0>,
 'revision_security_classification': <step.ArmCollection size 0>,
 'revision_timestamps': <step.ArmCollection size 0>,
 'security_classification': <step.ArmCollection size 0>,
 'shape_definition': <step.Object #22 product_definition_shape>}

ARM Geometric_tolerance

The root of an ARM Geometric_tolerance is a geometric_tolerance instance. There are subtypes in both ARM and EXPRESS for position, flatness, surface profile, and many other kinds of tolerance. The actual EXPRESS instance can get rather complex as seen in the example below. The ToleranceAPI has a variety of high-level functions for working with tolerances.

<step.Object ARM SURFACE_PROFILE_TOLERANCE_WITH_DATUM #5449 geometric_tolerance_with_datum_reference_and_surface_profile_tolerance>
{'applied_to': <step.Object ARM COMPOSITE_CALLOUT #5417 all_around_shape_aspect>,
 'associated_draughting': <step.ArmCollection size 1>,
 'datum_system': <step.Object SetOfdatum_system_or_reference size 1>,
 'description': '',
 'id': None,
 'magnitude': <step.Object #5447 MEASURE 0.5 mm>,
 'name': 'Position surface profile.2',
 'qualifying_note': '',
 'reference_datum': <step.ArmCollection size 0>,
 'related_tolerances': <step.ArmCollection size 0>,
 'significant_digits': None,
 'system_datum': <step.Object ARM DATUM_SYSTEM #5448 datum_system>,
 'tolerance_value': <step.Object #5447 MEASURE 0.5 mm>,
 'toleranced_shape_aspect': <step.Object ARM COMPOSITE_CALLOUT #5417 all_around_shape_aspect>}

<step.Object ARM POSITION_TOLERANCE_WITH_DATUM #1554 geometric_tolerance_with_datum_reference_and_geometric_tolerance_with_modifiers_and_position_tolerance>
{'affected_plane': None,
 'applied_to': <step.Object ARM CENTER_OF_SYMMETRY_CALLOUT #1533 centre_of_symmetry>,
 'associated_draughting': <step.ArmCollection size 1>,
 'datum_system': <step.Object SetOfdatum_system_or_reference size 1>,
 'description': '',
 'id': None,
 'magnitude': <step.Object ARM QUALIFIED_PLUS_MINUS_VALUE #1552 length_measure_with_unit_and_measure_representation_item_and_qualified_representation_item>,
 'modifiers': <step.Object SetOfgeometric_tolerance_modifier size 1>,
 'name': 'Position.1',
 'qualifying_note': '',
 'reference_datum': <step.ArmCollection size 0>,
 'related_tolerances': <step.ArmCollection size 0>,
 'significant_digits': None,
 'system_datum': <step.Object ARM DATUM_SYSTEM #1438 datum_system>,
 'tolerance_value': <step.Object ARM QUALIFIED_PLUS_MINUS_VALUE #1552 length_measure_with_unit_and_measure_representation_item_and_qualified_representation_item>,
 'toleranced_shape_aspect': <step.Object ARM CENTER_OF_SYMMETRY_CALLOUT #1533 centre_of_symmetry>}

ARM Material

The root of an ARM material is a material_designation instance. It generally appears as the its_material property of a workpiece.

<step.Object ARM MATERIAL #17348 material_designation>
{'definitions': <step.Object SetOfcharacterized_definition size 1>,
 'material_identifier': 'EN AW-7075 (3.4365 or AlZn5,5MgCu)',
 'material_property': <step.ArmCollection size 0>,
 'name': 'EN AW-7075 (3.4365 or AlZn5,5MgCu)',
 'standard_identifier': 'ASM'}

ARM Project

The root of an ARM Project is a product_definition instance. Every STEP-NC program contains one project, and the "main_workplan" gives the starting point for the manufacturing process. The AptAPI.get_current_project() function is an easy way to find this.

<step.Object ARM PROJECT #10 product_definition>
{'description': '',
 'formation': <step.Object #12 product_definition_formation>,
 'frame_of_reference': <step.Object #16 product_definition_context>,
 'id': '',
 'its_id': 'imts_ashtray_v1',
 'its_manufacturer': None,
 'its_manufacturer_organization': None,
 'its_owner': None,
 'its_owner_organization': None,
 'its_release': None,
 'its_security_classification': <step.ArmCollection size 0>,
 'its_status': None,
 'its_workpieces': <step.ArmCollection size 1>,
 'main_workplan': <step.Object ARM WORKPLAN #19 machining_workplan>}

ARM Workplan and Workingstep

The ARM Workplan and Workingstep concepts are the two most commonly used subtypes of the ARM Executable concept, which describes the control flow in an STEP-NC process. The root is a machining_process_executable instance, or subtypes machining_workplan and machining_workingstep.

The Adaptive class is the easiest way to walk through a STEP-NC process. The as_is_geometry, to_be_geometry, and removal_geometry properties describe the shape at that location in the process.

<step.Object ARM WORKPLAN #19 machining_workplan>
{'as_is_geometry': <step.Object ARM WORKPIECE #2054 product_definition>,
 'consequence': '',
 'description': '',
 'enabled': None,
 'fixture_geometry': None,
 'its_channel': None,
 'its_elements': <step.ArmCollection size 1>,
 'its_id': 'Aerospace',
 'its_minimum_machine_params': None,
 'its_security_classification': <step.ArmCollection size 0>,
 'its_setup': <step.Object ARM SETUP #6267 product_definition_formation>,
 'machine_used': None,
 'name': 'Aerospace',
 'planning_operation': None,
 'process_properties': <step.ArmCollection size 0>,
 'purpose': '',
 'removal_geometry': None,
 'to_be_geometry': <step.Object ARM WORKPIECE #1648 product_definition>,
 'toolpath_orientation': None,
 'twin_end': None,
 'twin_exception': None,
 'twin_plan': None,
 'twin_source': None,
 'twin_start': None,
 'twin_worktime': None}

<step.Object ARM MACHINING_WORKINGSTEP #905 machining_workingstep>
{'as_is_geometry': None,
 'consequence': '',
 'description': 'machining',
 'enabled': None,
 'final_features': <step.ArmCollection size 0>,
 'fixture_geometry': None,
 'its_feature': <step.Object ARM TOOLPATH_FEATURE #994 instanced_feature>,
 'its_id': '2D 90deg arcs and lines WS 2',
 'its_operation': <step.Object ARM FREEFORM_OPERATION #863 freeform_milling_operation>,
 'its_secplane': None,
 'its_secplane_rep': None,
 'its_security_classification': <step.ArmCollection size 0>,
 'machine_used': None,
 'name': '2D 90deg arcs and lines WS 2',
 'process_properties': <step.ArmCollection size 0>,
 'purpose': '',
 'removal_geometry': None,
 'to_be_geometry': None,
 'toolpath_orientation': None,
 'twin_end': None,
 'twin_exception': None,
 'twin_plan': None,
 'twin_source': None,
 'twin_start': None,
 'twin_worktime': None}