orto 1.5.0__py3-none-any.whl → 1.6.0__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/plotter.py CHANGED
@@ -2,117 +2,44 @@ import matplotlib.pyplot as plt
2
2
  import matplotlib as mpl
3
3
  from matplotlib.ticker import AutoMinorLocator
4
4
  import numpy as np
5
- from numpy.typing import ArrayLike, NDArray
5
+ from numpy.typing import ArrayLike
6
6
  import itertools
7
7
  import pathlib
8
8
 
9
9
  from . import utils as ut
10
-
11
-
12
- def gaussian(p: ArrayLike, fwhm: float, b: float, area: float) -> NDArray:
13
- """
14
- Gaussian g(p) with given peak position (b), fwhm, and area
15
-
16
- g(p) = area/(c*sqrt(2pi)) * exp(-(p-b)**2/(2c**2))
17
-
18
- c = fwhm/(2*np.sqrt(2*np.log(2)))
19
-
20
- Parameters
21
- ----------
22
- p : array_like
23
- Continuous variable
24
- fwhm: float
25
- Full Width at Half-Maximum
26
- b : float
27
- Peak position
28
- area : float
29
- Area of Gaussian function
30
-
31
- Return
32
- ------
33
- list[float]
34
- g(p) at each value of p
35
- """
36
-
37
- c = fwhm / (2 * np.sqrt(2 * np.log(2)))
38
-
39
- a = 1. / (c * np.sqrt(2 * np.pi))
40
-
41
- gaus = a * np.exp(-(p - b)**2 / (2 * c**2))
42
-
43
- gaus *= area
44
-
45
- return gaus
46
-
47
-
48
- def lorentzian(p: ArrayLike, fwhm, p0, area) -> NDArray:
49
- """
50
- Lotenztian L(p) with given peak position (b), fwhm, and area
51
-
52
- L(p) = (0.5*area*fwhm/pi) * 1/((p-p0)**2 + (0.5*fwhm)**2)
53
-
54
- Parameters
55
- ----------
56
- p : array_like
57
- Continuous variable
58
- fwhm: float
59
- Full Width at Half-Maximum
60
- p0 : float
61
- Peak position
62
- area : float
63
- Area of Lorentzian function
64
-
65
- Return
66
- ------
67
- list[float]
68
- L(p) at each value of p
69
- """
70
-
71
- lor = 0.5 * fwhm / np.pi
72
- lor *= 1. / ((p - p0)**2 + (0.5 * fwhm)**2)
73
-
74
- lor *= area
75
-
76
- return lor
77
-
78
-
79
- def plot_abs(x_values: ArrayLike, x_type: str, foscs: ArrayLike,
80
- lineshape: str = 'gaussian', linewidth: float = 100.,
81
- x_lim: list[float] = ['auto', 'auto'],
82
- abs_type: str = 'napierian',
83
- y_lim: list[float] = [0., 'auto'],
84
- x_shift: float = 0., normalise: bool = False,
85
- osc_style: str = 'separate', save: bool = False,
86
- save_name: str = 'absorption_spectrum.png', show: bool = False,
87
- verbose: bool = True,
88
- window_title: str = 'Absorption Spectrum',
89
- plot_type: str = 'absorption') -> tuple[plt.Figure, list[plt.Axes]]: # noqa
10
+ from . import data
11
+
12
+
13
+ def plot_absorption_spectrum(abs_data: data.AbsorptionData,
14
+ linecolor: str = 'black',
15
+ stickcolour: str = 'black',
16
+ x_lim: list[float] = ['auto', 'auto'],
17
+ y_lim: list[float] = [0., 'auto'],
18
+ x_shift: float = 0.,
19
+ normalise: bool = False,
20
+ osc_style: str = 'separate',
21
+ fig: plt.Figure = None, ax: plt.Axes = None,
22
+ oax: plt.Axes = None, save: bool = False,
23
+ save_name: str = 'absorption_spectrum.png',
24
+ show: bool = False,
25
+ verbose: bool = True,
26
+ window_title: str = 'Absorption Spectrum',
27
+ legend: bool = True) -> tuple[plt.Figure, plt.Axes, plt.Axes | None]: # noqa
90
28
  '''
91
- Plots absorption spectrum with intensity specified by oscillator strength.\n # noqa
92
- Spectrum is computed as a sum of Gaussian or Lorentzian lineshapes.\n
93
- The x_values can be either wavenumbers [cm^-1], wavelengths [nm] or\n
94
- energies [eV].\n
29
+ Plots absorption spectrum from AbsorptionSpectrum object.\n
95
30
 
96
31
  Parameters
97
32
  ----------
98
- x_values: array_like
99
- x_values for each transition, either wavenumber, wavelength or energy\n
100
- with unit type specified by x_type
101
- x_type: str {'wavenumber', 'wavelength', 'energy'}
102
- Type of x_values, either wavenumber [cm^-1], wavelength [nm] or\n
103
- energy [eV].
104
- foscs: array_like
105
- Oscillator strength of each transition
106
- lineshape: str {'gaussian', 'lorentzian'}
107
- Lineshape function to use for each transition/signal
108
- linewidth: float
109
- Linewidth used in lineshape [cm^-1]
33
+ abs_data: data.AbsorptionData
34
+ Data object containing absorption data and spectrum
35
+ linecolor: str, default 'black'
36
+ Color of the continuous spectrum line
37
+ stickcolour: str, default 'black'
38
+ Color of the oscillator strength sticks
110
39
  x_lim: list[float], default ['auto', 'auto']
111
- Minimum and maximum x-values to plot [cm^-1 or nm]
40
+ Minimum and maximum x-values to plot
112
41
  y_lim: list[float | str], default [0., 'auto']
113
- Minimum and maximum y-values to plot [cm^-1 mol^-1 L]
114
- abs_type: str {'napierian', 'logarithmic'}
115
- Absorbance (and epsilon) type to use. Orca_mapspc uses napierian
42
+ Minimum and maximum y-values to plot
116
43
  normalise: bool, default False
117
44
  If True, normalise the absorption spectrum to the maximum value.
118
45
  osc_style: str, default 'separate'
@@ -120,6 +47,12 @@ def plot_abs(x_values: ArrayLike, x_type: str, foscs: ArrayLike,
120
47
  - 'separate': plots oscillator strengths as stems on separate axis
121
48
  - 'combined': plots oscillator strengths on intensity axis
122
49
  - 'off': does not plot oscillator strengths
50
+ fig: plt.Figure | None, optional
51
+ If provided, uses this Figure object for plotting
52
+ ax: plt.Axes | None, optional
53
+ If provided, uses this Axis object for plotting spectrum
54
+ oax: plt.Axes | None, optional
55
+ If provided, uses this Axis object for plotting oscillator strengths
123
56
  save: bool, default False
124
57
  If True, plot is saved to save_name
125
58
  save_name: str | pathlib.Path, default 'absorption_spectrum.png'
@@ -130,9 +63,8 @@ def plot_abs(x_values: ArrayLike, x_type: str, foscs: ArrayLike,
130
63
  If True, plot file location is written to terminal
131
64
  window_title: str, default 'UV-Visible Absorption Spectrum'
132
65
  Title of figure window, not of plot
133
- plot_type: str, default 'absorption'
134
- Type of plot to create, either 'absorption' or 'emission'.
135
-
66
+ legend: bool, default True
67
+ If True, a legend is added to the plot
136
68
  Returns
137
69
  -------
138
70
  plt.Figure
@@ -141,20 +73,16 @@ def plot_abs(x_values: ArrayLike, x_type: str, foscs: ArrayLike,
141
73
  Matplotlib Axis object for main plot followed by\n
142
74
  Matplotlib Axis object for twinx oscillator strength axis
143
75
  '''
144
-
145
76
  save_name = pathlib.Path(save_name)
146
77
 
147
- x_values = np.asarray(x_values) + x_shift
148
- foscs = np.asarray(foscs)
149
- if len(x_values) != len(foscs):
150
- raise ValueError('x_values and foscs must have the same length')
78
+ if abs_data.spectrum is None:
79
+ raise ValueError('AbsorptionData object does not contain spectrum')
151
80
 
152
- fig, ax = plt.subplots(1, 1, num=window_title)
81
+ if fig is None or ax is None:
82
+ fig, ax = plt.subplots(1, 1, num=window_title)
153
83
 
154
- ls_func = {
155
- 'gaussian': gaussian,
156
- 'lorentzian': lorentzian
157
- }
84
+ if oax is None and osc_style == 'separate':
85
+ oax = ax.twinx()
158
86
 
159
87
  if not isinstance(x_lim, list):
160
88
  raise ValueError('`x_lim` must be a list of values')
@@ -163,137 +91,133 @@ def plot_abs(x_values: ArrayLike, x_type: str, foscs: ArrayLike,
163
91
  if isinstance(x_lim[0], str):
164
92
  if x_lim[0] == 'auto':
165
93
  x_lim[0] = ax.get_ylim()[0]
166
- else:
94
+ elif ut.is_floatable(x_lim[0]):
167
95
  x_lim[0] = float(x_lim[0])
96
+ else:
97
+ raise ValueError(f'Invalid x_lim[0] value: {x_lim[0]}')
168
98
  if isinstance(x_lim[1], str):
169
99
  if x_lim[1] == 'auto':
170
100
  x_lim[1] = ax.get_ylim()[1]
171
- else:
101
+ elif ut.is_floatable(x_lim[1]):
172
102
  x_lim[1] = float(x_lim[1])
173
- else:
174
- x_lim = [np.min(x_values), np.max(x_values)]
103
+ else:
104
+ raise ValueError(f'Invalid x_lim[1] value: {x_lim[1]}')
175
105
 
176
106
  # Set limits and range of continuous variable
177
- ax.set_xlim([x_lim[0], x_lim[1]])
178
- x_grid = np.linspace(x_lim[0], x_lim[1], 100000)
179
-
180
- # Exclude values of x_values out of the range of x_lim
181
- x_values = np.asarray(
182
- [val for val in x_values if x_lim[0] <= val <= x_lim[1]]
183
- )
184
- # Exclude oscillator strengths for those values
185
- foscs = np.asarray(
186
- [
187
- fosc
188
- for val, fosc in zip(x_values, foscs)
189
- if x_lim[0] <= val <= x_lim[1]]
190
- )
191
-
192
- # Conversion from oscillator strength to napierian integrated absorption
193
- # coefficient
194
- # This is the value of A for a harmonically oscillating electron
195
- A_elec = 2.31E8
196
- # convert to common log absorbance if desired
197
- if abs_type == 'log':
198
- A_elec /= np.log(10)
199
- A_logs = [fosc * A_elec for fosc in foscs]
200
-
201
- # Spectrum as sum of signals. Always computed in wavenumbers.
202
- spectrum = np.sum([
203
- ls_func[lineshape](x_grid, linewidth, x_value, A_log)
204
- for x_value, A_log in zip(x_values, A_logs)
205
- ], axis=0)
107
+ # ax.set_xlim([x_lim[0], x_lim[1]])
206
108
 
109
+ # Normalisation of spectrum
207
110
  if normalise:
208
111
  # Normalise the spectrum to the maximum value
209
- spectrum /= np.max(spectrum)
210
- ax.set_ylabel(
211
- 'Normalised {} (arbitrary units)'.format(
212
- plot_type.capitalize()
213
- )
214
- ) # noqa
112
+ _y_values = abs_data.spectrum.y_values / np.max(abs_data.spectrum.y_values) # noqa
113
+ _osc = abs_data.osc_strengths / np.max(abs_data.osc_strengths)
114
+ ax.set_ylabel('Normalised Absorption')
215
115
  else:
216
- ax.set_ylabel(r'$\epsilon$ (cm$^\mathregular{-1}$ mol$^\mathregular{-1}$ L)') # noqa
217
-
218
- _txt_save_name = save_name.with_suffix('.txt')
219
- np.savetxt(
220
- _txt_save_name,
221
- np.vstack([x_grid, spectrum]).T,
222
- fmt='%.5f',
223
- header=f'{plot_type.capitalize()} spectrum data\nx (wavenumber, wavelength or energy), y (absorbance)' # noqa
224
- )
225
- if verbose:
226
- ut.cprint(
227
- f'\n{plot_type.capitalize()} spectrum data saved to\n {_txt_save_name}', # noqa
228
- 'cyan'
229
- )
116
+ _y_values = abs_data.spectrum.y_values
117
+ _osc = abs_data.osc_strengths
118
+ ax.set_ylabel(abs_data.spectrum.y_label)
119
+
120
+ if abs_data.spectrum.x_label == 'Wavelength (nm)':
121
+ ax.invert_xaxis()
122
+ stick_x_values = [
123
+ wavelength + x_shift
124
+ for wavelength in abs_data.wavelengths
125
+ ]
126
+ elif abs_data.spectrum.x_label == 'Energy (eV)':
127
+ stick_x_values = [
128
+ energy + x_shift
129
+ for energy in abs_data.energies
130
+ ]
131
+ elif abs_data.spectrum.x_label == r'Wavenumber (cm$\mathregular{^{-1}}$)':
132
+ stick_x_values = [
133
+ wavenumber + x_shift
134
+ for wavenumber in abs_data.wavenumbers
135
+ ]
136
+
137
+ x_values = abs_data.spectrum.x_grid + x_shift
230
138
 
231
139
  # Main spectrum
232
- ax.plot(x_grid, spectrum, color='k')
140
+ ax.plot(
141
+ x_values,
142
+ _y_values,
143
+ color=linecolor,
144
+ label=abs_data.spectrum.comment
145
+ )
233
146
 
234
147
  if osc_style == 'separate':
235
- fax = ax.twinx()
236
148
  # Oscillator strength twin axis
237
- fax.stem(x_values, foscs, basefmt=' ', markerfmt=' ')
238
- fax.yaxis.set_minor_locator(AutoMinorLocator())
239
- fax.set_ylabel(r'$f_\mathregular{osc}$')
240
- fax.set_ylim([0., fax.get_ylim()[1]])
149
+ oax.stem(
150
+ stick_x_values,
151
+ _osc,
152
+ basefmt=' ',
153
+ markerfmt=' ',
154
+ linefmt=stickcolour
155
+ )
156
+ oax.yaxis.set_minor_locator(AutoMinorLocator())
157
+ oax.set_ylabel(r'$f_\mathregular{osc}$')
158
+ oax.set_ylim([0., oax.get_ylim()[1]])
241
159
  elif osc_style == 'combined':
242
- fax = None
243
- plt.subplots_adjust(right=0.2)
244
160
  ax.stem(
245
- x_values,
246
- foscs/np.max(foscs) * np.max(spectrum),
161
+ stick_x_values,
162
+ abs_data.osc_strengths/np.max(abs_data.osc_strengths) * np.max(_y_values), # noqa
247
163
  basefmt=' ',
248
- markerfmt=' '
164
+ markerfmt=' ',
165
+ linefmt=stickcolour
249
166
  )
167
+ oax.set_yticks([])
168
+ oax.spines['right'].set_visible(False)
169
+ oax.spines['top'].set_visible(False)
250
170
  ax.spines['right'].set_visible(False)
251
171
  ax.spines['top'].set_visible(False)
252
172
  else:
253
- fax = None
254
173
  # No oscillator strength plot
255
174
  plt.subplots_adjust(right=0.2)
175
+ oax.set_yticks([])
176
+ oax.spines['right'].set_visible(False)
177
+ oax.spines['top'].set_visible(False)
256
178
  ax.spines['right'].set_visible(False)
257
179
  ax.spines['top'].set_visible(False)
258
180
 
259
- if y_lim[0] != y_lim[1]:
260
- if isinstance(y_lim[0], str):
261
- if y_lim[0] == 'auto':
262
- y_lim[0] = ax.get_ylim()[0]
181
+ # Set y limits if specified
182
+ _y_lim = y_lim.copy()
183
+ if _y_lim[0] != _y_lim[1]:
184
+ # Lower limit either auto or specified
185
+ if isinstance(_y_lim[0], str):
186
+ if _y_lim[0] == 'auto':
187
+ _y_lim[0] = ax.get_ylim()[0]
263
188
  else:
264
- y_lim[0] = float(y_lim[0])
265
- if isinstance(y_lim[1], str):
266
- if y_lim[1] == 'auto':
267
- y_lim[1] = ax.get_ylim()[1]
189
+ _y_lim[0] = float(_y_lim[0])
190
+ # Upper limit either auto or specified
191
+ if isinstance(_y_lim[1], str):
192
+ if _y_lim[1] == 'auto':
193
+ _y_lim[1] = ax.get_ylim()[1]
268
194
  else:
269
- y_lim[1] = float(y_lim[1])
270
- ax.set_ylim([y_lim[0], y_lim[1]])
195
+ _y_lim[1] = float(_y_lim[1])
196
+ # Set values
197
+ ax.set_ylim([_y_lim[0], _y_lim[1]])
271
198
 
272
199
  ax.xaxis.set_minor_locator(AutoMinorLocator())
273
200
  ax.yaxis.set_minor_locator(AutoMinorLocator())
274
201
 
275
- xtype_to_label = {
276
- 'wavenumber': r'Wavenumber (cm$^\mathregular{-1}$)',
277
- 'wavelength': 'Wavelength (nm)',
278
- 'energy': r'Energy (eV)'
279
- }
280
-
281
- ax.set_xlabel(xtype_to_label[x_type.lower()])
202
+ ax.set_xlabel(abs_data.spectrum.x_label)
282
203
 
283
204
  fig.tight_layout()
284
205
 
206
+ if legend:
207
+ ax.legend()
208
+
285
209
  if save:
286
210
  plt.savefig(save_name, dpi=500)
287
211
  if verbose:
288
212
  ut.cprint(
289
- f'\n{plot_type.capitalize()} spectrum saved to\n {save_name}',
213
+ f'\nSpectrum saved to\n {save_name}',
290
214
  'cyan'
291
215
  )
292
216
 
293
217
  if show:
294
218
  plt.show()
295
219
 
296
- return fig, [ax, fax]
220
+ return fig, ax, oax
297
221
 
298
222
 
299
223
  def wl_to_wn(wl: float) -> float:
@@ -407,8 +331,8 @@ def plot_ir(wavenumbers: ArrayLike, linear_absorbance: ArrayLike,
407
331
  fig, ax = plt.subplots(1, 1, num=window_title)
408
332
 
409
333
  ls_func = {
410
- 'gaussian': gaussian,
411
- 'lorentzian': lorentzian
334
+ 'gaussian': ut.gaussian,
335
+ 'lorentzian': ut.lorentzian
412
336
  }
413
337
 
414
338
  if None not in x_lim:
orto/utils.py CHANGED
@@ -293,3 +293,126 @@ def orbname_to_mathmode(names: ArrayLike) -> NDArray:
293
293
  ])
294
294
 
295
295
  return mmode
296
+
297
+
298
+ def check_font_envvar() -> None:
299
+ '''
300
+ Checks if orto_fontname environment variable is set, and if so
301
+ sets matplotlib font to specified font
302
+ '''
303
+
304
+ import matplotlib.pyplot as plt
305
+
306
+ if os.getenv('orto_fontname'):
307
+ try:
308
+ plt.rcParams['font.family'] = os.getenv('orto_fontname')
309
+ except ValueError:
310
+ red_exit(
311
+ 'Error setting font to {}'.format(
312
+ os.getenv('orto_fontname')
313
+ )
314
+ )
315
+
316
+ return
317
+
318
+
319
+ def gaussian(p: ArrayLike, fwhm: float, b: float, area: float) -> NDArray:
320
+ """
321
+ Gaussian g(p) with given peak position (b), fwhm, and area
322
+
323
+ g(p) = area/(c*sqrt(2pi)) * exp(-(p-b)**2/(2c**2))
324
+
325
+ c = fwhm/(2*np.sqrt(2*np.log(2)))
326
+
327
+ Parameters
328
+ ----------
329
+ p : array_like
330
+ Continuous variable
331
+ fwhm: float
332
+ Full Width at Half-Maximum
333
+ b : float
334
+ Peak position
335
+ area : float
336
+ Area of Gaussian function
337
+
338
+ Return
339
+ ------
340
+ list[float]
341
+ g(p) at each value of p
342
+ """
343
+
344
+ c = fwhm / (2 * np.sqrt(2 * np.log(2)))
345
+
346
+ a = 1. / (c * np.sqrt(2 * np.pi))
347
+
348
+ gaus = a * np.exp(-(p - b)**2 / (2 * c**2))
349
+
350
+ gaus *= area
351
+
352
+ return gaus
353
+
354
+
355
+ def lorentzian(p: ArrayLike, fwhm, p0, area) -> NDArray:
356
+ """
357
+ Lotenztian L(p) with given peak position (b), fwhm, and area
358
+
359
+ L(p) = (0.5*area*fwhm/pi) * 1/((p-p0)**2 + (0.5*fwhm)**2)
360
+
361
+ Parameters
362
+ ----------
363
+ p : array_like
364
+ Continuous variable
365
+ fwhm: float
366
+ Full Width at Half-Maximum
367
+ p0 : float
368
+ Peak position
369
+ area : float
370
+ Area of Lorentzian function
371
+
372
+ Return
373
+ ------
374
+ list[float]
375
+ L(p) at each value of p
376
+ """
377
+
378
+ lor = 0.5 * fwhm / np.pi
379
+ lor *= 1. / ((p - p0)**2 + (0.5 * fwhm)**2)
380
+
381
+ lor *= area
382
+
383
+ return lor
384
+
385
+
386
+ def find_unique_substring(names):
387
+ '''
388
+ Finds unique substring in each name from list of names
389
+ '''
390
+
391
+ unique_names = []
392
+ for name in names:
393
+ for il, letter in enumerate(name):
394
+ if all(oname[il] != letter for oname in names if oname != name):
395
+ unique_names.append(name[il:])
396
+ break
397
+ return unique_names
398
+
399
+ def is_floatable(string: str) -> bool:
400
+ '''
401
+ Checks if string can be converted to float
402
+
403
+ Parameters
404
+ ----------
405
+ string : str
406
+ String to check
407
+
408
+ Returns
409
+ -------
410
+ bool
411
+ True if string can be converted to float, False otherwise
412
+ '''
413
+
414
+ try:
415
+ float(string)
416
+ return True
417
+ except ValueError:
418
+ return False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: orto
3
- Version: 1.5.0
3
+ Version: 1.6.0
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
@@ -12,6 +12,7 @@ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
12
12
  Classifier: Operating System :: OS Independent
13
13
  Requires-Python: >=3.10
14
14
  Description-Content-Type: text/markdown
15
+ License-File: LICENSE
15
16
  Requires-Dist: numpy>=2.1.2
16
17
  Requires-Dist: xyz_py>=5.13.1
17
18
  Requires-Dist: matplotlib>=3.9.2
@@ -25,6 +26,7 @@ Dynamic: classifier
25
26
  Dynamic: description
26
27
  Dynamic: description-content-type
27
28
  Dynamic: home-page
29
+ Dynamic: license-file
28
30
  Dynamic: project-url
29
31
  Dynamic: requires-dist
30
32
  Dynamic: requires-python
@@ -0,0 +1,17 @@
1
+ orto/__init__.py,sha256=IedlltYr3qYZxChNUdz62qogXA9Pos_MUvXdGXqAa0E,41
2
+ orto/__version__.py,sha256=bYN93DTWr8alkTnO3wj31CU5gqTshxIcsbXUcJcUAc8,22
3
+ orto/cli.py,sha256=AH9Cnfu21XGTs2ygLZGb8yxzJPe1gxxnF9qOsm_H1II,76491
4
+ orto/constants.py,sha256=anxaiTykO8Q_CXliR7zuOAdnXZrQ2-C4ndaviyl7kGc,419
5
+ orto/data.py,sha256=r6Ht1X0-FhjUbEAAi3a9F2R2_QG3QFElaAAcZNz4GRQ,11213
6
+ orto/exceptions.py,sha256=D7oNeAEGeJNt5thzt6PaCn5FY6JcbJOWUE1N1LVhhuE,159
7
+ orto/extractor.py,sha256=d2_pGQeIjK_JbsMINTawUgcO2vcPq0b9uQj9VKuI720,75953
8
+ orto/input.py,sha256=N8JbySSVEC_qmXZ7ppJsZ7Z1qel6PfalGYRtnX1hJ6U,9900
9
+ orto/job.py,sha256=SM0nlc_bqhhPvfuuykhMvaUnkwC3Gp-6RvYw_a0TyGc,5855
10
+ orto/plotter.py,sha256=-8Lgv-kDjw_wHZrDrQzQGT521gSZ3IJdIeLqzdQgflQ,17656
11
+ orto/utils.py,sha256=fghKZnrO1HTtOZPZRbNK6QTgUOXiIQ6NEFvesDSoY0o,9836
12
+ orto-1.6.0.dist-info/licenses/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
13
+ orto-1.6.0.dist-info/METADATA,sha256=zfjB9HzSeKgJKRlTqLMw2AmqspP1nyYAlJZDa_vS3kE,1184
14
+ orto-1.6.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
15
+ orto-1.6.0.dist-info/entry_points.txt,sha256=HXenCglMp_03JkN34pK2phkjXK9CFcXTGHKv5QaVY8I,39
16
+ orto-1.6.0.dist-info/top_level.txt,sha256=hQ-z28gTN_FZ2B5Kiwxr_9cUTcCoib9W5HjbkceDXw4,5
17
+ orto-1.6.0.dist-info/RECORD,,