irspec 0.1.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.
- irspec/__init__.py +2 -0
- irspec/__main__.py +4 -0
- irspec/absorbance_to_transmittance.py +146 -0
- irspec/absorptivity_to_absorbance.py +94 -0
- irspec/cli.py +54 -0
- irspec/data/fonts/OFL.txt +92 -0
- irspec/data/fonts/README.txt +10 -0
- irspec/data/fonts/STIXTwoMath-Regular.ttf +0 -0
- irspec/data/fonts/STIXTwoText-Italic.ttf +0 -0
- irspec/data/fonts/STIXTwoText-Regular.ttf +0 -0
- irspec/data/irspec-ir.sty +1852 -0
- irspec/data/irspec.R +277 -0
- irspec/export.py +146 -0
- irspec/figure.py +101 -0
- irspec/fonts.py +32 -0
- irspec/ir_corr.py +73 -0
- irspec/ir_digitize.py +990 -0
- irspec/ir_organize.py +386 -0
- irspec/jdx_tool.py +461 -0
- irspec/layout.py +74 -0
- irspec/mpl.py +178 -0
- irspec/plot.py +65 -0
- irspec/session.py +427 -0
- irspec/spa_peaks.py +443 -0
- irspec/spa_tool.py +717 -0
- irspec/texout.py +97 -0
- irspec-0.1.0.dist-info/METADATA +409 -0
- irspec-0.1.0.dist-info/RECORD +32 -0
- irspec-0.1.0.dist-info/WHEEL +5 -0
- irspec-0.1.0.dist-info/entry_points.txt +2 -0
- irspec-0.1.0.dist-info/licenses/LICENSE +21 -0
- irspec-0.1.0.dist-info/top_level.txt +1 -0
irspec/__init__.py
ADDED
irspec/__main__.py
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""absorbance_to_transmittance.py -- convert an IR spectrum's y-axis between
|
|
3
|
+
Absorbance and %Transmittance for nulabreport figures.
|
|
4
|
+
|
|
5
|
+
WHY THIS EXISTS
|
|
6
|
+
nulabreport's \\irspectrum / \\irspectrumcompare macros just plot whatever
|
|
7
|
+
y-column a CSV gives them; they do not know or care whether that column
|
|
8
|
+
is Absorbance or %Transmittance. When a report puts several reference
|
|
9
|
+
spectra on comparable axes (this lab's own OMNIC exports are always
|
|
10
|
+
%Transmittance, 0-100), a source that is natively Absorbance has to be
|
|
11
|
+
converted on purpose -- silently mixing the two on one figure, or on
|
|
12
|
+
stacked panels a reader will visually compare, misleads regardless of
|
|
13
|
+
axis labels. This script does that conversion, once, in a place that
|
|
14
|
+
documents the formula, rather than as an unrepeatable one-off snippet
|
|
15
|
+
buried in a chat session.
|
|
16
|
+
|
|
17
|
+
Do NOT convert the other direction (Transmittance -> Absorbance) as a
|
|
18
|
+
way to "normalise everything to Absorbance" instead -- this lab's own
|
|
19
|
+
instrument output and house convention are %Transmittance; Absorbance
|
|
20
|
+
sources get converted to match, not the reverse. convert_series() below
|
|
21
|
+
supports both directions for completeness (and because the algebra is
|
|
22
|
+
symmetric), but the CLI defaults to --to transmittance for that reason.
|
|
23
|
+
|
|
24
|
+
THE FORMULA
|
|
25
|
+
Absorbance and (fractional) Transmittance are related by the
|
|
26
|
+
Beer-Lambert definition A = -log10(T), i.e. T = 10^(-A), where T runs
|
|
27
|
+
0-1. This lab's %Transmittance convention is just T x 100:
|
|
28
|
+
|
|
29
|
+
%T = 100 x 10^(-A)
|
|
30
|
+
A = -log10(%T / 100)
|
|
31
|
+
|
|
32
|
+
Both directions are monotonic and well-defined for A >= 0 (equivalently
|
|
33
|
+
0 < %T <= 100); A < 0 (%T > 100) can occur in noisy baseline data and is
|
|
34
|
+
passed through the same formula rather than clipped, so a slightly
|
|
35
|
+
negative-absorbance noise point becomes a slightly-over-100 %T point
|
|
36
|
+
instead of silently disappearing.
|
|
37
|
+
|
|
38
|
+
INPUT / OUTPUT FORMAT
|
|
39
|
+
Same "plain" CSV convention used everywhere else in this pipeline
|
|
40
|
+
(spa_tool.py's write_plain_csv(), jdx_tool.py's decoded output): a
|
|
41
|
+
one-line header "wavenumber,intensity" followed by comma-delimited
|
|
42
|
+
rows, decimal point (not comma), ascending or descending wavenumber
|
|
43
|
+
order preserved as given -- this script does not resort or resample,
|
|
44
|
+
it only rewrites the intensity column in place.
|
|
45
|
+
|
|
46
|
+
USAGE
|
|
47
|
+
python3 absorbance_to_transmittance.py IN.csv --out OUT.csv
|
|
48
|
+
python3 absorbance_to_transmittance.py IN.csv --out OUT.csv --to absorbance
|
|
49
|
+
|
|
50
|
+
IN.csv and OUT.csv may be the same path (the file is fully read before
|
|
51
|
+
anything is written).
|
|
52
|
+
|
|
53
|
+
EXAMPLE (this report's actual use, 2026-09-18)
|
|
54
|
+
literature/webbook/plain/PROPIOPHENONE.csv was decoded from the NIST
|
|
55
|
+
Chemistry WebBook's native Absorbance .jdx (see
|
|
56
|
+
literature/webbook/decode_notes.md) and left as Absorbance in an
|
|
57
|
+
earlier pass of this report so as not to silently misrepresent the
|
|
58
|
+
source. Once the report started stacking it directly against
|
|
59
|
+
Transmittance curves in \\irspectrumcompare figures, the honest fix was
|
|
60
|
+
to convert it, not just label it:
|
|
61
|
+
|
|
62
|
+
python3 nulabreport/tools/absorbance_to_transmittance.py \\
|
|
63
|
+
literature/webbook/plain/PROPIOPHENONE.csv \\
|
|
64
|
+
--out literature/webbook/plain/PROPIOPHENONE.csv
|
|
65
|
+
|
|
66
|
+
The original Absorbance values are not lost: they still live untouched
|
|
67
|
+
in the raw source, literature/webbook/csv/PROPIOPHENONE.csv (semicolon-
|
|
68
|
+
delimited, decimal-comma, as downloaded), which this script never
|
|
69
|
+
reads or writes -- only the derived "plain" CSV is rewritten.
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
import argparse
|
|
73
|
+
import csv
|
|
74
|
+
import math
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def convert_series(intensities, to="transmittance"):
|
|
78
|
+
"""Convert a list of y-values between Absorbance and %Transmittance.
|
|
79
|
+
|
|
80
|
+
to="transmittance": treats input as Absorbance, returns %Transmittance
|
|
81
|
+
via %T = 100 * 10**(-A).
|
|
82
|
+
to="absorbance": treats input as %Transmittance, returns Absorbance
|
|
83
|
+
via A = -log10(%T / 100).
|
|
84
|
+
"""
|
|
85
|
+
if to == "transmittance":
|
|
86
|
+
return [100.0 * (10.0 ** (-a)) for a in intensities]
|
|
87
|
+
elif to == "absorbance":
|
|
88
|
+
out = []
|
|
89
|
+
for pct_t in intensities:
|
|
90
|
+
if pct_t <= 0:
|
|
91
|
+
raise ValueError(
|
|
92
|
+
f"%T value {pct_t!r} is <= 0; cannot take log10 for "
|
|
93
|
+
"Absorbance conversion"
|
|
94
|
+
)
|
|
95
|
+
out.append(-math.log10(pct_t / 100.0))
|
|
96
|
+
return out
|
|
97
|
+
else:
|
|
98
|
+
raise ValueError(f"unknown --to target: {to!r}")
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def read_plain_csv(path):
|
|
102
|
+
with open(path, newline="") as f:
|
|
103
|
+
reader = csv.reader(f)
|
|
104
|
+
header = next(reader)
|
|
105
|
+
rows = [(row[0], float(row[1])) for row in reader if row]
|
|
106
|
+
return header, rows
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def write_plain_csv(path, header, wavenumbers, intensities, digits=4):
|
|
110
|
+
with open(path, "w", newline="") as f:
|
|
111
|
+
writer = csv.writer(f)
|
|
112
|
+
writer.writerow(header)
|
|
113
|
+
for wn, inten in zip(wavenumbers, intensities):
|
|
114
|
+
writer.writerow([wn, f"{inten:.{digits}f}"])
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def main():
|
|
118
|
+
ap = argparse.ArgumentParser(
|
|
119
|
+
description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
|
|
120
|
+
)
|
|
121
|
+
ap.add_argument("csv_in", help="input plain CSV (wavenumber,intensity)")
|
|
122
|
+
ap.add_argument("--out", required=True, help="output CSV path (may equal csv_in)")
|
|
123
|
+
ap.add_argument(
|
|
124
|
+
"--to",
|
|
125
|
+
choices=["transmittance", "absorbance"],
|
|
126
|
+
default="transmittance",
|
|
127
|
+
help="conversion direction (default: transmittance, i.e. input is "
|
|
128
|
+
"treated as Absorbance)",
|
|
129
|
+
)
|
|
130
|
+
ap.add_argument("--digits", type=int, default=4, help="decimal places on output")
|
|
131
|
+
args = ap.parse_args()
|
|
132
|
+
|
|
133
|
+
header, rows = read_plain_csv(args.csv_in)
|
|
134
|
+
wavenumbers = [wn for wn, _ in rows]
|
|
135
|
+
intensities = [inten for _, inten in rows]
|
|
136
|
+
|
|
137
|
+
converted = convert_series(intensities, to=args.to)
|
|
138
|
+
|
|
139
|
+
write_plain_csv(args.out, header, wavenumbers, converted, digits=args.digits)
|
|
140
|
+
|
|
141
|
+
label = "%Transmittance" if args.to == "transmittance" else "Absorbance"
|
|
142
|
+
print(f"wrote {len(converted)} points to {args.out} ({label})")
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
if __name__ == "__main__":
|
|
146
|
+
main()
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""absorptivity_to_absorbance.py -- NIST QUANT-IR gas-phase .jdx -> true
|
|
3
|
+
Absorbance CSVs, for any report.
|
|
4
|
+
|
|
5
|
+
python3 absorptivity_to_absorbance.py FILE.jdx --name NAME \\
|
|
6
|
+
--out csv/NAME.csv --plain-out plain/NAME.csv (--peak-a A | --cl CL)
|
|
7
|
+
|
|
8
|
+
Self-contained, like this folder's other tools: what a future session needs
|
|
9
|
+
is in this docstring.
|
|
10
|
+
|
|
11
|
+
===============================================================================
|
|
12
|
+
1. WHAT THE FILE HOLDS, AND WHAT IT IS NOT
|
|
13
|
+
===============================================================================
|
|
14
|
+
NIST QUANT-IR gas-phase spectra on the WebBook (##$NIST SOURCE=QUANT-IR, e.g.
|
|
15
|
+
1634-04-4-IR.jdx, MTBE, seen 2026-10-06) carry ##YUNITS=(micromol/mol)-1m-1
|
|
16
|
+
(base 10): the decadic absorption coefficient per (umol/mol x m), i.e.
|
|
17
|
+
|
|
18
|
+
alpha = A / (c * L) c in umol/mol (mole fraction), L in m
|
|
19
|
+
|
|
20
|
+
so values are ~1e-3 and are NOT an absorbance. jdx_tool.py reads them as
|
|
21
|
+
"Absorbance" (same upward bands, nothing converted) so it can decode the
|
|
22
|
+
file, but they cannot go on an axis next to real spectra, and pgfplots stops
|
|
23
|
+
with "Dimension too large" at that magnitude.
|
|
24
|
+
|
|
25
|
+
===============================================================================
|
|
26
|
+
2. THE CONVERSION
|
|
27
|
+
===============================================================================
|
|
28
|
+
Beer-Lambert, linear in concentration x path:
|
|
29
|
+
|
|
30
|
+
A = alpha * c * L = alpha * CL, CL in umol/mol x m
|
|
31
|
+
|
|
32
|
+
The file does NOT state c or L (it says "Primary Gas Standard" and a multipass
|
|
33
|
+
cell, nothing numeric), and this script never invents them. You must give the
|
|
34
|
+
product, one of two ways:
|
|
35
|
+
|
|
36
|
+
--cl CL the real c x L, umol/mol x m, if you know it from the
|
|
37
|
+
source paper/NIST's record (a true absorbance).
|
|
38
|
+
--peak-a A scale so the strongest band reaches absorbance A (CL =
|
|
39
|
+
A / max alpha). Peak-normalised: the SHAPE and band ratios
|
|
40
|
+
are exact (A is linear in alpha), the absolute height is a
|
|
41
|
+
choice, not a measurement. Say so in the figure caption
|
|
42
|
+
("scaled to strongest band A = 1").
|
|
43
|
+
|
|
44
|
+
Because the conversion is a single multiplier, band ratios, positions and
|
|
45
|
+
widths are those of the original; only the y scale changes. The archival
|
|
46
|
+
CSV is written too, in Absorbance, through jdx_tool.py's own writers (same
|
|
47
|
+
shapes as any other jdx_tool output). Both CSVs are therefore ready for
|
|
48
|
+
spa_peaks.py --axis Absorbance and \\irspectrum {Absorbance}.
|
|
49
|
+
|
|
50
|
+
Then, as for every Absorbance source, run absorbance_to_transmittance.py on
|
|
51
|
+
the plain CSV: the house convention is %T only. With --peak-a the %T depth
|
|
52
|
+
is as arbitrary as the chosen A, so say so in the caption.
|
|
53
|
+
|
|
54
|
+
Verified 2026-10-06 on 1634-04-4-IR.jdx: output max = the --peak-a value,
|
|
55
|
+
band ratios identical to the input's, plain CSV 650+ cm-1 only.
|
|
56
|
+
"""
|
|
57
|
+
import argparse
|
|
58
|
+
import os
|
|
59
|
+
import sys
|
|
60
|
+
|
|
61
|
+
from . import jdx_tool # noqa: E402 (decoder and house CSV writers)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def main():
|
|
65
|
+
ap = argparse.ArgumentParser(
|
|
66
|
+
description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
|
|
67
|
+
)
|
|
68
|
+
ap.add_argument("jdx", help="QUANT-IR .jdx with absorptivity y-units")
|
|
69
|
+
ap.add_argument("--name", required=True, help="NAME_WITH_UNDERSCORES (CSV header)")
|
|
70
|
+
ap.add_argument("--out", required=True, help="archival CSV path")
|
|
71
|
+
ap.add_argument("--plain-out", required=True, help="plain CSV path")
|
|
72
|
+
g = ap.add_mutually_exclusive_group(required=True)
|
|
73
|
+
g.add_argument("--cl", type=float, help="c x L, umol/mol x m (true absorbance)")
|
|
74
|
+
g.add_argument("--peak-a", type=float, help="scale so max band = this absorbance")
|
|
75
|
+
args = ap.parse_args()
|
|
76
|
+
|
|
77
|
+
xs, ys, meta = jdx_tool.read_jdx(args.jdx)
|
|
78
|
+
with open(args.jdx, encoding="utf-8", errors="replace") as f:
|
|
79
|
+
if "(MICROMOL/MOL)-1M-1" not in f.read().upper():
|
|
80
|
+
sys.exit(f"{args.jdx}: y-units are not (micromol/mol)-1m-1; nothing to convert")
|
|
81
|
+
top = max(ys)
|
|
82
|
+
if top <= 0:
|
|
83
|
+
sys.exit("no positive band in the spectrum")
|
|
84
|
+
cl = args.cl if args.cl is not None else args.peak_a / top
|
|
85
|
+
ys = [y * cl for y in ys]
|
|
86
|
+
jdx_tool.write_csv(xs, ys, meta, args.out, args.name)
|
|
87
|
+
jdx_tool.write_plain_csv(xs, ys, meta, args.plain_out)
|
|
88
|
+
how = "c x L given" if args.cl is not None else f"peak-normalised, strongest band A = {args.peak_a}"
|
|
89
|
+
print(f"{args.jdx}: A = alpha x {cl:.6g} ({how}); max A {max(ys):.4f} "
|
|
90
|
+
f"-> {args.out}, {args.plain_out}")
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
if __name__ == "__main__":
|
|
94
|
+
main()
|
irspec/cli.py
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""The `irspec` command: one entry point over the tools.
|
|
2
|
+
|
|
3
|
+
irspec session DIR a folder of spectra -> CSVs, peaks, figure PDF
|
|
4
|
+
irspec export PDF ... PNG/TIFF/SVG pictures from a figure PDF
|
|
5
|
+
irspec plot DIR ... the figures drawn by matplotlib or R, no TeX needed
|
|
6
|
+
irspec spa ... OMNIC .SPA -> CSVs, peaks, legacy plots (spa_tool)
|
|
7
|
+
irspec jdx ... JCAMP-DX -> CSVs (jdx_tool)
|
|
8
|
+
irspec peaks ... peak-pick a .SPA, .jdx or CSV (spa_peaks)
|
|
9
|
+
irspec digitize ... a spectrum published as a picture -> CSVs (ir_digitize)
|
|
10
|
+
irspec a2t ... Absorbance <-> %Transmittance (absorbance_to_transmittance)
|
|
11
|
+
irspec absorptivity ... QUANT-IR absorptivity -> Absorbance (absorptivity_to_absorbance)
|
|
12
|
+
irspec corr ... Pearson r between spectra (ir_corr)
|
|
13
|
+
|
|
14
|
+
`session` is the command most people want; the others are its steps, for when
|
|
15
|
+
one step is all that is needed (`irspec jdx convert X.jdx`). Each takes its
|
|
16
|
+
own --help.
|
|
17
|
+
"""
|
|
18
|
+
import importlib
|
|
19
|
+
import sys
|
|
20
|
+
|
|
21
|
+
from . import __version__
|
|
22
|
+
|
|
23
|
+
COMMANDS = {
|
|
24
|
+
"session": "session",
|
|
25
|
+
"export": "export",
|
|
26
|
+
"plot": "plot",
|
|
27
|
+
"spa": "spa_tool",
|
|
28
|
+
"jdx": "jdx_tool",
|
|
29
|
+
"peaks": "spa_peaks",
|
|
30
|
+
"digitize": "ir_digitize",
|
|
31
|
+
"a2t": "absorbance_to_transmittance",
|
|
32
|
+
"absorptivity": "absorptivity_to_absorbance",
|
|
33
|
+
"corr": "ir_corr",
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def main(argv=None):
|
|
38
|
+
argv = list(sys.argv[1:] if argv is None else argv)
|
|
39
|
+
if not argv or argv[0] in ("-h", "--help", "help"):
|
|
40
|
+
print(__doc__.strip())
|
|
41
|
+
return
|
|
42
|
+
if argv[0] in ("-V", "--version"):
|
|
43
|
+
print(f"irspec {__version__}")
|
|
44
|
+
return
|
|
45
|
+
cmd = argv[0]
|
|
46
|
+
if cmd not in COMMANDS:
|
|
47
|
+
sys.exit(f"irspec: unknown command {cmd!r}; choose from: {', '.join(COMMANDS)}")
|
|
48
|
+
mod = importlib.import_module(f"irspec.{COMMANDS[cmd]}")
|
|
49
|
+
sys.argv = [f"irspec {cmd}", *argv[1:]]
|
|
50
|
+
mod.main()
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
if __name__ == "__main__":
|
|
54
|
+
main()
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
Copyright 2001-2021 The STIX Fonts Project Authors (https://github.com/stipub/stixfonts), with Reserved Font Name "TM Math". STIX Fonts™ is a trademark of The Institute of Electrical and Electronics Engineers, Inc.
|
|
2
|
+
|
|
3
|
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
|
4
|
+
This license is copied below, and is also available with a FAQ at:
|
|
5
|
+
http://scripts.sil.org/OFL
|
|
6
|
+
|
|
7
|
+
-----------------------------------------------------------
|
|
8
|
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
|
9
|
+
-----------------------------------------------------------
|
|
10
|
+
|
|
11
|
+
PREAMBLE
|
|
12
|
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
|
13
|
+
development of collaborative font projects, to support the font creation
|
|
14
|
+
efforts of academic and linguistic communities, and to provide a free and
|
|
15
|
+
open framework in which fonts may be shared and improved in partnership
|
|
16
|
+
with others.
|
|
17
|
+
|
|
18
|
+
The OFL allows the licensed fonts to be used, studied, modified and
|
|
19
|
+
redistributed freely as long as they are not sold by themselves. The
|
|
20
|
+
fonts, including any derivative works, can be bundled, embedded,
|
|
21
|
+
redistributed and/or sold with any software provided that any reserved
|
|
22
|
+
names are not used by derivative works. The fonts and derivatives,
|
|
23
|
+
however, cannot be released under any other type of license. The
|
|
24
|
+
requirement for fonts to remain under this license does not apply
|
|
25
|
+
to any document created using the fonts or their derivatives.
|
|
26
|
+
|
|
27
|
+
DEFINITIONS
|
|
28
|
+
"Font Software" refers to the set of files released by the Copyright
|
|
29
|
+
Holder(s) under this license and clearly marked as such. This may
|
|
30
|
+
include source files, build scripts and documentation.
|
|
31
|
+
|
|
32
|
+
"Reserved Font Name" refers to any names specified as such after the
|
|
33
|
+
copyright statement(s).
|
|
34
|
+
|
|
35
|
+
"Original Version" refers to the collection of Font Software components as
|
|
36
|
+
distributed by the Copyright Holder(s).
|
|
37
|
+
|
|
38
|
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
|
39
|
+
or substituting -- in part or in whole -- any of the components of the
|
|
40
|
+
Original Version, by changing formats or by porting the Font Software to a
|
|
41
|
+
new environment.
|
|
42
|
+
|
|
43
|
+
"Author" refers to any designer, engineer, programmer, technical
|
|
44
|
+
writer or other person who contributed to the Font Software.
|
|
45
|
+
|
|
46
|
+
PERMISSION & CONDITIONS
|
|
47
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
48
|
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
|
49
|
+
redistribute, and sell modified and unmodified copies of the Font
|
|
50
|
+
Software, subject to the following conditions:
|
|
51
|
+
|
|
52
|
+
1) Neither the Font Software nor any of its individual components,
|
|
53
|
+
in Original or Modified Versions, may be sold by itself.
|
|
54
|
+
|
|
55
|
+
2) Original or Modified Versions of the Font Software may be bundled,
|
|
56
|
+
redistributed and/or sold with any software, provided that each copy
|
|
57
|
+
contains the above copyright notice and this license. These can be
|
|
58
|
+
included either as stand-alone text files, human-readable headers or
|
|
59
|
+
in the appropriate machine-readable metadata fields within text or
|
|
60
|
+
binary files as long as those fields can be easily viewed by the user.
|
|
61
|
+
|
|
62
|
+
3) No Modified Version of the Font Software may use the Reserved Font
|
|
63
|
+
Name(s) unless explicit written permission is granted by the corresponding
|
|
64
|
+
Copyright Holder. This restriction only applies to the primary font name as
|
|
65
|
+
presented to the users.
|
|
66
|
+
|
|
67
|
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
|
68
|
+
Software shall not be used to promote, endorse or advertise any
|
|
69
|
+
Modified Version, except to acknowledge the contribution(s) of the
|
|
70
|
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
|
71
|
+
permission.
|
|
72
|
+
|
|
73
|
+
5) The Font Software, modified or unmodified, in part or in whole,
|
|
74
|
+
must be distributed entirely under this license, and must not be
|
|
75
|
+
distributed under any other license. The requirement for fonts to
|
|
76
|
+
remain under this license does not apply to any document created
|
|
77
|
+
using the Font Software.
|
|
78
|
+
|
|
79
|
+
TERMINATION
|
|
80
|
+
This license becomes null and void if any of the above conditions are
|
|
81
|
+
not met.
|
|
82
|
+
|
|
83
|
+
DISCLAIMER
|
|
84
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
85
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
|
86
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
|
87
|
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
|
88
|
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
89
|
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
90
|
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
91
|
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
92
|
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
STIX Two Text (Regular, Italic) and STIX Two Math, unmodified, from the STIX Fonts
|
|
2
|
+
Project (https://github.com/stipub/stixfonts), version 2.13 (Text) and 2.12 (Math).
|
|
3
|
+
Copyright 2001-2021 The STIX Fonts Project Authors. Licensed under the SIL Open
|
|
4
|
+
Font License, Version 1.1: the full text is in OFL.txt, and the fonts' own license
|
|
5
|
+
fields say the same.
|
|
6
|
+
|
|
7
|
+
irspec uses them only when STIX Two is not installed on the machine: matplotlib and
|
|
8
|
+
R draw with them, and the plain-lualatex fallback loads them from irspec-fonts/.
|
|
9
|
+
They are not sold or distributed on their own; they travel with irspec under the
|
|
10
|
+
same license terms.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|