def get_graph_xray(formula, dens, name=None, use_delta=False): material=Material(formula, dens=dens, name=name) # Generate the figure **without using pyplot**. fig = Figure() ax = fig.subplots() if use_delta: E, delta = material.delta_vs_E() ax.plot(E, delta, label='delta') E, beta = material.beta_vs_E() ax.plot(E, beta, label='beta') else: E, rho_x = material.rho_vs_E() ax.plot(E, rho_x.real/r_e_angstrom, label='Re') ax.plot(E, -rho_x.imag/r_e_angstrom, label='-Im') ax.legend() ax.set_xscale('log') ax.set_xlabel('E (keV)') ax.set_title('X-Ray optical parameters for %s'%name) if use_delta: ax.set_ylabel('refractive index components (1)') ax.set_yscale('log') else: ax.set_ylabel('electron density (rₑ/ų)') twin=ax.twinx() ymin, ymax=ax.get_ylim() twin.set_ylim(ymin*r_e*10., ymax*r_e*10) twin.set_ylabel('SLD (10⁻⁶ Å⁻²)') # Save it to a temporary buffer. buf = BytesIO() fig.savefig(buf, format="png") return bytes(buf.getbuffer())
def test_density(self): m1 = Material([(Element('Ni'), 1.0)], dens=8.9) m2 = Material([(Element('Fe'), 2.0), (Element('O'), 3.0)], dens=5.24) self.assertAlmostEqual(m1.dens, 8.9) self.assertAlmostEqual(m2.dens, 5.24) with self.assertRaises(ValueError): Material([(Element('Ni'), 1.0)], dens=5.0, fu_dens=1.04)
def test_lambda_interpolation(self): n = Element('B') self.assertAlmostEqual(n.b.imag, n.b_of_L(1.798).imag, 2) n.b_of_L(0) n.b_of_L(1000) m = Material('B', dens=2.5) self.assertAlmostEqual(m.rho_n.imag, m.rho_n_of_L(1.798).imag, 2) Material('O', dens=2.5).b_vs_L()
def test_neutron_d2o(self): m1 = Material([(Element('D'), 2.0), (Element('O'), 1.0)], dens=1.11) m2 = Material([(Element('H[2]'), 2.0), (Element('O'), 1.0)], dens=1.11) # compare with value from NIST self.assertAlmostEqual(m1.rho_n.real, REFERENCE_RESULTS['D2O'][0].real) self.assertAlmostEqual(m1.rho_n.imag, REFERENCE_RESULTS['D2O'][0].imag) self.assertEqual(m1.rho_n, m2.rho_n)
def test_rho_x(self): m1 = Material([(Element('Ni'), 1.0)], xsld=REFERENCE_RESULTS['Ni'][2], xE=Mo_kalpha) m2 = Material([(Element('Fe'), 2.0), (Element('O'), 3.0)], xsld=REFERENCE_RESULTS['Fe2O3'][1], xE=Cu_kalpha) self.assertAlmostEqual(m1.dens, 8.9, places=3) self.assertAlmostEqual(m2.dens, 5.24, places=3)
def test_exchange(self): m1 = Material('H2O', dens=1.0) m3 = Material('HHxO', fu_dens=m1.fu_dens) m3a = Material('HHxO', fu_dens=m1.fu_dens, name='test') m4 = Material('HDO', dens=1.0) self.assertEqual(m1.formula, m3.not_exchanged.formula) self.assertEqual(m4.formula, m3.exchanged.formula) self.assertAlmostEqual(m3a.not_exchanged.fu_dens, m1.fu_dens) self.assertAlmostEqual(m3a.exchanged.fu_dens, m1.fu_dens)
def test_fail(self): with self.assertRaises(ValueError): m1 = Material([(Element('Ni'), 1.0)]) with self.assertRaises(ValueError): m2 = Material([(Element('Pu'), 1.0)], dens=20.0) with self.assertRaises(ValueError): m3 = Material([(Element('Po'), 1.0)], dens=20.0) mok = Material('Ni', dens=1.0) with self.assertRaises(ValueError): -1 * mok
def test_volume(self): m1 = Material([(Element('Ni'), 1.0)], fu_volume=10.950863331638253) m2 = Material([(Element('Fe'), 2.0), (Element('O'), 3.0)], fu_volume=50.60467453722025) m3 = Material([(Element('Ni'), 1.0)], fu_dens=1. / 10.950863331638253) self.assertAlmostEqual(m1.dens, 8.9, places=6) self.assertAlmostEqual(m2.dens, 5.24, places=6) self.assertAlmostEqual(m1.dens, m3.dens, places=6) self.assertAlmostEqual(m1.fu_volume, 10.950863331638253, places=10) self.assertAlmostEqual(m2.fu_volume, 50.60467453722025, places=10) self.assertAlmostEqual(m3.fu_volume, 10.950863331638253, places=10) with self.assertRaises(ValueError): Material([(Element('Ni'), 1.0)], dens=5.0, fu_volume=10.950864)
def test_string_conversion(self): m2 = Material([(Element('Mo'), 1.0), (Element('Fe'), 2.0), (Element('O'), 3.2)], dens=5.24, ID=13) str(m2) repr(m2) m2 = Material([(Element('Mo'), 1.0), (Element('Fe'), 2.0), (Element('O'), 3.2)], dens=5.24, ID=None, name='MoFeO') str(m2) repr(m2)
def test_match_point(self): m1 = Material('H2O', dens=1.0) m2 = Material('D2O', fu_dens=m1.fu_dens) # replace D2O with one that has equal volume from slddb import material material.H2O = m1 material.D2O = m2 self.assertAlmostEqual((m1 + m2).match_point, 0.5) self.assertAlmostEqual((3 * m1 + m2).match_point, 0.25) self.assertAlmostEqual((m1 + 3 * m2).match_point, 0.75) m3 = Material('HDHx2O2', fu_dens=m1.fu_dens / 2.) self.assertAlmostEqual(m3.match_point, 0.5 / 1.1) m4 = Material('D3O', fu_dens=m1.fu_dens) self.assertTrue(m4.match_point > 1.0)
def test_neutron_fe2o3(self): m2 = Material([(Element('Fe'), 2.0), (Element('O'), 3.0)], dens=5.24) # compare with value from NIST self.assertAlmostEqual(m2.rho_n.real, REFERENCE_RESULTS['Fe2O3'][0].real) self.assertAlmostEqual(m2.rho_n.imag, REFERENCE_RESULTS['Fe2O3'][0].imag)
def test_magnetic(self): m0 = Material([(Element('Fe'), 2.0), (Element('O'), 3.0)], dens=5.24) m1 = Material([(Element('Fe'), 2.0), (Element('O'), 3.0)], dens=5.24, mu=3.5) m2 = Material([(Element('Fe'), 2.0), (Element('O'), 3.0)], dens=5.24, M=m1.M) self.assertEqual(m0.rho_m, 0.) self.assertEqual(m0.M, 0.) self.assertAlmostEqual(m1.mu, m2.mu) self.assertAlmostEqual(m1.rho_m, m2.rho_m) self.assertAlmostEqual(m1.M, m2.M) with self.assertRaises(ValueError): Material([(Element('Fe'), 2.0), (Element('O'), 3.0)], dens=5.24, mu=m1.mu, M=m1.M)
def get_absorption_graph(formula, dens, name=None): m=Material(formula, dens=dens, name=name) # Generate a graph for matching H2O/D2O with the given material if name is None: name=str(m.formula) fig = Figure() ax = fig.subplots() L,rho_n=m.rho_n_vs_L() ax.semilogx(L, -rho_n.imag*1e6) ax.set_xlabel('Wavelength [Å]') ax.set_ylabel('-Im(SLD) (10⁻⁶ Å⁻²)') ax.set_title('Neutron wavelength dependant absorption part of %s'%name) ax.set_xlim([0.2, 20.]) ax.grid() # Save it to a temporary buffer. buf = BytesIO() fig.savefig(buf, format="png") return bytes(buf.getbuffer())
def test_combine(self): m1 = Material([(Element('Ni'), 1.0)], fu_volume=1.0) m2 = Material([(Element('Co'), 1.0)], fu_volume=1.0) ms = m1 + m2 mss = m1 + m1 mp1 = 2.0 * m1 mp2 = m2 * 2.0 self.assertEqual(str(ms.formula), 'CoNi') self.assertEqual(str(mss.formula), 'Ni2') self.assertEqual(ms.fu_volume, 2.0) self.assertEqual(mp1.fu_volume, 2.0) self.assertEqual(mp2.fu_volume, 2.0) fs = m1.formula + m2.formula + m2.formula self.assertEqual(str(fs), 'Co2Ni') with self.assertRaises(ValueError): m1 + 'abc' with self.assertRaises(ValueError): 'abc' * m1
def test_deuteration(self): m1 = Material('H2O', dens=1.0) m2 = Material('D2O', fu_dens=m1.fu_dens) m3 = Material('HHxO', fu_dens=m1.fu_dens, name='exchangable') m4 = Material('HDO', fu_dens=m1.fu_dens) self.assertEqual(m1.deuterated.formula, m2.formula) self.assertAlmostEqual(m1.deuterated.fu_dens, m2.fu_dens) self.assertEqual(m3.deuterated.formula, m2.formula) self.assertAlmostEqual(m3.deuterated.fu_dens, m2.fu_dens) self.assertEqual(m1.deuterate(0.5).formula, m4.formula) self.assertAlmostEqual(m1.deuterate(0.5).fu_dens, m4.fu_dens) self.assertEqual(m3.edeuterated.formula, Formula('DHxO')) m5 = Material( 'HHxO', fu_dens=m1.fu_dens).edeuterated # check the case of name=None
def get_deuteration_graph(formula, dens, name=None): m=Material(formula, dens=dens, name=name) # Generate a graph for matching H2O/D2O with the given material if name is None: name=str(m.formula) mpoint=m.not_exchanged.match_point fig = Figure() ax = fig.subplots() ax.plot([0,100], [m.rho_n.real*1e6, m.rho_n.real*1e6], label=name, color='C0') ax.plot([0,100], [H2O.rho_n.real*1e6, D2O.rho_n.real*1e6], label='Water', color='C1') if mpoint>=0 and mpoint<=1: ax.plot([100*mpoint, 100*mpoint], [H2O.rho_n.real*1e6, m.rho_n.real*1e6], '--', label='Contrast Matched', color='C1') ax.text(100*mpoint, m.rho_n.real*1e6, '%.1f%%'%(100*mpoint), va='bottom', ha='right') if 'Hx' in m.formula: # create material where 90% exchangable sites are replace by deuterium md=m.exchange(0., 1.0, exchange=0.9) ax.plot([0,100], [m.rho_n.real*1e6, md.rho_n.real*1e6], label='90% exchange', color='C2') mpoint2=m.match_exchange(0., exchange=0.9) if mpoint2>=0 and mpoint2<=1: mrho=mpoint2*md.rho_n.real+(1-mpoint2)*m.rho_n.real ax.plot([100*mpoint2, 100*mpoint2], [H2O.rho_n.real*1e6, mrho*1e6], '--', label='Contrast Matched', color='C2') ax.plot([0*mpoint2, 100*mpoint2], [mrho*1e6, mrho*1e6], '--', color='C2') ax.text(100*mpoint2, mrho*1e6, '%.3f | %.1f%%'%(mrho*1e6, 100*mpoint2), va='bottom', ha='right') ax.legend() ax.set_xlabel('Water deuteration %') ax.set_ylabel('SLD (10⁻⁶ Å⁻²)') ax.set_title('Neutron contrast matching of %s'%name) ax.set_xlim([0., 100.]) ax.set_ylim([H2O.rho_n.real*1e6, D2O.rho_n.real*1e6]) # Save it to a temporary buffer. buf = BytesIO() fig.savefig(buf, format="png") return bytes(buf.getbuffer())
def calc_api(args): if 'protein' in args: try: material = collect_protein(args['protein']) except Exception as e: return repr(e) else: name = args.get('name', default='protein') elif 'dna' in args: try: material = collect_dna(args['dna']) except Exception as e: return repr(e) else: name = args.get('name', default='DNA') elif 'rna' in args: try: material = collect_rna(args['rna']) except Exception as e: return repr(e) else: name = args.get('name', default='RNA') elif 'formula' in args and 'density' in args: f = Formula(args['formula'], sort=False) try: material = Material(f, dens=float(args['density'])) except Exception as e: return repr(e) else: name = args.get('name', default='User Query') else: return 'Could not calculate, missing formula and density or protein/dna/rna sequence' material.name = name if args.get('material_description', default='') != '': material.extra_data['description'] = args['material_description'] out = material.export(xray_units=args.get('xray_unit', 'edens')) return json.dumps(out, indent=' ')
def test_xray_all(self): m2 = Material([(Element('Fe'), 2.0), (Element('O'), 3.0)], dens=5.24) E1, rho = m2.rho_vs_E() E2, delta = m2.delta_vs_E() E3, beta = m2.beta_vs_E() E4, mu = m2.mu_vs_E() assert_array_equal(E1, E2) assert_array_equal(E1, E3) assert_array_equal(E1, E4)
def test_xray_kalpha(self): m2 = Material([(Element('Fe'), 2.0), (Element('O'), 3.0)], dens=5.24) # compare calculated values with known parameters from external sources with self.subTest('Cu', i=0): sld = m2.rho_of_E(Cu_kalpha) # sld-calculator.appspot.com: 4.1125e-05 -3.6347e-06 self.assertAlmostEqual(sld.real, 4.1125e-05) self.assertAlmostEqual(sld.imag, -3.6347e-06) # Henke: 8047.82959 eV delta=1.55382077E-05 beta=1.37184929E-06 self.assertAlmostEqual(m2.delta_of_E(Cu_kalpha1), 1.55382E-05, places=5) self.assertAlmostEqual(m2.beta_of_E(Cu_kalpha1), 1.37185E-06, places=5) # Henke: 8047.83 eV mu=8.93664 µm self.assertAlmostEqual(m2.mu_of_E(Cu_kalpha1), 1. / 8.93664e4, places=5) with self.subTest('Mo', i=1): sld = m2.rho_of_E(Mo_kalpha) # sld-calculator.appspot.com: 4.274e-05 -9.5604e-07 self.assertAlmostEqual(sld.real, 4.274e-05) self.assertAlmostEqual(sld.imag, -9.5604e-07) # Henke: 17479.4004 eV delta=3.4223483E-06 beta=7.66335759E-08 self.assertAlmostEqual(m2.delta_of_E(Mo_kalpha1), 3.4223483E-06, places=5) self.assertAlmostEqual(m2.beta_of_E(Mo_kalpha1), 7.66335759E-08, places=5) # Henke: 17479.4 eV mu=73.6570 µm self.assertAlmostEqual(m2.mu_of_E(Mo_kalpha1), 1. / 73.6570e4, places=5)
def calculate_user(formula, density, mu, density_choice, mu_choice, name=None, material_description=""): kwrds={} if density==0: return render_template('sldcalc.html', error="Density can not be zero!") if density_choice=='density': kwrds['dens']=density elif density_choice=='volume': kwrds['fu_volume']=density elif density_choice=='FUdens': kwrds['fu_dens']=density elif density_choice=='FUdnm': kwrds['fu_dens']=density*1e-3 if mu_choice=='muB': kwrds['mu']=mu elif mu_choice=='magn': kwrds['M']=mu try: material=Material([(get_element(element), amount) for element, amount in formula], **kwrds) except Exception as e: traceback.print_exc() return render_template('sldcalc.html', error=repr(e)) else: match_point=0.0 E, rho_x=material.rho_vs_E() _, delta=material.delta_vs_E() _, beta=material.beta_vs_E() script='' # get_graph(E, rho_x.real, rho_x.imag, name or str(formula)) if 'H' in material.formula or 'Hx' in material.formula or 'D' in material.formula: deuterated=material.deuterated if 'Hx' in material.formula: exchanged=material.exchanged match_point = 100.*material.match_exchange() else: exchanged=None else: deuterated=None exchanged=None if 'H' in material.formula or 'Hx' in material.formula or 'D' in material.formula: contrast_matching = True else: contrast_matching = False return render_template('sldcalc.html', material=material, deuterated=deuterated, exchanged=exchanged, match_point=match_point, contrast_matching = contrast_matching, material_name=name or "User input", material_description=material_description, script=script, xray_E=E.tolist(), xray_rho_real=nan_to_num(rho_x.real).tolist(), xray_rho_imag=nan_to_num(rho_x.imag).tolist(), xray_delta=nan_to_num(delta).tolist(), xray_beta=nan_to_num(beta).tolist())
def test_neutron_ni(self): m1 = Material([(Element('Ni'), 1.0)], dens=8.9) # compare with value from NIST self.assertAlmostEqual(m1.rho_n.real, REFERENCE_RESULTS['Ni'][0].real) self.assertAlmostEqual(m1.rho_n.imag, REFERENCE_RESULTS['Ni'][0].imag)
return redirect(url_for('calculate_sld', _anchor='results_header', formula=str(result.formula), density=result.fu_volume, name=name or mtype, description=result.extra_data.get('description', None), **CALC_DEFAULT_FIELDS)) def collect_blend(mtype, idstr): if mtype=='protein': return collect_protein(idstr) elif mtype=='dna': return collect_dna(idstr) elif mtype=='rna': return collect_rna(idstr) elif mtype=='db': return collect_blendIDs(idstr) hx2o=Material([(get_element(element), amount) for element, amount in [('Hx', 2.0), ('O', 1.0)]], dens=1.0) def collect_protein(acids): acids=clean_str(acids).upper() result=collect_combination(acids, AMINO_ABRV)+hx2o result.extra_data['description']=f'protein - {len(acids)} residues' return result def collect_dna(bases): bases=clean_str(bases).upper() result=collect_combination(bases, DNA_ABRV)+hx2o result.extra_data['description']=f'DNA - {len(bases)} residues' return result def collect_rna(bases): bases=clean_str(bases).upper() result=collect_combination(bases, RNA_ABRV)+hx2o
def test_creation(self): m1 = Material([(Element('Ni'), 1.0)], dens=1.0) m2 = Material('Ni', dens=1.0) m3 = Material(Formula('Ni'), dens=1.0) with self.assertRaises(TypeError): m4 = Material(123.4, dens=1.0)
def test_formula(self): m1 = Material([(Element('Ni'), 1.0)], xsld=REFERENCE_RESULTS['Ni'][2], xE=Mo_kalpha) self.assertEqual(str(m1.formula), 'Ni') self.assertEqual(m1.formula, Formula([('Ni', 1.0)]))
def test_rho_n(self): m1 = Material([(Element('Ni'), 1.0)], rho_n=REFERENCE_RESULTS['Ni'][0]) m2 = Material([(Element('Fe'), 2.0), (Element('O'), 3.0)], rho_n=REFERENCE_RESULTS['Fe2O3'][0]) self.assertAlmostEqual(m1.dens, 8.9, places=3) self.assertAlmostEqual(m2.dens, 5.24, places=3)
def test_dict_conversion(self): m1 = Material([(Element('Mo'), 1.0), (Element('Fe'), 2.0), (Element('O'), 3.2)], dens=5.24, ID=13) m1.export(xray_units='sld') m1.export(xray_units='n_db') m1.export(xray_units='edens') with self.assertRaises(ValueError): m1.export(xray_units='test') m2 = Material('B[10]4C', dens=2.55) m2.export()