From 5b53f02b6b5e48b0fc371f4d289f891084ca27ad Mon Sep 17 00:00:00 2001 From: Brian Ben Maranville Date: Thu, 16 Jun 2022 16:42:18 -0400 Subject: [PATCH 01/66] move creation of form object outside cgi_call --- cgi-bin/nact.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cgi-bin/nact.py b/cgi-bin/nact.py index 42720ed..97f8bc0 100755 --- a/cgi-bin/nact.py +++ b/cgi-bin/nact.py @@ -252,8 +252,7 @@ def parse_date(datestring, default_timezone=default_timezone): dt = utc.localize(dt) - timedelta(0, offset) return dt -def cgi_call(): - form = cgi.FieldStorage() +def cgi_call(form): #print(form, file=sys.stderr) #print >>sys.stderr, "sample",form.getfirst('sample') #print >>sys.stderr, "mass",form.getfirst('mass') @@ -482,6 +481,7 @@ def cgi_call(): if __name__ == "__main__": try: + form = cgi.FieldStorage() response = cgi_call() except Exception: response = { From 5bfa08a58d75cc19108e768f8bd9ed0553ff83af Mon Sep 17 00:00:00 2001 From: Brian Ben Maranville Date: Thu, 16 Jun 2022 16:42:50 -0400 Subject: [PATCH 02/66] adding pyodide version of calculator --- activation/index_pyodide.html | 1313 +++++++++++++++++++++++++++++++++ activation/webworker.js | 64 ++ 2 files changed, 1377 insertions(+) create mode 100644 activation/index_pyodide.html create mode 100644 activation/webworker.js diff --git a/activation/index_pyodide.html b/activation/index_pyodide.html new file mode 100644 index 0000000..dd32465 --- /dev/null +++ b/activation/index_pyodide.html @@ -0,0 +1,1313 @@ + + + + + Neutron Activation and Scattering Calculator + + + + + + + + + + + + + + + + + + +
+

Loading...

+
+
+ +
+ +
+ +
+

Material

+ + + +
+
+
+
+ +
+

Neutron Activation

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ + For rabbit system
+ + + +
+
+
+
+
+
+
+ + + + + +
+
+
+
+
+
+
+ +
+ +
+

Absorption and Scattering

+ + + + + + + + +
+ + + +
+
+
+
+
+ + + +
+
+
+
+
+ +
+ +
+ +
+
+
+

Neutron activation and scattering calculator

+

+This calculator uses neutron cross sections to compute activation +on the sample given the mass in the sample and the time in the beam, +or to perform scattering calculations for the neutrons which are +not absorbed by the sample. +

+
    +
  1. Enter the sample formula in the material panel.
  2. +
  3. To perform activation calculations, fill in the thermal +flux, the mass, the time on and off the beam, then press the +calculate button in the neutron activation panel.
  4. +
  5. To perform scattering calculations, fill in the wavelength +of the neutron and/or xrays, the thickness and the +density (if not given in the formula), then press the +calculate button in the absorption and scattering panel.
  6. +
+
+ + +
+

Chemical formula

+

The chemical formula parser allows you to specify materials and mixtures. +Formulas are parsed with +periodictable +python package (Kienzle 2008). +

+ +
+
simple formula
+
A basic formula consists of elements and their quantities. +
CaCO3
represents the chemical CaCO3
+
+ +
multi-part formula
+
Formulas can be built from parts by separating them with "+" or space, + with a number before the part representing repeats. Using parentheses, + a formula is treated as if it were a single unit. +
CaCO3+6H20
, +
CaCO3 6H2O
and +
CaCO3(H2O)6
all represent ikaite, + CaCO3·6H2O +
+
+ +
isotopes
+
Isotopes are represented by element[nuclide index]. +Special symbols
D
and +
T
+can be used for 2H and 3H. +Isotopes can be mixed within a formula, such as +
DHO
for partially deuterated water. +Use
H[1]
in formula for labile hydrogen. +These will be substituded with H and D in proportion with the D2O +fraction when computing the contrast match point of the sample. +
O[18]
represents the 18O
+
C3H4H[1]NO@1.29n
represents alanine with one labile hydrogen. +
+ +
density
+
Mass density is needed to compute scattering factors for the material. +The density can be entered in the density field, or it can be given in +the formula by adding @value to the end. Densities for the pure elements are +already known. +
H2O@1
+indicates that water has a density of 1 g/cm3
+
+ +
isotopic density
+
If the formula uses a mixture of isotopes, you can still use the density +of the material assuming natural abundance, but add an "n" to the value +to scale it to the isotope specific density. If you already know the +isotopic density, use the value by itself and it will not be scaled. +
D2O@1n
, +
D2O@1.11
, and +
D2O@1.11i
+all give the density of D2O as 1.11 g/cm3
+
+ +
mole fractions
+
Using non-integer quantities, arbitrary concentration ratios can be + be constructed. +
78.2H2O[16] + 21.8H2O[18] @1n
+ represents water with 78.2% 16O and 21.8% 18O +
+
+ +
mass fractions
+
Formulas can be mixed by mass, with each part starting with a percentage + followed by formula followed by "//". The first part must use "%wt" to + indicate that it is a mass fraction. The final part is the base, and it + does not need a percentage since it makes up the rest of the material. +
50%wt Co // Ti
+ is more descriptive than Co0.552Ti0.448
+
33%wt Co // 33% Fe // Ti
+ builds a 1:1:1 mixture by mass of cobalt-iron-titanium
+
+ +
volume fractions
+
Volume fractions are like mass fractions, but they use "%vol" instead. + Each component of the volume fraction must specify the density. +
20%vol (10%wt NaCl@2.16 // H2O@1) // D2O@1n
+ is a 10% saline solution by weight mixed 20:80 by volume with + D2O, which is the same as +
NaCl(H2O)29.1966(D2O)122.794@1.10i
+
+
+ +
mass and volume mixtures
+
Specific amounts of materials can be mixed, with each part giving + the quantity of material followed by "//". Quantities can be masses + (kg, g, mg, ug, or ng) or they can be volumes (L, mL, uL, nL). Density + is required for materials given by volume. For scattering calculations + density is required for the materials given by mass as well. +
5g NaCl // 50mL H2O@1
+ is more descriptive than +
NaCl(H2O)32.4407
+
+
5g NaCl@2.16 // 50mL H2O@1
+ computes the density as 1.05 g/cm3. Not useful in this + case since 9%wt brine has a density of 1.0633 at ambient temperature. +
+
50 mL (45 mL H2O@1 // 5 g NaCl)@1.0707 // 20 mL D2O@1n
+ uses the appropriate density for a 10%wt brine in the mixture. +
+
+ +
layer thickness
+
Multilayer samples can specified as layer thickness and material separated + by "//". Thicknesses are in length units (cm, mm, um, nm). The + resulting material will compute activation for 1 cm2 of material. + Density is required for each layer. +
1 cm Si // 5 nm Cr // 10 nm Au
+
+
+
+ +
biomolecules
+
+ For FASTA sequences + use "code:sequence", where code is "aa" for amino acid sequences, "dna" for + DNA sequences, or "rna" for RNA sequences. Density is estimated automatically. + This calculation uses 1H for labile hydrogen, with substitution + by H in natural abundance and pure D when computing contrast match point. +
β-casein amino acid sequence
aa:RELEELNVPGEIVESLSSSEESITRINKKIEKFQSEEQQQTEDELQDKIHPFAQTQSLVYPFPGPIPNSLPQNIPPLTQTPVVVPPFLQPEVMGVSKVKEAMAPKHKEMPFPKYPVEPFTESQSLTLTDVENLHLPLPLLQSWMHQPHQPLPPTVMFPPQSVLSLSQSKVLPVPQKAVPYPQRDMPIQAFLLYQEPVLGPVRGPFPIIV
+
+
+ +
+

Thermal flux

+

Units: n/cm2/s

+

+ Provide the thermal flux equivalent for the pre-sample beam configuration + for the instrument. This is only need for computing the neutron + activation from the experiment, and is not used for computing scattering + cross sections. Within the NCNR, you can access a list of + instrument fluxes, + but this is not available from outside. +

+

+ The neutron activation calculation follows (Shleien 1998). + Activation is a function of isotope, not element. When + an element is used in a formula, the natural abundance of the individual + isotopes is used to determine the total activation. By default, the + activation calculator uses values from the IAEA + handbook (IAEA 1987), and the + scattering calculator uses the NIST atomic weights and isotope composition + database (Bölke 2005). +

+ +

Calculation parameters are controlled by URL:

+
+
isotope abundance
+
+ The NIST database can be selected for isotope abundance using: + index.html?abundance=NIST +
+ +
activation cutoff
+
+ The cutoff values for displaying activation data are set to 0.0005 μCi + by default. The full activation levels + can be displayed using: index.html?cutoff=0 +
+ +
decay cutoff
+
The activation calculator determines the amount of time for the activation to decay to + the cutoff level, or to 0.0005 μCi if cutoff is 0. This can be set to a value + such as 0.1 μCi using: index.html?decay=0.1 +
+
+ +

Notes on calculation:

+
  • + For some numerical combinations with very large half-lives the numerical + precision is inadequate and you get negative results. This can be + corrected by reformulation or approximations but has not been done. + Remember, the X in EXP(X) is limited to |X|<709 +
  • + Simplifications have been made as indicated in the comments column in + data table +
  • + Typically, for a decay chain where the daughter is also produced (isomers) + the s of the parent has been added to that of the daughter when the + daughter t1/2 is much longer (true for most cases) and the parent + t1/2 is relatively short, e.g. less than 1 day, so that all the daughter + will be made relatively promptly. +
  • + In cases where the above condition is not met an * is put next to the + nuclide name to warn that the daughter production has not been accounted + for. In most cases the daughter is in a simple decay equilibrium. +
  • + Where the decay product is a new nuclide a line has been added to the + database to account for this. This production mode is indicated in + the reaction column by 'b'. Where both m and g state contribute to daughter + production it is simplified to a single parent, that with the greater + cross-section or that with the longer half-life together with the sum + of the cross-sections. +
  • + In a few cases where the parent nuclide t1/2 is very short all production + is assigned to the daughter and no entry is made for the parent, as + noted in the comments column. +
  • + No correction for neutron burn up has been made. +
  • + Most cross-section data is from IAEA 273. +
  • + Fast neutron data from NBSIR 85-3151, Compendium of Benchmark Neutron Fields + is for reaction above the Cd cutooff, .4eV. Noted in comment column. +
  • + Fast neutron reaction data from IAEA 273 has been weighted by a unit fluence + fast maxwellian spectrum as described in NBSIR 85-3151, but no further + weighting for a 1/v or thermal component has been made. Only selected + reactions have been included. +
  • + Reaction = b indicates production via decay from an activation produced parent. +
  • + Notation on reaction product name: +
    m, m1, m2
    + indicate metastable states. Decay may be the ground state or another nuclide. +
    +
    + indicates radioactive daughter production already included in daughter listing + several parent t1/2's required to acheive calculated daughter activity. + All activations are assigned at end of irradiation. + In most cases the added activity to the daughter is small. +
    *
    + indicates radioactive daughter production NOT calculated, approx + secular equilibrium. +
    s
    + indicates radioactive daughter of this nuclide in secular equilibrium + after several daughter t1/2's. +
    t
    + indicates transient equil via beta decay. Accumulation of that nuclide + during irradiation is separately calculated. +
    +
+
+ +
+

Cadmium ratio

+

Units: none

+

+ Samples in the rabbit tubes can be shielded with cadmium to reduce the thermal + flux while leaving the epithermal flux mostly unchanged. The cadmium ratio + determines the degree of reduction in the scattering cross sections, corresponding + to the reduced flux. This value is unitless. Use a value of 0 for beamline + experiments. +

+
+ +
+

Thermal/fast ratio

+

Units: none

+

+ When performing neutron activation analysis in a rabbit tube, the additional + fast neutron activations need to be determined. The thermal/fast ratio is + used to determine the fast neutron flux from the thermal flux equivalent for + the given rabbit tube. The resulting fast flux is (thermal flux)/(thermal/fast ratio). + This value is unitless. Use a value of 0 for beamline experiments. +

+
+ +
+

Material mass

+

Units: g, kg, mg or ug

+

+ The total neutron activation depends on the mass of the individual + isotopes in the sample and the total time in the beam. All activation + calculations assume a thin plate sample, with all parts of the sample + exposed to full flux during activation, and no self-shielding when + estimating the activation level outside the beam. +

+
+ +
+

Exposure

+

Units: h m s d w y

+

+ Exposure is the duration of the exposure at the given flux. Activation + will be accumulated over that time, with decay beginning the moment the + sample is activated. Time defaults to hours, but can be set to + hours, minutes, seconds, days, weeks or years by adding h, m, s, d, w, or y + to the value respectively. +

+
+ +
+

Decay

+

Units: h m s d w y OR yyyy-mm-dd hh:mm:ss

+

+ The sample begins to decay immediately, even while it is being activated. + The decay field allows you to specify how long since the sample + was removed from the beam. The default is hours, but can be set to + hours, minutes, seconds, days, weeks or years by adding h, m, s, d, w, or y + to the value respectively. + We always compute the activation level when the sample is removed from the beam, + and at 1 hour, 1 day and 15 days post activation. +

+

+ Instead of saying how long the sample activation has decayed, you can use + the time that the sample was removed from the beam. Times are given as + year-month-day hour:minute:second. + Approximate times are allowed, such as 2010-03 for March, 2010. This is + equivalent to 2010-03-31 23:59:59, which is the end of March so that the + activation estimate will be conservative. This is the most activation + consistent with the sample being on the beam sometime in March, 2010. + Times are specified in US/Eastern. Add "Z" after the time of day to + indicate universal coordinated time (UTC), or add a timezone offset such + as "+01" for +1 hours in France in winter, when daylight savings time is + not in effect. +

+

Examples

+ + + + + + + + + + + + + +
If you type:This is equivalent to:
2 m2 minutes ago
11 hour ago
2.5w2 and a half weeks ago
3 y3 years ago
2015-01-02 21:45:00January 2, 2015 at 9:45 PM US/Eastern
2010-03March 31, 2010 at 11:59:59 PM US/Eastern
2010-7-5 12:23July 5, 2010 at 12:23:59 PM US/Eastern
2015-01-02 21:45:00ZJanuary 2, 2015 at 9:45 PM UTC
2015-01-02 21:45:00-0600January 2, 2015 at 9:45 PM US/Central
2015-08-02 21:45:00-0500August 2, 2015 at 9:45 PM US/Central
+
+ +
+

Mass density

+

Units: g/cm3 or A3

+

+ Density is used to compute absorption, transmission and scattering. +

+
from formula
+
Leave the density field blank and add +
@
+ density + to the end of the formula, where density is in g/cm3. + For compounds with specific isotopes, you can use the density of the + naturally occurring compound as +
@
+ density +
n
+ and the isotope specific density will be computed. Density defaults to + 1 g/cm3, or for pure elements, the natural density given in + the periodic table is used. + +
D2O@1n
or +
D2O@1.11
+
+
g/cm3
+
Enter the density by itself, which will be interpreted as g/cm3, or + equivalently, kg/L. No units are needed. If the value is + density +
n
then it is density of the the + naturally occuring compound and the isotopic density will be computed. +
D2O has a natural density of +
1n
and an isotopic density of +
1.11
+
+
cell volume
+
Enter a number followed by A3 for Å3. Be sure that your + formula contains the correct number of atoms for the unit cell, possibly by + using n(formula), where n is 6 for hexagonal close packed, 4 for face centered + cells, 2 for body centered and base centered cells, or 1 for simple cells. +
4NaCl has a cell volume of +
179.4 A3
+
+
crystal lattice parameters
+
Enter lattice parameters "a:n b:n c:n alpha:n beta:n gamma:n" + where a, b, c are in Å and α, β, γ are in degrees. + If not specified, b and c default to a. Ratios can also be used, + so that "b/a:n" gives b=n*a, and "c/a:n" gives c=n*a. Angles + α, β, and γ default to 90°. Be sure that the + formula contains the correct number of atoms for the unit cell. +
4NaCl has a cubic lattice with +
a:5.6402
+
+
+
+ +
+

Thickness

+

Units: cm

+

+ The material thickness in cm is used to determine sample transmission, + or how much beam will be absorbed by the sample or scattered incoherently. + Leave it at 1 cm if you do not need this information. +

+
+ +
+

Source neutrons

+

Units: Ang, meV or m/s

+

+ The energy of the source neutrons will affect the absorption cross section + and hence the penetration depth and sample attenuation. Energy can be + expressed as wavelength in Å, as energy in meV, or as neutron + velocity in m/s. + Neutron cross sections are tabulated + at 1.798 Å = 25.3 meV = 2200 m/s, with an assumed 1/v dependence for + the absorption cross section (Rauch 2003, + Sears 2006). +

+ For heavier isotopes (Cd, Hf, rare earths) and/or shorter wavelengths + (below 1 Å) there are neutron resonances + in the thermal range. For rare-earth elements the energy-dependent coherent + sld is calculated following scattering length values tabulated + in Lynn and Seeger 1992. Incoherent + scattering will be understimated for these elements. +

+ There is also a wavelength dependence for single phonon interactions which + gives rise to significant inelastic scattering for lighter isotopes (H, D) + and/or longer wavelengths (above 5 Å). This factor is both + temperature and material dependent and will not be included + in the scattering calculations. In particular, penetration length and + transmitted flux are going to be significantly overestimated. +

+
+ +
+

Source X-rays

+

Units: Ang, keV or Ka

+

+ X-ray absorption and scattering are computed from the energy dependent + atomic scattering factors (Henke 1993). + Energy can be expressed as wavelength in Å, as energy in keV, or + using an element name for the Kα emission line2 for + that element (Deslattes 2003). +

+
+ +
+

References

+
    +
  1. + Bölke, et al. (2005). + Isotopic Compositions of the Elements, 2001. + J. Phys. Chem. Ref. Data, Vol. 34, No. 1, 2005 + [abundance data] +
  2. +
  3. + Deslattes, R.D.; Kessler, Jr., E.G.; Indelicato, P.; de Billy, L.; Lindroth, E. and Anton, J. (2003). + Rev. Mod. Phys. 75, 35-99. + [xray emission lines] +
  4. +
  5. + Henke, B.L.; Gullikson, E.M. and Davis, J.C. (1993). + X-ray interactions: + photoabsorption, scattering, transmission, and reflection at E=50-30000 eV, Z=1-92, + Atomic Data and Nuclear Data Tables Vol. 54 (no.2), 181-342. + [xray cross sections] +
  6. +
  7. + IAEA (1987). + Handbook on Nuclear Activation Data. + TR 273 (International Atomic Energy Agency, Vienna, Austria). + [tech report] +
  8. + +
  9. + Kienzle, P. A. (2008-2019). + Extensible periodic table (v1.5.2). + Computer Software. + https://periodictable.readthedocs.io. + [calculator source, + web service source] +
  10. +
  11. + Lynn, J.E. and Seeger, P.A. (1990). + Resonance effects in neutron scattering lengths of rare-earth nuclides. + Atomic Data and Nuclear Data Tables 44, 191-207. + doi:10.1016/0092-640X(90)90013-A + [rare earth scattering lengths] +
  12. + Rauch, H. and Waschkowski, W. (2003). + Neutron Scattering Lengths in ILL Neutron Data Booklet (second edition), + A.-J. Dianoux, G. Lander, Eds. + Old City Publishing, Philidelphia, PA. pp 1.1-1 to 1.1-17. + [booklet, + neutron cross sections] +
  13. +
  14. + Sears, V. F. (2006). "Scattering lengths for neutrons" In Prince, E. Ed. + International Tables for Crystallography Volume C: Mathematical, Physical and Chemical Tables" + Kluwer Academic Publishers, pp 444-454. + doi:10.1107/97809553602060000103 + [scattering calculations] +
  15. +
  16. + Shleien, B.; Slaback, L.A. and Birky, B.K. (1998). + Handbook of health physics and radiological health. + Williams & Wilkins, Baltimore. + [activation data] +
  17. +
+
+ +
+

History

+
+
2021-04-21
Support energy-dependent rare earth elements. +
Use complex scattering length bc when computing + σc = 4π |bc|2/100 and + σi = σs - σc. +
+
2020-10-29
Change field labels from 'time on/off beam' to 'exposure/decay duration'.
+
2020-01-22
Restore support for Internet Explorer 10 and 11.
+
2019-12-02
Fix cutoff=0 handling in URL.
+
2019-11-14
Correct units on activity table: nCi becomes uCi. +
Elemental carbon density changed to 2.2 to match CXRO, CRC and RSC. +
+
2019-11-04
Update neutron refs with links to ILL data book and Table for Crystallography.
+
2019-09-16
Improve help system: can now scroll between sections.
+
2019-09-11
Include notes on activation calculation.
+
2019-08-27
Change default cutoff to 0.5 nCi.
+
2018-01-12
Make activation table sortable.
+
2017-05-11
Improved support for printing tables. +
Support for biomolecules with labile hydrogen (FASTA format). +
Mixture by mass and volume, e.g., 5 g NaCl // 50 mL H2O@1 +
Multi-layer materials, e.g., 5 um Si // 3 nm Cr // 8 nm Au +
Compute incoherent cross section from coherent and total. +
+
2016-12-07
Use exponential notation for all activity levels.
+
2015-10-20
Allow decay time to be calculated from timestamp..
+
2014-03-20
Default to isotopic density.
+
2013-11-05
Support for X-ray scattering.
+
2013-04-17
Initial release.
+
+
+ + + +
+ +
+ +
+
+
+ +
+ + + diff --git a/activation/webworker.js b/activation/webworker.js new file mode 100644 index 0000000..09260a0 --- /dev/null +++ b/activation/webworker.js @@ -0,0 +1,64 @@ +// webworker.js + +// Setup your project to serve `py-worker.js`. You should also serve +// `pyodide.js`, and all its associated `.asm.js`, `.data`, `.json`, +// and `.wasm` files as well: +importScripts("https://cdn.jsdelivr.net/pyodide/v0.20.0/full/pyodide.js"); + +async function loadPyodideAndPackages() { + self.pyodide = await loadPyodide(); + await self.pyodide.loadPackage(["numpy", "pytz", "micropip"]); + await self.pyodide.runPythonAsync(` + import micropip + await micropip.install("periodictable") + import periodictable + print(periodictable.__version__) + `) + + // Downloading a single file + await pyodide.runPythonAsync(` + from pyodide.http import pyfetch + response = await pyfetch("../cgi-bin/nact.py") + with open("nact.py", "wb") as f: + f.write(await response.bytes()) + import nact + import json + import re + + class FakeFieldStorage(dict): + def getfirst(self, name, default=None): + rval = self.get(name, default) + return rval if rval != "" else default + def getlist(self, name, default=None): + name = re.sub("\\[\\]$", "", name) + rval = self.get(name, default) + if isinstance(rval, str) or isinstance(rval, bytes): + return [rval] + return list(rval) + `) +} +let pyodideReadyPromise = loadPyodideAndPackages(); +pyodideReadyPromise.then(() => self.postMessage({ready: true})); + +self.onmessage = async (event) => { + // make sure loading is done + await pyodideReadyPromise; + // Don't bother yet with this line, suppose our API is built in such a way: + const { request } = event.data; + const json_data = JSON.stringify(event.data.data); + // Now is the easy part, the one that is similar to working in the main thread: + try { + let python = ` + request = json.loads('${json_data}') + form = FakeFieldStorage(request) + print('rest:', form.getlist('rest[]')) + json.dumps(nact.cgi_call(form)) + `; + //console.log('python:', python); + let results = await self.pyodide.runPythonAsync(python); + let ldata = JSON.parse(results); + self.postMessage(ldata); + } catch (error) { + self.postMessage({ success: false, detail: {error: error.message }}); + } +}; \ No newline at end of file From a716abbad32fb6dbec62e47160e08dbd430b694d Mon Sep 17 00:00:00 2001 From: Brian Ben Maranville Date: Thu, 16 Jun 2022 16:48:39 -0400 Subject: [PATCH 03/66] remove debugging statement --- activation/webworker.js | 1 - 1 file changed, 1 deletion(-) diff --git a/activation/webworker.js b/activation/webworker.js index 09260a0..11e8e54 100644 --- a/activation/webworker.js +++ b/activation/webworker.js @@ -51,7 +51,6 @@ self.onmessage = async (event) => { let python = ` request = json.loads('${json_data}') form = FakeFieldStorage(request) - print('rest:', form.getlist('rest[]')) json.dumps(nact.cgi_call(form)) `; //console.log('python:', python); From 058c936d3349099d029e4fdaa41cc15b759aba16 Mon Sep 17 00:00:00 2001 From: Brian Ben Maranville Date: Thu, 16 Jun 2022 16:59:16 -0400 Subject: [PATCH 04/66] make worker_ready message more distinct --- activation/index_pyodide.html | 3 +-- activation/webworker.js | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/activation/index_pyodide.html b/activation/index_pyodide.html index dd32465..5eb921d 100644 --- a/activation/index_pyodide.html +++ b/activation/index_pyodide.html @@ -7,7 +7,6 @@ - + + + + + + + + + + + + + + +
+

Loading...

+
+
+ +
+ +
+ +
+

Material

+ + + +
+
+
+
+ +
+

Neutron Activation

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ + For rabbit system
+ + + +
+
+
+
+
+
+
+ + + + + +
+
+
+
+
+
+
+ +
+ +
+

Absorption and Scattering

+ + + + + + + + +
+ + + +
+
+
+
+
+ + + +
+
+
+
+
+ +
+ +
+ +
+
+
+

Neutron activation and scattering calculator

+

+This calculator uses neutron cross sections to compute activation +on the sample given the mass in the sample and the time in the beam, +or to perform scattering calculations for the neutrons which are +not absorbed by the sample. +

+
    +
  1. Enter the sample formula in the material panel.
  2. +
  3. To perform activation calculations, fill in the thermal +flux, the mass, the time on and off the beam, then press the +calculate button in the neutron activation panel.
  4. +
  5. To perform scattering calculations, fill in the wavelength +of the neutron and/or xrays, the thickness and the +density (if not given in the formula), then press the +calculate button in the absorption and scattering panel.
  6. +
+
+ + +
+

Chemical formula

+

The chemical formula parser allows you to specify materials and mixtures. +Formulas are parsed with +periodictable +python package (Kienzle 2008). +

+ +
+
simple formula
+
A basic formula consists of elements and their quantities. +
CaCO3
represents the chemical CaCO3
+
+ +
multi-part formula
+
Formulas can be built from parts by separating them with "+" or space, + with a number before the part representing repeats. Using parentheses, + a formula is treated as if it were a single unit. +
CaCO3+6H20
, +
CaCO3 6H2O
and +
CaCO3(H2O)6
all represent ikaite, + CaCO3·6H2O +
+
+ +
isotopes
+
Isotopes are represented by element[nuclide index]. +Special symbols
D
and +
T
+can be used for 2H and 3H. +Isotopes can be mixed within a formula, such as +
DHO
for partially deuterated water. +Use
H[1]
in formula for labile hydrogen. +These will be substituded with H and D in proportion with the D2O +fraction when computing the contrast match point of the sample. +
O[18]
represents the 18O
+
C3H4H[1]NO@1.29n
represents alanine with one labile hydrogen. +
+ +
density
+
Mass density is needed to compute scattering factors for the material. +The density can be entered in the density field, or it can be given in +the formula by adding @value to the end. Densities for the pure elements are +already known. +
H2O@1
+indicates that water has a density of 1 g/cm3
+
+ +
isotopic density
+
If the formula uses a mixture of isotopes, you can still use the density +of the material assuming natural abundance, but add an "n" to the value +to scale it to the isotope specific density. If you already know the +isotopic density, use the value by itself and it will not be scaled. +
D2O@1n
, +
D2O@1.11
, and +
D2O@1.11i
+all give the density of D2O as 1.11 g/cm3
+
+ +
mole fractions
+
Using non-integer quantities, arbitrary concentration ratios can be + be constructed. +
78.2H2O[16] + 21.8H2O[18] @1n
+ represents water with 78.2% 16O and 21.8% 18O +
+
+ +
mass fractions
+
Formulas can be mixed by mass, with each part starting with a percentage + followed by formula followed by "//". The first part must use "%wt" to + indicate that it is a mass fraction. The final part is the base, and it + does not need a percentage since it makes up the rest of the material. +
50%wt Co // Ti
+ is more descriptive than Co0.552Ti0.448
+
33%wt Co // 33% Fe // Ti
+ builds a 1:1:1 mixture by mass of cobalt-iron-titanium
+
+ +
volume fractions
+
Volume fractions are like mass fractions, but they use "%vol" instead. + Each component of the volume fraction must specify the density. +
20%vol (10%wt NaCl@2.16 // H2O@1) // D2O@1n
+ is a 10% saline solution by weight mixed 20:80 by volume with + D2O, which is the same as +
NaCl(H2O)29.1966(D2O)122.794@1.10i
+
+
+ +
mass and volume mixtures
+
Specific amounts of materials can be mixed, with each part giving + the quantity of material followed by "//". Quantities can be masses + (kg, g, mg, ug, or ng) or they can be volumes (L, mL, uL, nL). Density + is required for materials given by volume. For scattering calculations + density is required for the materials given by mass as well. +
5g NaCl // 50mL H2O@1
+ is more descriptive than +
NaCl(H2O)32.4407
+
+
5g NaCl@2.16 // 50mL H2O@1
+ computes the density as 1.05 g/cm3. Not useful in this + case since 9%wt brine has a density of 1.0633 at ambient temperature. +
+
50 mL (45 mL H2O@1 // 5 g NaCl)@1.0707 // 20 mL D2O@1n
+ uses the appropriate density for a 10%wt brine in the mixture. +
+
+ +
layer thickness
+
Multilayer samples can specified as layer thickness and material separated + by "//". Thicknesses are in length units (cm, mm, um, nm). The + resulting material will compute activation for 1 cm2 of material. + Density is required for each layer. +
1 cm Si // 5 nm Cr // 10 nm Au
+
+
+
+ +
biomolecules
+
+ For FASTA sequences + use "code:sequence", where code is "aa" for amino acid sequences, "dna" for + DNA sequences, or "rna" for RNA sequences. Density is estimated automatically. + This calculation uses 1H for labile hydrogen, with substitution + by H in natural abundance and pure D when computing contrast match point. +
β-casein amino acid sequence
aa:RELEELNVPGEIVESLSSSEESITRINKKIEKFQSEEQQQTEDELQDKIHPFAQTQSLVYPFPGPIPNSLPQNIPPLTQTPVVVPPFLQPEVMGVSKVKEAMAPKHKEMPFPKYPVEPFTESQSLTLTDVENLHLPLPLLQSWMHQPHQPLPPTVMFPPQSVLSLSQSKVLPVPQKAVPYPQRDMPIQAFLLYQEPVLGPVRGPFPIIV
+
+
+ +
+

Thermal flux

+

Units: n/cm2/s

+

+ Provide the thermal flux equivalent for the pre-sample beam configuration + for the instrument. This is only need for computing the neutron + activation from the experiment, and is not used for computing scattering + cross sections. Within the NCNR, you can access a list of + instrument fluxes, + but this is not available from outside. +

+

+ The neutron activation calculation follows (Shleien 1998). + Activation is a function of isotope, not element. When + an element is used in a formula, the natural abundance of the individual + isotopes is used to determine the total activation. By default, the + activation calculator uses values from the IAEA + handbook (IAEA 1987), and the + scattering calculator uses the NIST atomic weights and isotope composition + database (Bölke 2005). +

+ +

Calculation parameters are controlled by URL:

+
+
isotope abundance
+
+ The NIST database can be selected for isotope abundance using: + index.html?abundance=NIST +
+ +
activation cutoff
+
+ The cutoff values for displaying activation data are set to 0.0005 μCi + by default. The full activation levels + can be displayed using: index.html?cutoff=0 +
+ +
decay cutoff
+
The activation calculator determines the amount of time for the activation to decay to + the cutoff level, or to 0.0005 μCi if cutoff is 0. This can be set to a value + such as 0.1 μCi using: index.html?decay=0.1 +
+
+ +

Notes on calculation:

+
  • + For some numerical combinations with very large half-lives the numerical + precision is inadequate and you get negative results. This can be + corrected by reformulation or approximations but has not been done. + Remember, the X in EXP(X) is limited to |X|<709 +
  • + Simplifications have been made as indicated in the comments column in + data table +
  • + Typically, for a decay chain where the daughter is also produced (isomers) + the s of the parent has been added to that of the daughter when the + daughter t1/2 is much longer (true for most cases) and the parent + t1/2 is relatively short, e.g. less than 1 day, so that all the daughter + will be made relatively promptly. +
  • + In cases where the above condition is not met an * is put next to the + nuclide name to warn that the daughter production has not been accounted + for. In most cases the daughter is in a simple decay equilibrium. +
  • + Where the decay product is a new nuclide a line has been added to the + database to account for this. This production mode is indicated in + the reaction column by 'b'. Where both m and g state contribute to daughter + production it is simplified to a single parent, that with the greater + cross-section or that with the longer half-life together with the sum + of the cross-sections. +
  • + In a few cases where the parent nuclide t1/2 is very short all production + is assigned to the daughter and no entry is made for the parent, as + noted in the comments column. +
  • + No correction for neutron burn up has been made. +
  • + Most cross-section data is from IAEA 273. +
  • + Fast neutron data from NBSIR 85-3151, Compendium of Benchmark Neutron Fields + is for reaction above the Cd cutooff, .4eV. Noted in comment column. +
  • + Fast neutron reaction data from IAEA 273 has been weighted by a unit fluence + fast maxwellian spectrum as described in NBSIR 85-3151, but no further + weighting for a 1/v or thermal component has been made. Only selected + reactions have been included. +
  • + Reaction = b indicates production via decay from an activation produced parent. +
  • + Notation on reaction product name: +
    m, m1, m2
    + indicate metastable states. Decay may be the ground state or another nuclide. +
    +
    + indicates radioactive daughter production already included in daughter listing + several parent t1/2's required to acheive calculated daughter activity. + All activations are assigned at end of irradiation. + In most cases the added activity to the daughter is small. +
    *
    + indicates radioactive daughter production NOT calculated, approx + secular equilibrium. +
    s
    + indicates radioactive daughter of this nuclide in secular equilibrium + after several daughter t1/2's. +
    t
    + indicates transient equil via beta decay. Accumulation of that nuclide + during irradiation is separately calculated. +
    +
+
+ +
+

Cadmium ratio

+

Units: none

+

+ Samples in the rabbit tubes can be shielded with cadmium to reduce the thermal + flux while leaving the epithermal flux mostly unchanged. The cadmium ratio + determines the degree of reduction in the scattering cross sections, corresponding + to the reduced flux. This value is unitless. Use a value of 0 for beamline + experiments. +

+
+ +
+

Thermal/fast ratio

+

Units: none

+

+ When performing neutron activation analysis in a rabbit tube, the additional + fast neutron activations need to be determined. The thermal/fast ratio is + used to determine the fast neutron flux from the thermal flux equivalent for + the given rabbit tube. The resulting fast flux is (thermal flux)/(thermal/fast ratio). + This value is unitless. Use a value of 0 for beamline experiments. +

+
+ +
+

Material mass

+

Units: g, kg, mg or ug

+

+ The total neutron activation depends on the mass of the individual + isotopes in the sample and the total time in the beam. All activation + calculations assume a thin plate sample, with all parts of the sample + exposed to full flux during activation, and no self-shielding when + estimating the activation level outside the beam. +

+
+ +
+

Exposure

+

Units: h m s d w y

+

+ Exposure is the duration of the exposure at the given flux. Activation + will be accumulated over that time, with decay beginning the moment the + sample is activated. Time defaults to hours, but can be set to + hours, minutes, seconds, days, weeks or years by adding h, m, s, d, w, or y + to the value respectively. +

+
+ +
+

Decay

+

Units: h m s d w y OR yyyy-mm-dd hh:mm:ss

+

+ The sample begins to decay immediately, even while it is being activated. + The decay field allows you to specify how long since the sample + was removed from the beam. The default is hours, but can be set to + hours, minutes, seconds, days, weeks or years by adding h, m, s, d, w, or y + to the value respectively. + We always compute the activation level when the sample is removed from the beam, + and at 1 hour, 1 day and 15 days post activation. +

+

+ Instead of saying how long the sample activation has decayed, you can use + the time that the sample was removed from the beam. Times are given as + year-month-day hour:minute:second. + Approximate times are allowed, such as 2010-03 for March, 2010. This is + equivalent to 2010-03-31 23:59:59, which is the end of March so that the + activation estimate will be conservative. This is the most activation + consistent with the sample being on the beam sometime in March, 2010. + Times are specified in US/Eastern. Add "Z" after the time of day to + indicate universal coordinated time (UTC), or add a timezone offset such + as "+01" for +1 hours in France in winter, when daylight savings time is + not in effect. +

+

Examples

+ + + + + + + + + + + + + +
If you type:This is equivalent to:
2 m2 minutes ago
11 hour ago
2.5w2 and a half weeks ago
3 y3 years ago
2015-01-02 21:45:00January 2, 2015 at 9:45 PM US/Eastern
2010-03March 31, 2010 at 11:59:59 PM US/Eastern
2010-7-5 12:23July 5, 2010 at 12:23:59 PM US/Eastern
2015-01-02 21:45:00ZJanuary 2, 2015 at 9:45 PM UTC
2015-01-02 21:45:00-0600January 2, 2015 at 9:45 PM US/Central
2015-08-02 21:45:00-0500August 2, 2015 at 9:45 PM US/Central
+
+ +
+

Mass density

+

Units: g/cm3 or A3

+

+ Density is used to compute absorption, transmission and scattering. +

+
from formula
+
Leave the density field blank and add +
@
+ density + to the end of the formula, where density is in g/cm3. + For compounds with specific isotopes, you can use the density of the + naturally occurring compound as +
@
+ density +
n
+ and the isotope specific density will be computed. Density defaults to + 1 g/cm3, or for pure elements, the natural density given in + the periodic table is used. + +
D2O@1n
or +
D2O@1.11
+
+
g/cm3
+
Enter the density by itself, which will be interpreted as g/cm3, or + equivalently, kg/L. No units are needed. If the value is + density +
n
then it is density of the the + naturally occuring compound and the isotopic density will be computed. +
D2O has a natural density of +
1n
and an isotopic density of +
1.11
+
+
cell volume
+
Enter a number followed by A3 for Å3. Be sure that your + formula contains the correct number of atoms for the unit cell, possibly by + using n(formula), where n is 6 for hexagonal close packed, 4 for face centered + cells, 2 for body centered and base centered cells, or 1 for simple cells. +
4NaCl has a cell volume of +
179.4 A3
+
+
crystal lattice parameters
+
Enter lattice parameters "a:n b:n c:n alpha:n beta:n gamma:n" + where a, b, c are in Å and α, β, γ are in degrees. + If not specified, b and c default to a. Ratios can also be used, + so that "b/a:n" gives b=n*a, and "c/a:n" gives c=n*a. Angles + α, β, and γ default to 90°. Be sure that the + formula contains the correct number of atoms for the unit cell. +
4NaCl has a cubic lattice with +
a:5.6402
+
+
+
+ +
+

Thickness

+

Units: cm

+

+ The material thickness in cm is used to determine sample transmission, + or how much beam will be absorbed by the sample or scattered incoherently. + Leave it at 1 cm if you do not need this information. +

+
+ +
+

Source neutrons

+

Units: Ang, meV or m/s

+

+ The energy of the source neutrons will affect the absorption cross section + and hence the penetration depth and sample attenuation. Energy can be + expressed as wavelength in Å, as energy in meV, or as neutron + velocity in m/s. + Neutron cross sections are tabulated + at 1.798 Å = 25.3 meV = 2200 m/s, with an assumed 1/v dependence for + the absorption cross section (Rauch 2003, + Sears 2006). +

+ For heavier isotopes (Cd, Hf, rare earths) and/or shorter wavelengths + (below 1 Å) there are neutron resonances + in the thermal range. For rare-earth elements the energy-dependent coherent + sld is calculated following scattering length values tabulated + in Lynn and Seeger 1992. Incoherent + scattering will be understimated for these elements. +

+ There is also a wavelength dependence for single phonon interactions which + gives rise to significant inelastic scattering for lighter isotopes (H, D) + and/or longer wavelengths (above 5 Å). This factor is both + temperature and material dependent and will not be included + in the scattering calculations. In particular, penetration length and + transmitted flux are going to be significantly overestimated. +

+
+ +
+

Source X-rays

+

Units: Ang, keV or Ka

+

+ X-ray absorption and scattering are computed from the energy dependent + atomic scattering factors (Henke 1993). + Energy can be expressed as wavelength in Å, as energy in keV, or + using an element name for the Kα emission line2 for + that element (Deslattes 2003). +

+
+ +
+

References

+
    +
  1. + Bölke, et al. (2005). + Isotopic Compositions of the Elements, 2001. + J. Phys. Chem. Ref. Data, Vol. 34, No. 1, 2005 + [abundance data] +
  2. +
  3. + Deslattes, R.D.; Kessler, Jr., E.G.; Indelicato, P.; de Billy, L.; Lindroth, E. and Anton, J. (2003). + Rev. Mod. Phys. 75, 35-99. + [xray emission lines] +
  4. +
  5. + Henke, B.L.; Gullikson, E.M. and Davis, J.C. (1993). + X-ray interactions: + photoabsorption, scattering, transmission, and reflection at E=50-30000 eV, Z=1-92, + Atomic Data and Nuclear Data Tables Vol. 54 (no.2), 181-342. + [xray cross sections] +
  6. +
  7. + IAEA (1987). + Handbook on Nuclear Activation Data. + TR 273 (International Atomic Energy Agency, Vienna, Austria). + [tech report] +
  8. + +
  9. + Kienzle, P. A. (2008-2019). + Extensible periodic table (v1.5.2). + Computer Software. + https://periodictable.readthedocs.io. + [calculator source, + web service source] +
  10. +
  11. + Lynn, J.E. and Seeger, P.A. (1990). + Resonance effects in neutron scattering lengths of rare-earth nuclides. + Atomic Data and Nuclear Data Tables 44, 191-207. + doi:10.1016/0092-640X(90)90013-A + [rare earth scattering lengths] +
  12. + Rauch, H. and Waschkowski, W. (2003). + Neutron Scattering Lengths in ILL Neutron Data Booklet (second edition), + A.-J. Dianoux, G. Lander, Eds. + Old City Publishing, Philidelphia, PA. pp 1.1-1 to 1.1-17. + [booklet, + neutron cross sections] +
  13. +
  14. + Sears, V. F. (2006). "Scattering lengths for neutrons" In Prince, E. Ed. + International Tables for Crystallography Volume C: Mathematical, Physical and Chemical Tables" + Kluwer Academic Publishers, pp 444-454. + doi:10.1107/97809553602060000103 + [scattering calculations] +
  15. +
  16. + Shleien, B.; Slaback, L.A. and Birky, B.K. (1998). + Handbook of health physics and radiological health. + Williams & Wilkins, Baltimore. + [activation data] +
  17. +
+
+ +
+

History

+
+
2021-04-21
Support energy-dependent rare earth elements. +
Use complex scattering length bc when computing + σc = 4π |bc|2/100 and + σi = σs - σc. +
+
2020-10-29
Change field labels from 'time on/off beam' to 'exposure/decay duration'.
+
2020-01-22
Restore support for Internet Explorer 10 and 11.
+
2019-12-02
Fix cutoff=0 handling in URL.
+
2019-11-14
Correct units on activity table: nCi becomes uCi. +
Elemental carbon density changed to 2.2 to match CXRO, CRC and RSC. +
+
2019-11-04
Update neutron refs with links to ILL data book and Table for Crystallography.
+
2019-09-16
Improve help system: can now scroll between sections.
+
2019-09-11
Include notes on activation calculation.
+
2019-08-27
Change default cutoff to 0.5 nCi.
+
2018-01-12
Make activation table sortable.
+
2017-05-11
Improved support for printing tables. +
Support for biomolecules with labile hydrogen (FASTA format). +
Mixture by mass and volume, e.g., 5 g NaCl // 50 mL H2O@1 +
Multi-layer materials, e.g., 5 um Si // 3 nm Cr // 8 nm Au +
Compute incoherent cross section from coherent and total. +
+
2016-12-07
Use exponential notation for all activity levels.
+
2015-10-20
Allow decay time to be calculated from timestamp..
+
2014-03-20
Default to isotopic density.
+
2013-11-05
Support for X-ray scattering.
+
2013-04-17
Initial release.
+
+
+ + + +
+ +
+ +
+
+
+ +
+ + + diff --git a/activation/sw.js b/activation/sw.js new file mode 100644 index 0000000..ea8d263 --- /dev/null +++ b/activation/sw.js @@ -0,0 +1,76 @@ +// sw.js + +// Setup your project to serve `py-worker.js`. You should also serve +// `pyodide.js`, and all its associated `.asm.js`, `.data`, `.json`, +// and `.wasm` files as well: +importScripts("https://cdn.jsdelivr.net/npm/xhr-shim@0.1.3/src/index.js"); +self.XMLHttpRequest = self.XMLHttpRequestShim; +importScripts("https://cdn.jsdelivr.net/pyodide/v0.20.0/full/pyodide.js"); + + +async function loadPyodideAndPackages() { + self.pyodide = await loadPyodide(); + await self.pyodide.loadPackage(["numpy", "pytz", "micropip"]); + await self.pyodide.runPythonAsync(` + import micropip + await micropip.install("periodictable") + import periodictable + print(periodictable.__version__) + `) + + // Downloading a single file + await pyodide.runPythonAsync(` + from pyodide.http import pyfetch + response = await pyfetch("../cgi-bin/nact.py") + with open("nact.py", "wb") as f: + f.write(await response.bytes()) + import nact + import json + import re + + class FakeFieldStorage(dict): + def getfirst(self, name, default=None): + rval = self.get(name, default) + return rval if rval != "" else default + def getlist(self, name, default=None): + name = re.sub("\\[\\]$", "", name) + rval = self.get(name, default) + if isinstance(rval, str) or isinstance(rval, bytes): + return [rval] + return list(rval) + `) +} + +self.addEventListener("install", async () => { + let pyodideReadyPromise = loadPyodideAndPackages(); + await pyodideReadyPromise; + console.log("install finished from sw.js side"); +}) + +self.addEventListener("activate", function (event) { + event.waitUntil(self.clients.claim()); + console.log("clients claimed"); +}); + +self.addEventListener("fetch", (event) => { + if (event.request.url.endsWith("/nact.py")) { + event.respondWith(do_calculation(event)); + } +}); + +async function do_calculation(event) { + try { + const json_data = await event.request.text(); + let python = ` + request = json.loads('${json_data}') + form = FakeFieldStorage(request) + json.dumps(nact.cgi_call(form)) + `; + let results = await self.pyodide.runPythonAsync(python); + return new Response(results, { headers: { 'Content-Type': 'application/json' } }); + } + catch (error) { + const edata = JSON.stringify({ success: false, detail: {error: error.message }}); + return new Response(edata, {headers: {'Content-Type': 'application/json'}}); + } +} \ No newline at end of file From 57e4173fcc1f6fff7730707fa982b72a410ddeda Mon Sep 17 00:00:00 2001 From: bbm Date: Tue, 25 Oct 2022 10:14:39 -0400 Subject: [PATCH 07/66] adding message back to client(s) when service worker is ready --- activation/index_pyodide_serviceworker.html | 32 ++++++++++++--------- activation/sw.js | 7 ++++- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/activation/index_pyodide_serviceworker.html b/activation/index_pyodide_serviceworker.html index d1f8947..85bc846 100644 --- a/activation/index_pyodide_serviceworker.html +++ b/activation/index_pyodide_serviceworker.html @@ -20,20 +20,26 @@ const registerServiceWorker = async () => { if ('serviceWorker' in navigator) { try { - const registration = await navigator.serviceWorker.register( - './sw.js', - { - // scope: '/cgi-bin/' + navigator.serviceWorker.addEventListener("message", (event) => { + console.log("message: ", event.data); + if (event.data === "ready") { + worker_ready.resolve(); + } + }); + const registration = await navigator.serviceWorker.register( + './sw.js', + { + // scope: '/cgi-bin/' + } + ); + if (registration.installing) { + console.log('Service worker installing'); + } else if (registration.waiting) { + console.log('Service worker installed'); + } else if (registration.active) { + console.log('Service worker active'); + worker_ready.resolve(); } - ); - worker_ready.resolve(); - if (registration.installing) { - console.log('Service worker installing'); - } else if (registration.waiting) { - console.log('Service worker installed'); - } else if (registration.active) { - console.log('Service worker active'); - } } catch (error) { console.error(`Registration failed with ${error}`); } diff --git a/activation/sw.js b/activation/sw.js index ea8d263..924337b 100644 --- a/activation/sw.js +++ b/activation/sw.js @@ -48,7 +48,12 @@ self.addEventListener("install", async () => { }) self.addEventListener("activate", function (event) { - event.waitUntil(self.clients.claim()); + event.waitUntil((async () => { + await self.clients.claim(); + self.clients.matchAll().then(clients => { + clients.forEach(client => client.postMessage("ready")); + }) + })()); console.log("clients claimed"); }); From bd45628884ce5a80a4daf5ad047a26bf631ca74d Mon Sep 17 00:00:00 2001 From: bbm Date: Tue, 25 Oct 2022 11:16:43 -0400 Subject: [PATCH 08/66] improve loading lifecycle for python code --- activation/sw.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/activation/sw.js b/activation/sw.js index 924337b..eb51544 100644 --- a/activation/sw.js +++ b/activation/sw.js @@ -9,9 +9,9 @@ importScripts("https://cdn.jsdelivr.net/pyodide/v0.20.0/full/pyodide.js"); async function loadPyodideAndPackages() { - self.pyodide = await loadPyodide(); - await self.pyodide.loadPackage(["numpy", "pytz", "micropip"]); - await self.pyodide.runPythonAsync(` + const pyodide = await loadPyodide(); + await pyodide.loadPackage(["numpy", "pytz", "micropip"]); + await pyodide.runPythonAsync(` import micropip await micropip.install("periodictable") import periodictable @@ -38,21 +38,23 @@ async function loadPyodideAndPackages() { if isinstance(rval, str) or isinstance(rval, bytes): return [rval] return list(rval) - `) + `); + self.pyodide = pyodide; } self.addEventListener("install", async () => { - let pyodideReadyPromise = loadPyodideAndPackages(); - await pyodideReadyPromise; + self.pyodideReadyPromise = loadPyodideAndPackages(); + await self.pyodideReadyPromise; console.log("install finished from sw.js side"); }) self.addEventListener("activate", function (event) { event.waitUntil((async () => { + await self.pyodideReadyPromise; await self.clients.claim(); self.clients.matchAll().then(clients => { clients.forEach(client => client.postMessage("ready")); - }) + }); })()); console.log("clients claimed"); }); From 62251d02c4895c7833df117723af27efdd17c5f6 Mon Sep 17 00:00:00 2001 From: bbm Date: Tue, 25 Oct 2022 12:00:53 -0400 Subject: [PATCH 09/66] adding check for hard refresh - does a second soft reload to re-activate the service worker --- activation/index_pyodide_serviceworker.html | 6 ++++++ activation/sw.js | 10 ++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/activation/index_pyodide_serviceworker.html b/activation/index_pyodide_serviceworker.html index 85bc846..003a25b 100644 --- a/activation/index_pyodide_serviceworker.html +++ b/activation/index_pyodide_serviceworker.html @@ -32,10 +32,16 @@ // scope: '/cgi-bin/' } ); + if (navigator.serviceWorker.controller == null) { + // then it's a hard refresh which has disabled the service worker: + window.location.reload(); + } if (registration.installing) { console.log('Service worker installing'); } else if (registration.waiting) { console.log('Service worker installed'); + worker_ready.resolve(); + } else if (registration.active) { console.log('Service worker active'); worker_ready.resolve(); diff --git a/activation/sw.js b/activation/sw.js index eb51544..efd6a14 100644 --- a/activation/sw.js +++ b/activation/sw.js @@ -42,10 +42,12 @@ async function loadPyodideAndPackages() { self.pyodide = pyodide; } -self.addEventListener("install", async () => { +self.addEventListener("install", () => { + // self.skipWaiting(); self.pyodideReadyPromise = loadPyodideAndPackages(); - await self.pyodideReadyPromise; - console.log("install finished from sw.js side"); + self.pyodideReadyPromise.then(() => { + console.log("install finished from sw.js side"); + }); }) self.addEventListener("activate", function (event) { @@ -55,8 +57,8 @@ self.addEventListener("activate", function (event) { self.clients.matchAll().then(clients => { clients.forEach(client => client.postMessage("ready")); }); + console.log("clients claimed"); })()); - console.log("clients claimed"); }); self.addEventListener("fetch", (event) => { From 0ba99c9e8d8cdf863f137e012872091693652df7 Mon Sep 17 00:00:00 2001 From: bbm Date: Tue, 25 Oct 2022 12:41:01 -0400 Subject: [PATCH 10/66] use separate fetch command to make sure pyodide is ready --- activation/index_pyodide_serviceworker.html | 21 +++++---------------- activation/sw.js | 14 +++++++++++++- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/activation/index_pyodide_serviceworker.html b/activation/index_pyodide_serviceworker.html index 003a25b..fda74d2 100644 --- a/activation/index_pyodide_serviceworker.html +++ b/activation/index_pyodide_serviceworker.html @@ -20,18 +20,7 @@ const registerServiceWorker = async () => { if ('serviceWorker' in navigator) { try { - navigator.serviceWorker.addEventListener("message", (event) => { - console.log("message: ", event.data); - if (event.data === "ready") { - worker_ready.resolve(); - } - }); - const registration = await navigator.serviceWorker.register( - './sw.js', - { - // scope: '/cgi-bin/' - } - ); + const registration = await navigator.serviceWorker.register('./sw.js'); if (navigator.serviceWorker.controller == null) { // then it's a hard refresh which has disabled the service worker: window.location.reload(); @@ -40,11 +29,8 @@ console.log('Service worker installing'); } else if (registration.waiting) { console.log('Service worker installed'); - worker_ready.resolve(); - } else if (registration.active) { console.log('Service worker active'); - worker_ready.resolve(); } } catch (error) { console.error(`Registration failed with ${error}`); @@ -55,7 +41,10 @@ } }; - registerServiceWorker(); + registerServiceWorker().then(async () => { + const ready_result = await fetch ("ready"); + worker_ready.resolve(); + }); diff --git a/activation/sw.js b/activation/sw.js index efd6a14..eb4aa4b 100644 --- a/activation/sw.js +++ b/activation/sw.js @@ -7,6 +7,7 @@ importScripts("https://cdn.jsdelivr.net/npm/xhr-shim@0.1.3/src/index.js"); self.XMLHttpRequest = self.XMLHttpRequestShim; importScripts("https://cdn.jsdelivr.net/pyodide/v0.20.0/full/pyodide.js"); +let pyodide = null; async function loadPyodideAndPackages() { const pyodide = await loadPyodide(); @@ -43,7 +44,7 @@ async function loadPyodideAndPackages() { } self.addEventListener("install", () => { - // self.skipWaiting(); + self.skipWaiting(); self.pyodideReadyPromise = loadPyodideAndPackages(); self.pyodideReadyPromise.then(() => { console.log("install finished from sw.js side"); @@ -62,11 +63,22 @@ self.addEventListener("activate", function (event) { }); self.addEventListener("fetch", (event) => { + if (event.request.url.endsWith("/ready")) { + event.respondWith(make_ready()); + } if (event.request.url.endsWith("/nact.py")) { event.respondWith(do_calculation(event)); } }); +async function make_ready() { + if (!self?.pyodide?.runPythonAsync) { + const pyodideReadyPromise = loadPyodideAndPackages(); + await pyodideReadyPromise; + } + return new Response("true", { headers: { 'Content-Type': 'application/json' } }); +} + async function do_calculation(event) { try { const json_data = await event.request.text(); From e81baa3f80bc83fdadcbfeb7f047b1b3b0b414f8 Mon Sep 17 00:00:00 2001 From: Brian Benjamin Maranville Date: Fri, 7 Jun 2024 14:29:29 -0400 Subject: [PATCH 11/66] udpate pyodide version --- activation/webworker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activation/webworker.js b/activation/webworker.js index 5a82a11..970b092 100644 --- a/activation/webworker.js +++ b/activation/webworker.js @@ -3,7 +3,7 @@ // Setup your project to serve `py-worker.js`. You should also serve // `pyodide.js`, and all its associated `.asm.js`, `.data`, `.json`, // and `.wasm` files as well: -importScripts("https://cdn.jsdelivr.net/pyodide/v0.20.0/full/pyodide.js"); +importScripts("https://cdn.jsdelivr.net/pyodide/v0.26.0/full/pyodide.js"); // importScripts("./pyodide/pyodide.js"); async function loadPyodideAndPackages() { From 856f0d7fffbce6226ab3ae0923e80022f77b1314 Mon Sep 17 00:00:00 2001 From: bbm Date: Mon, 9 Dec 2024 14:39:23 -0500 Subject: [PATCH 12/66] updates from upstream index.html --- activation/index_pyodide.html | 152 ++++++++++++++++++++++++---------- activation/webworker.js | 2 +- 2 files changed, 107 insertions(+), 47 deletions(-) diff --git a/activation/index_pyodide.html b/activation/index_pyodide.html index 5eb921d..726a613 100644 --- a/activation/index_pyodide.html +++ b/activation/index_pyodide.html @@ -78,6 +78,8 @@ /* output markup */ .error { color: red; } p.disclaimer { color: darkred; font-size:1.2em; } + .activity_unusual { background-color:wheat; } + /* .activity_normal { background-color: lightred; } */ #id_chemical_formula { width: 30em; } @@ -293,9 +295,11 @@ var abundance_par = getURLParameter('abundance'); if (abundance_par==='null') ABUNDANCE = "IAEA"; + // CRUFT: periodictable no longer uses NIST 2001 data for abundance + else if (abundance_par==='NIST') ABUNDANCE = "IUPAC"; else ABUNDANCE = abundance_par; - if (ABUNDANCE!=="NIST" && ABUNDANCE!=="IAEA") { - show_error("

abundance="+sanitize(abundance_par)+" in URL should be NIST or IAEA; default is IAEA

"); + if (ABUNDANCE!=="IUPAC" && ABUNDANCE!=="IAEA") { + show_error("

abundance="+sanitize(abundance_par)+" in URL should be IUPAC or IAEA; default is IAEA

"); ABUNDANCE = "IAEA"; } } @@ -411,8 +415,21 @@ content += '' + data.headers[i] + ''; } content += '\n \n \n' + var some_unusual = false; for (var i in data.rows) { - content += ' '; + var row_style = ''; + if (data.rows[i][1] === 'b') { + some_unusual = true; + row_style = 'activity_unusual'; + } else if (data.rows[i][2].slice(-1) === 't') { + some_unusual = true; + row_style = 'activity_unusual'; + //} else if (data.rows[i][2].slice(-1) === 's') { + // row_style = 'activity_normal'; + } else { + row_style = 'activity_normal'; + } + content += ` `; for (var j=0; j =4) { content += ''+format_activation_value(data.rows[i][j], cutoff)+''; @@ -426,7 +443,11 @@ for (var j=0; j < act.total.length; j++) { content += ''+format_activation_value(act.total[j], cutoff)+''; } - content += '\n \n \n'; + content += '\n'; + if (some_unusual) { + content += ' b reaction activity is slightly underestimated; it does not include decay of transients after removal from beam.\n'; + } + content += ' \n\n'; return content; } function show_error(error_html) { @@ -436,6 +457,7 @@ $(content).prependTo('div[id=results]'); } function process_response(ldata) { + //console.log(ldata); if (typeof(ldata)==="string") ldata=$.parseJSON(ldata); if (!ldata.success) { var error_html = ''; @@ -467,7 +489,9 @@ content += '

Estimated activation only. All samples must be evaluated by NIST Health Physics to determine if and how the sample can be removed from the NCNR.

'; // Atoms - content += '

Sample in beam: ' + format_mass(sample.mass) + ' of ' + sanitize(sample.formula) + '\n'; + //var formula = sample.formula; + var formula = sanitize(sample.formula_latex).replace(/\$_{([^}]*)}\$/g, '$1'); + content += '

Sample in beam: ' + format_mass(sample.mass) + ' of ' + formula + '\n'; // Rabbit parameters if (act.Cd > 0 || act.fast > 0) { @@ -519,7 +543,9 @@ + xscat.xray.wavelength.toFixed(3) + " Å" + " = " + xscat.xray.energy.toFixed(3) + " keV
"; // Atoms - content += "Sample in beam: " + sanitize(sample.formula) + " at " + sample.density.toFixed(2) + " g/cm3"; + //var formula = sample.formula; + var formula = sanitize(sample.formula_latex).replace(/\$_{([^}]*)}\$/g, '$1'); + content += "Sample in beam: " + formula + " at " + sample.density.toFixed(2) + " g/cm3"; if (density_str.indexOf(':') !== -1) content += " from lattice "+sanitize(density_str); content += "

"; @@ -582,7 +608,10 @@ content += '\n'; $(content).prependTo('div[id=results]'); //add to the dom - $("table").tablesorter({sortList: [[8,1]]}); + // Start table unsorted so that b reactions follow transients as they + // do in the activation table. Note that there is no way to get back + // the original order. + $("table").tablesorter(); } // Dynamic help support. Clicking an input field jumps to the @@ -609,7 +638,6 @@ window.onload = async function () { parse_url_parameters(); - await worker_ready.promise; enable_forms(); setup_help(); }; @@ -730,9 +758,9 @@

Absorption and Scattering

@@ -744,9 +772,9 @@

Absorption and Scattering

Neutron activation and scattering calculator

This calculator uses neutron cross sections to compute activation -on the sample given the mass in the sample and the time in the beam, -or to perform scattering calculations for the neutrons which are -not absorbed by the sample. +of the sample given the mass in the sample and the time in the beam, +and to perform absorption and scattering calculations for samples on +slow neutron beamlines (energy below 325 meV, wavelength above 0.05 nm).

  1. Enter the sample formula in the material panel.
  2. @@ -894,11 +922,12 @@

    Thermal flux

    Units: n/cm2/s

    Provide the thermal flux equivalent for the pre-sample beam configuration - for the instrument. This is only need for computing the neutron - activation from the experiment, and is not used for computing scattering - cross sections. Within the NCNR, you can access a list of - instrument fluxes, - but this is not available from outside. + for the instrument. Because neutron capture cross sections are linear + above 0.5 Å for most isotopes, simply scale the flux by λ/1.798 Å, where + λ is the average wavelength at the sample weighted by spectral intensity. + For non-linear isotopes activation may be underestimated + (176Lu < 1.8 Å; 151Eu < 0.8 Å) + or overestimated (33S < 11 Å; 204Hg < 20 Å).

    The neutron activation calculation follows (Shleien 1998). @@ -907,16 +936,31 @@

    Thermal flux

    isotopes is used to determine the total activation. By default, the activation calculator uses values from the IAEA handbook (IAEA 1987), and the - scattering calculator uses the NIST atomic weights and isotope composition - database (Bölke 2005). + scattering calculator uses the IUPAC 2021 atomic weights and isotope composition + database (CIAAW 2021). +

    +

    + For very high fluences, e.g., more than 1016 n/cm2, the activation + equations give erroneous results because of the precision limitations. + If there is doubt simply do the calculation at a lower flux and + proportion the result. This will not work for the cascade reactions, + i.e., two neutron additions. +

    +

    + Reaction = b : This is the beta produced daughter of an activated parent. + This is calculated only for the cases where the daughter is long lived + relative to the parent. The calculated activity is through the end of + exposure only. Contributions from the added decay of the parent after the + end of irradiation are left for the user to determine, but are usually + negligible for irradiations that are long relative to the parent halflife.

    Calculation parameters are controlled by URL:

    isotope abundance
    - The NIST database can be selected for isotope abundance using: - index.html?abundance=NIST + Use the following to select IUPAC 2021 isotopic abundance data rather than the IAEA 1987 data: + index.html?abundance=IUPAC
    activation cutoff
    @@ -941,7 +985,7 @@

    Thermal flux

    Remember, the X in EXP(X) is limited to |X|<709
  3. Simplifications have been made as indicated in the comments column in - data table + data table
  4. Typically, for a decay chain where the daughter is also produced (isomers) the s of the parent has been added to that of the daughter when the @@ -993,7 +1037,7 @@

    Thermal flux

    indicates radioactive daughter of this nuclide in secular equilibrium after several daughter t1/2's.
    t
    - indicates transient equil via beta decay. Accumulation of that nuclide + indicates transient equilibrium via beta decay. Accumulation of that nuclide during irradiation is separately calculated.
  5. @@ -1164,10 +1208,11 @@

    Source neutrons

    For heavier isotopes (Cd, Hf, rare earths) and/or shorter wavelengths (below 1 Å) there are neutron resonances - in the thermal range. For rare-earth elements the energy-dependent coherent - sld is calculated following scattering length values tabulated - in Lynn and Seeger 1992. Incoherent - scattering will be understimated for these elements. + in the thermal range. For common rare-earth isotopes the energy-dependent + coherent and absorption cross sections tabulated in + Lynn and Seeger 1992 are used. + Incoherent scattering will be understimated for these elements. + Resonances for 113Cd and 180Ta are ignored.

    There is also a wavelength dependence for single phonon interactions which gives rise to significant inelastic scattering for lighter isotopes (H, D) @@ -1193,11 +1238,12 @@

    Source X-rays

    References

      -
    1. +
    2. + CIAAW. Isotopic compositions of the elements 2021. Available online + at www.ciaaw.org Bölke, et al. (2005). - Isotopic Compositions of the Elements, 2001. - J. Phys. Chem. Ref. Data, Vol. 34, No. 1, 2005 - [abundance data] + [atomic weights, + isotopic abundance]
    3. Deslattes, R.D.; Kessler, Jr., E.G.; Indelicato, P.; de Billy, L.; Lindroth, E. and Anton, J. (2003). @@ -1219,11 +1265,11 @@

      References

    4. - Kienzle, P. A. (2008-2019). - Extensible periodic table (v1.5.2). - Computer Software. + Kienzle, P. A. (2008). + Extensible periodic table + [Computer Software]. https://periodictable.readthedocs.io. - [calculator source, + [calculator source, web service source]
    5. @@ -1251,7 +1297,7 @@

      References

      Shleien, B.; Slaback, L.A. and Birky, B.K. (1998). Handbook of health physics and radiological health. Williams & Wilkins, Baltimore. - [activation data] + [activation data]
    @@ -1259,23 +1305,35 @@

    References

    History

    -
    2021-04-21
    Support energy-dependent rare earth elements. +
    2024-12-03 v2.0.0
    Update mass and abundance tables, and physical constant values +
    neutron cross section updates for H, He, C, O, Zn, Kr, Sn, Xe, Sm, Eu, Ir, Pb, Bi +
    X-ray cross section updates for Pt, Cr, Nb, Y, Er +
    208Pb activation scaled by 0.001 (value was reported in mbarns but added as barns) +
    +
    2024-03-22 v1.7.0
    Mixture formulas allow wt% and vol%. +
    Formulas allow unicode subscripts such as H₂O. +
    FASTA sequences (aa: rna: dna:) allowed as mixture components. +
    FASTA calculations updated. +
    Use correct halflife for Tm-171, Ho-163 and W-188 activation products. +
    Improve numerical precision of activation calculations. +
    +
    2021-04-21 v1.6.0
    Support energy-dependent rare earth elements.
    Use complex scattering length bc when computing σc = 4π |bc|2/100 and σi = σs - σc.
    -
    2020-10-29
    Change field labels from 'time on/off beam' to 'exposure/decay duration'.
    +
    2020-10-29 v1.5.3
    Change field labels from 'time on/off beam' to 'exposure/decay duration'.
    2020-01-22
    Restore support for Internet Explorer 10 and 11.
    2019-12-02
    Fix cutoff=0 handling in URL.
    -
    2019-11-14
    Correct units on activity table: nCi becomes uCi. +
    2019-11-14 v1.5.2
    Correct units on activity table: nCi becomes uCi.
    Elemental carbon density changed to 2.2 to match CXRO, CRC and RSC.
    2019-11-04
    Update neutron refs with links to ILL data book and Table for Crystallography.
    2019-09-16
    Improve help system: can now scroll between sections.
    -
    2019-09-11
    Include notes on activation calculation.
    +
    2019-09-11 v1.5.1
    Include notes on activation calculation.
    2019-08-27
    Change default cutoff to 0.5 nCi.
    2018-01-12
    Make activation table sortable.
    -
    2017-05-11
    Improved support for printing tables. +
    2017-05-11 v1.5.0
    Improved support for printing tables.
    Support for biomolecules with labile hydrogen (FASTA format).
    Mixture by mass and volume, e.g., 5 g NaCl // 50 mL H2O@1
    Multi-layer materials, e.g., 5 um Si // 3 nm Cr // 8 nm Au @@ -1283,9 +1341,9 @@

    History

    2016-12-07
    Use exponential notation for all activity levels.
    2015-10-20
    Allow decay time to be calculated from timestamp..
    -
    2014-03-20
    Default to isotopic density.
    +
    2014-03-20 v1.4.1
    Default to isotopic density.
    2013-11-05
    Support for X-ray scattering.
    -
    2013-04-17
    Initial release.
    +
    2013-04-17 v1.3.8
    Initial release.
    @@ -1306,7 +1364,9 @@ Neutron activation: NCNR Health Physics <hp@nist.gov>
    Scattering calculations: Paul Kienzle <paul.kienzle@nist.gov>

    -

    + diff --git a/activation/webworker.js b/activation/webworker.js index 970b092..e061940 100644 --- a/activation/webworker.js +++ b/activation/webworker.js @@ -46,7 +46,7 @@ self.onmessage = async (event) => { await pyodideReadyPromise; // Don't bother yet with this line, suppose our API is built in such a way: const { request } = event.data; - const json_data = JSON.stringify(event.data.data); + const json_data = JSON.stringify(request.data); // Now is the easy part, the one that is similar to working in the main thread: try { let python = ` From aa979831211ab8b546b193454e82a7604792946b Mon Sep 17 00:00:00 2001 From: bbm Date: Mon, 9 Dec 2024 14:43:23 -0500 Subject: [PATCH 13/66] revert payload extraction from event --- activation/webworker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activation/webworker.js b/activation/webworker.js index e061940..970b092 100644 --- a/activation/webworker.js +++ b/activation/webworker.js @@ -46,7 +46,7 @@ self.onmessage = async (event) => { await pyodideReadyPromise; // Don't bother yet with this line, suppose our API is built in such a way: const { request } = event.data; - const json_data = JSON.stringify(request.data); + const json_data = JSON.stringify(event.data.data); // Now is the easy part, the one that is similar to working in the main thread: try { let python = ` From 1d7835225ecd21b34b0ff29c87c7c94b7a19db05 Mon Sep 17 00:00:00 2001 From: bbm Date: Mon, 9 Dec 2024 14:48:23 -0500 Subject: [PATCH 14/66] wait for the worker to be ready --- activation/index_pyodide.html | 1 + 1 file changed, 1 insertion(+) diff --git a/activation/index_pyodide.html b/activation/index_pyodide.html index 726a613..524afdf 100644 --- a/activation/index_pyodide.html +++ b/activation/index_pyodide.html @@ -638,6 +638,7 @@ window.onload = async function () { parse_url_parameters(); + await worker_ready.promise; enable_forms(); setup_help(); }; From 3439f4055c8dbb0ecbd084f5cbeb2a1e1f79bbaa Mon Sep 17 00:00:00 2001 From: bbm Date: Thu, 12 Feb 2026 11:49:46 -0500 Subject: [PATCH 15/66] make cgi a lazy import --- cgi-bin/nact.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/cgi-bin/nact.py b/cgi-bin/nact.py index 3b71ccf..12ae923 100755 --- a/cgi-bin/nact.py +++ b/cgi-bin/nact.py @@ -8,7 +8,6 @@ from __future__ import print_function import sys -import cgi import re import json from math import exp @@ -16,11 +15,7 @@ from datetime import datetime, timedelta from calendar import monthrange -# CRUFT: python 2 doesn't have html.escape -try: - from html import escape -except ImportError: - from cgi import escape +from html import escape from pytz import timezone, utc @@ -491,6 +486,7 @@ def cgi_call(form): if __name__ == "__main__": + import cgi try: form = cgi.FieldStorage() response = cgi_call(form) From 0a007572ed0ccd3442450d2238c6de394fa233f3 Mon Sep 17 00:00:00 2001 From: bbm Date: Thu, 12 Feb 2026 11:51:05 -0500 Subject: [PATCH 16/66] update pyodide version --- activation/index_pyodide.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activation/index_pyodide.html b/activation/index_pyodide.html index 524afdf..1fe20bb 100644 --- a/activation/index_pyodide.html +++ b/activation/index_pyodide.html @@ -5,7 +5,7 @@ Neutron Activation and Scattering Calculator - + + + + + + + + + + + + + + + + + + + + +
    + +
    + +

    NIST Center for Neutron Research

    +
    + + National Institute of Standards and Technology + +
    + +
    + +
    + +
    + +
    +

    Material

    + + + +
    +
    +
    +
    + +
    +

    Neutron Activation

    + + + + + + + + + + + + + + + + + + + + + + + + +
    + + For rabbit system
    + + + +
    +
    +
    +
    +
    +
    +
    + + + + + +
    +
    +
    +
    +
    +
    +
    + +
    + +
    +

    Absorption and Scattering

    + + + + + + + + +
    + + + +
    +
    +
    +
    +
    + + + +
    +
    +
    +
    +
    + +
    + +
    + +
    +
    +
    +
    +

    Neutron activation and scattering calculator

    +

    +This calculator uses neutron cross sections to compute activation +of the sample given the mass in the sample and the time in the beam, +and to perform absorption and scattering calculations for samples on +slow neutron beamlines (energy below 325 meV, wavelength above 0.05 nm). +

    +
      +
    1. Enter the sample formula in the material panel.
    2. +
    3. To perform activation calculations, fill in the thermal +flux, the mass, the time on and off the beam, then press the +calculate button in the neutron activation panel.
    4. +
    5. To perform scattering calculations, fill in the wavelength +of the neutron and/or xrays, the thickness and the +density (if not given in the formula), then press the +calculate button in the absorption and scattering panel.
    6. +
    +
    + + +
    +

    Chemical formula

    +

    The chemical formula parser allows you to specify materials and mixtures. +Formulas are parsed with +periodictable +python package (Kienzle 2008). +

    + +
    +
    simple formula
    +
    A basic formula consists of elements and their quantities. +
    CaCO3
    represents the chemical CaCO3
    +
    + +
    multi-part formula
    +
    Formulas can be built from parts by separating them with "+" or space, + with a number before the part representing repeats. Using parentheses, + a formula is treated as if it were a single unit. +
    CaCO3+6H20
    , +
    CaCO3 6H2O
    and +
    CaCO3(H2O)6
    all represent ikaite, + CaCO3·6H2O +
    +
    + +
    isotopes
    +
    Isotopes are represented by element[nuclide index]. +Special symbols
    D
    and +
    T
    +can be used for 2H and 3H. +Isotopes can be mixed within a formula, such as +
    DHO
    for partially deuterated water. +Use
    H[1]
    in formula for labile hydrogen. +These will be substituded with H and D in proportion with the D2O +fraction when computing the contrast match point of the sample. +
    O[18]
    represents the 18O
    +
    C3H4H[1]NO@1.29n
    represents alanine with one labile hydrogen. +
    + +
    density
    +
    Mass density is needed to compute scattering factors for the material. +The density can be entered in the density field, or it can be given in +the formula by adding @value to the end. Densities for the pure elements are +already known. +
    H2O@1
    +indicates that water has a density of 1 g/cm3
    +
    + +
    isotopic density
    +
    If the formula uses a mixture of isotopes, you can still use the density +of the material assuming natural abundance, but add an "n" to the value +to scale it to the isotope specific density. If you already know the +isotopic density, use the value by itself and it will not be scaled. +
    D2O@1n
    , +
    D2O@1.11
    , and +
    D2O@1.11i
    +all give the density of D2O as 1.11 g/cm3
    +
    + +
    mole fractions
    +
    Using non-integer quantities, arbitrary concentration ratios can be + be constructed. +
    78.2H2O[16] + 21.8H2O[18] @1n
    + represents water with 78.2% 16O and 21.8% 18O +
    +
    + +
    mass fractions
    +
    Formulas can be mixed by mass, with each part starting with a percentage + followed by formula followed by "//". The first part must use "%wt" to + indicate that it is a mass fraction. The final part is the base, and it + does not need a percentage since it makes up the rest of the material. +
    50%wt Co // Ti
    + is more descriptive than Co0.552Ti0.448
    +
    33%wt Co // 33% Fe // Ti
    + builds a 1:1:1 mixture by mass of cobalt-iron-titanium
    +
    + +
    volume fractions
    +
    Volume fractions are like mass fractions, but they use "%vol" instead. + Each component of the volume fraction must specify the density. +
    20%vol (10%wt NaCl@2.16 // H2O@1) // D2O@1n
    + is a 10% saline solution by weight mixed 20:80 by volume with + D2O, which is the same as +
    NaCl(H2O)29.1966(D2O)122.794@1.10i
    +
    +
    + +
    mass and volume mixtures
    +
    Specific amounts of materials can be mixed, with each part giving + the quantity of material followed by "//". Quantities can be masses + (kg, g, mg, ug, or ng) or they can be volumes (L, mL, uL, nL). Density + is required for materials given by volume. For scattering calculations + density is required for the materials given by mass as well. +
    5g NaCl // 50mL H2O@1
    + is more descriptive than +
    NaCl(H2O)32.4407
    +
    +
    5g NaCl@2.16 // 50mL H2O@1
    + computes the density as 1.05 g/cm3. Not useful in this + case since 9%wt brine has a density of 1.0633 at ambient temperature. +
    +
    50 mL (45 mL H2O@1 // 5 g NaCl)@1.0707 // 20 mL D2O@1n
    + uses the appropriate density for a 10%wt brine in the mixture. +
    +
    + +
    layer thickness
    +
    Multilayer samples can specified as layer thickness and material separated + by "//". Thicknesses are in length units (cm, mm, um, nm). The + resulting material will compute activation for 1 cm2 of material. + Density is required for each layer. +
    1 cm Si // 5 nm Cr // 10 nm Au
    +
    +
    +
    + +
    biomolecules
    +
    + For FASTA sequences + use "code:sequence", where code is "aa" for amino acid sequences, "dna" for + DNA sequences, or "rna" for RNA sequences. Density is estimated automatically. + This calculation uses 1H for labile hydrogen, with substitution + by H in natural abundance and pure D when computing contrast match point. +
    β-casein amino acid sequence
    aa:RELEELNVPGEIVESLSSSEESITRINKKIEKFQSEEQQQTEDELQDKIHPFAQTQSLVYPFPGPIPNSLPQNIPPLTQTPVVVPPFLQPEVMGVSKVKEAMAPKHKEMPFPKYPVEPFTESQSLTLTDVENLHLPLPLLQSWMHQPHQPLPPTVMFPPQSVLSLSQSKVLPVPQKAVPYPQRDMPIQAFLLYQEPVLGPVRGPFPIIV
    +
    +
    + +
    +

    Thermal flux

    +

    Units: n/cm2/s

    +

    + Provide the thermal flux equivalent for the pre-sample beam configuration + for the instrument. Because neutron capture cross sections are linear + above 0.5 Å for most isotopes, simply scale the flux by λ/1.798 Å, where + λ is the average wavelength at the sample weighted by spectral intensity. + For non-linear isotopes activation may be underestimated + (176Lu < 1.8 Å; 151Eu < 0.8 Å) + or overestimated (33S < 11 Å; 204Hg < 20 Å). +

    +

    + The neutron activation calculation follows (Shleien 1998). + Activation is a function of isotope, not element. When + an element is used in a formula, the natural abundance of the individual + isotopes is used to determine the total activation. By default, the + activation calculator uses values from the IAEA + handbook (IAEA 1987), and the + scattering calculator uses the IUPAC 2021 atomic weights and isotope composition + database (CIAAW 2021). +

    +

    + For very high fluences, e.g., more than 1016 n/cm2, the activation + equations give erroneous results because of the precision limitations. + If there is doubt simply do the calculation at a lower flux and + proportion the result. This will not work for the cascade reactions, + i.e., two neutron additions. +

    +

    + Reaction = b : This is the beta produced daughter of an activated parent. + This is calculated only for the cases where the daughter is long lived + relative to the parent. The calculated activity is through the end of + exposure only. Contributions from the added decay of the parent after the + end of irradiation are left for the user to determine, but are usually + negligible for irradiations that are long relative to the parent halflife. +

    + +

    Calculation parameters are controlled by URL:

    +
    +
    isotope abundance
    +
    + Use the following to select IUPAC 2021 isotopic abundance data rather than the IAEA 1987 data: + index.html?abundance=IUPAC +
    + +
    activation cutoff
    +
    + The cutoff values for displaying activation data are set to 0.0005 μCi + by default. The full activation levels + can be displayed using: index.html?cutoff=0 +
    + +
    decay cutoff
    +
    The activation calculator determines the amount of time for the activation to decay to + the cutoff level, or to 0.0005 μCi if cutoff is 0. This can be set to a value + such as 0.1 μCi using: index.html?decay=0.1 +
    +
    + +

    Notes on calculation:

    +
    • + For some numerical combinations with very large half-lives the numerical + precision is inadequate and you get negative results. This can be + corrected by reformulation or approximations but has not been done. + Remember, the X in EXP(X) is limited to |X|<709 +
    • + Simplifications have been made as indicated in the comments column in + data table +
    • + Typically, for a decay chain where the daughter is also produced (isomers) + the s of the parent has been added to that of the daughter when the + daughter t1/2 is much longer (true for most cases) and the parent + t1/2 is relatively short, e.g. less than 1 day, so that all the daughter + will be made relatively promptly. +
    • + In cases where the above condition is not met an * is put next to the + nuclide name to warn that the daughter production has not been accounted + for. In most cases the daughter is in a simple decay equilibrium. +
    • + Where the decay product is a new nuclide a line has been added to the + database to account for this. This production mode is indicated in + the reaction column by 'b'. Where both m and g state contribute to daughter + production it is simplified to a single parent, that with the greater + cross-section or that with the longer half-life together with the sum + of the cross-sections. +
    • + In a few cases where the parent nuclide t1/2 is very short all production + is assigned to the daughter and no entry is made for the parent, as + noted in the comments column. +
    • + No correction for neutron burn up has been made. +
    • + Most cross-section data is from IAEA 273. +
    • + Fast neutron data from NBSIR 85-3151, Compendium of Benchmark Neutron Fields + is for reaction above the Cd cutooff, .4eV. Noted in comment column. +
    • + Fast neutron reaction data from IAEA 273 has been weighted by a unit fluence + fast maxwellian spectrum as described in NBSIR 85-3151, but no further + weighting for a 1/v or thermal component has been made. Only selected + reactions have been included. +
    • + Reaction = b indicates production via decay from an activation produced parent. +
    • + Notation on reaction product name: +
      m, m1, m2
      + indicate metastable states. Decay may be the ground state or another nuclide. +
      +
      + indicates radioactive daughter production already included in daughter listing + several parent t1/2's required to acheive calculated daughter activity. + All activations are assigned at end of irradiation. + In most cases the added activity to the daughter is small. +
      *
      + indicates radioactive daughter production NOT calculated, approx + secular equilibrium. +
      s
      + indicates radioactive daughter of this nuclide in secular equilibrium + after several daughter t1/2's. +
      t
      + indicates transient equilibrium via beta decay. Accumulation of that nuclide + during irradiation is separately calculated. +
      +
    +
    + +
    +

    Cadmium ratio

    +

    Units: none

    +

    + Samples in the rabbit tubes can be shielded with cadmium to reduce the thermal + flux while leaving the epithermal flux mostly unchanged. The cadmium ratio + determines the degree of reduction in the scattering cross sections, corresponding + to the reduced flux. This value is unitless. Use a value of 0 for beamline + experiments. +

    +
    + +
    +

    Thermal/fast ratio

    +

    Units: none

    +

    + When performing neutron activation analysis in a rabbit tube, the additional + fast neutron activations need to be determined. The thermal/fast ratio is + used to determine the fast neutron flux from the thermal flux equivalent for + the given rabbit tube. The resulting fast flux is (thermal flux)/(thermal/fast ratio). + This value is unitless. Use a value of 0 for beamline experiments. +

    +
    + +
    +

    Material mass

    +

    Units: g, kg, mg or ug

    +

    + The total neutron activation depends on the mass of the individual + isotopes in the sample and the total time in the beam. All activation + calculations assume a thin plate sample, with all parts of the sample + exposed to full flux during activation, and no self-shielding when + estimating the activation level outside the beam. +

    +
    + +
    +

    Exposure

    +

    Units: h m s d w y

    +

    + Exposure is the duration of the exposure at the given flux. Activation + will be accumulated over that time, with decay beginning the moment the + sample is activated. Time defaults to hours, but can be set to + hours, minutes, seconds, days, weeks or years by adding h, m, s, d, w, or y + to the value respectively. +

    +
    + +
    +

    Decay

    +

    Units: h m s d w y OR yyyy-mm-dd hh:mm:ss

    +

    + The sample begins to decay immediately, even while it is being activated. + The decay field allows you to specify how long since the sample + was removed from the beam. The default is hours, but can be set to + hours, minutes, seconds, days, weeks or years by adding h, m, s, d, w, or y + to the value respectively. + We always compute the activation level when the sample is removed from the beam, + and at 1 hour, 1 day and 15 days post activation. +

    +

    + Instead of saying how long the sample activation has decayed, you can use + the time that the sample was removed from the beam. Times are given as + year-month-day hour:minute:second. + Approximate times are allowed, such as 2010-03 for March, 2010. This is + equivalent to 2010-03-31 23:59:59, which is the end of March so that the + activation estimate will be conservative. This is the most activation + consistent with the sample being on the beam sometime in March, 2010. + Times are specified in US/Eastern. Add "Z" after the time of day to + indicate universal coordinated time (UTC), or add a timezone offset such + as "+01" for +1 hours in France in winter, when daylight savings time is + not in effect. +

    +

    + + + + + + + + + + + + + +
    If you type:This is equivalent to:
    2 m2 minutes ago
    11 hour ago
    2.5w2 and a half weeks ago
    3 y3 years ago
    2015-01-02 21:45:00January 2, 2015 at 9:45 PM US/Eastern
    2010-03March 31, 2010 at 11:59:59 PM US/Eastern
    2010-7-5 12:23July 5, 2010 at 12:23:59 PM US/Eastern
    2015-01-02 21:45:00ZJanuary 2, 2015 at 9:45 PM UTC
    2015-01-02 21:45:00-0600January 2, 2015 at 9:45 PM US/Central
    2015-08-02 21:45:00-0500August 2, 2015 at 9:45 PM US/Central
    +

    + +
    +

    Mass density

    +

    Units: g/cm3 or A3

    +

    + Density is used to compute absorption, transmission and scattering. +

    +
    from formula
    +
    Leave the density field blank and add +
    @
    + density + to the end of the formula, where density is in g/cm3. + For compounds with specific isotopes, you can use the density of the + naturally occurring compound as +
    @
    + density +
    n
    + and the isotope specific density will be computed. Density defaults to + 1 g/cm3, or for pure elements, the natural density given in + the periodic table is used. + +
    D2O@1n
    or +
    D2O@1.11
    +
    +
    g/cm3
    +
    Enter the density by itself, which will be interpreted as g/cm3, or + equivalently, kg/L. No units are needed. If the value is + density +
    n
    then it is density of the the + naturally occuring compound and the isotopic density will be computed. +
    D2O has a natural density of +
    1n
    and an isotopic density of +
    1.11
    +
    +
    cell volume
    +
    Enter a number followed by A3 for Å3. Be sure that your + formula contains the correct number of atoms for the unit cell, possibly by + using n(formula), where n is 6 for hexagonal close packed, 4 for face centered + cells, 2 for body centered and base centered cells, or 1 for simple cells. +
    4NaCl has a cell volume of +
    179.4 A3
    +
    +
    crystal lattice parameters
    +
    Enter lattice parameters "a:n b:n c:n alpha:n beta:n gamma:n" + where a, b, c are in Å and α, β, γ are in degrees. + If not specified, b and c default to a. Ratios can also be used, + so that "b/a:n" gives b=n*a, and "c/a:n" gives c=n*a. Angles + α, β, and γ default to 90°. Be sure that the + formula contains the correct number of atoms for the unit cell. +
    4NaCl has a cubic lattice with +
    a:5.6402
    +
    +
    +
    + +
    +

    Thickness

    +

    Units: cm

    +

    + The material thickness in cm is used to determine sample transmission, + or how much beam will be absorbed by the sample or scattered incoherently. + Leave it at 1 cm if you do not need this information. +

    +
    + +
    +

    Source neutrons

    +

    Units: Ang, meV or m/s

    +

    + The energy of the source neutrons will affect the absorption cross section + and hence the penetration depth and sample attenuation. Energy can be + expressed as wavelength in Å, as energy in meV, or as neutron + velocity in m/s. + Neutron cross sections are tabulated + at 1.798 Å = 25.3 meV = 2200 m/s, with an assumed 1/v dependence for + the absorption cross section (Rauch 2003, + Sears 2006). +

    + For heavier isotopes (Cd, Hf, rare earths) and/or shorter wavelengths + (below 1 Å) there are neutron resonances + in the thermal range. For common rare-earth isotopes the energy-dependent + coherent and absorption cross sections tabulated in + Lynn and Seeger 1992 are used. + Incoherent scattering will be understimated for these elements. + Resonances for 113Cd and 180Ta are ignored. +

    + There is also a wavelength dependence for single phonon interactions which + gives rise to significant inelastic scattering for lighter isotopes (H, D) + and/or longer wavelengths (above 5 Å). This factor is both + temperature and material dependent and will not be included + in the scattering calculations. In particular, penetration length and + transmitted flux are going to be significantly overestimated. +

    +
    + +
    +

    Source X-rays

    +

    Units: Ang, keV or Ka

    +

    + X-ray absorption and scattering are computed from the energy dependent + atomic scattering factors (Henke 1993). + Energy can be expressed as wavelength in Å, as energy in keV, or + using an element name for the Kα emission line2 for + that element (Deslattes 2003). +

    +
    + +
    +

    References

    +
      +
    1. + CIAAW. Isotopic compositions of the elements 2021. Available online + at www.ciaaw.org + Bölke, et al. (2005). + [atomic weights, + isotopic abundance] +
    2. +
    3. + Deslattes, R.D.; Kessler, Jr., E.G.; Indelicato, P.; de Billy, L.; Lindroth, E. and Anton, J. (2003). + Rev. Mod. Phys. 75, 35-99. + [xray emission lines] +
    4. +
    5. + Henke, B.L.; Gullikson, E.M. and Davis, J.C. (1993). + X-ray interactions: + photoabsorption, scattering, transmission, and reflection at E=50-30000 eV, Z=1-92, + Atomic Data and Nuclear Data Tables Vol. 54 (no.2), 181-342. + [xray cross sections] +
    6. +
    7. + IAEA (1987). + Handbook on Nuclear Activation Data. + TR 273 (International Atomic Energy Agency, Vienna, Austria). + [tech report] +
    8. + +
    9. + Kienzle, P. A. (2008). + Extensible periodic table + [Computer Software]. + https://periodictable.readthedocs.io. + [calculator source, + web service source] +
    10. +
    11. + Lynn, J.E. and Seeger, P.A. (1990). + Resonance effects in neutron scattering lengths of rare-earth nuclides. + Atomic Data and Nuclear Data Tables 44, 191-207. + doi:10.1016/0092-640X(90)90013-A + [rare earth scattering lengths] +
    12. + Rauch, H. and Waschkowski, W. (2003). + Neutron Scattering Lengths in ILL Neutron Data Booklet (second edition), + A.-J. Dianoux, G. Lander, Eds. + Old City Publishing, Philidelphia, PA. pp 1.1-1 to 1.1-17. + [booklet, + neutron cross sections] +
    13. +
    14. + Sears, V. F. (2006). "Scattering lengths for neutrons" In Prince, E. Ed. + International Tables for Crystallography Volume C: Mathematical, Physical and Chemical Tables" + Kluwer Academic Publishers, pp 444-454. + doi:10.1107/97809553602060000103 + [scattering calculations] +
    15. +
    16. + Shleien, B.; Slaback, L.A. and Birky, B.K. (1998). + Handbook of health physics and radiological health. + Williams & Wilkins, Baltimore. + [activation data] +
    17. +
    +
    + +
    +

    History

    +
    +
    2025-04-23 v2.0.0
    +
    Fix sort by half-life with units of ky, My, Gy.
    +
    2025-02-28 v2.0.0
    +
    Use standard year as 365 rather than 365.2425 days when reporting decay time. +
    +
    2024-12-03 v2.0.0
    Update mass and abundance tables, and physical constant values +
    neutron cross section updates for H, He, C, O, Zn, Kr, Sn, Xe, Sm, Eu, Ir, Pb, Bi +
    X-ray cross section updates for Pt, Cr, Nb, Y, Er +
    208Pb activation scaled by 0.001 (value was reported in mbarns but added as barns) +
    +
    2024-03-22 v1.7.0
    Mixture formulas allow wt% and vol%. +
    Formulas allow unicode subscripts such as H₂O. +
    FASTA sequences (aa: rna: dna:) allowed as mixture components. +
    FASTA calculations updated. +
    Use correct halflife for Tm-171, Ho-163 and W-188 activation products. +
    Improve numerical precision of activation calculations. +
    +
    2021-04-21 v1.6.0
    Support energy-dependent rare earth elements. +
    Use complex scattering length bc when computing + σc = 4π |bc|2/100 and + σi = σs - σc. +
    +
    2020-10-29 v1.5.3
    Change field labels from 'time on/off beam' to 'exposure/decay duration'.
    +
    2020-01-22
    Restore support for Internet Explorer 10 and 11.
    +
    2019-12-02
    Fix cutoff=0 handling in URL.
    +
    2019-11-14 v1.5.2
    Correct units on activity table: nCi becomes uCi. +
    Elemental carbon density changed to 2.2 to match CXRO, CRC and RSC. +
    +
    2019-11-04
    Update neutron refs with links to ILL data book and Table for Crystallography.
    +
    2019-09-16
    Improve help system: can now scroll between sections.
    +
    2019-09-11 v1.5.1
    Include notes on activation calculation.
    +
    2019-08-27
    Change default cutoff to 0.5 nCi.
    +
    2018-01-12
    Make activation table sortable.
    +
    2017-05-11 v1.5.0
    Improved support for printing tables. +
    Support for biomolecules with labile hydrogen (FASTA format). +
    Mixture by mass and volume, e.g., 5 g NaCl // 50 mL H2O@1 +
    Multi-layer materials, e.g., 5 um Si // 3 nm Cr // 8 nm Au +
    Compute incoherent cross section from coherent and total. +
    +
    2016-12-07
    Use exponential notation for all activity levels.
    +
    2015-10-20
    Allow decay time to be calculated from timestamp..
    +
    2014-03-20 v1.4.1
    Default to isotopic density.
    +
    2013-11-05
    Support for X-ray scattering.
    +
    2013-04-17 v1.3.8
    Initial release.
    +
    +
    + + + +
    +
    + +
    +
    + +
    Initializing calculator...
    +
    +
    + + + + +
    + + From 0c0d834b9a0d82653d2de10b184b9bc0140a230d Mon Sep 17 00:00:00 2001 From: bbm Date: Wed, 25 Feb 2026 11:44:02 -0500 Subject: [PATCH 19/66] use module webworker --- activation/index_pyodide.html | 2 +- activation/index_pyodide_optimized.html | 2 +- activation/webworker.js | 7 ++----- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/activation/index_pyodide.html b/activation/index_pyodide.html index 1fe20bb..980f5df 100644 --- a/activation/index_pyodide.html +++ b/activation/index_pyodide.html @@ -16,7 +16,7 @@ }); } } - const pyodideWorker = new Worker("./webworker.js"); + const pyodideWorker = new Worker("./webworker.js", {type: "module"}); const worker_ready = new Deferred(); pyodideWorker.onmessage = (event) => { if ('worker_ready' in event.data) { diff --git a/activation/index_pyodide_optimized.html b/activation/index_pyodide_optimized.html index ce7e0cc..cdc32d4 100644 --- a/activation/index_pyodide_optimized.html +++ b/activation/index_pyodide_optimized.html @@ -16,7 +16,7 @@ }); } } - const pyodideWorker = new Worker("./webworker.js"); + const pyodideWorker = new Worker("./webworker.js", {type: "module"}); const worker_ready = new Deferred(); pyodideWorker.onmessage = (event) => { if ('worker_ready' in event.data) { diff --git a/activation/webworker.js b/activation/webworker.js index 74caeb8..d86fef3 100644 --- a/activation/webworker.js +++ b/activation/webworker.js @@ -1,10 +1,7 @@ // webworker.js -// Setup your project to serve `py-worker.js`. You should also serve -// `pyodide.js`, and all its associated `.asm.js`, `.data`, `.json`, -// and `.wasm` files as well: -importScripts("https://cdn.jsdelivr.net/pyodide/v0.29.3/full/pyodide.js"); -// importScripts("./pyodide/pyodide.js"); +import { loadPyodide } from "https://cdn.jsdelivr.net/pyodide/v0.29.3/full/pyodide.mjs"; +// import { loadPyodide } from "./pyodide/pyodide.mjs"; async function loadPyodideAndPackages() { self.pyodide = await loadPyodide(); From d56564dba8d576b19a5028bd8aa70f97885feaf0 Mon Sep 17 00:00:00 2001 From: bbm Date: Wed, 25 Feb 2026 11:48:32 -0500 Subject: [PATCH 20/66] add workflow for deploying to gh-pages --- .github/workflows/deploy.yml | 50 ++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 .github/workflows/deploy.yml diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..9d389aa --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,50 @@ +name: Deploy static site to GitHub Pages + +on: + push: + branches: + - pyodide # Triggers the workflow on pushes to the pyodide branch + workflow_dispatch: # Allows manual triggering from the GitHub UI + +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout your repository + uses: actions/checkout@v4 + # Add steps to build your static site (e.g., npm run build) + - name: Install files + run: | + mkdir -p dist + cp activation/index_pyodide_optimized.html dist/index.html + cp activation/jquery* dist/ + cp activation/webworker.js dist/ + - name: Get Pyodide + run: | + PYODIDE_VERSION=0.29.3 + mkdir -p dist/pyodide + curl -L https://github.com/pyodide/pyodide/releases/download/${PYODIDE_VERSION}/pyodide-core-${PYODIDE_VERSION}.tar.bz2 -o pyodide.tar.bz2 + tar -xjf pyodide.tar.bz2 -C dist/pyodide --strip-components=1 + rm pyodide.tar.bz2 + - name: Upload artifact + # The contents of the 'build' directory will be uploaded as an artifact + uses: actions/upload-pages-artifact@v4 + with: + path: 'dist/' # Change this to your build output directory (e.g., public, dist) + + deploy: + # Add a dependency to the build job + needs: build + runs-on: ubuntu-latest + permissions: + pages: write # Grants the GITHUB_TOKEN the necessary permissions to deploy to GitHub Pages + id-token: write # Required for OIDC authentication + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 # This action handles the deployment From c5dca965c77a1ec1857db64f3369ef1dca5d2a82 Mon Sep 17 00:00:00 2001 From: bbm Date: Wed, 25 Feb 2026 12:11:37 -0500 Subject: [PATCH 21/66] add script for getting static pyodide libraries we need --- activation/get_pyodide.sh | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100755 activation/get_pyodide.sh diff --git a/activation/get_pyodide.sh b/activation/get_pyodide.sh new file mode 100755 index 0000000..b644719 --- /dev/null +++ b/activation/get_pyodide.sh @@ -0,0 +1,22 @@ +# !/bin/bash + +# Default version of pyodide to download if not set via environment variable +PYODIDE_VERSION=${PYODIDE_VERSION:-0.29.3} + +rm -rf pyodide +mkdir pyodide + +# Get the core pyodide files first (this is smaller and faster to download than the full version) +curl -L https://github.com/pyodide/pyodide/releases/download/${PYODIDE_VERSION}/pyodide-core-${PYODIDE_VERSION}.tar.bz2 -o pyodide.tar.bz2 + tar -xjf pyodide.tar.bz2 -C ./pyodide --strip-components=1 + +# Download the full version to get the specific wheels we need (numpy, pytz, micropip) +curl -L https://github.com/pyodide/pyodide/releases/download/${PYODIDE_VERSION}/pyodide-${PYODIDE_VERSION}.tar.bz2 -o pyodide_full.tar.bz2 + +# Extract only the core runtime + our specific wheels +tar -xjf pyodide_full.tar.bz2 -C ./pyodide --strip-components=1 \ + --wildcards --no-anchored \ + 'micropip-*.whl' 'numpy-*.whl' 'pytz-*.whl' 'pyparsing-*.whl' + +# Download the latest periodictable wheel from PyPI +pip download periodictable --no-deps --only-binary :all: -d ./pyodide/ \ No newline at end of file From 1c9949063a2b3a008bb45cdfc234b3067e779997 Mon Sep 17 00:00:00 2001 From: bbm Date: Wed, 25 Feb 2026 12:12:08 -0500 Subject: [PATCH 22/66] use new script for getting pyodide --- .github/workflows/deploy.yml | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 9d389aa..393e693 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -15,19 +15,17 @@ jobs: - name: Checkout your repository uses: actions/checkout@v4 # Add steps to build your static site (e.g., npm run build) + - name: Get pyodide + run: | + PYODIDE_VERSION=0.29.3 + cd activation && ./get_pyodide.sh - name: Install files run: | mkdir -p dist cp activation/index_pyodide_optimized.html dist/index.html cp activation/jquery* dist/ cp activation/webworker.js dist/ - - name: Get Pyodide - run: | - PYODIDE_VERSION=0.29.3 - mkdir -p dist/pyodide - curl -L https://github.com/pyodide/pyodide/releases/download/${PYODIDE_VERSION}/pyodide-core-${PYODIDE_VERSION}.tar.bz2 -o pyodide.tar.bz2 - tar -xjf pyodide.tar.bz2 -C dist/pyodide --strip-components=1 - rm pyodide.tar.bz2 + cp -r activation/pyodide dist/pyodide - name: Upload artifact # The contents of the 'build' directory will be uploaded as an artifact uses: actions/upload-pages-artifact@v4 From e469fe937bed050f5ecb60e8020f5e11b09e46d0 Mon Sep 17 00:00:00 2001 From: bbm Date: Wed, 25 Feb 2026 12:12:26 -0500 Subject: [PATCH 23/66] use local pyodide --- activation/webworker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activation/webworker.js b/activation/webworker.js index d86fef3..d5afcf8 100644 --- a/activation/webworker.js +++ b/activation/webworker.js @@ -1,6 +1,6 @@ // webworker.js -import { loadPyodide } from "https://cdn.jsdelivr.net/pyodide/v0.29.3/full/pyodide.mjs"; +import { loadPyodide } from "./pyodide/pyodide.mjs"; // import { loadPyodide } from "./pyodide/pyodide.mjs"; async function loadPyodideAndPackages() { From 1ed74f57b20aa93610c83c4ffc94bf3ebc68e958 Mon Sep 17 00:00:00 2001 From: bbm Date: Wed, 25 Feb 2026 12:16:21 -0500 Subject: [PATCH 24/66] use local nact.py --- .github/workflows/deploy.yml | 1 + activation/webworker.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 393e693..04ef89c 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -25,6 +25,7 @@ jobs: cp activation/index_pyodide_optimized.html dist/index.html cp activation/jquery* dist/ cp activation/webworker.js dist/ + cp cgi-bin/nact.py dist/ cp -r activation/pyodide dist/pyodide - name: Upload artifact # The contents of the 'build' directory will be uploaded as an artifact diff --git a/activation/webworker.js b/activation/webworker.js index d5afcf8..fdeebc2 100644 --- a/activation/webworker.js +++ b/activation/webworker.js @@ -16,7 +16,7 @@ async function loadPyodideAndPackages() { // Downloading a single file await pyodide.runPythonAsync(` from pyodide.http import pyfetch - response = await pyfetch("../cgi-bin/nact.py") + response = await pyfetch("./nact.py") with open("nact.py", "wb") as f: f.write(await response.bytes()) import nact From c706e2c824cd4bb36fd084924cfd2d146d951f14 Mon Sep 17 00:00:00 2001 From: bbm Date: Wed, 25 Feb 2026 12:18:06 -0500 Subject: [PATCH 25/66] add favicon.ico to site --- .github/workflows/deploy.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 04ef89c..1117f23 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -25,6 +25,7 @@ jobs: cp activation/index_pyodide_optimized.html dist/index.html cp activation/jquery* dist/ cp activation/webworker.js dist/ + cp activation/favicon.ico dist/ cp cgi-bin/nact.py dist/ cp -r activation/pyodide dist/pyodide - name: Upload artifact From bdeb709ef512cc8cb3e15d21cffec9a20ef1273a Mon Sep 17 00:00:00 2001 From: bbm Date: Wed, 25 Feb 2026 14:19:31 -0500 Subject: [PATCH 26/66] adding deploy script --- deploy.sh | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100755 deploy.sh diff --git a/deploy.sh b/deploy.sh new file mode 100755 index 0000000..93d5c00 --- /dev/null +++ b/deploy.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +TARGET_DIR=${TARGET_DIR:-/var/www/html/resources/activation} + +# First, get the latest pyodide files and the specific periodictable wheel we need: +./activation/get_pyodide.sh + +# Now copy all the necessary files to the target directory for deployment: +mkdir -p $TARGET_DIR +cp activation/index_pyodide_optimized.html $TARGET_DIR/index.html +cp activation/jquery* $TARGET_DIR/ +cp activation/webworker.js $TARGET_DIR/ +cp activation/favicon.ico $TARGET_DIR/ +cp activation/periodictable_wheel_name.txt $TARGET_DIR/ +cp cgi-bin/nact.py $TARGET_DIR/ +cp -r activation/pyodide $TARGET_DIR/pyodide \ No newline at end of file From bd3fb8db1a3474f30acccf25726a5f90fe826a0c Mon Sep 17 00:00:00 2001 From: bbm Date: Wed, 25 Feb 2026 14:20:05 -0500 Subject: [PATCH 27/66] add helper file that contains full path to periodictable local wheel --- activation/get_pyodide.sh | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/activation/get_pyodide.sh b/activation/get_pyodide.sh index b644719..f2c8632 100755 --- a/activation/get_pyodide.sh +++ b/activation/get_pyodide.sh @@ -1,5 +1,8 @@ # !/bin/bash +# Run in the activation directory (where this script lives) +cd "$(dirname "$0")" + # Default version of pyodide to download if not set via environment variable PYODIDE_VERSION=${PYODIDE_VERSION:-0.29.3} @@ -19,4 +22,11 @@ tar -xjf pyodide_full.tar.bz2 -C ./pyodide --strip-components=1 \ 'micropip-*.whl' 'numpy-*.whl' 'pytz-*.whl' 'pyparsing-*.whl' # Download the latest periodictable wheel from PyPI -pip download periodictable --no-deps --only-binary :all: -d ./pyodide/ \ No newline at end of file +pip download periodictable --no-deps --only-binary :all: -d ./pyodide/ + +# Write out the full wheel file name to a text file for use in the workflow +ls pyodide/periodictable-*.whl > periodictable_wheel_name.txt + +# Cleanup +rm -f pyodide.tar.bz2 +rm -f pyodide_full.tar.bz2 From ab53c1a8c55454465a81624697b079b667112de6 Mon Sep 17 00:00:00 2001 From: bbm Date: Wed, 25 Feb 2026 14:20:24 -0500 Subject: [PATCH 28/66] use new deployment all-in-one script --- .github/workflows/deploy.yml | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 1117f23..97921e6 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -15,19 +15,11 @@ jobs: - name: Checkout your repository uses: actions/checkout@v4 # Add steps to build your static site (e.g., npm run build) - - name: Get pyodide + - name: Run deployment script run: | PYODIDE_VERSION=0.29.3 - cd activation && ./get_pyodide.sh - - name: Install files - run: | - mkdir -p dist - cp activation/index_pyodide_optimized.html dist/index.html - cp activation/jquery* dist/ - cp activation/webworker.js dist/ - cp activation/favicon.ico dist/ - cp cgi-bin/nact.py dist/ - cp -r activation/pyodide dist/pyodide + TARGET_DIR=dist + ./deploy.sh - name: Upload artifact # The contents of the 'build' directory will be uploaded as an artifact uses: actions/upload-pages-artifact@v4 From 325e3ce31c752b6366e76824fb46235c8e156299 Mon Sep 17 00:00:00 2001 From: bbm Date: Wed, 25 Feb 2026 14:20:50 -0500 Subject: [PATCH 29/66] use new manifest file to get full path to periodictable local wheel --- activation/webworker.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/activation/webworker.js b/activation/webworker.js index fdeebc2..3e4fa7c 100644 --- a/activation/webworker.js +++ b/activation/webworker.js @@ -6,9 +6,13 @@ import { loadPyodide } from "./pyodide/pyodide.mjs"; async function loadPyodideAndPackages() { self.pyodide = await loadPyodide(); await self.pyodide.loadPackage(["numpy", "pytz", "micropip"]); + + // get the periodictable wheel name from the special file: + const response = await fetch("./periodictable_wheel_name.txt"); + const wheelName = (await response.text()).trim(); await self.pyodide.runPythonAsync(` import micropip - await micropip.install("periodictable") + await micropip.install("./${wheelName}") import periodictable print(periodictable.__version__) `) From 98b9cc59b0919d47c4d384ed23ed5df0f35133d6 Mon Sep 17 00:00:00 2001 From: bbm Date: Wed, 25 Feb 2026 14:21:18 -0500 Subject: [PATCH 30/66] use unicode arrows in table headers instead of GIF from vendored theme --- activation/index_pyodide_optimized.html | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/activation/index_pyodide_optimized.html b/activation/index_pyodide_optimized.html index cdc32d4..53202a4 100644 --- a/activation/index_pyodide_optimized.html +++ b/activation/index_pyodide_optimized.html @@ -68,16 +68,20 @@ tbody tr:nth-child(2n) td, tbody tr.even td, ul li:nth-child(2n), ol li:nth-child(2n) { background: inherit; /* background: none repeat scroll 0 0 #F3F3F9; */ } table.tablesorter thead tr .headerSortable { - background-image: url(resonance-theme/bg.gif); - background-repeat: no-repeat; - background-position: center right; padding-right: 2em; /* space for sort arrows */ + cursor: pointer; } - table.tablesorter thead tr .headerSortUp { - background-image: url(resonance-theme/asc.gif); + table.tablesorter thead tr .headerSortable::after { + content: " \25B4\25BE"; /* ▴▾ */ + opacity: 0.4; } - table.tablesorter thead tr .headerSortDown { - background-image: url(resonance-theme/desc.gif); + table.tablesorter thead tr .headerSortUp::after { + content: " \25B2"; /* ▲ */ + opacity: 1; + } + table.tablesorter thead tr .headerSortDown::after { + content: " \25BC"; /* ▼ */ + opacity: 1; } /* output markup */ @@ -784,7 +788,10 @@
    From a5cfdf41cdcc45e42e26ca2b207bb31b1ac51ee9 Mon Sep 17 00:00:00 2001 From: bbm Date: Wed, 25 Feb 2026 14:24:01 -0500 Subject: [PATCH 31/66] need to export env variables for them to be picked up by deploy.sh --- .github/workflows/deploy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 97921e6..6456bb8 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -17,8 +17,8 @@ jobs: # Add steps to build your static site (e.g., npm run build) - name: Run deployment script run: | - PYODIDE_VERSION=0.29.3 - TARGET_DIR=dist + export PYODIDE_VERSION=0.29.3 + export TARGET_DIR=dist ./deploy.sh - name: Upload artifact # The contents of the 'build' directory will be uploaded as an artifact From 050e9edfb6eb9240087b373559bf18198c4294b4 Mon Sep 17 00:00:00 2001 From: bbm Date: Wed, 25 Feb 2026 14:34:39 -0500 Subject: [PATCH 32/66] fix table sorting --- activation/index_pyodide_optimized.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/activation/index_pyodide_optimized.html b/activation/index_pyodide_optimized.html index 53202a4..5a92dc5 100644 --- a/activation/index_pyodide_optimized.html +++ b/activation/index_pyodide_optimized.html @@ -75,11 +75,11 @@ content: " \25B4\25BE"; /* ▴▾ */ opacity: 0.4; } - table.tablesorter thead tr .headerSortUp::after { + table.tablesorter thead tr .headerSortable.headerSortUp::after { content: " \25B2"; /* ▲ */ opacity: 1; } - table.tablesorter thead tr .headerSortDown::after { + table.tablesorter thead tr .headerSortable.headerSortDown::after { content: " \25BC"; /* ▼ */ opacity: 1; } @@ -739,11 +739,11 @@ // End of div content += '
    \n'; - $(content).prependTo('div[id=results]'); //add to the dom + var $new = $(content).prependTo('div[id=results]'); //add to the dom // Start table unsorted so that b reactions follow transients as they // do in the activation table. Note that there is no way to get back // the original order. - $("table").tablesorter(); + $new.find("table").tablesorter(); scroll_to_result(); } From 7443d2da6ce480014ecb723d19b085b5b564ced0 Mon Sep 17 00:00:00 2001 From: bbm Date: Wed, 25 Feb 2026 14:37:13 -0500 Subject: [PATCH 33/66] use pip3 since legacy installs will use that --- activation/get_pyodide.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activation/get_pyodide.sh b/activation/get_pyodide.sh index f2c8632..49d23da 100755 --- a/activation/get_pyodide.sh +++ b/activation/get_pyodide.sh @@ -22,7 +22,7 @@ tar -xjf pyodide_full.tar.bz2 -C ./pyodide --strip-components=1 \ 'micropip-*.whl' 'numpy-*.whl' 'pytz-*.whl' 'pyparsing-*.whl' # Download the latest periodictable wheel from PyPI -pip download periodictable --no-deps --only-binary :all: -d ./pyodide/ +pip3 download periodictable --no-deps --only-binary :all: -d ./pyodide/ # Write out the full wheel file name to a text file for use in the workflow ls pyodide/periodictable-*.whl > periodictable_wheel_name.txt From 0f3c833d9c42369264dffd2f640ab9e86ed62bbc Mon Sep 17 00:00:00 2001 From: bbm Date: Wed, 25 Feb 2026 14:56:51 -0500 Subject: [PATCH 34/66] rename deploy script because there will be more than one --- deploy.sh => deploy_calculator.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename deploy.sh => deploy_calculator.sh (100%) diff --git a/deploy.sh b/deploy_calculator.sh similarity index 100% rename from deploy.sh rename to deploy_calculator.sh From c8ca32d5397954522a270e00af026bfab071fc9e Mon Sep 17 00:00:00 2001 From: bbm Date: Wed, 25 Feb 2026 14:57:02 -0500 Subject: [PATCH 35/66] use renamed deploy script --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 6456bb8..c4dd004 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -19,7 +19,7 @@ jobs: run: | export PYODIDE_VERSION=0.29.3 export TARGET_DIR=dist - ./deploy.sh + ./deploy_calculator.sh - name: Upload artifact # The contents of the 'build' directory will be uploaded as an artifact uses: actions/upload-pages-artifact@v4 From f3d0e48add16103e04477dfec31d20a32d339955 Mon Sep 17 00:00:00 2001 From: bbm Date: Wed, 25 Feb 2026 16:35:04 -0500 Subject: [PATCH 36/66] remove unused page --- activation/index_pyodide_serviceworker.html | 1343 ------------------- activation/sw.js | 97 -- 2 files changed, 1440 deletions(-) delete mode 100644 activation/index_pyodide_serviceworker.html delete mode 100644 activation/sw.js diff --git a/activation/index_pyodide_serviceworker.html b/activation/index_pyodide_serviceworker.html deleted file mode 100644 index fda74d2..0000000 --- a/activation/index_pyodide_serviceworker.html +++ /dev/null @@ -1,1343 +0,0 @@ - - - - - Neutron Activation and Scattering Calculator - - - - - - - - - - - - - - - - - -
    -

    Loading...

    -
    -
    - -
    - -
    - -
    -

    Material

    - - - -
    -
    -
    -
    - -
    -

    Neutron Activation

    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - For rabbit system
    - - - -
    -
    -
    -
    -
    -
    -
    - - - - - -
    -
    -
    -
    -
    -
    -
    - -
    - -
    -

    Absorption and Scattering

    - - - - - - - - -
    - - - -
    -
    -
    -
    -
    - - - -
    -
    -
    -
    -
    - -
    - -
    - -
    -
    -
    -

    Neutron activation and scattering calculator

    -

    -This calculator uses neutron cross sections to compute activation -on the sample given the mass in the sample and the time in the beam, -or to perform scattering calculations for the neutrons which are -not absorbed by the sample. -

    -
      -
    1. Enter the sample formula in the material panel.
    2. -
    3. To perform activation calculations, fill in the thermal -flux, the mass, the time on and off the beam, then press the -calculate button in the neutron activation panel.
    4. -
    5. To perform scattering calculations, fill in the wavelength -of the neutron and/or xrays, the thickness and the -density (if not given in the formula), then press the -calculate button in the absorption and scattering panel.
    6. -
    -
    - - -
    -

    Chemical formula

    -

    The chemical formula parser allows you to specify materials and mixtures. -Formulas are parsed with -periodictable -python package (Kienzle 2008). -

    - -
    -
    simple formula
    -
    A basic formula consists of elements and their quantities. -
    CaCO3
    represents the chemical CaCO3
    -
    - -
    multi-part formula
    -
    Formulas can be built from parts by separating them with "+" or space, - with a number before the part representing repeats. Using parentheses, - a formula is treated as if it were a single unit. -
    CaCO3+6H20
    , -
    CaCO3 6H2O
    and -
    CaCO3(H2O)6
    all represent ikaite, - CaCO3·6H2O -
    -
    - -
    isotopes
    -
    Isotopes are represented by element[nuclide index]. -Special symbols
    D
    and -
    T
    -can be used for 2H and 3H. -Isotopes can be mixed within a formula, such as -
    DHO
    for partially deuterated water. -Use
    H[1]
    in formula for labile hydrogen. -These will be substituded with H and D in proportion with the D2O -fraction when computing the contrast match point of the sample. -
    O[18]
    represents the 18O
    -
    C3H4H[1]NO@1.29n
    represents alanine with one labile hydrogen. -
    - -
    density
    -
    Mass density is needed to compute scattering factors for the material. -The density can be entered in the density field, or it can be given in -the formula by adding @value to the end. Densities for the pure elements are -already known. -
    H2O@1
    -indicates that water has a density of 1 g/cm3
    -
    - -
    isotopic density
    -
    If the formula uses a mixture of isotopes, you can still use the density -of the material assuming natural abundance, but add an "n" to the value -to scale it to the isotope specific density. If you already know the -isotopic density, use the value by itself and it will not be scaled. -
    D2O@1n
    , -
    D2O@1.11
    , and -
    D2O@1.11i
    -all give the density of D2O as 1.11 g/cm3
    -
    - -
    mole fractions
    -
    Using non-integer quantities, arbitrary concentration ratios can be - be constructed. -
    78.2H2O[16] + 21.8H2O[18] @1n
    - represents water with 78.2% 16O and 21.8% 18O -
    -
    - -
    mass fractions
    -
    Formulas can be mixed by mass, with each part starting with a percentage - followed by formula followed by "//". The first part must use "%wt" to - indicate that it is a mass fraction. The final part is the base, and it - does not need a percentage since it makes up the rest of the material. -
    50%wt Co // Ti
    - is more descriptive than Co0.552Ti0.448
    -
    33%wt Co // 33% Fe // Ti
    - builds a 1:1:1 mixture by mass of cobalt-iron-titanium
    -
    - -
    volume fractions
    -
    Volume fractions are like mass fractions, but they use "%vol" instead. - Each component of the volume fraction must specify the density. -
    20%vol (10%wt NaCl@2.16 // H2O@1) // D2O@1n
    - is a 10% saline solution by weight mixed 20:80 by volume with - D2O, which is the same as -
    NaCl(H2O)29.1966(D2O)122.794@1.10i
    -
    -
    - -
    mass and volume mixtures
    -
    Specific amounts of materials can be mixed, with each part giving - the quantity of material followed by "//". Quantities can be masses - (kg, g, mg, ug, or ng) or they can be volumes (L, mL, uL, nL). Density - is required for materials given by volume. For scattering calculations - density is required for the materials given by mass as well. -
    5g NaCl // 50mL H2O@1
    - is more descriptive than -
    NaCl(H2O)32.4407
    -
    -
    5g NaCl@2.16 // 50mL H2O@1
    - computes the density as 1.05 g/cm3. Not useful in this - case since 9%wt brine has a density of 1.0633 at ambient temperature. -
    -
    50 mL (45 mL H2O@1 // 5 g NaCl)@1.0707 // 20 mL D2O@1n
    - uses the appropriate density for a 10%wt brine in the mixture. -
    -
    - -
    layer thickness
    -
    Multilayer samples can specified as layer thickness and material separated - by "//". Thicknesses are in length units (cm, mm, um, nm). The - resulting material will compute activation for 1 cm2 of material. - Density is required for each layer. -
    1 cm Si // 5 nm Cr // 10 nm Au
    -
    -
    -
    - -
    biomolecules
    -
    - For FASTA sequences - use "code:sequence", where code is "aa" for amino acid sequences, "dna" for - DNA sequences, or "rna" for RNA sequences. Density is estimated automatically. - This calculation uses 1H for labile hydrogen, with substitution - by H in natural abundance and pure D when computing contrast match point. -
    β-casein amino acid sequence
    aa:RELEELNVPGEIVESLSSSEESITRINKKIEKFQSEEQQQTEDELQDKIHPFAQTQSLVYPFPGPIPNSLPQNIPPLTQTPVVVPPFLQPEVMGVSKVKEAMAPKHKEMPFPKYPVEPFTESQSLTLTDVENLHLPLPLLQSWMHQPHQPLPPTVMFPPQSVLSLSQSKVLPVPQKAVPYPQRDMPIQAFLLYQEPVLGPVRGPFPIIV
    -
    -
    - -
    -

    Thermal flux

    -

    Units: n/cm2/s

    -

    - Provide the thermal flux equivalent for the pre-sample beam configuration - for the instrument. This is only need for computing the neutron - activation from the experiment, and is not used for computing scattering - cross sections. Within the NCNR, you can access a list of - instrument fluxes, - but this is not available from outside. -

    -

    - The neutron activation calculation follows (Shleien 1998). - Activation is a function of isotope, not element. When - an element is used in a formula, the natural abundance of the individual - isotopes is used to determine the total activation. By default, the - activation calculator uses values from the IAEA - handbook (IAEA 1987), and the - scattering calculator uses the NIST atomic weights and isotope composition - database (Bölke 2005). -

    - -

    Calculation parameters are controlled by URL:

    -
    -
    isotope abundance
    -
    - The NIST database can be selected for isotope abundance using: - index.html?abundance=NIST -
    - -
    activation cutoff
    -
    - The cutoff values for displaying activation data are set to 0.0005 μCi - by default. The full activation levels - can be displayed using: index.html?cutoff=0 -
    - -
    decay cutoff
    -
    The activation calculator determines the amount of time for the activation to decay to - the cutoff level, or to 0.0005 μCi if cutoff is 0. This can be set to a value - such as 0.1 μCi using: index.html?decay=0.1 -
    -
    - -

    Notes on calculation:

    -
    • - For some numerical combinations with very large half-lives the numerical - precision is inadequate and you get negative results. This can be - corrected by reformulation or approximations but has not been done. - Remember, the X in EXP(X) is limited to |X|<709 -
    • - Simplifications have been made as indicated in the comments column in - data table -
    • - Typically, for a decay chain where the daughter is also produced (isomers) - the s of the parent has been added to that of the daughter when the - daughter t1/2 is much longer (true for most cases) and the parent - t1/2 is relatively short, e.g. less than 1 day, so that all the daughter - will be made relatively promptly. -
    • - In cases where the above condition is not met an * is put next to the - nuclide name to warn that the daughter production has not been accounted - for. In most cases the daughter is in a simple decay equilibrium. -
    • - Where the decay product is a new nuclide a line has been added to the - database to account for this. This production mode is indicated in - the reaction column by 'b'. Where both m and g state contribute to daughter - production it is simplified to a single parent, that with the greater - cross-section or that with the longer half-life together with the sum - of the cross-sections. -
    • - In a few cases where the parent nuclide t1/2 is very short all production - is assigned to the daughter and no entry is made for the parent, as - noted in the comments column. -
    • - No correction for neutron burn up has been made. -
    • - Most cross-section data is from IAEA 273. -
    • - Fast neutron data from NBSIR 85-3151, Compendium of Benchmark Neutron Fields - is for reaction above the Cd cutooff, .4eV. Noted in comment column. -
    • - Fast neutron reaction data from IAEA 273 has been weighted by a unit fluence - fast maxwellian spectrum as described in NBSIR 85-3151, but no further - weighting for a 1/v or thermal component has been made. Only selected - reactions have been included. -
    • - Reaction = b indicates production via decay from an activation produced parent. -
    • - Notation on reaction product name: -
      m, m1, m2
      - indicate metastable states. Decay may be the ground state or another nuclide. -
      +
      - indicates radioactive daughter production already included in daughter listing - several parent t1/2's required to acheive calculated daughter activity. - All activations are assigned at end of irradiation. - In most cases the added activity to the daughter is small. -
      *
      - indicates radioactive daughter production NOT calculated, approx - secular equilibrium. -
      s
      - indicates radioactive daughter of this nuclide in secular equilibrium - after several daughter t1/2's. -
      t
      - indicates transient equil via beta decay. Accumulation of that nuclide - during irradiation is separately calculated. -
      -
    -
    - -
    -

    Cadmium ratio

    -

    Units: none

    -

    - Samples in the rabbit tubes can be shielded with cadmium to reduce the thermal - flux while leaving the epithermal flux mostly unchanged. The cadmium ratio - determines the degree of reduction in the scattering cross sections, corresponding - to the reduced flux. This value is unitless. Use a value of 0 for beamline - experiments. -

    -
    - -
    -

    Thermal/fast ratio

    -

    Units: none

    -

    - When performing neutron activation analysis in a rabbit tube, the additional - fast neutron activations need to be determined. The thermal/fast ratio is - used to determine the fast neutron flux from the thermal flux equivalent for - the given rabbit tube. The resulting fast flux is (thermal flux)/(thermal/fast ratio). - This value is unitless. Use a value of 0 for beamline experiments. -

    -
    - -
    -

    Material mass

    -

    Units: g, kg, mg or ug

    -

    - The total neutron activation depends on the mass of the individual - isotopes in the sample and the total time in the beam. All activation - calculations assume a thin plate sample, with all parts of the sample - exposed to full flux during activation, and no self-shielding when - estimating the activation level outside the beam. -

    -
    - -
    -

    Exposure

    -

    Units: h m s d w y

    -

    - Exposure is the duration of the exposure at the given flux. Activation - will be accumulated over that time, with decay beginning the moment the - sample is activated. Time defaults to hours, but can be set to - hours, minutes, seconds, days, weeks or years by adding h, m, s, d, w, or y - to the value respectively. -

    -
    - -
    -

    Decay

    -

    Units: h m s d w y OR yyyy-mm-dd hh:mm:ss

    -

    - The sample begins to decay immediately, even while it is being activated. - The decay field allows you to specify how long since the sample - was removed from the beam. The default is hours, but can be set to - hours, minutes, seconds, days, weeks or years by adding h, m, s, d, w, or y - to the value respectively. - We always compute the activation level when the sample is removed from the beam, - and at 1 hour, 1 day and 15 days post activation. -

    -

    - Instead of saying how long the sample activation has decayed, you can use - the time that the sample was removed from the beam. Times are given as - year-month-day hour:minute:second. - Approximate times are allowed, such as 2010-03 for March, 2010. This is - equivalent to 2010-03-31 23:59:59, which is the end of March so that the - activation estimate will be conservative. This is the most activation - consistent with the sample being on the beam sometime in March, 2010. - Times are specified in US/Eastern. Add "Z" after the time of day to - indicate universal coordinated time (UTC), or add a timezone offset such - as "+01" for +1 hours in France in winter, when daylight savings time is - not in effect. -

    -

    Examples

    - - - - - - - - - - - - - -
    If you type:This is equivalent to:
    2 m2 minutes ago
    11 hour ago
    2.5w2 and a half weeks ago
    3 y3 years ago
    2015-01-02 21:45:00January 2, 2015 at 9:45 PM US/Eastern
    2010-03March 31, 2010 at 11:59:59 PM US/Eastern
    2010-7-5 12:23July 5, 2010 at 12:23:59 PM US/Eastern
    2015-01-02 21:45:00ZJanuary 2, 2015 at 9:45 PM UTC
    2015-01-02 21:45:00-0600January 2, 2015 at 9:45 PM US/Central
    2015-08-02 21:45:00-0500August 2, 2015 at 9:45 PM US/Central
    -
    - -
    -

    Mass density

    -

    Units: g/cm3 or A3

    -

    - Density is used to compute absorption, transmission and scattering. -

    -
    from formula
    -
    Leave the density field blank and add -
    @
    + density - to the end of the formula, where density is in g/cm3. - For compounds with specific isotopes, you can use the density of the - naturally occurring compound as -
    @
    + density +
    n
    - and the isotope specific density will be computed. Density defaults to - 1 g/cm3, or for pure elements, the natural density given in - the periodic table is used. - -
    D2O@1n
    or -
    D2O@1.11
    -
    -
    g/cm3
    -
    Enter the density by itself, which will be interpreted as g/cm3, or - equivalently, kg/L. No units are needed. If the value is - density +
    n
    then it is density of the the - naturally occuring compound and the isotopic density will be computed. -
    D2O has a natural density of -
    1n
    and an isotopic density of -
    1.11
    -
    -
    cell volume
    -
    Enter a number followed by A3 for Å3. Be sure that your - formula contains the correct number of atoms for the unit cell, possibly by - using n(formula), where n is 6 for hexagonal close packed, 4 for face centered - cells, 2 for body centered and base centered cells, or 1 for simple cells. -
    4NaCl has a cell volume of -
    179.4 A3
    -
    -
    crystal lattice parameters
    -
    Enter lattice parameters "a:n b:n c:n alpha:n beta:n gamma:n" - where a, b, c are in Å and α, β, γ are in degrees. - If not specified, b and c default to a. Ratios can also be used, - so that "b/a:n" gives b=n*a, and "c/a:n" gives c=n*a. Angles - α, β, and γ default to 90°. Be sure that the - formula contains the correct number of atoms for the unit cell. -
    4NaCl has a cubic lattice with -
    a:5.6402
    -
    -
    -
    - -
    -

    Thickness

    -

    Units: cm

    -

    - The material thickness in cm is used to determine sample transmission, - or how much beam will be absorbed by the sample or scattered incoherently. - Leave it at 1 cm if you do not need this information. -

    -
    - -
    -

    Source neutrons

    -

    Units: Ang, meV or m/s

    -

    - The energy of the source neutrons will affect the absorption cross section - and hence the penetration depth and sample attenuation. Energy can be - expressed as wavelength in Å, as energy in meV, or as neutron - velocity in m/s. - Neutron cross sections are tabulated - at 1.798 Å = 25.3 meV = 2200 m/s, with an assumed 1/v dependence for - the absorption cross section (Rauch 2003, - Sears 2006). -

    - For heavier isotopes (Cd, Hf, rare earths) and/or shorter wavelengths - (below 1 Å) there are neutron resonances - in the thermal range. For rare-earth elements the energy-dependent coherent - sld is calculated following scattering length values tabulated - in Lynn and Seeger 1992. Incoherent - scattering will be understimated for these elements. -

    - There is also a wavelength dependence for single phonon interactions which - gives rise to significant inelastic scattering for lighter isotopes (H, D) - and/or longer wavelengths (above 5 Å). This factor is both - temperature and material dependent and will not be included - in the scattering calculations. In particular, penetration length and - transmitted flux are going to be significantly overestimated. -

    -
    - -
    -

    Source X-rays

    -

    Units: Ang, keV or Ka

    -

    - X-ray absorption and scattering are computed from the energy dependent - atomic scattering factors (Henke 1993). - Energy can be expressed as wavelength in Å, as energy in keV, or - using an element name for the Kα emission line2 for - that element (Deslattes 2003). -

    -
    - -
    -

    References

    -
      -
    1. - Bölke, et al. (2005). - Isotopic Compositions of the Elements, 2001. - J. Phys. Chem. Ref. Data, Vol. 34, No. 1, 2005 - [abundance data] -
    2. -
    3. - Deslattes, R.D.; Kessler, Jr., E.G.; Indelicato, P.; de Billy, L.; Lindroth, E. and Anton, J. (2003). - Rev. Mod. Phys. 75, 35-99. - [xray emission lines] -
    4. -
    5. - Henke, B.L.; Gullikson, E.M. and Davis, J.C. (1993). - X-ray interactions: - photoabsorption, scattering, transmission, and reflection at E=50-30000 eV, Z=1-92, - Atomic Data and Nuclear Data Tables Vol. 54 (no.2), 181-342. - [xray cross sections] -
    6. -
    7. - IAEA (1987). - Handbook on Nuclear Activation Data. - TR 273 (International Atomic Energy Agency, Vienna, Austria). - [tech report] -
    8. - -
    9. - Kienzle, P. A. (2008-2019). - Extensible periodic table (v1.5.2). - Computer Software. - https://periodictable.readthedocs.io. - [calculator source, - web service source] -
    10. -
    11. - Lynn, J.E. and Seeger, P.A. (1990). - Resonance effects in neutron scattering lengths of rare-earth nuclides. - Atomic Data and Nuclear Data Tables 44, 191-207. - doi:10.1016/0092-640X(90)90013-A - [rare earth scattering lengths] -
    12. - Rauch, H. and Waschkowski, W. (2003). - Neutron Scattering Lengths in ILL Neutron Data Booklet (second edition), - A.-J. Dianoux, G. Lander, Eds. - Old City Publishing, Philidelphia, PA. pp 1.1-1 to 1.1-17. - [booklet, - neutron cross sections] -
    13. -
    14. - Sears, V. F. (2006). "Scattering lengths for neutrons" In Prince, E. Ed. - International Tables for Crystallography Volume C: Mathematical, Physical and Chemical Tables" - Kluwer Academic Publishers, pp 444-454. - doi:10.1107/97809553602060000103 - [scattering calculations] -
    15. -
    16. - Shleien, B.; Slaback, L.A. and Birky, B.K. (1998). - Handbook of health physics and radiological health. - Williams & Wilkins, Baltimore. - [activation data] -
    17. -
    -
    - -
    -

    History

    -
    -
    2021-04-21
    Support energy-dependent rare earth elements. -
    Use complex scattering length bc when computing - σc = 4π |bc|2/100 and - σi = σs - σc. -
    -
    2020-10-29
    Change field labels from 'time on/off beam' to 'exposure/decay duration'.
    -
    2020-01-22
    Restore support for Internet Explorer 10 and 11.
    -
    2019-12-02
    Fix cutoff=0 handling in URL.
    -
    2019-11-14
    Correct units on activity table: nCi becomes uCi. -
    Elemental carbon density changed to 2.2 to match CXRO, CRC and RSC. -
    -
    2019-11-04
    Update neutron refs with links to ILL data book and Table for Crystallography.
    -
    2019-09-16
    Improve help system: can now scroll between sections.
    -
    2019-09-11
    Include notes on activation calculation.
    -
    2019-08-27
    Change default cutoff to 0.5 nCi.
    -
    2018-01-12
    Make activation table sortable.
    -
    2017-05-11
    Improved support for printing tables. -
    Support for biomolecules with labile hydrogen (FASTA format). -
    Mixture by mass and volume, e.g., 5 g NaCl // 50 mL H2O@1 -
    Multi-layer materials, e.g., 5 um Si // 3 nm Cr // 8 nm Au -
    Compute incoherent cross section from coherent and total. -
    -
    2016-12-07
    Use exponential notation for all activity levels.
    -
    2015-10-20
    Allow decay time to be calculated from timestamp..
    -
    2014-03-20
    Default to isotopic density.
    -
    2013-11-05
    Support for X-ray scattering.
    -
    2013-04-17
    Initial release.
    -
    -
    - - - -
    - -
    - -
    -
    -
    - -
    - - - diff --git a/activation/sw.js b/activation/sw.js deleted file mode 100644 index eb4aa4b..0000000 --- a/activation/sw.js +++ /dev/null @@ -1,97 +0,0 @@ -// sw.js - -// Setup your project to serve `py-worker.js`. You should also serve -// `pyodide.js`, and all its associated `.asm.js`, `.data`, `.json`, -// and `.wasm` files as well: -importScripts("https://cdn.jsdelivr.net/npm/xhr-shim@0.1.3/src/index.js"); -self.XMLHttpRequest = self.XMLHttpRequestShim; -importScripts("https://cdn.jsdelivr.net/pyodide/v0.20.0/full/pyodide.js"); - -let pyodide = null; - -async function loadPyodideAndPackages() { - const pyodide = await loadPyodide(); - await pyodide.loadPackage(["numpy", "pytz", "micropip"]); - await pyodide.runPythonAsync(` - import micropip - await micropip.install("periodictable") - import periodictable - print(periodictable.__version__) - `) - - // Downloading a single file - await pyodide.runPythonAsync(` - from pyodide.http import pyfetch - response = await pyfetch("../cgi-bin/nact.py") - with open("nact.py", "wb") as f: - f.write(await response.bytes()) - import nact - import json - import re - - class FakeFieldStorage(dict): - def getfirst(self, name, default=None): - rval = self.get(name, default) - return rval if rval != "" else default - def getlist(self, name, default=None): - name = re.sub("\\[\\]$", "", name) - rval = self.get(name, default) - if isinstance(rval, str) or isinstance(rval, bytes): - return [rval] - return list(rval) - `); - self.pyodide = pyodide; -} - -self.addEventListener("install", () => { - self.skipWaiting(); - self.pyodideReadyPromise = loadPyodideAndPackages(); - self.pyodideReadyPromise.then(() => { - console.log("install finished from sw.js side"); - }); -}) - -self.addEventListener("activate", function (event) { - event.waitUntil((async () => { - await self.pyodideReadyPromise; - await self.clients.claim(); - self.clients.matchAll().then(clients => { - clients.forEach(client => client.postMessage("ready")); - }); - console.log("clients claimed"); - })()); -}); - -self.addEventListener("fetch", (event) => { - if (event.request.url.endsWith("/ready")) { - event.respondWith(make_ready()); - } - if (event.request.url.endsWith("/nact.py")) { - event.respondWith(do_calculation(event)); - } -}); - -async function make_ready() { - if (!self?.pyodide?.runPythonAsync) { - const pyodideReadyPromise = loadPyodideAndPackages(); - await pyodideReadyPromise; - } - return new Response("true", { headers: { 'Content-Type': 'application/json' } }); -} - -async function do_calculation(event) { - try { - const json_data = await event.request.text(); - let python = ` - request = json.loads('${json_data}') - form = FakeFieldStorage(request) - json.dumps(nact.cgi_call(form)) - `; - let results = await self.pyodide.runPythonAsync(python); - return new Response(results, { headers: { 'Content-Type': 'application/json' } }); - } - catch (error) { - const edata = JSON.stringify({ success: false, detail: {error: error.message }}); - return new Response(edata, {headers: {'Content-Type': 'application/json'}}); - } -} \ No newline at end of file From 395017ff79231d7c043c80772606e7a1eb6515f0 Mon Sep 17 00:00:00 2001 From: bbm Date: Wed, 25 Feb 2026 16:35:40 -0500 Subject: [PATCH 37/66] remove another unused page --- activation/index_pyodide.html | 1373 --------------------------------- 1 file changed, 1373 deletions(-) delete mode 100644 activation/index_pyodide.html diff --git a/activation/index_pyodide.html b/activation/index_pyodide.html deleted file mode 100644 index 980f5df..0000000 --- a/activation/index_pyodide.html +++ /dev/null @@ -1,1373 +0,0 @@ - - - - - Neutron Activation and Scattering Calculator - - - - - - - - - - - - - - - - - -
    -

    Loading...

    -
    -
    - -
    - -
    - -
    -

    Material

    - - - -
    -
    -
    -
    - -
    -

    Neutron Activation

    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - For rabbit system
    - - - -
    -
    -
    -
    -
    -
    -
    - - - - - -
    -
    -
    -
    -
    -
    -
    - -
    - -
    -

    Absorption and Scattering

    - - - - - - - - -
    - - - -
    -
    -
    -
    -
    - - - -
    -
    -
    -
    -
    - -
    - -
    - -
    -
    -
    -

    Neutron activation and scattering calculator

    -

    -This calculator uses neutron cross sections to compute activation -of the sample given the mass in the sample and the time in the beam, -and to perform absorption and scattering calculations for samples on -slow neutron beamlines (energy below 325 meV, wavelength above 0.05 nm). -

    -
      -
    1. Enter the sample formula in the material panel.
    2. -
    3. To perform activation calculations, fill in the thermal -flux, the mass, the time on and off the beam, then press the -calculate button in the neutron activation panel.
    4. -
    5. To perform scattering calculations, fill in the wavelength -of the neutron and/or xrays, the thickness and the -density (if not given in the formula), then press the -calculate button in the absorption and scattering panel.
    6. -
    -
    - - -
    -

    Chemical formula

    -

    The chemical formula parser allows you to specify materials and mixtures. -Formulas are parsed with -periodictable -python package (Kienzle 2008). -

    - -
    -
    simple formula
    -
    A basic formula consists of elements and their quantities. -
    CaCO3
    represents the chemical CaCO3
    -
    - -
    multi-part formula
    -
    Formulas can be built from parts by separating them with "+" or space, - with a number before the part representing repeats. Using parentheses, - a formula is treated as if it were a single unit. -
    CaCO3+6H20
    , -
    CaCO3 6H2O
    and -
    CaCO3(H2O)6
    all represent ikaite, - CaCO3·6H2O -
    -
    - -
    isotopes
    -
    Isotopes are represented by element[nuclide index]. -Special symbols
    D
    and -
    T
    -can be used for 2H and 3H. -Isotopes can be mixed within a formula, such as -
    DHO
    for partially deuterated water. -Use
    H[1]
    in formula for labile hydrogen. -These will be substituded with H and D in proportion with the D2O -fraction when computing the contrast match point of the sample. -
    O[18]
    represents the 18O
    -
    C3H4H[1]NO@1.29n
    represents alanine with one labile hydrogen. -
    - -
    density
    -
    Mass density is needed to compute scattering factors for the material. -The density can be entered in the density field, or it can be given in -the formula by adding @value to the end. Densities for the pure elements are -already known. -
    H2O@1
    -indicates that water has a density of 1 g/cm3
    -
    - -
    isotopic density
    -
    If the formula uses a mixture of isotopes, you can still use the density -of the material assuming natural abundance, but add an "n" to the value -to scale it to the isotope specific density. If you already know the -isotopic density, use the value by itself and it will not be scaled. -
    D2O@1n
    , -
    D2O@1.11
    , and -
    D2O@1.11i
    -all give the density of D2O as 1.11 g/cm3
    -
    - -
    mole fractions
    -
    Using non-integer quantities, arbitrary concentration ratios can be - be constructed. -
    78.2H2O[16] + 21.8H2O[18] @1n
    - represents water with 78.2% 16O and 21.8% 18O -
    -
    - -
    mass fractions
    -
    Formulas can be mixed by mass, with each part starting with a percentage - followed by formula followed by "//". The first part must use "%wt" to - indicate that it is a mass fraction. The final part is the base, and it - does not need a percentage since it makes up the rest of the material. -
    50%wt Co // Ti
    - is more descriptive than Co0.552Ti0.448
    -
    33%wt Co // 33% Fe // Ti
    - builds a 1:1:1 mixture by mass of cobalt-iron-titanium
    -
    - -
    volume fractions
    -
    Volume fractions are like mass fractions, but they use "%vol" instead. - Each component of the volume fraction must specify the density. -
    20%vol (10%wt NaCl@2.16 // H2O@1) // D2O@1n
    - is a 10% saline solution by weight mixed 20:80 by volume with - D2O, which is the same as -
    NaCl(H2O)29.1966(D2O)122.794@1.10i
    -
    -
    - -
    mass and volume mixtures
    -
    Specific amounts of materials can be mixed, with each part giving - the quantity of material followed by "//". Quantities can be masses - (kg, g, mg, ug, or ng) or they can be volumes (L, mL, uL, nL). Density - is required for materials given by volume. For scattering calculations - density is required for the materials given by mass as well. -
    5g NaCl // 50mL H2O@1
    - is more descriptive than -
    NaCl(H2O)32.4407
    -
    -
    5g NaCl@2.16 // 50mL H2O@1
    - computes the density as 1.05 g/cm3. Not useful in this - case since 9%wt brine has a density of 1.0633 at ambient temperature. -
    -
    50 mL (45 mL H2O@1 // 5 g NaCl)@1.0707 // 20 mL D2O@1n
    - uses the appropriate density for a 10%wt brine in the mixture. -
    -
    - -
    layer thickness
    -
    Multilayer samples can specified as layer thickness and material separated - by "//". Thicknesses are in length units (cm, mm, um, nm). The - resulting material will compute activation for 1 cm2 of material. - Density is required for each layer. -
    1 cm Si // 5 nm Cr // 10 nm Au
    -
    -
    -
    - -
    biomolecules
    -
    - For FASTA sequences - use "code:sequence", where code is "aa" for amino acid sequences, "dna" for - DNA sequences, or "rna" for RNA sequences. Density is estimated automatically. - This calculation uses 1H for labile hydrogen, with substitution - by H in natural abundance and pure D when computing contrast match point. -
    β-casein amino acid sequence
    aa:RELEELNVPGEIVESLSSSEESITRINKKIEKFQSEEQQQTEDELQDKIHPFAQTQSLVYPFPGPIPNSLPQNIPPLTQTPVVVPPFLQPEVMGVSKVKEAMAPKHKEMPFPKYPVEPFTESQSLTLTDVENLHLPLPLLQSWMHQPHQPLPPTVMFPPQSVLSLSQSKVLPVPQKAVPYPQRDMPIQAFLLYQEPVLGPVRGPFPIIV
    -
    -
    - -
    -

    Thermal flux

    -

    Units: n/cm2/s

    -

    - Provide the thermal flux equivalent for the pre-sample beam configuration - for the instrument. Because neutron capture cross sections are linear - above 0.5 Å for most isotopes, simply scale the flux by λ/1.798 Å, where - λ is the average wavelength at the sample weighted by spectral intensity. - For non-linear isotopes activation may be underestimated - (176Lu < 1.8 Å; 151Eu < 0.8 Å) - or overestimated (33S < 11 Å; 204Hg < 20 Å). -

    -

    - The neutron activation calculation follows (Shleien 1998). - Activation is a function of isotope, not element. When - an element is used in a formula, the natural abundance of the individual - isotopes is used to determine the total activation. By default, the - activation calculator uses values from the IAEA - handbook (IAEA 1987), and the - scattering calculator uses the IUPAC 2021 atomic weights and isotope composition - database (CIAAW 2021). -

    -

    - For very high fluences, e.g., more than 1016 n/cm2, the activation - equations give erroneous results because of the precision limitations. - If there is doubt simply do the calculation at a lower flux and - proportion the result. This will not work for the cascade reactions, - i.e., two neutron additions. -

    -

    - Reaction = b : This is the beta produced daughter of an activated parent. - This is calculated only for the cases where the daughter is long lived - relative to the parent. The calculated activity is through the end of - exposure only. Contributions from the added decay of the parent after the - end of irradiation are left for the user to determine, but are usually - negligible for irradiations that are long relative to the parent halflife. -

    - -

    Calculation parameters are controlled by URL:

    -
    -
    isotope abundance
    -
    - Use the following to select IUPAC 2021 isotopic abundance data rather than the IAEA 1987 data: - index.html?abundance=IUPAC -
    - -
    activation cutoff
    -
    - The cutoff values for displaying activation data are set to 0.0005 μCi - by default. The full activation levels - can be displayed using: index.html?cutoff=0 -
    - -
    decay cutoff
    -
    The activation calculator determines the amount of time for the activation to decay to - the cutoff level, or to 0.0005 μCi if cutoff is 0. This can be set to a value - such as 0.1 μCi using: index.html?decay=0.1 -
    -
    - -

    Notes on calculation:

    -
    • - For some numerical combinations with very large half-lives the numerical - precision is inadequate and you get negative results. This can be - corrected by reformulation or approximations but has not been done. - Remember, the X in EXP(X) is limited to |X|<709 -
    • - Simplifications have been made as indicated in the comments column in - data table -
    • - Typically, for a decay chain where the daughter is also produced (isomers) - the s of the parent has been added to that of the daughter when the - daughter t1/2 is much longer (true for most cases) and the parent - t1/2 is relatively short, e.g. less than 1 day, so that all the daughter - will be made relatively promptly. -
    • - In cases where the above condition is not met an * is put next to the - nuclide name to warn that the daughter production has not been accounted - for. In most cases the daughter is in a simple decay equilibrium. -
    • - Where the decay product is a new nuclide a line has been added to the - database to account for this. This production mode is indicated in - the reaction column by 'b'. Where both m and g state contribute to daughter - production it is simplified to a single parent, that with the greater - cross-section or that with the longer half-life together with the sum - of the cross-sections. -
    • - In a few cases where the parent nuclide t1/2 is very short all production - is assigned to the daughter and no entry is made for the parent, as - noted in the comments column. -
    • - No correction for neutron burn up has been made. -
    • - Most cross-section data is from IAEA 273. -
    • - Fast neutron data from NBSIR 85-3151, Compendium of Benchmark Neutron Fields - is for reaction above the Cd cutooff, .4eV. Noted in comment column. -
    • - Fast neutron reaction data from IAEA 273 has been weighted by a unit fluence - fast maxwellian spectrum as described in NBSIR 85-3151, but no further - weighting for a 1/v or thermal component has been made. Only selected - reactions have been included. -
    • - Reaction = b indicates production via decay from an activation produced parent. -
    • - Notation on reaction product name: -
      m, m1, m2
      - indicate metastable states. Decay may be the ground state or another nuclide. -
      +
      - indicates radioactive daughter production already included in daughter listing - several parent t1/2's required to acheive calculated daughter activity. - All activations are assigned at end of irradiation. - In most cases the added activity to the daughter is small. -
      *
      - indicates radioactive daughter production NOT calculated, approx - secular equilibrium. -
      s
      - indicates radioactive daughter of this nuclide in secular equilibrium - after several daughter t1/2's. -
      t
      - indicates transient equilibrium via beta decay. Accumulation of that nuclide - during irradiation is separately calculated. -
      -
    -
    - -
    -

    Cadmium ratio

    -

    Units: none

    -

    - Samples in the rabbit tubes can be shielded with cadmium to reduce the thermal - flux while leaving the epithermal flux mostly unchanged. The cadmium ratio - determines the degree of reduction in the scattering cross sections, corresponding - to the reduced flux. This value is unitless. Use a value of 0 for beamline - experiments. -

    -
    - -
    -

    Thermal/fast ratio

    -

    Units: none

    -

    - When performing neutron activation analysis in a rabbit tube, the additional - fast neutron activations need to be determined. The thermal/fast ratio is - used to determine the fast neutron flux from the thermal flux equivalent for - the given rabbit tube. The resulting fast flux is (thermal flux)/(thermal/fast ratio). - This value is unitless. Use a value of 0 for beamline experiments. -

    -
    - -
    -

    Material mass

    -

    Units: g, kg, mg or ug

    -

    - The total neutron activation depends on the mass of the individual - isotopes in the sample and the total time in the beam. All activation - calculations assume a thin plate sample, with all parts of the sample - exposed to full flux during activation, and no self-shielding when - estimating the activation level outside the beam. -

    -
    - -
    -

    Exposure

    -

    Units: h m s d w y

    -

    - Exposure is the duration of the exposure at the given flux. Activation - will be accumulated over that time, with decay beginning the moment the - sample is activated. Time defaults to hours, but can be set to - hours, minutes, seconds, days, weeks or years by adding h, m, s, d, w, or y - to the value respectively. -

    -
    - -
    -

    Decay

    -

    Units: h m s d w y OR yyyy-mm-dd hh:mm:ss

    -

    - The sample begins to decay immediately, even while it is being activated. - The decay field allows you to specify how long since the sample - was removed from the beam. The default is hours, but can be set to - hours, minutes, seconds, days, weeks or years by adding h, m, s, d, w, or y - to the value respectively. - We always compute the activation level when the sample is removed from the beam, - and at 1 hour, 1 day and 15 days post activation. -

    -

    - Instead of saying how long the sample activation has decayed, you can use - the time that the sample was removed from the beam. Times are given as - year-month-day hour:minute:second. - Approximate times are allowed, such as 2010-03 for March, 2010. This is - equivalent to 2010-03-31 23:59:59, which is the end of March so that the - activation estimate will be conservative. This is the most activation - consistent with the sample being on the beam sometime in March, 2010. - Times are specified in US/Eastern. Add "Z" after the time of day to - indicate universal coordinated time (UTC), or add a timezone offset such - as "+01" for +1 hours in France in winter, when daylight savings time is - not in effect. -

    -

    Examples

    - - - - - - - - - - - - - -
    If you type:This is equivalent to:
    2 m2 minutes ago
    11 hour ago
    2.5w2 and a half weeks ago
    3 y3 years ago
    2015-01-02 21:45:00January 2, 2015 at 9:45 PM US/Eastern
    2010-03March 31, 2010 at 11:59:59 PM US/Eastern
    2010-7-5 12:23July 5, 2010 at 12:23:59 PM US/Eastern
    2015-01-02 21:45:00ZJanuary 2, 2015 at 9:45 PM UTC
    2015-01-02 21:45:00-0600January 2, 2015 at 9:45 PM US/Central
    2015-08-02 21:45:00-0500August 2, 2015 at 9:45 PM US/Central
    -
    - -
    -

    Mass density

    -

    Units: g/cm3 or A3

    -

    - Density is used to compute absorption, transmission and scattering. -

    -
    from formula
    -
    Leave the density field blank and add -
    @
    + density - to the end of the formula, where density is in g/cm3. - For compounds with specific isotopes, you can use the density of the - naturally occurring compound as -
    @
    + density +
    n
    - and the isotope specific density will be computed. Density defaults to - 1 g/cm3, or for pure elements, the natural density given in - the periodic table is used. - -
    D2O@1n
    or -
    D2O@1.11
    -
    -
    g/cm3
    -
    Enter the density by itself, which will be interpreted as g/cm3, or - equivalently, kg/L. No units are needed. If the value is - density +
    n
    then it is density of the the - naturally occuring compound and the isotopic density will be computed. -
    D2O has a natural density of -
    1n
    and an isotopic density of -
    1.11
    -
    -
    cell volume
    -
    Enter a number followed by A3 for Å3. Be sure that your - formula contains the correct number of atoms for the unit cell, possibly by - using n(formula), where n is 6 for hexagonal close packed, 4 for face centered - cells, 2 for body centered and base centered cells, or 1 for simple cells. -
    4NaCl has a cell volume of -
    179.4 A3
    -
    -
    crystal lattice parameters
    -
    Enter lattice parameters "a:n b:n c:n alpha:n beta:n gamma:n" - where a, b, c are in Å and α, β, γ are in degrees. - If not specified, b and c default to a. Ratios can also be used, - so that "b/a:n" gives b=n*a, and "c/a:n" gives c=n*a. Angles - α, β, and γ default to 90°. Be sure that the - formula contains the correct number of atoms for the unit cell. -
    4NaCl has a cubic lattice with -
    a:5.6402
    -
    -
    -
    - -
    -

    Thickness

    -

    Units: cm

    -

    - The material thickness in cm is used to determine sample transmission, - or how much beam will be absorbed by the sample or scattered incoherently. - Leave it at 1 cm if you do not need this information. -

    -
    - -
    -

    Source neutrons

    -

    Units: Ang, meV or m/s

    -

    - The energy of the source neutrons will affect the absorption cross section - and hence the penetration depth and sample attenuation. Energy can be - expressed as wavelength in Å, as energy in meV, or as neutron - velocity in m/s. - Neutron cross sections are tabulated - at 1.798 Å = 25.3 meV = 2200 m/s, with an assumed 1/v dependence for - the absorption cross section (Rauch 2003, - Sears 2006). -

    - For heavier isotopes (Cd, Hf, rare earths) and/or shorter wavelengths - (below 1 Å) there are neutron resonances - in the thermal range. For common rare-earth isotopes the energy-dependent - coherent and absorption cross sections tabulated in - Lynn and Seeger 1992 are used. - Incoherent scattering will be understimated for these elements. - Resonances for 113Cd and 180Ta are ignored. -

    - There is also a wavelength dependence for single phonon interactions which - gives rise to significant inelastic scattering for lighter isotopes (H, D) - and/or longer wavelengths (above 5 Å). This factor is both - temperature and material dependent and will not be included - in the scattering calculations. In particular, penetration length and - transmitted flux are going to be significantly overestimated. -

    -
    - -
    -

    Source X-rays

    -

    Units: Ang, keV or Ka

    -

    - X-ray absorption and scattering are computed from the energy dependent - atomic scattering factors (Henke 1993). - Energy can be expressed as wavelength in Å, as energy in keV, or - using an element name for the Kα emission line2 for - that element (Deslattes 2003). -

    -
    - -
    -

    References

    -
      -
    1. - CIAAW. Isotopic compositions of the elements 2021. Available online - at www.ciaaw.org - Bölke, et al. (2005). - [atomic weights, - isotopic abundance] -
    2. -
    3. - Deslattes, R.D.; Kessler, Jr., E.G.; Indelicato, P.; de Billy, L.; Lindroth, E. and Anton, J. (2003). - Rev. Mod. Phys. 75, 35-99. - [xray emission lines] -
    4. -
    5. - Henke, B.L.; Gullikson, E.M. and Davis, J.C. (1993). - X-ray interactions: - photoabsorption, scattering, transmission, and reflection at E=50-30000 eV, Z=1-92, - Atomic Data and Nuclear Data Tables Vol. 54 (no.2), 181-342. - [xray cross sections] -
    6. -
    7. - IAEA (1987). - Handbook on Nuclear Activation Data. - TR 273 (International Atomic Energy Agency, Vienna, Austria). - [tech report] -
    8. - -
    9. - Kienzle, P. A. (2008). - Extensible periodic table - [Computer Software]. - https://periodictable.readthedocs.io. - [calculator source, - web service source] -
    10. -
    11. - Lynn, J.E. and Seeger, P.A. (1990). - Resonance effects in neutron scattering lengths of rare-earth nuclides. - Atomic Data and Nuclear Data Tables 44, 191-207. - doi:10.1016/0092-640X(90)90013-A - [rare earth scattering lengths] -
    12. - Rauch, H. and Waschkowski, W. (2003). - Neutron Scattering Lengths in ILL Neutron Data Booklet (second edition), - A.-J. Dianoux, G. Lander, Eds. - Old City Publishing, Philidelphia, PA. pp 1.1-1 to 1.1-17. - [booklet, - neutron cross sections] -
    13. -
    14. - Sears, V. F. (2006). "Scattering lengths for neutrons" In Prince, E. Ed. - International Tables for Crystallography Volume C: Mathematical, Physical and Chemical Tables" - Kluwer Academic Publishers, pp 444-454. - doi:10.1107/97809553602060000103 - [scattering calculations] -
    15. -
    16. - Shleien, B.; Slaback, L.A. and Birky, B.K. (1998). - Handbook of health physics and radiological health. - Williams & Wilkins, Baltimore. - [activation data] -
    17. -
    -
    - -
    -

    History

    -
    -
    2024-12-03 v2.0.0
    Update mass and abundance tables, and physical constant values -
    neutron cross section updates for H, He, C, O, Zn, Kr, Sn, Xe, Sm, Eu, Ir, Pb, Bi -
    X-ray cross section updates for Pt, Cr, Nb, Y, Er -
    208Pb activation scaled by 0.001 (value was reported in mbarns but added as barns) -
    -
    2024-03-22 v1.7.0
    Mixture formulas allow wt% and vol%. -
    Formulas allow unicode subscripts such as H₂O. -
    FASTA sequences (aa: rna: dna:) allowed as mixture components. -
    FASTA calculations updated. -
    Use correct halflife for Tm-171, Ho-163 and W-188 activation products. -
    Improve numerical precision of activation calculations. -
    -
    2021-04-21 v1.6.0
    Support energy-dependent rare earth elements. -
    Use complex scattering length bc when computing - σc = 4π |bc|2/100 and - σi = σs - σc. -
    -
    2020-10-29 v1.5.3
    Change field labels from 'time on/off beam' to 'exposure/decay duration'.
    -
    2020-01-22
    Restore support for Internet Explorer 10 and 11.
    -
    2019-12-02
    Fix cutoff=0 handling in URL.
    -
    2019-11-14 v1.5.2
    Correct units on activity table: nCi becomes uCi. -
    Elemental carbon density changed to 2.2 to match CXRO, CRC and RSC. -
    -
    2019-11-04
    Update neutron refs with links to ILL data book and Table for Crystallography.
    -
    2019-09-16
    Improve help system: can now scroll between sections.
    -
    2019-09-11 v1.5.1
    Include notes on activation calculation.
    -
    2019-08-27
    Change default cutoff to 0.5 nCi.
    -
    2018-01-12
    Make activation table sortable.
    -
    2017-05-11 v1.5.0
    Improved support for printing tables. -
    Support for biomolecules with labile hydrogen (FASTA format). -
    Mixture by mass and volume, e.g., 5 g NaCl // 50 mL H2O@1 -
    Multi-layer materials, e.g., 5 um Si // 3 nm Cr // 8 nm Au -
    Compute incoherent cross section from coherent and total. -
    -
    2016-12-07
    Use exponential notation for all activity levels.
    -
    2015-10-20
    Allow decay time to be calculated from timestamp..
    -
    2014-03-20 v1.4.1
    Default to isotopic density.
    -
    2013-11-05
    Support for X-ray scattering.
    -
    2013-04-17 v1.3.8
    Initial release.
    -
    -
    - - - -
    - -
    - -
    -
    -
    - -
    - - - From 32e3e1da063e5996df8ec4e8db9932c120fe96b3 Mon Sep 17 00:00:00 2001 From: bbm Date: Wed, 25 Feb 2026 16:55:57 -0500 Subject: [PATCH 38/66] adding shared css --- activation/css/footer.css | 10 ++ activation/css/loading-spinner.css | 30 +++++ activation/css/main.css | 186 +++++++++++++++++++++++++++++ activation/css/nist-header.css | 56 +++++++++ 4 files changed, 282 insertions(+) create mode 100644 activation/css/footer.css create mode 100644 activation/css/loading-spinner.css create mode 100644 activation/css/main.css create mode 100644 activation/css/nist-header.css diff --git a/activation/css/footer.css b/activation/css/footer.css new file mode 100644 index 0000000..807fb95 --- /dev/null +++ b/activation/css/footer.css @@ -0,0 +1,10 @@ +.footer { + display: flex; + justify-content: space-between; + align-items: center; + padding: 0.5rem; +} + +.footer .contacts { + flex: 1; +} diff --git a/activation/css/loading-spinner.css b/activation/css/loading-spinner.css new file mode 100644 index 0000000..235b010 --- /dev/null +++ b/activation/css/loading-spinner.css @@ -0,0 +1,30 @@ +.loader .spinner { + border: 4px solid #f3f3f3; /* Light grey background */ + border-top: 4px solid #3498db; /* Blue "spinning" part */ + border-radius: 50%; + width: 30px; + height: 30px; + animation: spin 1s linear infinite; +} + +.loader.finished { + display: none; +} + +.loader { + display: flex; + align-items: center; + gap: 10px; + margin: 0 auto; + width: fit-content; + padding: 1em; +} + +.loader.not-started { + display: none; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} diff --git a/activation/css/main.css b/activation/css/main.css new file mode 100644 index 0000000..b139fea --- /dev/null +++ b/activation/css/main.css @@ -0,0 +1,186 @@ +html, body { + height: 100%; + margin: 0; + padding: 0; +} +@media print +{ + html, body { font-size: 10pt !important; height: unset; } + table, caption, th, td { + font-size: 10pt !important; + /* border: 0.1pt solid lightgray !important; */ + border: none !important; + } + .no-print { display: none !important; height: 0; } + .no-print *{ display: none !important; height: 0; } + .print-only { display: block !important; } + .print-only *{ display: block !important; } +} +.print-only { display: none; } +.print-only *{ display: none; } + +p { margin-bottom: 0; } +.footer p { margin-top: 0; } + +/* body { font-size: 0.9em; } */ +.disabled { opacity: 0.3; } +label { font-weight: inherit; } +.controls input { width: 100%; } +table { margin: 0; padding: 0; border-spacing: 0; border-color: lightgray; } +caption, td, th { padding: 0 0.5em 0 0.5em; } +th { vertical-align: baseline; } +tbody tr:nth-child(2n) th, tbody tr.even th, +tbody tr:nth-child(2n) td, tbody tr.even td, +ul li:nth-child(2n), ol li:nth-child(2n) { background: inherit; /* background: none repeat scroll 0 0 #F3F3F9; */ } +table.tablesorter thead tr .headerSortable { + padding-right: 2em; /* space for sort arrows */ + cursor: pointer; +} +table.tablesorter thead tr .headerSortable::after { + content: " \25B4\25BE"; /* ▴▾ */ + opacity: 0.4; +} +table.tablesorter thead tr .headerSortable.headerSortUp::after { + content: " \25B2"; /* ▲ */ + opacity: 1; +} +table.tablesorter thead tr .headerSortable.headerSortDown::after { + content: " \25BC"; /* ▼ */ + opacity: 1; +} + +/* output markup */ +.error { color: red; } +p.disclaimer { color: darkred; font-size:1.2em; } +.activity_unusual { background-color:wheat; } +/* .activity_normal { background-color: lightred; } */ + +#id_chemical_formula { width: 30em; } + +div.cutoff { display: block; } +div.nocutoff { display: none; } +button.activity_button { float: right; } + +/* #wrapper { + height: 100%; + display: flex; + flex-direction: column; +} */ + +/* frame layout */ +#content-frame { + display: flex; + flex-direction: row; + width: 100%; +} + +#activation-frame { + width:30em; +} + +#help-frame { + position: relative; + flex: 1; + /* min-width:10em; max-width:40em; */ + overflow-y:scroll; +} + +#help-wrapper { + position: absolute; + padding-left:1em; + padding-right: 1em; + margin-right:0em; +} + +#help-wrapper .word-break { + word-break: break-all; +} + +#results-frame { + overflow: auto; + flex: 1; + border-top:#005ea2 1px solid; + border-bottom:#005ea2 1px solid; +} + +div.control-group { margin-left: 0.5em; vertical-align: bottom; } +/* div.control-group { height: 3ex; width: 15em; } */ +/* .help starts display:none so that size is initially zero. */ +.help { display:block; } +/*.help dl { margin-left: 30em; } +.help ol { margin-left: 30em; } +.help p { margin-left: 30em; } +*/ +.help h3 { margin-top: 0.25em; } +.help dd { margin-left: 1em; } +.help dt { margin-left: 0em; padding: 0.3em; font-weight: bold; } +.help ol { list-style-position: inside; padding-left: 0em; } +.help li { margin-left: 0em; margin-bottom: 1ex; } +.help div.bold { font-weight: bold; display: inline; } +.help div.entrytext { + display:inline; + font-weight:bold; + font-style:oblique; +} +.help div.example:before { content:"Example: "; } + +/* fading horizontal rule +modified from http://konigi.com/tools/css-techniques-horizontal-rules +*/ +.help hr { + width: 100%; + height: 1px; + margin: 2.4em 0; + border: none; + background: #ddd; + background-image: -webkit-gradient( + linear, + left bottom, + right bottom, + color-stop(0, rgb(255,255,255)), + color-stop(0.1, rgb(221,221,221)), + color-stop(0.9, rgb(221,221,221)), + color-stop(1, rgb(255,255,255)) + ); + background-image: -moz-linear-gradient( + left center, + rgb(255,255,255) 0%, + rgb(221,221,221) 10%, + rgb(221,221,221) 90%, + rgb(255,255,255) 100% + ); +} + +/* dictionary type: value on same line */ +dl.inline { + display: -ms-grid; -ms-grid-template-columns: max-content auto; + display: grid; grid-template-columns: max-content auto; +} +dl.inline dt { + -ms-grid-column-start: 1; + grid-column-start: 1; + padding: 0.1em; +} +dl.inline dd { + -ms-grid-column-start: 2; + grid-column-start: 2; + padding: 0.1em; margin-left: 0.5em; +} + +.panel { border-radius:0.6em; border: 2pt solid gray; margin: 0.5em; padding: 0.5em; } +.panel h3 { margin-top: -1em; margin-bottom: 0.3em; font-size: 1em; } +.panel h3 .text { background: white; margin-left: 1em; padding: 0 0.3em 0 0.3em; } +.panel { position: relative; } +.panel .btn { position:absolute; right: 1em; top: 0.75em;} +/* .panel .btn { position:absolute; top:1em; right:1em; } */ + +/* Keep constant baseline spacing even with superscript/subscript */ +sup, sub { + height: 0; + line-height: 1; + vertical-align: baseline; + _vertical-align: bottom; + position: relative; +} +sup { bottom: 1ex; } +sub { top: .5ex; } diff --git a/activation/css/nist-header.css b/activation/css/nist-header.css new file mode 100644 index 0000000..d75f88d --- /dev/null +++ b/activation/css/nist-header.css @@ -0,0 +1,56 @@ +@font-face { + font-family:"Source Sans Pro Web"; + font-style:normal; + font-weight:400; + font-display:fallback; + src: url(https://www.nist.gov/libraries/nist-component-library/dist/fonts/source-sans-pro/sourcesanspro-bold-webfont.woff2) format("woff2"), + url(https://www.nist.gov/libraries/nist-component-library/dist/fonts/source-sans-pro/sourcesanspro-regular-webfont.woff) format("woff"), + url(https://www.nist.gov/libraries/nist-component-library/dist/fonts/source-sans-pro/sourcesanspro-regular-webfont.ttf) format("truetype"); +} + +.ncnr-nist-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 1rem; + background-color: #f5f5f5; + border-bottom: 1px solid #ddd; + background: url(https://www.nist.gov/libraries/nist-component-library/dist/img/pattern/bg_pattern.png) #006dbc; + position: relative; +} + +.ncnr-nist-header::before { + content: ""; + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + background-image: linear-gradient(to right,transparent,#005ea2); +} + +.ncnr-nist-header h2 { + margin: 0; + font-family: Source Sans Pro Web; + font-size: 1.86rem; + line-height: 1.1; + text-decoration: none; + padding-left: 1rem; + text-transform: uppercase; + font-weight: 700; +} + +.ncnr-nist-header a { + text-decoration: none; + color: #FFF; + z-index: 2; + position: relative; +} + +.ncnr-nist-header img { + position: relative; + padding-right: 2rem; + max-width: 100px; + height: auto; + z-index: 2; +} From 28bd6e2123a64d49d4ac539f12d96695a68ae235 Mon Sep 17 00:00:00 2001 From: bbm Date: Wed, 25 Feb 2026 16:56:07 -0500 Subject: [PATCH 39/66] use shared css --- activation/index.html | 269 +-------------------- activation/index_pyodide_optimized.html | 308 +----------------------- 2 files changed, 15 insertions(+), 562 deletions(-) diff --git a/activation/index.html b/activation/index.html index 0a1bfea..c646860 100644 --- a/activation/index.html +++ b/activation/index.html @@ -4,267 +4,14 @@ Neutron Activation and Scattering Calculator + + + + - - - - - - - @@ -32,300 +36,6 @@ - - - - - - -
    From f07c4d10aa9db4a837a654ff764dd5496f392e74 Mon Sep 17 00:00:00 2001 From: bbm Date: Fri, 27 Feb 2026 09:40:18 -0500 Subject: [PATCH 40/66] capture errors and return to client, like is done in cgi interface --- activation/webworker.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/activation/webworker.js b/activation/webworker.js index 3e4fa7c..f8c6b5f 100644 --- a/activation/webworker.js +++ b/activation/webworker.js @@ -53,7 +53,16 @@ self.onmessage = async (event) => { let python = ` request = json.loads('${json_data}') form = FakeFieldStorage(request) - json.dumps(nact.cgi_call(form)) + try: + response = nact.cgi_call(form) + except Exception: + response = { + 'success': False, + 'version': periodictable.__version__, + 'detail': {'query': error()}, + 'error': 'unexpected exception', + } + json.dumps(response) `; //console.log('python:', python); let results = await self.pyodide.runPythonAsync(python); From 3ea73f19bd9343eb6c62631e08c993b63e0ddc1b Mon Sep 17 00:00:00 2001 From: bbm Date: Fri, 27 Feb 2026 09:41:05 -0500 Subject: [PATCH 41/66] move api connection to separate script, and move shared main app code to js file --- activation/index_pyodide_optimized.html | 492 +----------------------- 1 file changed, 7 insertions(+), 485 deletions(-) diff --git a/activation/index_pyodide_optimized.html b/activation/index_pyodide_optimized.html index 67f88ae..3f62f52 100644 --- a/activation/index_pyodide_optimized.html +++ b/activation/index_pyodide_optimized.html @@ -11,488 +11,10 @@ - - - - - + + + @@ -551,7 +73,7 @@

    Neutron Activation

    -
    +
    @@ -562,7 +84,7 @@

    Neutron Activation

    - + @@ -573,7 +95,7 @@

    Neutron Activation

    -
    +
    @@ -934,7 +456,7 @@

    Material mass

    -
    +

    Exposure

    Units: h m s d w y

    From 1d8054d49d1ac6736c943536194cdc8392c7456f Mon Sep 17 00:00:00 2001 From: bbm Date: Fri, 27 Feb 2026 09:41:19 -0500 Subject: [PATCH 42/66] adding main app code --- activation/calculator_main.js | 450 ++++++++++++++++++++++++++++++++++ 1 file changed, 450 insertions(+) create mode 100644 activation/calculator_main.js diff --git a/activation/calculator_main.js b/activation/calculator_main.js new file mode 100644 index 0000000..12935ef --- /dev/null +++ b/activation/calculator_main.js @@ -0,0 +1,450 @@ +// API comes in from webworker_api.js or form_api.js above +// JQuery ($) is loaded in a script tag as well + +// standard year for activation calculations is 365, not 365.2425 +const HOURS_PER_YEAR = 365*24; // = 365.2425*24; +const ELEMENTS = {"n": 0, "H": 1, "He": 2, "Li": 3, "Be": 4, "B": 5, "C": 6, "N": 7, "O": 8, "F": 9, "Ne": 10, "Na": 11, "Mg": 12, "Al": 13, "Si": 14, "P": 15, "S": 16, "Cl": 17, "Ar": 18, "K": 19, "Ca": 20, "Sc": 21, "Ti": 22, "V": 23, "Cr": 24, "Mn": 25, "Fe": 26, "Co": 27, "Ni": 28, "Cu": 29, "Zn": 30, "Ga": 31, "Ge": 32, "As": 33, "Se": 34, "Br": 35, "Kr": 36, "Rb": 37, "Sr": 38, "Y": 39, "Zr": 40, "Nb": 41, "Mo": 42, "Tc": 43, "Ru": 44, "Rh": 45, "Pd": 46, "Ag": 47, "Cd": 48, "In": 49, "Sn": 50, "Sb": 51, "Te": 52, "I": 53, "Xe": 54, "Cs": 55, "Ba": 56, "La": 57, "Ce": 58, "Pr": 59, "Nd": 60, "Pm": 61, "Sm": 62, "Eu": 63, "Gd": 64, "Tb": 65, "Dy": 66, "Ho": 67, "Er": 68, "Tm": 69, "Yb": 70, "Lu": 71, "Hf": 72, "Ta": 73, "W": 74, "Re": 75, "Os": 76, "Ir": 77, "Pt": 78, "Au": 79, "Hg": 80, "Tl": 81, "Pb": 82, "Bi": 83, "Po": 84, "At": 85, "Rn": 86, "Fr": 87, "Ra": 88, "Ac": 89, "Th": 90, "Pa": 91, "U": 92, "Np": 93, "Pu": 94, "Am": 95, "Cm": 96, "Bk": 97, "Cf": 98, "Es": 99, "Fm": 100, "Md": 101, "No": 102, "Lr": 103, "Rf": 104, "Db": 105, "Sg": 106, "Bh": 107, "Hs": 108, "Mt": 109, "Ds": 110, "Rg": 111, "Cn": 112, "Nh": 113, "Fl": 114, "Mc": 115, "Lv": 116, "Ts": 117, "Og": 118}; +let ACTIVE_BUTTON = "activation"; +// Parse environment variables "index.html?cutoff=...&abundance=..." +function getURLParameter(name) { + var value = decodeURIComponent( + (RegExp(name + '=' + '(.+?)(&|$)').exec(location.search)||[,null])[1] + ); + return value; +} +// From Doron Grinzaig (2017-11-21) +// https://stackoverflow.com/questions/14129953/how-to-encode-a-string-in-javascript-for-displaying-in-html +function sanitize(html) { + return $('

    ').text(html).html(); +} +function format_activation_value(v, cutoff) { + return (v= 1000.) return v.toFixed(0)+' g'; + else if (v >= 1.) return v.toFixed(3)+' g'; + else if (v >= 1e-3) return (1e3*v).toFixed(3)+' mg'; + else if (v >= 1e-6) return (1e6*v).toFixed(3)+' ug'; + else if (v >= 1e-9) return (1e9*v).toFixed(3)+' ng'; + else return v.toExponential(4)+' ng'; +} +function format_time(v) { + if (v >= HOURS_PER_YEAR) return nice_number(v/HOURS_PER_YEAR)+' yrs'; + else if (v >= 48 || v == 24) return nice_number(v/24)+' days'; + else if (v >= 2 || v == 1) return nice_number(v)+' hrs'; + else if (v >= 2/60. | v == 1/60.) return nice_number(v*60)+' min'; + else return (v*3600).toPrecision(3)+' sec'; +} +function parse_half_life(s) { + var y = HOURS_PER_YEAR*3600; + var units = {Gy: 1e9*y, My: 1e6*y, ky: 100*y, y: y, d: 24*3600, h: 3600, m: 60, s: 1}; + var a = s.split(" "); + var value_str = a[0], units_str = a[1]; + return parseFloat(value_str) * units[units_str]; +} +function parse_isotope(s) { + var a = s.split("-"); + var element = a[0], isotope = a[1]; + return ELEMENTS[element] + parseInt(isotope)/1000; +} +$.tablesorter.addParser({ + id: 'isotope', + is: function (s) { return /^ *[A-Z][a-z]?-[0-9]+[sm+]* *$/.test(s); }, + format: function (s) { return parse_isotope(s); }, + type: 'numeric' +}); +$.tablesorter.addParser({ + id: 'half-life', + is: function (s) { return /^ *[0-9.+-eE]+ *[kMG]?[smhdy] *$/.test(s); }, + format: function (s) { return parse_half_life(s); }, + type: 'numeric' +}); +$.tablesorter.addParser({ + id: 'float', + is: function (s) { return /^ *[0-9.+-eE]+ *$/.test(s); }, + format: function (s) { return s == '---' ? 0. : parseFloat(s); }, + type: 'numeric' +}); + +function parse_url_parameters() { + // Parse URL parameters. + var cutoff_par = getURLParameter('cutoff'); + if (cutoff_par==='null') CUTOFF = 0.0005; + else CUTOFF = Number(cutoff_par); + if (isNaN(CUTOFF)) { // IE doesn't support Number.isNaN + show_error("

    cutoff="+sanitize(cutoff_par)+" in URL should be floating point μCi; default is 0.0005.

    "); + CUTOFF = 0.0005; + } + CUTOFF_Bq = CUTOFF*37000; + + var decay_par = getURLParameter('decay'); + if (decay_par==='null') DECAY_LEVEL = CUTOFF>0?CUTOFF:0.0005; + else DECAY_LEVEL = Number(decay_par) + if (isNaN(DECAY_LEVEL)) { // IE doesn't support Number.isNaN + show_error("

    decay="+sanitize(decay_par)+" in URL should be floating point μCi; default is cutoff.

    "); + DECAY_LEVEL = CUTOFF>0?CUTOFF:0.0005; + } + + var abundance_par = getURLParameter('abundance'); + if (abundance_par==='null') ABUNDANCE = "IAEA"; + // CRUFT: periodictable no longer uses NIST 2001 data for abundance + else if (abundance_par==='NIST') ABUNDANCE = "IUPAC"; + else ABUNDANCE = abundance_par; + if (ABUNDANCE!=="IUPAC" && ABUNDANCE!=="IAEA") { + show_error("

    abundance="+sanitize(abundance_par)+" in URL should be IUPAC or IAEA; default is IAEA

    "); + ABUNDANCE = "IAEA"; + } +} + +function enable_forms() { + // Enable forms; they are disabled by default so that noscript users + // can't do anything. + $('.container').removeClass("disabled"); + $('#id_chemical_formula').removeAttr("disabled"); + $('#id_submit_scat').removeAttr("disabled"); + $('#id_submit_act').removeAttr("disabled"); + $('a').each(function(){ this.tabIndex = -1; }); + $('.help').each(function(){ $(this).append("
    "); }); + $('input[type=text]').keydown(function(e) { + if (e.keyCode == 13) { + e.preventDefault(); + submit_query(ACTIVE_BUTTON); + } + }); + $('input[type=text]').focus(function(e) { + var panel = $(this).closest('.panel')[0].id; + if (panel == "scattering-panel") { + ACTIVE_BUTTON = "scattering"; + } else if (panel == "activation-panel") { + ACTIVE_BUTTON = "activation"; + } + } ); + + //$("#id-activationForm").submit(submit_query); + $("#id-activationForm").submit(function(event) {event.preventDefault();}); + $('#id_submit_scat').click(function() { submit_query('scattering'); }); + $('#id_submit_act').click(function() { submit_query('activation'); }); +} + +function submit_query(target){ + ACTIVE_BUTTON = target; + + // activate the loader spinner: + document.querySelector("div.loader").classList.remove("not-started"); + + const form = document.getElementById("id-activationForm"); + const formData = new FormData(form); + const data = Object.fromEntries(formData.entries()); + + // populate rest array and remove time_off from data + data.rest = ["0","1","24","360",data.pop("time_off")]; + const query = { + calculate: target, + decay: DECAY_LEVEL, + abundance: ABUNDANCE, + ...data + }; + API.submit(query); +} + +function cssrule(class_name){ + var ss = document.styleSheets; + for (var i=0; i= cutoff); + columns.push(row.levels[j]) + } + if (active) data.rows.push(columns); + } + + var activity_header, activity_button; + if (cutoff>0) { + activity_header = 'Activity (μCi) above ' + cutoff.toExponential(4) + ' μCi'; + activity_button = ''; + } else if (CUTOFF>0) { + activity_header = 'Activity (μCi)'; + activity_button = ''; + } else { + activity_header = 'Activity (μCi)'; + activity_button = ''; + } + //add headers to table + content += '\n \n'; + content += ' \n'; + content += ' '; + for (var i in data.headers) { + content += ''; + } + content += '\n \n \n' + var some_unusual = false; + for (var i in data.rows) { + var row_style = ''; + if (data.rows[i][1] === 'b') { + some_unusual = true; + row_style = 'activity_unusual'; + } else if (data.rows[i][2].slice(-1) === 't') { + some_unusual = true; + row_style = 'activity_unusual'; + //} else if (data.rows[i][2].slice(-1) === 's') { + // row_style = 'activity_normal'; + } else { + row_style = 'activity_normal'; + } + content += ` `; + for (var j=0; j =4) { + content += ''; + } else { + content += ''; + } + } + content += '\n'; + } + content += ' \n \n '; + for (var j=0; j < act.total.length; j++) { + content += ''; + } + content += '\n'; + if (some_unusual) { + content += ' \n'; + } + content += ' \n
    '+activity_header+activity_button+'
    ' + data.headers[i] + '
    '+format_activation_value(data.rows[i][j], cutoff)+'' + data.rows[i][j] + '
    total activity'+format_activation_value(act.total[j], cutoff)+'
    b reaction activity is slightly underestimated; it does not include decay of transients after removal from beam.
    \n'; + return content; +} +function show_error(error_html) { + var content = '

    \n'; + content += error_html; + content += '
    \n'; + $(content).prependTo('div[id=results]'); +} +function process_response(ldata) { + //console.log(ldata); + if (typeof(ldata)==="string") ldata=$.parseJSON(ldata); + if (!ldata.success) { + var error_html = ''; + var keys = Object.keys(ldata.detail); + keys.sort(); + for (i = keys.length-1; i >= 0; i--) { + error_html += '
    Error ' +sanitize(keys[i])+': '+sanitize(ldata.detail[keys[i]])+'
    \n'; + } + show_error(error_html); + return; + } + + var act = ldata.activation; + var sample = ldata.sample; + var scat = ldata.scattering; + var xscat = ldata.xray_scattering; + var content = '

    \n'; + + if (typeof act == 'undefined') { + // do nothing if not returned + } else if ("error" in act) { + // Restricted title + content += '

    activation calculation failed with

    \n'+sanitize(act.error)+'
    \n'; + } else { + // Full title + content += '

    Activation of ' + sample.name + ' after ' + format_time(act.exposure)+' at '+act.flux.toPrecision(3)+' n/cm2/s

    \n'; + + // Disclaimer + content += '

    Estimated activation only. All samples must be evaluated by NIST Health Physics to determine if and how the sample can be removed from the NCNR.

    '; + + // Atoms + //var formula = sample.formula; + var formula = sanitize(sample.formula_latex).replace(/\$_{([^}]*)}\$/g, '$1'); + content += '

    Sample in beam: ' + format_mass(sample.mass) + ' of ' + formula + '\n'; + + // Rabbit parameters + if (act.Cd > 0 || act.fast > 0) { + content += '
    Rabbit system: Cd ratio = ' + act.Cd + ', thermal/fast ratio = ' + act.fast + '\n' + } + + // Decay time + if (act.decay_time > 0) { + content += '
    Time to decay below '+act.decay_level.toExponential(4)+' μCi is '+format_time(act.decay_time)+'.\n'; + } + content += '

    \n' + + // Activation table + if (CUTOFF == 0.) { + content += activation_table(act, 0.); + } else { + content += '
    \n' + activation_table(act, CUTOFF) + '
    \n'; + content += '
    \n' + activation_table(act, 0.) + '
    \n'; + } + } + + + if (typeof scat == 'undefined') { + // do nothing if not returned + } else if ("error" in scat) { + content += '

    neutron scattering calculation failed with

    \n'+sanitize(scat.error)+'
    \n'; + } else if ("error" in xscat) { + content += '

    X-ray scattering calculation failed with

    \n'+sanitize(xscat.error)+'
    \n'; + } else { + // Drop coherent cross section from penetration depth calculation. + // An alternative formulation, based on total scattering b, would be + // penetration = 1/(1/scat.penetration - scat.xs.coh), which perhaps + // takes diffuse coherent scattering into account [Glinka 2011]. + var penetration = 1 /(scat.xs.abs+scat.xs.incoh); + var transmission = 100*Math.exp(-sample.thickness/penetration); + var flux_str = $('input:text[id=id_flux]').val(); + var transmitted_flux = parseFloat(flux_str)*transmission/100.0; + + // Mass density + var density_str = $('input:text[id=id_density]').val(); + content += "

    Scattering from " + sanitize(sample.name) + "

    "; + + // Source neutrons + content += "

    Source neutrons: " + + scat.neutron.wavelength.toFixed(3) + " Å" + + " = "+scat.neutron.energy.toFixed(2) + " meV" + + " = "+scat.neutron.velocity.toFixed(0) + " m/s
    "; + content += "Source X-rays: " + + xscat.xray.wavelength.toFixed(3) + " Å" + + " = " + xscat.xray.energy.toFixed(3) + " keV
    "; + // Atoms + //var formula = sample.formula; + var formula = sanitize(sample.formula_latex).replace(/\$_{([^}]*)}\$/g, '$1'); + content += "Sample in beam: " + formula + " at " + sample.density.toFixed(2) + " g/cm3"; + if (density_str.indexOf(':') !== -1) content += " from lattice "+sanitize(density_str); + content += "

    "; + + // Neutron scattering + content += '\n '; + content += ''; + content += ''; + content += ''; + content += ''; + content += '\n '; + content += ''; + content += "'; + content += ''; + content += "'; + content += '\n '; + content += ''; + content += "'; + content += ''; + content += "'; + content += '\n '; + content += ''; + content += ''; + content += ''; + content += ''; + content += '\n '; + content += '\n
    1/e penetration depth
    (cm)
    Scattering length density
    (10-62)
    Scattering cross section
    (1/cm)
    X-ray SLD
    (10-62)
    abs'+(1/scat.xs.abs).toFixed(3)+'real"+scat.sld.real.toFixed(3)+'coh'+scat.xs.coh.toFixed(3)+'real"+xscat.sld.real.toFixed(3)+'
    abs+incoh'+(1/(scat.xs.incoh+scat.xs.abs)).toFixed(3)+'imag"+(-scat.sld.imag).toFixed(3)+'abs'+scat.xs.abs.toFixed(3)+'imag"+(-xscat.sld.imag).toFixed(3)+'
    abs+incoh+coh'+scat.penetration.toFixed(3)+'incoh'+scat.sld.incoh.toFixed(3)+'incoh'+scat.xs.incoh.toFixed(3)+''+''+'
    '; + + // Neutron transmission + content += '

    Neutron transmission is ' + +(transmission>=2||transmitted_flux2/s' + +' for a '+sanitize(flux_str)+' n/cm2/s beam.\n'; + + // Contrast match + if (scat.contrast_match.D2O_fraction === null) { + content += "

    "; + } else { + content += '
    Contrast match point: '; + if (scat.contrast_match.D2O_fraction < 0) { + content += '< 0% D2O

    \n'; + } else if (scat.contrast_match.D2O_fraction > 1) { + content += '> 100% D2O

    \n'; + } else { + console.log(scat.sld, scat); + content += (scat.contrast_match.D2O_fraction*100).toFixed(1) + + '% D2O by volume (real SLD = ' + + scat.contrast_match.sld.toFixed(3) + + '×10-62)

    \n'; + } + } + } + + + // End of div + content += '
    \n'; + + var $new = $(content).prependTo('div[id=results]'); //add to the dom + // Start table unsorted so that b reactions follow transients as they + // do in the activation table. Note that there is no way to get back + // the original order. + $new.find("table").tablesorter(); + scroll_to_result(); +} + +function scroll_to_result(){ + var opt = {behavior: "smooth", block: "nearest"}; + document.getElementById("results").firstChild.scrollIntoView(opt); +} + +// Dynamic help support. Clicking an input field jumps to the +// corresponding section of the help. Input "gork" uses: +// +// and the corresponding help section uses: +//

    Gork Section Title

    ...
    +function help_jump(section_name){ + var section = document.getElementById(section_name); + var frame = document.getElementById('help-frame'); + if (!!section) { + frame.scrollTop = section.offsetTop; // - frame.offsetTop; + } +} + +function setup_help() { + // $('#help-frame').height($('#activation-frame').height()); + $('input').focusin(function(){help_jump("help_"+this.id.slice(3))}); + $('.cite').click(function(event){ + event.preventDefault(); + help_jump(this.getAttribute('href').substring(1)) + }); +} + +function ready_callback() { + document.querySelector("div.loader").classList.add("finished"); +} + +API.initialize(process_response, ready_callback); + +$(document).ready(function () { + parse_url_parameters(); + enable_forms(); + setup_help(); + // var timestamp = (new Date(Date.parse(document.lastModified))).toLocaleDateString(); + // document.getElementById("lastmod-timestamp").innerHTML = timestamp; +}); From 8457a4c30c016f7bccda18641ab8f9be7ceca177 Mon Sep 17 00:00:00 2001 From: bbm Date: Fri, 27 Feb 2026 10:10:14 -0500 Subject: [PATCH 43/66] index.html is the same as the pyodide version, except for API definition --- activation/index.html | 480 +----------------------------------------- 1 file changed, 9 insertions(+), 471 deletions(-) diff --git a/activation/index.html b/activation/index.html index c646860..a516ff3 100644 --- a/activation/index.html +++ b/activation/index.html @@ -12,472 +12,9 @@ - - + + + @@ -507,7 +44,7 @@

    Material

    -
    +
    @@ -536,7 +73,7 @@

    Neutron Activation

    -
    +
    @@ -547,7 +84,7 @@

    Neutron Activation

    - + @@ -558,7 +95,7 @@

    Neutron Activation

    -
    +
    @@ -919,7 +456,7 @@

    Material mass

    -
    +

    Exposure

    Units: h m s d w y

    @@ -1200,6 +737,7 @@

    History

    +
    Initializing calculator...
    From 6f7bbaa7ccdce816e45a0512509723fbf87eab43 Mon Sep 17 00:00:00 2001 From: bbm Date: Fri, 27 Feb 2026 10:10:55 -0500 Subject: [PATCH 44/66] add API for fetch interface (CGI) --- activation/api_fetch.js | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 activation/api_fetch.js diff --git a/activation/api_fetch.js b/activation/api_fetch.js new file mode 100644 index 0000000..1dc9d1a --- /dev/null +++ b/activation/api_fetch.js @@ -0,0 +1,29 @@ +class FetchAPI { + response_callback = null; + url = null; + + initialize (response_callback, ready_callback=() => {}, url="/cgi-bin/nact.py") { + this.response_callback = response_callback; + this.url = url; + ready_callback(); + } + + submit(data) { + const { rest, ...form_data } = data; + const request_body = new URLSearchParams(form_data); + // array handling in old URLSearchParams is a bit tricky, so we do it manually: + rest.forEach((value) => { + request_body.append('rest[]', value); + }); + + fetch(this.url, { + method: "POST", + body: request_body + }) + .then(response => response.json()) + .then(json => this.response_callback(json)) + .catch(error => this.response_callback({'success':false,'detail':{'fetch error':error}})); + } +} + +const API = new FetchAPI(); \ No newline at end of file From 49cbead3a4f0587ac2023c170b52c388e4a0b38d Mon Sep 17 00:00:00 2001 From: bbm Date: Fri, 27 Feb 2026 10:11:17 -0500 Subject: [PATCH 45/66] initialize API after page is done rendering --- activation/calculator_main.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/activation/calculator_main.js b/activation/calculator_main.js index 12935ef..051c59b 100644 --- a/activation/calculator_main.js +++ b/activation/calculator_main.js @@ -138,10 +138,12 @@ function submit_query(target){ const form = document.getElementById("id-activationForm"); const formData = new FormData(form); - const data = Object.fromEntries(formData.entries()); + const initial_data = Object.fromEntries(formData.entries()); + const { time_off, ...data } = initial_data; // destructuring assignment to remove time_off from data + + // populate rest array with time_off from initial data + data.rest = ["0","1","24","360",time_off]; - // populate rest array and remove time_off from data - data.rest = ["0","1","24","360",data.pop("time_off")]; const query = { calculate: target, decay: DECAY_LEVEL, @@ -439,9 +441,9 @@ function ready_callback() { document.querySelector("div.loader").classList.add("finished"); } -API.initialize(process_response, ready_callback); $(document).ready(function () { + API.initialize(process_response, ready_callback); parse_url_parameters(); enable_forms(); setup_help(); From b85432249d583953c53fa728ede57343e4f02d04 Mon Sep 17 00:00:00 2001 From: bbm Date: Fri, 27 Feb 2026 10:11:40 -0500 Subject: [PATCH 46/66] renamed api script --- activation/index_pyodide_optimized.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activation/index_pyodide_optimized.html b/activation/index_pyodide_optimized.html index 3f62f52..71ea5cc 100644 --- a/activation/index_pyodide_optimized.html +++ b/activation/index_pyodide_optimized.html @@ -12,7 +12,7 @@ - + From ffb7a4a1525042b25f885fbec48d1d45a856b991 Mon Sep 17 00:00:00 2001 From: bbm Date: Fri, 27 Feb 2026 10:12:06 -0500 Subject: [PATCH 47/66] adding API for webworker (pyodide) --- activation/api_webworker.js | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 activation/api_webworker.js diff --git a/activation/api_webworker.js b/activation/api_webworker.js new file mode 100644 index 0000000..61e469c --- /dev/null +++ b/activation/api_webworker.js @@ -0,0 +1,29 @@ +class WebWorkerAPI { + response_callback = null; + ready_callback = null; + url = null; + pyodideWorker = null; + + initialize (response_callback, ready_callback=() => {}, url="./webworker.js") { + this.response_callback = response_callback; + this.ready_callback = ready_callback; + this.url = url; + this.pyodideWorker = new Worker(this.url, {type: "module"}); + this.pyodideWorker.onmessage = (event) => { + if ('worker_ready' in event.data) { + this.ready_callback(); + } + else { + this.response_callback(event.data); + } + } + } + + submit(data) { + this.pyodideWorker.postMessage({ + data: data + }); + } +} + +const API = new WebWorkerAPI(); From f7b990fdda9f4b8da6ab79e64af293745fdb83d1 Mon Sep 17 00:00:00 2001 From: bbm Date: Fri, 27 Feb 2026 10:29:14 -0500 Subject: [PATCH 48/66] use dict intput to api_call, convert cgi to dict --- cgi-bin/nact.py | 65 +++++++++++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 24 deletions(-) diff --git a/cgi-bin/nact.py b/cgi-bin/nact.py index 12ae923..9f57258 100755 --- a/cgi-bin/nact.py +++ b/cgi-bin/nact.py @@ -248,39 +248,35 @@ def parse_date(datestring, default_timezone=default_timezone): dt = utc.localize(dt) - timedelta(0, offset) return dt -def cgi_call(form): - #print(form, file=sys.stderr) - #print >>sys.stderr, "sample",form.getfirst('sample') - #print >>sys.stderr, "mass",form.getfirst('mass') - +def api_call(form): # Parse inputs errors = {} - calculate = form.getfirst('calculate', 'all') + calculate = form.get('calculate', 'all') if calculate not in ('scattering', 'activation', 'all'): errors['calculate'] = "calculate should be one of 'scattering', 'activation' or 'all'" try: - sample = form.getfirst('sample') + sample = form.get('sample') chem = formula(sample) except Exception: errors['sample'] = error() try: - fluence = float(form.getfirst('flux', 100000)) + fluence = float(form.get('flux', 100000)) except Exception: errors['flux'] = error() try: - fast_ratio = float(form.getfirst('fast', '0')) + fast_ratio = float(form.get('fast', '0')) except Exception: errors['fast'] = error() try: - Cd_ratio = float(form.getfirst('Cd', '0')) + Cd_ratio = float(form.get('Cd', '0')) except Exception: errors['Cd'] = error() try: - exposure = parse_hours(form.getfirst('exposure', '1')) + exposure = parse_hours(form.get('exposure', '1')) except Exception: errors['exposure'] = error() try: - mass_str = form.getfirst('mass', '0') + mass_str = form.get('mass', '0') if mass_str.endswith('kg'): mass = 1000*float(mass_str[:-2]) elif mass_str.endswith('mg'): @@ -294,26 +290,26 @@ def cgi_call(form): except Exception: errors['mass'] = error() try: - density_type, density_value = parse_density(form.getfirst('density', '0')) + density_type, density_value = parse_density(form.get('density', '0')) except Exception: errors['density'] = error() try: - #print >>sys.stderr,form.getlist('rest[]') - rest_times = [parse_rest(v) for v in form.getlist('rest[]')] + rest_times = [parse_rest(v) for v in form.get('rest', [])] if not rest_times: rest_times = [0, 1, 24, 360] except Exception: errors['rest'] = error() try: - decay_level = float(form.getfirst('decay', '0.001')) + decay_level = float(form.get('decay', '0.001')) except Exception: errors['decay'] = error() try: - thickness = float(form.getfirst('thickness', '1')) + thickness = float(form.get('thickness', '1')) except Exception: errors['thickness'] = error() try: - wavelength_str = form.getfirst('wavelength', '1').strip() + # Ensure we cast to string so we can safely .strip() + wavelength_str = str(form.get('wavelength', '1')).strip() if wavelength_str.endswith('meV'): wavelength = nsf.neutron_wavelength(float(wavelength_str[:-3])) elif wavelength_str.endswith('m/s'): @@ -322,11 +318,10 @@ def cgi_call(form): wavelength = float(wavelength_str[:-3]) else: wavelength = float(wavelength_str) - #print >>sys.stderr,wavelength_str except Exception: errors['wavelength'] = error() try: - xray_source = form.getfirst('xray', 'Cu Ka').strip() + xray_source = str(form.get('xray', 'Cu Ka')).strip() if xray_source.endswith('Ka'): xray_wavelength = elements.symbol(xray_source[:-2].strip()).K_alpha elif xray_source.endswith('keV'): @@ -337,14 +332,12 @@ def cgi_call(form): xray_wavelength = elements.symbol(xray_source).K_alpha else: xray_wavelength = float(xray_source) - #print >>sys.stderr,"xray",xray_source,xray_wavelength except Exception: errors['xray'] = error() try: - abundance_source = form.getfirst('abundance', 'IAEA') + abundance_source = form.get('abundance', 'IAEA') if abundance_source == "IUPAC": abundance = activation.table_abundance - # CRUFT: periodictable no longer uses NIST 2001 data for abundance elif abundance_source == "NIST": abundance = activation.table_abundance elif abundance_source == "IAEA": @@ -484,12 +477,36 @@ def cgi_call(form): return result +def fieldstorage_to_dict(form: 'cgi.FieldStorage') -> dict: + """ + Converts a cgi.FieldStorage object into a standard Python dictionary. + Keys ending in '[]' will map to lists. + Otherwise, they map to single string values. + """ + result = {} + if form is None: + return result + + for key in form.keys(): + values = form.getlist(key) + # If it's a single value and doesn't explicitly denote an array via '[]' + if key.endswith('[]'): + # Remove the '[]' from the key for the result dictionary + fixed_key = key[:-2] + result[fixed_key] = values + elif len(values) == 1: + result[key] = values[0] + + return result if __name__ == "__main__": import cgi try: form = cgi.FieldStorage() - response = cgi_call(form) + + # Convert to dictionary + form_dict = fieldstorage_to_dict(form) + response = api_call(form_dict) except Exception: response = { 'success': False, From 63ed18ccdd78ab1734e83f9fa23a7bec2de41587 Mon Sep 17 00:00:00 2001 From: bbm Date: Fri, 27 Feb 2026 12:41:59 -0500 Subject: [PATCH 49/66] just pass JSON --- activation/api_fetch.js | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/activation/api_fetch.js b/activation/api_fetch.js index 1dc9d1a..12b8368 100644 --- a/activation/api_fetch.js +++ b/activation/api_fetch.js @@ -2,23 +2,19 @@ class FetchAPI { response_callback = null; url = null; - initialize (response_callback, ready_callback=() => {}, url="/cgi-bin/nact.py") { + initialize (response_callback, ready_callback=() => {}, url="/api/calculate") { this.response_callback = response_callback; this.url = url; ready_callback(); } submit(data) { - const { rest, ...form_data } = data; - const request_body = new URLSearchParams(form_data); - // array handling in old URLSearchParams is a bit tricky, so we do it manually: - rest.forEach((value) => { - request_body.append('rest[]', value); - }); - fetch(this.url, { method: "POST", - body: request_body + body: JSON.stringify(data), + headers: { + 'Content-Type': 'application/json' + } }) .then(response => response.json()) .then(json => this.response_callback(json)) From fd605fb19fb040f594b7aeef0ad9f01b7fe67e71 Mon Sep 17 00:00:00 2001 From: bbm Date: Fri, 27 Feb 2026 12:42:24 -0500 Subject: [PATCH 50/66] default index.html is webworker version (replaced in local servers) --- activation/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/activation/index.html b/activation/index.html index a516ff3..2611f35 100644 --- a/activation/index.html +++ b/activation/index.html @@ -12,8 +12,8 @@ - - + + From a1fe2e1691b7b0d1e4872d71b7d576617a6e8286 Mon Sep 17 00:00:00 2001 From: bbm Date: Fri, 27 Feb 2026 12:43:04 -0500 Subject: [PATCH 51/66] nact.py api_call takes a plain dict (JSON) now, no need to fake CGI field storage --- activation/webworker.js | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/activation/webworker.js b/activation/webworker.js index f8c6b5f..b26812c 100644 --- a/activation/webworker.js +++ b/activation/webworker.js @@ -25,18 +25,7 @@ async function loadPyodideAndPackages() { f.write(await response.bytes()) import nact import json - import re - class FakeFieldStorage(dict): - def getfirst(self, name, default=None): - rval = self.get(name, default) - return rval if rval != "" else default - def getlist(self, name, default=None): - name = re.sub("\\[\\]$", "", name) - rval = self.get(name, default) - if isinstance(rval, str) or isinstance(rval, bytes): - return [rval] - return list(rval) `) } let pyodideReadyPromise = loadPyodideAndPackages(); @@ -45,16 +34,13 @@ pyodideReadyPromise.then(() => self.postMessage({worker_ready: true})); self.onmessage = async (event) => { // make sure loading is done await pyodideReadyPromise; - // Don't bother yet with this line, suppose our API is built in such a way: - const { request } = event.data; - const json_data = JSON.stringify(event.data.data); // Now is the easy part, the one that is similar to working in the main thread: try { + const json_data = JSON.stringify(event.data.data); let python = ` request = json.loads('${json_data}') - form = FakeFieldStorage(request) try: - response = nact.cgi_call(form) + response = nact.api_call(request) except Exception: response = { 'success': False, From 2714602ca365d92a7a2cb4eb586153f727fdaa19 Mon Sep 17 00:00:00 2001 From: bbm Date: Fri, 27 Feb 2026 12:43:57 -0500 Subject: [PATCH 52/66] json dict always includes mass, even if empty, so handle that, and expect rest to be string of comma-separated values --- cgi-bin/nact.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/cgi-bin/nact.py b/cgi-bin/nact.py index 9f57258..2c9d821 100755 --- a/cgi-bin/nact.py +++ b/cgi-bin/nact.py @@ -248,7 +248,7 @@ def parse_date(datestring, default_timezone=default_timezone): dt = utc.localize(dt) - timedelta(0, offset) return dt -def api_call(form): +def api_call(form: dict): # Parse inputs errors = {} calculate = form.get('calculate', 'all') @@ -277,7 +277,9 @@ def api_call(form): errors['exposure'] = error() try: mass_str = form.get('mass', '0') - if mass_str.endswith('kg'): + if not mass_str: + mass = 0 + elif mass_str.endswith('kg'): mass = 1000*float(mass_str[:-2]) elif mass_str.endswith('mg'): mass = 0.001*float(mass_str[:-2]) @@ -479,9 +481,7 @@ def api_call(form): def fieldstorage_to_dict(form: 'cgi.FieldStorage') -> dict: """ - Converts a cgi.FieldStorage object into a standard Python dictionary. - Keys ending in '[]' will map to lists. - Otherwise, they map to single string values. + special handling for "rest", which is a list of times. """ result = {} if form is None: @@ -489,13 +489,12 @@ def fieldstorage_to_dict(form: 'cgi.FieldStorage') -> dict: for key in form.keys(): values = form.getlist(key) - # If it's a single value and doesn't explicitly denote an array via '[]' - if key.endswith('[]'): - # Remove the '[]' from the key for the result dictionary - fixed_key = key[:-2] - result[fixed_key] = values - elif len(values) == 1: - result[key] = values[0] + if len(values) == 1: + value = values[0] + if key == "rest": + result[key] = value.split(",") + else: + result[key] = value return result From 79d8bdac47fb100ae7f467ab2823721a88a882c0 Mon Sep 17 00:00:00 2001 From: bbm Date: Fri, 27 Feb 2026 12:47:01 -0500 Subject: [PATCH 53/66] add regex replace to load the api_cgi.js API in the page, replacing api_webworker.js --- cgi_server.py | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100755 cgi_server.py diff --git a/cgi_server.py b/cgi_server.py new file mode 100755 index 0000000..ff58b6c --- /dev/null +++ b/cgi_server.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python +""" +Simple server for running the neutron activation calculator. + +This is intended for testing. It has not been assessed for security and is +not recommended for a public facing server. The activation calculator +expects a cgi interface, which should be provided by the web infrastructure +(apache, nginx, etc.) that you are using on your production server. + +Usage: python server.py [host | host:port] + +Default is localhost:8008 +""" + +from __future__ import print_function + +import re +import sys +import os +try: + from http.server import HTTPServer, CGIHTTPRequestHandler + from socketserver import ThreadingMixIn +except ImportError: + from BaseHTTPServer import HTTPServer + from SocketServer import ThreadingMixIn + from CGIHTTPServer import CGIHTTPRequestHandler +import cgitb +cgitb.enable() ## This line enables CGI error reporting + +class ThreadedHTTPServer(ThreadingMixIn, HTTPServer): + """Very simple threaded server""" + allow_reuse_address = True + request_queue_size = 50 + +# ========================================== +# NEW: Custom Handler to intercept index.html +# ========================================== +class CustomCGIHTTPRequestHandler(CGIHTTPRequestHandler): + def do_GET(self): + # Intercept requests exactly matching the index route + if self.path in ('/activation/', '/activation/index.html'): + + # self.translate_path converts the URL path to a local OS file path + file_path = self.translate_path('/activation/index.html') + + try: + # Read the original file + with open(file_path, 'r', encoding='utf-8') as f: + content = f.read() + + pattern = re.compile(r'src="api_[a-zA-Z_-]+.js"', re.IGNORECASE) + replacement = 'src="api_cgi.js"' + + # Perform the substitution + modified_content = pattern.sub(replacement, content) + + # Convert the string back to bytes for transport + encoded_content = modified_content.encode('utf-8') + + self.send_response(200) + self.send_header("Content-type", "text/html; charset=utf-8") + self.send_header("Content-Length", str(len(encoded_content))) + self.end_headers() + self.wfile.write(encoded_content) + + except (IOError, OSError): + self.send_error(404, "File not found") + else: + # For everything else (CGI scripts, CSS, JS, images), use the default behavior + CGIHTTPRequestHandler.do_GET(self) + +server = ThreadedHTTPServer +handler = CustomCGIHTTPRequestHandler +handler.cgi_directories = ["/cgi-bin"] + +if len(sys.argv) > 1: + host, *rest = sys.argv[1].split(':', 1) + port = int(rest[0]) if rest else 8008 +else: + host, port = "localhost", 8008 +print(f"serving on http://{host}:{port}/activation/") +httpd = server((host, port), handler) +httpd.serve_forever() From d46b3212195e56777e31bd17a4175767ef75d293 Mon Sep 17 00:00:00 2001 From: bbm Date: Fri, 27 Feb 2026 13:01:36 -0500 Subject: [PATCH 54/66] update readme for json API and flask server --- README.md | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index d78a1a9..ba411bb 100644 --- a/README.md +++ b/README.md @@ -13,14 +13,8 @@ available on [github](https://github.com/pkienzle/periodictable). Installation ============ -The activation web frontend is in the activation subdirectory and the cgi -backend is in cgi-bin. Update the server with something like: - - sudo cp -rp activation/* /var/www/resources/activation - sudo cp -p cgi-bin/nact.py /var/www/cgi-bin - -The web page uses the date of activate/index.html to show the last -modification date on the program, so be sure to preserve attributes in copy. +The activation web frontend is in the activation subdirectory. +The backend API is in the cgi-bin folder (nact.py) Be sure the web server is configured to use python 3, with the periodictable package updated to the latest version: @@ -33,7 +27,8 @@ of updates this will also set the last modification date on index.html. For testing you can run the server from the repository: - python server.py [host | host:port] + pip install flask + python flask_server.py [host | host:port] Additional files: @@ -41,7 +36,7 @@ Additional files: needed unless you wish to update the graphs, for example, when new versions of the endf database are released. -* server.py is used to run a test server for debugging the web application, or +* flask_server.py is used to run a test server for debugging the web application, or showing potential new features to users. See the help inside the file for details on running the server. @@ -84,6 +79,25 @@ request = { } ``` +```python +python_request = { + 'calculate': "all", # target is "scattering" or "activation" or "all" + 'sample': 'Co', # Material + 'flux': '100000', # Thermal flux + 'Cd': '0', # Cd ratio + 'fast': '0', # Thermal/fast ratio + 'mass': '0', # Mass + 'exposure': '1', # Time on beam + 'rest': ["0","1","24","360"], # Time off beam + 'density': '0', # Density + 'thickness': '1', # Thickness + 'wavelength': '1', # Source neutrons + 'xray': 'Cu Ka', # Source Xrays + 'decay': '0.001', # target for "Time to decay below" + 'abundance': 'IAEA' # natural abundance tables (IAEA or NIST) +} +``` + The response is a JSON object with the following fields ```javascript response = { From 4f6cd2e4895ad9cf1ab280bcee21bb09183056a6 Mon Sep 17 00:00:00 2001 From: bbm Date: Fri, 27 Feb 2026 13:40:31 -0500 Subject: [PATCH 55/66] remove server.py, replace with flask_server.py and cgi_server.py --- server.py | 45 --------------------------------------------- 1 file changed, 45 deletions(-) delete mode 100755 server.py diff --git a/server.py b/server.py deleted file mode 100755 index 234575a..0000000 --- a/server.py +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env python -""" -Simple server for running the neutron activation calculator. - -This is intended for testing. It has not been assessed for security and is -not recommended for a public facing server. The activation calculator -expects a cgi interface, which should be provided by the web infrastructure -(apache, nginx, etc.) that you are using on your production server. - -Usage: python server.py [host | host:port] - -Default is localhost:8008 -""" - -from __future__ import print_function - -import sys -import os -try: - from http.server import HTTPServer, CGIHTTPRequestHandler - from socketserver import ThreadingMixIn -except ImportError: - from BaseHTTPServer import HTTPServer - from SocketServer import ThreadingMixIn - from CGIHTTPServer import CGIHTTPRequestHandler -import cgitb -cgitb.enable() ## This line enables CGI error reporting - -class ThreadedHTTPServer(ThreadingMixIn, HTTPServer): - """Very simple threaded server""" - allow_reuse_address = True - request_queue_size = 50 - -server = ThreadedHTTPServer -handler = CGIHTTPRequestHandler -handler.cgi_directories = ["/cgi-bin"] - -if len(sys.argv) > 1: - host, *rest = sys.argv[1].split(':', 1) - port = int(rest[0]) if rest else 8008 -else: - host, port = "", 8008 -print(f"serving on http://{host}:{port}/activation/") -httpd = server((host, port), handler) -httpd.serve_forever() From f59b5887398194cb7fc1bc2c91a676eab8bb8f84 Mon Sep 17 00:00:00 2001 From: bbm Date: Fri, 27 Feb 2026 15:14:50 -0500 Subject: [PATCH 56/66] use index_template, and render it with periodictable version and webworker api script --- deploy_calculator.sh | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/deploy_calculator.sh b/deploy_calculator.sh index 93d5c00..2426346 100755 --- a/deploy_calculator.sh +++ b/deploy_calculator.sh @@ -7,10 +7,17 @@ TARGET_DIR=${TARGET_DIR:-/var/www/html/resources/activation} # Now copy all the necessary files to the target directory for deployment: mkdir -p $TARGET_DIR -cp activation/index_pyodide_optimized.html $TARGET_DIR/index.html +cp activation/index_template.html $TARGET_DIR/index.html cp activation/jquery* $TARGET_DIR/ cp activation/webworker.js $TARGET_DIR/ cp activation/favicon.ico $TARGET_DIR/ cp activation/periodictable_wheel_name.txt $TARGET_DIR/ cp cgi-bin/nact.py $TARGET_DIR/ -cp -r activation/pyodide $TARGET_DIR/pyodide \ No newline at end of file +cp -r activation/pyodide $TARGET_DIR/pyodide + +# Get the version of periodictable from the wheel file name and write it to a text file for use in the workflow +PERIODICTABLE_VERSION=$(python -c "import periodictable; print(periodictable.__version__)") + +# Write replacements in template +sed -i "s@{{ api_script }}@api_webworker.js@g" $TARGET_DIR/index.html +sed -i "s@{{ periodictable_version }}@$PERIODICTABLE_VERSION@g" $TARGET_DIR/index.html \ No newline at end of file From 23d76c32508f33bef6581880fd8ee3e7d6e9ee3a Mon Sep 17 00:00:00 2001 From: bbm Date: Fri, 27 Feb 2026 15:15:10 -0500 Subject: [PATCH 57/66] removing deprecated files --- activation/index.html | 759 ------------------------------------------ cgi_server.py | 83 ----- 2 files changed, 842 deletions(-) delete mode 100644 activation/index.html delete mode 100755 cgi_server.py diff --git a/activation/index.html b/activation/index.html deleted file mode 100644 index 2611f35..0000000 --- a/activation/index.html +++ /dev/null @@ -1,759 +0,0 @@ - - - - - Neutron Activation and Scattering Calculator - - - - - - - - - - - - - - - - - -
    - -
    - -

    NIST Center for Neutron Research

    -
    - - National Institute of Standards and Technology - -
    - -
    - -
    - -
    - -
    -

    Material

    - - - -
    -
    -
    -
    - -
    -

    Neutron Activation

    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - For rabbit system
    - - - -
    -
    -
    -
    -
    -
    -
    - - - - - -
    -
    -
    -
    -
    -
    -
    - -
    - -
    -

    Absorption and Scattering

    - - - - - - - - -
    - - - -
    -
    -
    -
    -
    - - - -
    -
    -
    -
    -
    - -
    - -
    - -
    -
    -
    -
    -

    Neutron activation and scattering calculator

    -

    -This calculator uses neutron cross sections to compute activation -of the sample given the mass in the sample and the time in the beam, -and to perform absorption and scattering calculations for samples on -slow neutron beamlines (energy below 325 meV, wavelength above 0.05 nm). -

    -
      -
    1. Enter the sample formula in the material panel.
    2. -
    3. To perform activation calculations, fill in the thermal -flux, the mass, the time on and off the beam, then press the -calculate button in the neutron activation panel.
    4. -
    5. To perform scattering calculations, fill in the wavelength -of the neutron and/or xrays, the thickness and the -density (if not given in the formula), then press the -calculate button in the absorption and scattering panel.
    6. -
    -
    - - -
    -

    Chemical formula

    -

    The chemical formula parser allows you to specify materials and mixtures. -Formulas are parsed with -periodictable -python package (Kienzle 2008). -

    - -
    -
    simple formula
    -
    A basic formula consists of elements and their quantities. -
    CaCO3
    represents the chemical CaCO3
    -
    - -
    multi-part formula
    -
    Formulas can be built from parts by separating them with "+" or space, - with a number before the part representing repeats. Using parentheses, - a formula is treated as if it were a single unit. -
    CaCO3+6H20
    , -
    CaCO3 6H2O
    and -
    CaCO3(H2O)6
    all represent ikaite, - CaCO3·6H2O -
    -
    - -
    isotopes
    -
    Isotopes are represented by element[nuclide index]. -Special symbols
    D
    and -
    T
    -can be used for 2H and 3H. -Isotopes can be mixed within a formula, such as -
    DHO
    for partially deuterated water. -Use
    H[1]
    in formula for labile hydrogen. -These will be substituded with H and D in proportion with the D2O -fraction when computing the contrast match point of the sample. -
    O[18]
    represents the 18O
    -
    C3H4H[1]NO@1.29n
    represents alanine with one labile hydrogen. -
    - -
    density
    -
    Mass density is needed to compute scattering factors for the material. -The density can be entered in the density field, or it can be given in -the formula by adding @value to the end. Densities for the pure elements are -already known. -
    H2O@1
    -indicates that water has a density of 1 g/cm3
    -
    - -
    isotopic density
    -
    If the formula uses a mixture of isotopes, you can still use the density -of the material assuming natural abundance, but add an "n" to the value -to scale it to the isotope specific density. If you already know the -isotopic density, use the value by itself and it will not be scaled. -
    D2O@1n
    , -
    D2O@1.11
    , and -
    D2O@1.11i
    -all give the density of D2O as 1.11 g/cm3
    -
    - -
    mole fractions
    -
    Using non-integer quantities, arbitrary concentration ratios can be - be constructed. -
    78.2H2O[16] + 21.8H2O[18] @1n
    - represents water with 78.2% 16O and 21.8% 18O -
    -
    - -
    mass fractions
    -
    Formulas can be mixed by mass, with each part starting with a percentage - followed by formula followed by "//". The first part must use "%wt" to - indicate that it is a mass fraction. The final part is the base, and it - does not need a percentage since it makes up the rest of the material. -
    50%wt Co // Ti
    - is more descriptive than Co0.552Ti0.448
    -
    33%wt Co // 33% Fe // Ti
    - builds a 1:1:1 mixture by mass of cobalt-iron-titanium
    -
    - -
    volume fractions
    -
    Volume fractions are like mass fractions, but they use "%vol" instead. - Each component of the volume fraction must specify the density. -
    20%vol (10%wt NaCl@2.16 // H2O@1) // D2O@1n
    - is a 10% saline solution by weight mixed 20:80 by volume with - D2O, which is the same as -
    NaCl(H2O)29.1966(D2O)122.794@1.10i
    -
    -
    - -
    mass and volume mixtures
    -
    Specific amounts of materials can be mixed, with each part giving - the quantity of material followed by "//". Quantities can be masses - (kg, g, mg, ug, or ng) or they can be volumes (L, mL, uL, nL). Density - is required for materials given by volume. For scattering calculations - density is required for the materials given by mass as well. -
    5g NaCl // 50mL H2O@1
    - is more descriptive than -
    NaCl(H2O)32.4407
    -
    -
    5g NaCl@2.16 // 50mL H2O@1
    - computes the density as 1.05 g/cm3. Not useful in this - case since 9%wt brine has a density of 1.0633 at ambient temperature. -
    -
    50 mL (45 mL H2O@1 // 5 g NaCl)@1.0707 // 20 mL D2O@1n
    - uses the appropriate density for a 10%wt brine in the mixture. -
    -
    - -
    layer thickness
    -
    Multilayer samples can specified as layer thickness and material separated - by "//". Thicknesses are in length units (cm, mm, um, nm). The - resulting material will compute activation for 1 cm2 of material. - Density is required for each layer. -
    1 cm Si // 5 nm Cr // 10 nm Au
    -
    -
    -
    - -
    biomolecules
    -
    - For FASTA sequences - use "code:sequence", where code is "aa" for amino acid sequences, "dna" for - DNA sequences, or "rna" for RNA sequences. Density is estimated automatically. - This calculation uses 1H for labile hydrogen, with substitution - by H in natural abundance and pure D when computing contrast match point. -
    β-casein amino acid sequence
    aa:RELEELNVPGEIVESLSSSEESITRINKKIEKFQSEEQQQTEDELQDKIHPFAQTQSLVYPFPGPIPNSLPQNIPPLTQTPVVVPPFLQPEVMGVSKVKEAMAPKHKEMPFPKYPVEPFTESQSLTLTDVENLHLPLPLLQSWMHQPHQPLPPTVMFPPQSVLSLSQSKVLPVPQKAVPYPQRDMPIQAFLLYQEPVLGPVRGPFPIIV
    -
    -
    - -
    -

    Thermal flux

    -

    Units: n/cm2/s

    -

    - Provide the thermal flux equivalent for the pre-sample beam configuration - for the instrument. Because neutron capture cross sections are linear - above 0.5 Å for most isotopes, simply scale the flux by λ/1.798 Å, where - λ is the average wavelength at the sample weighted by spectral intensity. - For non-linear isotopes activation may be underestimated - (176Lu < 1.8 Å; 151Eu < 0.8 Å) - or overestimated (33S < 11 Å; 204Hg < 20 Å). -

    -

    - The neutron activation calculation follows (Shleien 1998). - Activation is a function of isotope, not element. When - an element is used in a formula, the natural abundance of the individual - isotopes is used to determine the total activation. By default, the - activation calculator uses values from the IAEA - handbook (IAEA 1987), and the - scattering calculator uses the IUPAC 2021 atomic weights and isotope composition - database (CIAAW 2021). -

    -

    - For very high fluences, e.g., more than 1016 n/cm2, the activation - equations give erroneous results because of the precision limitations. - If there is doubt simply do the calculation at a lower flux and - proportion the result. This will not work for the cascade reactions, - i.e., two neutron additions. -

    -

    - Reaction = b : This is the beta produced daughter of an activated parent. - This is calculated only for the cases where the daughter is long lived - relative to the parent. The calculated activity is through the end of - exposure only. Contributions from the added decay of the parent after the - end of irradiation are left for the user to determine, but are usually - negligible for irradiations that are long relative to the parent halflife. -

    - -

    Calculation parameters are controlled by URL:

    -
    -
    isotope abundance
    -
    - Use the following to select IUPAC 2021 isotopic abundance data rather than the IAEA 1987 data: - index.html?abundance=IUPAC -
    - -
    activation cutoff
    -
    - The cutoff values for displaying activation data are set to 0.0005 μCi - by default. The full activation levels - can be displayed using: index.html?cutoff=0 -
    - -
    decay cutoff
    -
    The activation calculator determines the amount of time for the activation to decay to - the cutoff level, or to 0.0005 μCi if cutoff is 0. This can be set to a value - such as 0.1 μCi using: index.html?decay=0.1 -
    -
    - -

    Notes on calculation:

    -
    • - For some numerical combinations with very large half-lives the numerical - precision is inadequate and you get negative results. This can be - corrected by reformulation or approximations but has not been done. - Remember, the X in EXP(X) is limited to |X|<709 -
    • - Simplifications have been made as indicated in the comments column in - data table -
    • - Typically, for a decay chain where the daughter is also produced (isomers) - the s of the parent has been added to that of the daughter when the - daughter t1/2 is much longer (true for most cases) and the parent - t1/2 is relatively short, e.g. less than 1 day, so that all the daughter - will be made relatively promptly. -
    • - In cases where the above condition is not met an * is put next to the - nuclide name to warn that the daughter production has not been accounted - for. In most cases the daughter is in a simple decay equilibrium. -
    • - Where the decay product is a new nuclide a line has been added to the - database to account for this. This production mode is indicated in - the reaction column by 'b'. Where both m and g state contribute to daughter - production it is simplified to a single parent, that with the greater - cross-section or that with the longer half-life together with the sum - of the cross-sections. -
    • - In a few cases where the parent nuclide t1/2 is very short all production - is assigned to the daughter and no entry is made for the parent, as - noted in the comments column. -
    • - No correction for neutron burn up has been made. -
    • - Most cross-section data is from IAEA 273. -
    • - Fast neutron data from NBSIR 85-3151, Compendium of Benchmark Neutron Fields - is for reaction above the Cd cutooff, .4eV. Noted in comment column. -
    • - Fast neutron reaction data from IAEA 273 has been weighted by a unit fluence - fast maxwellian spectrum as described in NBSIR 85-3151, but no further - weighting for a 1/v or thermal component has been made. Only selected - reactions have been included. -
    • - Reaction = b indicates production via decay from an activation produced parent. -
    • - Notation on reaction product name: -
      m, m1, m2
      - indicate metastable states. Decay may be the ground state or another nuclide. -
      +
      - indicates radioactive daughter production already included in daughter listing - several parent t1/2's required to acheive calculated daughter activity. - All activations are assigned at end of irradiation. - In most cases the added activity to the daughter is small. -
      *
      - indicates radioactive daughter production NOT calculated, approx - secular equilibrium. -
      s
      - indicates radioactive daughter of this nuclide in secular equilibrium - after several daughter t1/2's. -
      t
      - indicates transient equilibrium via beta decay. Accumulation of that nuclide - during irradiation is separately calculated. -
      -
    -
    - -
    -

    Cadmium ratio

    -

    Units: none

    -

    - Samples in the rabbit tubes can be shielded with cadmium to reduce the thermal - flux while leaving the epithermal flux mostly unchanged. The cadmium ratio - determines the degree of reduction in the scattering cross sections, corresponding - to the reduced flux. This value is unitless. Use a value of 0 for beamline - experiments. -

    -
    - -
    -

    Thermal/fast ratio

    -

    Units: none

    -

    - When performing neutron activation analysis in a rabbit tube, the additional - fast neutron activations need to be determined. The thermal/fast ratio is - used to determine the fast neutron flux from the thermal flux equivalent for - the given rabbit tube. The resulting fast flux is (thermal flux)/(thermal/fast ratio). - This value is unitless. Use a value of 0 for beamline experiments. -

    -
    - -
    -

    Material mass

    -

    Units: g, kg, mg or ug

    -

    - The total neutron activation depends on the mass of the individual - isotopes in the sample and the total time in the beam. All activation - calculations assume a thin plate sample, with all parts of the sample - exposed to full flux during activation, and no self-shielding when - estimating the activation level outside the beam. -

    -
    - -
    -

    Exposure

    -

    Units: h m s d w y

    -

    - Exposure is the duration of the exposure at the given flux. Activation - will be accumulated over that time, with decay beginning the moment the - sample is activated. Time defaults to hours, but can be set to - hours, minutes, seconds, days, weeks or years by adding h, m, s, d, w, or y - to the value respectively. -

    -
    - -
    -

    Decay

    -

    Units: h m s d w y OR yyyy-mm-dd hh:mm:ss

    -

    - The sample begins to decay immediately, even while it is being activated. - The decay field allows you to specify how long since the sample - was removed from the beam. The default is hours, but can be set to - hours, minutes, seconds, days, weeks or years by adding h, m, s, d, w, or y - to the value respectively. - We always compute the activation level when the sample is removed from the beam, - and at 1 hour, 1 day and 15 days post activation. -

    -

    - Instead of saying how long the sample activation has decayed, you can use - the time that the sample was removed from the beam. Times are given as - year-month-day hour:minute:second. - Approximate times are allowed, such as 2010-03 for March, 2010. This is - equivalent to 2010-03-31 23:59:59, which is the end of March so that the - activation estimate will be conservative. This is the most activation - consistent with the sample being on the beam sometime in March, 2010. - Times are specified in US/Eastern. Add "Z" after the time of day to - indicate universal coordinated time (UTC), or add a timezone offset such - as "+01" for +1 hours in France in winter, when daylight savings time is - not in effect. -

    -

    - - - - - - - - - - - - - -
    If you type:This is equivalent to:
    2 m2 minutes ago
    11 hour ago
    2.5w2 and a half weeks ago
    3 y3 years ago
    2015-01-02 21:45:00January 2, 2015 at 9:45 PM US/Eastern
    2010-03March 31, 2010 at 11:59:59 PM US/Eastern
    2010-7-5 12:23July 5, 2010 at 12:23:59 PM US/Eastern
    2015-01-02 21:45:00ZJanuary 2, 2015 at 9:45 PM UTC
    2015-01-02 21:45:00-0600January 2, 2015 at 9:45 PM US/Central
    2015-08-02 21:45:00-0500August 2, 2015 at 9:45 PM US/Central
    -

    - -
    -

    Mass density

    -

    Units: g/cm3 or A3

    -

    - Density is used to compute absorption, transmission and scattering. -

    -
    from formula
    -
    Leave the density field blank and add -
    @
    + density - to the end of the formula, where density is in g/cm3. - For compounds with specific isotopes, you can use the density of the - naturally occurring compound as -
    @
    + density +
    n
    - and the isotope specific density will be computed. Density defaults to - 1 g/cm3, or for pure elements, the natural density given in - the periodic table is used. - -
    D2O@1n
    or -
    D2O@1.11
    -
    -
    g/cm3
    -
    Enter the density by itself, which will be interpreted as g/cm3, or - equivalently, kg/L. No units are needed. If the value is - density +
    n
    then it is density of the the - naturally occuring compound and the isotopic density will be computed. -
    D2O has a natural density of -
    1n
    and an isotopic density of -
    1.11
    -
    -
    cell volume
    -
    Enter a number followed by A3 for Å3. Be sure that your - formula contains the correct number of atoms for the unit cell, possibly by - using n(formula), where n is 6 for hexagonal close packed, 4 for face centered - cells, 2 for body centered and base centered cells, or 1 for simple cells. -
    4NaCl has a cell volume of -
    179.4 A3
    -
    -
    crystal lattice parameters
    -
    Enter lattice parameters "a:n b:n c:n alpha:n beta:n gamma:n" - where a, b, c are in Å and α, β, γ are in degrees. - If not specified, b and c default to a. Ratios can also be used, - so that "b/a:n" gives b=n*a, and "c/a:n" gives c=n*a. Angles - α, β, and γ default to 90°. Be sure that the - formula contains the correct number of atoms for the unit cell. -
    4NaCl has a cubic lattice with -
    a:5.6402
    -
    -
    -
    - -
    -

    Thickness

    -

    Units: cm

    -

    - The material thickness in cm is used to determine sample transmission, - or how much beam will be absorbed by the sample or scattered incoherently. - Leave it at 1 cm if you do not need this information. -

    -
    - -
    -

    Source neutrons

    -

    Units: Ang, meV or m/s

    -

    - The energy of the source neutrons will affect the absorption cross section - and hence the penetration depth and sample attenuation. Energy can be - expressed as wavelength in Å, as energy in meV, or as neutron - velocity in m/s. - Neutron cross sections are tabulated - at 1.798 Å = 25.3 meV = 2200 m/s, with an assumed 1/v dependence for - the absorption cross section (Rauch 2003, - Sears 2006). -

    - For heavier isotopes (Cd, Hf, rare earths) and/or shorter wavelengths - (below 1 Å) there are neutron resonances - in the thermal range. For common rare-earth isotopes the energy-dependent - coherent and absorption cross sections tabulated in - Lynn and Seeger 1992 are used. - Incoherent scattering will be understimated for these elements. - Resonances for 113Cd and 180Ta are ignored. -

    - There is also a wavelength dependence for single phonon interactions which - gives rise to significant inelastic scattering for lighter isotopes (H, D) - and/or longer wavelengths (above 5 Å). This factor is both - temperature and material dependent and will not be included - in the scattering calculations. In particular, penetration length and - transmitted flux are going to be significantly overestimated. -

    -
    - -
    -

    Source X-rays

    -

    Units: Ang, keV or Ka

    -

    - X-ray absorption and scattering are computed from the energy dependent - atomic scattering factors (Henke 1993). - Energy can be expressed as wavelength in Å, as energy in keV, or - using an element name for the Kα emission line2 for - that element (Deslattes 2003). -

    -
    - -
    -

    References

    -
      -
    1. - CIAAW. Isotopic compositions of the elements 2021. Available online - at www.ciaaw.org - Bölke, et al. (2005). - [atomic weights, - isotopic abundance] -
    2. -
    3. - Deslattes, R.D.; Kessler, Jr., E.G.; Indelicato, P.; de Billy, L.; Lindroth, E. and Anton, J. (2003). - Rev. Mod. Phys. 75, 35-99. - [xray emission lines] -
    4. -
    5. - Henke, B.L.; Gullikson, E.M. and Davis, J.C. (1993). - X-ray interactions: - photoabsorption, scattering, transmission, and reflection at E=50-30000 eV, Z=1-92, - Atomic Data and Nuclear Data Tables Vol. 54 (no.2), 181-342. - [xray cross sections] -
    6. -
    7. - IAEA (1987). - Handbook on Nuclear Activation Data. - TR 273 (International Atomic Energy Agency, Vienna, Austria). - [tech report] -
    8. - -
    9. - Kienzle, P. A. (2008). - Extensible periodic table - [Computer Software]. - https://periodictable.readthedocs.io. - [calculator source, - web service source] -
    10. -
    11. - Lynn, J.E. and Seeger, P.A. (1990). - Resonance effects in neutron scattering lengths of rare-earth nuclides. - Atomic Data and Nuclear Data Tables 44, 191-207. - doi:10.1016/0092-640X(90)90013-A - [rare earth scattering lengths] -
    12. - Rauch, H. and Waschkowski, W. (2003). - Neutron Scattering Lengths in ILL Neutron Data Booklet (second edition), - A.-J. Dianoux, G. Lander, Eds. - Old City Publishing, Philidelphia, PA. pp 1.1-1 to 1.1-17. - [booklet, - neutron cross sections] -
    13. -
    14. - Sears, V. F. (2006). "Scattering lengths for neutrons" In Prince, E. Ed. - International Tables for Crystallography Volume C: Mathematical, Physical and Chemical Tables" - Kluwer Academic Publishers, pp 444-454. - doi:10.1107/97809553602060000103 - [scattering calculations] -
    15. -
    16. - Shleien, B.; Slaback, L.A. and Birky, B.K. (1998). - Handbook of health physics and radiological health. - Williams & Wilkins, Baltimore. - [activation data] -
    17. -
    -
    - -
    -

    History

    -
    -
    2025-04-23 v2.0.0
    -
    Fix sort by half-life with units of ky, My, Gy.
    -
    2025-02-28 v2.0.0
    -
    Use standard year as 365 rather than 365.2425 days when reporting decay time. -
    -
    2024-12-03 v2.0.0
    Update mass and abundance tables, and physical constant values -
    neutron cross section updates for H, He, C, O, Zn, Kr, Sn, Xe, Sm, Eu, Ir, Pb, Bi -
    X-ray cross section updates for Pt, Cr, Nb, Y, Er -
    208Pb activation scaled by 0.001 (value was reported in mbarns but added as barns) -
    -
    2024-03-22 v1.7.0
    Mixture formulas allow wt% and vol%. -
    Formulas allow unicode subscripts such as H₂O. -
    FASTA sequences (aa: rna: dna:) allowed as mixture components. -
    FASTA calculations updated. -
    Use correct halflife for Tm-171, Ho-163 and W-188 activation products. -
    Improve numerical precision of activation calculations. -
    -
    2021-04-21 v1.6.0
    Support energy-dependent rare earth elements. -
    Use complex scattering length bc when computing - σc = 4π |bc|2/100 and - σi = σs - σc. -
    -
    2020-10-29 v1.5.3
    Change field labels from 'time on/off beam' to 'exposure/decay duration'.
    -
    2020-01-22
    Restore support for Internet Explorer 10 and 11.
    -
    2019-12-02
    Fix cutoff=0 handling in URL.
    -
    2019-11-14 v1.5.2
    Correct units on activity table: nCi becomes uCi. -
    Elemental carbon density changed to 2.2 to match CXRO, CRC and RSC. -
    -
    2019-11-04
    Update neutron refs with links to ILL data book and Table for Crystallography.
    -
    2019-09-16
    Improve help system: can now scroll between sections.
    -
    2019-09-11 v1.5.1
    Include notes on activation calculation.
    -
    2019-08-27
    Change default cutoff to 0.5 nCi.
    -
    2018-01-12
    Make activation table sortable.
    -
    2017-05-11 v1.5.0
    Improved support for printing tables. -
    Support for biomolecules with labile hydrogen (FASTA format). -
    Mixture by mass and volume, e.g., 5 g NaCl // 50 mL H2O@1 -
    Multi-layer materials, e.g., 5 um Si // 3 nm Cr // 8 nm Au -
    Compute incoherent cross section from coherent and total. -
    -
    2016-12-07
    Use exponential notation for all activity levels.
    -
    2015-10-20
    Allow decay time to be calculated from timestamp..
    -
    2014-03-20 v1.4.1
    Default to isotopic density.
    -
    2013-11-05
    Support for X-ray scattering.
    -
    2013-04-17 v1.3.8
    Initial release.
    -
    -
    - - - -
    -
    - -
    -
    - -
    Initializing calculator...
    -
    -
    - - - - -
    - - diff --git a/cgi_server.py b/cgi_server.py deleted file mode 100755 index ff58b6c..0000000 --- a/cgi_server.py +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/env python -""" -Simple server for running the neutron activation calculator. - -This is intended for testing. It has not been assessed for security and is -not recommended for a public facing server. The activation calculator -expects a cgi interface, which should be provided by the web infrastructure -(apache, nginx, etc.) that you are using on your production server. - -Usage: python server.py [host | host:port] - -Default is localhost:8008 -""" - -from __future__ import print_function - -import re -import sys -import os -try: - from http.server import HTTPServer, CGIHTTPRequestHandler - from socketserver import ThreadingMixIn -except ImportError: - from BaseHTTPServer import HTTPServer - from SocketServer import ThreadingMixIn - from CGIHTTPServer import CGIHTTPRequestHandler -import cgitb -cgitb.enable() ## This line enables CGI error reporting - -class ThreadedHTTPServer(ThreadingMixIn, HTTPServer): - """Very simple threaded server""" - allow_reuse_address = True - request_queue_size = 50 - -# ========================================== -# NEW: Custom Handler to intercept index.html -# ========================================== -class CustomCGIHTTPRequestHandler(CGIHTTPRequestHandler): - def do_GET(self): - # Intercept requests exactly matching the index route - if self.path in ('/activation/', '/activation/index.html'): - - # self.translate_path converts the URL path to a local OS file path - file_path = self.translate_path('/activation/index.html') - - try: - # Read the original file - with open(file_path, 'r', encoding='utf-8') as f: - content = f.read() - - pattern = re.compile(r'src="api_[a-zA-Z_-]+.js"', re.IGNORECASE) - replacement = 'src="api_cgi.js"' - - # Perform the substitution - modified_content = pattern.sub(replacement, content) - - # Convert the string back to bytes for transport - encoded_content = modified_content.encode('utf-8') - - self.send_response(200) - self.send_header("Content-type", "text/html; charset=utf-8") - self.send_header("Content-Length", str(len(encoded_content))) - self.end_headers() - self.wfile.write(encoded_content) - - except (IOError, OSError): - self.send_error(404, "File not found") - else: - # For everything else (CGI scripts, CSS, JS, images), use the default behavior - CGIHTTPRequestHandler.do_GET(self) - -server = ThreadedHTTPServer -handler = CustomCGIHTTPRequestHandler -handler.cgi_directories = ["/cgi-bin"] - -if len(sys.argv) > 1: - host, *rest = sys.argv[1].split(':', 1) - port = int(rest[0]) if rest else 8008 -else: - host, port = "localhost", 8008 -print(f"serving on http://{host}:{port}/activation/") -httpd = server((host, port), handler) -httpd.serve_forever() From dc050d988f012b884e41a3135d17a906faff6e3f Mon Sep 17 00:00:00 2001 From: bbm Date: Fri, 27 Feb 2026 15:16:43 -0500 Subject: [PATCH 58/66] adding flask server --- flask_server.py | 70 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 flask_server.py diff --git a/flask_server.py b/flask_server.py new file mode 100644 index 0000000..5710ed3 --- /dev/null +++ b/flask_server.py @@ -0,0 +1,70 @@ +from pathlib import Path +import re +import sys +from flask import abort, Flask, request, jsonify, make_response, render_template, send_from_directory + +# Import your refactored script (ensure it's named nact.py in the same folder) +sys.path.append(str(Path(__file__).parent / 'cgi-bin')) +import nact + +app = Flask(__name__, template_folder="activation") + + +@app.route('/api/calculate', methods=['POST']) +def calculate(): + """ + Handles the API request, converts the input into a standard dict, + and passes it to nact.cgi_call(). + """ + + try: + data = request.get_json() + result = nact.api_call(data) + return jsonify(result) + except Exception as e: + return jsonify({ + 'success': False, + 'error': 'Server error', + 'detail': str(e) + }), 500 + + +@app.route('/') +@app.route('/index.html') +def serve_index(): + """ + Reads the index.html file, performs a regex substitution on a script tag, + and returns the modified HTML. + """ + return render_template( + 'index_template.html', + api_script='api_fetch.js', + periodictable_version=nact.periodictable.__version__ + ) + + +@app.route('/') +def serve_static_files(filename): + """ + Serves any other file requested at the root level from the 'activation' folder. + """ + # Prevent this route from accidentally serving the unmodified index.html + if filename == 'index.html': + # You can either call serve_index() directly or return a 404 + return serve_index() + + # Securely send the file from the 'activation' directory + try: + return send_from_directory('activation', filename) + except FileNotFoundError: + abort(404) + + +if __name__ == '__main__': + if len(sys.argv) > 1: + host, *rest = sys.argv[1].split(':', 1) + port = int(rest[0]) if rest else 8008 + else: + host, port = "localhost", 8008 + # Run the server in debug mode on port 5000 + app.run(debug=True, host=host, port=port) \ No newline at end of file From 422e5b601dce944248ff570c0de26f48c4c2ffd0 Mon Sep 17 00:00:00 2001 From: bbm Date: Fri, 27 Feb 2026 15:25:12 -0500 Subject: [PATCH 59/66] update sample query --- README.md | 170 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 88 insertions(+), 82 deletions(-) diff --git a/README.md b/README.md index ba411bb..ec9634e 100644 --- a/README.md +++ b/README.md @@ -162,119 +162,125 @@ Example ------- ```sh -$ curl -s -d "sample=Co" -X POST https://www.ncnr.nist.gov/cgi-bin/nact.py | python -m json.tool +$ curl -s -d '{"sample": "Co"}' -H "Content-Type: application/json" -X POST http://localhost:8008/api/calculate | python -m json.tool { - "sample": { - "name": "Co", - "density": 8.9, - "natural_density": 8.9, - "thickness": 1.0, - "mass": 1.0, - "formula": "Co" - }, "activation": { - "flux": 100000.0, - "decay_level": 0.001, - "total": [ - 0.5088248094656863, - 0.009706843055148993, - 1.550197781340068e-05, - 1.5423998799711213e-05 - ], - "rest": [ - 0, - 1, - 24, - 360 - ], + "Cd": 0.0, "activity": [ { - "reaction": "act", - "product": "Co-60", - "halflife": "5.272 y", - "comments": "s for 10m isomer added to ground state", + "comments": "", + "halflife": "10.5 m", + "isotope": "Co-59", "levels": [ - 1.550756280503848e-05, - 1.5507330056885684e-05, - 1.5501977813400642e-05, - 1.5423998799711213e-05 + 0.5087467869376632, + 0.009690144997026036, + 2.6447704770864502e-42, + 0.0 ], - "isotope": "Co-59" + "product": "Co-60m+", + "reaction": "act" }, { - "reaction": "act", - "product": "Co-60m+", - "halflife": "10.5 m", - "comments": "", + "comments": "Co-61 prod from Co-60m only", + "halflife": "1.65 h", + "isotope": "Co-59", "levels": [ - 0.5088093019028804, - 0.009691335725091536, - 2.6450954673146495e-42, - 0.0 + 7.305869373119584e-16, + 4.799870068457319e-16, + 3.0552994658480865e-20, + 1.52897407497221e-81 ], - "isotope": "Co-59" + "product": "Co-61", + "reaction": "2n" }, { - "reaction": "2n", - "product": "Co-61", - "halflife": "1.65 h", - "comments": "Co-61 prod from Co-60m only", + "comments": "s for 10m isomer added to ground state", + "halflife": "5.272 y", + "isotope": "Co-59", "levels": [ - 7.306767120646388e-16, - 4.800459878001244e-16, - 3.055674902007567e-20, - 1.5291619557875176e-81 + 1.5505657464889658e-05, + 1.5505424745333514e-05, + 1.5500073159453058e-05, + 1.5422103726672467e-05 ], - "isotope": "Co-59" + "product": "Co-60", + "reaction": "act" }, { - "reaction": "2n", - "product": "Co-61", - "halflife": "1.65 h", "comments": "Co-61 prod assuming all Co-60m has decayed to Co-60", + "halflife": "1.65 h", + "isotope": "Co-59", "levels": [ - 1.3649499897275873e-16, - 8.967560554449202e-17, - 5.7081926346341585e-21, - 2.8565705754412276e-82 + 1.3647822848511002e-16, + 8.966458753177e-17, + 5.707491296308241e-21, + 2.8562196022780084e-82 ], - "isotope": "Co-59" + "product": "Co-61", + "reaction": "2n" } ], + "decay_level": 0.001, + "decay_time": 1.5773360047132599, "exposure": 1.0, - "decay_time": 1.5773675158317233, "fast": 0.0, - "Cd": 0.0 + "flux": 100000.0, + "rest": [ + 0, + 1, + 24, + 360 + ], + "total": [ + 0.508762292595129, + 0.00970565042177194, + 1.5500073159453095e-05, + 1.5422103726672467e-05 + ] + }, + "sample": { + "density": 8.9, + "formula": "Co", + "formula_latex": "Co", + "mass": 1.0, + "name": "Co", + "natural_density": 8.9, + "thickness": 1.0 }, "scattering": { - "sld": { - "real": 2.2645416201426363, - "imag": 0.009403091502484154, - "incoh": 5.632988294016107 + "contrast_match": { + "D2O_fraction": 0.4066002243307043, + "sld": 2.2645414633790257 }, - "xs": { - "coh": 0.07085810248318081, - "abs": 1.8806183004968307, - "incoh": 0.43843639843243204 - }, - "penetration": 0.4184253079898973, "neutron": { - "wavelength": 1.0, - "energy": 81.80420235572412, - "velocity": 3956.0339760560055 + "energy": 81.80421023488275, + "velocity": 3956.0340061039888, + "wavelength": 1.0 + }, + "penetration": 0.4184253369555237, + "sld": { + "imag": 0.009403090851552168, + "incoh": 5.632980055822083, + "real": 2.2645414633790257 }, - "transmission": 9.163767420488476 + "transmission": 9.16376893656492, + "xs": { + "abs": 1.8806181703104334, + "coh": 0.07085931929382916, + "incoh": 0.4384351463657107 + } }, + "success": true, + "version": "2.0.2", "xray_scattering": { - "xray": { - "wavelength": 1.5418, - "energy": 8.041522080237366 - }, "sld": { - "real": 63.020248367719645, - "imag": 9.14097379704212 + "imag": 9.140742563282087, + "real": 63.02025244915057 + }, + "xray": { + "energy": 8.041522793695698, + "wavelength": 1.5418 } - }, - "success": true + } } ``` From 785bed829456a1cb21599fbc16559e95a06d3e13 Mon Sep 17 00:00:00 2001 From: bbm Date: Fri, 27 Feb 2026 15:30:42 -0500 Subject: [PATCH 60/66] replacing duplicate html with single index_template.html --- .../{index_pyodide_optimized.html => index_template.html} | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename activation/{index_pyodide_optimized.html => index_template.html} (99%) diff --git a/activation/index_pyodide_optimized.html b/activation/index_template.html similarity index 99% rename from activation/index_pyodide_optimized.html rename to activation/index_template.html index 71ea5cc..b661a5d 100644 --- a/activation/index_pyodide_optimized.html +++ b/activation/index_template.html @@ -12,8 +12,8 @@ - - + + @@ -44,7 +44,7 @@

    Material

    -
    +
    @@ -749,7 +749,7 @@
    -
    Using periodictable v2.0.2 From d1aa1d92a4215f6ced102e4ab59143cb5bdc588a Mon Sep 17 00:00:00 2001 From: bbm Date: Fri, 27 Feb 2026 15:35:58 -0500 Subject: [PATCH 61/66] need css and all js scripts in deployment --- deploy_calculator.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/deploy_calculator.sh b/deploy_calculator.sh index 2426346..149e045 100755 --- a/deploy_calculator.sh +++ b/deploy_calculator.sh @@ -9,11 +9,13 @@ TARGET_DIR=${TARGET_DIR:-/var/www/html/resources/activation} mkdir -p $TARGET_DIR cp activation/index_template.html $TARGET_DIR/index.html cp activation/jquery* $TARGET_DIR/ +cp activation/*.js $TARGET_DIR/ cp activation/webworker.js $TARGET_DIR/ cp activation/favicon.ico $TARGET_DIR/ cp activation/periodictable_wheel_name.txt $TARGET_DIR/ cp cgi-bin/nact.py $TARGET_DIR/ cp -r activation/pyodide $TARGET_DIR/pyodide +cp -r activation/css $TARGET_DIR/ # Get the version of periodictable from the wheel file name and write it to a text file for use in the workflow PERIODICTABLE_VERSION=$(python -c "import periodictable; print(periodictable.__version__)") From a25de2a20830ca57ae46dc46e9cb558a241c3722 Mon Sep 17 00:00:00 2001 From: bbm Date: Fri, 27 Feb 2026 16:59:25 -0500 Subject: [PATCH 62/66] add pyodide build artifacts to .gitignore --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index a0eb841..02a01ea 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,7 @@ endf/MT.DAT endf/PLOT.CHR endf/PLOT.SYM endf/*.out + +# pyodide build cruft +activation/pyodide +activation/periodictable_wheel_name.txt From 76aa759782ddca3f70f37b9fe93fa7e02325efc1 Mon Sep 17 00:00:00 2001 From: bbm Date: Fri, 27 Feb 2026 17:06:20 -0500 Subject: [PATCH 63/66] use macos-friendly sed invocation --- deploy_calculator.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deploy_calculator.sh b/deploy_calculator.sh index 149e045..4b97ea3 100755 --- a/deploy_calculator.sh +++ b/deploy_calculator.sh @@ -7,7 +7,6 @@ TARGET_DIR=${TARGET_DIR:-/var/www/html/resources/activation} # Now copy all the necessary files to the target directory for deployment: mkdir -p $TARGET_DIR -cp activation/index_template.html $TARGET_DIR/index.html cp activation/jquery* $TARGET_DIR/ cp activation/*.js $TARGET_DIR/ cp activation/webworker.js $TARGET_DIR/ @@ -21,5 +20,6 @@ cp -r activation/css $TARGET_DIR/ PERIODICTABLE_VERSION=$(python -c "import periodictable; print(periodictable.__version__)") # Write replacements in template -sed -i "s@{{ api_script }}@api_webworker.js@g" $TARGET_DIR/index.html -sed -i "s@{{ periodictable_version }}@$PERIODICTABLE_VERSION@g" $TARGET_DIR/index.html \ No newline at end of file +API_SUB="s@{{ api_script }}@api_webworker.js@g" +VER_SUB="s@{{ periodictable_version }}@$PERIODICTABLE_VERSION@g" +sed -e "$API_SUB;$VER_SUB" activation/index_template.html > "$TARGET_DIR/index.html" From 4b718b1a5afc8e22d9150a52b2940f36400f9d5e Mon Sep 17 00:00:00 2001 From: bbm Date: Fri, 27 Feb 2026 17:08:01 -0500 Subject: [PATCH 64/66] add pyodide deploy and test instructions --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index ec9634e..3f13508 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,19 @@ Additional files: * cgi-bin/hello.py is a minimal test script for python cgi. +Pyodide implementation +====================== +You can make a serverless install using pyodide to run the backend API. The `deploy_calculator.sh` +script will install to `/var/html/resources/activation/index.html`. + +To test the pyodide version before deploying, install into a temporary directory: +```sh +TARGET_DIR=/tmp/pt bash deploy_calculator.sh +(cd /tmp/pt && python -m http.server) +``` +You can then navigate to http://localhost:8000/index.html to view the application. + + Backend interface ================= From ea81f8732dea5e4eec261ddd1a83cf4d1d50b803 Mon Sep 17 00:00:00 2001 From: Brian Benjamin Maranville Date: Fri, 27 Feb 2026 17:38:39 -0500 Subject: [PATCH 65/66] BSD (macos) and GNU-friendly invocation of tar --- activation/get_pyodide.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/activation/get_pyodide.sh b/activation/get_pyodide.sh index 49d23da..9bc19e8 100755 --- a/activation/get_pyodide.sh +++ b/activation/get_pyodide.sh @@ -17,9 +17,7 @@ curl -L https://github.com/pyodide/pyodide/releases/download/${PYODIDE_VERSION}/ curl -L https://github.com/pyodide/pyodide/releases/download/${PYODIDE_VERSION}/pyodide-${PYODIDE_VERSION}.tar.bz2 -o pyodide_full.tar.bz2 # Extract only the core runtime + our specific wheels -tar -xjf pyodide_full.tar.bz2 -C ./pyodide --strip-components=1 \ - --wildcards --no-anchored \ - 'micropip-*.whl' 'numpy-*.whl' 'pytz-*.whl' 'pyparsing-*.whl' +tar -xjf pyodide_full.tar.bz2 "*micropip-*.whl" "*numpy-*.whl" "*pytz-*.whl" "*pyparsing-*.whl" # Download the latest periodictable wheel from PyPI pip3 download periodictable --no-deps --only-binary :all: -d ./pyodide/ From ed65f782df163088e1d0934e85940a0ca7aa19c8 Mon Sep 17 00:00:00 2001 From: bbm Date: Fri, 27 Feb 2026 17:47:08 -0500 Subject: [PATCH 66/66] need to nudge GNU tar with env variable that BSD ignores --- activation/get_pyodide.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activation/get_pyodide.sh b/activation/get_pyodide.sh index 9bc19e8..dc9e539 100755 --- a/activation/get_pyodide.sh +++ b/activation/get_pyodide.sh @@ -17,7 +17,7 @@ curl -L https://github.com/pyodide/pyodide/releases/download/${PYODIDE_VERSION}/ curl -L https://github.com/pyodide/pyodide/releases/download/${PYODIDE_VERSION}/pyodide-${PYODIDE_VERSION}.tar.bz2 -o pyodide_full.tar.bz2 # Extract only the core runtime + our specific wheels -tar -xjf pyodide_full.tar.bz2 "*micropip-*.whl" "*numpy-*.whl" "*pytz-*.whl" "*pyparsing-*.whl" +TAR_OPTIONS="--wildcards" tar -xjf pyodide_full.tar.bz2 "*micropip-*.whl" "*numpy-*.whl" "*pytz-*.whl" "*pyparsing-*.whl" # Download the latest periodictable wheel from PyPI pip3 download periodictable --no-deps --only-binary :all: -d ./pyodide/