tschoonj / xmimsim

Monte Carlo simulation of energy-dispersive X-ray fluorescence spectrometers
Other
32 stars 11 forks source link

gobject-introspection support #42

Closed tschoonj closed 5 years ago

tschoonj commented 5 years ago

@NGeorgescu

Inspired by your work on writing the Python front-end for XMI-MSIM, I decided to take it one step further in this PR:

By modifying the API (renaming methods and changing arguments in some places), I have now enabled support for GObject-Introspection, which means that you can use XMI-MSIM from all languages that support it: the main examples being Python (PyGObject) and JavaScript (GJS).

For example you will be able to create XMI-MSIM input-files, run them, read in the output-files etc. I also have preliminary support for some of the GUI widgets so you will be able to display the output in the results page as well.

Feel free to give this a try and let me know what you think...

An example in Python follows...

from __future__ import print_function

import gi
gi.require_version('XmiMsim', '1.0')
from gi.repository import XmiMsim, GLib

# Load the XML catalog
XmiMsim.xmlLoadCatalog()

# create new input-file from scratch and save it
# general
general = XmiMsim.General.new('test.xmso', n_photons_interval=10000, n_photons_line=1000000, n_interactions_trajectory=4)

# composition
layer0 = XmiMsim.Layer.new([7, 8, 18], [0.7, 0.29, 0.01], 0.001, 2)
layer1 = XmiMsim.Layer.new([8, 16, 29, 92], [0.276479, 0.100464, 0.199048, 0.424009], 2.5, 1)
composition = XmiMsim.Composition.new([layer0, layer1], reference_layer=2)

# geometry
geometry = XmiMsim.Geometry.new(
  d_sample_source=100.0,
  n_sample_orientation=[0.0, 1.0, 1.0],
  p_detector_window=[0.0, -1.0, 100],
  n_detector_orientation=[0, 1, 0],
  area_detector=0.3,
  collimator_height=0.0,
  collimator_diameter=0.0,
  d_source_slit=100.0,
  slit_size_x=0.001,
  slit_size_y=0.001
  )

# excitation
excitation = XmiMsim.Excitation.new(discrete=[XmiMsim.EnergyDiscrete.new(20.0, 1E9, 1E9, 0.0, 0.0, 0.0, 0.0, XmiMsim.EnergyDiscreteDistribution.MONOCHROMATIC, 0.0)])

# absorbers
absorbers = XmiMsim.Absorbers.new(det_layers=[XmiMsim.Layer.new(Z=[4], weight=[1.0], density=1.85, thickness=0.002)])

# detector
detector = XmiMsim.Detector.new(
  detector_type=XmiMsim.DetectorConvolutionProfile.SILI, 
  live_time=1.0,
  pulse_width=1.0E-5,
  gain=0.02,
  zero=0,
  fano=0.12,
  noise=0.1,
  nchannels=2048,
  crystal_layers=[XmiMsim.Layer.new(Z=[14], weight=[1.0], density=2.33, thickness=0.5)]
  )

# input
input = XmiMsim.Input.new(general, composition, geometry, excitation, absorbers, detector)

# write to file
input.write_to_xml_file('test.xmsi')

# simulate
options = XmiMsim.MainOptions.new()
job = XmiMsim.Job.new(
   "/usr/local/bin/xmimsim",
   "test.xmsi",
   options)

# hook up signals with callbacks
def finished_cb(job, result, message, loop):
    print("result: {}".format(result))
    print("message: {}".format(message))
    loop.quit()

def print_stdout_cb(job, string):
    print("stdout: {}".format(string))

def print_stderr_cb(job, string):
    print("stderr: {}".format(string))

loop = GLib.MainLoop.new(None, False)
job.connect('finished-event', finished_cb, loop)
job.connect('stdout-event', print_stdout_cb)
job.connect('stderr-event', print_stderr_cb)

job.send_all_stdout_events(True) # prints even progress to stdout...

job.start()
loop.run() # this will block until the simulation finishes

# read the XMSO file in
output = XmiMsim.Output.read_from_xml_file("test.xmso")

# get spectrum as list of doubles
spectra = output.get_spectrum_convoluted(4) # after 4 interactions!

# get history as dict
history = output.get_history()

# counts for Cu-KL3 after all interactions
counts = history[29].lines['KL3'].total_counts

# show in results widget
gi.require_version('XmiMsimGui', '1.0')
gi.require_version('Gtk', '3.0')
from gi.repository import XmiMsimGui, Gtk
XmiMsimGui.init()
sw = XmiMsimGui.XmsoResultsScrolledWindow()
sw.load_from_file("test.xmso")
win = Gtk.Window()
win.set_position(Gtk.WindowPosition.CENTER)
win.add(sw)
win.set_default_size(800, 800)
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()
NGeorgescu commented 5 years ago

Cool stuff. Does it work with Windows out of curiosity?

tschoonj commented 5 years ago

If you're using MSYS2 then yes: I am running a Python unittest on AppVeyor so it definitely works.

However, Anaconda won't work unfortunately as there are currently no builds for gobject-introspection and pygobject...

tschoonj commented 5 years ago

The unittest code is here:

https://github.com/tschoonj/xmimsim/blob/ff47fb88ab66df718fa753032a40c27c4c8d07b2/tests/test-gi-xmimsim.py#L1-L889

NGeorgescu commented 5 years ago

Cool I will stare this with my collaborators who may be very interested.