react-cheminfo 0.29.0 → 0.31.0
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.
- package/README.md +62 -2
- package/lib/chrome/ui/AccountButton.d.ts +76 -0
- package/lib/chrome/ui/AccountButton.d.ts.map +1 -0
- package/lib/chrome/ui/AccountButton.js +66 -0
- package/lib/chrome/ui/AccountButton.js.map +1 -0
- package/lib/chrome/ui/index.d.ts +2 -0
- package/lib/chrome/ui/index.d.ts.map +1 -1
- package/lib/chrome/ui/index.js +1 -0
- package/lib/chrome/ui/index.js.map +1 -1
- package/lib/clipboard/ui/ClickToCopy.d.ts +6 -0
- package/lib/clipboard/ui/ClickToCopy.d.ts.map +1 -1
- package/lib/clipboard/ui/ClickToCopy.js +3 -3
- package/lib/clipboard/ui/ClickToCopy.js.map +1 -1
- package/lib/download/core/downloadFigure.d.ts +7 -5
- package/lib/download/core/downloadFigure.d.ts.map +1 -1
- package/lib/download/core/downloadFigure.js +7 -6
- package/lib/download/core/downloadFigure.js.map +1 -1
- package/lib/download/core/figureLayout.d.ts +55 -0
- package/lib/download/core/figureLayout.d.ts.map +1 -0
- package/lib/download/core/figureLayout.js +89 -0
- package/lib/download/core/figureLayout.js.map +1 -0
- package/lib/download/core/figureScale.d.ts +9 -0
- package/lib/download/core/figureScale.d.ts.map +1 -1
- package/lib/download/core/figureScale.js +10 -0
- package/lib/download/core/figureScale.js.map +1 -1
- package/lib/download/core/figureSettle.d.ts +51 -0
- package/lib/download/core/figureSettle.d.ts.map +1 -0
- package/lib/download/core/figureSettle.js +81 -0
- package/lib/download/core/figureSettle.js.map +1 -0
- package/lib/download/core/figureSvg.d.ts +7 -1
- package/lib/download/core/figureSvg.d.ts.map +1 -1
- package/lib/download/core/figureSvg.js +1 -0
- package/lib/download/core/figureSvg.js.map +1 -1
- package/lib/download/core/figureSvgDocument.d.ts +7 -0
- package/lib/download/core/figureSvgDocument.d.ts.map +1 -1
- package/lib/download/core/figureSvgDocument.js +11 -2
- package/lib/download/core/figureSvgDocument.js.map +1 -1
- package/lib/download/core/index.d.ts +5 -1
- package/lib/download/core/index.d.ts.map +1 -1
- package/lib/download/core/index.js +3 -1
- package/lib/download/core/index.js.map +1 -1
- package/lib/download/ui/FigureDownload.d.ts +18 -4
- package/lib/download/ui/FigureDownload.d.ts.map +1 -1
- package/lib/download/ui/FigureDownload.js +35 -9
- package/lib/download/ui/FigureDownload.js.map +1 -1
- package/lib/download/ui/FigureDownloadPanel.d.ts +17 -7
- package/lib/download/ui/FigureDownloadPanel.d.ts.map +1 -1
- package/lib/download/ui/FigureDownloadPanel.js +30 -22
- package/lib/download/ui/FigureDownloadPanel.js.map +1 -1
- package/lib/download/ui/FigureSizeField.d.ts +27 -0
- package/lib/download/ui/FigureSizeField.d.ts.map +1 -0
- package/lib/download/ui/FigureSizeField.js +87 -0
- package/lib/download/ui/FigureSizeField.js.map +1 -0
- package/lib/download/ui/FigureSizeRows.d.ts +34 -0
- package/lib/download/ui/FigureSizeRows.d.ts.map +1 -0
- package/lib/download/ui/FigureSizeRows.js +54 -0
- package/lib/download/ui/FigureSizeRows.js.map +1 -0
- package/lib/download/ui/index.d.ts +2 -0
- package/lib/download/ui/index.d.ts.map +1 -1
- package/lib/download/ui/index.js.map +1 -1
- package/lib/download/ui/useFigureRedraw.d.ts +27 -0
- package/lib/download/ui/useFigureRedraw.d.ts.map +1 -0
- package/lib/download/ui/useFigureRedraw.js +78 -0
- package/lib/download/ui/useFigureRedraw.js.map +1 -0
- package/lib/i18n/core/chromeCatalog.d.ts +1 -1
- package/lib/i18n/core/chromeCatalog.d.ts.map +1 -1
- package/lib/locales/de.json +13 -2
- package/lib/locales/en.json +13 -2
- package/lib/locales/es.json +13 -2
- package/lib/locales/fr.json +13 -2
- package/lib/overlay/ui/OverlayValueMenu.d.ts.map +1 -1
- package/lib/overlay/ui/OverlayValueMenu.js +7 -1
- package/lib/overlay/ui/OverlayValueMenu.js.map +1 -1
- package/lib/structure/core/conformerBoltzmann.d.ts +56 -0
- package/lib/structure/core/conformerBoltzmann.d.ts.map +1 -0
- package/lib/structure/core/conformerBoltzmann.js +96 -0
- package/lib/structure/core/conformerBoltzmann.js.map +1 -0
- package/lib/structure/core/conformerEnergy.d.ts +69 -0
- package/lib/structure/core/conformerEnergy.d.ts.map +1 -0
- package/lib/structure/core/conformerEnergy.js +47 -0
- package/lib/structure/core/conformerEnergy.js.map +1 -0
- package/lib/structure/core/index.d.ts +3 -0
- package/lib/structure/core/index.d.ts.map +1 -1
- package/lib/structure/core/index.js +2 -0
- package/lib/structure/core/index.js.map +1 -1
- package/lib/structure/ui/ConformerTable.d.ts +73 -0
- package/lib/structure/ui/ConformerTable.d.ts.map +1 -0
- package/lib/structure/ui/ConformerTable.js +259 -0
- package/lib/structure/ui/ConformerTable.js.map +1 -0
- package/lib/structure/ui/conformerColumns.d.ts +30 -0
- package/lib/structure/ui/conformerColumns.d.ts.map +1 -0
- package/lib/structure/ui/conformerColumns.js +37 -0
- package/lib/structure/ui/conformerColumns.js.map +1 -0
- package/lib/ui.d.ts +4 -0
- package/lib/ui.d.ts.map +1 -1
- package/lib/ui.js +2 -0
- package/lib/ui.js.map +1 -1
- package/package.json +1 -1
- package/src/chrome/ui/AccountButton.tsx +185 -0
- package/src/chrome/ui/index.ts +2 -0
- package/src/clipboard/ui/ClickToCopy.tsx +9 -1
- package/src/download/core/downloadFigure.ts +12 -9
- package/src/download/core/figureLayout.ts +114 -0
- package/src/download/core/figureScale.ts +13 -0
- package/src/download/core/figureSettle.ts +112 -0
- package/src/download/core/figureSvg.ts +8 -1
- package/src/download/core/figureSvgDocument.ts +19 -2
- package/src/download/core/index.ts +13 -0
- package/src/download/ui/FigureDownload.tsx +88 -35
- package/src/download/ui/FigureDownloadPanel.tsx +45 -22
- package/src/download/ui/FigureSizeField.tsx +153 -0
- package/src/download/ui/FigureSizeRows.tsx +108 -0
- package/src/download/ui/index.ts +2 -0
- package/src/download/ui/useFigureRedraw.tsx +115 -0
- package/src/locales/de.json +13 -2
- package/src/locales/en.json +13 -2
- package/src/locales/es.json +13 -2
- package/src/locales/fr.json +13 -2
- package/src/overlay/ui/OverlayValueMenu.tsx +7 -1
- package/src/structure/core/conformerBoltzmann.ts +102 -0
- package/src/structure/core/conformerEnergy.ts +97 -0
- package/src/structure/core/index.ts +15 -0
- package/src/structure/ui/ConformerTable.tsx +429 -0
- package/src/structure/ui/conformerColumns.ts +55 -0
- package/src/ui.ts +12 -0
- package/styles/chrome.css +55 -0
package/src/locales/fr.json
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"language.label": "Langue",
|
|
3
3
|
"chrome.pages": "Pages",
|
|
4
|
+
"account.signIn": "Se connecter",
|
|
5
|
+
"account.signOut": "Se déconnecter",
|
|
6
|
+
"account.signedInAs": "Connecté comme {name}",
|
|
4
7
|
"ecosystem.tools": "Outils",
|
|
5
8
|
"ecosystem.menuHeading": "Nos outils, tous dans le navigateur",
|
|
6
9
|
"ecosystem.otherTools": "Nos autres outils",
|
|
@@ -180,12 +183,20 @@
|
|
|
180
183
|
"download.format": "Format",
|
|
181
184
|
"download.formatHelp": "Un PNG est une image de la figure, ce qu'acceptent une diapositive, une fenêtre de discussion ou un ticket. Un SVG est la figure elle-même : chaque trait reste net quel que soit l'agrandissement, et il reste modifiable ensuite.",
|
|
182
185
|
"download.resolution": "Résolution",
|
|
183
|
-
"download.resolutionHelp": "Combien de
|
|
186
|
+
"download.resolutionHelp": "Combien de fois la figure à l'écran mesure le fichier. Un PNG reçoit d'autant plus de pixels : deux convient pour une diapositive, trois ou quatre pour l'impression. Un SVG reste net à toute taille, et s'ouvre d'autant plus grand.",
|
|
184
187
|
"download.resolutionExample": "Une figure large de 640 pixels à l'écran est enregistrée large de 1280 pixels.",
|
|
185
188
|
"download.noFigure": "Il n'y a encore aucune figure à enregistrer sur la page.",
|
|
186
189
|
"download.hintRasterSvg": "Un SVG contenant une image de {pixels} : une scène 3D n'a pas de forme vectorielle.",
|
|
187
|
-
"download.hintSvg": "
|
|
190
|
+
"download.hintSvg": "S'ouvre à {pixels}, et reste net à toute taille.",
|
|
188
191
|
"download.hintPng": "Enregistré {pixels}.",
|
|
192
|
+
"download.size": "Taille",
|
|
193
|
+
"download.sizeHelp": "La forme à laquelle la figure est dessinée pour le fichier. Elle est remise en page, si bien que les axes et les étiquettes s'ajustent à cette forme au lieu d'y être étirés. Une colonne de revue mesure 8,5 cm, et son texte s'imprime à la taille où il se lit à l'écran.",
|
|
194
|
+
"download.sizeScreen": "Comme affichée",
|
|
195
|
+
"download.sizeColumn": "Colonne de revue",
|
|
196
|
+
"download.sizeCustom": "Personnalisée",
|
|
197
|
+
"download.customSize": "Largeur × hauteur",
|
|
198
|
+
"download.width": "Largeur",
|
|
199
|
+
"download.height": "Hauteur",
|
|
189
200
|
"pedagogy.check": "Vérifier",
|
|
190
201
|
"pedagogy.revealHint": "Révéler un indice",
|
|
191
202
|
"pedagogy.revealHintCount": "Révéler un indice ({revealed}/{total})",
|
|
@@ -108,7 +108,13 @@ export function OverlayValueMenu<TValue extends string = string>(
|
|
|
108
108
|
text={option.label}
|
|
109
109
|
htmlTitle={option.title}
|
|
110
110
|
disabled={option.disabled}
|
|
111
|
-
|
|
111
|
+
// A menu opened from inside a panel would otherwise dismiss the
|
|
112
|
+
// panel too, taking the reader's other settings away mid-choice.
|
|
113
|
+
shouldDismissPopover={false}
|
|
114
|
+
onClick={() => {
|
|
115
|
+
onChange(option.value);
|
|
116
|
+
setOpen(false);
|
|
117
|
+
}}
|
|
112
118
|
/>
|
|
113
119
|
))}
|
|
114
120
|
</Menu>
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How a set of conformers divides itself between its minima at a temperature.
|
|
3
|
+
*
|
|
4
|
+
* Each conformer in the list is one minimum of the surface, so the share of
|
|
5
|
+
* molecules sitting in it is its Boltzmann factor over the sum of them all.
|
|
6
|
+
* Mirror-image conformers are separate entries and therefore counted twice,
|
|
7
|
+
* which is right: they are two distinct microstates, and that is what makes
|
|
8
|
+
* butane two-thirds gauche at room temperature rather than one-half.
|
|
9
|
+
*
|
|
10
|
+
* What this is not: a free energy. The weights come from a single energy per
|
|
11
|
+
* conformer, with no vibrational entropy, no zero-point energy and no solvent,
|
|
12
|
+
* so a share is the shape of the answer rather than the answer. It is also only
|
|
13
|
+
* as good as the energies handed to it — see {@link boltzmannConfidence}, which
|
|
14
|
+
* is what a table showing these shares says out loud.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/** Room temperature, in kelvin, and what a share is quoted at unless asked otherwise. */
|
|
18
|
+
export const ROOM_TEMPERATURE = 300;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The gas constant in kcal/(mol·K), matching MMFF94's own energy unit.
|
|
22
|
+
*
|
|
23
|
+
* At {@link ROOM_TEMPERATURE} this makes RT 0.596 kcal/mol, so a conformer one
|
|
24
|
+
* kcal/mol up is populated about a fifth as much as the lowest.
|
|
25
|
+
*/
|
|
26
|
+
export const GAS_CONSTANT = 0.001_987_204_259;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The share of molecules in each conformer at thermal equilibrium.
|
|
30
|
+
*
|
|
31
|
+
* The energies are taken relative to whichever is lowest, so they may be
|
|
32
|
+
* absolute or already relative. A conformer whose energy is unknown takes no
|
|
33
|
+
* share and is left out of the sum: it cannot be placed on the surface, and
|
|
34
|
+
* spreading the remainder over the others is a smaller lie than inventing a
|
|
35
|
+
* weight for it.
|
|
36
|
+
* @param energies - One energy per conformer in kcal/mol, `null` where unknown.
|
|
37
|
+
* @param temperature - Temperature in kelvin.
|
|
38
|
+
* @default ROOM_TEMPERATURE
|
|
39
|
+
* @returns One share per conformer, from 0 to 1 and summing to 1 over the ones
|
|
40
|
+
* that have an energy; `null` wherever the energy was `null`.
|
|
41
|
+
*/
|
|
42
|
+
export function boltzmannShares(
|
|
43
|
+
energies: ReadonlyArray<number | null>,
|
|
44
|
+
temperature: number = ROOM_TEMPERATURE,
|
|
45
|
+
): Array<number | null> {
|
|
46
|
+
const shares: Array<number | null> = new Array(energies.length).fill(null);
|
|
47
|
+
if (energies.length === 0) return shares;
|
|
48
|
+
|
|
49
|
+
let lowest = Number.POSITIVE_INFINITY;
|
|
50
|
+
for (const energy of energies) {
|
|
51
|
+
if (energy !== null && Number.isFinite(energy) && energy < lowest) {
|
|
52
|
+
lowest = energy;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (lowest === Number.POSITIVE_INFINITY) return shares;
|
|
56
|
+
|
|
57
|
+
// Measured from the lowest, so every exponent is at most zero and the sum
|
|
58
|
+
// cannot overflow however far apart the energies are.
|
|
59
|
+
const rt = GAS_CONSTANT * temperature;
|
|
60
|
+
if (!(rt > 0)) return shares;
|
|
61
|
+
|
|
62
|
+
const factors: Array<number | null> = new Array(energies.length).fill(null);
|
|
63
|
+
let total = 0;
|
|
64
|
+
for (let index = 0; index < energies.length; index++) {
|
|
65
|
+
const energy = energies[index] ?? null;
|
|
66
|
+
if (energy === null || !Number.isFinite(energy)) continue;
|
|
67
|
+
const factor = Math.exp(-(energy - lowest) / rt);
|
|
68
|
+
factors[index] = factor;
|
|
69
|
+
total += factor;
|
|
70
|
+
}
|
|
71
|
+
if (total === 0) return shares;
|
|
72
|
+
|
|
73
|
+
for (let index = 0; index < factors.length; index++) {
|
|
74
|
+
const factor = factors[index] ?? null;
|
|
75
|
+
if (factor !== null) shares[index] = factor / total;
|
|
76
|
+
}
|
|
77
|
+
return shares;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* The factor a share is uncertain by, given how well the energies behind it are
|
|
82
|
+
* known.
|
|
83
|
+
*
|
|
84
|
+
* A population is exponential in the energy gap, so an error in a relative
|
|
85
|
+
* energy is an error in a share by `exp(error / RT)` — and RT is 0.596 kcal/mol
|
|
86
|
+
* at {@link ROOM_TEMPERATURE}. A force field that ranks conformers to within
|
|
87
|
+
* about 1.5 kcal/mol therefore places a population to within a factor of
|
|
88
|
+
* roughly twelve, which is why a share read off one is a shape and not a
|
|
89
|
+
* number.
|
|
90
|
+
* @param energyError - The typical error of a relative energy, kcal/mol.
|
|
91
|
+
* @param temperature - Temperature in kelvin.
|
|
92
|
+
* @default ROOM_TEMPERATURE
|
|
93
|
+
* @returns The multiplicative factor, at least 1.
|
|
94
|
+
*/
|
|
95
|
+
export function boltzmannConfidence(
|
|
96
|
+
energyError: number,
|
|
97
|
+
temperature: number = ROOM_TEMPERATURE,
|
|
98
|
+
): number {
|
|
99
|
+
const rt = GAS_CONSTANT * temperature;
|
|
100
|
+
if (!(rt > 0) || !Number.isFinite(energyError) || energyError <= 0) return 1;
|
|
101
|
+
return Math.exp(energyError / rt);
|
|
102
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which energy of a conformer a reader is being shown.
|
|
3
|
+
*
|
|
4
|
+
* A refined conformer carries two of everything — what the force field said and
|
|
5
|
+
* what the better method said afterwards — and a table that mixes them is a
|
|
6
|
+
* ranking of nothing. So every column reads through one of these, and they all
|
|
7
|
+
* take the same ranking.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// Type-only, so nothing here pulls the generator — or openchemlib — into
|
|
11
|
+
// `react-cheminfo/core`, which every page loads.
|
|
12
|
+
import type { ConformerRanking } from './conformers.ts';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* What a refinement has to say for an energy column to read it.
|
|
16
|
+
*
|
|
17
|
+
* The structural minimum rather than the whole `ConformerRefinement`, so a site
|
|
18
|
+
* that carries its conformers in a shape of its own — positions instead of a
|
|
19
|
+
* molfile, say — can still be read by the same helpers and drawn by the same
|
|
20
|
+
* table.
|
|
21
|
+
*/
|
|
22
|
+
export interface ConformerRowRefinement {
|
|
23
|
+
/** The rank this conformer held before the refinement reordered the set. */
|
|
24
|
+
forceFieldId: number;
|
|
25
|
+
/** Total energy at the relaxed geometry, kcal/mol. */
|
|
26
|
+
energy: number;
|
|
27
|
+
/** Energy above the most stable refined conformer, kcal/mol. */
|
|
28
|
+
relativeEnergy: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The least a conformer must carry to be ranked and drawn.
|
|
33
|
+
*
|
|
34
|
+
* `Conformer` from `react-cheminfo/conformers` satisfies it, and so does any
|
|
35
|
+
* per-site record that keeps the same three numbers.
|
|
36
|
+
*/
|
|
37
|
+
export interface ConformerRow {
|
|
38
|
+
/** 1-based rank in the set, most stable first. */
|
|
39
|
+
id: number;
|
|
40
|
+
/** Total force-field energy in kcal/mol, `null` when not computed. */
|
|
41
|
+
energy: number | null;
|
|
42
|
+
/** Energy above the most stable conformer, `null` without an energy. */
|
|
43
|
+
relativeEnergy: number | null;
|
|
44
|
+
/**
|
|
45
|
+
* What a better method said, once the set has been refined.
|
|
46
|
+
* @default null
|
|
47
|
+
*/
|
|
48
|
+
refinement?: ConformerRowRefinement | null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* The energy above the most stable conformer, in the ranking asked for.
|
|
53
|
+
* @param conformer - The conformer to read.
|
|
54
|
+
* @param ranking - Which method's energies to read.
|
|
55
|
+
* @default 'force-field'
|
|
56
|
+
* @returns kcal/mol above the lowest, or `null` when that method produced none.
|
|
57
|
+
*/
|
|
58
|
+
export function relativeEnergyOf(
|
|
59
|
+
conformer: ConformerRow,
|
|
60
|
+
ranking: ConformerRanking = 'force-field',
|
|
61
|
+
): number | null {
|
|
62
|
+
return ranking === 'refined'
|
|
63
|
+
? (conformer.refinement?.relativeEnergy ?? null)
|
|
64
|
+
: conformer.relativeEnergy;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* The total energy, in the ranking asked for, so the two columns of a row
|
|
69
|
+
* describe one method.
|
|
70
|
+
* @param conformer - The conformer to read.
|
|
71
|
+
* @param ranking - Which method's energies to read.
|
|
72
|
+
* @default 'force-field'
|
|
73
|
+
* @returns kcal/mol, or `null` when that method produced none.
|
|
74
|
+
*/
|
|
75
|
+
export function totalEnergyOf(
|
|
76
|
+
conformer: ConformerRow,
|
|
77
|
+
ranking: ConformerRanking = 'force-field',
|
|
78
|
+
): number | null {
|
|
79
|
+
return ranking === 'refined'
|
|
80
|
+
? (conformer.refinement?.energy ?? null)
|
|
81
|
+
: conformer.energy;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* The ranking a set should be read in: refined once anything has been refined,
|
|
86
|
+
* the force field's until then.
|
|
87
|
+
* @param conformers - The set to inspect.
|
|
88
|
+
* @returns `'refined'` when at least one conformer carries a refinement.
|
|
89
|
+
*/
|
|
90
|
+
export function bestRanking(
|
|
91
|
+
conformers: readonly ConformerRow[],
|
|
92
|
+
): ConformerRanking {
|
|
93
|
+
for (const conformer of conformers) {
|
|
94
|
+
if (conformer.refinement != null) return 'refined';
|
|
95
|
+
}
|
|
96
|
+
return 'force-field';
|
|
97
|
+
}
|
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
export type { AtomLabelPlacement, LabelledMolecule } from './atomLabels.ts';
|
|
2
2
|
export { applyAtomLabels, customAtomLabel } from './atomLabels.ts';
|
|
3
|
+
export {
|
|
4
|
+
GAS_CONSTANT,
|
|
5
|
+
ROOM_TEMPERATURE,
|
|
6
|
+
boltzmannConfidence,
|
|
7
|
+
boltzmannShares,
|
|
8
|
+
} from './conformerBoltzmann.ts';
|
|
9
|
+
export type {
|
|
10
|
+
ConformerRow,
|
|
11
|
+
ConformerRowRefinement,
|
|
12
|
+
} from './conformerEnergy.ts';
|
|
13
|
+
export {
|
|
14
|
+
bestRanking,
|
|
15
|
+
relativeEnergyOf,
|
|
16
|
+
totalEnergyOf,
|
|
17
|
+
} from './conformerEnergy.ts';
|
|
3
18
|
export type {
|
|
4
19
|
EditorGesture,
|
|
5
20
|
EditorGuideKey,
|