% --------------------------------------------------------------------------
% the MODIAGRAM package
%
%   easy creation of molecular orbital diagrams
%
% --------------------------------------------------------------------------
% Clemens Niederberger
% Web:    https://www.bitbucket.org/cgnieder/modiagram
% E-Mail: contact@mychemistry.eu
% --------------------------------------------------------------------------
% If you have any ideas, questions, suggestions or bugs to report, please
% feel free to contact me.
% --------------------------------------------------------------------------
% Copyright 2011--2014 Clemens Niederberger
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3
% of this license or (at your option) any later version.
% The latest version of this license is in
%   http://www.latex-project.org/lppl.txt
% and version 1.3 or later is part of all distributions of LaTeX
% version 2005/12/01 or later.
%
% This work has the LPPL maintenance status `maintained'.
%
% The Current Maintainer of this work is Clemens Niederberger.
%
% This work consists of the files modiagram.sty, modiagram_en.tex,
% README and the derived file modiagram_en.pdf.
% --------------------------------------------------------------------------
\RequirePackage{ expl3 , xparse , l3keys2e , tikz , chemgreek }
\usetikzlibrary{calc,arrows}
\ProvidesExplPackage
  {modiagram}
  {2014/06/28}
  {0.2e}
  {easy creation of molecular orbital diagrams}

% --------------------------------------------------------------------------
% check expl3 version:
\@ifpackagelater { expl3 } { 2013/12/14 }
  { }
  {
    \PackageError { modiagram } { Support~package~expl3~too~old }
      {
        You~need~to~update~your~installation~of~the~bundles~'l3kernel'~and~
        'l3packages'.\MessageBreak
        Loading~modiagram~will~abort!
      }
    \tex_endinput:D
  }

% --------------------------------------------------------------------------- %
% error messages
\msg_set:nnn { MOdiagram } { missing-atom }
  {
    You~need~to~specify~the~left~and~right~atom~first~before~you~can~use~
    \token_to_str:N \molecule \c_space_tl \msg_line_context: .
  }

\msg_set:nnn { MOdiagram } { missing-AO }
  {
    You~need~to~specify~both~#2~AOs~first~before~you~can~use~
    #1~ \msg_line_context: .
  }

\msg_set:nnn { MOdiagram } { electron-placement }
  {
    The~value~for~the~electron~placement~must~be~between~0~and~1~
    \msg_line_context: . 
  }

% --------------------------------------------------------------------------- %
% temporary variables
\tl_new:N  \l__MOdiagram_tmpa_tl
\tl_new:N  \l__MOdiagram_tmpb_tl
\dim_new:N \l__MOdiagram_tmpa_dim
\fp_new:N  \l__MOdiagram_tmpa_fp

% --------------------------------------------------------------------------- %
% variants of expl3 kernel commands:
\cs_generate_variant:Nn \str_case:nnn { V }
\cs_generate_variant:Nn \dim_compare:nNnTF { cNc }

% --------------------------------------------------------------------------- %
% main environment
\NewDocumentEnvironment { MOdiagram } { o g }
  {
    \cs_set_eq:NN \atom \__MOdiagram_atom:
    \cs_set_eq:NN \molecule \__MOdiagram_molecule:
    \cs_set_eq:NN \AO \__MOdiagram_arbitrary_AO:
    \cs_set_eq:NN \EnergyAxis \__MOdiagram_EnergyAxis:
    \dim_gzero:N \g__MOdiagram_min_energy_dim
    \dim_gzero:N \g__MOdiagram_max_energy_dim
    \int_gzero:N \g__MOdiagram_AO_name_int
    \IfNoValueF { #1 } { \keys_set:nn { MOdiagram / diagram } { #1 } }
    \__MOdiagram_set_labels:
    \__MOdiagram_tikzpicture:n { }
    \char_set_catcode_letter:N \:
    \char_set_catcode_other:N \;
  }
  {
    \bool_if:NT \l__MOdiagram_names_bool
      {
        \__MOdiagram_node:f { \tl_use:N \l__MOdiagram_names_style_tl }
          at
          (
            \l__MOdiagram_left_atom_position_dim ,
            \g__MOdiagram_min_energy_dim - 1cm
          )
          { \tl_use:N \l__MOdiagram_atom_left_name_tl } ;
        \__MOdiagram_node:f { \tl_use:N \l__MOdiagram_names_style_tl }
          at
          (
            \l__MOdiagram_molecule_position_dim ,
            \g__MOdiagram_min_energy_dim - 1cm
          )
          { \tl_use:N \l__MOdiagram_molecule_name_tl } ;
        \__MOdiagram_node:f { \tl_use:N \l__MOdiagram_names_style_tl }
          at
          (
            \l__MOdiagram_left_atom_position_dim
              + \l__MOdiagram_inter_atom_distance_dim ,
            \g__MOdiagram_min_energy_dim - 1cm
          )
          { \tl_use:N \l__MOdiagram_atom_right_name_tl } ;
      }
    \endtikzpicture
  }

\bool_new:N \l__MOdiagram_AO_square_bool
\bool_new:N \l__MOdiagram_AO_round_bool
\bool_new:N \l__MOdiagram_AO_circle_bool
\bool_new:N \l__MOdiagram_AO_fancy_bool
\bool_new:N \l__MOdiagram_AO_labels_bool
\bool_new:N \l__MOdiagram_names_bool

\tl_new:N \l__MOdiagram_names_style_tl
\tl_set:Nn \l__MOdiagram_names_style_tl { anchor=base }

\tl_new:N \l__MOdiagram_lines_tl
\tl_set:Nn \l__MOdiagram_lines_tl { dotted }

\tl_new:N \l__MOdiagram_orbital_label_fontsize_tl
\tl_new:N \l__MOdiagram_orbital_label_style_tl

\dim_new:N \l__MOdiagram_AO_width_dim
\dim_set:Nn \l__MOdiagram_AO_width_dim { 10pt }

\tl_new:N \l__MOdiagram_AO_up_electron_tl
\tl_set:Nn \l__MOdiagram_AO_up_electron_tl { .4 }
\tl_new:N \l__MOdiagram_AO_down_electron_tl
\tl_set:Nn \l__MOdiagram_AO_down_electron_tl { .6 }

\dim_new:N \l__MOdiagram_left_atom_position_dim
\dim_set:Nn \l__MOdiagram_left_atom_position_dim { 1cm }
\dim_new:N \l__MOdiagram_inter_atom_distance_dim
\dim_set:Nn \l__MOdiagram_inter_atom_distance_dim { 4cm }
\dim_new:N \l__MOdiagram_molecule_position_dim

\dim_new:N \g__MOdiagram_min_energy_dim
\dim_new:N \g__MOdiagram_max_energy_dim

\dim_new:N \l__MOdiagram_energy_gain_dim
\dim_new:N \l__MOdiagram_energy_loss_dim

% detect lowest and highest orbital so we can draw the appropriate energy axis:
\cs_new_protected:Npn \__MOdiagram_energy_range:N #1
  {
    \dim_set:Nn \l__MOdiagram_tmpa_dim { #1 }
    \dim_compare:nT { \l__MOdiagram_tmpa_dim < \g__MOdiagram_min_energy_dim }
      { \dim_gset_eq:NN \g__MOdiagram_min_energy_dim \l__MOdiagram_tmpa_dim }
    \dim_compare:nT { \l__MOdiagram_tmpa_dim > \g__MOdiagram_max_energy_dim }
      { \dim_gset_eq:NN \g__MOdiagram_max_energy_dim \l__MOdiagram_tmpa_dim }
  }
\cs_generate_variant:Nn \__MOdiagram_energy_range:N { n }

% split energy levels for creating the MO; we need to detect wether the left
% or the right AO is the lower or higher one, respectively
\cs_new_protected:Npn \__MOdiagram_split_energy:NNN #1#2#3
  {
    \dim_compare:cNcTF
      { l__MOdiagram_atom_left_#1_dim } < { l__MOdiagram_atom_right_#1_dim }
      {
        \dim_set_eq:Nc \l__MOdiagram_energy_gain_dim
          { l__MOdiagram_atom_left_#1_dim }
        \dim_sub:Nn \l__MOdiagram_energy_gain_dim { #2 }
        \dim_set_eq:Nc \l__MOdiagram_energy_loss_dim
          { l__MOdiagram_atom_right_#1_dim }
        \dim_add:Nn \l__MOdiagram_energy_loss_dim { #3 }
      }
      {
        \dim_set_eq:Nc \l__MOdiagram_energy_gain_dim
          { l__MOdiagram_atom_right_#1_dim }
        \dim_sub:Nn \l__MOdiagram_energy_gain_dim { #2 }
        \dim_set_eq:Nc \l__MOdiagram_energy_loss_dim
          { l__MOdiagram_atom_left_#1_dim }
        \dim_add:Nn \l__MOdiagram_energy_loss_dim { #3 }
      }
  }
\cs_generate_variant:Nn \__MOdiagram_split_energy:NNN { nNN }

% position the spin-up/spin-down el:
\cs_new_protected:Npn \__MOdiagram_AO_place_electron:nn #1#2
  {
    \fp_compare:nNnT { #2 } < { 0 }
      { \msg_error:nn { MOdiagram } { electron-placement } }
    \fp_compare:nNnT { abs( #2 ) } > { 1 }
      { \msg_error:nn { MOdiagram } { electron-placement } }
    \bool_if:nTF { #1 }
      { \tl_set:Nn \l__MOdiagram_AO_down_electron_tl { #2 } }
      { \tl_set:Nn \l__MOdiagram_AO_up_electron_tl { #2 } }
  }
\cs_generate_variant:Nn \__MOdiagram_AO_place_electron:nn { nx }

\cs_new_protected:Npn \__MOdiagram_AO_place_electrons:n #1
  {
    \fp_set:Nn \l__MOdiagram_tmpa_fp { .5 * ( 1 - #1 ) }
    \__MOdiagram_AO_place_electron:nx { 0 } { \fp_to_tl:N \l__MOdiagram_tmpa_fp }
    \fp_set:Nn \l__MOdiagram_tmpa_fp { .5 * ( 1 + #1 ) }
    \__MOdiagram_AO_place_electron:nx { 1 } { \fp_to_tl:N \l__MOdiagram_tmpa_fp }
  }

% place the right atom
\cs_new_protected:Npn \__MOdiagram_molecule_position:n #1
  {
    \fp_set_from_dim:Nn \l__MOdiagram_tmpa_fp { #1 }
    \fp_set:Nn \l__MOdiagram_tmpa_fp { .5 * \l__MOdiagram_tmpa_fp }
    \dim_set:Nn \l__MOdiagram_molecule_position_dim
      { \fp_to_dim:N \l__MOdiagram_tmpa_fp + \l__MOdiagram_left_atom_position_dim }
  }
\cs_generate_variant:Nn \__MOdiagram_molecule_position:n { f }

\__MOdiagram_molecule_position:f
  { \dim_use:N \l__MOdiagram_inter_atom_distance_dim }

% set up keys for the environment
\keys_define:nn { MOdiagram / diagram }
  {
    style          .choice: ,
    style / plain  .code:n    =
      {
        \bool_set_false:N \l__MOdiagram_AO_square_bool
        \bool_set_false:N \l__MOdiagram_AO_round_bool
        \bool_set_false:N \l__MOdiagram_AO_circle_bool
        \bool_set_false:N \l__MOdiagram_AO_fancy_bool
        \tl_set:Nn \l__MOdiagram_lines_tl { dotted }
      } ,
    style / square .code:n    =
      {
        \bool_set_true:N \l__MOdiagram_AO_square_bool
        \bool_set_false:N \l__MOdiagram_AO_round_bool
        \bool_set_false:N \l__MOdiagram_AO_circle_bool
        \bool_set_false:N \l__MOdiagram_AO_fancy_bool
        \tl_set:Nn \l__MOdiagram_lines_tl { gray }
      } ,
    style / circle .code:n    =
      {
        \bool_set_false:N \l__MOdiagram_AO_square_bool
        \bool_set_false:N \l__MOdiagram_AO_round_bool
        \bool_set_true:N \l__MOdiagram_AO_circle_bool
        \bool_set_false:N \l__MOdiagram_AO_fancy_bool
        \tl_set:Nn \l__MOdiagram_lines_tl { gray }
      } ,
    style / round  .code:n    =
      {
        \bool_set_true:N \l__MOdiagram_AO_square_bool
        \bool_set_true:N \l__MOdiagram_AO_round_bool
        \bool_set_false:N \l__MOdiagram_AO_circle_bool
        \bool_set_false:N \l__MOdiagram_AO_fancy_bool
        \tl_set:Nn \l__MOdiagram_lines_tl { gray }
      } ,
    style / fancy  .code:n    =
      {
        \bool_set_true:N \l__MOdiagram_AO_square_bool
        \bool_set_true:N \l__MOdiagram_AO_round_bool
        \bool_set_false:N \l__MOdiagram_AO_circle_bool
        \bool_set_true:N \l__MOdiagram_AO_fancy_bool
        \tl_set:Nn \l__MOdiagram_lines_tl { densely~dashed }
      } ,
    lines         .tl_set:N   = \l__MOdiagram_lines_tl ,
    distance      .code:n     =
      {
        \dim_set:Nn \l__MOdiagram_inter_atom_distance_dim { #1 }
        \__MOdiagram_molecule_position:n { #1 }
      } ,
    AO-width      .tl_set:N   = \l__MOdiagram_AO_width_dim ,
    up-el-pos     .code:n     = \__MOdiagram_AO_place_electron:nn { 0 } { #1 } ,
    down-el-pos   .code:n     = \__MOdiagram_AO_place_electron:nn { 1 } { #1 } ,
    el-sep        .code:n     = \__MOdiagram_AO_place_electrons:n { #1 } ,
    labels        .bool_set:N = \l__MOdiagram_AO_labels_bool ,
    names         .bool_set:N = \l__MOdiagram_names_bool ,
    names-style   .tl_set:N   = \l__MOdiagram_names_style_tl ,
    names-style-add .code:n   =
      { \tl_put_right:Nn \l__MOdiagram_names_style_tl { , #1 } } ,
    labels-fs     .tl_set:N   = \l__MOdiagram_orbital_label_fontsize_tl ,
    labels-style  .tl_set:N   = \l__MOdiagram_orbital_label_style_tl
  }

\ProcessKeysOptions { MOdiagram / diagram }

% --------------------------------------------------------------------------- %
% setup command
\NewDocumentCommand \MOsetup { m }
  { \keys_set:nn { MOdiagram / diagram } { #1 } }

% --------------------------------------------------------------------------- %
% draw AOs
\tl_new:N \l__MOdiagram_atom_left_name_tl
\tl_new:N \l__MOdiagram_atom_right_name_tl

\bool_new:N \l__MOdiagram_left_atom_placed_bool
\bool_set_false:N \l__MOdiagram_left_atom_placed_bool
\bool_new:N \l__MOdiagram_right_atom_placed_bool
\bool_set_false:N \l__MOdiagram_right_atom_placed_bool

\NewDocumentCommand \__MOdiagram_atom: { o m m }
  {
    \__MOdiagram_atom_disable:
    \keys_set:nn { MOdiagram / atom } { position = #2 }
    \keys_set:nn { MOdiagram / atom } { #3 }
    \bool_if:NTF \l__MOdiagram_atom_left_bool
      { \bool_set_true:N \l__MOdiagram_left_atom_placed_bool }
      { \bool_set_true:N \l__MOdiagram_right_atom_placed_bool }
    \IfNoValueF { #1 }
      {
        \bool_if:NTF \l__MOdiagram_atom_left_bool
          { \tl_set:Nn \l__MOdiagram_atom_left_name_tl { #1 } }
          { \tl_set:Nn \l__MOdiagram_atom_right_name_tl { #1 } }
      }
    \__MOdiagram_one_s:
    \__MOdiagram_two_s:
    \__MOdiagram_two_p:
%     \__MOdiagram_three_s:
%     \__MOdiagram_three_p:
%     \__MOdiagram_four_s:
  }

\bool_new:N \l__MOdiagram_atom_left_bool

% is \atom placed left or right?
\keys_define:nn { MOdiagram / atom }
  {
    position         .choice: ,
    position / left  .code:n =
      { \bool_set_true:N \l__MOdiagram_atom_left_bool } ,
    position / right .code:n =
      { \bool_set_false:N \l__MOdiagram_atom_left_bool }
  }

\dim_new:N \l__MOdiagram_atom_xshift_dim

% these are going to be our `arguments' for the \atom command:
\keys_define:nn { MOdiagram / atom }
  {
    1s          .code:n    = { \__MOdiagram_one_s_set:n { #1 } } ,
    1s          .default:n = { 0 ; pair } ,
    2s          .code:n    = { \__MOdiagram_two_s_set:n { #1 } } ,
    2s          .default:n = { 2 ; pair } ,
    2p          .code:n    = { \__MOdiagram_two_p_set:n { #1 } } ,
    2p          .default:n = { 5 ; pair , pair , pair } ,
    color       .code:n    = { \__MOdiagram_electron_color_set:n { #1 } } ,
    label       .code:n    = { \__MOdiagram_orbital_label_set:n { #1 } } ,
    up-el-pos   .code:n    = { \__MOdiagram_electron_up_set:n { #1 } } ,
    down-el-pos .code:n    = { \__MOdiagram_electron_down_set:n { #1 } }
  }

% --------------------------------------------------------------------------- %
% 1s orbital
\dim_new:N \l__MOdiagram_atom_one_s_dim
\dim_new:N \l__MOdiagram_atom_left_one_s_dim
\dim_new:N \l__MOdiagram_atom_right_one_s_dim

\tl_new:N \l__MOdiagram_AO_one_s_electron_tl

\bool_new:N \l__MOdiagram_atom_one_s_bool
\bool_new:N \l__MOdiagram_one_s_left_bool
\bool_set_false:N \l__MOdiagram_one_s_left_bool
\bool_new:N \l__MOdiagram_one_s_right_bool
\bool_set_false:N \l__MOdiagram_one_s_right_bool

% read 1s argument
\cs_new_protected:Npn \__MOdiagram_one_s_set:n #1
  {
    \bool_set_true:N \l__MOdiagram_atom_one_s_bool
    \tl_if_in:onTF { #1 } { ; }
      { \__MOdiagram_one_s_set_aux:n #1 \q_stop }
      {
        \tl_clear:N \l__MOdiagram_AO_one_s_electron_tl
        \tl_if_blank:nTF { #1 }
          { \dim_set:Nn \l__MOdiagram_atom_one_s_dim { 0 cm } }
          { \dim_set:Nn \l__MOdiagram_atom_one_s_dim { #1 cm } }
      }
  }

\cs_new_protected:Npn \__MOdiagram_one_s_set_aux:n #1;#2 \q_stop
  {
    \tl_if_blank:nTF { #1 }
      { \dim_set:Nn \l__MOdiagram_atom_one_s_dim { 0 cm } }
      { \dim_set:Nn \l__MOdiagram_atom_one_s_dim { #1 cm } }
    \tl_set:Nn \l__MOdiagram_AO_one_s_electron_tl { #2 }
  }

% display 1s orbital
\cs_new_protected:Npn \__MOdiagram_one_s:
  {
    \bool_if:NT \l__MOdiagram_atom_one_s_bool
      {
        \bool_if:NTF \l__MOdiagram_atom_left_bool
          {
            \dim_set_eq:NN
              \l__MOdiagram_atom_xshift_dim
              \l__MOdiagram_left_atom_position_dim
            \dim_set_eq:NN
              \l__MOdiagram_atom_left_one_s_dim
              \l__MOdiagram_atom_one_s_dim
            \bool_set_true:N \l__MOdiagram_one_s_left_bool
          }
          {
            \dim_set:Nn \l__MOdiagram_atom_xshift_dim
              {
                \l__MOdiagram_left_atom_position_dim
                  + \l__MOdiagram_inter_atom_distance_dim
              }
            \dim_set_eq:NN
              \l__MOdiagram_atom_right_one_s_dim
              \l__MOdiagram_atom_one_s_dim
            \bool_set_true:N \l__MOdiagram_one_s_right_bool
          }
        \__MOdiagram_energy_range:N \l__MOdiagram_atom_one_s_dim
        \__MOdiagram_node:n { inner~sep=0 , outer~sep=0 }
          (1s
            \bool_if:NTF \l__MOdiagram_atom_left_bool
              { left }
              { right }
          )
          at ( \l__MOdiagram_atom_xshift_dim , \l__MOdiagram_atom_one_s_dim )
          {
            \bool_if:NTF \l__MOdiagram_atom_left_bool
              {
                \__MOdiagram_get_electron_color:n { 1sleft }
                \__MOdiagram_get_electron_up:n { 1sleft }
                \__MOdiagram_get_electron_down:n { 1sleft }
              }
              {
                \__MOdiagram_get_electron_color:n { 1sright }
                \__MOdiagram_get_electron_up:n { 1sright }
                \__MOdiagram_get_electron_down:n { 1sright }
              }
            \__MOdiagram_AO:ff
              { \tl_use:N \l__MOdiagram_AO_one_s_electron_tl }
              { \tl_use:N \l__MOdiagram_electron_current_color_tl }
          } ;
        \bool_if:NTF \l__MOdiagram_atom_left_bool
          { \__MOdiagram_get_orbital_label:n { 1s left } }
          { \__MOdiagram_get_orbital_label:n { 1s right } }
      }
  }

% --------------------------------------------------------------------------- %
% 2s orbital
\dim_new:N \l__MOdiagram_atom_two_s_dim
\dim_new:N \l__MOdiagram_atom_left_two_s_dim
\dim_new:N \l__MOdiagram_atom_right_two_s_dim

\tl_new:N \l__MOdiagram_AO_two_s_electron_tl

\bool_new:N \l__MOdiagram_atom_two_s_bool
\bool_new:N \l__MOdiagram_two_s_left_bool
\bool_set_false:N \l__MOdiagram_two_s_left_bool
\bool_new:N \l__MOdiagram_two_s_right_bool
\bool_set_false:N \l__MOdiagram_two_s_right_bool

% read 2s argument
\cs_new_protected:Npn \__MOdiagram_two_s_set:n #1
  {
    \bool_set_true:N \l__MOdiagram_atom_two_s_bool
    \tl_if_in:onTF { #1 } { ; }
      { \__MOdiagram_two_s_set_aux:n #1 \q_stop }
      {
        \tl_clear:N \l__MOdiagram_AO_two_s_electron_tl
        \tl_if_blank:nTF { #1 }
          { \dim_set:Nn \l__MOdiagram_atom_two_s_dim { 2 cm } }
          { \dim_set:Nn \l__MOdiagram_atom_two_s_dim { #1 cm } }
      }
  }

\cs_new_protected:Npn \__MOdiagram_two_s_set_aux:n #1;#2 \q_stop
  {
    \tl_if_blank:nTF { #1 }
      { \dim_set:Nn \l__MOdiagram_atom_two_s_dim { 2 cm } }
      { \dim_set:Nn \l__MOdiagram_atom_two_s_dim { #1 cm } }
    \tl_set:Nn \l__MOdiagram_AO_two_s_electron_tl { #2 }
  }

% display 2s orbital
\cs_new_protected:Npn \__MOdiagram_two_s:
  {
    \bool_if:NT \l__MOdiagram_atom_two_s_bool
      {
        \bool_if:NTF \l__MOdiagram_atom_left_bool
          {
            \dim_set_eq:NN
              \l__MOdiagram_atom_xshift_dim
              \l__MOdiagram_left_atom_position_dim
            \dim_set_eq:NN
              \l__MOdiagram_atom_left_two_s_dim
              \l__MOdiagram_atom_two_s_dim
            \bool_set_true:N \l__MOdiagram_two_s_left_bool
          }
          {
            \dim_set:Nn \l__MOdiagram_atom_xshift_dim
              {
                \l__MOdiagram_left_atom_position_dim
                  + \l__MOdiagram_inter_atom_distance_dim
              }
            \dim_set_eq:NN
              \l__MOdiagram_atom_right_two_s_dim
              \l__MOdiagram_atom_two_s_dim
            \bool_set_true:N \l__MOdiagram_two_s_right_bool
          }
        \__MOdiagram_energy_range:N \l__MOdiagram_atom_two_s_dim
        \__MOdiagram_node:n { inner~sep=0 , outer~sep=0 }
          (2s
            \bool_if:NTF \l__MOdiagram_atom_left_bool
              { left }
              { right }
          )
          at ( \l__MOdiagram_atom_xshift_dim , \l__MOdiagram_atom_two_s_dim )
          {
            \bool_if:NTF \l__MOdiagram_atom_left_bool
              {
                \__MOdiagram_get_electron_color:n { 2sleft }
                \__MOdiagram_get_electron_up:n { 2sleft }
                \__MOdiagram_get_electron_down:n { 2sleft }
              }
              {
                \__MOdiagram_get_electron_color:n { 2sright }
                \__MOdiagram_get_electron_up:n { 2sright }
                \__MOdiagram_get_electron_down:n { 2sright }
              }
            \__MOdiagram_AO:ff
              { \tl_use:N \l__MOdiagram_AO_two_s_electron_tl }
              { \tl_use:N \l__MOdiagram_electron_current_color_tl }
          } ;
        \bool_if:NTF \l__MOdiagram_atom_left_bool
          { \__MOdiagram_get_orbital_label:n { 2s left } }
          { \__MOdiagram_get_orbital_label:n { 2s right } }
      }
  }

% --------------------------------------------------------------------------- %
% 2p orbital
\dim_new:N \l__MOdiagram_atom_two_p_dim
\dim_new:N \l__MOdiagram_atom_left_two_p_dim
\dim_new:N \l__MOdiagram_atom_right_two_p_dim

\dim_new:N \l__MOdiagram_atom_px_shift_dim
\dim_new:N \l__MOdiagram_atom_py_shift_dim
\dim_new:N \l__MOdiagram_atom_pz_shift_dim

\tl_new:N \l__MOdiagram_AO_two_px_electron_tl
\tl_new:N \l__MOdiagram_AO_two_py_electron_tl
\tl_new:N \l__MOdiagram_AO_two_pz_electron_tl

\bool_new:N \l__MOdiagram_atom_two_p_bool
\bool_new:N \l__MOdiagram_two_p_left_bool
\bool_set_false:N \l__MOdiagram_two_p_left_bool
\bool_new:N \l__MOdiagram_two_p_right_bool
\bool_set_false:N \l__MOdiagram_two_p_right_bool

% read 2p argument
\cs_new_protected:Npn \__MOdiagram_two_p_set:n #1
  {
    \bool_set_true:N \l__MOdiagram_atom_two_p_bool
    \tl_if_in:onTF { #1 } { ; }
      { \__MOdiagram_two_p_set_aux_i:n #1 \q_stop }
      {
        \tl_clear:N \l__MOdiagram_AO_two_px_electron_tl
        \tl_clear:N \l__MOdiagram_AO_two_py_electron_tl
        \tl_clear:N \l__MOdiagram_AO_two_pz_electron_tl
        \tl_if_blank:nTF { #1 }
          { \dim_set:Nn \l__MOdiagram_atom_two_p_dim { 5 cm } }
          { \dim_set:Nn \l__MOdiagram_atom_two_p_dim { #1 cm } }
      }
  }

\cs_new_protected:Npn \__MOdiagram_two_p_set_aux_i:n #1;#2 \q_stop
  {
    \tl_if_blank:nTF { #1 }
      { \dim_set:Nn \l__MOdiagram_atom_two_p_dim { 5 cm } }
      { \dim_set:Nn \l__MOdiagram_atom_two_p_dim { #1 cm } }
    \__MOdiagram_two_p_set_aux_ii:n { #2 }
  }

\NewDocumentCommand \__MOdiagram_two_p_set_aux_ii:n
  { > { \SplitArgument { 2 } { , } } m }
  { \__MOdiagram_two_p_set_aux_iii:nnn #1 }

\cs_set_nopar:Npn \__MOdiagram_two_p_set_aux_iii:nnn #1#2#3
  {
    \tl_if_blank:nF { #1 } { \tl_set:Nn \l__MOdiagram_AO_two_px_electron_tl { #1 } }
    \tl_if_blank:nF { #2 } { \tl_set:Nn \l__MOdiagram_AO_two_py_electron_tl { #2 } }
    \tl_if_blank:nF { #3 } { \tl_set:Nn \l__MOdiagram_AO_two_pz_electron_tl { #3 } }
  }

% place the x, y, and z orbitals
\cs_new_protected:Npn \__MOdiagram_p_orbitals_shift:nnn #1#2#3
  {
    \fp_set_from_dim:Nn \l__MOdiagram_tmpa_fp { \l__MOdiagram_AO_width_dim } 
    {
      \fp_set:Nn \l__MOdiagram_tmpa_fp { #1 * \l__MOdiagram_tmpa_fp }
      \dim_gset:Nn \l__MOdiagram_atom_px_shift_dim { \fp_to_dim:N \l__MOdiagram_tmpa_fp }
    }
    {
      \fp_set:Nn \l__MOdiagram_tmpa_fp { #2 * \l__MOdiagram_tmpa_fp }
      \dim_gset:Nn \l__MOdiagram_atom_py_shift_dim { \fp_to_dim:N \l__MOdiagram_tmpa_fp }
    }
    {
      \fp_set:Nn \l__MOdiagram_tmpa_fp { #3 * \l__MOdiagram_tmpa_fp }
      \dim_gset:Nn \l__MOdiagram_atom_pz_shift_dim { \fp_to_dim:N \l__MOdiagram_tmpa_fp }
    }
  }

% display 2p orbitals
\cs_new_protected:Npn \__MOdiagram_two_p:
  {
    \bool_if:NT \l__MOdiagram_atom_two_p_bool
      {
        \bool_if:NTF \l__MOdiagram_atom_left_bool
          {
            \dim_set_eq:NN
              \l__MOdiagram_atom_xshift_dim
              \l__MOdiagram_left_atom_position_dim 
            \__MOdiagram_p_orbitals_shift:nnn { -4 } { -2 } { 0 }
            \dim_set_eq:NN
              \l__MOdiagram_atom_left_two_p_dim
              \l__MOdiagram_atom_two_p_dim
            \dim_set_eq:NN
              \l_energy_axis_dim
              \l__MOdiagram_atom_px_shift_dim
            \bool_set_true:N \l__MOdiagram_two_p_left_bool
          }
          {
            \dim_set:Nn \l__MOdiagram_atom_xshift_dim
              {
                \l__MOdiagram_left_atom_position_dim
                  + \l__MOdiagram_inter_atom_distance_dim
              }
            \__MOdiagram_p_orbitals_shift:nnn { 0 } { 2 } { 4 }
            \dim_set_eq:NN
              \l__MOdiagram_atom_right_two_p_dim
              \l__MOdiagram_atom_two_p_dim
            \bool_set_true:N \l__MOdiagram_two_p_right_bool
          }
        \__MOdiagram_energy_range:N \l__MOdiagram_atom_two_p_dim
        \__MOdiagram_node:n { inner~sep=0 , outer~sep=0 }
          (2pz
            \bool_if:NTF \l__MOdiagram_atom_left_bool
              { left }
              { right }
          )
          at
          (
            \l__MOdiagram_atom_xshift_dim + \l__MOdiagram_atom_pz_shift_dim ,
            \l__MOdiagram_atom_two_p_dim
          )
          {
            \bool_if:NTF \l__MOdiagram_atom_left_bool
              {
                \__MOdiagram_get_electron_color:n { 2pz left }
                \__MOdiagram_get_electron_up:n { 2pz left }
                \__MOdiagram_get_electron_down:n { 2pz left }
              }
              {
                \__MOdiagram_get_electron_color:n { 2pz right }
                \__MOdiagram_get_electron_up:n { 2pz right }
                \__MOdiagram_get_electron_down:n { 2pz right }
              }
            \__MOdiagram_AO:ff
              { \tl_use:N \l__MOdiagram_AO_two_pz_electron_tl }
              { \tl_use:N \l__MOdiagram_electron_current_color_tl }
          } ;
        \bool_if:NTF \l__MOdiagram_atom_left_bool
          { \__MOdiagram_get_orbital_label:n { 2pz left } }
          { \__MOdiagram_get_orbital_label:n { 2pz right } }
        \__MOdiagram_node:n { inner~sep=0 , outer~sep=0 }
          (2py
            \bool_if:NTF \l__MOdiagram_atom_left_bool
              { left }
              { right }
          )
          at
          (
            \l__MOdiagram_atom_xshift_dim + \l__MOdiagram_atom_py_shift_dim ,
            \l__MOdiagram_atom_two_p_dim
          )
          {
            \bool_if:NTF \l__MOdiagram_atom_left_bool
              {
                \__MOdiagram_get_electron_color:n { 2py left }
                \__MOdiagram_get_electron_up:n { 2py left }
                \__MOdiagram_get_electron_down:n { 2py left }
              }
              {
                \__MOdiagram_get_electron_color:n { 2py right }
                \__MOdiagram_get_electron_up:n { 2py right }
                \__MOdiagram_get_electron_down:n { 2py right }
              }
            \__MOdiagram_AO:ff
              { \tl_use:N \l__MOdiagram_AO_two_py_electron_tl }
              { \tl_use:N \l__MOdiagram_electron_current_color_tl }
          } ;
        \bool_if:NTF \l__MOdiagram_atom_left_bool
          { \__MOdiagram_get_orbital_label:n { 2py left } }
          { \__MOdiagram_get_orbital_label:n { 2py right } }
        \__MOdiagram_node:n { inner~sep=0 , outer~sep=0 }
          (2px
            \bool_if:NTF \l__MOdiagram_atom_left_bool
              { left }
              { right }
          )
          at
          (
            \l__MOdiagram_atom_xshift_dim + \l__MOdiagram_atom_px_shift_dim ,
            \l__MOdiagram_atom_two_p_dim
          )
          {
            \bool_if:NTF \l__MOdiagram_atom_left_bool
              {
                \__MOdiagram_get_electron_color:n { 2px left }
                \__MOdiagram_get_electron_up:n { 2px left }
                \__MOdiagram_get_electron_down:n { 2px left }
              }
              {
                \__MOdiagram_get_electron_color:n { 2px right }
                \__MOdiagram_get_electron_up:n { 2px right }
                \__MOdiagram_get_electron_down:n { 2px right }
              }
            \__MOdiagram_AO:ff
              { \tl_use:N \l__MOdiagram_AO_two_px_electron_tl }
              { \tl_use:N \l__MOdiagram_electron_current_color_tl }
          } ;
        \bool_if:NTF \l__MOdiagram_atom_left_bool
          { \__MOdiagram_get_orbital_label:n { 2px left } }
          { \__MOdiagram_get_orbital_label:n { 2px right } }
      }  
  }

% --------------------------------------------------------------------------- %
% draw MOs
\tl_new:N \l__MOdiagram_molecule_name_tl

\NewDocumentCommand \__MOdiagram_molecule: { o m }
  {
    \bool_if:nTF
      {
        \l__MOdiagram_left_atom_placed_bool
          &&
        \l__MOdiagram_right_atom_placed_bool
      }
      {
        \__MOdiagram_molecule_disable:
        \keys_set:nn { MOdiagram / molecule } { #2 }
        \IfNoValueF { #1 }
          { \tl_set:Nn \l__MOdiagram_molecule_name_tl { #1 } }
        \__MOdiagram_one_mo_s:
        \__MOdiagram_two_mo_s:
        \__MOdiagram_two_mo_p:
%         \__MOdiagram_three_mo_s:
%         \__MOdiagram_three_mo_p:
%         \__MOdiagram_four_mo_s:
      }
      { \msg_error:nn { MOdiagram } { missing-atom } }
  }

% these are going to be our molecule arguments:
\keys_define:nn { MOdiagram / molecule }
  {
    1sMO        .code:n    = { \__MOdiagram_one_mo_s_set:n { #1 } } ,
    1sMO        .default:n = { .5 ; pair , pair } ,
    2sMO        .code:n    = { \__MOdiagram_two_mo_s_set:n { #1 } } ,
    2sMO        .default:n = { .5 ; pair , pair } ,
    2pMO        .code:n    = { \__MOdiagram_two_mo_p_set:n { #1 } } ,
    2pMO        .default:n = { 1.5 , .5 ; pair , pair , pair , pair , pair , pair } ,
    color       .code:n    = { \__MOdiagram_electron_color_set:n { #1 } } ,
    label       .code:n    = { \__MOdiagram_orbital_label_set:n { #1 } } ,
    up-el-pos   .code:n    = { \__MOdiagram_electron_up_set:n { #1 } } ,
    down-el-pos .code:n    = { \__MOdiagram_electron_down_set:n { #1 } }
  }

% --------------------------------------------------------------------------- %
% 1sigma orbitals
\dim_new:N \l__MOdiagram_molecule_one_sigma_dim
\dim_new:N \l__MOdiagram_molecule_one_sigmas_dim

\tl_new:N \l__MOdiagram_MO_one_sigma_s_electron_tl
\tl_new:N \l__MOdiagram_MO_one_sigmas_s_electron_tl
\bool_new:N \l__MOdiagram_molecule_one_mo_s_bool

% read 1sMO argument
\cs_new_protected:Npn \__MOdiagram_one_mo_s_set:n #1
  {
    \bool_set_true:N \l__MOdiagram_molecule_one_mo_s_bool
    \tl_if_in:onTF { #1 } { ; }
      { \__MOdiagram_one_mo_s_set_aux:n #1 \q_stop }
      { \__MOdiagram_one_mo_s_set_energy:n { #1 } }
  }

\cs_new_protected:Npn \__MOdiagram_one_mo_s_set_aux:n #1;#2 \q_stop
  {
    \__MOdiagram_one_mo_s_set_energy:n { #1 }
    \__MOdiagram_one_mo_s_set_electrons:n { #2 }
  }

\cs_new_protected:Npn \__MOdiagram_one_mo_s_set_energy:n #1
  {
    \tl_if_in:onTF { #1 } { / }
      { \__MOdiagram_one_mo_s_set_energy_aux:n #1 \q_stop }
      {
        \tl_if_blank:nTF { #1 }
          {
            \dim_set:Nn \l__MOdiagram_molecule_one_sigma_dim { .5 cm }
            \dim_set:Nn \l__MOdiagram_molecule_one_sigmas_dim { .5 cm }
          }
          {
            \dim_set:Nn \l__MOdiagram_molecule_one_sigma_dim { #1 cm }
            \dim_set:Nn \l__MOdiagram_molecule_one_sigmas_dim { #1 cm }
          }
      }
  }

\cs_new_protected:Npn \__MOdiagram_one_mo_s_set_energy_aux:n #1/#2 \q_stop
  {
    \tl_if_blank:nTF { #1 }
      { \dim_set:Nn \l__MOdiagram_molecule_one_sigma_dim { .5 cm } }
      { \dim_set:Nn \l__MOdiagram_molecule_one_sigma_dim { #1 cm } }
    \tl_if_blank:nTF { #2 }
      { \dim_set:Nn \l__MOdiagram_molecule_one_sigmas_dim { .5 cm } }
      { \dim_set:Nn \l__MOdiagram_molecule_one_sigmas_dim { #2 cm } }
  }

\cs_set_nopar:Npn \__MOdiagram_one_mo_s_set_electrons:n #1
  {
    \tl_if_in:onTF { #1 } { , }
      { \__MOdiagram_one_mo_s_set_electrons_aux:n #1 \q_stop }
      { \tl_set:Nn \l__MOdiagram_MO_one_sigma_s_electron_tl { #1 } }
  }

\cs_new_protected:Npn \__MOdiagram_one_mo_s_set_electrons_aux:n #1,#2 \q_stop
  {
    \tl_set:Nn \l__MOdiagram_MO_one_sigma_s_electron_tl { #1 }
    \tl_set:Nn \l__MOdiagram_MO_one_sigmas_s_electron_tl { #2 }
  }

% display 1sigma/sigma* MOs:
\cs_new_protected:Npn \__MOdiagram_one_mo_s:
  {
    \bool_if:NT \l__MOdiagram_molecule_one_mo_s_bool
      {
        \bool_if:nF
          { \l__MOdiagram_one_s_left_bool && \l__MOdiagram_one_s_right_bool }
          { \msg_error:nnxx { MOdiagram } { missing-AO } { 1sMO } { 1s } }
        \__MOdiagram_split_energy:nNN { one_s }
          \l__MOdiagram_molecule_one_sigma_dim
          \l__MOdiagram_molecule_one_sigmas_dim
        \__MOdiagram_energy_range:N \l__MOdiagram_energy_gain_dim
        \__MOdiagram_energy_range:N \l__MOdiagram_energy_loss_dim
        \__MOdiagram_node:n { inner~sep=0 , outer~sep=0 }
          (1sigma)
          at
          (
            \l__MOdiagram_molecule_position_dim ,
            \l__MOdiagram_energy_gain_dim
          )
          {
            \__MOdiagram_get_electron_color:n { 1sigma }
            \__MOdiagram_get_electron_up:n { 1sigma }
            \__MOdiagram_get_electron_down:n { 1sigma }
            \__MOdiagram_AO:ff
              { \tl_use:N \l__MOdiagram_MO_one_sigma_s_electron_tl }
              { \tl_use:N \l__MOdiagram_electron_current_color_tl }
          } ;
        \__MOdiagram_get_orbital_label:n { 1sigma }
        \__MOdiagram_node:n { inner~sep=0 , outer~sep=0 }
          (1sigma*)
          at
          (
            \l__MOdiagram_molecule_position_dim ,
            \l__MOdiagram_energy_loss_dim
          )
          {
            \__MOdiagram_get_electron_color:n { 1sigma* }
            \__MOdiagram_get_electron_up:n { 1sigma* }
            \__MOdiagram_get_electron_down:n { 1sigma* }
            \__MOdiagram_AO:ff
              { \tl_use:N \l__MOdiagram_MO_one_sigmas_s_electron_tl }
              { \tl_use:N \l__MOdiagram_electron_current_color_tl }
          } ;
        \__MOdiagram_get_orbital_label:n { 1sigma* }
        \__MOdiagram_draw:f
          { \l__MOdiagram_lines_tl }
          (1s left.east)  -- (1sigma.west)  (1sigma.east)   -- (1s right.west)
          (1s left.east)  -- (1sigma*.west) (1sigma*.east)  -- (1s right.west) ;
      }
  }

% --------------------------------------------------------------------------- %
% 2sigma orbitals
\dim_new:N \l__MOdiagram_molecule_two_sigma_dim
\dim_new:N \l__MOdiagram_molecule_two_sigmas_dim

\tl_new:N \l__MOdiagram_MO_two_sigma_s_electron_tl
\tl_new:N \l__MOdiagram_MO_two_sigmas_s_electron_tl
\bool_new:N \l__MOdiagram_molecule_two_mo_s_bool

% read 2sMO argument
\cs_new_protected:Npn \__MOdiagram_two_mo_s_set:n #1
  {
    \bool_set_true:N \l__MOdiagram_molecule_two_mo_s_bool
    \tl_if_in:onTF { #1 } { ; }
      { \__MOdiagram_two_mo_s_set_aux:n #1 \q_stop }
      { \__MOdiagram_two_mo_s_set_energy:n { #1 } }
  }

\cs_new_protected:Npn \__MOdiagram_two_mo_s_set_aux:n #1;#2 \q_stop
  {
    \__MOdiagram_two_mo_s_set_energy:n { #1 }
    \__MOdiagram_two_mo_s_set_electrons:n { #2 }
  }

\cs_new_protected:Npn \__MOdiagram_two_mo_s_set_energy:n #1
  {
    \tl_if_in:onTF { #1 } { / }
      { \__MOdiagram_two_mo_s_set_energy_aux:n #1 \q_stop }
      {
        \tl_if_blank:nTF { #1 }
          {
            \dim_set:Nn \l__MOdiagram_molecule_two_sigma_dim { .5 cm }
            \dim_set:Nn \l__MOdiagram_molecule_two_sigmas_dim { .5 cm }
          }
          {
            \dim_set:Nn \l__MOdiagram_molecule_two_sigma_dim { #1 cm }
            \dim_set:Nn \l__MOdiagram_molecule_two_sigmas_dim { #1 cm }
          }
      }
  }

\cs_new_protected:Npn \__MOdiagram_two_mo_s_set_energy_aux:n #1/#2 \q_stop
  {
    \tl_if_blank:nTF { #1 }
      { \dim_set:Nn \l__MOdiagram_molecule_two_sigma_dim { .5 cm } }
      { \dim_set:Nn \l__MOdiagram_molecule_two_sigma_dim { #1 cm } }
    \tl_if_blank:nTF { #2 }
      { \dim_set:Nn \l__MOdiagram_molecule_two_sigmas_dim { .5 cm } }
      { \dim_set:Nn \l__MOdiagram_molecule_two_sigmas_dim { #2 cm } }
  }

\cs_set_nopar:Npn \__MOdiagram_two_mo_s_set_electrons:n #1
  {
    \tl_if_in:onTF { #1 } { , }
      { \__MOdiagram_two_mo_s_set_electrons_aux:n #1 \q_stop }
      { \tl_set:Nn \l__MOdiagram_MO_two_sigma_s_electron_tl { #1 } }
  }

\cs_new_protected:Npn \__MOdiagram_two_mo_s_set_electrons_aux:n #1,#2 \q_stop
  {
    \tl_set:Nn \l__MOdiagram_MO_two_sigma_s_electron_tl { #1 }
    \tl_set:Nn \l__MOdiagram_MO_two_sigmas_s_electron_tl { #2 }
  }

% display 2sigma/sigma* MOs:
\cs_new_protected:Npn \__MOdiagram_two_mo_s:
  {
    \bool_if:NT \l__MOdiagram_molecule_two_mo_s_bool
      {
        \bool_if:nF
          { \l__MOdiagram_two_s_left_bool && \l__MOdiagram_two_s_right_bool }
          { \msg_error:nnxx { MOdiagram } { missing-AO } { 2sMO } { 2s } }
        \__MOdiagram_split_energy:nNN { two_s }
          \l__MOdiagram_molecule_two_sigma_dim
          \l__MOdiagram_molecule_two_sigmas_dim
        \__MOdiagram_energy_range:N \l__MOdiagram_energy_gain_dim
        \__MOdiagram_energy_range:N \l__MOdiagram_energy_loss_dim
        \__MOdiagram_node:n { inner~sep=0 , outer~sep=0 }
          (2sigma)
          at
          (
            \l__MOdiagram_molecule_position_dim ,
            \l__MOdiagram_energy_gain_dim
          )
          {
            \__MOdiagram_get_electron_color:n { 2sigma }
            \__MOdiagram_get_electron_up:n { 2sigma }
            \__MOdiagram_get_electron_down:n { 2sigma }
            \__MOdiagram_AO:ff
              { \tl_use:N \l__MOdiagram_MO_two_sigma_s_electron_tl }
              { \tl_use:N \l__MOdiagram_electron_current_color_tl }
          } ;
        \__MOdiagram_get_orbital_label:n { 2sigma }
        \__MOdiagram_node:n { inner~sep=0 , outer~sep=0 }
          (2sigma*)
          at
          (
            \l__MOdiagram_molecule_position_dim ,
            \l__MOdiagram_energy_loss_dim
          )
          {
            \__MOdiagram_get_electron_color:n { 2sigma* }
            \__MOdiagram_get_electron_up:n { 2sigma* }
            \__MOdiagram_get_electron_down:n { 2sigma* }
            \__MOdiagram_AO:ff
              { \tl_use:N \l__MOdiagram_MO_two_sigmas_s_electron_tl }
              { \tl_use:N \l__MOdiagram_electron_current_color_tl }
          } ;
        \__MOdiagram_get_orbital_label:n { 2sigma* }
        \__MOdiagram_draw:f
          { \l__MOdiagram_lines_tl }
          (2s left.east)  -- (2sigma.west)  (2sigma.east)   -- (2s right.west)
          (2s left.east)  -- (2sigma*.west) (2sigma*.east)  -- (2s right.west) ;
      }
  }

% --------------------------------------------------------------------------- %
% 2psigma and 2ppi orbitals
\dim_new:N \l__MOdiagram_molecule_two_psigma_dim
\dim_new:N \l__MOdiagram_molecule_two_psigmas_dim
\dim_new:N \l__MOdiagram_molecule_two_ppi_dim
\dim_new:N \l__MOdiagram_molecule_two_ppis_dim

\tl_new:N \l__MOdiagram_MO_two_sigma_p_electron_tl
\tl_new:N \l__MOdiagram_MO_two_sigmas_p_electron_tl
\tl_new:N \l__MOdiagram_MO_two_piy_p_electron_tl
\tl_new:N \l__MOdiagram_MO_two_piys_p_electron_tl
\tl_new:N \l__MOdiagram_MO_two_piz_p_electron_tl
\tl_new:N \l__MOdiagram_MO_two_pizs_p_electron_tl

\bool_new:N \l__MOdiagram_molecule_two_mo_p_bool

% read 2pMO argument
\cs_set_nopar:Npn \__MOdiagram_two_mo_p_set:n #1
  {
    \bool_set_true:N \l__MOdiagram_molecule_two_mo_p_bool
    \tl_if_in:onTF { #1 } { ; }
      { \__MOdiagram_two_mo_p_set_aux:n #1 \q_stop }
      { \__MOdiagram_two_mo_p_set_energy:n { #1 } }
  }

\cs_set_nopar:Npn \__MOdiagram_two_mo_p_set_aux:n #1;#2 \q_stop
  {
    \__MOdiagram_two_mo_p_set_energy:n { #1 }
    \__MOdiagram_two_mo_p_set_electrons:n { #2 }
  }

\cs_new_protected:Npn \__MOdiagram_two_mo_p_set_energy:n #1
  {
    \tl_if_in:onTF { #1 } { , }
      { \__MOdiagram_two_mo_p_set_energy_aux:n #1 \q_stop }
      {
        \tl_if_in:onTF { #1 } { / }
          {
            \__MOdiagram_two_mo_p_set_energy_sigma_aux:n #1 \q_stop
            \__MOdiagram_two_mo_p_set_energy_pi:n { .5 }
          }
          {
            \__MOdiagram_two_mo_p_set_energy_sigma:n { #1 }
            \__MOdiagram_two_mo_p_set_energy_pi:n { .5 } 
          }
      }
  }

\cs_new_protected:Npn \__MOdiagram_two_mo_p_set_energy_aux:n #1,#2 \q_stop
  {
    \tl_if_in:onTF { #1 } { / }
      { \__MOdiagram_two_mo_p_set_energy_sigma_aux:n #1 \q_stop }
      { \__MOdiagram_two_mo_p_set_energy_sigma:n { #1 } }
    \tl_if_in:onTF { #2 } { / }
      { \__MOdiagram_two_mo_p_set_energy_pi_aux:n #2 \q_stop }
      { \__MOdiagram_two_mo_p_set_energy_pi:n { #2 } }
  }

\cs_new_protected:Npn \__MOdiagram_two_mo_p_set_energy_sigma:n #1
  {
    \tl_if_blank:nTF { #1 }
      {
        \dim_set:Nn \l__MOdiagram_molecule_two_psigma_dim { 1.5 cm }
        \dim_set:Nn \l__MOdiagram_molecule_two_psigmas_dim { 1.5 cm }
      }
      {
        \dim_set:Nn \l__MOdiagram_molecule_two_psigma_dim { #1 cm }
        \dim_set:Nn \l__MOdiagram_molecule_two_psigmas_dim { #1 cm }
      }
  }

\cs_new_protected:Npn \__MOdiagram_two_mo_p_set_energy_sigma_aux:n #1/#2 \q_stop
  {
    \tl_if_blank:nTF { #1 }
      { \dim_set:Nn \l__MOdiagram_molecule_two_psigma_dim { 1.5 cm } }
      { \dim_set:Nn \l__MOdiagram_molecule_two_psigma_dim { #1 cm } }
    \tl_if_blank:nTF { #2 }
      { \dim_set:Nn \l__MOdiagram_molecule_two_psigmas_dim { 1.5 cm } }
      { \dim_set:Nn \l__MOdiagram_molecule_two_psigmas_dim { #2 cm } }
  }

\cs_new_protected:Npn \__MOdiagram_two_mo_p_set_energy_pi:n #1
  {
    \tl_if_blank:nTF { #1 }
      {
        \dim_set:Nn \l__MOdiagram_molecule_two_ppi_dim { .5 cm }
        \dim_set:Nn \l__MOdiagram_molecule_two_ppis_dim { .5 cm }
      }
      {
        \dim_set:Nn \l__MOdiagram_molecule_two_ppi_dim { #1 cm }
        \dim_set:Nn \l__MOdiagram_molecule_two_ppis_dim { #1 cm }
      }
  }

\cs_new_protected:Npn \__MOdiagram_two_mo_p_set_energy_pi_aux:n #1/#2 \q_stop
  {
    \tl_if_blank:nTF { #1 }
      { \dim_set:Nn \l__MOdiagram_molecule_two_ppi_dim { .5 cm } }
      { \dim_set:Nn \l__MOdiagram_molecule_two_ppi_dim { #1 cm } }
    \tl_if_blank:nTF { #2 }
      { \dim_set:Nn \l__MOdiagram_molecule_two_ppis_dim { .5 cm } }
      { \dim_set:Nn \l__MOdiagram_molecule_two_ppis_dim { #2 cm } }
  }

\NewDocumentCommand \__MOdiagram_two_mo_p_set_electrons:n
  { > { \SplitArgument { 5 } { , } } m }
  { \__MOdiagram_two_mo_p_set_electrons_aux:n #1 }

\cs_new_protected:Npn \__MOdiagram_two_mo_p_set_electrons_aux:n #1#2#3#4#5#6
  {
    \tl_set:Nn \l__MOdiagram_MO_two_sigma_p_electron_tl  { #1 }
    \tl_set:Nn \l__MOdiagram_MO_two_sigmas_p_electron_tl { #6 }
    \tl_set:Nn \l__MOdiagram_MO_two_piy_p_electron_tl    { #2 }
    \tl_set:Nn \l__MOdiagram_MO_two_piys_p_electron_tl   { #4 }
    \tl_set:Nn \l__MOdiagram_MO_two_piz_p_electron_tl    { #3 }
    \tl_set:Nn \l__MOdiagram_MO_two_pizs_p_electron_tl   { #5 }
  }

% display 2sigma+pi/sigma*+pi* orbitals:
\cs_new_protected:Npn \__MOdiagram_two_mo_p:
  {
    \bool_if:NT \l__MOdiagram_molecule_two_mo_p_bool
      {
        \bool_if:nF
          { \l__MOdiagram_two_p_left_bool && \l__MOdiagram_two_p_right_bool }
          { \msg_error:nnxx { MOdiagram } { missing-AO } { 2pMO } { 2p } }
        \__MOdiagram_split_energy:nNN { two_p }
          \l__MOdiagram_molecule_two_psigma_dim
          \l__MOdiagram_molecule_two_psigmas_dim
        \__MOdiagram_energy_range:N \l__MOdiagram_energy_gain_dim
        \__MOdiagram_energy_range:N \l__MOdiagram_energy_loss_dim
        \__MOdiagram_node:n { inner~sep=0 , outer~sep=0 }
          (2psigma)
          at
          (
            \l__MOdiagram_molecule_position_dim ,
            \l__MOdiagram_energy_gain_dim
          )
          {
            \__MOdiagram_get_electron_color:n { 2psigma }
            \__MOdiagram_get_electron_up:n { 2psigma }
            \__MOdiagram_get_electron_down:n { 2psigma }
            \__MOdiagram_AO:ff
              { \tl_use:N \l__MOdiagram_MO_two_sigma_p_electron_tl }
              { \tl_use:N \l__MOdiagram_electron_current_color_tl }
          } ;
        \__MOdiagram_get_orbital_label:n { 2psigma }
        \__MOdiagram_node:n { inner~sep=0 , outer~sep=0 }
          (2psigma*)
          at
          (
            \l__MOdiagram_molecule_position_dim ,
            \l__MOdiagram_energy_loss_dim
          )
          {
            \__MOdiagram_get_electron_color:n { 2psigma* }
            \__MOdiagram_get_electron_up:n { 2psigma* }
            \__MOdiagram_get_electron_down:n { 2psigma* }
            \__MOdiagram_AO:ff
              { \tl_use:N \l__MOdiagram_MO_two_sigmas_p_electron_tl }
              { \tl_use:N \l__MOdiagram_electron_current_color_tl }
          } ;
        \__MOdiagram_get_orbital_label:n { 2psigma* }
        \__MOdiagram_split_energy:nNN { two_p }
          \l__MOdiagram_molecule_two_ppi_dim
          \l__MOdiagram_molecule_two_ppis_dim
        \__MOdiagram_node:n { inner~sep=0 , outer~sep=0 }
          (2piy)
          at
          (
            \l__MOdiagram_molecule_position_dim - \l__MOdiagram_AO_width_dim ,
            \l__MOdiagram_energy_gain_dim
          )
          {
            \__MOdiagram_get_electron_color:n { 2piy }
            \__MOdiagram_get_electron_up:n { 2piy }
            \__MOdiagram_get_electron_down:n { 2piy }
            \__MOdiagram_AO:ff
              { \tl_use:N \l__MOdiagram_MO_two_piy_p_electron_tl }
              { \tl_use:N \l__MOdiagram_electron_current_color_tl }
          } ;
        \__MOdiagram_get_orbital_label:n { 2piy }
        \__MOdiagram_node:n { inner~sep=0 , outer~sep=0 }
          (2piy*)
          at
          (
            \l__MOdiagram_molecule_position_dim - \l__MOdiagram_AO_width_dim ,
            \l__MOdiagram_energy_loss_dim
          )
          {
            \__MOdiagram_get_electron_color:n { 2piy* }
            \__MOdiagram_get_electron_up:n { 2piy* }
            \__MOdiagram_get_electron_down:n { 2piy* }
            \__MOdiagram_AO:ff
              { \tl_use:N \l__MOdiagram_MO_two_piys_p_electron_tl }
              { \tl_use:N \l__MOdiagram_electron_current_color_tl }
          } ;
        \__MOdiagram_get_orbital_label:n { 2piy* }
        \__MOdiagram_node:n { inner~sep=0 , outer~sep=0 }
          (2piz)
          at
          (
            \l__MOdiagram_molecule_position_dim + \l__MOdiagram_AO_width_dim ,
            \l__MOdiagram_energy_gain_dim
          )
          {
            \__MOdiagram_get_electron_color:n { 2piz }
            \__MOdiagram_get_electron_up:n { 2piz }
            \__MOdiagram_get_electron_down:n { 2piz }
            \__MOdiagram_AO:ff
              { \tl_use:N \l__MOdiagram_MO_two_piz_p_electron_tl }
              { \tl_use:N \l__MOdiagram_electron_current_color_tl }
          } ;
        \__MOdiagram_get_orbital_label:n { 2piz }
        \__MOdiagram_node:n { inner~sep=0 , outer~sep=0 }
          (2piz*)
          at
          (
            \l__MOdiagram_molecule_position_dim + \l__MOdiagram_AO_width_dim ,
            \l__MOdiagram_energy_loss_dim
          )
          {
            \__MOdiagram_get_electron_color:n { 2piz* }
            \__MOdiagram_get_electron_up:n { 2piz* }
            \__MOdiagram_get_electron_down:n { 2piz* }
            \__MOdiagram_AO:ff
              { \tl_use:N \l__MOdiagram_MO_two_pizs_p_electron_tl }
              { \tl_use:N \l__MOdiagram_electron_current_color_tl }
          } ;
        \__MOdiagram_get_orbital_label:n { 2piz* }
        \__MOdiagram_draw:f
          { \l__MOdiagram_lines_tl }
          (2pz left.east)  -- (2psigma.west)  (2psigma.east)   -- (2px right.west)
          (2pz left.east)  -- (2psigma*.west) (2psigma*.east)  -- (2px right.west)
          (2pz left.east)  -- (2piy.west)     (2piz.east)      -- (2px right.west)
          (2pz left.east)  -- (2piy*.west)    (2piz*.east)     -- (2px right.west) ;
      }
  }

% --------------------------------------------------------------------------- %
% draw actual AO / MO
\tl_new:N \l__MOdiagram_electron_color_tl

\cs_new_protected:Npn \__MOdiagram_AO:nn #1#2
  {
    \group_begin:
      \tl_set:Nn \l__MOdiagram_electron_color_tl { #2 }
      \tikzpicture
        \bool_if:NT \l__MOdiagram_AO_fancy_bool
          {
            \draw (0,0) -- ++(-.5*\l__MOdiagram_AO_width_dim,0) ;
            \draw (2pt+\l__MOdiagram_AO_width_dim,0)
                  -- ++(.5*\l__MOdiagram_AO_width_dim,0) ;
          }
        \bool_if:NT \l__MOdiagram_AO_circle_bool
          {
            \draw (-.4142pt,0) ++(-.2071*\l__MOdiagram_AO_width_dim,0)
                  -- ++(-.25*\l__MOdiagram_AO_width_dim,0) ;
            \draw (2.4142pt,0) ++(1.2071*\l__MOdiagram_AO_width_dim,0)
                  -- ++(.25*\l__MOdiagram_AO_width_dim,0) ;
          }
        \__MOdiagram_node:x
          {
            inner~sep = 0 ,
            \bool_if:NT \l__MOdiagram_AO_square_bool { draw } ,
            \bool_if:NT \l__MOdiagram_AO_circle_bool { circle , draw } ,
            minimum~size =
              \bool_if:NTF \l__MOdiagram_AO_square_bool
                { 2pt+\l__MOdiagram_AO_width_dim }
                {
                  \bool_if:NTF \l__MOdiagram_AO_circle_bool
                    { 1.4142*(2pt+\l__MOdiagram_AO_width_dim) }
                    { \l__MOdiagram_AO_width_dim }
                } ,
            \bool_if:NT \l__MOdiagram_AO_round_bool
              { rounded~corners=2pt }
          }
          at (.5*\l__MOdiagram_AO_width_dim+1pt,0)
          {
            \tikz
              {
                \bool_if:nTF { \l__MOdiagram_AO_square_bool || \l__MOdiagram_AO_circle_bool }
                  { \draw[draw=none] (0,0) -- ++(\l__MOdiagram_AO_width_dim,0) ; }
                  { \draw (0,0) -- ++(\l__MOdiagram_AO_width_dim,0) ; }
                \tl_set:Nn \l__MOdiagram_tmpa_tl { #1 }
                \tl_remove_all:Nn \l__MOdiagram_tmpa_tl { ~ }
                \str_case:Vnn \l__MOdiagram_tmpa_tl
                  {
                    { up }
                      {
                        \__MOdiagram_draw:f
                          { -left~to,semithick , \l__MOdiagram_electron_color_tl , inner~sep=0,outer~sep=0 }
                          (\l__MOdiagram_AO_up_electron_tl*\l__MOdiagram_AO_width_dim,-.4*\l__MOdiagram_AO_width_dim)
                          -- ++(0,.8*\l__MOdiagram_AO_width_dim) ;
                      }
                    { down }
                      {
                        \__MOdiagram_draw:f
                          { -left~to,semithick , \l__MOdiagram_electron_color_tl }
                          (\l__MOdiagram_AO_down_electron_tl*\l__MOdiagram_AO_width_dim,.4*\l__MOdiagram_AO_width_dim)
                          -- ++(0,-.8*\l__MOdiagram_AO_width_dim) ;
                      }
                    { pair }
                      {
                        \__MOdiagram_draw:f
                          { -left~to,semithick , \l__MOdiagram_electron_color_tl }
                          (\l__MOdiagram_AO_up_electron_tl*\l__MOdiagram_AO_width_dim,-.4*\l__MOdiagram_AO_width_dim)
                          -- ++(0,.8*\l__MOdiagram_AO_width_dim) ;
                        \__MOdiagram_draw:f
                          { -left~to,semithick , \l__MOdiagram_electron_color_tl }
                          (\l__MOdiagram_AO_down_electron_tl*\l__MOdiagram_AO_width_dim,.4*\l__MOdiagram_AO_width_dim)
                          -- ++(0,-.8*\l__MOdiagram_AO_width_dim) ;
                      }
                  }
                  {}
              }
          } ;
      \endtikzpicture
    \group_end:
  }
\cs_generate_variant:Nn \__MOdiagram_AO:nn { ff }

% -------------------------------------------------------------------------- %
% per default disable all AOs / MOs
\cs_new_protected:Npn \__MOdiagram_atom_disable:
  {
    \bool_set_false:N \l__MOdiagram_atom_one_s_bool
    \bool_set_false:N \l__MOdiagram_atom_two_s_bool
    \bool_set_false:N \l__MOdiagram_atom_two_p_bool
%     \bool_set_false:N \l__MOdiagram_atom_three_s_bool
%     \bool_set_false:N \l__MOdiagram_atom_three_p_bool
  }

\cs_new_protected:Npn \__MOdiagram_molecule_disable:
  { \bool_set_false:N \l__MOdiagram_molecule_one_mo_s_bool }

% --------------------------------------------------------------------------- %
% arbitrary placement of AOs / MOs
\dim_new:N \l__MOdiagram_AO_dim % y
\dim_new:N \l__MOdiagram_AO_position_dim % x

\dim_new:N \l__MOdiagram_AO_px_shift_dim
\dim_new:N \l__MOdiagram_AO_py_shift_dim
\dim_new:N \l__MOdiagram_AO_pz_shift_dim

\tl_new:N \l__MOdiagram_AO_px_electron_tl
\tl_new:N \l__MOdiagram_AO_py_electron_tl
\tl_new:N \l__MOdiagram_AO_pz_electron_tl

\tl_new:N \l__MOdiagram_AO_x_electron_color_tl
\tl_new:N \l__MOdiagram_AO_y_electron_color_tl
\tl_new:N \l__MOdiagram_AO_z_electron_color_tl

\bool_new:N \l__MOdiagram_AO_label_bool
\bool_new:N \l__MOdiagram_AO_x_label_bool
\bool_new:N \l__MOdiagram_AO_y_label_bool
\bool_new:N \l__MOdiagram_AO_z_label_bool

\tl_new:N \l__MOdiagram_AO_x_label_tl
\tl_new:N \l__MOdiagram_AO_y_label_tl
\tl_new:N \l__MOdiagram_AO_z_label_tl

\bool_new:N \l__MOdiagram_AO_up_electron_bool
\bool_new:N \l__MOdiagram_AO_x_up_electron_bool
\bool_new:N \l__MOdiagram_AO_y_up_electron_bool
\bool_new:N \l__MOdiagram_AO_z_up_electron_bool
\tl_new:N \l__MOdiagram_AO_x_up_electron_tl
\tl_new:N \l__MOdiagram_AO_y_up_electron_tl
\tl_new:N \l__MOdiagram_AO_z_up_electron_tl

\bool_new:N \l__MOdiagram_AO_down_electron_bool
\bool_new:N \l__MOdiagram_AO_x_down_electron_bool
\bool_new:N \l__MOdiagram_AO_y_down_electron_bool
\bool_new:N \l__MOdiagram_AO_z_down_electron_bool
\tl_new:N \l__MOdiagram_AO_x_down_electron_tl
\tl_new:N \l__MOdiagram_AO_y_down_electron_tl
\tl_new:N \l__MOdiagram_AO_z_down_electron_tl

\tl_new:N \l__MOdiagram_AO_name_tl

\bool_new:N \l__MOdiagram_AO_p_bool
\bool_new:N \l__MOdiagram_AO_left_bool

\int_new:N \g__MOdiagram_AO_name_int

% read argument in s case:
\cs_new_protected:Npn \__MOdiagram_AO_s_set:n #1
  {
    \tl_if_in:onTF { #1 } { ; }
      { \__MOdiagram_AO_s_set_aux:n #1 \q_stop }
      {
        \dim_set:Nn \l__MOdiagram_AO_dim { #1 cm }
        \tl_set:Nn \l__MOdiagram_AO_px_electron_tl { pair }
      }
  }

\cs_new_protected:Npn \__MOdiagram_AO_s_set_aux:n #1;#2 \q_stop
  {
    \dim_set:Nn \l__MOdiagram_AO_dim { #1 cm }
    \tl_set:Nn \l__MOdiagram_AO_px_electron_tl { #2 }
  }

% read argument in p case:
\cs_new_protected:Npn \__MOdiagram_AO_p_set:n #1
  {
    \tl_if_in:onTF { #1 } { ; }
      { \__MOdiagram_AO_p_set_aux:n #1 \q_stop }
      {
        \dim_set:Nn \l__MOdiagram_AO_dim { #1 cm }
        \tl_set:Nn \l__MOdiagram_AO_px_electron_tl { pair }
        \tl_set:Nn \l__MOdiagram_AO_py_electron_tl { pair }
        \tl_set:Nn \l__MOdiagram_AO_pz_electron_tl { pair }
      }
  }

\cs_new_protected:Npn \__MOdiagram_AO_p_set_aux:n #1;#2 \q_stop
  {
    \dim_set:Nn \l__MOdiagram_AO_dim { #1 cm }
    \__MOdiagram_AO_p_set_electrons:n { #2 }
  }
\NewDocumentCommand \__MOdiagram_AO_p_set_electrons:n
  { > { \SplitArgument { 2 } { , } } m }
  { \__MOdiagram_AO_p_set_electrons_aux:n #1 }

\cs_new_protected:Npn \__MOdiagram_AO_p_set_electrons_aux:n #1#2#3
  {
    \tl_set:Nn \l__MOdiagram_AO_px_electron_tl { #1 }
    \tl_set:Nn \l__MOdiagram_AO_py_electron_tl { #2 }
    \tl_set:Nn \l__MOdiagram_AO_pz_electron_tl { #3 }
  }

\cs_new_protected:Npn \__MOdiagram_AO_get_orbital_x_label:n #1
  {
    \bool_if:nT { \l__MOdiagram_AO_x_label_bool || \l__MOdiagram_AO_label_bool }
      {
        \__MOdiagram_node:x
          { below , \tl_use:N \l__MOdiagram_orbital_label_style_tl }
          at ( #1 . south )
          {
            \tl_use:N \l__MOdiagram_orbital_label_fontsize_tl
            \tl_use:N \l__MOdiagram_AO_x_label_tl
          } ;
      }
  }
\cs_generate_variant:Nn \__MOdiagram_AO_get_orbital_x_label:n { o }

\cs_new_protected:Npn \__MOdiagram_AO_get_orbital_y_label:n #1
  {
    \bool_if:nT { \l__MOdiagram_AO_y_label_bool || \l__MOdiagram_AO_label_bool }
      {
        \__MOdiagram_node:x
          { below , \tl_use:N \l__MOdiagram_orbital_label_style_tl }
          at ( #1 . south )
          {
            \tl_use:N \l__MOdiagram_orbital_label_fontsize_tl
            \tl_use:N \l__MOdiagram_AO_y_label_tl
          } ;
      }
  }
\cs_generate_variant:Nn \__MOdiagram_AO_get_orbital_y_label:n { o }

\cs_new_protected:Npn \__MOdiagram_AO_get_orbital_z_label:n #1
  {
    \bool_if:nT { \l__MOdiagram_AO_z_label_bool || \l__MOdiagram_AO_label_bool }
      {
        \__MOdiagram_node:x
          { below , \tl_use:N \l__MOdiagram_orbital_label_style_tl }
          at ( #1 . south )
          {
            \tl_use:N \l__MOdiagram_orbital_label_fontsize_tl
            \tl_use:N \l__MOdiagram_AO_z_label_tl
          } ;
      }
  }
\cs_generate_variant:Nn \__MOdiagram_AO_get_orbital_z_label:n { o }

% these are going to be our arguments
\keys_define:nn { MOdiagram / AO }
  {
    type     .choice: ,
    type / s .code:n = { \bool_set_false:N \l__MOdiagram_AO_p_bool } ,
    type / p .code:n = { \bool_set_true:N \l__MOdiagram_AO_p_bool }
  }

\keys_define:nn { MOdiagram / AO / properties }
  {
    color          .code:n   =
      {
        \tl_set:Nn \l__MOdiagram_AO_x_electron_color_tl { #1 }
        \tl_set:Nn \l__MOdiagram_AO_y_electron_color_tl { #1 }
        \tl_set:Nn \l__MOdiagram_AO_z_electron_color_tl { #1 }
      } ,
    color[x]       .tl_set:N = \l__MOdiagram_AO_x_electron_color_tl ,
    color[y]       .tl_set:N = \l__MOdiagram_AO_y_electron_color_tl ,
    color[z]       .tl_set:N = \l__MOdiagram_AO_z_electron_color_tl ,
    label          .code:n   =
      {
        \bool_set_true:N \l__MOdiagram_AO_label_bool
        \tl_set:Nn \l__MOdiagram_AO_x_label_tl { #1 }
        \tl_set:Nn \l__MOdiagram_AO_y_label_tl { #1 }
        \tl_set:Nn \l__MOdiagram_AO_z_label_tl { #1 }
      } ,
    label[x]       .code:n   =
      {
        \bool_set_true:N \l__MOdiagram_AO_x_label_bool
        \tl_set:Nn \l__MOdiagram_AO_x_label_tl { #1 }
      } ,
    label[y]       .code:n   =
      {
        \bool_set_true:N \l__MOdiagram_AO_y_label_bool
        \tl_set:Nn \l__MOdiagram_AO_y_label_tl { #1 }
      } ,
    label[z]       .code:n   =
      {
        \bool_set_true:N \l__MOdiagram_AO_z_label_bool
        \tl_set:Nn \l__MOdiagram_AO_z_label_tl { #1 }
      } ,
    up-el-pos      .code:n   =
      {
        \bool_set_true:N \l__MOdiagram_AO_up_electron_bool
        \tl_set:Nn \l__MOdiagram_AO_x_up_electron_tl { #1 }
        \tl_set:Nn \l__MOdiagram_AO_y_up_electron_tl { #1 }
        \tl_set:Nn \l__MOdiagram_AO_z_up_electron_tl { #1 }
      } ,
    up-el-pos[x]   .code:n   =
      {
        \bool_set_true:N \l__MOdiagram_AO_x_up_electron_bool
        \tl_set:Nn \l__MOdiagram_AO_x_up_electron_tl { #1 }
      } ,
    up-el-pos[y]   .code:n   =
      {
        \bool_set_true:N \l__MOdiagram_AO_y_up_electron_bool
        \tl_set:Nn \l__MOdiagram_AO_y_up_electron_tl { #1 }
      } ,
    up-el-pos[z]   .code:n   =
      {
        \bool_set_true:N \l__MOdiagram_AO_z_up_electron_bool
        \tl_set:Nn \l__MOdiagram_AO_y_up_electron_tl { #1 }
      } ,
    down-el-pos    .code:n   =
      {
        \bool_set_true:N \l__MOdiagram_AO_down_electron_bool
        \tl_set:Nn \l__MOdiagram_AO_x_down_electron_tl { #1 }
        \tl_set:Nn \l__MOdiagram_AO_y_down_electron_tl { #1 }
        \tl_set:Nn \l__MOdiagram_AO_z_down_electron_tl { #1 }
      } ,
    down-el-pos[x] .code:n   =
      {
        \bool_set_true:N \l__MOdiagram_AO_x_down_electron_bool
        \tl_set:Nn \l__MOdiagram_AO_x_down_electron_tl { #1 }
      } ,
    down-el-pos[y] .code:n   =
      {
        \bool_set_true:N \l__MOdiagram_AO_y_down_electron_bool
        \tl_set:Nn \l__MOdiagram_AO_y_down_electron_tl { #1 }
      } ,
    down-el-pos[z] .code:n   =
      {
        \bool_set_true:N \l__MOdiagram_AO_z_down_electron_bool
        \tl_set:Nn \l__MOdiagram_AO_z_down_electron_tl { #1 }
      }
  }

% AO[<name>](<x-coord>){<type>}[<keyval>]{<AO-spec>}
\NewDocumentCommand \__MOdiagram_arbitrary_AO: { o D(){0cm} m o m }
  {
    \group_begin:
    \IfNoValueTF { #1 }
      {
        \int_gincr:N \g__MOdiagram_AO_name_int
        \tl_set:Nn \l__MOdiagram_AO_name_tl
          { AO \int_use:N \g__MOdiagram_AO_name_int }
      }
      { \tl_set:Nn \l__MOdiagram_AO_name_tl { #1 } }
    \IfNoValueF { #4 }
      { \keys_set:nn { MOdiagram / AO / properties } { #4 } }
    \keys_set:nn { MOdiagram / AO } { type = #3 }
    \bool_if:NTF \l__MOdiagram_AO_p_bool
      { \__MOdiagram_AO_p_set:n { #5 } }
      { \__MOdiagram_AO_s_set:n { #5 } }
    \dim_set:Nn \l__MOdiagram_AO_position_dim { #2 }
    \__MOdiagram_p_orbitals_shift:nnn { 0 } { 2 } { 4 }
    \__MOdiagram_energy_range:N \l__MOdiagram_AO_dim
    \__MOdiagram_node:n { inner~sep=0 , outer~sep=0 }
      (
        \tl_use:N \l__MOdiagram_AO_name_tl
        \bool_if:NT \l__MOdiagram_AO_p_bool { x }
      )
      at
      (
        \l__MOdiagram_AO_position_dim + \l__MOdiagram_atom_px_shift_dim ,
        \l__MOdiagram_AO_dim
      )
      {
        \bool_if:nT
          {
            \l__MOdiagram_AO_up_electron_bool ||
            \l__MOdiagram_AO_x_up_electron_bool
          }
          {
            \__MOdiagram_AO_place_electron:nx { 0 }
              { \tl_use:N \l__MOdiagram_AO_x_up_electron_tl }
          }
        \bool_if:nT
          {
            \l__MOdiagram_AO_down_electron_bool ||
            \l__MOdiagram_AO_x_down_electron_bool
          }
          {
            \__MOdiagram_AO_place_electron:nx { 1 }
              { \tl_use:N \l__MOdiagram_AO_x_down_electron_tl }
          }
        \__MOdiagram_AO:ff
          { \tl_use:N \l__MOdiagram_AO_px_electron_tl }
          { \tl_use:N \l__MOdiagram_AO_x_electron_color_tl }
      } ;
    \__MOdiagram_AO_get_orbital_x_label:o
      {
        \tl_use:N \l__MOdiagram_AO_name_tl
        \bool_if:NT \l__MOdiagram_AO_p_bool { x }
      }
    \bool_if:NT \l__MOdiagram_AO_p_bool
      {
        \__MOdiagram_node:n { inner~sep=0 , outer~sep=0 }
          ( \tl_use:N \l__MOdiagram_AO_name_tl y )
          at
          (
            \l__MOdiagram_AO_position_dim + \l__MOdiagram_atom_py_shift_dim ,
            \l__MOdiagram_AO_dim
          )
          {
            \bool_if:nT
              {
                \l__MOdiagram_AO_up_electron_bool ||
                \l__MOdiagram_AO_y_up_electron_bool
              }
              {
                \__MOdiagram_AO_place_electron:nx { 0 }
                  { \tl_use:N \l__MOdiagram_AO_y_up_electron_tl }
              }
            \bool_if:nT
              {
                \l__MOdiagram_AO_down_electron_bool ||
                \l__MOdiagram_AO_y_down_electron_bool
              }
              {
                \__MOdiagram_AO_place_electron:nx { 1 }
                  { \tl_use:N \l__MOdiagram_AO_y_down_electron_tl }
              }
            \__MOdiagram_AO:ff
              { \tl_use:N \l__MOdiagram_AO_py_electron_tl }
              { \tl_use:N \l__MOdiagram_AO_y_electron_color_tl }
          } ;
        % `o' expansion doesn't seem to make sense here:
        \__MOdiagram_AO_get_orbital_y_label:o { \tl_use:N \l__MOdiagram_AO_name_tl y }
        \__MOdiagram_node:n { inner~sep=0 , outer~sep=0 }
          ( \tl_use:N \l__MOdiagram_AO_name_tl z )
          at
          (
            \l__MOdiagram_AO_position_dim + \l__MOdiagram_atom_pz_shift_dim ,
            \l__MOdiagram_AO_dim
          )
          {
            \bool_if:nT
              {
                \l__MOdiagram_AO_up_electron_bool ||
                \l__MOdiagram_AO_z_up_electron_bool
              }
              {
                \__MOdiagram_AO_place_electron:nx { 0 }
                  { \tl_use:N \l__MOdiagram_AO_z_up_electron_tl }
              }
            \bool_if:nT
              {
                \l__MOdiagram_AO_down_electron_bool ||
                \l__MOdiagram_AO_z_down_electron_bool
              }
              {
                \__MOdiagram_AO_place_electron:nx { 1 }
                  { \tl_use:N \l__MOdiagram_AO_z_down_electron_tl }
              }
            \__MOdiagram_AO:ff
              { \tl_use:N \l__MOdiagram_AO_pz_electron_tl }
              { \tl_use:N \l__MOdiagram_AO_z_electron_color_tl }
          } ;
        \__MOdiagram_AO_get_orbital_z_label:o
          { \tl_use:N \l__MOdiagram_AO_name_tl z }
      }
    \group_end:
  }

% --------------------------------------------------------------------------- %
% connect arbitrary AOs / MOs
\NewDocumentCommand \connect { m }
  {
    \clist_map_variable:nNn { #1 } \l__MOdiagram_tmpa_tl
      {
        \tl_remove_all:Nn \l__MOdiagram_tmpa_tl { ~ }
        \tl_if_blank:VF \l__MOdiagram_tmpa_tl
          {
            \__MOdiagram_detect_nodes:x { \l__MOdiagram_tmpa_tl }
             \tl_if_in:NnF \l__MOdiagram_node_A_tl { . }
               { \tl_put_right:Nn \l__MOdiagram_node_A_tl { . east } }
             \tl_if_in:NnF \l__MOdiagram_node_B_tl { . }
               { \tl_put_right:Nn \l__MOdiagram_node_B_tl { . west } }
            \__MOdiagram_draw_connection:xxx
              { \tl_use:N \l__MOdiagram_lines_tl }
              { \tl_use:N \l__MOdiagram_node_A_tl }
              { \tl_use:N \l__MOdiagram_node_B_tl }
          }
      }
  }

\NewDocumentCommand \__MOdiagram_detect_nodes:n { > { \SplitArgument { 1 } { & } } m }
  { \__MOdiagram_detect_nodes_aux_i:nn #1 }
\cs_generate_variant:Nn \__MOdiagram_detect_nodes:n { x }

\cs_new_protected:Npn \__MOdiagram_detect_nodes_aux_i:nn #1#2
  {
    \tl_set:Nn \l__MOdiagram_node_A_tl { #1 }
    \tl_set:Nn \l__MOdiagram_node_B_tl { #2 }
  }

\cs_new:Npn \__MOdiagram_draw_connection:nnn #1#2#3
  { \draw[#1] (#2) -- (#3) ; }
\cs_generate_variant:Nn \__MOdiagram_draw_connection:nnn { xxx }

% --------------------------------------------------------------------------- %
% orbital labels
\prop_new:N \l__MOdiagram_orbital_label_prop
\tl_set:Nn \l__MOdiagram_orbital_label_fontsize_tl { \small }

\cs_new:Npn \__MOdiagram_orbital_label_set:n #1
  { \keys_set:nn { MOdiagram / label } { #1 } }

\cs_new_protected:Npn \__MOdiagram_get_orbital_label:n #1
  {
    \tl_clear:N \l__MOdiagram_tmpa_tl
    \tl_clear:N \l__MOdiagram_tmpb_tl
    \prop_get:NnNT \l__MOdiagram_orbital_label_prop { #1 } \l__MOdiagram_tmpa_tl
      {
        \__MOdiagram_node:x
          { below , \tl_use:N \l__MOdiagram_orbital_label_style_tl }
          at ( #1 . south )
          {
            \tl_use:N \l__MOdiagram_orbital_label_fontsize_tl
            \tl_use:N \l__MOdiagram_tmpa_tl
          } ;
      }
  }

\keys_define:nn { MOdiagram / label }
  {
    1sleft   .code:n =
      { \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 1sleft }   { #1 } } ,
    1sright  .code:n =
      { \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 1sright }  { #1 } } ,
    2sleft   .code:n =
      { \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2sleft }   { #1 } } ,
    2sright  .code:n =
      { \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2sright }  { #1 } } ,
    2pxleft  .code:n =
      { \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2pxleft }  { #1 } } ,
    2pxright .code:n =
      { \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2pxright } { #1 } } ,
    2pyleft  .code:n =
      { \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2pyleft }  { #1 } } ,
    2pyright .code:n =
      { \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2pyright } { #1 } } ,
    2pzleft  .code:n =
      { \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2pzleft }  { #1 } } ,
    2pzright .code:n =
      { \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2pzright } { #1 } } ,
    1sigma   .code:n =
      { \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 1sigma }   { #1 } } ,
    1sigma*  .code:n =
      { \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 1sigma* }  { #1 } } ,
    2sigma   .code:n =
      { \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2sigma }   { #1 } } ,
    2sigma*  .code:n =
      { \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2sigma* }  { #1 } } ,
    2psigma  .code:n =
      { \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2psigma }  { #1 } } ,
    2psigma* .code:n =
      { \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2psigma* } { #1 } } ,
    2piy     .code:n =
      { \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2piy }     { #1 } } ,
    2piy*    .code:n =
      { \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2piy* }    { #1 } } ,
    2piz     .code:n =
      { \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2piz }     { #1 } } ,
    2piz*    .code:n =
      { \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2piz* }    { #1 } }
  }

\char_set_catcode_math_subscript:N \@
\cs_new_protected:Npn \__MOdiagram_set_labels:
  {
    \bool_if:NT \l__MOdiagram_AO_labels_bool
      {
        \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 1sleft }   { 1s }
        \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 1sright }  { 1s }
        \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2sleft }   { 2s }
        \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2sright }  { 2s }
        \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2pxleft }  { 2p$@x$ }
        \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2pxright } { 2p$@x$ }
        \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2pyleft }  { 2p$@y$ }
        \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2pyright } { 2p$@y$ }
        \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2pzleft }  { 2p$@z$ }
        \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2pzright } { 2p$@z$ }
        \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 1sigma }   { 1\chemsigma$@s$ }
        \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 1sigma* }  { 1\chemsigma$^*@s$ }
        \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2sigma }   { 2\chemsigma$@s$ }
        \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2sigma* }  { 2\chemsigma$^*@s$ }
        \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2psigma }  { 2\chemsigma$@x$ }
        \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2psigma* } { 2\chemsigma$^*@x$ }
        \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2piy }     { 2\chempi$@y$ }
        \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2piy* }    { 2\chempi$^*@y$ }
        \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2piz }     { 2\chempi$@z$ }
        \prop_put:Nnn \l__MOdiagram_orbital_label_prop { 2piz* }    { 2\chempi$^*@z$ }
      }
  }
\char_set_catcode_letter:N \@

% --------------------------------------------------------------------------- %
% electron colours
\prop_new:N \l__MOdiagram_electron_color_prop
\tl_new:N \l__MOdiagram_electron_current_color_tl

\cs_new:Npn \__MOdiagram_electron_color_set:n #1
  { \keys_set:nn { MOdiagram / color } { #1 } }

\cs_new_protected:Npn \__MOdiagram_get_electron_color:n #1
  {
    \tl_clear:N \l__MOdiagram_tmpa_tl
    \tl_clear:N \l__MOdiagram_tmpb_tl
    \prop_get:NnNT \l__MOdiagram_electron_color_prop { #1 } \l__MOdiagram_tmpa_tl
      { \tl_set_eq:NN \l__MOdiagram_electron_current_color_tl \l__MOdiagram_tmpa_tl }
  }

\keys_define:nn { MOdiagram / color }
  {
    1sleft   .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_color_prop { 1sleft }   { #1 } } ,
    1sright  .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_color_prop { 1sright }  { #1 } } ,
    2sleft   .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_color_prop { 2sleft }   { #1 } } ,
    2sright  .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_color_prop { 2sright }  { #1 } } ,
    2pxleft  .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_color_prop { 2pxleft }  { #1 } } ,
    2pxright .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_color_prop { 2pxright } { #1 } } ,
    2pyleft  .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_color_prop { 2pyleft }  { #1 } } ,
    2pyright .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_color_prop { 2pyright } { #1 } } ,
    2pzleft  .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_color_prop { 2pzleft }  { #1 } } ,
    2pzright .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_color_prop { 2pzright } { #1 } } ,
    1sigma   .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_color_prop { 1sigma }   { #1 } } ,
    1sigma*  .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_color_prop { 1sigma* }  { #1 } } ,
    2sigma   .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_color_prop { 2sigma }   { #1 } } ,
    2sigma*  .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_color_prop { 2sigma* }  { #1 } } ,
    2psigma  .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_color_prop { 2psigma }  { #1 } } ,
    2psigma* .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_color_prop { 2psigma* } { #1 } } ,
    2piy     .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_color_prop { 2piy }     { #1 } } ,
    2piy*    .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_color_prop { 2piy* }    { #1 } } ,
    2piz     .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_color_prop { 2piz }     { #1 } } ,
    2piz*    .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_color_prop { 2piz* }    { #1 } }
  }

% --------------------------------------------------------------------------- %
% electron positions
\prop_new:N \l__MOdiagram_electron_up_prop

\cs_new:Npn \__MOdiagram_electron_up_set:n #1
  { \keys_set:nn { MOdiagram / up-pos } { #1 } }

\cs_new_protected:Npn \__MOdiagram_get_electron_up:n #1
  {
    \tl_clear:N \l__MOdiagram_tmpa_tl
    \tl_clear:N \l__MOdiagram_tmpb_tl
    \prop_get:NnNT \l__MOdiagram_electron_up_prop { #1 } \l__MOdiagram_tmpa_tl
      { \tl_set_eq:NN \l__MOdiagram_AO_up_electron_tl \l__MOdiagram_tmpa_tl }
  }

\keys_define:nn { MOdiagram / up-pos }
  {
    1sleft   .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_up_prop { 1sleft }   { #1 } } ,
    1sright  .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_up_prop { 1sright }  { #1 } } ,
    2sleft   .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_up_prop { 2sleft }   { #1 } } ,
    2sright  .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_up_prop { 2sright }  { #1 } } ,
    2pxleft  .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_up_prop { 2pxleft }  { #1 } } ,
    2pxright .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_up_prop { 2pxright } { #1 } } ,
    2pyleft  .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_up_prop { 2pyleft }  { #1 } } ,
    2pyright .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_up_prop { 2pyright } { #1 } } ,
    2pzleft  .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_up_prop { 2pzleft }  { #1 } } ,
    2pzright .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_up_prop { 2pzright } { #1 } } ,
    1sigma   .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_up_prop { 1sigma }   { #1 } } ,
    1sigma*  .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_up_prop { 1sigma* }  { #1 } } ,
    2sigma   .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_up_prop { 2sigma }   { #1 } } ,
    2sigma*  .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_up_prop { 2sigma* }  { #1 } } ,
    2psigma  .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_up_prop { 2psigma }  { #1 } } ,
    2psigma* .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_up_prop { 2psigma* } { #1 } } ,
    2piy     .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_up_prop { 2piy }     { #1 } } ,
    2piy*    .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_up_prop { 2piy* }    { #1 } } ,
    2piz     .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_up_prop { 2piz }     { #1 } } ,
    2piz*    .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_up_prop { 2piz* }    { #1 } }
  }

\prop_new:N \l__MOdiagram_electron_down_prop

\cs_new:Npn \__MOdiagram_electron_down_set:n #1
  { \keys_set:nn { MOdiagram / down-pos } { #1 } }

\cs_new_protected:Npn \__MOdiagram_get_electron_down:n #1
  {
    \tl_clear:N \l__MOdiagram_tmpa_tl
    \tl_clear:N \l__MOdiagram_tmpb_tl
    \prop_get:NnNT \l__MOdiagram_electron_down_prop { #1 } \l__MOdiagram_tmpa_tl
      { \tl_set_eq:NN \l__MOdiagram_AO_down_electron_tl \l__MOdiagram_tmpa_tl }
  }

\keys_define:nn { MOdiagram / down-pos }
  {
    1sleft   .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_down_prop { 1sleft }   { #1 } } ,
    1sright  .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_down_prop { 1sright }  { #1 } } ,
    2sleft   .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_down_prop { 2sleft }   { #1 } } ,
    2sright  .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_down_prop { 2sright }  { #1 } } ,
    2pxleft  .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_down_prop { 2pxleft }  { #1 } } ,
    2pxright .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_down_prop { 2pxright } { #1 } } ,
    2pyleft  .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_down_prop { 2pyleft }  { #1 } } ,
    2pyright .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_down_prop { 2pyright } { #1 } } ,
    2pzleft  .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_down_prop { 2pzleft }  { #1 } } ,
    2pzright .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_down_prop { 2pzright } { #1 } } ,
    1sigma   .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_down_prop { 1sigma }   { #1 } } ,
    1sigma*  .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_down_prop { 1sigma* }  { #1 } } ,
    2sigma   .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_down_prop { 2sigma }   { #1 } } ,
    2sigma*  .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_down_prop { 2sigma* }  { #1 } } ,
    2psigma  .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_down_prop { 2psigma }  { #1 } } ,
    2psigma* .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_down_prop { 2psigma* } { #1 } } ,
    2piy     .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_down_prop { 2piy }     { #1 } } ,
    2piy*    .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_down_prop { 2piy* }    { #1 } } ,
    2piz     .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_down_prop { 2piz }     { #1 } } ,
    2piz*    .code:n =
      { \prop_put:Nnn \l__MOdiagram_electron_down_prop { 2piz* }    { #1 } }
  }

% --------------------------------------------------------------------------- %
% energy axis
\dim_new:N \l_energy_axis_dim
\dim_set:Nn \l_energy_axis_dim { 0pt }

\tl_new:N \l__MOdiagram_Eaxis_head_tl
\tl_set:Nn \l__MOdiagram_Eaxis_head_tl { latex }
\tl_new:N \l__MOdiagram_Eaxis_title_tl

\bool_new:N \l__MOdiagram_Eaxis_title_bool
\bool_set_false:N \l__MOdiagram_Eaxis_title_bool

\NewDocumentCommand \__MOdiagram_EnergyAxis: { o }
  {
    \IfNoValueF { #1 } { \keys_set:nn { MOdiagram / axis } { #1 } }
    \__MOdiagram_draw:f { - \tl_use:N \l__MOdiagram_Eaxis_head_tl }
      (\l_energy_axis_dim , \g__MOdiagram_min_energy_dim - 1cm )
      --
      (\l_energy_axis_dim , \g__MOdiagram_max_energy_dim + 1cm ) 
      \bool_if:NT \l__MOdiagram_Eaxis_title_bool
        { node [ above ] { \tl_use:N \l__MOdiagram_Eaxis_title_tl } }
    ;
  }

\keys_define:nn { MOdiagram / axis }
  {
    title .code:n =
      {
        \bool_set_true:N \l__MOdiagram_Eaxis_title_bool
        \tl_set:Nn \l__MOdiagram_Eaxis_title_tl { #1 }
      } ,
    title .default:n = energy ,
    head  .tl_set:N  = \l__MOdiagram_Eaxis_head_tl ,
    head  .default:n = >
  }

% --------------------------------------------------------------------------- %
% tikz helper functions
\cs_new:Npn \__MOdiagram_node:n #1
  { \node [ #1 ] }
\cs_generate_variant:Nn \__MOdiagram_node:n { f,x }

\cs_new:Npn \__MOdiagram_draw:n #1
  { \draw [ #1 ] }
\cs_generate_variant:Nn \__MOdiagram_draw:n { f }

\cs_new:Npn \__MOdiagram_tikz:nn #1
  { \tikz [ #1 ] }
\cs_generate_variant:Nn \__MOdiagram_tikz:nn { fn,xn }

\cs_new:Npn \__MOdiagram_tikzpicture:n #1
  { \tikzpicture [ #1 ] }
\cs_generate_variant:Nn \__MOdiagram_tikzpicture:n { f }

\tex_endinput:D

% --------------------------------------------------------------------------- %
Version history
2011/09/25 version 0.1  - first upload to CTAN
2011/10/27 version 0.2  - \atom, \molecule, \AO, \EnergyAxis only defined within
                          the MOdiagram environment
                        - bugfix in energy splitting process
                        - bugfix: wrong labelling of plain empty orbitals
                        - different values for energy gain and loss possible
                        - default values for the AO and MO; if empty values are
                          used, the ";" and "," can be omitted
                        - default node names for the arbitrary AOs
                        - horizontal shift of electrons possible
                        - customization of atom- and molecule names possible
2013/04/28 version 0.2c - fix: adapt to deprecated expl3 command
2014/05/12 version 0.2d - fix: adapt to deprecated expl3 command
                        - change dependency from `textgreek' to `chemgreek'
2014/06/28 version 0.2e - fix: adapt to deprecated expl3 command

TODO
- 3s, 3p , 3sMO , 3pMO , 4s , sp3
- energy axis: ticks? at orbital heights?
- electron configuration
- localisation for the energy axis title using the translator package
- Default-Einheit (bislang cm) ändern können?
