Model > Data
Count by Property
Counts objects by the values of one property, or by pairs of values of two (a two-level pivot), over the selection, the visible items or the whole model. Shows a sorted table with shares and a top 20 chart, then lets you select any group. Optional Excel export.
Status
Launched Ran inside Navisworks at least once with no error logged; nobody checked the result yet.
Ran headless under pynavis run against a sample model; no selection: ran to the end: 'Counted 1 value over 1 object'; result not checked by a person.
The public ask
No public source is on record for this tool.
Events it listens to
None. It runs only when you click it.
Files
Paths are relative to the Playground.extension folder.
Model.tab/Data.panel/Count_by_Property.pushbutton/bundle.yamlModel.tab/Data.panel/Count_by_Property.pushbutton/icon.dark.pngModel.tab/Data.panel/Count_by_Property.pushbutton/icon.pngModel.tab/Data.panel/Count_by_Property.pushbutton/icon.small.dark.pngModel.tab/Data.panel/Count_by_Property.pushbutton/icon.small.pngModel.tab/Data.panel/Count_by_Property.pushbutton/script.py
Install
- Only this tool. In Navisworks, click pyNavis > Playground, search for Count by Property, tick it and click Install.
- The whole extension. Download
Playground.extension.zip, unzip it, put thePlayground.extensionfolder in%APPDATA%\pyNavis\extensions\, and click pyNavis > Reload. Count by Property is on the Model tab, Data panel.
You need pyNavis 1.3.0 or later.
Tried it? Tell us whether it worked or not. That report is what moves a tool up the status ladder.
ReportSource
The tool's own files, word for word as published in pynavis/Playground. Paths are relative to the Playground.extension folder.
script.py
The script that runs on a click.
Model.tab/Data.panel/Count_by_Property.pushbutton/script.py View on GitHub# -*- coding: utf-8 -*-
"""Counts objects by the values of one or two properties and lets you select a group."""
from pynavis import script, toast
from namo import data_common, items, progress, propindex, reports, ui
from namo import rep_count_by_property as rep
NONE = '(none)'
DEFAULTS = {'category': 'Element', 'property': 'Category', 'category2': '', 'property2': '',
'scope': 'model', 'level': 'objects', 'xlsx': False}
def ask(doc, values):
"""The config for this run, or None when cancelled."""
has_selection = data_common.selected_count(doc) > 0
choices = propindex.property_choices(doc, scope='selection' if has_selection else 'model')
if not choices:
toast.info('No properties found', 'The items in scope carry no properties to count.')
return None
rows = [{'cells': [c, p, n], 'value': propindex.pair_text(c, p)} for c, p, n in choices]
first = propindex.pair_text(values['category'], values['property'])
picked = ui.choose('Count by Property', rows, ['Tab', 'Property', 'Items seen'], multiselect=False,
checked=[first], prompt='Count objects by which property?', ok='Next')
if picked is None:
return None
category, prop = propindex.split_pair(picked[0])
seconds = [(NONE, NONE)] + [(r['value'], r['value']) for r in rows if r['value'] != picked[0]]
second = propindex.pair_text(values['category2'], values['property2']) if values.get('property2') else NONE
fields = [{'kind': 'label', 'text': 'Counting by %s.' % picked[0]},
{'kind': 'choice', 'key': 'second', 'label': 'Then by (optional, for a two-level pivot)',
'options': seconds, 'default': second if second in [s[1] for s in seconds] else NONE}]
fields += data_common.scope_fields(has_selection, values.get('scope'), values.get('level'))
fields.append({'kind': 'check', 'key': 'xlsx', 'label': 'Also save an Excel workbook',
'default': bool(values.get('xlsx'))})
answer = ui.form('Count by Property', fields, ok='Count')
if answer is None:
return None
config = {'category': category, 'property': prop, 'category2': '', 'property2': '',
'scope': answer['scope'], 'level': answer['level'], 'xlsx': bool(answer['xlsx'])}
if answer['second'] != NONE:
config['category2'], config['property2'] = propindex.split_pair(answer['second'])
return config
def pick_group(result):
groups = result.get('groups') or []
if len(groups) < 2:
return
rows = []
for index, group in enumerate(groups):
rows.append({'cells': list(group['key']) + [group['count']], 'value': index})
headers = rep.headers_of(result.get('config') or {})[:-1]
picked = ui.choose('Select a group', rows, headers, multiselect=False,
prompt='Pick a group to select its items, or Cancel to keep the counts.', ok='Select')
if picked is None:
return
group = groups[picked[0]]
count = items.select(group['items'])
toast.success('Selected %s %s' % ('{:,}'.format(count), 'item' if count == 1 else 'items'),
' / '.join(group['key']))
def run():
if ui.is_runner():
result = reports.run('count_by_property', script.get_config(DEFAULTS), interactive=False)
if not result.get('cancelled'):
toast.show(result['level'], result['message'], result['detail'])
return
doc = data_common.active_doc()
if not data_common.has_models(doc):
data_common.no_model_toast()
return
values = script.get_config(DEFAULTS)
config = ask(doc, values)
if config is None:
return
script.save_config(config)
if config['xlsx']:
path = data_common.ask_save('{file} - Count by property - {date}', 'xlsx', 'Save the counts', doc)
if path is None:
return
config['path'] = path
result = progress.run('Count by Property', lambda report: reports.run(
'count_by_property', config, doc=doc, interactive=True, progress=report))
if result is progress.CANCELLED or result.get('cancelled'):
return
toast.show(result['level'], result['message'], result['detail'])
if result['level'] in ('success', 'warning'):
result['config'] = config
pick_group(result)
run()
Library modules this tool uses
From the shared namo library, which installs with every tool. Each name opens the module on GitHub.
namo.data_commonShared plumbing for the Inspect and Data panel tools: progress stages, where files go by default, the scope dialog fields, and the small checks every button starts with.namo.itemsModel items: walking, collecting, identifying, measuring and showing them.namo.progressGlue between pyNavis' cancellable progress window and Playground's progress callbacks.namo.propindexProperty scanning shared by Property Explorer, Count by Property, Data Validator and the Write Data tools: scopes, fast value reading, the category > property > value index.namo.rep_count_by_propertyCount by Property: how many objects carry each value of one property (or each pair of values of two, as a two-level pivot), in the output window and/or an Excel file.namo.reportsThe registry of automation-ready reports, and the helpers every report shares.namo.uiWPF building blocks for Playground tools, themed from the pyNavis design system.
bundle.yaml
The bundle contract: the keys pyNavis reads for this tool.
Model.tab/Data.panel/Count_by_Property.pushbutton/bundle.yaml View on GitHubtitle: Count by\nProperty
tooltip: Counts objects by the values of one property, or by pairs of values of two (a two-level pivot), over the selection, the visible items or the whole model. Shows a sorted table with shares and a top 20 chart, then lets you select any group. Optional Excel export.
context: doc