{ "cells": [ { "cell_type": "markdown", "id": "delayed-redhead", "metadata": {}, "source": [ "# Widgets\n", "McStasScript includes a few widgets designed for use in Jupyter Notebooks. They are not loaded with the standard import package as they rely on additional dependencies and requires more time to import which is not appropriate for scripts." ] }, { "cell_type": "code", "execution_count": null, "id": "lasting-donna", "metadata": {}, "outputs": [], "source": [ "import mcstasscript as ms\n", "import mcstasscript.jb_interface as ms_widget" ] }, { "cell_type": "markdown", "id": "silver-portal", "metadata": {}, "source": [ "## Set up of an example instrument\n", "As an example we set up a simple model of a time of flight powder diffractometer on a long pulsed source." ] }, { "cell_type": "code", "execution_count": null, "id": "fleet-genealogy", "metadata": { "tags": [ "scroll-input" ] }, "outputs": [], "source": [ "instrument = ms.McStas_instr(\"POWTOF\")\n", "\n", "instrument.add_parameter(\"double\", \"Lmin\", value=0.5, comment=\"[AA] Lower edge of wavelength band\")\n", "instrument.add_parameter(\"double\", \"Wavelength_band\", value=1.8, comment=\"[AA] Width of wavelength band\")\n", "instrument.add_parameter(\"double\", \"two_theta\", value=90.0, comment=\"[deg] TOF det 2 theta\")\n", "instrument.add_parameter(\"double\", \"npulses\", value=2.0,\n", " comment=\"[1] Number of pulses from source\",\n", " options=[1, 2, 3, 4, 5, 6])\n", "\n", "instrument.add_declare_var(\"int\", \"npulses_declare\")\n", "instrument.add_declare_var(\"double\", \"Lmax\")\n", "instrument.add_declare_var(\"double\", \"Lcenter\")\n", "\n", "instrument.append_initialize(\"npulses_declare=npulses; \")\n", "instrument.append_initialize(\"Lmax = Lmin + Wavelength_band; \")\n", "\n", "instrument.add_declare_var(\"double\", \"sample_position\", value=160)\n", "\n", "Origin = instrument.add_component(\"Origin\", \"Progress_bar\")\n", "\n", "Source = instrument.add_component(\"Source\", \"Source_simple\")\n", "Source.yheight = 0.03\n", "Source.xwidth = 0.03\n", "Source.dist = \"sample_position\"\n", "Source.focus_xw = 0.03\n", "Source.focus_yh = 0.03\n", "Source.lambda0 = \"Lmin + 0.5*Wavelength_band\"\n", "Source.dlambda = \"0.5*Wavelength_band\"\n", "Source.flux = 1E13\n", "Source.append_EXTEND(\"double t_between_pulses=1.0/14.0;\")\n", "Source.append_EXTEND(\"double pulse_n=(double) floor(rand01()*npulses_declare);\")\n", "Source.append_EXTEND(\"double pulse_delay=t_between_pulses*pulse_n;\")\n", "Source.append_EXTEND(\"t=2860*rand01()*1E-6 + pulse_delay;\")\n", "Source.set_AT(0, RELATIVE=Origin)\n", "\n", "instrument.add_declare_var(\"double\", \"tmax_source\")\n", "instrument.add_declare_var(\"double\", \"last_pulse_t\")\n", "instrument.append_initialize(\"last_pulse_t = 1E6*(npulses-1)*1/14.0;\")\n", "instrument.append_initialize(\"tmax_source = 3000 + 1.1*last_pulse_t;\")\n", "\n", "TOFmon1 = instrument.add_component(\"TOFmon1\", \"TOF_monitor\")\n", "TOFmon1.nt = 200\n", "TOFmon1.filename = '\"TOFmon1\"'\n", "TOFmon1.xwidth = 0.02\n", "TOFmon1.yheight = 0.02\n", "TOFmon1.tmin = 0\n", "TOFmon1.tmax = \"tmax_source\"\n", "TOFmon1.restore_neutron = 1\n", "TOFmon1.set_AT([0, 0, 1e-6], RELATIVE=Source)\n", "\n", "TOFLambda1 = instrument.add_component(\"TOFLambda1\", \"TOFLambda_monitor\")\n", "TOFLambda1.nL = 200\n", "TOFLambda1.nt = 300\n", "TOFLambda1.tmin = 0\n", "TOFLambda1.tmax = \"tmax_source\"\n", "TOFLambda1.filename = '\"TOFLambda1\"'\n", "TOFLambda1.xwidth = 0.02\n", "TOFLambda1.yheight = 0.02\n", "TOFLambda1.Lmin = 0.1\n", "TOFLambda1.Lmax = 5\n", "TOFLambda1.restore_neutron = 1\n", "TOFLambda1.set_AT([0, 0, 1e-6], RELATIVE=Source)\n", "\n", "PSD = instrument.add_component(\"PSD\", \"PSD_monitor\")\n", "PSD.filename = '\"PSD\"'\n", "PSD.xwidth = 0.03\n", "PSD.yheight = 0.03\n", "PSD.set_AT([0, 0, 0.5], RELATIVE=Source)\n", "\n", "\n", "instrument.add_parameter(\"double\", \"enable_chopper_1\", value=0,\n", " comment=\"Enable clockwise chopper\", options=[0, 1])\n", "instrument.add_parameter(\"double\", \"enable_chopper_2\", value=0,\n", " comment=\"Enable counter clockwise chopper\", options=[0, 1])\n", "\n", "instrument.add_declare_var(\"double\", \"speed\")\n", "instrument.add_declare_var(\"double\", \"delay\")\n", "instrument.add_declare_var(\"double\", \"chopper_position\", value=6.5)\n", "instrument.append_initialize(\"Lcenter = Lmin + 0.5*Wavelength_band; \")\n", "instrument.append_initialize(\"speed = 2.0*PI/Lcenter*K2V; \")\n", "instrument.append_initialize(\"delay = chopper_position/speed; \")\n", "instrument.append_initialize(\"delay = delay + 1.340E-3; \")\n", "instrument.add_parameter(\"frequency_multiplier\", value=1,\n", " comment=\"[1] Chopper frequency as multiple of source frequency\")\n", "\n", "chopper = instrument.add_component(\"chopper\", \"DiskChopper\")\n", "chopper.theta_0 = 4.0\n", "chopper.radius = 0.35\n", "chopper.yheight = 0.03\n", "chopper.nu = \"frequency_multiplier*14.0\"\n", "chopper.delay = \"delay\"\n", "chopper.set_AT([0, 0, 'chopper_position - 0.01'], RELATIVE=Source)\n", "chopper.set_WHEN(\"enable_chopper_1 > 0.5\")\n", "\n", "counter_chopper = instrument.add_component(\"counter_chopper\", \"DiskChopper\")\n", "counter_chopper.theta_0 = 4.0\n", "counter_chopper.radius = 0.35\n", "counter_chopper.yheight = 0.03\n", "counter_chopper.nu = \"-frequency_multiplier*14.0\"\n", "counter_chopper.delay = \"delay\"\n", "counter_chopper.set_AT([0, 0, 'chopper_position - 0.005'], RELATIVE=Source)\n", "counter_chopper.set_WHEN(\"enable_chopper_2 > 0.5\")\n", "\n", "instrument.add_declare_var(\"double\", \"speed_max\")\n", "instrument.append_initialize(\"speed_max = 2*PI/Lmin*K2V;\")\n", "\n", "instrument.add_declare_var(\"double\", \"speed_min\")\n", "instrument.append_initialize(\"speed_min = 2*PI/Lmax*K2V;\")\n", "\n", "instrument.add_declare_var(\"double\", \"chopper_tmin\")\n", "instrument.add_declare_var(\"double\", \"chopper_tmax\")\n", "instrument.append_initialize(\"chopper_tmin = 0.9*1E6*chopper_position/speed_max;\")\n", "instrument.append_initialize(\"chopper_tmax = 1.1*1E6*chopper_position/speed_min + tmax_source;\")\n", "\n", "TOFmon2 = instrument.add_component(\"TOFmon2\", \"TOF_monitor\")\n", "TOFmon2.nt = 100\n", "TOFmon2.filename = '\"TOFmon2\"'\n", "TOFmon2.xwidth = 0.02\n", "TOFmon2.yheight = 0.02\n", "TOFmon2.tmin = \"chopper_tmin\"\n", "TOFmon2.tmax = \"chopper_tmax\"\n", "TOFmon2.restore_neutron = 1\n", "TOFmon2.set_AT([0, 0, 'chopper_position'], RELATIVE=Source)\n", "\n", "TOFLambda2 = instrument.add_component(\"TOFLambda2\", \"TOFLambda_monitor\")\n", "TOFLambda2.nL = 200\n", "TOFLambda2.nt = 300\n", "TOFLambda2.tmin = \"chopper_tmin\"\n", "TOFLambda2.tmax = \"chopper_tmax\"\n", "TOFLambda2.filename = '\"TOFLambda2\"'\n", "TOFLambda2.xwidth = 0.02\n", "TOFLambda2.yheight = 0.02\n", "TOFLambda2.Lmin = 0.1\n", "TOFLambda2.Lmax = 5\n", "TOFLambda2.restore_neutron = 1\n", "TOFLambda2.set_AT([0, 0, 'chopper_position'], RELATIVE=Source)\n", "\n", "instrument.add_declare_var(\"double\", \"sample_tmin\")\n", "instrument.add_declare_var(\"double\", \"sample_tmax\")\n", "instrument.append_initialize(\"sample_tmin = 0.9*1E6*sample_position/speed_max;\")\n", "instrument.append_initialize(\"sample_tmax = 1.1*1E6*sample_position/speed_min + last_pulse_t;\")\n", "\n", "TOFmon3 = instrument.add_component(\"TOFmon3\", \"TOF_monitor\")\n", "TOFmon3.nt = 200\n", "TOFmon3.filename = '\"TOFmon3\"'\n", "TOFmon3.xwidth = 0.02\n", "TOFmon3.yheight = 0.02\n", "TOFmon3.tmin = \"sample_tmin\"\n", "TOFmon3.tmax = \"sample_tmax\"\n", "TOFmon3.restore_neutron = 1\n", "TOFmon3.set_AT([0, 0, 'sample_position'], RELATIVE=Source)\n", "\n", "TOFLambda3 = instrument.add_component(\"TOFLambda3\", \"TOFLambda_monitor\")\n", "TOFLambda3.nL = 200\n", "TOFLambda3.nt = 300\n", "TOFLambda3.tmin = \"sample_tmin\"\n", "TOFLambda3.tmax = \"sample_tmax\"\n", "TOFLambda3.filename = '\"TOFLambda3\"'\n", "TOFLambda3.xwidth = 0.02\n", "TOFLambda3.yheight = 0.02\n", "TOFLambda3.Lmin = 0.1\n", "TOFLambda3.Lmax = 5\n", "TOFLambda3.restore_neutron = 1\n", "TOFLambda3.set_AT([0, 0, 'sample_position'], RELATIVE=Source)\n", "\n", "Sample = instrument.add_component(\"Sample\", \"Powder1\")\n", "Sample.radius = 0.003\n", "Sample.yheight = 0.02\n", "Sample.q = 5\n", "Sample.d_phi = 12\n", "Sample.set_AT([0, 0, 'sample_position'], RELATIVE=Source)\n", "\n", "beamstop = instrument.add_component(\"beamstop\", \"Beamstop\")\n", "beamstop.radius = 0.2\n", "beamstop.set_AT([0, 0, 0.5], RELATIVE=Sample)\n", "\n", "TOF_cylPSD = instrument.add_component(\"TOF_cylPSD\", \"TOF_cylPSD_monitor\")\n", "TOF_cylPSD.nt = 200\n", "TOF_cylPSD.nphi = 180\n", "TOF_cylPSD.filename = '\"TOF_cylPSD\"'\n", "TOF_cylPSD.radius = 2.0\n", "TOF_cylPSD.yheight = 0.20\n", "TOF_cylPSD.tmin = \"sample_tmin\"\n", "TOF_cylPSD.tmax = \"sample_tmax\"\n", "TOF_cylPSD.restore_neutron = 1\n", "TOF_cylPSD.set_AT([0, 0, 0], RELATIVE=Sample)\n", "\n", "TOFdetArm = instrument.add_component(\"TOFdetArm\", \"Arm\")\n", "TOFdetArm.set_AT([0, 0, 0], RELATIVE=Sample)\n", "TOFdetArm.set_ROTATED([0, 'two_theta', 0], RELATIVE=Sample)\n", "\n", "TOFdet = instrument.add_component(\"TOFdet\", \"TOF_monitor\")\n", "TOFdet.nt = 100\n", "TOFdet.filename = '\"TOFdet\"'\n", "TOFdet.xwidth = 0.01\n", "TOFdet.yheight = 0.2\n", "TOFdet.tmin = 70000\n", "TOFdet.tmax = 80000\n", "TOFdet.restore_neutron = 1\n", "TOFdet.set_AT([0, 0, 2.001], RELATIVE=TOFdetArm)" ] }, { "cell_type": "code", "execution_count": null, "id": "three-public", "metadata": { "scrolled": true }, "outputs": [], "source": [ "data = instrument.backengine()" ] }, { "cell_type": "markdown", "id": "facial-monkey", "metadata": {}, "source": [ "## Plotting interface\n", "The data generated by the above instrument can now be shown in a widget interface. Before launching the interface it is important to choose the widget backend for matplotlib, which is done in the following cell. The *show* function in ms_widget is then used to display the interface, it just needs the returned data as an argument." ] }, { "cell_type": "code", "execution_count": null, "id": "patient-shelter", "metadata": {}, "outputs": [], "source": [ "%matplotlib widget" ] }, { "cell_type": "code", "execution_count": null, "id": "seven-dairy", "metadata": {}, "outputs": [], "source": [ "#ms_widget.show(data)" ] }, { "cell_type": "markdown", "id": "global-extension", "metadata": {}, "source": [ "An image of the interface is shown below as the interactive widget is not currently working in the HTML documentation.\n", "\n", "![plotting interface](plotting_widget.png \"Plotting widget\")" ] }, { "cell_type": "markdown", "id": "thirty-patch", "metadata": {}, "source": [ "In the above interface the left side shows the current plot, and the right side contains a dropdown box for selecting the a new plot and plot options. The log plot checkbox works for both 1D and 2D data, though the remaining options are only applied for 2D datasets." ] }, { "cell_type": "markdown", "id": "aware-applicant", "metadata": {}, "source": [ "## Simulation interface\n", "It is also possible to run the simulation from a widget, simply pass an instrument object to the *show* function." ] }, { "cell_type": "code", "execution_count": null, "id": "adolescent-monte", "metadata": { "scrolled": false }, "outputs": [], "source": [ "#ms_widget.show(instrument)" ] }, { "cell_type": "markdown", "id": "supported-contrast", "metadata": {}, "source": [ "An image of the interface is shown below as the interactive widget is not currently working in the HTML documentation.\n", "\n", "![simulation interface](simulation_widget.png \"Simulation widget\")" ] }, { "cell_type": "markdown", "id": "announced-passage", "metadata": {}, "source": [ "The top of the interface contains all input parameters of the instrument. These can be either text fields or dropdown boxes, the latter being the case if options are given to the parameter object. The next elements from the top is the run button, ncount field and mpi field. Pressing the run button starts the simulation, and while it is running, the icon will be an hourglass. Underneath is the plotting interface which will be updated each time a simulation completes." ] }, { "cell_type": "markdown", "id": "convenient-honolulu", "metadata": {}, "source": [ "### Interface object\n", "The *show* function does not allow the user to retrieve the simulated data. If that is desired one instead have to use the *SimInterface* class that creates a SimInterface object. This object can be used to show display the interface with *show_interface*." ] }, { "cell_type": "code", "execution_count": null, "id": "entertaining-pantyhose", "metadata": {}, "outputs": [], "source": [ "sim_interface = ms_widget.SimInterface(instrument)\n", "#sim_interface.show_interface()" ] }, { "cell_type": "markdown", "id": "swedish-dubai", "metadata": {}, "source": [ "Through the *SimInterface* object it is possible to access data from the last simulation." ] }, { "cell_type": "code", "execution_count": null, "id": "verbal-concentrate", "metadata": {}, "outputs": [], "source": [ "data = sim_interface.get_data()" ] }, { "cell_type": "markdown", "id": "chronic-theater", "metadata": {}, "source": [ "## Instrument diagram as a widget\n", "The last widget included in McStasScript is the instrument diagram, though it only behaves in an interactive manner when the matplotlib widget backend is used. As a widget it is possible to get information on each component box by hovering the mouse of the left edge of the box. " ] }, { "cell_type": "code", "execution_count": null, "id": "manual-series", "metadata": {}, "outputs": [], "source": [ "#instrument.show_diagram()" ] }, { "cell_type": "markdown", "id": "arabic-adult", "metadata": {}, "source": [ "An image of the interface is shown below as the interactive widget is not currently working in the HTML documentation.\n", "\n", "![instrument diagram](instrument_diagram_widget.png \"Instrument diagram\")" ] }, { "cell_type": "code", "execution_count": null, "id": "neutral-azerbaijan", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "celltoolbar": "Tags", "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.8" } }, "nbformat": 4, "nbformat_minor": 5 }