diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..c4dd004 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,42 @@ +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: Run deployment script + run: | + export PYODIDE_VERSION=0.29.3 + export TARGET_DIR=dist + ./deploy_calculator.sh + - 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 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; +} diff --git a/activation/get_pyodide.sh b/activation/get_pyodide.sh new file mode 100755 index 0000000..49d23da --- /dev/null +++ b/activation/get_pyodide.sh @@ -0,0 +1,32 @@ +# !/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} + +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 +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 + +# Cleanup +rm -f pyodide.tar.bz2 +rm -f pyodide_full.tar.bz2 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 + + + + - - - - - - - + + + + + + + + + + + + +
+ +
+ +

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/activation/webworker.js b/activation/webworker.js new file mode 100644 index 0000000..3e4fa7c --- /dev/null +++ b/activation/webworker.js @@ -0,0 +1,65 @@ +// webworker.js + +import { loadPyodide } from "./pyodide/pyodide.mjs"; +// 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("./${wheelName}") + import periodictable + print(periodictable.__version__) + `) + + // Downloading a single file + await pyodide.runPythonAsync(` + from pyodide.http import pyfetch + response = await pyfetch("./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({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 { + let python = ` + request = json.loads('${json_data}') + form = FakeFieldStorage(request) + 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 diff --git a/cgi-bin/nact.py b/cgi-bin/nact.py index 24cc2f8..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 @@ -253,8 +248,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') @@ -492,8 +486,10 @@ def cgi_call(): if __name__ == "__main__": + import cgi try: - response = cgi_call() + form = cgi.FieldStorage() + response = cgi_call(form) except Exception: response = { 'success': False, diff --git a/deploy_calculator.sh b/deploy_calculator.sh new file mode 100755 index 0000000..93d5c00 --- /dev/null +++ b/deploy_calculator.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