GUI¶
All the scripts and modules tasked to create the GUI for Gaussian-2-Blender.
The GUI was built using Python’s tkinter library.
Main GUI Script¶
Actions Region Module¶
Blender Path Module¶
Bond Conventions Module¶
Console Region Module¶
Coordinates Module¶
- class Coordinates.Coordinates[source]¶
Bases:
object- check_animationframes(file_paths)[source]¶
Checks whether all animation frames (molecular structure files) have the same number and identity of elements.
Gets the first element of every tuple in the first coordinate set.
Creates a list ‘coord’ of coordinates for every file_path in the list.
Compares the values in ref_elements (from the first file) with those in all_elements.
Returns True if all elements match, otherwise returns False.
- Parameters:
file_paths (list of str) – List of file paths to the molecular structure files.
- Returns:
True if all files have the same number and identity of elements, False otherwise.
- Return type:
bool
- check_newline_characters(file_path)[source]¶
Checks the newline character type used in a file.
- Parameters:
file_path (str) – The path to the file to check.
- Returns:
The newline type used in the file: ‘windows’, ‘unix’, or ‘mac’.
- Return type:
str or None
- combine_animation_frames(file_paths)[source]¶
Combines Cartesian coordinates from multiple molecular structure files into a single list of tuples.
- Parameters:
file_paths (list of str) – A list of strings containing the paths to the files representing different frames.
- Returns:
A list of tuples, where each tuple contains: - atom_id (str): The identifier of the atom (e.g., “C01” for carbon). - coordinates (float, float, …, float): The Cartesian coordinates for the atom across all frames.
- Return type:
list of tuple
- extract_cartesian_coordinates(file_path)[source]¶
Extracts Cartesian coordinates from a molecular structure file.
- Parameters:
file_path (str) – The path to the file containing the molecular structure.
- Returns:
A list of tuples, where each tuple contains: - atom_id (str): The atomic symbol with an element index (e.g., “C01” for carbon). - x (float): The x-coordinate of the atom. - y (float): The y-coordinate of the atom. - z (float): The z-coordinate of the atom.
- Return type:
list of tuple
- get_coordinates_line_numbers(file_lines)[source]¶
Finds the line numbers where the Cartesian coordinates are located in the file.
- Parameters:
file_lines (list of str) – List of lines read from the molecular structure file.
extension – File extension to check (default is “.com”).
- Returns:
A tuple (start_line, end_line), where start_line is the first line containing coordinates and end_line is the line after the last coordinate.
- Return type:
tuple
Create Tooltip Module¶
- class CreateTooltip.CreateTooltip(widget, text='widget info')[source]¶
Bases:
objectA class to create tooltips for a given widget in Tkinter.
This class binds event handlers to the widget to show and hide tooltips when the mouse hovers over or leaves the widget.
- enter(event=None)[source]¶
Handles the mouse entering the widget. Schedules the tooltip to be shown.
- Parameters:
event – The event triggered by the mouse entering the widget.
- hidetip()[source]¶
Hides the currently displayed tooltip. Destroys the Toplevel window containing the tooltip.
- leave(event=None)[source]¶
Handles the mouse leaving the widget. Unschedules and hides the tooltip.
- Parameters:
event – The event triggered by the mouse leaving the widget.
- schedule()[source]¶
Schedules the tooltip to be shown after a delay.
Cancels any previously scheduled tooltip and sets a new timer to show the tooltip.
Highlighter Region Module¶
- class HighlighterRegion.HighlighterRegion(parent)[source]¶
Bases:
object- addThreshold()[source]¶
Create a new row with read-only dropdowns for Atom 1, Atom 2, Bond order, and an entry for the numeric threshold.
- add_widgets()[source]¶
Adds widgets (checkboxes, labels, and entry fields) for atom and bond highlighting.
- check_for_atom_syntax(entry: str) bool[source]¶
Checks if the atom entry follows the correct syntax: ElementSymbol + two-digit number.
- Parameters:
entry (str) – The atom entry to validate (e.g., “C01”, “H02”).
- Returns:
True if the entry is valid, False otherwise.
- Return type:
bool
- check_for_bond_syntax(entry: str) bool[source]¶
Checks if the bond entry follows the correct syntax (e.g., “C01-C02”; “C03=C04”).
- Parameters:
entry (str) – The bond entry to validate.
- Returns:
True if the bond entry follows the correct syntax, False otherwise.
- Return type:
bool
- get_custom_thresholds()[source]¶
- Returns a list of dicts:
- {
“atom_pair”: (“Atom1Symbol”, “Atom2Symbol”), # canonicalized (sorted) “bond_order”: int, # 1, 2, or 3 “threshold”: float # Å
}
Skips incomplete/invalid rows.
- on_enable_editing(event, tk_textbox, tk_checkbox_variable)[source]¶
Enables editing for the clicked entry box if the associated checkbox is checked.
- Parameters:
event (tk.Event) – The event that triggered this function.
tk_textbox (tk.Entry) – The text entry widget to enable or disable.
tk_checkbox_variable (tk.BooleanVar) – The associated checkbox’s variable that determines the state.
- on_validate_atom_list(event=None)[source]¶
Handles validation when the atom entry loses focus or the Enter key is pressed.
- Parameters:
event (tk.Event, optional) – The event that triggered the validation. Default is None.
- Returns:
Returns “break” if Enter was pressed and input is invalid, otherwise None.
- Return type:
str | None
- on_validate_bond_entry(event=None, var=None, entry_widget=None)[source]¶
Handler for validating bond entries.
- Parameters:
event (tk.Event, optional) – The event that triggered the validation.
var (tk.StringVar) – The variable linked to the entry widget.
entry_widget (tk.Entry) – The entry widget to validate.
- Returns:
Returns “break” if Enter was pressed and input is invalid, otherwise None.
- Return type:
str | None
- reset_highlighter_options()[source]¶
Resets the highlighter options (e.g., disables widgets and clears input lists).
- setup_frame(parent)[source]¶
Sets up the frame for the highlighter region.
- Parameters:
parent (tk.Widget) – The parent widget to attach the frame to.
- toggleAtomHighlighter()[source]¶
Toggles the state of atom highlighting. Enables or disables the atom list entry. If the checkbox is checked, the atom list entry is enabled. If unchecked, it is disabled and cleared.
- toggleBondForcer()[source]¶
Toggles the possibility of forcing two atoms to be bonded in a specific way. Only works when there is only one input file. If the checkbox is checked, the bond force list entry is enabled. If unchecked, it is disabled and cleared.
- toggleBondHighlighter()[source]¶
Toggles the state of bond highlighting. Enables or disables the bond list entry. If the checkbox is checked, the bond list entry is enabled. If unchecked, it is disabled and cleared.
- toggleCustomThreshold()[source]¶
Toggles the ability to customize the threshold between two atoms and make it a type of bond.
- validate_atom_list(entry: str) bool[source]¶
Validates a comma-separated list of atom entries.
- Parameters:
entry (str) – A comma-separated string of atom entries to validate (e.g., “C01, H02”).
- Returns:
True if all entries are valid, False if any entry is invalid.
- Return type:
bool
- validate_bond_list(entry: str) bool[source]¶
Validates a semicolon-separated list of bond entries.
- Parameters:
entry (str) – A semicolon-separated string of bond entries to validate (e.g., “C01-C02; C03=C04”).
- Returns:
True if all bond entries are valid, False if any entry is invalid.
- Return type:
bool
Information Module¶
Input Region Module¶
Instructions Module¶
- class Instructions.Instructions[source]¶
Bases:
object- classmethod get(name)[source]¶
Retrieve a list of instructions by name.
- Parameters:
name – The key for the instruction set (e.g., ‘input’, ‘customization’).
- Returns:
A list of (text, tag) tuples or an empty list if not found.
- instructions = {'actions': [('Actions you can do:\n', 'bold'), ("17. Click on 'Reset' to reset everything to the default values.\n", 'normal'), ("18. Click on 'Convert!' to convert your input into the 3D file according to what you selected.\n", 'normal')], 'customization': [('Customization \n', 'bold'), ('5. Specify any bonds you would like to overwrite from the initial input file.\n', 'normal'), (' 5.1. These are the characters that represent different bond orders:\n', 'italic'), (" 5.1.1. Bond order 0.5: '_'\n", 'italic'), (" 5.1.2. Bond order 1: '-'\n", 'italic'), (" 5.1.3. Bond order 1.5: '%'\n", 'italic'), (" 5.1.4. Bond order 2: '='\n", 'italic'), (" 5.1.5. Bond order 3: '#'\n", 'italic'), (' 5.2. Type the bonds separated by semicolons like the example below:\n', 'normal'), (' C01-C02; C03=O04; O04_H27; H27_N09\n', 'code'), ("6. Check 'custom threshold' to bond atoms automatically whenever they fall within a set distance of each other, instead of (or in addition to) forcing individual bonds.\n", 'normal'), (" 6.1. Click 'add' to create a new rule: choose Atom 1, Atom 2, a bond order (0-3), and a distance threshold in Angstroms.\n", 'italic'), (' 6.2. Any pair of atoms of those two elements closer than the threshold will be bonded with that order. A bond order of 0 marks that pair as explicitly not bonded.\n', 'italic'), (" 6.3. Click 'add' again for more rules, or 'remove' to delete the most recently added one.\n", 'italic'), ('7. Identify any atoms and/or bonds that you would like to highlight in the final 3D model.\n', 'normal'), (' 7.1. Type the atoms separated by commas like the example below:\n', 'normal'), (' O04, N09\n', 'code'), (' 7.2. Type the bonds separated by semicolons like the example below:\n', 'normal'), (' O04_H27; H27_N09\n', 'code')], 'input': [('Input \n', 'bold'), ('1. The path to the Blender executable should be found automatically in the default installation folder.\n', 'normal'), (" 1.1. If not found: click 'search' next to the Blender path and navigate to the folder that contains blender.exe (Windows) or Blender.app (macOS).\n", 'italic'), ('2. Select the input file(s) that you want to convert.\n', 'normal'), (" 2.1. The input can be '.com', '.xyz', '.mol2', or '.vasp'.\n", 'italic'), (" 2.2. If you select '.com', make sure the file includes connectivity after the atom coordinates.\n", 'italic'), (" 2.3. If you select '.xyz' or '.mol2', bonds will be rendered based on average covalent bond lengths.\n", 'italic'), (" 2.4. If you select '.vasp', the 'Unit Cell' tab becomes available, where you can add unit cell growth, Miller planes, and coordination polyhedra.\n", 'italic'), (' 2.5. You can select more than one input file at a time, but all of them must share the same extension.\n', 'italic'), ("3. Choose a model type: 'Ball-and-Stick', 'Stick-only', or 'Van-der-Waals'.\n", 'normal'), ("4. If you select the 'is animation' box, make sure to follow these rules:\n", 'normal'), (" 4.1. If the input is '.com':\n", 'italic'), (" 4.1.1. In the 'input file(s)' section, select two or more '.com' files.\n", 'italic'), (' 4.1.2. All the input files must share the same atom identity, order and connectivity.\n', 'italic'), (" 4.2. If the input is '.xyz':\n", 'italic'), (" 4.2.1. All the cartesian coordinates must be located in the same '.xyz' file.\n", 'italic'), (' 4.2.2. Make sure the file is a trajectory containing multiple frames, with the same number, identity, and order of atoms in each.\n', 'italic'), (" 4.3. At the moment, there is no animation possible with '.mol2' or '.vasp' files.\n", 'italic')], 'ions': [('Regarding Ions\n', 'bold'), ('8. If the molecule to be rendered has ions, select the checkbox specifying that it has.\n', 'normal'), ("9. Click on 'add'.\n", 'normal'), (' 9.1. From the drop down menu select the element, and its charge/oxidation state.\n', 'italic'), (' 9.2. Select the coordination number for the ion.\n', 'italic'), (" 9.3. If there is more than one ion, click on 'add' again.\n", 'italic'), (" 9.4. Click 'remove' to delete the most recently added ion.\n", 'italic')], 'output': [('About the output\n', 'bold'), ('15. Select the output path for the 3D object to be rendered.\n', 'normal'), ("16. Select the file type for the 3D object: '.fbx', '.obj', '.dae', '.glb', '.stl', or '.usdz'.\n", 'normal'), (" 16.1. If you chose 'is animation' in the input tab, you can only render as '.fbx', '.glb', or '.usdz'.\n", 'italic'), (' 16.2. ', 'italic'), ('known issue: ', 'bold'), ('at the moment if you export as glb, each bond and atom will have a separate animation instead of all animations being merged as one. If you want to avoid this, export as fbx.\n', 'italic'), (' 16.3. If you want to export as glb, you would have to use glTF Transform (a separate tool, not included in TheorChem2Blender) to merge the animations.\n', 'italic')], 'unit_cell': [('Unit Cell \n', 'bold'), ("This tab only becomes available when your input type (in the Input tab) is set to '.vasp'.\n", 'italic'), ("10. If you defined cell boundaries in your input using a bond order of 0.5, check 'unit cell boundaries' to render them as solid unit cell edges.\n", 'normal'), ("11. Check 'allow unit cell growth' to render one or more duplicated copies of the unit cell.\n", 'normal'), (" 11.1. Click 'add cell growth', then choose how many times to repeat the cell along x, y, and z (1-5 each).\n", 'italic'), (' 11.2. You can add more than one growth row to render several different supercell sizes in the same batch.\n', 'italic'), ("12. Check 'allow Miller indices' to render crystallographic planes.\n", 'normal'), (" 12.1. Click 'add plane', then choose h, k, and l (each from -9 to 9).\n", 'italic'), (' 12.2. Every Miller plane you add is rendered on every unit cell growth size defined above.\n', 'italic'), ("13. Check 'build polyhedra' to draw coordination polyhedra around selected center atoms.\n", 'normal'), (" 13.1. Click 'add center', then choose the element that will act as the polyhedron center.\n", 'italic'), (' 13.2. Any atom of that element with three or more bonded neighbors will get a convex-hull polyhedron built around it.\n', 'italic'), ("14. Click 'Clear' to reset unit cell boundaries, growth, Miller planes, and polyhedra back to empty.\n", 'normal')]}¶
Ion Conventions Module¶
Ionic Module¶
Ion Region Module¶
- class IonRegion.IonRegion(parent)[source]¶
Bases:
objectSection of the app that receives information about possible ions present
- create_widgets(parent)[source]¶
Create all widgets and frames for the ion information section.
These all live directly in self.frame - no inner canvas/scrollbar. The tab’s own content container (see TheorChem2Blender.py) already provides scrolling if this ever grows taller than the space available, so a second, nested scrollable area here was redundant.
- Parameters:
parent (tk.Widget) – The parent widget that will contain this section.
Labeled Combo Row Module¶
- class LabeledComboRow.LabeledComboRow(parent, input_label_list, option_ranges, group_label=None, group_tooltip=None, field_tooltips=None, bg='#e0e0e0', fg='black', padx=2, pady=2, combobox_width=5)[source]¶
Bases:
objectBuilds one row of labeled dropdowns: an optional group label on top, followed by pairs of small field-labels and comboboxes.
This is a small reusable building block used by UnitCellRegion.py in two ways:
A single instance for “unit cell growth” (x, y, z)
One instance per row for each Miller plane (h, k, l), created and destroyed dynamically by the “add plane” / “Remove Last” / “Remove All” buttons.
Output Region Module¶
- class OutputRegion.OutputRegion(parent, initial_dir)[source]¶
Bases:
objectSection of the app that selects the output path for the converted file(s)
- restrict_output_types_for_animation(is_animation)[source]¶
Updates the list of selectable output file types based on whether animation is enabled.
- Parameters:
is_animation (bool) – Indicates whether the animation mode is active.
- Behavior:
Clears the current dropdown menu options.
Populates the menu with the appropriate list of file types.
Resets the selected output type if the current selection is no longer valid.
Proportional Container Module¶
- class ProportionalContainer.ProportionalContainer(parent, row, weight, enable_scrolling=False, bg='#e0e0e0')[source]¶
Bases:
objectA container that always spans the full available width of its parent, and a height controlled entirely by a grid row weight - so it keeps the right proportions automatically whenever the window is resized, with no manual recalculating needed.
This is the building block behind “every tab has three containers”: an instructions container, a content container, and (shared across every tab, built separately - see ConsoleRegion) the console container. Each tab wraps its Information widget and its main region widget in one of these.
- Usage:
- container = ProportionalContainer(
parent=self.unit_cell_tab, row=1, weight=ScreenSizeManager.CONTENT_HEIGHT_WEIGHT, enable_scrolling=True
) self.unit_cell_region = UnitCellRegion(container.content_frame)
The weight isn’t a percentage by itself - it’s relative to the weights given to whatever else shares the same parent’s rows. See ScreenSizeManager for the actual weight constants used across the app (INFO_HEIGHT_WEIGHT, CONTENT_HEIGHT_WEIGHT, CONSOLE_HEIGHT_WEIGHT), chosen so they add up to 100 and read directly as percentages.
Repeatable Row Group Module¶
- class RepeatableRowGroup.RepeatableRowGroup(parent, row_factory, group_label=None, group_tooltip=None, add_button_text='add', remove_last_button_text='Remove Last', remove_all_button_text='Remove All', add_tooltip=None, remove_last_tooltip=None, remove_all_tooltip=None, bg='#e0e0e0', fg='black', start_enabled=True, row_spacing=1, enable_scrolling=False, max_height_fraction=0.2)[source]¶
Bases:
objectManages a labeled, repeatable list of rows: an optional header label, a container where rows stack vertically, and three buttons (add / remove last / remove all) that build and destroy rows on demand.
This class does not know what a “row” looks like on the inside - it just needs a row_factory function that builds one and hands it back. Any row object handed back must provide:
a .frame attribute (the widget to display)
a .destroy() method (to remove it from the screen)
a .get_values() method (used by get_row_values() below)
- This same class is used twice in UnitCellRegion.py:
Once for the list of unit cell growth rows (with row spacing and scrolling turned on, since that list can grow tall)
Once more, nested inside each growth row, for that row’s own list of Miller planes (left at its small default spacing, with scrolling turned off)
Screen Size Manager Module¶
- class ScreenSizeManager.ScreenSizeManager[source]¶
Bases:
objectReads the screen’s width and height once, right when the app starts, and makes those values available anywhere in the app afterward. Also the single place where every window-size-related tuning constant lives, so they’re easy to find and adjust later.
Why this exists: several regions (like UnitCellRegion’s scrollable growth list) need to know how big the screen is, but re-querying Tkinter for it in every widget is wasteful and easy to get wrong before the window is fully drawn. Instead, TheorChem2Blender.py calls initialize(root) exactly once, right after creating the root window, and every other module can just import this class and call its getters - no need to pass screen size through constructors.
- Usage:
# once, in TheorChem2Blender.py, right after self.root = tk.Tk() ScreenSizeManager.initialize(self.root) self.root.minsize(ScreenSizeManager.MIN_WIDTH, ScreenSizeManager.MIN_HEIGHT)
# anywhere else in the app from gui.ScreenSizeManager import ScreenSizeManager max_height = ScreenSizeManager.get_screen_height() * 0.2
- CONSOLE_HEIGHT_WEIGHT = 25¶
- CONTENT_HEIGHT_WEIGHT = 71¶
- INFO_HEIGHT_WEIGHT = 4¶
- MIN_HEIGHT = 600¶
- MIN_WIDTH = 800¶
- classmethod initialize(root)[source]¶
Reads and caches the screen’s width and height, in pixels.
Must be called once, before any code calls get_screen_width() or get_screen_height(). Safe to call again later (e.g. if the app ever needs to support moving between monitors), which simply refreshes the cached values.
- Parameters:
root – The Tk root window, used only to query the screen size.
Selected Ion Module¶
- class SelectedIon.SelectedIon(parent, row_number, column_number)[source]¶
Bases:
objectIon data widget that contains the information for one ion. This widget allows the user to select an element, specify its charge, and coordination number based on predefined ionic radii data.
Text Redirector Module¶
- class TextRedirector.TextRedirector(widget, tag='stdout', log_path=None, console_region=None)[source]¶
Bases:
objectSends print()/traceback output to the Console tab’s Text widget, and - when a log_path is given - also appends it to output.log.
That log file is what lets Blender’s own print() statements reach the same console: Blender runs as a separate OS process (see TheorChem2Blender._run_blender_subprocess), so its output is invisible to this redirect and instead gets written straight to output.log by the OS. ConsoleRegion.poll_log_file() tails that file for content this class didn’t already insert directly - see console_region below.
Unit Cell Region Module¶
- class UnitCellRegion.UnitCellRegion(parent)[source]¶
Bases:
objectSection of the app that customizes information about crystals and their unit cells
- get_miller_indices()[source]¶
Returns a list of [h, k, l] Miller planes the user has added, e.g. [[1, 0, 0], [1, 1, 1]]. An empty list means no Miller planes were requested. Independent from get_unit_cell_repeats() - the two are no longer linked.
NOTE: this used to return a single {“h”:.., “k”:.., “l”:..} value. TheorChem2Blender.py’s callers still expect the old single-value shape and have not been updated yet - tracked as a follow-up task, same as get_unit_cell_repeats() above.
- get_polyhedra_centers()[source]¶
Returns the list of selected center element types if polyhedra building is enabled and at least one center is specified.
- Returns:
(list) Element symbols, e.g. [‘V’, ‘Fe’], or empty list.
- get_unit_cell_repeats()[source]¶
Returns a list of [x, y, z] unit cell growth sizes the user has added, e.g. [[2, 2, 2], [3, 3, 3]]. An empty list means no growth was requested.
NOTE: this used to return a single [x, y, z] value. TheorChem2Blender.py’s callers still expect the old single-value shape and have not been updated yet - that update, plus the matching changes in scripts/, is tracked as a follow-up task.
- growth_activator()[source]¶
Enable or disable the unit cell growth controls based on the checkbox state.