Setvariable Procedure to Allow Use of Wavemetrics %w Formatting

This setvariable procedure allows use of the %W formatting code, which handles SI prefixes rationally, over a large range. However, it has, until now, not been advisable to use in a setvariable control, because, as explained in the command help, Igor reads the value back without interpreting the extra text, so if you have 1 mm showing in the setvariable, and you type in 2, you get 2 m, i.e., 1000 times more than you wanted. This procedure provides a work-around for that behaviour.
// Code for using SI units and handling Wavemetrics' %w formatting code in setvarariable controls
// The key point is use of a second variable to hold the absolute value of the previous value so we know order of magnitude
// and can adjust for it when user types in a new value. The second copy of the variable is assumed to be named the same
// as the main setvariable variable plus "SIS" and to be in the same datafolder.
// The name of an additional function to run, if required, is stored in user data.


//to make a sample test panel - make sure packages folder exists first:
    variable/G root:packages:MicrometerVal=0.15, root:packages:MicrometerValSIS =0.15
    newpanel
    SetVariable micrometerSetVal,pos={5,5},size={145,17},proc= SIformattedSetVarProcAdjustInc, title="Micrometer"
    SetVariable micrometerSetVal,font="Arial",fSize=12,format="%.2W1Pm"
    SetVariable micrometerSetVal,limits={0,inf,0.01},value= root:packages:MicrometerVal
    SetVariable micrometerSetVal, userData = "myotherProc" //name of additional procedure

// test additional function to run when value is changed (this is optional)
function myotherProc(sva) : SetVariableControl
    STRUCT WMSetVariableAction &sva
   
    print "hello, my name is ", sva.ctrlname, "and my value is ", sva.dval + "."
end

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// The Setvariable procedure
Function SIformattedSetVarProc(sva) : SetVariableControl
    STRUCT WMSetVariableAction &sva
   
    variable eventCode =sva.eventCode
    string vName = sva.vName
    string ctrlName =  sva.ctrlName
    controlinfo $ctrlName
    NVAR gVal = $S_DataFolder + vName
    FUNCREF  SIformattedProtoSetVarfunc extraFunc = $sva.userdata //reference to additional function to run, if any

    switch (eventCode)
        case 1: // mouse up  - Igor handles clicks properly, so just set back up variable
            NVAR valSIS =  $S_DataFolder + vName + "SIS"//reference to backup value
            valSIS =abs (gVal)
            break
        case 2: // Enter key
            NVAR valSIS =  $S_DataFolder + vName + "SIS"//reference to backup value
            if (valSIS < 10^-21)
                gVal /= 10^24
            elseif (valSIS < 10^-18)
                gVal /= 10^21
            elseif (valSIS < 10^-15)
                gVal /= 10^18
            elseif (valSIS < 10^-12)
                gVal /= 10^15
            elseif (ValSIS  < 10^-9)
                gVal /= 10^12
            elseif (ValSIS  < 10^-6)
                gVal /= 10^9
            elseif (valSIS < 10^-3)
                gVal /= 10^6
            elseif (valSIS < 1)
                gVal /= 10^3
            elseif (valSIS < 10^3)
                gVal *= 1
            elseif (valSIS < 10^6)
                gVal *= 10^3
            elseif (valSIS < 10^9)
                gVal *= 10^6
            elseif (valSIS < 10^12)
                gVal *= 10^9
            elseif (valSIS > 10^15)
                gVal *= 10^12
            elseif (ValSIS > 10^18)
                gVal *= 10^15
            elseif (ValSIS > 10^21)
                gVal *= 10^18
            elseif(ValSIS > 10^24)
                gVal *= 10^21
            else
                gVal *= 10^24
            endif
            valSIS =abs (gVal)
            break
        case 3: // Live update - do nothing
        case -1: // killing -  do nothing
            break
    endswitch  
    //Run additional function, if it was given
    if (cmpstr (sva.userdata, "") != 0)
        sva.dVal = gVal //first update the struct with correct value
        extraFunc (sva)
    endif
    return 0
End

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//This version  also dynamically adjusts the setvariable increment to 1 percent of the current order of magnitude of the variable.
Function SIformattedSetVarProcAdjustInc(sva) : SetVariableControl
    STRUCT WMSetVariableAction &sva
   
    variable eventCode =sva.eventCode
    string vName = sva.vName
    string ctrlName =  sva.ctrlName
    controlinfo $ctrlName
    NVAR gVal = $S_DataFolder + vName
    FUNCREF  SIformattedProtoSetVarfunc extraFunc = $sva.userdata //reference to additional function to run, if any

    switch (eventCode)
        case 1: // mouse up  - Igor handles clicks properly, so just set back up variable
            NVAR valSIS =  $S_DataFolder + vName + "SIS"//reference to backup value
            valSIS =abs (gVal)
            break
        case 2: // Enter key
            NVAR valSIS =  $S_DataFolder + vName + "SIS"//reference to backup value
            if (valSIS < 10^-21)
                gVal /= 10^24
            elseif (valSIS < 10^-18)
                gVal /= 10^21
            elseif (valSIS < 10^-15)
                gVal /= 10^18
            elseif (valSIS < 10^-12)
                gVal /= 10^15
            elseif (ValSIS  < 10^-9)
                gVal /= 10^12
            elseif (ValSIS  < 10^-6)
                gVal /= 10^9
            elseif (valSIS < 10^-3)
                gVal /= 10^6
            elseif (valSIS < 1)
                gVal /= 10^3
            elseif (valSIS < 10^3)
                gVal *= 1
            elseif (valSIS < 10^6)
                gVal *= 10^3
            elseif (valSIS < 10^9)
                gVal *= 10^6
            elseif (valSIS < 10^12)
                gVal *= 10^9
            elseif (valSIS > 10^15)
                gVal *= 10^12
            elseif (ValSIS > 10^18)
                gVal *= 10^15
            elseif (ValSIS > 10^21)
                gVal *= 10^18
            elseif(ValSIS > 10^24)
                gVal *= 10^21
            else
                gVal *= 10^24
            endif
            valSIS =abs (gVal)
            break
        case 3: // Live update - do nothing
        case -1: // killing -  do nothing
            break
    endswitch  

    //Adjust the setvariable increment to 1 percent of current order of magnitude.
    //IMPORTANT - If your expected values will span 0,use non-adjusting version, as adjusting
    // the  increment leads to a "Xeno-like paradox",  where you can never click past 0
    variable start, stop
    string limitStr
    start = strsearch  (s_recreation, "limits={", 0)
    stop =  strsearch  (s_recreation, "}", start)
    limitStr = s_recreation [start + 8, stop-1]
    start = str2num (stringFromList (0, limitStr, ","))
    stop = str2num (stringFromList (1, limitStr, ","))
    //adjust increment based on magnitude of current value
    if (valSIS < 10.0001^-12)
        SetVariable $ctrlname limits={(start),(stop),10^-14}
    elseif (valSIS < 10.0001^-11)
        SetVariable $ctrlname limits={(start),(stop),10^-13}
    elseif (valSIS < 10.0001^-10)
        SetVariable $ctrlname limits={(start),(stop),10^-12}
    elseif (valSIS < 10.0001^-9)
        SetVariable $ctrlname limits={(start),(stop),10^-11}
    elseif (valSIS < 10.0001^-8)
        SetVariable $ctrlname limits={(start),(stop),10^-10}
    elseif (valSIS < 10.0001^-7)
        SetVariable $ctrlname limits={(start),(stop),10^-9}
    elseif (valSIS < 10.0001^-6)
        SetVariable $ctrlname limits={(start),(stop),10^-8}
    elseif (valSIS  < 10.0001^-5)
        SetVariable $ctrlname limits={(start),(stop),10^-7}
    elseif (valSIS  < 10.0001^-4)
        SetVariable $ctrlname limits={(start),(stop),10^-6}
    elseif (valSIS < 10.0001^-3)
        SetVariable $ctrlname limits={(start),(stop),10^-5}
    elseif (valSIS < 10.0001^-2)
        SetVariable $ctrlname limits={(start),(stop),10^-4}
    elseif (valSIS < 10.0001^-1)
        SetVariable $ctrlname limits={(start),(stop),10^-3}
    elseif (valSIS < 10^0)
        SetVariable $ctrlname limits={(start),(stop),10^-2}
    elseif (valSIS < 9.9999^1)
        SetVariable $ctrlname limits={(start),(stop),10^-1}
    elseif (valSIS < 9.9999^2)
        SetVariable $ctrlname limits={(start),(stop),10^0}
    elseif (valSIS < 9.9999^3)
        SetVariable $ctrlname limits={(start),(stop),10^1}
    elseif (valSIS < 9.9999^4)
        SetVariable $ctrlname limits={(start),(stop),10^2}
    elseif (valSIS < 9.9999^5)
        SetVariable $ctrlname limits={(start),(stop),10^3}
    elseif (valSIS < 9.9999^6)
        SetVariable $ctrlname limits={(start),(stop),10^4}
    elseif (valSIS < 9.9999^7)
        SetVariable $ctrlname limits={(start),(stop),10^5}
    elseif (valSIS < 9.9999^8)
        SetVariable $ctrlname limits={(start),(stop),10^6}
    elseif (valSIS < 9.9999^9)
        SetVariable $ctrlname limits={(start),(stop),10^7}
    elseif (valSIS < 9.9999^10)
        SetVariable $ctrlname limits={(start),(stop),10^8}
    elseif (valSIS < 9.9999^11)
        SetVariable $ctrlname limits={(start),(stop),10^9}
    elseif (valSIS < 9.9999^12)
        SetVariable $ctrlname limits={(start),(stop),10^10}
    endif
   
    //Run additional function, if it was given
    if (cmpstr (sva.userdata, "") != 0)
        sva.dVal = gVal //first update the struct with correct value
        extraFunc (sva)
    endif
    return 0
End

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Prototype function for additional stuff do do when value changes
function SIformattedProtoSetVarfunc (sva) : SetVariableControl
    STRUCT WMSetVariableAction &sva
    //Nothing happens here
    return 0
end

Forum

Support

Gallery

Igor Pro 8

Learn More

Igor XOP Toolkit

Learn More

Igor NIDAQ Tools MX

Learn More