![](/profiles/wavemetrics/themes/wavemetrics/logo.png)
Violin plots
![](/sites/default/files/styles/thumbnail/public/sjr51/profile-images/2018-07/cube.png?itok=iXDZATA2)
sjr51
#pragma rtGlobals=3 // Use modern global access method and strict wave access. #include <Percentile and Box Plot> //Before executing, you need to have plotted the boxplots using Percentile and Box Plot //Plot the box plots into a target window using all waves from a source window //This is a limitation of the functions, they rely on two graph windows (source and target) for making the violins. //A width of 0.1 is good for the box plots and the boxplots look better with whiskers going to 0 and 100 rather than 10 and 90 (Igor default) Menu "Macros" "Violin Plot...", ViolinPlot() "Scrub Violins", ClearViolins() End Function ViolinPlot () String sourceWindow // window with the waves to make boxplot and violins String targetWindow // window with the boxplots to add violins Variable trimValue=1 // violins can be trimmed (default) or plotted with long tails Variable thickValue=0.1 // this is the width of the boxplot Prompt sourceWindow, "What is the source graph?", popup, WinList("*", ";", "WIN:1") Prompt targetWindow, "What is the box plot graph?", popup, WinList("*", ";", "WIN:1") Prompt trimValue, "yes=1, no=0" Prompt thickValue, "auto=0.1" DoPrompt "Pick graphs", sourceWindow, targetWindow, trimValue, thickValue String/G gSrcWin = sourceWindow //set global strings and variables String/G gTgtWin = targetWindow Variable/G gtrim = trimValue Variable/G gthick = thickValue DoWindow /F $sourceWindow String wlist = Wavelist("*",";","WIN:") String name Variable nWaves = ItemsInList(wlist) Variable i for(i = 0; i < nWaves; i += 1) name = StringFromList(i,wList) //picks waves from source window and sends them to be plotted as violins in target window Wave w0 = $name Violin(w0,i) endfor DoWindow /F $targetWindow SetAxis/A/N=1/E=1 left SetAxis bottom -0.5,(nWaves-0.5) End /// @param w 1D wave for plotting as violin /// @param xpos variable to describe where violin will go on x-axis Function Violin(w,xpos) Wave w Variable xpos SVAR srcWin = gSrcWin //set local ref for global strings SVAR tgtWin = gTgtWin NVAR trim = gtrim NVAR thick = gThick Variable nPoints = numpnts(w) Variable xMin, xMax if(trim == 1) xMin = wavemin(w) xMax = wavemax(w) // trimmed violins else Variable bw = ((4 * sqrt(variance(w))^5) / (3 * numpnts(w)))^0.2 // this is Silverman's rule-of-thumb xMin = wavemin(w) - (2*bw) xMax = wavemax(w) + (2*bw) // not trimmed, limit kde to 2 bandwidths beyond min/max endif Variable dX = min((xMax - xMin) / 100,1) // delta x for StatsKDE StatsKDE/Q/BWM=2/DEST=kdeWave/KT=1/S={xMin,dX,xMax} w WAVE/Z w1 = kdeWave Variable auc = sum(w1) w1 /= auc * (thick / 2) // omit *thick for a violin=2 i.e. two half-violins that =1 String wnL = NameofWave(w) + "_kdeL" Duplicate/D/O w1 $wnL String wnR = NameofWave(w) + "_kdeR" Duplicate/D/O w1 $wnR String wnLx = NameofWave(w) + "_kdeLx" Duplicate/D/O w1 $wnLx String wnRx = NameofWave(w) + "_kdeRx" Duplicate/D/O w1 $wnRx String vwny = NameofWave(w) + "_kdevy" String vwnx = NameofWave(w) + "_kdevx" KillWaves/Z w1 Wave wnL1 = $wnL Wave wnR1 = $wnR Wave wnLx1 = $wnLx Wave wnRx1 = $wnRx wnLx1 = x //get x scale wnRx1 = x if (trim == 1) InsertPoints 0,1, wnLx1 //add point, set to same as first point to complete the bottom of a trimmed violin InsertPoints 0,1, wnRx1 wnLx1[0] = wnLx1[1] wnRx1[0] = wnRx1[1] InsertPoints 0,1, wnL1 InsertPoints 0,1, wnR1 wnL1[0] = 0 wnR1[0] = 0 endif wnR1 *= -1 //make the other side of violin Reverse wnR1, wnRx1 //reverse the righthand side of violin Concatenate/O/NP {wnL1,wnR1}, $vwny // form the wave for y position of outline (will be x when vertical) Concatenate/O/NP {wnLx1,wnRx1}, $vwnx // form the wave for x position of outline (will be y when vertical) wave vwny1 = $vwny wave vwnx1 = $vwnx DoWindow/F $tgtWin //bring target window to the front SetDrawLayer ProgBack // violins are drawn in ProgBack SetDrawEnv ycoord=left, xcoord=bottom, fillfgc=(65535,0,0),fillpat=3 // violins are red DrawPoly xpos+vwny1[0],vwnx1[0],1,1, vwny1,vwnx1 // draws violin KillWaves/Z wnL1,wnR1,wnLx1,wnRx1 // clean-up SetDrawLayer UserFront // set layer back End //Handy function to scrub the violins away Function ClearViolins() SVAR tgtWin = gTgtWin DoWindow /F $tgtWin SetDrawLayer /K ProgBack // kills ProgBack SetDrawLayer UserFront End
Edit: updated this procedure to use StatsKDE. Only runs in IP7. Violin Demo file is out of date.
![Screenshot of violin plots generated in example experiment](/sites/default/files/styles/content_body/public/images-imported/ViolinScreenshot.preview.png?itok=eaoCZlHM)
![](/sites/default/files/forum.png)
Forum
![](/sites/default/files/support.png)
Support
![](/sites/default/files/gallery.png)
Gallery
Igor Pro 9
Learn More
Igor XOP Toolkit
Learn More
Igor NIDAQ Tools MX
Learn More
Hello! I'm trying to use this to make violin plots with my data but I'm running into some issues I just can't quite get my head around. When I run the script with the "demo" data everything works fine, but when I try to run the script with my own data things go wrong. The boxplot x-axis just expands and there is no violin plots that is overlaid on it. I also tried making a "dummy wave" with 20 random values and trying to make the violin plot with that, but it would do the same thing. I've attached some screenshots of what happens when I run the macro, and I also attached one of the waves that I'm trying to represent as a violin plot. Any help or guidance would be much appreciated! Thanks in advance!
July 22, 2018 at 03:59 pm - Permalink
I should point out that Igor 8 has violin plots built-in.
See https://www.wavemetrics.com/products/igorpro/creatinggraphs/2dgraphs/li…
July 22, 2018 at 05:54 pm - Permalink
I saw that actually but wanted to avoid having to update in the middle of a project in case any incompatibilities came up with a toolkit I was using...but I guess I'll have to give it a go in Igor 8. Thanks!
July 22, 2018 at 06:38 pm - Permalink
In reply to I saw that actually but… by JoeKo91
As Jim says IP8 has support for Violins and improved box plots. They're also far more customisable than this code snippet.
July 22, 2018 at 11:12 pm - Permalink
In reply to As Jim says IP8 has support… by sjr51
Hi SJR51,
I hope this message finds you well. I want to express my sincere gratitude for taking the time to read my message. I consider myself fortunate that you have developed the violin plot macro for Igor 6. As a first-year graduate student at Kent State University, our lab primarily utilizes Igor 6, and I had been diligently searching for a solution. It was through my research that I discovered your invaluable contribution as the sole creator of the violin plot on the internet.
I deeply appreciate your hard work and dedication to this project. I downloaded your Igor experiment file and followed the provided instructions meticulously. Everything worked seamlessly, with one minor exception. I encountered some difficulty in adding data points as marker, akin to Igor Pro 9 as depicted in the second picture. I was wondering if you could kindly offer some guidance on how to achieve this functionality within the limitations of Igor 6.
In our relatively small lab, the high cost of Igor Pro 9 is beyond our means, so I am particularly interested in optimizing the capabilities of Igor 6. Nevertheless, I want to emphasize my gratitude for all the effort and expertise you have poured into developing this plot. Your work truly showcases your remarkable skills as an engineer and researcher.
Thank you once again for your invaluable contribution to the Igor community.
Sincerely,
zach
October 17, 2023 at 10:48 am - Permalink
The current price today, Oct. 17, 2023, to upgrade a single-user academic license from Igor 6 to Igor 9 is $305 (other upgrade options vary in price). If you are making box plots and violin plots, the upgrade will make your life easier!
October 17, 2023 at 03:56 pm - Permalink