Author: Jay Howson
Note: This page is under construction. I have example files to add, more pictures to add, code to write, etc. I’ll get to it eventually I promise.
Once I had my canberra spectroscopy system working, I found myself wanting more out of the MCA software. Both the MEDm and IDL software were convenient, in that MEDm at least was pre-installed with the EPICS software. Both did what they were supposed to do. However there was also a lot they did not do. The Canberra GENIE software was way to expensive for someone doing spectroscopy as a hobby to purchase. (it would be nice if Canberra offered a lite version of the software to amateurs)
I knew that others had gotten labview to interface with EPICS, I wondered if MATLAB could do the same. Sure enough it could.
Thru my work I have gained (over several years) a reasonable skill level at making GUI’s in matlab. I had yet to interface one to hardware but (not to toot my own horn) i’m pretty good at making a GUI with intelligent buttons and a decent user intuitiveness when it comes to data processing. I knew that matlab was a tool I could effectively and efficiently use to make a MCA environment which worked for me, and potentially others in the future.
Another benefit was the ability to request a home-use license for Matlab thru my work place which has been highly convenient to me thus far. I will be very sad if “the man” ever takes that job perk away from me.
The key to getting MATLAB and epics to play nice together, was a set of MATLAB scripts titled CA_MATLAB. I think there exists a new version at this point, but this is what I started with and I have not yet felt the need to try and upgrade.
- You can read about the software here
- and download here
- Note the version of Ca_Matlab i use was superceded by a new version which only works with 2019a or new matlab. Read more here
- Example Files
- Coming Soon
The author does a pretty good job at documenting how exactly to use it.
But I will write up my own micro tutorial here demonstrating how I use it.
- Place the file you downloaded into the main directory that you use for matlab.
- Such that a file titled “ca_matlab-1.0.0.jar” is in the 1st level down
- I also stick it in my scripts folder, out of convenience
- You will need to add this file and its folder to your matlab path
- accomplished via a right click, “add to path” on the parent directory
I will let the author explain the why behind the code on this own site, linked above. This code should be at the start of every script you try and make.
Site Note: The code display plugin doesn’t seem to respect the fact that I changed Octave to say Matlab.
import ch.psi.jcae.* if not(exist('java_classpath_set')) javaaddpath('Scripts\ca_matlab-1.0.0.jar') java_classpath_set = 1; end context = Context(); properties = java.util.Properties(); properties.setProperty('EPICS_CA_MAX_ARRAY_BYTES',getenv('EPICS_CA_MAX_ARRAY_BYTES')); context = Context(properties);
Now, I have discovered a few tricks to make things work smoothly in a gui environment. As you many know, a MATLAB GUI script is effectively a giant list of individual functions linked to a “. fig” file called callbacks. I like to use GUIDE, which creates both in tandem with one another auto creating callbacks when you add a graphical object. You can read more about the in’s and out’s of making GUI’s elsewhere.
Firstly, a context apparently needs to exist within every function. I didn’t want to have to go thru and repeat the above code for every single function, so I made context() a global variable
import ch.psi.jcae.* if not(exist('java_classpath_set')) javaaddpath('Scripts\ca_matlab-1.0.0.jar') java_classpath_set = 1; end global context(); context = Context(); properties = java.util.Properties(); properties.setProperty('EPICS_CA_MAX_ARRAY_BYTES',getenv('EPICS_CA_MAX_ARRAY_BYTES')); context = Context(properties);
Line 9, has to do with the max amount of bytes you can read at any one time. I was having issues reading all the data from EPICS into matlab. The fix is explained on the Canberra spectroscopy page. The important detail here is that the fix needs to be imported into the MATLAB environment as well. All Line 9 does is read the enviroment variable we created before, and assign its value to a property within the Context().
Now that we have initiated Ca_matlab we can try to issue or read some commands.
Each parameter and setting the AIM 556 controls has a unique channel. Each Channel has a unique name. Finding these unique names is a chore, i used MEDm and looked at the code behind each button (a right click on a button in MEDm will tell you all sorts of information about that button)
- First we create a channel
- Then we read or write to the channel
- Finally we close the channel
I’m unclear on what happens if you decide not to close a channel. I tried it and nothing bad seemed to happen, but i close all my channels anyway.
For example here is a snippet of code where i pull the number of channels my AIM is using and use that value to create a channel array. I assume you have the previously described code before this code in your script.
mcaTest_aim_adc1NUSE = Channels.create(context, ChannelDescriptor('double','mcaTest:aim_adc1.NUSE')); aim_adc1NUSE = mcaTest_aim_adc1NUSE.get(); channelArray = [1:1:aim_adc1NUSE]'; mcaTest_aim_adc1NUSE.close();
If you are inside of a function, or a callback for your GUI you need to bring your context into your function/callback. We made the context a global, thus
function Button(hObject, eventdata, handles) import ch.psi.jcae.* global context mcaTest_aim_adc1NUSE = Channels.create(context,ChannelDescriptor('double','mcaTest:aim_adc1.NUSE')); aim_adc1NUSE = mcaTest_aim_adc1NUSE.get(); channelArray = [1:1:aim_adc1NUSE]'; mcaTest_aim_adc1NUSE.close();
- the channel we accessed was “mcaTest:aim_adc1.NUSE”
- we access the mcaTest database in EPICS
- we access the AIM’s 1st ADC slot
- we accessed the NUSE variable,
- which is the number of channels in use on the AIM’s ADC1 slot
Of course doing all that every single time you want to access a channel is also annoying. So I made a function that I just needed to feed 2 variables.
function output = EPICS_READ(PV,type) %Ex %PV: database:pvVARIABLE %database = mcaTest %pv = hvps1 %VARIABLE = STATUS %mcaTest:hvps1STATUS % %options for type are %double, integer, short, float, byte, boolean, string and the respective array forms double, integer, int, short, float, byte, boolean, string %%%%%%%%%%%%%%%%%%%%% %https://github.com/channelaccess/ca_matlab global context import ch.psi.jcae.* channel = Channels.create(context, ChannelDescriptor(type, PV)); output = channel.get(); channel.close();
a write function is similar
function EPICS_WRITE(PV,type,value) %Ex %PV: database:pvVARIABLE %database = mcaTest %pv = hvps1 %VARIABLE = STATUS %mcaTest:hvps1STATUS % %options for type are %double, integer, short, float, byte, boolean, string and the respective array forms double, integer, int, short, float, byte, boolean, string %%%%%%%%%%%%%%%%%%%%% %https://github.com/channelaccess/ca_matlab global context import ch.psi.jcae.* channel = Channels.create(context, ChannelDescriptor(type, PV)); channel.put(value); channel.close();
PZValue = EPICS_READ('mcaTest:amp1PZRBV','double'); %read the pole Zero Value of my Canberra_9615 AMP EPICS_WRITE('mcaTest:adc1GAIN','double',aim_adc1GAIN-1); %The Canberra_9635 permits any of the below channel counts for its GAIN setting %256, 521, 1024, 2048, 4096, 8192, 16384 % However the ADC is zero referenced, so you must subtract 1 before writing a GAIN value Data = EPICS_READ('mcaTest_aim_adc1','integer'); %This will read data from the AIM, note how i had to use the integer type. %This allows for arrays to be read
I find that if I am writing or reading multiple commands in a single function, its faster to go direct, rather than using the EPICS_READ or EPICS_WRITE commands.
And that’s pretty much all there is to it.
After close to a year of work at this point, I think my MCA is coming along nicely. Granted I haven’t spent a solid year making it, but off and on work.
Every time I open up the code It gets better.
I should note, it is not my intention at this time to release my matlab MCA to the public. If you are a friend, we can talk. However, it has far to many bugs and I have no desire to offer program support to the masses. It is also fairly closely linked to my specific setup, if you don’t have my exact modules set, it wont run for you with out modification. I encourage you to learn and try and make your own. This work has all been a learning experience for me and I am better for it.
This far I have completed
- Full control over modules with menus and buttons for each available function
- Ability to save data with a footer which encompass all the settings
- Ability to load data
- Graphical Display of
- Current Read Data
- Background files
- Background subtracted (and interpolated) Read Data (in real time)
- It uses a ratio of live times to define a scaler.
- Comparative Data loaded into the GUI from saved files
- I can directly compare multiple saved files with data currently be collected
- Display data in channels or energy on the X-axis
- Display log or linear on both axies
- Other minor plot options
- Ability to input energy/channel information and perform a polynomial fit to calibrate the energy curve to your detector
- My Scionix_Detector works best with a cubic fit
- this energy data is preserved when you save a file, enabling you to always compare with other files when displayed in energy
- display a comparative fit between the two data sets, calculated verses input
- Stop data collection
- after a fixed time, live time or real time
- adjust units to suit your needs
- after a fixed sum of counts within a channel window
- after a fixed time, live time or real time
- I’m sure there is some other stuff I have implemented by I am forgetting to mention
Planned features to be added include
- Continuous never ending fixing of bugs as I find them
- Load different fits, for use with different detectors
- Additional plot display options
- Ability to turn on or off modules at startup
- such that I can vary my NIM setup if I chose to
- Data Tagging
- Label peaks as you see them with custom text
- Graphical Saves
- Save the spectrum as an image
- Auto State restore
- To read a files footer and auto set set all the settings based on it
- Waterfall plots and time linked measurements
- To graphically display half lives for short lives things like radon or neutron activation products from fusor runs.
- Isotope Energies Display (gamma for now)
- Displayed as vertical lines for each energy an isotope emits
- With relative intensities displayed as calculated and normalized variable height vertical lines for each energy an isotope emits.
- With optional daughter decay chain energies displayed as different color vertical lines at normalized variable heights
- Perhaps someday ill try my hand at isotope Identification, maybe
- I’m sure there is some other stuff I have had ideas to implement but I am forgetting to mention