
From a graph marquee, save a list of points, average, or NaN data

jcor
#pragma rtGlobals=3 // Use modern global access method and strict wave access. // Does simple tasks on the data within a marquee -- either prints avg or sets nan function doWithinMarquee([doWhat, quiet]) // Note: if no changes are made, nothing is printed. // Joel Corbin, 2016-09-22 string doWhat // == one of: "avg", "nan", "getPlist" (get str list of row indices for selection) // (see below for what these mean) variable quiet // if set, function doesn't print anything if (ParamIsDefault(doWhat)) doWhat="avg" endif variable printStuff=0 if (ParamIsDefault(quiet) || quiet) printStuff=1 endif String graphName= WinName(0,1) String traceList=TraceNameList(graphName,";",1+4) // 1+4 --> normal+visible traces variable i, n_traces= itemsInList(traceList) variable alertedAlready= 0 variable n_traces_used= 0 // search for & get traces for any subwindows. Expand graph names to match traces to allow this. string graphsList= strmultiply(graphName, n_traces) // empty if n=0 string childWinList= ChildWindowList(graphName) variable j, n_childs= itemsInList(childWinList) for (j=0; j<n_childs; j+=1) // [this doesn't execute if n_childs==0] string nextSubGr= graphName + "#" + stringFromList(j, childWinList) // ParentGraph#Subwindow format graphsList+= nextSubGr + ";" traceList+= TraceNameList(nextSubGr,";",1+4) // 1+4 --> normal+visible traces endfor n_traces= itemsInList(traceList) // for each trace... for (i=0; i<n_traces; i+=1) // prepare graphName= stringFromList(i, graphsList) string traceName= stringFromList(i, traceList) Wave/Z yw= TraceNameToWaveRef(graphName,traceName) Wave/Z xw= XWaveRefFromTrace(graphName,traceName) if (!WaveExists(yw)) printf "\t//* Wave %s not found.\r", traceName endif // get axis and marquee properties String hAxis= StringByKey("XAXIS", TraceInfo(graphName, traceName, 0)) String vAxis= StringByKey("YAXIS", TraceInfo(graphName, traceName, 0)) GetMarquee /W=$graphName $hAxis, $vAxis // removed /K (kill marquee) for the sake of the points version Variable xMin= min(V_right, V_left) Variable xMax= max(V_right, V_left) Variable yMin= min(V_top, V_bottom) Variable yMax= max(V_top, V_bottom) // get mask of selected items [code here inspired by http://www.igorexchange.com/node/1140] make /free /n=(numpnts(yw)) mask if( WaveExists(xw)) // y vs x mask = (yw[p] > yMin) && (yw[p] < yMax) && (xw > xMin) && (xw < xMax) ? 1 : 0 else // just a waveform, use X scaling mask = (yw[p] > yMin) && (yw[p] < yMax) && (pnt2x(yw,p) > xMin) && (pnt2x(yw,p) < xMax) ? 1 : 0 endif // if trace is masked [some points not visible] the result is wrong. if (0) String maskName= StringByKey("mask(x)", TraceInfo(graphName, traceName, 0), "=", ";") // But to mask a trace, I do a hack using zmarkersize... so very hard to work with] print maskName // msizez ?? endif strswitch (doWhat) case "avg": mask= yw*mask/mask // get stats WaveStats /Q mask if (V_npnts > 2) StatsQuantiles /iNaN /Q mask else V_Q25=nan; V_Median=nan; V_Q75=nan endif // print result if (xMin > date2secs(2000, 1, 1)) // assume time: string S_range= secs2dt(xMin) + ", " + secs2dt(xMax) else S_range= num2str(xMin) + ", " + num2str(xMax) endif if (V_npnts > 0) if (printStuff) printf "Wave %s(%s) {avg, SD, %%SD}\t= {%.4g, %.4g, %.1f %%}; {min, Q25, Q50, Q75, max} = {%.4g, %.4g, %.4g, %.4g, %.4g}\r", traceName, S_range, V_avg, V_sdev, V_sdev/V_avg*100, V_min, V_Q25, V_Median, V_Q75, V_Max endif n_traces_used+=1 endif break case "nan": if (!alertedAlready) alertedAlready=1 // warn doAlert 1, "This will permanently remove data from the selected wave(s). Continue?" if (V_flag==2) abort "Abort -- no changes made. -- " + GetRTStackInfo(0) endif endif WaveStats /Q yw variable V_nansBefore= V_numNaNs // do it mask= !mask / !mask // maskOfKeepers[1,nan] <- maskOfMarqueeMembers[0,1] yw *= mask // print a report WaveStats /Q yw variable V_numDeleted= V_numNaNs - V_nansBefore if (V_numDeleted) if (printStuff) printf "\t//* %s deleted %g points from wave %s according to a marquee selection [%s].\r", GetRTStackInfo(1), V_numDeleted, getwavesdatafolder(yw,2), secs2dt(datetime) endif n_traces_used+=1 endif GetMarquee /W=$graphName /K // kill marquee break case "getPlist": DFREF sdf= getDataFolderDFR() cd root:; newdatafolder /o/s Packages; newdatafolder /o/s jTools variable V_noList= 0 if (DimSize(xw, 1)>1 || DimSize(yw, 1)>1) // can't handle multidimensional inputs... if (printStuff) printf "\t//* doWithinMarquee() can't handle multidimensional inputs, returning nothing...\r" endif V_noList= 1 make /free /n=1 mask=nan endif // do it mask= mask/mask * p duplicate /free mask, mask_deletedNaNs deleteNaNs(mask_deletedNaNs) if (!numpnts(mask_deletedNaNs)) // no selection cd sdf continue endif // save result 1/2 duplicate /o mask, root:Packages:jTools:MarqueeMask /WAVE=MarqueeMask n_traces_used+= 1 if (n_traces_used > 1) printf "// (Multiple traces used, not saving selected points in MarqueeP / MarqueeMask... (to fix, remove all other traces first)" // there is no mechanism for choosing which trace to save yet endif // save result 2/2 duplicate /o mask_deletedNaNs, root:Packages:jTools:MarqueePs /WAVE=MarqueePs string wnote= "Saved from a marquee selection of wave %s \ron %s by doWithinMarquee(\"getPlist\")" if (V_noList) // ensure no misleading info saved xMin=nan; xMax=nan; yMin=nan; yMax=nan; else wnote+= "\rThe marquee was located at {left, right, top, bottom} = {%g, %g, %g, %g}\r on the axes %s\r and %s" sprintf wnote, wnote, getwavesdatafolder(yw,2), secs2dt(datetime), xMin, xMax, yMin, yMax, getwavesdatafolder(yw,2), ifElseStr(WaveExists(xw), getwavesdatafolder(yw,2), "[none]") endif note /K MarqueePs, wnote note /K MarqueeMask, wnote PutScrapText getwavesdatafolder(MarqueePs,2) // wrap up if (numpnts(MarqueePs) < 100) // interact if just a few points string output= wave2list(MarqueePs) if (printStuff) printf "The following indices of wave %s (trace %s) were selected:\r%s\rand are saved in %s and %s \r", getWaveFullPathStr(yw), traceName, output, getWaveFullPathStr(MarqueePs), getWaveFullPathStr(MarqueeMask) endif // doAlert 0, "A list of row indices has been copied to the clipboard and printed." PutScrapText output else if (printStuff) printf "// %g indices of wave %s (trace %s) were selected\r // and saved in %s and %s [the former wave ref copied to clipboard]\r", numpnts(mask), getWaveFullPathStr(yw), traceName, getWaveFullPathStr(MarqueePs), getWaveFullPathStr(MarqueeMask) endif endif cd sdf break default: cd sdf abort "Argument not recognized -- " + GetRTStackInfo(0) endswitch endfor if (n_traces_used==0) print "No points were selected." endif end // Given "item" and 3, returns "item;item;item" function/s strmultiply(input, n) string input variable n variable i=0 string output= "" for (i=0; i<n; i+=1) output += input + ";" n -= 1 endfor return output end function/s secs2dt(secs) // Given a datetime in seconds, returns an ISO-8601--formatted datetime. // e.g. secs2dt(date2secs(2012,1,31)) returns "2012-01-31 00:00:00" variable secs if (secs) return secs2date(secs,-2) + " " + secs2time(secs,3) endif return "" end function deleteNaNs(w) // Deletes points in w containing NaNs. wave w variable i, j, np= numpnts(w) make /free /n=(np) onda for (i=0; i<np; i+=1) if (numtype(w[i])!=2) onda[j]= w[i] j+=1 endif endfor DeletePoints j, i-j, onda duplicate /o onda, w end function/s ifelseStr(bool, iftrue, iffalse) // if variable bool is true, return iftrue, else return iffalse. // analogue to R's ifelse() variable bool string iftrue, iffalse if (bool) return iftrue endif return iffalse end // Given a wave reference, returns a string-list formatted version of the wave. function/s wave2list(w[,noNaNs]) // printed using %g. // e.g. make w={1,2,3}; print wave2list(w) returns "1;2;3" // make w={1,nan,3}; print wave2list(w) returns "1;3" wave w variable noNaNs // optionally remove NaNs from the returned list if (!WaveExists(w) || numpnts(w)==0) return "" endif string str wfprintf str, "%g;", w if (noNaNs) do str = removeFromList("NaN", str) while (findInList("NaN", str)>=0) endif return str end // returns "root:exampleDF:exampleWaveName" function/s getWaveFullPathStr(w) wave w if (WaveExists(w)) return getwavesdatafolder(w,2) else return "" endif end function findInList(findstr, liststr[, sep]) // Returns the list index in which findstr is found in ;-list liststr, // else returns -1 string findstr, liststr, sep if (ParamIsDefault(sep)) sep = ";" endif return WhichListItem(findstr, liststr, sep) end

Forum

Support

Gallery
Igor Pro 9
Learn More
Igor XOP Toolkit
Learn More
Igor NIDAQ Tools MX
Learn More