diff --git a/Examples/python/fitting/ex08_SimultaneousFitOfTwoDatasets/SimultaneousFitOfTwoDatasets.py b/Examples/python/fitting/ex08_SimultaneousFitOfTwoDatasets/SimultaneousFitOfTwoDatasets.py index ed2c227f83886e1c25980964644143b5ad66aeca..8821793f3fcec6b5f3340afda7ecb2e39d9bc4eb 100644 --- a/Examples/python/fitting/ex08_SimultaneousFitOfTwoDatasets/SimultaneousFitOfTwoDatasets.py +++ b/Examples/python/fitting/ex08_SimultaneousFitOfTwoDatasets/SimultaneousFitOfTwoDatasets.py @@ -80,31 +80,23 @@ class DrawObserver(ba.IFitObserver): self.fig.canvas.draw() plt.ion() - def plot_colormap(self, data, title, min=1.0, max=1e6): - im = plt.imshow( - data.getArray(), - norm=matplotlib.colors.LogNorm(min, max), - extent=[data.getXmin()/deg, data.getXmax()/deg, - data.getYmin()/deg, data.getYmax()/deg], - aspect='auto') - plt.colorbar(im) - plt.title(title) - def plot_datasets(self, fit_suite, canvas): for i_dataset in range(0, fit_suite.numberOfFitObjects()): - real_data = fit_suite.getRealData(i_dataset) - simul_data = fit_suite.getSimulationData(i_dataset) - chi2_map = fit_suite.getChiSquaredMap(i_dataset) + real_data = fit_suite.experimentalData(i_dataset) + simul_data = fit_suite.simulationResult(i_dataset) + chi2_map = fit_suite.relativeDifference(i_dataset) + + zmax = real_data.histogram2d().getMaximum() plt.subplot(canvas[i_dataset*3]) - self.plot_colormap(real_data, "\"Real\" data - #"+str(i_dataset+1), - min=1.0, max=real_data.getMaximum()) + ba.plot_colormap(real_data, title="\"Real\" data - #"+str(i_dataset+1), + zmin=1.0, zmax=zmax, zlabel="") plt.subplot(canvas[1+i_dataset*3]) - self.plot_colormap(simul_data, "Simulated data - #"+str(i_dataset+1), - min=1.0, max=real_data.getMaximum()) + ba.plot_colormap(simul_data, title="Simulated data - #"+str(i_dataset+1), + zmin=1.0, zmax=zmax, zlabel="") plt.subplot(canvas[2+i_dataset*3]) - self.plot_colormap(chi2_map, "Chi2 map - #"+str(i_dataset+1), - min=0.001, max=10.0) + ba.plot_colormap(chi2_map, title="Chi2 map - #"+str(i_dataset+1), + zmin=0.001, zmax=10.0, zlabel="") def plot_fit_parameters(self, fit_suite, canvas): # fit parameters @@ -125,7 +117,7 @@ class DrawObserver(ba.IFitObserver): # most of the space canvas = matplotlib.gridspec.GridSpec( 3, 3, width_ratios=[1, 1, 1], height_ratios=[4, 4, 1]) - canvas.update(left=0.05, right=0.95, hspace=0.4, wspace=0.2) + canvas.update(left=0.05, right=0.95, hspace=0.5, wspace=0.2) self.plot_datasets(fit_suite, canvas) self.plot_fit_parameters(fit_suite, canvas) diff --git a/Examples/python/simulation/ex03_InterferenceFunctions/Interference1DLattice.py b/Examples/python/simulation/ex03_InterferenceFunctions/Interference1DLattice.py index 2d4d2c65f482096b7c69516df2a5fcf4e59090d2..b478a6d1307605e39f82f994b05d12110f4c515f 100644 --- a/Examples/python/simulation/ex03_InterferenceFunctions/Interference1DLattice.py +++ b/Examples/python/simulation/ex03_InterferenceFunctions/Interference1DLattice.py @@ -1,34 +1,37 @@ """ -Long boxes on a 1D lattice +Simulation of grating using very long boxes and 1D lattice. +Monte-carlo integration is used to get rid of +large-particle form factor oscillations. """ -import numpy import bornagain as ba from bornagain import deg, angstrom, nm -def get_sample(): +def get_sample(lattice_rotation_angle=45*deg): """ - Returns a sample with a grating on a substrate. - The structure is modelled by infinitely long boxes forming a 1D lattice. + Returns a sample with a grating on a substrate, + modelled by very long boxes forming a 1D lattice with Cauchy correlations. """ # defining materials m_ambience = ba.HomogeneousMaterial("Air", 0.0, 0.0) m_substrate = ba.HomogeneousMaterial("Substrate", 6e-6, 2e-8) m_particle = ba.HomogeneousMaterial("Particle", 6e-4, 2e-8) + box_length, box_width, box_height = 10*nm, 10000*nm, 10*nm + lattice_length = 30*nm + # collection of particles - lattice_length = 30.0*nm - lattice_rotation_angle = 0.0*deg interference = ba.InterferenceFunction1DLattice( lattice_length, lattice_rotation_angle) - pdf = ba.FTDecayFunction1DCauchy(20./2./numpy.pi*nm) + pdf = ba.FTDecayFunction1DCauchy(1000.0) interference.setDecayFunction(pdf) - box_ff = ba.FormFactorBox(1000*nm, 10*nm, 15.0*nm) + box_ff = ba.FormFactorBox(box_length, box_width, box_height) box = ba.Particle(m_particle, box_ff) - transform = ba.RotationZ(25.0*deg) + particle_layout = ba.ParticleLayout() - particle_layout.addParticle(box, 1.0, ba.kvector_t(0.0, 0.0, 0.0), transform) + particle_layout.addParticle( + box, 1.0, ba.kvector_t(0.0, 0.0, 0.0), ba.RotationZ(lattice_rotation_angle)) particle_layout.setInterferenceFunction(interference) # assembling the sample @@ -49,7 +52,8 @@ def get_simulation(): simulation = ba.GISASSimulation() simulation.setDetectorParameters(200, -1.0*deg, 1.0*deg, 200, 0.0*deg, 2.0*deg) - simulation.setBeamParameters(24.0*angstrom, 0.2*deg, 0.0*deg) + simulation.setBeamParameters(1.0*angstrom, 0.2*deg, 0.0*deg) + simulation.getOptions().setMonteCarloIntegration(True, 100) return simulation @@ -59,10 +63,11 @@ def run_simulation(): """ simulation = get_simulation() simulation.setSample(get_sample()) + simulation.setTerminalProgressMonitor() simulation.runSimulation() return simulation.result() if __name__ == '__main__': result = run_simulation() - ba.plot_simulation_result(result) + ba.plot_simulation_result(result, 1e-03) diff --git a/Examples/python/simulation/ex03_InterferenceFunctions/RectangularGrating.py b/Examples/python/simulation/ex03_InterferenceFunctions/RectangularGrating.py index bdb63ec0fa301151fc5cbed1fc875249d7fd1354..c5e7b472662ddb33dec040db2d7e38fa4aeb6c2c 100644 --- a/Examples/python/simulation/ex03_InterferenceFunctions/RectangularGrating.py +++ b/Examples/python/simulation/ex03_InterferenceFunctions/RectangularGrating.py @@ -4,30 +4,31 @@ Monte-carlo integration is used to get rid of large-particle form factor oscillations. """ import bornagain as ba -from bornagain import deg, angstrom, nm +from bornagain import deg, angstrom, nm, micrometer -def get_sample(lattice_rotation_angle=45*deg): +def get_sample(lattice_rotation_angle=0.0*deg): """ - Returns a sample with a grating on a substrate, - modelled by very long boxes forming a 1D lattice with Cauchy correlations. + Returns a sample with a grating on a substrate. + lattice_rotation_angle = 0 - beam parallel to grating lines + lattice_rotation_angle = 90*deg - beam perpendicular to grating lines """ # defining materials m_ambience = ba.HomogeneousMaterial("Air", 0.0, 0.0) - m_substrate = ba.HomogeneousMaterial("Substrate", 6e-6, 2e-8) - m_particle = ba.HomogeneousMaterial("Particle", 6e-4, 2e-8) + m_si = ba.HomogeneousMaterial("Si", 5.78164736e-6, 1.02294578e-7) - box_length, box_width, box_height = 10*nm, 10000*nm, 10*nm - lattice_length = 30*nm + box_length, box_width, box_height = 50*micrometer, 70*nm, 50*nm + lattice_length = 150*nm # collection of particles interference = ba.InterferenceFunction1DLattice( - lattice_length, lattice_rotation_angle) - pdf = ba.FTDecayFunction1DCauchy(1000.0) + lattice_length, 90.0*deg - lattice_rotation_angle) + + pdf = ba.ba.FTDecayFunction1DGauss(450.0) interference.setDecayFunction(pdf) - box_ff = ba.FormFactorBox(box_length, box_width, box_height) - box = ba.Particle(m_particle, box_ff) + box_ff = ba.FormFactorLongBoxLorentz(box_length, box_width, box_height) + box = ba.Particle(m_si, box_ff) particle_layout = ba.ParticleLayout() particle_layout.addParticle( @@ -37,11 +38,16 @@ def get_sample(lattice_rotation_angle=45*deg): # assembling the sample air_layer = ba.Layer(m_ambience) air_layer.addLayout(particle_layout) - substrate_layer = ba.Layer(m_substrate) + substrate_layer = ba.Layer(m_si) + + roughness = ba.LayerRoughness() + roughness.setSigma(5.0 * nm) + roughness.setHurstParameter(0.5) + roughness.setLatteralCorrLength(10.0 * nm) multi_layer = ba.MultiLayer() multi_layer.addLayer(air_layer) - multi_layer.addLayer(substrate_layer) + multi_layer.addLayerWithTopRoughness(substrate_layer, roughness) return multi_layer @@ -50,9 +56,10 @@ def get_simulation(): Create and return GISAXS simulation with beam and detector defined """ simulation = ba.GISASSimulation() - simulation.setDetectorParameters(200, -1.0*deg, 1.0*deg, - 200, 0.0*deg, 2.0*deg) - simulation.setBeamParameters(1.0*angstrom, 0.2*deg, 0.0*deg) + simulation.setDetectorParameters(200, -0.5*deg, 0.5*deg, + 200, 0.0*deg, 0.6*deg) + simulation.setBeamParameters(1.34*angstrom, 0.4*deg, 0.0*deg) + simulation.setBeamIntensity(1e+08) simulation.getOptions().setMonteCarloIntegration(True, 100) return simulation diff --git a/GUI/coregui/Views/widgetbox/images/Lattice2DFinite.png b/GUI/coregui/Views/widgetbox/images/Lattice2DFinite.png new file mode 100644 index 0000000000000000000000000000000000000000..87b601e84ef60aabda663b6413bcb2c4df39d02b Binary files /dev/null and b/GUI/coregui/Views/widgetbox/images/Lattice2DFinite.png differ diff --git a/GUI/coregui/Views/widgetbox/widgetbox.qrc b/GUI/coregui/Views/widgetbox/widgetbox.qrc index 848b11fc1f23c61d21ba202020a1b637089f66ca..861427053d77c33a56363eb93c39b6c933db03a3 100644 --- a/GUI/coregui/Views/widgetbox/widgetbox.qrc +++ b/GUI/coregui/Views/widgetbox/widgetbox.qrc @@ -36,5 +36,6 @@ <file>images/SizeDistribution.png</file> <file>images/Lattice1D.png</file> <file>images/sample_layers2.png</file> + <file>images/Lattice2DFinite.png</file> </qresource> </RCC> diff --git a/GUI/coregui/Views/widgetbox/widgetbox.xml b/GUI/coregui/Views/widgetbox/widgetbox.xml index 066096c1b45aabf4c9271d50a62971b3fa4f6693..f26b6eefa82af3b55430d4d94dd7a51978ebeb7c 100644 --- a/GUI/coregui/Views/widgetbox/widgetbox.xml +++ b/GUI/coregui/Views/widgetbox/widgetbox.xml @@ -67,7 +67,7 @@ </widget> </categoryentry> - <categoryentry name="Finite 2D lattice" icon="images/Lattice2D.png"> + <categoryentry name="Finite 2D lattice" icon="images/Lattice2DFinite.png"> <widget class="InterferenceFinite2DLattice"> <property name="objectName"> <string notr="true">somestring</string> diff --git a/Tests/Functional/Python/PyPersistence/CMakeLists.txt b/Tests/Functional/Python/PyPersistence/CMakeLists.txt index 41ddb1ff5942b87d021be16168f689c3b17a2b6a..48f340e77a09cc06a937731f52a9f76734ba0ae0 100644 --- a/Tests/Functional/Python/PyPersistence/CMakeLists.txt +++ b/Tests/Functional/Python/PyPersistence/CMakeLists.txt @@ -36,7 +36,7 @@ test_example("simulation/ex03_InterferenceFunctions/ApproximationDA" 2e-10) test_example("simulation/ex03_InterferenceFunctions/ApproximationLMA" 2e-10) test_example("simulation/ex03_InterferenceFunctions/ApproximationSSCA" 2e-10) test_example("simulation/ex03_InterferenceFunctions/CosineRipplesAtRectLattice" 2e-10) -test_example("simulation/ex03_InterferenceFunctions/Interference1DLattice" 2e-10) +test_example("simulation/ex03_InterferenceFunctions/Interference1DLattice" 1.5) test_example("simulation/ex03_InterferenceFunctions/Interference1DRadialParaCrystal" 2e-10) test_example("simulation/ex03_InterferenceFunctions/Interference2DCenteredSquareLattice" 2e-10) test_example("simulation/ex03_InterferenceFunctions/Interference2DParaCrystal" 2e-10) diff --git a/Tests/ReferenceData/Python/Interference1DLattice.ref.int.gz b/Tests/ReferenceData/Python/Interference1DLattice.ref.int.gz index e8001e5bf71180634769eaa2dd9c85c8742252d1..834d93bd01543fa71c32f7a1e2f70d19e73741e6 100644 Binary files a/Tests/ReferenceData/Python/Interference1DLattice.ref.int.gz and b/Tests/ReferenceData/Python/Interference1DLattice.ref.int.gz differ diff --git a/Tests/ReferenceData/Python/RectangularGrating.ref.int.gz b/Tests/ReferenceData/Python/RectangularGrating.ref.int.gz index 3ba9799af330a01a4d84949b0204c5d66be280fb..0d7e955b23bf83f827995fe6c6d65f4d71d854a4 100644 Binary files a/Tests/ReferenceData/Python/RectangularGrating.ref.int.gz and b/Tests/ReferenceData/Python/RectangularGrating.ref.int.gz differ diff --git a/dev-tools/code-tools/update-website.py b/dev-tools/code-tools/update-website.py new file mode 100644 index 0000000000000000000000000000000000000000..6e0982b1ccf286d8833f80c660880f35ceeea43a --- /dev/null +++ b/dev-tools/code-tools/update-website.py @@ -0,0 +1,120 @@ +""" +To update examples on website: + +1) Run in your build directory +ctest -R PyExamples +This will run all existing examples and generate intensity images for web site. + +2) Modify variables in this script +WEBSITE_DIR, BORNAGAIN_SOURCE, EXAMPLE_IMAGES + +3) Run this script +python update-examples.py + +TODO: move the script under ctest control +""" +import os +import shutil + +WEBSITE_DIR = "/home/pospelov/development/BornAgain-website" +BORNAGAIN_SOURCE = "/home/pospelov/development/BornAgainHub/BornAgain" +EXAMPLE_IMAGES = "/home/pospelov/development/BornAgainHub/build/test_output/Functional/Python/PyExamples" + + +def copy_file_to_file(source, destination): + """ + Copies file to another. + """ + shutil.copyfile(source, destination) + + +def find_files(dir_name): + """ + Yield recursive list of files in given dir_name + """ + for subdir, dirs, files in os.walk(dir_name): + for filename in files: + yield subdir, filename + + +def get_files(dir_name, extension): + """ + Return list of all files in subdirectories of dir_name with given extension + """ + result = [] + for subdir, filename in find_files(dir_name): + name, ext = os.path.splitext(filename) + if ext in extension: + result.append(os.sep.join([subdir, filename])) + return result + + +def find_files_with_same_name(filename_list, name_to_find): + same_names = [] + for filename in filename_list: + if os.path.basename(filename) == name_to_find: + same_names.append(filename) + + return same_names + + +def copy_files(source_list, destination_list): + """ + Every file in destination_list will be replaced by the file with the same + basename found in source_list + """ + missed_files = [] + updated_files = [] + for f in destination_list: + found_source = find_files_with_same_name(source_list, os.path.basename(f)) + if len(found_source) == 1: + updated_files.append(f) + copy_file_to_file(found_source[0], f) + else: + print(len(found_source), "Problem with ", f) + missed_files.append(f) + + print("Summary:") + + print("Following files have been updated on website:") + for f in updated_files: + print(f) + + if len(missed_files): + print("Following files exist on website but not in source dir:") + for f in missed_files: + print(f) + + +def update_example_images(): + """ + Copies example intensity images from build directory to website directory + """ + website = os.path.join(WEBSITE_DIR, "content/documentation/sample-models") + source = EXAMPLE_IMAGES + website_files = get_files(website, ".png") + source_files = get_files(source, ".png") + + copy_files(source_files, website_files) + + +def update_example_scripts(): + """ + Copies example scripts from BornAgain directory to website directory + """ + website = os.path.join(WEBSITE_DIR, "static/files/python") + source = os.path.join(BORNAGAIN_SOURCE, "Examples/python") + website_files = get_files(website, ".py") + source_files = get_files(source, ".py") + + copy_files(source_files, website_files) + + +def update_website(): + update_example_images() + update_example_scripts() + + +if __name__ == '__main__': + update_website() +