ase2sprkkr-gui 0.2.0b1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ase2sprkkr_gui-0.2.0b1/PKG-INFO +41 -0
- ase2sprkkr_gui-0.2.0b1/README.md +25 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/__init__.py +1 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/ase/__init__.py +0 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/ase/element_assignment.py +424 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/ase/utils.py +42 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/assets/icons/COPYING-ICONS +209 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/assets/icons/README.md +19 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/assets/icons/bulk_crystal.png +0 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/assets/icons/database.svg +1 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/assets/icons/labplot-xy-interpolation-curve.svg +17 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/assets/icons/run-build-clean.svg +14 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/assets/icons/settings-cog.svg +4 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/assets/icons/sprkkr-orbital.svg +150 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/assets/icons/structure_interface.png +0 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/assets/icons/surface_2d.svg +1 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/assets/icons/system-run.svg +14 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/assets/structures/ITXC_structure.dat +446 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/assets/structures/README.md +10 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/cli/__init__.py +1 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/cli/gui.py +15 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/__init__.py +1 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/application/__init__.py +1 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/application/atomic_io.py +77 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/application/attached_run_execution.py +48 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/application/config.py +11 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/application/console_interrupt.py +74 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/application/execution_cancellation.py +103 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/application/execution_profiles.py +173 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/application/historical_state.py +114 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/application/imported_project_results.py +85 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/application/operation_results.py +38 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/application/persistent_jobs.py +875 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/application/potential_version.py +7 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/application/recent_files.py +181 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/application/result_action_policy.py +165 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/application/result_artifacts.py +69 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/application/result_cache.py +101 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/application/result_contract.py +16 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/application/result_files.py +7 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/application/result_loading.py +185 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/application/result_presentation.py +326 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/application/result_store.py +805 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/application/run_file_deletion.py +331 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/application/settings.py +67 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/application/shell_history.py +146 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/application/sprkkr_execution.py +157 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/application/structure_snapshot.py +102 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/application/viewers.py +50 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/application/window_geometry.py +352 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/application/workspace.py +222 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/application/workspace_controller.py +967 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/controllers/__init__.py +1 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/controllers/persistent_jobs.py +771 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/dialogs/__init__.py +1 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/dialogs/_tree_base.py +102 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/dialogs/assign_results.py +135 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/dialogs/attached_run.py +83 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/dialogs/calculation_history.py +34 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/dialogs/delete_run_record.py +442 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/dialogs/expert_input.py +176 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/dialogs/guided_input.py +431 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/dialogs/input_file.py +143 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/dialogs/main_window.py +515 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/dialogs/object_view.py +198 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/dialogs/profiles.py +486 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/dialogs/project_browser.py +675 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/dialogs/project_edit.py +59 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/dialogs/run_calculation.py +307 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/dialogs/run_conflict.py +247 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/dialogs/run_monitor.py +260 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/dialogs/settings.py +109 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/dialogs/structures/__init__.py +1 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/dialogs/structures/build_2d.py +342 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/dialogs/structures/database.py +191 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/dialogs/structures/element_assignment.py +342 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/dialogs/structures/element_selector.py +345 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/dialogs/structures/empty_spheres.py +157 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/dialogs/structures/online_database.py +878 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/dialogs/structures/shell.py +177 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/dialogs/structures/source.py +255 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/dialogs/structures/spacegroup_selector.py +838 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/dialogs/structures/transforms.py +417 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/dialogs/workflow_window.py +389 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/flows/__init__.py +1 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/flows/calculation.py +412 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/flows/files.py +464 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/flows/input_editing.py +106 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/flows/input_parameters.py +101 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/flows/structure_candidates.py +146 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/flows/structures.py +373 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/flows/visualization.py +107 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/input_parameters/__init__.py +1 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/input_parameters/bindings.py +46 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/input_parameters/bsf.py +58 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/input_parameters/dataset.py +75 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/input_parameters/defaults.py +12 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/input_parameters/energy.py +67 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/input_parameters/expert_fields.py +87 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/input_parameters/field_binding.py +595 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/input_parameters/keyword_choices.py +46 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/input_parameters/session.py +465 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/input_parameters/single_site_contour.py +47 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/input_parameters/specs/__init__.py +1 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/input_parameters/specs/arpes.py +75 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/input_parameters/specs/bsf.py +132 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/input_parameters/specs/dos.py +29 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/input_parameters/specs/jxc.py +31 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/input_parameters/specs/scf.py +124 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/input_parameters/specs/schema.py +177 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/input_parameters/specs/shared.py +289 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/input_parameters/specs/xas.py +39 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/input_parameters/tasks.py +161 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/input_parameters/tooltips.py +60 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/input_parameters/validation.py +43 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/misc/__init__.py +1 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/misc/colors.py +32 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/misc/dialog_flow.py +52 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/misc/icons.py +17 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/misc/modal_task.py +131 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/misc/resources.py +8 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/misc/structure_wait.py +22 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/misc/tables.py +13 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/plots/__init__.py +1 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/plots/lattice.py +344 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/presentation.py +18 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/presenters/__init__.py +1 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/presenters/result_actions.py +103 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/recent_presentation.py +128 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/style.py +195 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/viewers/__init__.py +1 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/viewers/ase_gui.py +123 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/__init__.py +1 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/action_card.py +110 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/browser_panel.py +42 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/calculation_setup.py +184 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/double_edit.py +19 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/execution_profiles.py +406 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/expert_side_panel.py +54 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/input_parameters/__init__.py +1 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/input_parameters/bsf.py +488 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/input_parameters/commit.py +83 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/input_parameters/common.py +96 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/input_parameters/dataset.py +84 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/input_parameters/energy.py +110 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/input_parameters/expert_tree.py +378 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/input_parameters/expert_tree_renderer.py +860 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/input_parameters/expert_tree_runtime.py +225 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/input_parameters/expert_tree_structure.py +212 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/input_parameters/form.py +502 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/input_parameters/kpath.py +61 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/input_parameters/modal_editor.py +83 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/input_parameters/parameter.py +153 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/input_parameters/registry.py +92 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/input_parameters/relativistic_scaling.py +188 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/input_parameters/scalar.py +427 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/input_parameters/value_editor.py +61 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/nullable_spinbox.py +90 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/numeric_table.py +69 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/optimade_filters.py +264 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/persistent_jobs.py +785 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/recent_launcher.py +93 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/result_actions.py +456 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/settings/__init__.py +5 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/settings/general.py +113 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/settings/run_configurations.py +189 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/structure_overview.py +444 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/structures/__init__.py +1 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/structures/element_assignment.py +406 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/structures/structure_pane.py +161 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/structures/wyckoff_position.py +154 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/units.py +43 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/widgets/workflow_actions.py +158 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/workflow/__init__.py +1 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/workflow/model.py +188 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/workflow/planner.py +345 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/workflow/scf_status.py +66 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/gui/workspace_semantics.py +14 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/main.py +435 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/online_databases/__init__.py +39 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/online_databases/models.py +198 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/online_databases/optimade.py +1138 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/online_databases/provider.py +60 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/physics/__init__.py +0 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/physics/composition.py +161 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/physics/lattice.py +76 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/physics/pyxtal_utils.py +117 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui/physics/structure_database.py +198 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui.egg-info/PKG-INFO +41 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui.egg-info/SOURCES.txt +346 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui.egg-info/dependency_links.txt +1 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui.egg-info/entry_points.txt +5 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui.egg-info/requires.txt +9 -0
- ase2sprkkr_gui-0.2.0b1/ase2sprkkr_gui.egg-info/top_level.txt +1 -0
- ase2sprkkr_gui-0.2.0b1/pyproject.toml +45 -0
- ase2sprkkr_gui-0.2.0b1/setup.cfg +4 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_active_project.py +180 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_application_icon.py +59 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_ase_gui_readiness.py +112 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_atomic_io.py +51 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_attached_run_execution.py +107 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_backend_persistence_contract.py +180 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_backend_public_imports.py +33 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_bsf_calculation_setup.py +381 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_build2d_recent_files_di.py +144 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_calculation_concurrency.py +390 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_calculation_dialog_geometry.py +36 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_calculation_history.py +320 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_calculation_profile_flow.py +462 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_calculation_structure_cleanliness.py +137 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_calculation_worker_isolation.py +71 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_clearing_inputs.py +162 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_cli_plugin.py +58 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_console_interrupt.py +138 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_continue_output.py +130 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_current_potential_state_reuse.py +209 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_dataset_naming.py +145 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_dialog_flow.py +54 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_editor_commit_boundaries.py +77 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_element_assignment_dialog.py +81 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_element_assignment_state.py +186 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_empty_spheres_dialog.py +43 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_empty_spheres_workflow.py +225 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_energy_editor.py +199 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_exception_boundaries.py +306 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_execution_dialog_projects.py +769 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_execution_profile_application.py +175 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_execution_profile_architecture.py +26 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_execution_profiles.py +85 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_expert_changed_state_errors.py +48 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_expert_field_specs.py +38 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_expert_shared_editors.py +535 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_expert_tree_deferred_updates.py +33 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_expert_tree_rendering.py +350 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_expert_tree_runtime.py +129 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_expert_tree_runtime_lifecycle.py +45 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_expert_tree_structure.py +134 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_field_binding.py +440 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_file_flows.py +154 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_file_version.py +50 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_finalization_failed_actions.py +91 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_generation_model.py +314 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_gui_architecture.py +399 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_gui_composition.py +97 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_gui_data_integrity.py +441 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_guided_explicit_commit.py +50 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_guided_form_spec_validation.py +52 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_guided_history_lifetime.py +22 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_guided_parameter_tooltips.py +72 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_guided_presentation_rules.py +76 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_guided_task_availability.py +179 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_guided_validation_navigation.py +76 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_imported_results_projects.py +146 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_input_file_editor.py +147 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_input_file_explicit_commit.py +95 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_input_parameter_flows.py +112 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_input_parameters_session.py +630 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_input_parameters_session_comparison.py +25 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_input_parameters_session_dormant.py +63 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_input_parameters_session_read_contract.py +17 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_input_parameters_session_unification.py +225 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_keyword_choices.py +297 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_kkrunner_wip2_contract.py +60 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_kpath_qt_integration.py +140 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_kpath_table.py +169 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_lattice_transforms.py +71 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_main_window_view_decomposition.py +225 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_modal_task.py +33 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_mpi_warning_submit.py +57 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_online_database_live.py +187 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_online_database_provider.py +448 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_online_structure_dialog.py +286 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_operation_capabilities.py +201 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_operation_result_identity.py +39 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_package_identity.py +26 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_persistent_finalization_recovery.py +72 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_persistent_history_entry.py +161 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_persistent_jobs.py +290 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_persistent_jobs_architecture.py +71 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_persistent_jobs_controller.py +943 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_persistent_result_application.py +72 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_persistent_result_files.py +111 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_persistent_result_preload.py +176 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_persistent_result_reference.py +64 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_persistent_submitting_recovery.py +86 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_potential_authority.py +327 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_presentation.py +104 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_profile_editor_ui.py +388 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_project_browser.py +768 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_project_execution_workflow.py +69 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_projected_editor_bindings.py +66 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_python39_compat.py +74 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_recent_files.py +132 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_recent_menu_policy.py +129 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_recompute_task_routing.py +176 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_restart_scf_execution.py +103 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_result_actions_history.py +125 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_result_actions_widget.py +275 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_result_cache.py +44 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_result_file_provenance.py +168 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_result_lineage_fast_forward.py +49 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_result_loading.py +224 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_result_potential_projection.py +228 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_result_refresh_ownership.py +48 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_result_selection_intent.py +59 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_result_state_capability.py +118 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_result_store_history.py +298 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_result_store_invariants.py +318 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_result_store_lightweight_provenance.py +94 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_run_cancellation.py +61 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_run_conflict_dialog.py +361 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_run_file_deletion.py +557 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_run_identification.py +178 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_run_monitor.py +166 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_runtime_public_api.py +19 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_scalar_validation_boundary.py +35 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_scaling_editor.py +95 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_settings.py +247 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_shared_use_cases.py +259 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_sprkkr_execution.py +289 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_structure_candidates.py +208 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_structure_composition.py +133 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_structure_continuation.py +284 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_structure_database.py +75 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_structure_database_dialog.py +119 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_structure_pane.py +36 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_structure_shell.py +271 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_structure_shell_history.py +205 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_structure_type_icons.py +49 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_task_capabilities.py +164 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_thread_boundaries.py +43 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_transactional_structure_edit.py +33 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_use_result_state_invariants.py +131 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_values_equal.py +12 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_viewer_handling.py +220 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_visualization_flow.py +116 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_window_geometry.py +119 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_workflow_actions_widget.py +240 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_workflow_formula.py +40 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_workflow_planner.py +357 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_workflow_recent_integration.py +39 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_workflow_scf_status.py +37 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_workflow_task_identity.py +29 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_workflow_window.py +393 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_workspace_controller_clear_structure.py +27 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_workspace_controller_reads.py +27 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_workspace_restarted.py +153 -0
- ase2sprkkr_gui-0.2.0b1/tests/test_workspace_state.py +104 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ase2sprkkr-gui
|
|
3
|
+
Version: 0.2.0b1
|
|
4
|
+
Summary: PyQt6 GUI for building/editing ASE structures and running SPR-KKR via ase2sprkkr.
|
|
5
|
+
Requires-Python: >=3.9
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: kkrunner<0.3,>=0.2.0b2
|
|
8
|
+
Requires-Dist: PyQt6
|
|
9
|
+
Requires-Dist: qonsole<4,>=3.3
|
|
10
|
+
Requires-Dist: matplotlib
|
|
11
|
+
Requires-Dist: numpy
|
|
12
|
+
Requires-Dist: ase
|
|
13
|
+
Requires-Dist: platformdirs
|
|
14
|
+
Requires-Dist: pyxtal
|
|
15
|
+
Requires-Dist: ase2sprkkr<5,>=4.0.0b3
|
|
16
|
+
|
|
17
|
+
# ASE2SPRKKR GUI
|
|
18
|
+
|
|
19
|
+
A PyQt6 desktop interface for creating and editing ASE structures, configuring
|
|
20
|
+
SPR-KKR calculations, and exploring calculation results through ASE2SPRKKR.
|
|
21
|
+
|
|
22
|
+
## Install
|
|
23
|
+
|
|
24
|
+
Install this beta alongside the matching released ASE2SPRKKR and KKRunner packages:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
python -m pip install --pre ase2sprkkr-gui
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Run
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
ase2sprkkr-gui
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The GUI requires the ASE2SPRKKR Python backend. Running actual SPR-KKR
|
|
37
|
+
calculations also requires a separately installed SPR-KKR executable.
|
|
38
|
+
|
|
39
|
+
## Development
|
|
40
|
+
|
|
41
|
+
Source: https://github.com/ase2sprkkr/ase2sprkkr-gui
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# ASE2SPRKKR GUI
|
|
2
|
+
|
|
3
|
+
A PyQt6 desktop interface for creating and editing ASE structures, configuring
|
|
4
|
+
SPR-KKR calculations, and exploring calculation results through ASE2SPRKKR.
|
|
5
|
+
|
|
6
|
+
## Install
|
|
7
|
+
|
|
8
|
+
Install this beta alongside the matching released ASE2SPRKKR and KKRunner packages:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
python -m pip install --pre ase2sprkkr-gui
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Run
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
ase2sprkkr-gui
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The GUI requires the ASE2SPRKKR Python backend. Running actual SPR-KKR
|
|
21
|
+
calculations also requires a separately installed SPR-KKR executable.
|
|
22
|
+
|
|
23
|
+
## Development
|
|
24
|
+
|
|
25
|
+
Source: https://github.com/ase2sprkkr/ase2sprkkr-gui
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Ase2sprkkr graphical interface for ASE and SPR-KKR workflows."""
|
|
File without changes
|
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
"""Qt-independent working model for assigning elements to structure sites."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
import re
|
|
6
|
+
from typing import Any, Iterable
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
from ase import Atoms
|
|
10
|
+
from ase.data import chemical_symbols
|
|
11
|
+
from ase2sprkkr import SPRKKRAtoms
|
|
12
|
+
from ase2sprkkr.sprkkr.atomic_types import AtomicType
|
|
13
|
+
from ase2sprkkr.sprkkr.sites import Site, SiteType
|
|
14
|
+
|
|
15
|
+
from ase2sprkkr_gui.ase.utils import labels_for_partitions, partition_by_kinds
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
_VALID_SYMBOLS = {
|
|
19
|
+
symbol for symbol in chemical_symbols if isinstance(symbol, str)
|
|
20
|
+
} | {"Vc"}
|
|
21
|
+
_OCCUPANCY_TOLERANCE = 1e-6
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass
|
|
25
|
+
class OccupancyEntry:
|
|
26
|
+
"""One editable component of a site's chemical occupation."""
|
|
27
|
+
|
|
28
|
+
symbol: str = ""
|
|
29
|
+
value: float = 1.0
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@dataclass
|
|
33
|
+
class AssignmentSite:
|
|
34
|
+
"""One independently editable group of equivalent fractional positions."""
|
|
35
|
+
|
|
36
|
+
label: str
|
|
37
|
+
positions: np.ndarray
|
|
38
|
+
origins: list[int | None]
|
|
39
|
+
occupancies: list[OccupancyEntry]
|
|
40
|
+
|
|
41
|
+
@property
|
|
42
|
+
def can_split(self) -> bool:
|
|
43
|
+
return len(self.positions) > 1
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class ElementAssignmentDraft:
|
|
47
|
+
"""Transactional edit buffer for the element-assignment dialog.
|
|
48
|
+
|
|
49
|
+
This deliberately is not another general material or structure model.
|
|
50
|
+
``Atoms``/``SPRKKRAtoms`` remain the authoritative accepted structures,
|
|
51
|
+
while this sidecar can represent dialog-only provenance, labels, grouping,
|
|
52
|
+
and temporarily incomplete occupancy without polluting or invalidating the
|
|
53
|
+
source object. :meth:`apply` materializes a valid structure only on OK.
|
|
54
|
+
|
|
55
|
+
``origins`` records which input atom, if any, supplied every position. It
|
|
56
|
+
replaces the former ambiguous combination of payload ``index`` and
|
|
57
|
+
``origin`` fields and remains aligned with ``positions`` after edits.
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
def __init__(self, atoms: Atoms):
|
|
61
|
+
self._source_atoms = atoms
|
|
62
|
+
self._cell = np.asarray(atoms.cell, dtype=float).copy()
|
|
63
|
+
self.sites = self._sites_from_atoms(atoms)
|
|
64
|
+
self._original_partition = tuple(
|
|
65
|
+
tuple(site.origins) for site in self.sites
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def cell(self) -> np.ndarray:
|
|
70
|
+
"""Return a copy of the currently edited lattice vectors."""
|
|
71
|
+
return self._cell.copy()
|
|
72
|
+
|
|
73
|
+
def set_cell_component(self, row: int, column: int, value: float) -> None:
|
|
74
|
+
self._cell[row, column] = float(value)
|
|
75
|
+
|
|
76
|
+
def split_site(self, site: AssignmentSite) -> tuple[AssignmentSite, ...]:
|
|
77
|
+
"""Replace a multi-position site by uniquely labelled single sites."""
|
|
78
|
+
site_index = self._site_index(site)
|
|
79
|
+
if not site.can_split:
|
|
80
|
+
return (site,)
|
|
81
|
+
|
|
82
|
+
used_labels = {candidate.label for candidate in self.sites}
|
|
83
|
+
replacements: list[AssignmentSite] = []
|
|
84
|
+
for position_index, position in enumerate(site.positions):
|
|
85
|
+
template = f"{site.label}.{position_index + 1}"
|
|
86
|
+
label = self._unique_label(template, used_labels)
|
|
87
|
+
used_labels.add(label)
|
|
88
|
+
replacements.append(
|
|
89
|
+
AssignmentSite(
|
|
90
|
+
label=label,
|
|
91
|
+
positions=np.asarray(position, dtype=float).reshape(1, 3),
|
|
92
|
+
origins=[site.origins[position_index]],
|
|
93
|
+
occupancies=self._copy_occupancies(site.occupancies),
|
|
94
|
+
)
|
|
95
|
+
)
|
|
96
|
+
self.sites[site_index:site_index + 1] = replacements
|
|
97
|
+
return tuple(replacements)
|
|
98
|
+
|
|
99
|
+
def add_position(self, site: AssignmentSite) -> int:
|
|
100
|
+
"""Append a position, duplicating the last coordinates when present."""
|
|
101
|
+
self._site_index(site)
|
|
102
|
+
if len(site.positions):
|
|
103
|
+
position = site.positions[-1].copy()
|
|
104
|
+
site.positions = np.vstack((site.positions, position))
|
|
105
|
+
else:
|
|
106
|
+
site.positions = np.zeros((1, 3), dtype=float)
|
|
107
|
+
site.origins.append(None)
|
|
108
|
+
return len(site.positions) - 1
|
|
109
|
+
|
|
110
|
+
def remove_position(self, site: AssignmentSite, index: int) -> bool:
|
|
111
|
+
"""Remove a position while preserving the invariant of one per site."""
|
|
112
|
+
self._site_index(site)
|
|
113
|
+
if len(site.positions) <= 1:
|
|
114
|
+
return False
|
|
115
|
+
index = max(0, min(int(index), len(site.positions) - 1))
|
|
116
|
+
site.positions = np.delete(site.positions, index, axis=0)
|
|
117
|
+
del site.origins[index]
|
|
118
|
+
return True
|
|
119
|
+
|
|
120
|
+
def set_position_component(
|
|
121
|
+
self,
|
|
122
|
+
site: AssignmentSite,
|
|
123
|
+
position: int,
|
|
124
|
+
component: int,
|
|
125
|
+
value: float,
|
|
126
|
+
) -> None:
|
|
127
|
+
self._site_index(site)
|
|
128
|
+
site.positions[position, component] = float(value)
|
|
129
|
+
|
|
130
|
+
def add_occupancy(
|
|
131
|
+
self,
|
|
132
|
+
site: AssignmentSite,
|
|
133
|
+
symbol: str = "",
|
|
134
|
+
value: float = 1.0,
|
|
135
|
+
) -> OccupancyEntry:
|
|
136
|
+
self._site_index(site)
|
|
137
|
+
entry = OccupancyEntry(symbol, float(value))
|
|
138
|
+
site.occupancies.append(entry)
|
|
139
|
+
return entry
|
|
140
|
+
|
|
141
|
+
def remove_occupancy(
|
|
142
|
+
self, site: AssignmentSite, entry: OccupancyEntry
|
|
143
|
+
) -> bool:
|
|
144
|
+
self._site_index(site)
|
|
145
|
+
if len(site.occupancies) <= 1:
|
|
146
|
+
return False
|
|
147
|
+
site.occupancies.remove(entry)
|
|
148
|
+
return True
|
|
149
|
+
|
|
150
|
+
def set_occupancy_symbol(
|
|
151
|
+
self, site: AssignmentSite, entry: OccupancyEntry, symbol: str
|
|
152
|
+
) -> None:
|
|
153
|
+
self._occupancy_index(site, entry)
|
|
154
|
+
entry.symbol = symbol.strip()
|
|
155
|
+
|
|
156
|
+
def set_occupancy_value(
|
|
157
|
+
self, site: AssignmentSite, entry: OccupancyEntry, value: float
|
|
158
|
+
) -> None:
|
|
159
|
+
self._occupancy_index(site, entry)
|
|
160
|
+
entry.value = float(value)
|
|
161
|
+
|
|
162
|
+
def normalize_occupancy(self, site: AssignmentSite) -> None:
|
|
163
|
+
self._site_index(site)
|
|
164
|
+
total = self.occupancy_total(site)
|
|
165
|
+
if total == 0.0:
|
|
166
|
+
return
|
|
167
|
+
for entry in site.occupancies:
|
|
168
|
+
entry.value /= total
|
|
169
|
+
|
|
170
|
+
@staticmethod
|
|
171
|
+
def occupancy_total(site: AssignmentSite) -> float:
|
|
172
|
+
return sum(entry.value for entry in site.occupancies)
|
|
173
|
+
|
|
174
|
+
@classmethod
|
|
175
|
+
def occupancy_is_overfull(cls, site: AssignmentSite) -> bool:
|
|
176
|
+
return cls.occupancy_total(site) > 1.0 + _OCCUPANCY_TOLERANCE
|
|
177
|
+
|
|
178
|
+
@staticmethod
|
|
179
|
+
def symbol_is_valid(symbol: str) -> bool:
|
|
180
|
+
return symbol in _VALID_SYMBOLS
|
|
181
|
+
|
|
182
|
+
def validation_errors(self, site: AssignmentSite) -> tuple[str, ...]:
|
|
183
|
+
"""Return all domain validation errors for one site."""
|
|
184
|
+
self._site_index(site)
|
|
185
|
+
errors: list[str] = []
|
|
186
|
+
if site.positions.ndim != 2 or site.positions.shape[1:] != (3,):
|
|
187
|
+
errors.append(f"Invalid positions for site {site.label}")
|
|
188
|
+
elif not len(site.positions):
|
|
189
|
+
errors.append(f"Site {site.label} requires a position")
|
|
190
|
+
if len(site.origins) != len(site.positions):
|
|
191
|
+
errors.append(f"Position origins are inconsistent for site {site.label}")
|
|
192
|
+
nonempty = [entry for entry in site.occupancies if entry.symbol]
|
|
193
|
+
invalid = [
|
|
194
|
+
entry.symbol
|
|
195
|
+
for entry in nonempty
|
|
196
|
+
if not self.symbol_is_valid(entry.symbol)
|
|
197
|
+
]
|
|
198
|
+
if invalid:
|
|
199
|
+
errors.append(
|
|
200
|
+
f"Invalid element for site {site.label}: {', '.join(invalid)}"
|
|
201
|
+
)
|
|
202
|
+
if not nonempty:
|
|
203
|
+
errors.append(f"Site {site.label} requires an element")
|
|
204
|
+
if any(
|
|
205
|
+
entry.value < 0.0 or entry.value > 1.0
|
|
206
|
+
for entry in site.occupancies
|
|
207
|
+
):
|
|
208
|
+
errors.append(
|
|
209
|
+
f"Occupation component is outside 0..1 for site {site.label}"
|
|
210
|
+
)
|
|
211
|
+
total = self.occupancy_total(site)
|
|
212
|
+
if total <= 0.0:
|
|
213
|
+
errors.append(f"Occupation must be positive for site {site.label}")
|
|
214
|
+
elif self.occupancy_is_overfull(site):
|
|
215
|
+
errors.append(f"Occupation too large for site {site.label}")
|
|
216
|
+
return tuple(errors)
|
|
217
|
+
|
|
218
|
+
def is_site_valid(self, site: AssignmentSite) -> bool:
|
|
219
|
+
return not self.validation_errors(site)
|
|
220
|
+
|
|
221
|
+
def is_valid(self) -> bool:
|
|
222
|
+
return bool(self.sites) and all(
|
|
223
|
+
self.is_site_valid(site) for site in self.sites
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
def apply(self, atoms: Atoms | None = None) -> Atoms:
|
|
227
|
+
"""Validate and materialize the draft into a detached structure."""
|
|
228
|
+
if not self.is_valid():
|
|
229
|
+
raise ValueError("Element assignment is not valid")
|
|
230
|
+
|
|
231
|
+
source = self._source_atoms
|
|
232
|
+
if atoms is None or atoms is source:
|
|
233
|
+
atoms = source.copy()
|
|
234
|
+
changed = self._partition_changed()
|
|
235
|
+
|
|
236
|
+
if changed:
|
|
237
|
+
materialization_source = atoms
|
|
238
|
+
rebuilt: Atoms | None = None
|
|
239
|
+
for site in self.sites:
|
|
240
|
+
if all(origin is not None for origin in site.origins):
|
|
241
|
+
indices = [int(origin) for origin in site.origins]
|
|
242
|
+
part = materialization_source[indices]
|
|
243
|
+
else:
|
|
244
|
+
part = self._rebuilt_site(materialization_source, site)
|
|
245
|
+
rebuilt = part if rebuilt is None else rebuilt + part
|
|
246
|
+
atoms = rebuilt if rebuilt is not None else Atoms(cell=self._cell)
|
|
247
|
+
|
|
248
|
+
positions: list[np.ndarray] = []
|
|
249
|
+
kinds: list[int] = []
|
|
250
|
+
symbols: list[str] = []
|
|
251
|
+
labels: list[str] = []
|
|
252
|
+
occupancy: dict[str, dict[Any, float]] = {}
|
|
253
|
+
for kind, site in enumerate(self.sites):
|
|
254
|
+
count = len(site.positions)
|
|
255
|
+
positions.append(site.positions @ self._cell)
|
|
256
|
+
kinds.extend([kind] * count)
|
|
257
|
+
site_occupancy = self._occupancy_mapping(site.occupancies)
|
|
258
|
+
occupancy[str(kind)] = site_occupancy
|
|
259
|
+
symbol = next(iter(site_occupancy), "X")
|
|
260
|
+
symbols.extend([getattr(symbol, "symbol", symbol)] * count)
|
|
261
|
+
labels.extend(
|
|
262
|
+
f"{site.label}.{position + 1}"
|
|
263
|
+
for position in range(count)
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
atoms.cell = self._cell
|
|
267
|
+
atoms.symbols = symbols
|
|
268
|
+
atoms.set_array("spacegroup_kinds", np.asarray(kinds, dtype=int))
|
|
269
|
+
atoms.set_array("labels", np.asarray(labels, dtype=object))
|
|
270
|
+
atoms.positions = np.vstack(positions)
|
|
271
|
+
atoms.info["occupancy"] = occupancy
|
|
272
|
+
if isinstance(source, SPRKKRAtoms):
|
|
273
|
+
if not isinstance(atoms, SPRKKRAtoms):
|
|
274
|
+
atoms = SPRKKRAtoms.promote_ase_atoms(
|
|
275
|
+
atoms, symmetry=False, update_info=False
|
|
276
|
+
)
|
|
277
|
+
self._apply_sprkkr_sites(atoms)
|
|
278
|
+
return atoms
|
|
279
|
+
|
|
280
|
+
def _apply_sprkkr_sites(self, atoms: SPRKKRAtoms) -> None:
|
|
281
|
+
"""Materialize site groups while retaining origin SiteType data."""
|
|
282
|
+
source_sites = self._source_atoms.sites
|
|
283
|
+
result_sites: list[Site] = []
|
|
284
|
+
for draft_site in self.sites:
|
|
285
|
+
occupation = self._occupancy_mapping(draft_site.occupancies)
|
|
286
|
+
origin = next(
|
|
287
|
+
(item for item in draft_site.origins if item is not None),
|
|
288
|
+
None,
|
|
289
|
+
)
|
|
290
|
+
if origin is None:
|
|
291
|
+
site_type = SiteType(atoms, occupation)
|
|
292
|
+
else:
|
|
293
|
+
site_type = source_sites[origin].site_type.copy(atoms=atoms)
|
|
294
|
+
site_type.occupation.set(
|
|
295
|
+
self._occupation_with_preserved_types(
|
|
296
|
+
site_type, occupation
|
|
297
|
+
)
|
|
298
|
+
)
|
|
299
|
+
result_sites.extend(
|
|
300
|
+
Site(site_type) for _position in draft_site.positions
|
|
301
|
+
)
|
|
302
|
+
atoms.set_sites(
|
|
303
|
+
np.asarray(result_sites, dtype=object),
|
|
304
|
+
spacegroup_info=False,
|
|
305
|
+
update=True,
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
@staticmethod
|
|
309
|
+
def _occupation_with_preserved_types(
|
|
310
|
+
site_type: SiteType,
|
|
311
|
+
occupation: dict[Any, float],
|
|
312
|
+
) -> dict[Any, float]:
|
|
313
|
+
"""Reuse matching AtomicTypes so their SPR-KKR data survive editing."""
|
|
314
|
+
available: dict[str, list[AtomicType]] = {}
|
|
315
|
+
for atomic_type in site_type.occupation:
|
|
316
|
+
available.setdefault(atomic_type.symbol, []).append(atomic_type)
|
|
317
|
+
result: dict[Any, float] = {}
|
|
318
|
+
for key, value in occupation.items():
|
|
319
|
+
symbol = getattr(key, "symbol", str(key))
|
|
320
|
+
candidates = available.get(symbol, [])
|
|
321
|
+
preserved = candidates.pop(0) if candidates else key
|
|
322
|
+
result[preserved] = value
|
|
323
|
+
return result
|
|
324
|
+
|
|
325
|
+
def _rebuilt_site(self, source: Atoms, site: AssignmentSite) -> Atoms:
|
|
326
|
+
"""Rebuild an edited site while retaining data of sourced atoms."""
|
|
327
|
+
result: Atoms | None = None
|
|
328
|
+
for position, origin in zip(site.positions, site.origins):
|
|
329
|
+
if origin is None:
|
|
330
|
+
atom = Atoms(
|
|
331
|
+
positions=[position], cell=self._cell, pbc=True
|
|
332
|
+
)
|
|
333
|
+
else:
|
|
334
|
+
atom = source[[origin]]
|
|
335
|
+
result = atom if result is None else result + atom
|
|
336
|
+
return result if result is not None else Atoms(cell=self._cell)
|
|
337
|
+
|
|
338
|
+
def _partition_changed(self) -> bool:
|
|
339
|
+
current = tuple(tuple(site.origins) for site in self.sites)
|
|
340
|
+
return current != self._original_partition or any(
|
|
341
|
+
origin is None for site in self.sites for origin in site.origins
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
def _site_index(self, site: AssignmentSite) -> int:
|
|
345
|
+
for index, candidate in enumerate(self.sites):
|
|
346
|
+
if candidate is site:
|
|
347
|
+
return index
|
|
348
|
+
raise ValueError("Site is not part of this assignment")
|
|
349
|
+
|
|
350
|
+
def _occupancy_index(
|
|
351
|
+
self, site: AssignmentSite, entry: OccupancyEntry
|
|
352
|
+
) -> int:
|
|
353
|
+
self._site_index(site)
|
|
354
|
+
for index, candidate in enumerate(site.occupancies):
|
|
355
|
+
if candidate is entry:
|
|
356
|
+
return index
|
|
357
|
+
raise ValueError("Occupancy is not part of this site")
|
|
358
|
+
|
|
359
|
+
@staticmethod
|
|
360
|
+
def _unique_label(template: str, used: set[str]) -> str:
|
|
361
|
+
if template not in used:
|
|
362
|
+
return template
|
|
363
|
+
suffix = 1
|
|
364
|
+
while f"{template}.{suffix}" in used:
|
|
365
|
+
suffix += 1
|
|
366
|
+
return f"{template}.{suffix}"
|
|
367
|
+
|
|
368
|
+
@staticmethod
|
|
369
|
+
def _copy_occupancies(
|
|
370
|
+
entries: Iterable[OccupancyEntry],
|
|
371
|
+
) -> list[OccupancyEntry]:
|
|
372
|
+
return [OccupancyEntry(entry.symbol, entry.value) for entry in entries]
|
|
373
|
+
|
|
374
|
+
@staticmethod
|
|
375
|
+
def _occupancy_mapping(
|
|
376
|
+
entries: Iterable[OccupancyEntry],
|
|
377
|
+
) -> dict[Any, float]:
|
|
378
|
+
result: dict[Any, float] = {}
|
|
379
|
+
for entry in entries:
|
|
380
|
+
if not entry.symbol:
|
|
381
|
+
continue
|
|
382
|
+
key: Any = entry.symbol
|
|
383
|
+
if key in result:
|
|
384
|
+
key = AtomicType.from_symbol(entry.symbol)
|
|
385
|
+
result[key] = entry.value
|
|
386
|
+
return result
|
|
387
|
+
|
|
388
|
+
@classmethod
|
|
389
|
+
def _sites_from_atoms(cls, atoms: Atoms) -> list[AssignmentSite]:
|
|
390
|
+
partitions = partition_by_kinds(atoms)
|
|
391
|
+
kinds = (
|
|
392
|
+
atoms.get_array("spacegroup_kinds")
|
|
393
|
+
if "spacegroup_kinds" in atoms.arrays
|
|
394
|
+
else None
|
|
395
|
+
)
|
|
396
|
+
stored_occupancy = atoms.info.get("occupancy", {})
|
|
397
|
+
labels = labels_for_partitions(atoms, partitions=partitions)
|
|
398
|
+
positions = atoms.get_scaled_positions()
|
|
399
|
+
sites: list[AssignmentSite] = []
|
|
400
|
+
for number, partition in enumerate(partitions):
|
|
401
|
+
indices = [int(index) for index in partition]
|
|
402
|
+
first = indices[0]
|
|
403
|
+
occupancy = None
|
|
404
|
+
if stored_occupancy and kinds is not None:
|
|
405
|
+
occupancy = stored_occupancy.get(str(kinds[first]))
|
|
406
|
+
if occupancy is None:
|
|
407
|
+
symbol = atoms[first].symbol
|
|
408
|
+
occupancy = {} if symbol == "X" else {symbol: 1.0}
|
|
409
|
+
entries = [
|
|
410
|
+
OccupancyEntry(
|
|
411
|
+
re.sub(r"_\d+$", "", getattr(symbol, "symbol", str(symbol))),
|
|
412
|
+
float(value),
|
|
413
|
+
)
|
|
414
|
+
for symbol, value in occupancy.items()
|
|
415
|
+
] or [OccupancyEntry()]
|
|
416
|
+
sites.append(
|
|
417
|
+
AssignmentSite(
|
|
418
|
+
label=str(labels[number]),
|
|
419
|
+
positions=np.asarray(positions[partition], dtype=float).copy(),
|
|
420
|
+
origins=indices,
|
|
421
|
+
occupancies=entries,
|
|
422
|
+
)
|
|
423
|
+
)
|
|
424
|
+
return sites
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import re
|
|
3
|
+
|
|
4
|
+
def labels_for_partitions(atoms, partitions=None, sep='_'):
|
|
5
|
+
"""Generate unique labels for atom kinds, appending suffixes as needed."""
|
|
6
|
+
try:
|
|
7
|
+
arr = atoms.get_array('labels')
|
|
8
|
+
except KeyError:
|
|
9
|
+
arr = atoms.symbols
|
|
10
|
+
partitions = partition_by_kinds(atoms) if partitions is None else partitions
|
|
11
|
+
firsts = [ i[0] for i in partitions ]
|
|
12
|
+
arr = arr[firsts]
|
|
13
|
+
|
|
14
|
+
used = set()
|
|
15
|
+
result = []
|
|
16
|
+
|
|
17
|
+
for label in arr:
|
|
18
|
+
label = re.sub(r"\.\d+$", "", label)
|
|
19
|
+
if label not in used:
|
|
20
|
+
result.append(label)
|
|
21
|
+
used.add(label)
|
|
22
|
+
else:
|
|
23
|
+
i = 1
|
|
24
|
+
while f"{label}{sep}{i}" in used:
|
|
25
|
+
i += 1
|
|
26
|
+
new_label = f"{label}{sep}{i}"
|
|
27
|
+
result.append(new_label)
|
|
28
|
+
used.add(new_label)
|
|
29
|
+
return result
|
|
30
|
+
|
|
31
|
+
def partition_by_kinds(atoms):
|
|
32
|
+
"""Partition atoms by their spacegroup kinds.
|
|
33
|
+
|
|
34
|
+
Returns a dict mapping kind index to list of atom indices.
|
|
35
|
+
"""
|
|
36
|
+
if not 'spacegroup_kinds' in atoms.arrays:
|
|
37
|
+
return np.arange(len(atoms)).reshape(-1,1)
|
|
38
|
+
|
|
39
|
+
kinds = atoms.get_array('spacegroup_kinds')
|
|
40
|
+
kind_idxs = np.argsort(kinds)
|
|
41
|
+
sorted_kinds = kinds[kind_idxs]
|
|
42
|
+
return np.split(kind_idxs, np.where(np.diff(sorted_kinds))[0] + 1)
|