At the moment, I’d probably pass them as custom atom labels. I know there needs to be a good way to pass general atom properties (beyond partial charges) and bond properties (e.g., Meyer bond order). I have to think a bit about the way to handle that in the C++ Molecule class.
The labels default to strings - I’d have to check if the code is smart enough to convert numbers to strings.
It probably makes sense to have something like this syntax. I would then need to add some support in the C++ classes to handle arbitrary per-atom and per-bond properties (including showing up in dialogs, labels, etc).
I really really like the sound of that. It’d be really cool to have it be the case that:
An entry in ["atoms"]["properties"] or ["bonds"]["properties"] can have any arbitrary string as its key and an array of any scalar type without it causing an error
Any found property can be selected for the atom or bond labels, additional to the current label options or the custom labels represented by ["atoms"]["labels"] and ["bonds"]["labels"] (what you are suggesting I believe)
All found properties are shown as columns in the tables in the property dialogs
Any property keys that Avogadro recognises can be treated specially i.e. the name can be reformatted and units indicated, and any that don’t can just be shown as is and left to the user to interpret.
Likewise it’d be very cool/useful/flexible if we could do the same with molecular properties: a number of standardised and documented properties can be interpreted nicely, but any arbitrary string key + scalar value is also shown and made editable in the Molecular Properties dialog.
Obviously the framework for that is a bit of work but I feel like long term it’d make life easier, because Avogadro wouldn’t have to implement a property across the entire interface before it gets “support”. For example, it would be then be possible to add support for a particular property to a single output file parser without having to wait for Avogadro to be first taught how to interpret and display it in an intelligent or tailor-made fashion. Or for a plugin to return whatever obscure property it wants.
Molecular properties will already show up. I’m not sure about the “editable” part (by default). Some things make sense to be editable, but most things that I can imagine (e.g., computed properties) should not. I think it’s probably better to leave that on a case-by-case basis.
Yes, I’m suggesting atom and bond labels, as well as a way that atom or bond (or residue) properties would show up in the appropriate property table dialogs (and the label rendering).
The main thing as I said is thinking about how to handle the data. At the moment, most things are handled by the Molecule class including arbitrary data. So I’ll have to think of nice ways to handle atom / bond properties transparently.
I guess it’s been a trend that I’m generally more in favour of providing the functionality and leaving it up to the user to decide what makes sense, because after all, in this situation they don’t have to edit it just because they can, and the result is nothing different to them editing the CJSON file in a text editor. And I don’t see the tangible benefit of preventing the user doing something they have actively chosen to do, because if they want to, my attitude is that they must have a reason and then we’re just getting in their way and forcing them to find work-arounds e.g. using a text editor.
But your preference is fitting with your broader design decisions and it isn’t an unreasonable one.
I had a quick look at the code, but you know it far more intimately than me and I am not at all familiar with the idiomatic C++ way of doing things. If I was doing it in Python my instinct would be to scrap the attributes for individual properties like partialCharges and instead give Molecule a properties attribute that takes an instance of a Properties or MoleculeProperties class, which just contains dicts/maps for atom/bond/molecular properties etc. in str: array[scalar] form similar to the CJSON.
I guess a Properties instance would want methods defined for adding or deleting entries for atoms/bonds etc. based on index e.g. Properties.remove_bond(index) so that you don’t have to manually make or remove an entry in every single array in each map.
In Python I’d then just use molecule.properties.atomic["partialCharges"][i] to get a value for atom i. My impression is that this is unidiomatic in C++ (I’ll ask ChatGPT why). So what would one want instead, something like a Properties.get_atom_property(property, index) method?