orto 1.13.1__py3-none-any.whl → 1.14.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
orto/__version__.py CHANGED
@@ -1 +1 @@
1
- __version__ = '1.13.1'
1
+ __version__ = '1.14.1'
orto/cli.py CHANGED
@@ -1076,123 +1076,290 @@ def gen_job_func(uargs):
1076
1076
  return
1077
1077
 
1078
1078
 
1079
- def plot_xes_func(uargs):
1079
+ def plot_xes_func(uargs, save_data_only=False):
1080
1080
  '''
1081
- Wrapper for CLI plot xes call
1081
+ Wrapper for CLI plot abs call\n\n
1082
+
1083
+ Plots ABSORPTION blocks from orca output\n
1084
+ - UVVIS (TDDFT)\n
1085
+ - XAS (TDDFT)\n\n
1082
1086
 
1083
1087
  Parameters
1084
1088
  ----------
1085
1089
  uargs: argparser object
1086
1090
  User arguments
1087
1091
 
1092
+ save_data_only: bool, default=False
1093
+ If True, saves generated spectrum data to file only.
1094
+
1088
1095
  Returns
1089
1096
  -------
1090
1097
  None
1091
1098
  '''
1092
- import matplotlib.pyplot as plt
1093
1099
  from . import plotter
1094
1100
  from . import extractor as oe
1101
+ from . import data as d
1095
1102
 
1096
- # Set user specified font name
1097
- ut.check_font_envvar()
1103
+ # Process x_shift argument
1104
+ if uargs.x_shift is None:
1105
+ uargs.x_shift = [0.0 for _ in uargs.output_file]
1106
+ elif len(uargs.x_shift) != len(uargs.output_file):
1107
+ ut.red_exit(
1108
+ 'Number of x_shift values must match number of output files'
1109
+ )
1098
1110
 
1099
- # Change matplotlib font size to be larger
1100
- plt.rcParams['font.size'] = 10
1101
- plt.rcParams['legend.fontsize'] = 9
1111
+ # Create dictionary to hold absorption data for plotting later
1112
+ spectra_dict = {}
1102
1113
 
1103
- version = oe.OrcaVersionExtractor.extract(uargs.output_file)
1114
+ # Extract data from each output file
1115
+ for it, output_file in enumerate(uargs.output_file):
1104
1116
 
1105
- if not len(version):
1106
- ut.cprint(
1107
- 'Warning: Cannot find version number in Orca output file',
1108
- 'black_yellowbg'
1109
- )
1110
- version = [6, 0, 0]
1117
+ version = oe.OrcaVersionExtractor.extract(output_file)
1111
1118
 
1112
- if version[0] >= 6:
1113
- if uargs.intensities == 'electric':
1114
- all_data = oe.XESElectricDipoleExtractor.extract(
1115
- uargs.output_file
1116
- )
1117
- elif uargs.intensities == 'velocity':
1118
- all_data = oe.XESVelocityDipoleExtractor.extract(
1119
- uargs.output_file
1120
- )
1121
- elif uargs.intensities == 'semi-classical':
1122
- all_data = oe.XESSemiClassicalDipoleExtractor.extract(
1123
- uargs.output_file
1124
- )
1125
- elif uargs.intensities == 'so_electric':
1126
- all_data = oe.SOXESElectricDipoleExtractor.extract(
1127
- uargs.output_file
1128
- )
1129
- elif uargs.intensities == 'so_velocity':
1130
- all_data = oe.SOXESVelocityDipoleExtractor.extract(
1131
- uargs.output_file
1119
+ if not len(version):
1120
+ ut.cprint(
1121
+ 'Warning: Cannot find version number in Orca output file',
1122
+ 'black_yellowbg'
1132
1123
  )
1133
- elif uargs.intensities == 'so_semi-classical':
1134
- all_data = oe.SOXESSemiClassicalDipoleExtractor.extract(
1135
- uargs.output_file
1124
+ version = [6, 0, 0]
1125
+
1126
+ # Extract absorption data from file
1127
+ # using appropriate extractor for version
1128
+ # and intensity type
1129
+ if version[0] >= 6:
1130
+ if uargs.intensities == 'electric':
1131
+ all_datasets = oe.XESElectricDipoleExtractor.extract(
1132
+ output_file
1133
+ )
1134
+ elif uargs.intensities == 'velocity':
1135
+ all_datasets = oe.XESVelocityDipoleExtractor.extract(
1136
+ output_file
1137
+ )
1138
+ elif uargs.intensities == 'semi-classical':
1139
+ all_datasets = oe.XESSemiClassicalDipoleExtractor.extract(
1140
+ output_file
1141
+ )
1142
+ else:
1143
+ ut.red_exit(
1144
+ 'Orca version < 6 not supported for XES spectrum generation'
1136
1145
  )
1137
- elif version[0] < 6:
1138
- ut.red_exit('Unsupported version of Orca for XES extraction', 'red')
1139
1146
 
1140
- ut.cprint('Using intensities: {}'.format(uargs.intensities), 'cyan')
1147
+ ut.cprint('Using intensities: {}'.format(uargs.intensities), 'cyan')
1141
1148
 
1142
- # Plot each section
1143
- for it, data in enumerate(all_data):
1149
+ # Create absorption data object
1150
+ # one per dataset extracted
1151
+ # (doubtful multiple datasets will be present, but just in case)
1152
+ all_abs_data = [
1153
+ d.AbsorptionData.from_extractor_dataset(
1154
+ dataset,
1155
+ uargs.intensities,
1156
+ remove_zero_osc=uargs.zero_osc
1157
+ )
1158
+ for dataset in all_datasets
1159
+ ]
1144
1160
 
1145
- if len(all_data) > 1:
1146
- save_name = f'emission_spectrum_section_{it:d}.png'
1147
- else:
1148
- save_name = 'emission_spectrum.png'
1161
+ # Check absorption data was found
1162
+ if len(all_abs_data) == 0:
1163
+ ut.red_exit(
1164
+ f'No ABSORPTION data found in file {output_file}', 'red'
1165
+ )
1166
+ # report if multiple absorption sections found
1167
+ elif len(all_abs_data) > 1:
1168
+ ut.cprint(
1169
+ f'\nFound {len(all_abs_data)} ABSORPTION sections in '
1170
+ f'file {output_file}\n'
1171
+ f'Plotting final section ONLY\n',
1172
+ 'cyan'
1173
+ )
1174
+ # and only use final one
1175
+ # (again, doubtful multiple sections will be present, but just in case)
1176
+ abs_data = all_abs_data[-1]
1149
1177
 
1178
+ # Determine x values for setting x limits of computed spectrum
1150
1179
  if uargs.x_unit == 'wavenumber':
1151
- x_values = np.asarray(data['energy (cm^-1)'])
1180
+ x_vals = abs_data.wavenumbers
1181
+ min_factor = 0.8
1182
+ max_factor = 1.1
1183
+ x_reversed = False
1152
1184
  elif uargs.x_unit == 'wavelength':
1153
- x_values = 1E7 / np.asarray(data['energy (cm^-1)'])
1185
+ x_vals = abs_data.wavelengths
1186
+ max_factor = 1.1
1187
+ min_factor = 0.8
1188
+ x_reversed = False
1154
1189
  elif uargs.x_unit == 'wavelength_rev':
1155
- x_values = 1E7 / np.asarray(data['energy (cm^-1)'])
1190
+ x_vals = abs_data.wavelengths
1191
+ max_factor = 1.1
1192
+ min_factor = 0.8
1193
+ x_reversed = True
1194
+ uargs.x_unit = 'wavelength'
1156
1195
  elif uargs.x_unit == 'energy':
1157
- x_values = np.asarray(data['energy (ev)'])
1158
-
1159
- data['fosc'] = np.asarray(data['fosc'])
1160
-
1161
- # Remove transitions with zero oscillator strength from
1162
- # beginning and end of spectrum
1163
- if not uargs.no_trim:
1164
- # Find first non-zero oscillator strength
1165
- first_nonzero = np.where(data['fosc'] > 1E-6)[0][0]
1166
- # Find last non-zero oscillator strength
1167
- last_nonzero = np.where(data['fosc'] > 1E-6)[0][-1]
1168
-
1169
- # Trim data
1170
- x_values = x_values[first_nonzero:last_nonzero + 1]
1171
- data['fosc'] = data['fosc'][first_nonzero:last_nonzero + 1]
1172
-
1173
- # Plot emission spectrum
1174
- fig, ax = plotter.plot_abs(
1175
- x_values,
1176
- uargs.x_unit,
1177
- data['fosc'],
1178
- show=_SHOW_CONV[uargs.plot],
1179
- save=_SAVE_CONV[uargs.plot],
1180
- save_name=save_name,
1181
- xlim=uargs.xlim,
1182
- ylim=uargs.ylim,
1183
- x_shift=uargs.shift,
1184
- linewidth=uargs.linewidth,
1196
+ x_vals = abs_data.energies
1197
+ min_factor = 0.9995
1198
+ max_factor = 1.0005
1199
+ x_reversed = False
1200
+
1201
+ # Set x_min
1202
+ # based on user arguments
1203
+ if isinstance(uargs.xlim[0], str):
1204
+ if uargs.xlim[0] == 'auto':
1205
+ x_min = min(x_vals) * min_factor
1206
+ elif ut.is_floatable(uargs.xlim[0]):
1207
+ x_min = float(uargs.xlim[0])
1208
+ else:
1209
+ raise ValueError(f'Invalid x_min value: {uargs.xlim[0]}')
1210
+ else:
1211
+ x_min = uargs.xlim[0]
1212
+
1213
+ # Set x_max
1214
+ # based on user arguments
1215
+ if isinstance(uargs.xlim[1], str):
1216
+ if uargs.xlim[1] == 'auto':
1217
+ x_max = max(x_vals) * max_factor
1218
+ elif ut.is_floatable(uargs.xlim[1]):
1219
+ x_max = float(uargs.xlim[1])
1220
+ else:
1221
+ raise ValueError(f'Invalid x_max value: {uargs.xlim[1]}')
1222
+ else:
1223
+ x_max = uargs.xlim[1]
1224
+
1225
+ # Trim transitions to a specific number of states if requested
1226
+ if uargs.trim_transitions is not None:
1227
+ abs_data.trim_to_n(uargs.trim_transitions)
1228
+
1229
+ # Generate spectrum data
1230
+ abs_data.generate_spectrum(
1231
+ fwhm=uargs.linewidth,
1185
1232
  lineshape=uargs.lineshape,
1186
- window_title=f'Emission Spectrum from {uargs.output_file}',
1233
+ x_type=uargs.x_unit,
1234
+ num_points=10000,
1235
+ x_min=x_min,
1236
+ x_max=x_max,
1237
+ comment=output_file,
1238
+ x_reversed=x_reversed
1239
+ )
1240
+
1241
+ # Save spectrum data to file
1242
+ if save_data_only:
1243
+ abs_data.save_spectrum_data(
1244
+ f'absorption_spectrum_{output_file.stem}.csv',
1245
+ comments='Data from {}\nfwhm={}, lineshape={}\nintensities={}'.format( # noqa
1246
+ output_file,
1247
+ uargs.linewidth,
1248
+ uargs.lineshape,
1249
+ uargs.intensities
1250
+ )
1251
+ )
1252
+ abs_data.save_transition_data(
1253
+ f'transition_data_{output_file.stem}.csv',
1254
+ comments='Data from {}\nintensities={}'.format(
1255
+ output_file,
1256
+ uargs.intensities
1257
+ )
1258
+ )
1259
+ ut.cprint(
1260
+ f'Saved absorption spectrum to absorption_spectrum_{output_file.stem}.csv', # noqa
1261
+ 'cyan'
1262
+ )
1263
+ ut.cprint(
1264
+ f'Saved absorption data to transition_data_{output_file.stem}.csv', # noqa
1265
+ 'cyan'
1266
+ )
1267
+ else:
1268
+ # Add to dictionary of absorption data for plotting later
1269
+ spectra_dict[output_file] = abs_data
1270
+
1271
+ # Exit if only saving data
1272
+ if save_data_only:
1273
+ return
1274
+
1275
+ # Plot all spectra
1276
+ import matplotlib.pyplot as plt
1277
+ import matplotlib.colors as mcolors
1278
+
1279
+ # Set font name and size
1280
+ ut.check_font_envvar()
1281
+ plt.rcParams['font.size'] = 10
1282
+ plt.rcParams['legend.fontsize'] = 9
1283
+ plt.rcParams['legend.loc'] = 'center right'
1284
+
1285
+ # Create list of colours for plotting
1286
+ if len(uargs.output_file) == 1:
1287
+ colours = ['black']
1288
+ else:
1289
+ colours = list(mcolors.TABLEAU_COLORS.values())
1290
+
1291
+ # Width of figure in inches
1292
+ # Make wider if multiple spectra to plot
1293
+ # to include legend
1294
+ if len(spectra_dict) > 1:
1295
+ width = 6.
1296
+ else:
1297
+ width = 4.
1298
+ # width in cm
1299
+ width_cm = 2.54 * width
1300
+
1301
+ # Create figure and axis with
1302
+ # height based on golden ratio
1303
+ golden = (1 + np.sqrt(5))/2
1304
+ fig, ax = plt.subplots(
1305
+ 1,
1306
+ 1,
1307
+ num='Absorption Spectrum',
1308
+ figsize=(width, 4. / golden)
1309
+ )
1310
+ # Secondary axis for oscillator strength sticks
1311
+ oax = ax.twinx()
1312
+
1313
+ # Plot absorption spectrum for each file
1314
+ for it, (output_file, abs_data) in enumerate(spectra_dict.items()): # noqa
1315
+
1316
+ plotter.plot_absorption_spectrum(
1317
+ abs_data,
1318
+ linecolor=colours[it],
1319
+ stickcolor=colours[it],
1187
1320
  osc_style=uargs.osc_style,
1188
1321
  normalise=uargs.normalise,
1189
- plot_type='emission'
1322
+ window_title='',
1323
+ fig=fig,
1324
+ ax=ax,
1325
+ oax=oax,
1326
+ show=False,
1327
+ save=False,
1328
+ xlim=[x_min, x_max],
1329
+ ylim=uargs.ylim,
1330
+ x_shift=uargs.x_shift[it],
1331
+ legend=False
1190
1332
  )
1191
1333
 
1192
- if uargs.x_unit == 'wavenumber':
1193
- ax[0].set_xlim([0, 50000])
1334
+ if uargs.xlim != ['auto', 'auto']:
1335
+ ax.set_xlim(float(uargs.xlim[0]), float(uargs.xlim[1]))
1336
+
1337
+ fig.tight_layout()
1338
+
1339
+ if len(spectra_dict) > 1:
1340
+ fig.subplots_adjust(right=3.3/6.)
1341
+ if uargs.legend is None:
1342
+ legend_labels = [
1343
+ f'{output_file.stem}' for output_file in spectra_dict.keys()
1344
+ ]
1345
+ fig.legend(legend_labels, loc=7)
1346
+ else:
1347
+ fig.legend(uargs.legend, loc=7)
1348
+
1349
+ if _SAVE_CONV[uargs.plot]:
1350
+ savename = 'absorption_spectrum.png'
1351
+ plt.savefig(savename, dpi=500)
1352
+ ut.cprint(f'Saved image to {savename}', 'cyan')
1353
+ ut.cprint(
1354
+ f'Use width={width:.1f} in. or {width_cm:.1f} cm',
1355
+ 'cyan'
1356
+ )
1357
+
1358
+ if _SHOW_CONV[uargs.plot]:
1194
1359
  plt.show()
1195
1360
 
1361
+ return
1362
+
1196
1363
 
1197
1364
  def plot_abs_func(uargs, save_data_only=False):
1198
1365
  '''
@@ -2781,6 +2948,132 @@ def read_args(arg_list=None):
2781
2948
  )
2782
2949
  )
2783
2950
 
2951
+ gen_xes = gen_parser.add_parser(
2952
+ 'xes',
2953
+ description='Generates XES data from SGS-DEF calculation output',
2954
+ usage=ut.cstring('orto gen xes <output_file> [options]', 'cyan'),
2955
+ formatter_class=argparse.RawTextHelpFormatter
2956
+ )
2957
+ gen_xes._positionals.title = 'Mandatory Arguments'
2958
+
2959
+ gen_xes.set_defaults(func=lambda x: plot_xes_func(x, save_data_only=True))
2960
+
2961
+ gen_xes.add_argument(
2962
+ 'output_file',
2963
+ type=pathlib.Path,
2964
+ nargs='+',
2965
+ help='Orca output file name'
2966
+ )
2967
+
2968
+ gen_xes.add_argument(
2969
+ '--intensities',
2970
+ '-i',
2971
+ type=str,
2972
+ choices=['velocity', 'electric', 'semi-classical'],
2973
+ default='electric',
2974
+ help='Type of intensity to plot (orca_mapspc uses electric)'
2975
+ )
2976
+
2977
+ gen_xes.add_argument(
2978
+ '--linewidth',
2979
+ '-lw',
2980
+ type=float,
2981
+ default=1,
2982
+ help=(
2983
+ 'Width of signal (FWHM for Gaussian, Width for Lorentzian),'
2984
+ ' in same unit as x axis'
2985
+ )
2986
+ )
2987
+
2988
+ gen_xes.add_argument(
2989
+ '--lineshape',
2990
+ '-ls',
2991
+ type=str,
2992
+ choices=['gaussian', 'lorentzian'],
2993
+ default='lorentzian',
2994
+ help='Lineshape to use for each signal'
2995
+ )
2996
+
2997
+ gen_xes.add_argument(
2998
+ '--x_unit',
2999
+ '-xu',
3000
+ type=str,
3001
+ choices=['energy', 'wavelength', 'wavenumber'],
3002
+ default='energy',
3003
+ help='x units to use for spectrum'
3004
+ )
3005
+
3006
+ gen_xes.add_argument(
3007
+ '--x_shift',
3008
+ type=float,
3009
+ default=None,
3010
+ nargs='+',
3011
+ help=(
3012
+ 'Shift spectrum by this amount in x units\n'
3013
+ 'Default: 0.'
3014
+ )
3015
+ )
3016
+
3017
+ gen_xes.add_argument(
3018
+ '--no_trim',
3019
+ action='store_true',
3020
+ default=False,
3021
+ help=(
3022
+ 'Do not trim spectrum to non-zero oscillator strength\n'
3023
+ 'Default: %(default)s'
3024
+ )
3025
+ )
3026
+
3027
+ gen_xes.add_argument(
3028
+ '--xlim',
3029
+ nargs=2,
3030
+ default=['auto', 'auto'],
3031
+ help='x limits of spectrum'
3032
+ )
3033
+
3034
+ gen_xes.add_argument(
3035
+ '--normalise',
3036
+ '-n',
3037
+ action='store_true',
3038
+ default=False,
3039
+ help=(
3040
+ 'Normalises spectrum to maximum value\n'
3041
+ 'Default: %(default)s'
3042
+ )
3043
+ )
3044
+
3045
+ gen_xes.add_argument(
3046
+ '--zero_osc',
3047
+ default=1E-7,
3048
+ type=float,
3049
+ help=(
3050
+ 'Oscillator strengths below this value are treated as zero\n'
3051
+ 'Default: %(default)s'
3052
+ )
3053
+ )
3054
+
3055
+ gen_xes.add_argument(
3056
+ '--unique_names',
3057
+ action='store_true',
3058
+ default=False,
3059
+ help=(
3060
+ 'Attempt to shorten file names in plot legend\n'
3061
+ 'Default: %(default)s'
3062
+ )
3063
+ )
3064
+
3065
+ gen_xes.add_argument(
3066
+ '--trim_transitions',
3067
+ '-tt',
3068
+ type=int,
3069
+ default=None,
3070
+ help=(
3071
+ 'Trim to first n transitions\n'
3072
+ 'where n is an integer\n'
3073
+ 'Default: %(default)s'
3074
+ )
3075
+ )
3076
+
2784
3077
  plot_subprog = all_subparsers.add_parser(
2785
3078
  'plot',
2786
3079
  description='Plot data from orca file',
@@ -2957,11 +3250,10 @@ def read_args(arg_list=None):
2957
3250
  'Default: %(default)s'
2958
3251
  )
2959
3252
  )
2960
-
2961
3253
  plot_xes = plot_parser.add_parser(
2962
3254
  'xes',
2963
- description='Plots XES from CI calculation output',
2964
- usage=ut.cstring('orto plot xes <output_file>', 'cyan'),
3255
+ description='Plots X-ray emission spectrum from SGS-DFT calculation output', # noqa
3256
+ usage=ut.cstring('orto plot xes <output_file> [options]', 'cyan'),
2965
3257
  formatter_class=argparse.RawTextHelpFormatter
2966
3258
  )
2967
3259
  plot_xes._positionals.title = 'Mandatory Arguments'
@@ -2971,6 +3263,7 @@ def read_args(arg_list=None):
2971
3263
  plot_xes.add_argument(
2972
3264
  'output_file',
2973
3265
  type=pathlib.Path,
3266
+ nargs='+',
2974
3267
  help='Orca output file name'
2975
3268
  )
2976
3269
 
@@ -2978,14 +3271,7 @@ def read_args(arg_list=None):
2978
3271
  '--intensities',
2979
3272
  '-i',
2980
3273
  type=str,
2981
- choices=[
2982
- 'velocity',
2983
- 'electric',
2984
- 'semi-classical',
2985
- 'so_velocity',
2986
- 'so_electric',
2987
- 'so_semi-classical',
2988
- ],
3274
+ choices=['velocity', 'electric', 'semi-classical'],
2989
3275
  default='electric',
2990
3276
  help='Type of intensity to plot (orca_mapspc uses electric)'
2991
3277
  )
@@ -2994,17 +3280,17 @@ def read_args(arg_list=None):
2994
3280
  '--linewidth',
2995
3281
  '-lw',
2996
3282
  type=float,
2997
- default=2000,
3283
+ default=1,
2998
3284
  help=(
2999
3285
  'Width of signal (FWHM for Gaussian, Width for Lorentzian),'
3000
- ' in Wavenumbers'
3286
+ ' in same unit as x axis'
3001
3287
  )
3002
3288
  )
3003
3289
 
3004
3290
  plot_xes.add_argument(
3005
3291
  '--osc_style',
3006
3292
  type=str,
3007
- default='combined',
3293
+ default='separate',
3008
3294
  help=(
3009
3295
  'Style of oscillators to plot\n'
3010
3296
  ' - \'separate\' plots oscillator strengths as stems on separate axis\n' # noqa
@@ -3042,29 +3328,21 @@ def read_args(arg_list=None):
3042
3328
 
3043
3329
  plot_xes.add_argument(
3044
3330
  '--x_unit',
3331
+ '-xu',
3045
3332
  type=str,
3046
- choices=['wavenumber', 'energy', 'wavelength'],
3047
- default='wavenumber',
3048
- help='x units to use for spectrum'
3333
+ choices=['energy', 'wavelength', 'wavelength_rev', 'wavenumber'],
3334
+ default='energy',
3335
+ help='x units to use for spectrum (rev = reversed axis direction)'
3049
3336
  )
3050
3337
 
3051
3338
  plot_xes.add_argument(
3052
- '--shift',
3339
+ '--x_shift',
3053
3340
  type=float,
3054
- default=0.,
3341
+ default=None,
3342
+ nargs='+',
3055
3343
  help=(
3056
3344
  'Shift spectrum by this amount in x units\n'
3057
- 'Default: %(default)s'
3058
- )
3059
- )
3060
-
3061
- plot_xes.add_argument(
3062
- '--no_trim',
3063
- action='store_true',
3064
- default=False,
3065
- help=(
3066
- 'Do not trim spectrum to non-zero oscillator strength\n'
3067
- 'Default: %(default)s'
3345
+ 'Default: 0.'
3068
3346
  )
3069
3347
  )
3070
3348
 
@@ -3093,6 +3371,49 @@ def read_args(arg_list=None):
3093
3371
  )
3094
3372
  )
3095
3373
 
3374
+ plot_xes.add_argument(
3375
+ '--zero_osc',
3376
+ default=1E-7,
3377
+ type=float,
3378
+ help=(
3379
+ 'Oscillator strengths below this value are treated as zero\n'
3380
+ 'Default: %(default)s'
3381
+ )
3382
+ )
3383
+
3384
+ plot_xes.add_argument(
3385
+ '--legend',
3386
+ type=str,
3387
+ nargs='+',
3388
+ default=None,
3389
+ help=(
3390
+ 'Legend labels for each spectrum plotted\n'
3391
+ 'If not provided, file names are used\n'
3392
+ )
3393
+ )
3394
+
3395
+ plot_xes.add_argument(
3396
+ '--trim_transitions',
3397
+ '-tt',
3398
+ type=int,
3399
+ default=None,
3400
+ help=(
3401
+ 'Trim to first n transitions\n'
3402
+ 'where n is an integer\n'
3403
+ 'Default: %(default)s'
3404
+ )
3405
+ )
3406
+
3407
+ plot_xes.add_argument(
3408
+ '--no_trim',
3409
+ action='store_true',
3410
+ default=False,
3411
+ help=(
3412
+ 'Do not trim spectrum to non-zero oscillator strength\n'
3413
+ 'Default: %(default)s'
3414
+ )
3415
+ )
3416
+
3096
3417
  plot_ailft = plot_parser.add_parser(
3097
3418
  'ailft_orbs',
3098
3419
  aliases=['ailft_orb'],
orto/extractor.py CHANGED
@@ -380,6 +380,81 @@ class ExchangeCouplingExtractor(extto.BetweenExtractor):
380
380
  return _ext.data
381
381
 
382
382
 
383
+ class AILFTOrbMatrixExtractor(extto.BetweenExtractor):
384
+ '''
385
+ Extracts AI-LFT orbital matrix from Orca output file
386
+ '''
387
+ # Regex Start Pattern
388
+ START_PATTERN = rb'(?<=Ligand field one-electron matrix VLFT \(a.u.\) : )' # noqa
389
+
390
+ # Regex End Pattern
391
+ END_PATTERN = rb'(?=-------------------------------------------------)'
392
+
393
+ MODIFIERS = [re.MULTILINE]
394
+
395
+ @property
396
+ def data(self) -> list[NDArray]:
397
+ '''
398
+ AI-LFT matrices, one per block, in atomic units
399
+ '''
400
+ return self._data
401
+
402
+ @staticmethod
403
+ def _process_block(block: str) -> NDArray:
404
+ '''
405
+ Converts single block into data entries described in self.data
406
+
407
+ Parameters
408
+ ----------
409
+ block: str
410
+ String block extracted from file
411
+
412
+ Returns
413
+ -------
414
+ ndarray of floats
415
+ Keys described in self.data
416
+ '''
417
+
418
+ # Find number of orbitals from header of matrix
419
+ orb_list = re.findall(
420
+ r'Orbital[\sxyzd2f3\-]+\n',
421
+ block
422
+ )
423
+ n_orbs = len(orb_list[0].split()) - 1
424
+
425
+ rows = re.findall(
426
+ rf'((?:\s+\-?\d\.\d{{6}}){{{n_orbs:d}}})', # noqa
427
+ block
428
+ )
429
+
430
+ matrix = np.array([
431
+ [float(ve) for ve in row.split()]
432
+ for row in rows
433
+ ])
434
+
435
+ return matrix
436
+
437
+ @classmethod
438
+ def extract(cls, file_name: str | pathlib.Path) -> list[NDArray]: # noqa
439
+ '''
440
+ Convenience method which instantiates class, extracts blocks, and
441
+ returns processed datasets
442
+
443
+ Parameters
444
+ ----------
445
+ file_name: str | pathlib.Path
446
+ File to parse
447
+
448
+ Returns
449
+ -------
450
+ list[ndarray of floats]
451
+ Each entry contains processed data, as defined in cls.data
452
+ '''
453
+ _ext = cls()
454
+ _ext(file_name, process=True)
455
+ return _ext.data
456
+
457
+
383
458
  class AILFTOrbEnergyExtractor(extto.BetweenExtractor):
384
459
  '''
385
460
  Extracts AI-LFT orbital energies from Orca output file
@@ -1762,7 +1837,7 @@ class XESElectricDipoleExtractor(AbsorptionElectricDipoleExtractor):
1762
1837
  OPERATOR_TYPE = 'Electric Dipole'
1763
1838
 
1764
1839
  # Regex Start Pattern
1765
- START_PATTERN = rb'(?<= X-RAY EMISSION SPECTRUM VIA TRANSITION VELOCITY DIPOLE MOMENTS\s[\S\s]{408}\s)' # noqa
1840
+ START_PATTERN = rb'(?<= X-RAY EMISSION SPECTRUM VIA TRANSITION ELECTRIC DIPOLE MOMENTS\s[\S\s]{408}\s)' # noqa
1766
1841
 
1767
1842
  # Regex End Pattern
1768
1843
  END_PATTERN = rb'(?=-{77})'
@@ -2292,7 +2367,7 @@ class StructureInputExtractor(extto.BetweenExtractor):
2292
2367
 
2293
2368
  # Get labels and coordinates
2294
2369
  all_info = re.findall(
2295
- r'([A-Za-z]+\s*-?\d\.\d*\s+-?\d\.\d*\s+-?\d\.\d*)',
2370
+ r'([A-Za-z]+\s*-?\d*\.\d*\s+-?\d*\.\d*\s+-?\d*\.\d*)',
2296
2371
  block
2297
2372
  )
2298
2373
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: orto
3
- Version: 1.13.1
3
+ Version: 1.14.1
4
4
  Summary: A package to make life easier when performing Orca calculations.
5
5
  Home-page: https://orto.kragskow.group
6
6
  Author: Jon Kragskow
@@ -1,17 +1,17 @@
1
1
  orto/__init__.py,sha256=IedlltYr3qYZxChNUdz62qogXA9Pos_MUvXdGXqAa0E,41
2
- orto/__version__.py,sha256=AWOJJXuaKFwrwxYimWHjFlOhtOJuGrGuiJ0JN7ehebE,23
3
- orto/cli.py,sha256=gBc8sSq9L3FXoYEyYxFQRMCCGtTEaVaGjePXOAnLM8Y,106677
2
+ orto/__version__.py,sha256=eyARjsqZfiB7blnKzG-sgKU2HEsI143aQSUAfhkeA8U,23
3
+ orto/cli.py,sha256=pyWz9CDKyoMyJtKlc68iW-9cZZc0VF6o44lmtvA4RC8,115549
4
4
  orto/constants.py,sha256=anxaiTykO8Q_CXliR7zuOAdnXZrQ2-C4ndaviyl7kGc,419
5
5
  orto/data.py,sha256=uHxgL-RIwQD61ZsrJPbrS0NBPDb3qIeLSbnpjlsPmiI,18225
6
6
  orto/exceptions.py,sha256=D7oNeAEGeJNt5thzt6PaCn5FY6JcbJOWUE1N1LVhhuE,159
7
- orto/extractor.py,sha256=nhrtzaeJtuU_SkMm201Z1ZqgHYnlsNfHxVOfVhs5plU,87484
7
+ orto/extractor.py,sha256=PpaR9F7yW0cJIDuvuuJSbvqAftmlj9sZmgb7g91c0Wo,89391
8
8
  orto/input.py,sha256=uUQV6A-8D0GZpRoY1rKK_aUPmk9kVVTnMzTHuisP5t4,11888
9
9
  orto/job.py,sha256=tDiz9omFwinoYJamgz66MZez0Ee9HMhuCIAeHMhXRF8,5916
10
10
  orto/plotter.py,sha256=gw1oSPilWvUO__CjIq8gP9a8_Xq0078VE9porOPvhCc,19661
11
11
  orto/utils.py,sha256=2vMUQa_QPi7RbBdZN9EUara6A58GLZkJb9TfMTbBroU,11259
12
- orto-1.13.1.dist-info/licenses/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
13
- orto-1.13.1.dist-info/METADATA,sha256=k71QOiH_in85mH8YKiMRgSr2XTG_6O5ROqkHqxosiQ0,1185
14
- orto-1.13.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
15
- orto-1.13.1.dist-info/entry_points.txt,sha256=HXenCglMp_03JkN34pK2phkjXK9CFcXTGHKv5QaVY8I,39
16
- orto-1.13.1.dist-info/top_level.txt,sha256=hQ-z28gTN_FZ2B5Kiwxr_9cUTcCoib9W5HjbkceDXw4,5
17
- orto-1.13.1.dist-info/RECORD,,
12
+ orto-1.14.1.dist-info/licenses/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
13
+ orto-1.14.1.dist-info/METADATA,sha256=SIjGV-P2CGJOphlqcU2uPPSDh7ZGufEIbFJkoc5bMS4,1185
14
+ orto-1.14.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
15
+ orto-1.14.1.dist-info/entry_points.txt,sha256=HXenCglMp_03JkN34pK2phkjXK9CFcXTGHKv5QaVY8I,39
16
+ orto-1.14.1.dist-info/top_level.txt,sha256=hQ-z28gTN_FZ2B5Kiwxr_9cUTcCoib9W5HjbkceDXw4,5
17
+ orto-1.14.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5