Spectra Difference Generator - Subtract, add, divide or multiply two spectra with precise control
Thu, 02/04/2021 - 04:48 am
This is a tool for conveniently aligning and comparing two (1D) data waves and calculate their difference, sum, product or quotient on the fly. The first input data is modified via controls while second input data acts as the reference to compare against. The former can be shifted, offset and scaled manually with respect to the reference to find the optimal overlap or to extract certain spectral features from the difference etc. The the original purpose was to calculate differences only (hence the name Difference Generator), but support for addition, multiplication and division has been added.
The underlying original data of both the edited wave and reference wave is never modified in any way. The comparison is handled with temporary data, and modifications (default wave ending "_mod") as well as the arithmetic result are always saved as new output waves. The default wave ending for the output is "_dif" for subtraction, "_sum" for addition, "_mul" for multiplication and "_div" for division. All settings are saved in the output wave's notes and will be reloaded automatically upon restarting the tool with the same input. The program is fully folder aware.
I tried my best to test everything thoroughly, but you should verify the correct behavior yourself to be sure. Bug reports and suggestions for new features are always welcome.
Graphical User Interface (GUI) controls
To start the user interface, select one or two (1D) waves in the Data Browser and then go to 'Spectra Tools' -> 'Compare and Modify Spectra ....' in the top menu. Or use the command line:
The second wave selected in the Data Browser (or the wave provided by the optional 'refwave' parameter) comes preselected as reference when starting the GUI. A quick overview of all controls can be found below:
- The wave to modify and the reference wave are selected from the current folder. The current folder can be changed in the Data Browser during operation (while the GUI is open) to use waves from a different folder. The list of waves in the drop-down menu will reflect always the available 1D waves in the currently active folder.
- Both waves can be smoothed (Gaussian broadened). The smoothing is saved in the modified output (ending '_mod'). The smoothing of the reference wave is only for display and to calculate the result, but is, of course, not actually applied to the original reference data. However, the smoothing setting is saved with the output and will be reapplied upon reloading. Use the home / end keyboard shortcuts to increase / decrease smoothing (holding alt/option will smooth the reference data).
- Chose the mode of operation in the drop-down menu: A-B subtraction (- keyboard key), A+B addition (+ key), A*B multiplication (* key) or A/B division (/ key).
- The result can be inverted (flipped in Y direction) with the Invert checkbox (i key). The state of all checkboxes is saved with the output and will be reapplied upon reloading.
- The wave to modify can be moved in X / horizontal and Y / vertical directions using the arrow buttons (cursor keys on the keyboard).
- Scaling is done with the stretch (page up key) and shrink (page down key) controls.
- The delta step of each modification can be set using the variable controls to the left.
- Or use the controls for absolute changes to dial in the desired shift and scaling directly.
- Next to the controls for absolute changes are reset buttons for all modifications or individual changes of the X/Y shift or scaling.
- Discard & Quit will just close the interface without saving anything.
- Save & Quit will save the current state as output waves (edited wave name + "_mod" and "_dif" etc.) and then closes the interface. Optionally, the result is displayed in a new graph afterwards if the relevant checkbox is active. At the same time, all previous graphs with the same data set displayed are updated as well to reflect the new modification settings.
Additional keyboard shortcuts:
- Hold Command (Mac) / Ctrl (Win) for changes in steps of 0.5 times the current delta value.
- Hold Shift for changes in steps of 10 times the current delta value.
- Hold both Shift + Command / Ctrl for changes in steps of 0.1 times the current delta value.
- r key to ‘Reset All'
- p key to toggle ‘Pin Background’
- Hold Command (Mac)/ Ctrl (Win) while pressing ‘Reset All’ and the reference wave will be set to none.
- Hold Command (Mac)/ Ctrl (Win) while pressing ‘Save & Quit’ to override quitting (save only, and the windows stays open). This can be used to compare many waves in quick succession, e.g., by selecting the next wave from the drop-down menu.
- Hold Option (Mac) / Alt (Win) while pressing ‘Save & Quit’ to force 'Use Ref. Name' for saving (this has the same function as the respective checkbox).
How the result is saved
The result is saved next to the input wave (the data to edit) as 'wavename + "_mod"' for the modified data and 'wavename + "_dif"' (or "_sum", "_mul", "_div" depending on the mode) for the (inverted) result. All modification settings are saved inside the wave note of both of these output waves. Here is an example where 'first spectrum' was edited and 'second spectrum' was the reference:
Loading the tool with the same initial data ('first spectrum' in this case) will reload the last session from the '_mod' or '_dif' wave (if '_mod' does not exist). Note that loading a '_dif' or '_mod' wave directly will just start a new session with this data (this makes it possible to create differences of differences etc.).The wave to edit and the reference wave can be in different folders. If neither a 'dif' (or 'sum', 'mul', 'div') or 'mod' wave with the same name is found in the input wave's folder, then the default settings are loaded. It is thus recommended to move the result and modified waves together with the original wave to a new folder to be able to reload the settings later. Then what will be reloaded if you have mixed result waves from summing, multiplying etc.? The loading hierarchy is 'mod' > 'dif' > 'sum' > 'mul' > 'div', and thus deleting the 'mod' and 'dif' waves will load the settings from the 'sum' wave if present.
What is the purpose of the 'Use Ref. Name' setting?
Imagine the following scenario: A 'baseline' data and then several spectra have been measured in succession like this:
Lets assume you want to remove the baseline wave from all the spectra, but the spectra should not be modified (for example, to preserve their relative shift or intensity). This is achieved by modifying (shifting, scaling etc.) the baseline for each spectrum individually and then saving the calculation result next to each spectrum. Load the baseline as wave to modify and one spectrum as reference, then do the modification (since the roles of edited wave and reference are reversed here, this usually means 'Invert' needs to be activated). Before saving check 'Use Ref. Name' to save the result next to each spectrum. This will give:
What if you reload spectrum1 but have conflicting settings in waves spectrum1_mod and spectrum1_dif? In this case spectrum1_mod is loaded according to the hierarchy 'mod' > 'dif' > 'sum' > 'mul' > 'div'.
Running your own code:
You can generate comparisons of two waves using the function:
The WaveArithmeticStruct structure looks like this:
Variable mode // mode: 1: Subtract (A-B) 2: Add (A+B) 3: Multiply (A*B) 4: Divide (A/B)
Wave orgWave // [mandatory] wave to compare 1 - will NOT be modified
Wave refWave // [mandatory] wave to compare 2 - will NOT be modified
Wave cmpWave // [mandatory] result of comparison between orgWave and refWave
Wave modWave // [optional] modified wave - saves modifed version of orgWave
Wave modRefWave // [optional] modified ref. wave - saves smoothed version of refWave
// optional input parameters:
Variable orgSmooth // amount of smoothing for wave 1 (default 0)
Variable refSmooth // amount of smoothing for wave 2 (default 0)
Variable baselineYval // y value of the baseline (default 0)
Variable baselineXval // x position of the baseline (default NaN)
Variable baselineFixed // baseline is omitted from Y scaling if set to 1 (default 0)
Variable invert // invert the output in Y (default 0)
Variable xShift // modify wave 1: x displacement (in wave's units)
Variable yShift // modify wave 1: y displacement (offset)
Variable yScale // modify wave 1: y scaling (default 1)
In your code, use the structure to pass the input waves and desired parameters to the function. You need to pass at least the two input (orgWave and refWave) and one output wav (cmpWave; this one will be overwritten). A simple example code could look like this:
STRUCT WaveArithmeticStruct s
WaveArithmeticInitialize(s) // initialize structure parameters with defaults
Duplicate/O wave1, $(NameOfWave(wave1)+"_dif")
Wave s.cmpWave = $(NameOfWave(wave1)+"_dif")
Wave s.orgWave = wave1
Wave s.refWave = wave2
s.refSmooth = 0.5 // smooth wave2 (optional; data will not be altered)
s.xshift = -0.02 // shift wave1 (optional; data will not be altered)
String statusmsg = WaveArithmeticKernel(s)
If the same wave endings (e.g., "_dif") are used then the output is fully compatible with the user interface, i.e., the same settings will be loaded when starting the interface with the same input waves.
Settings inside the procedure header
The procedure header contains several settings as static constants which are used by the user interface, and can be edited to your liking (but you should not mess with these unless really necessary):
static StrConstant kOutEnd = "_dif;_sum;_mul;_div;"
static StrConstant kAuxEnd = "_smt;_int;"
// the following constants define the string keys for saving and loading parameters from wave notes
static StrConstant kScaleKey = "Mod Scale"
static StrConstant kShiftKey = "Mod Shift"
static StrConstant kOffsetKey = "Mod Offset"
static StrConstant kModSmthKey = "Mod Smooth"
static StrConstant kRefSmthKey = "Ref Smooth"
static StrConstant kXCsrSetKey = "Cursor Set"
static StrConstant kSetModeKey = "Data difference;Data summed;Data multiplied;Data divided;"
static StrConstant kModeInvKey = "Result inverted"
static StrConstant kPinBaseKey = "Baseline scaled"
static StrConstant kRefNameKey = "Reference name used"
- The name endings ("_dif", "_mod" etc.) for saving the result waves can be modified here, should there be a conflict with other names in your experiment (in fact, Igor's own Differentiate function will also use 'dif' as name ending).
- The string keys for saving the settings into the result wave's note are editable as well, but altering these keys might make saved results incompatible for reloading later (if these keys are changed again).
Current Project Release
|Release File:||Difference Generator_v4.50.zip|
|Version Date:||Tue, 03/22/2022 - 03:30 am|
|Version Patch Level:||5|
|OS Compatibility:||Windows Mac-Intel|
Igor Pro 9
Igor XOP Toolkit
Igor NIDAQ Tools MX