qrotor.systems

Description

This module contains utility functions to handle multiple qrotor.system calculations. These are commonly used as a list of System objects.

Index

as_list() Ensures that a list only contains System objects
save_energies() Save the energy eigenvalues for all systems to a CSV
save_splittings() Save the tunnel splitting energies for all systems to a CSV
save_summary() Save a summary of some relevant parameters for all systems to a CSV
get_energies() Get the eigenvalues from all systems
get_gridsizes() Get all gridsizes
get_runtimes() Get all runtimes
get_tags() Get a list with all system tags
filter_tags() Filter the systems with or without specific tags
calculate_ideal_E() Calculate the ideal energy for a specified level
sort_by_gridsize() Sort systems by gridsize
reduce_size() Discard data that takes too much space
summary() Print a summary of a System or list of Systems

  1"""
  2# Description
  3
  4This module contains utility functions to handle multiple `qrotor.system` calculations.
  5These are commonly used as a list of `System` objects.
  6
  7
  8# Index
  9
 10| | |
 11| --- | --- |
 12| `as_list()`           | Ensures that a list only contains System objects |  
 13| `save_energies()`     | Save the energy eigenvalues for all systems to a CSV |  
 14| `save_splittings()`   | Save the tunnel splitting energies for all systems to a CSV |  
 15| `save_summary()`      | Save a summary of some relevant parameters for all systems to a CSV |  
 16| `get_energies()`      | Get the eigenvalues from all systems |  
 17| `get_gridsizes()`     | Get all gridsizes |  
 18| `get_runtimes()`      | Get all runtimes |  
 19| `get_tags()`          | Get a list with all system tags |  
 20| `filter_tags()`       | Filter the systems with or without specific tags |  
 21| `calculate_ideal_E()` | Calculate the ideal energy for a specified level |  
 22| `sort_by_gridsize()`  | Sort systems by gridsize |  
 23| `reduce_size()`       | Discard data that takes too much space |  
 24| `summary()`           | Print a summary of a System or list of Systems |  
 25
 26---
 27"""
 28
 29
 30from .system import System
 31from aton import txt
 32import pandas as pd
 33
 34
 35def as_list(systems) -> None:
 36    """Ensures that `systems` is a list of System objects.
 37
 38    If it is a System, returns a list with that System as the only element.
 39    If it is neither a list nor a System,
 40    or if the list does not contain only System objects,
 41    it raises an error.
 42    """
 43    if isinstance(systems, System):
 44        systems = [systems]
 45    if not isinstance(systems, list):
 46        raise TypeError(f"Must be a System object or a list of systems, found instead: {type(systems)}")
 47    for i in systems:
 48        if not isinstance(i, System):
 49            raise TypeError(f"All items in the list must be System objects, found instead: {type(i)}")
 50    return systems
 51
 52
 53def save_energies(
 54        systems:list,
 55        comment:str='',
 56        filepath:str='qrotor_eigenvalues.csv',
 57        ) -> pd.DataFrame:
 58    """Save the energy eigenvalues for all `systems` to a qrotor_eigenvalues.csv file.
 59
 60    Returns a Pandas Dataset with `System.comment` columns and `System.eigenvalues` values.
 61
 62    The output file can be changed with `filepath`,
 63    or set to null to avoid saving the dataset.
 64    A `comment` can be included at the top of the file.
 65    Note that `System.comment` must not include commas (`,`).
 66    """
 67    systems = as_list(systems)
 68    version = systems[0].version
 69    E = {}
 70    # Find max length of eigenvalues
 71    max_len = max((len(s.eigenvalues) if s.eigenvalues is not None else 0) for s in systems)
 72    for s in systems:
 73        if s.eigenvalues is not None:
 74            # Filter out None values and replace with NaN
 75            valid_eigenvalues = [float('nan') if e is None else e for e in s.eigenvalues]
 76            padded_eigenvalues = valid_eigenvalues + [float('nan')] * (max_len - len(s.eigenvalues))
 77        else:
 78            padded_eigenvalues = [float('nan')] * max_len
 79        E[s.comment] = padded_eigenvalues
 80    df = pd.DataFrame(E)
 81    if not filepath:
 82        return df
 83    # Else save to file
 84    df.to_csv(filepath, sep=',', index=False)
 85    # Include a comment at the top of the file
 86    file_comment = f'## {comment}\n' if comment else f''
 87    file_comment += f'# Energy eigenvalues\n'
 88    file_comment += f'# Calculated with QRotor {version}\n'
 89    file_comment += f'# https://pablogila.github.io/qrotor\n#'
 90    txt.edit.insert_at(filepath, file_comment, 0)
 91    print(f'Energy eigenvalues saved to {filepath}')
 92    return df
 93
 94
 95def save_splittings(
 96    systems:list,
 97    comment:str='',
 98    filepath:str='qrotor_splittings.csv',
 99    ) -> pd.DataFrame:
100    """Save the tunnel splitting energies for all `systems` to a qrotor_splittings.csv file.
101
102    Returns a Pandas Dataset with `System.comment` columns and `System.splittings` values.
103
104    The output file can be changed with `filepath`,
105    or set to null to avoid saving the dataset.
106    A `comment` can be included at the top of the file.
107    Note that `System.comment` must not include commas (`,`).
108    Different splitting lengths across systems are allowed - missing values will be NaN.
109    """
110    systems = as_list(systems)
111    version = systems[0].version
112    tunnelling_E = {}
113    # Find max length of splittings
114    max_len = max(len(s.splittings) for s in systems)
115    for s in systems:  # Pad shorter splittings with NaN
116        padded_splittings = s.splittings + [float('nan')] * (max_len - len(s.splittings))
117        tunnelling_E[s.comment] = padded_splittings
118    df = pd.DataFrame(tunnelling_E)
119    if not filepath:
120        return df
121    # Else save to file
122    df.to_csv(filepath, sep=',', index=False)
123    # Include a comment at the top of the file 
124    file_comment = f'## {comment}\n' if comment else f''
125    file_comment += f'# Tunnel splitting energies\n'
126    file_comment += f'# Calculated with QRotor {version}\n'
127    file_comment += f'# https://pablogila.github.io/qrotor\n#'
128    txt.edit.insert_at(filepath, file_comment, 0)
129    print(f'Tunnel splitting energies saved to {filepath}')
130    return df
131
132
133def save_summary(
134    systems:list,
135    comment:str='',
136    filepath:str='qrotor_summary.csv',
137    ) -> pd.DataFrame:
138    """Save a summary for all `systems` to a qrotor_summary.csv file.
139
140    Produces one row per System with the columns:
141    `comment`, `ZPE`, `E_activation`, `potential_max`, `1st_splitting`,
142    `1st_excitation`, `B`, `degeneracy`, `gridsize`.
143
144    Set `filepath` to null to just return the DataFrame.
145    """
146    systems = as_list(systems)
147    version = systems[0].version
148    rows = []
149    for s in systems:
150        eigenvalues = getattr(s, 'eigenvalues', None)
151        if eigenvalues is not None and len(eigenvalues) > 0:
152            first_val = eigenvalues[0]
153            zpe = float('nan') if first_val is None else first_val
154        else:
155            zpe = float('nan')
156        splittings = getattr(s, 'splittings', None)
157        if splittings is not None and len(splittings) > 0:
158            first_splitting = float('nan') if splittings[0] is None else splittings[0]
159        else:
160            first_splitting = float('nan')
161        excitations = getattr(s, 'excitations', None)
162        if excitations is not None and len(excitations) > 0:
163            first_excitation = float('nan') if excitations[0] is None else excitations[0]
164        else:
165            first_excitation = float('nan')
166        system_comment = getattr(s, 'comment', None)
167        E_activation = getattr(s, 'E_activation', None)
168        B = getattr(s, 'B', None)
169        tags = getattr(s, 'tags', None)
170        deg = getattr(s, 'deg', None)
171        gridsize = getattr(s, 'gridsize', None)
172        potential_max = getattr(s, 'potential_max', None)
173        # Each row contains the following:
174        rows.append({
175            'comment': system_comment,
176            'ZPE': zpe,
177            'potential_max': potential_max,
178            'E_activation': E_activation,
179            '1st_splitting': first_splitting,
180            '1st_excitation': first_excitation,
181            'B': B,
182            'degeneracy': deg,
183            'gridsize': gridsize,
184            'tags': tags,
185        })
186    # Save to file or just return df
187    df = pd.DataFrame(rows)
188    if not filepath:
189        return df
190    df.to_csv(filepath, sep=',', index=False)
191    # Include a comment at the top of the file
192    file_comment = f'## {comment}\n' if comment else ''
193    file_comment += '# Summary of systems\n'
194    file_comment += f'# Calculated with QRotor {version}\n'
195    file_comment += '# https://pablogila.github.io/qrotor\n#'
196    txt.edit.insert_at(filepath, file_comment, 0)
197    print(f'Summary saved to {filepath}')
198    return df
199
200
201def get_energies(systems:list) -> list:
202    """Get a list with all lists of eigenvalues from all systems.
203
204    If no eigenvalues are present for a particular system, appends None.
205    """
206    systems = as_list(systems)
207    energies = []
208    for i in systems:
209        if all(i.eigenvalues):
210            energies.append(i.eigenvalues)
211        else:
212            energies.append(None)
213    return energies
214
215
216def get_gridsizes(systems:list) -> list:
217    """Get a list with all gridsize values.
218
219    If no gridsize value is present for a particular system, appends None.
220    """
221    systems = as_list(systems)
222    gridsizes = []
223    for i in systems:
224        if i.gridsize:
225            gridsizes.append(i.gridsize)
226        elif any(i.potential_values):
227            gridsizes.append(len(i.potential_values))
228        else:
229            gridsizes.append(None)
230    return gridsizes
231
232
233def get_runtimes(systems:list) -> list:
234    """Returns a list with all runtime values.
235    
236    If no runtime value is present for a particular system, appends None.
237    """
238    systems = as_list(systems)
239    runtimes = []
240    for i in systems:
241        if i.runtime:
242            runtimes.append(i.runtime)
243        else:
244            runtimes.append(None)
245    return runtimes
246
247
248def get_tags(systems:list) -> list:
249    """Returns a list with all system tags."""
250    systems = as_list(systems)
251    tags = []
252    for i in systems:
253        # i.tags is guaranteed to exist and be a string (may be empty)
254        system_tags = i.tags.split()
255        for tag in system_tags:
256            if tag not in tags:
257                tags.append(tag)
258    return tags
259
260
261def filter_tags(
262        systems:list,
263        include:str='',
264        exclude:str='',
265        strict:bool=False,
266        ) -> list:
267    """Returns a filtered list of systems with or without specific tags.
268
269    You can `include` or `exclude` any number of tags, separated by blank spaces.
270    By default, the filters are triggered if any tag is found, i.e. *tag1 OR tag2*.
271    Set `strict=True` to require all tags to match, i.e. *tag1 AND tag2*.
272    """
273    systems = as_list(systems)
274    included_tags = include.split()
275    excluded_tags = exclude.split()
276    filtered_systems = []
277    for i in systems:
278        tags_found = get_tags(i)
279        if excluded_tags:
280            if strict and all(tag in tags_found for tag in excluded_tags):
281                continue
282            elif not strict and any(tag in tags_found for tag in excluded_tags):
283                continue
284        if included_tags:
285            if strict and not all(tag in tags_found for tag in included_tags):
286                continue
287            elif not strict and not any(tag in tags_found for tag in included_tags):
288                continue
289        filtered_systems.append(i)
290    return filtered_systems
291
292
293def calculate_ideal_E(E_level:int) -> int:
294    """Calculates the ideal energy for a specified `E_level`.
295
296    To be used in convergence tests with `potential_name = 'zero'`.
297    """
298    real_E_level = None
299    if E_level % 2 == 0:
300        real_E_level = E_level / 2
301    else:
302        real_E_level = (E_level + 1) / 2
303    ideal_E = int(real_E_level ** 2)
304    return ideal_E
305
306
307def sort_by_gridsize(systems:list) -> list:
308    """Sorts a list of System objects by `System.gridsize`."""
309    systems = as_list(systems)
310    systems = sorted(systems, key=lambda sys: sys.gridsize)
311    return systems
312
313
314def reduce_size(systems:list) -> list:
315    """Discard data that takes too much space.
316
317    Removes eigenvectors, potential values and grids,
318    for all System values inside the `systems` list.
319    """
320    systems = as_list(systems)
321    for dataset in systems:
322        dataset = dataset.reduce_size()
323    return systems
324
325
326def summary(
327        systems,
328        verbose:bool=False
329        ) -> None:
330    """Print a summary of a System or list of Systems.
331    
332    Print extra info with `verbose=True`
333    """
334    print('--------------------')
335    systems = as_list(systems)
336    
337    for system in systems:
338        dictionary = system.summary()
339        if verbose:
340            for key, value in dictionary.items():
341                print(f'{key:<24}', value)
342        else:
343            eigenvalues = system.eigenvalues if any(system.eigenvalues) else []
344            extra = ''
345            if len(system.eigenvalues) > 6:
346                eigenvalues = eigenvalues[:6]
347                extra = '...'
348            print('comment         ' + str(system.comment))
349            print('ZPE             ' + str(system.eigenvalues[0]))
350            print('E activation    ' + str(system.E_activation))
351            print('V max           ' + str(system.potential_max))
352            print('1st splitting   ' + str(system.splittings[0]))
353            print('1st excitation  ' + str(system.excitations[0]))
354            print('B               ' + str(system.B))
355            print('eigenvalues     ' + str([float(round(e, 4)) for e in eigenvalues]) + extra)
356            print('tags            ' + str(system.tags))
357            print('version         ' + str(system.version))
358        print('--------------------')
359    return None
def as_list(systems) -> None:
36def as_list(systems) -> None:
37    """Ensures that `systems` is a list of System objects.
38
39    If it is a System, returns a list with that System as the only element.
40    If it is neither a list nor a System,
41    or if the list does not contain only System objects,
42    it raises an error.
43    """
44    if isinstance(systems, System):
45        systems = [systems]
46    if not isinstance(systems, list):
47        raise TypeError(f"Must be a System object or a list of systems, found instead: {type(systems)}")
48    for i in systems:
49        if not isinstance(i, System):
50            raise TypeError(f"All items in the list must be System objects, found instead: {type(i)}")
51    return systems

Ensures that systems is a list of System objects.

If it is a System, returns a list with that System as the only element. If it is neither a list nor a System, or if the list does not contain only System objects, it raises an error.

def save_energies( systems: list, comment: str = '', filepath: str = 'qrotor_eigenvalues.csv') -> pandas.core.frame.DataFrame:
54def save_energies(
55        systems:list,
56        comment:str='',
57        filepath:str='qrotor_eigenvalues.csv',
58        ) -> pd.DataFrame:
59    """Save the energy eigenvalues for all `systems` to a qrotor_eigenvalues.csv file.
60
61    Returns a Pandas Dataset with `System.comment` columns and `System.eigenvalues` values.
62
63    The output file can be changed with `filepath`,
64    or set to null to avoid saving the dataset.
65    A `comment` can be included at the top of the file.
66    Note that `System.comment` must not include commas (`,`).
67    """
68    systems = as_list(systems)
69    version = systems[0].version
70    E = {}
71    # Find max length of eigenvalues
72    max_len = max((len(s.eigenvalues) if s.eigenvalues is not None else 0) for s in systems)
73    for s in systems:
74        if s.eigenvalues is not None:
75            # Filter out None values and replace with NaN
76            valid_eigenvalues = [float('nan') if e is None else e for e in s.eigenvalues]
77            padded_eigenvalues = valid_eigenvalues + [float('nan')] * (max_len - len(s.eigenvalues))
78        else:
79            padded_eigenvalues = [float('nan')] * max_len
80        E[s.comment] = padded_eigenvalues
81    df = pd.DataFrame(E)
82    if not filepath:
83        return df
84    # Else save to file
85    df.to_csv(filepath, sep=',', index=False)
86    # Include a comment at the top of the file
87    file_comment = f'## {comment}\n' if comment else f''
88    file_comment += f'# Energy eigenvalues\n'
89    file_comment += f'# Calculated with QRotor {version}\n'
90    file_comment += f'# https://pablogila.github.io/qrotor\n#'
91    txt.edit.insert_at(filepath, file_comment, 0)
92    print(f'Energy eigenvalues saved to {filepath}')
93    return df

Save the energy eigenvalues for all systems to a qrotor_eigenvalues.csv file.

Returns a Pandas Dataset with System.comment columns and System.eigenvalues values.

The output file can be changed with filepath, or set to null to avoid saving the dataset. A comment can be included at the top of the file. Note that System.comment must not include commas (,).

def save_splittings( systems: list, comment: str = '', filepath: str = 'qrotor_splittings.csv') -> pandas.core.frame.DataFrame:
 96def save_splittings(
 97    systems:list,
 98    comment:str='',
 99    filepath:str='qrotor_splittings.csv',
100    ) -> pd.DataFrame:
101    """Save the tunnel splitting energies for all `systems` to a qrotor_splittings.csv file.
102
103    Returns a Pandas Dataset with `System.comment` columns and `System.splittings` values.
104
105    The output file can be changed with `filepath`,
106    or set to null to avoid saving the dataset.
107    A `comment` can be included at the top of the file.
108    Note that `System.comment` must not include commas (`,`).
109    Different splitting lengths across systems are allowed - missing values will be NaN.
110    """
111    systems = as_list(systems)
112    version = systems[0].version
113    tunnelling_E = {}
114    # Find max length of splittings
115    max_len = max(len(s.splittings) for s in systems)
116    for s in systems:  # Pad shorter splittings with NaN
117        padded_splittings = s.splittings + [float('nan')] * (max_len - len(s.splittings))
118        tunnelling_E[s.comment] = padded_splittings
119    df = pd.DataFrame(tunnelling_E)
120    if not filepath:
121        return df
122    # Else save to file
123    df.to_csv(filepath, sep=',', index=False)
124    # Include a comment at the top of the file 
125    file_comment = f'## {comment}\n' if comment else f''
126    file_comment += f'# Tunnel splitting energies\n'
127    file_comment += f'# Calculated with QRotor {version}\n'
128    file_comment += f'# https://pablogila.github.io/qrotor\n#'
129    txt.edit.insert_at(filepath, file_comment, 0)
130    print(f'Tunnel splitting energies saved to {filepath}')
131    return df

Save the tunnel splitting energies for all systems to a qrotor_splittings.csv file.

Returns a Pandas Dataset with System.comment columns and System.splittings values.

The output file can be changed with filepath, or set to null to avoid saving the dataset. A comment can be included at the top of the file. Note that System.comment must not include commas (,). Different splitting lengths across systems are allowed - missing values will be NaN.

def save_summary( systems: list, comment: str = '', filepath: str = 'qrotor_summary.csv') -> pandas.core.frame.DataFrame:
134def save_summary(
135    systems:list,
136    comment:str='',
137    filepath:str='qrotor_summary.csv',
138    ) -> pd.DataFrame:
139    """Save a summary for all `systems` to a qrotor_summary.csv file.
140
141    Produces one row per System with the columns:
142    `comment`, `ZPE`, `E_activation`, `potential_max`, `1st_splitting`,
143    `1st_excitation`, `B`, `degeneracy`, `gridsize`.
144
145    Set `filepath` to null to just return the DataFrame.
146    """
147    systems = as_list(systems)
148    version = systems[0].version
149    rows = []
150    for s in systems:
151        eigenvalues = getattr(s, 'eigenvalues', None)
152        if eigenvalues is not None and len(eigenvalues) > 0:
153            first_val = eigenvalues[0]
154            zpe = float('nan') if first_val is None else first_val
155        else:
156            zpe = float('nan')
157        splittings = getattr(s, 'splittings', None)
158        if splittings is not None and len(splittings) > 0:
159            first_splitting = float('nan') if splittings[0] is None else splittings[0]
160        else:
161            first_splitting = float('nan')
162        excitations = getattr(s, 'excitations', None)
163        if excitations is not None and len(excitations) > 0:
164            first_excitation = float('nan') if excitations[0] is None else excitations[0]
165        else:
166            first_excitation = float('nan')
167        system_comment = getattr(s, 'comment', None)
168        E_activation = getattr(s, 'E_activation', None)
169        B = getattr(s, 'B', None)
170        tags = getattr(s, 'tags', None)
171        deg = getattr(s, 'deg', None)
172        gridsize = getattr(s, 'gridsize', None)
173        potential_max = getattr(s, 'potential_max', None)
174        # Each row contains the following:
175        rows.append({
176            'comment': system_comment,
177            'ZPE': zpe,
178            'potential_max': potential_max,
179            'E_activation': E_activation,
180            '1st_splitting': first_splitting,
181            '1st_excitation': first_excitation,
182            'B': B,
183            'degeneracy': deg,
184            'gridsize': gridsize,
185            'tags': tags,
186        })
187    # Save to file or just return df
188    df = pd.DataFrame(rows)
189    if not filepath:
190        return df
191    df.to_csv(filepath, sep=',', index=False)
192    # Include a comment at the top of the file
193    file_comment = f'## {comment}\n' if comment else ''
194    file_comment += '# Summary of systems\n'
195    file_comment += f'# Calculated with QRotor {version}\n'
196    file_comment += '# https://pablogila.github.io/qrotor\n#'
197    txt.edit.insert_at(filepath, file_comment, 0)
198    print(f'Summary saved to {filepath}')
199    return df

Save a summary for all systems to a qrotor_summary.csv file.

Produces one row per System with the columns: comment, ZPE, E_activation, potential_max, 1st_splitting, 1st_excitation, B, degeneracy, gridsize.

Set filepath to null to just return the DataFrame.

def get_energies(systems: list) -> list:
202def get_energies(systems:list) -> list:
203    """Get a list with all lists of eigenvalues from all systems.
204
205    If no eigenvalues are present for a particular system, appends None.
206    """
207    systems = as_list(systems)
208    energies = []
209    for i in systems:
210        if all(i.eigenvalues):
211            energies.append(i.eigenvalues)
212        else:
213            energies.append(None)
214    return energies

Get a list with all lists of eigenvalues from all systems.

If no eigenvalues are present for a particular system, appends None.

def get_gridsizes(systems: list) -> list:
217def get_gridsizes(systems:list) -> list:
218    """Get a list with all gridsize values.
219
220    If no gridsize value is present for a particular system, appends None.
221    """
222    systems = as_list(systems)
223    gridsizes = []
224    for i in systems:
225        if i.gridsize:
226            gridsizes.append(i.gridsize)
227        elif any(i.potential_values):
228            gridsizes.append(len(i.potential_values))
229        else:
230            gridsizes.append(None)
231    return gridsizes

Get a list with all gridsize values.

If no gridsize value is present for a particular system, appends None.

def get_runtimes(systems: list) -> list:
234def get_runtimes(systems:list) -> list:
235    """Returns a list with all runtime values.
236    
237    If no runtime value is present for a particular system, appends None.
238    """
239    systems = as_list(systems)
240    runtimes = []
241    for i in systems:
242        if i.runtime:
243            runtimes.append(i.runtime)
244        else:
245            runtimes.append(None)
246    return runtimes

Returns a list with all runtime values.

If no runtime value is present for a particular system, appends None.

def get_tags(systems: list) -> list:
249def get_tags(systems:list) -> list:
250    """Returns a list with all system tags."""
251    systems = as_list(systems)
252    tags = []
253    for i in systems:
254        # i.tags is guaranteed to exist and be a string (may be empty)
255        system_tags = i.tags.split()
256        for tag in system_tags:
257            if tag not in tags:
258                tags.append(tag)
259    return tags

Returns a list with all system tags.

def filter_tags( systems: list, include: str = '', exclude: str = '', strict: bool = False) -> list:
262def filter_tags(
263        systems:list,
264        include:str='',
265        exclude:str='',
266        strict:bool=False,
267        ) -> list:
268    """Returns a filtered list of systems with or without specific tags.
269
270    You can `include` or `exclude` any number of tags, separated by blank spaces.
271    By default, the filters are triggered if any tag is found, i.e. *tag1 OR tag2*.
272    Set `strict=True` to require all tags to match, i.e. *tag1 AND tag2*.
273    """
274    systems = as_list(systems)
275    included_tags = include.split()
276    excluded_tags = exclude.split()
277    filtered_systems = []
278    for i in systems:
279        tags_found = get_tags(i)
280        if excluded_tags:
281            if strict and all(tag in tags_found for tag in excluded_tags):
282                continue
283            elif not strict and any(tag in tags_found for tag in excluded_tags):
284                continue
285        if included_tags:
286            if strict and not all(tag in tags_found for tag in included_tags):
287                continue
288            elif not strict and not any(tag in tags_found for tag in included_tags):
289                continue
290        filtered_systems.append(i)
291    return filtered_systems

Returns a filtered list of systems with or without specific tags.

You can include or exclude any number of tags, separated by blank spaces. By default, the filters are triggered if any tag is found, i.e. tag1 OR tag2. Set strict=True to require all tags to match, i.e. tag1 AND tag2.

def calculate_ideal_E(E_level: int) -> int:
294def calculate_ideal_E(E_level:int) -> int:
295    """Calculates the ideal energy for a specified `E_level`.
296
297    To be used in convergence tests with `potential_name = 'zero'`.
298    """
299    real_E_level = None
300    if E_level % 2 == 0:
301        real_E_level = E_level / 2
302    else:
303        real_E_level = (E_level + 1) / 2
304    ideal_E = int(real_E_level ** 2)
305    return ideal_E

Calculates the ideal energy for a specified E_level.

To be used in convergence tests with potential_name = 'zero'.

def sort_by_gridsize(systems: list) -> list:
308def sort_by_gridsize(systems:list) -> list:
309    """Sorts a list of System objects by `System.gridsize`."""
310    systems = as_list(systems)
311    systems = sorted(systems, key=lambda sys: sys.gridsize)
312    return systems

Sorts a list of System objects by System.gridsize.

def reduce_size(systems: list) -> list:
315def reduce_size(systems:list) -> list:
316    """Discard data that takes too much space.
317
318    Removes eigenvectors, potential values and grids,
319    for all System values inside the `systems` list.
320    """
321    systems = as_list(systems)
322    for dataset in systems:
323        dataset = dataset.reduce_size()
324    return systems

Discard data that takes too much space.

Removes eigenvectors, potential values and grids, for all System values inside the systems list.

def summary(systems, verbose: bool = False) -> None:
327def summary(
328        systems,
329        verbose:bool=False
330        ) -> None:
331    """Print a summary of a System or list of Systems.
332    
333    Print extra info with `verbose=True`
334    """
335    print('--------------------')
336    systems = as_list(systems)
337    
338    for system in systems:
339        dictionary = system.summary()
340        if verbose:
341            for key, value in dictionary.items():
342                print(f'{key:<24}', value)
343        else:
344            eigenvalues = system.eigenvalues if any(system.eigenvalues) else []
345            extra = ''
346            if len(system.eigenvalues) > 6:
347                eigenvalues = eigenvalues[:6]
348                extra = '...'
349            print('comment         ' + str(system.comment))
350            print('ZPE             ' + str(system.eigenvalues[0]))
351            print('E activation    ' + str(system.E_activation))
352            print('V max           ' + str(system.potential_max))
353            print('1st splitting   ' + str(system.splittings[0]))
354            print('1st excitation  ' + str(system.excitations[0]))
355            print('B               ' + str(system.B))
356            print('eigenvalues     ' + str([float(round(e, 4)) for e in eigenvalues]) + extra)
357            print('tags            ' + str(system.tags))
358            print('version         ' + str(system.version))
359        print('--------------------')
360    return None

Print a summary of a System or list of Systems.

Print extra info with verbose=True