A vector icon set (SVG) covering all 184 non-deprecated, non-suppressed stereotypes of the System Architecture Framework (SAF) as listed in the main SAF specification, for use as custom stereotype icons in Cameo Systems Modeler / MagicDraw.
Generated as pure artwork: this folder contains the icon files, the scripts that produce them, and this documentation. It does not include a Cameo profile wiring (how to attach each icon to its stereotype) — that was out of scope by request.
saf-icons/
├── icons/ # the 184 generated SVGs, named <stereotypename>.svg
├── preview.html # browsable gallery grouped by domain, then object/relational/diagram
├── preview.md # markdown twin of preview.html (same grouping, embeddable in issues/docs)
├── README.md # this file
└── tools/
├── gen_icons.py # generator: mapping table (M) + glyph library + preview (html + md)
├── verify.py # pixel/XML verification + ASCII eyeball rendering
├── analyze_cross_domain.py # cross-domain relation analysis (realizeConcepts → exposes → domain)
├── stereotypes.json # source catalog (verbatim from GfSE/SAF-Specification)
└── _data/ # other catalog files: concepts/exposes/realizeconcept/viewpoints/domains
| Item | Source |
|---|---|
| Stereotype catalog | src/_data/stereotypes.json in GfSE/SAF-Specification (main branch) — the file that also drives the official stereotypes page |
| Icon conventions | SAF icon design guide: https://saf.gfse.org/devdoc/icons/readme.html |
Notes:
- Stereotype names are taken verbatim from
stereotypes.json(exact casing;_deprecatedsuffixes excluded by request). - Security-viewpoint stereotypes are suppressed (38 of them:
SAF_Adversary,SAF_Asset,SAF_Risk, theSAF_C7_*security diagram/table stereotypes, the AIC/protection shields,SAF_ThreatScenario,SAF_Vulnerability, etc.). They remain in the catalog but are deliberately not rendered. The exclusion list is theSUPPRESSEDset intools/gen_icons.py; the coverage assertion still validates that every suppressed name exists in the catalog. (The unused glyph functions for those families are kept in the library for potential reuse.) SAF_DomainKindis not part of the main-version catalog (it exists only in older versions), so it is intentionally absent here.- The SCM profile (stereotype-development profile) stereotypes are excluded — they are "typically not used in system models".
- One file per stereotype:
<stereotypename>.svg(e.g.SAF_OperationalProcess.svg). - Stereotypes that implement a viewpoint get diagram-kind icons (BDD, IBD, Table, Matrix, Sequence, State, Use Case, Activity, Profile, Grid, Generic).
Per the SAF icon design guide, every icon encodes its domain of primary use via colour and, preferably, the domain short code. Both are used:
| Code | Domain | Colour |
|---|---|---|
| A | Architecture Management | #A5A5A5 (gray) |
| O | Operational | #4472C4 (blue) |
| C | Conceptual | #FFC000 (amber) |
| P | Physical | #92D050 (green) |
| D | SAF Development | #C040C0 (purple) |
The glyph itself is drawn in the domain colour. A small rounded badge with the
domain letter in the top-right corner is optional and controlled by the
DOMAIN_BADGE flag in tools/gen_icons.py; it is currently disabled
(undecided). If re-enabled, the badge letter is the colour-blind-safe fallback.
- Canvas:
64×64,viewBox="0 0 64 64". - Flat vector style, dominant stroke weight ≈ 3 (2.2–3.2 for secondary detail).
- Glyph content lives in
x ∈ [12, 42],y ∈ [14, 52]; the top-right18×18corner is reserved for the optional domain badge, so glyphs never collide with it (badge currently off). - Depth is suggested with
fill-opacity(0.25–0.7), never gradients — flat, print-safe. - Dashed strokes carry the official boundary coding semantics (dashed = usage / flow / derivation, full = definition) on relation and process glyphs.
- Text is used sparingly and only where it reads as part of the symbol (
R,?,!,S,C, and the A/C/I/P letters inside security shields, plus the domain badge letter when enabled). Font stack isArial, Helvetica, sans-serif. This is deliberate: the official SAF icons also use<text>, so text rendering is assumed safe in Cameo.
Stereotypes that model the same kind of thing share a glyph family, so related elements read as a family at a glance:
| Family | Used for | Symbol |
|---|---|---|
block / block_soi |
Conceptual/Physical/Logical systems, SOI | box with component |
context |
Operational/Conceptual/Physical/Security context | container with parts |
environment |
environments | system in an orbit |
role / role_soi |
context/internal roles | frame with a name tab |
user / stakeholder / performer |
users, stakeholders, operational performers | person (ring / gear variants) |
item, hardware, software, resource |
physical items, HW, SW, resources | cube, chip, window, gear |
capability |
operational / system capabilities | pentagon badge + check |
function, action, process |
functions, actions, processes | rounded rect + "F" / play / "P" |
state |
operational / system states | state node → final dot |
usecase / misusecase |
use cases, misuse cases | ellipse (± strike) |
exchange, interface, requirement, asset |
exchange types, interfaces, requirements, assets | packet on arrow, SysML port type (block edge + port square + "T"), folded "R", diamond |
concern, viewpoint |
concerns, framework viewpoints | magnifier, viewfinder |
claim, counterclaim, claimant, refuter, claimable, subject, argument, evidence, assumption |
argumentation | speech bubbles, person variants, flag, shield, "?" doc |
standard, category, org, chapter, term, docref, example |
standards & terms | book, folder, building, tag, doc+chain, star |
adversary, attackpath/vector/action, shield*, risk, threat, securitycontext, objective, likelihood, severity, effect, impacted |
security | hooded figure, bolts, shields (A/C/I/check/crack/levels), warning, lifelines, gauges |
rel_realization / rel_cross |
cross-domain relations | box of the lower domain below, conceptual box (amber, C domain) above, dashed arrow up |
eatrace |
EA traceability | stacked layers |
rel_* |
associations/relations | connector glyphs, see below |
dia_* |
viewpoint-implementing stereotypes | diagram-kind glyphs, see below |
A shared horizontal connector with differentiated endpoints (and matching the standard SysML/UML semantics):
| Family | Meaning | Endpoint |
|---|---|---|
rel_composition |
composition | filled diamond (whole) + arrow |
rel_dependency |
dependency | dashed line + open arrow |
rel_generalization |
generalization | hollow triangle |
rel_derive |
derivation | filled circle (tail) + arrow |
rel_check |
satisfaction / support / conforms | checkmark + arrow |
rel_gear |
enabling | gear on the line |
rel_down |
refinement | drill-down arrow |
rel_constraint |
constraint | brace |
rel_imposition |
imposes | filled wedge |
rel_double |
two-way mapping (EA) | arrows both ways |
rel_support |
support | bracket under the line |
rel_simple |
generic relation | plain arrow |
Stereotypes that implement a viewpoint (e.g. SAF_C2_SCYD, SAF_O3_OPRO,
SAF_P1_PCXE) get an icon of the diagram type their view is presented as:
dia_bdd, dia_ibd, dia_table, dia_matrix, dia_sequence, dia_state,
dia_usecase, dia_activity, dia_profile, dia_grid, dia_generic.
For IBD the glyph shows a large rectangle on the left with two smaller boxes on
the right, connected by mid-line arrows. Activity diagrams show the UML activity
start (filled dot), a rounded action box, and the final (bullseye) symbol joined
by flow lines. State diagrams show
two boxes in diagonal corners (top-left, bottom-right) with L-shaped arrows
going back and forth.
- The whole set is produced from a single declarative mapping table
Mintools/gen_icons.py((stereotype, domain, family, variant)). - The generator asserts full coverage: it compares
Magainststereotypes.jsonand fails on missing or unknown names, preventing drift. - Every icon is machine-verified (see Verification below).
For viewpoint-implementing stereotypes the domain is taken from the viewpoint's
own documentation URL (Architecture Management / Operational / Conceptual / Physical / SAF Development Domain). For element stereotypes the domain follows
SAF semantics: argumentation, standards/terms and EA traceability → A;
operational performers/processes/states/stories/stakeholders → O;
system/conceptual elements, functions, capabilities, requirements, and all
security elements → C; hardware/software/items/resources → P;
framework viewpoints → D.
Within each domain the preview groups the icons into three kinds:
- Object stereotypes — element stereotypes (blocks, capabilities, functions, requirements, states, ...).
- Relational stereotypes — the
SAF_*Rel*/*_To_*associations (therel_*glyph families). - Diagram stereotypes — the
*_Viewpoint-implementing stereotypes that carry a diagram frame pictogram (thedia_*families).
Some relational stereotypes relate elements of different SAF domains. Relations point upward through the domain stack
Physical → Conceptual → Operational
i.e. a stereotype flagged (homed) in a domain relates to the domain above it, never below. Consequently:
- a P-flagged stereotype may relate to C (physical realizes conceptual);
- a C-flagged stereotype may relate to O (system enables operational);
- an O-flagged stereotype has nothing above it and cannot relate to the
conceptual domain — the O↔C pairs like
SAF_OperationalPerformerActingare operational-internal relations.
Cross-domain stereotypes get the special glyph (rel_cross /
rel_realization): box of the lower (home) domain below, box of the higher
domain above, dashed arrow pointing up (variant encodes the pair, e.g. PC,
CO).
Identification method (see tools/analyze_cross_domain.py, mirror data in
tools/_data/):
- trace
realizeConceptsfrom each stereotype to the concept(s) it realizes; - take the association ends of the realized relation concepts — the element types being related;
- use the
exposesrelation (viewpoint exposures inconcepts.json/exposes.json) to derive the home domain of each endpoint (its most frequent exposure domain); - a stereotype is cross-domain when its endpoints' home domains differ and its flagged (home) domain is the lower of the two.
Result (restyled icons):
| Stereotype | Pair | Glyph |
|---|---|---|
SAF_PhysicalRealization |
P → C | green below, amber above |
SAF_SystemCapabilityEnabling |
C → O | amber below, blue above |
SAF_SystemUseCaseEnabling |
C → O | amber below, blue above |
The borderline cases the method also flags (refinement/derivation families,
exchange-type composition, SAF_StakeholderRelation, the supporting
argumentation relations) were deliberately not restyled — their endpoints'
domains are mixed or span more than two domains, so a two-box glyph would be
misleading.
Note on name collisions: the concept taxonomy holds several same-named relation concepts (
depending,composed,enabling,acting in, ...) that exist once per domain. Resolving realized concepts by ID (not by name) is what keeps e.g.SAF_SystemCapabilityDependencycorrectly single-domain: despite the genericdependingname it realizes the System Capability variant and relates System Capability to System Capability only.
Requirements: Python 3 with cairosvg and Pillow
(python3 -m venv venv && venv/bin/pip install cairosvg pillow).
python tools/gen_icons.py # rewrites icons/ and preview.htmlpython tools/verify.py # XML + pixel checks on all 184 icons
python tools/verify.py SAF_Risk # ASCII-render one icon in the terminal- Edit the mapping table
Mintools/gen_icons.py— one line per stereotype:("SAF_MyStereotype", "<A|O|C|P|D>", "<family>", "<variant or None>"). - If you need a new pictogram, add a
g_*function to the glyph library and register it inFAMILIES. - Run the generator — the coverage assertion will tell you immediately if anything is missing or unknown.
- Run
verify.pyand eyeball the result with the ASCII renderer.
- Re-download the catalog files from
GfSE/SAF-Specification(main)src/_data/intotools/(stereotypes.json) andtools/_data/(concepts.json,exposes.json,realizeconcept.json,viewpoints.json,domains.json,domaincolors.json). - Regenerate. The assertion will list any new stereotypes (map them) or removed
ones (drop them). Re-run
python tools/analyze_cross_domain.pyto check whether any new relational stereotype turned cross-domain. Update this README's coverage numbers afterwards.
- Text dependency. The optional badge letter and a few glyph-internal letters
rely on SVG
<text>. If a target renderer ignores text, replace letters with pure geometry. Cameo's own official icons use<text>, so this is expected to work. - Artwork only. No
.mdzip/profile wiring is provided; attaching each icon to its stereotype in Cameo (stereotypeImageproperty) is still to be done. - Independent design. The icons follow the official conventions but are an
original design, not copies of the GfSE icon set. If exact stylistic parity
with the official icons is ever required, the reference SVGs live in the
SAF-Specification repo under
docs/icon folders. - Deprecated stereotypes (
*_deprecated) are intentionally excluded by request. The generator ignores them automatically (endswith("_deprecated")); to include them again, remove the filter ingen_icons.pyand re-add the entries toM. - PNG renders are not shipped; the SVGs scale to any size, but a
png/subfolder at fixed sizes (16/32/64) can be added withcairosvgif a tool version needs bitmaps.