Transform axis help
giovanni.matrone15
I have this simple graph temperature VS time (attached pxp) and I want to transform the bottom axis creating a mirror using the left axis. Basically I want to re-create the temperature axis with a spacing coming from the correspondence from the time axis.
Can you please help me in this? I have tried with the procedure attache and posted by another user but there are issue with the slope of the coefficient wave...
Forum
Support
Gallery
Igor Pro 9
Learn More
Igor XOP Toolkit
Learn More
Igor NIDAQ Tools MX
Learn More
TransformAxis won't make a Left axis based on a Bottom axis. TransformAxis was written with no awareness that someone might want a "mirror" axis that isn't directly opposite the main axis.
But upon looking at your experiment file, and re-reading your post, I find that I don't understand what you want to do. Do you want a Right axis with some combination of Left and Bottom? Could you write an equation that tells me what you want?
December 14, 2018 at 10:29 am - Permalink
Hi john,
thanks for helping.
I want a top axis (mirror of time axis) with values coming from temperature wave (that is also the right axis of my graph).
Generally I would like to plot the temperature axis not linearly spaced but with spacing coming from its correspondence from time axis.
I hope now It's clearer.
thanks
December 15, 2018 at 12:47 am - Permalink
I think the problem you will run into is that the temperature values are not monotonic. To be able to invert your transform in order to compute ticking, the inverse of the function must be single-valued.
Are you wishing that you could have ticks on the top axis that tell you what the temperature is at various places along the horizontal axis? If so, you can probably achieve what you want using a "truly free" axis with "user ticks from waves", with a hook function that looks up values from the temperature wave and creates tick labels. A bit involved, but doable. I could help with that...
The reason this would work, but Transform Axis doesn't, is that you can incorporate your knowledge of the data sets into the code, where Transform Axis has to be able to take anything that's thrown at it.
December 17, 2018 at 09:32 am - Permalink
Try the attached.
December 17, 2018 at 10:32 am - Permalink
I think your approach should work! thanks!
BTW I don't quite understand how you created the temp axis_labels and temp axis_values waves. Do you have a procedure for that?
December 18, 2018 at 01:17 am - Permalink
In Igor 8, as a help to users who want to create user tick waves, there is a button on the Auto/Man Ticks tab, "New from Auto Ticks". The idea is that it is a help for creating starter waves for the user ticks feature. You don't have to do it that way- you can simply create a numeric wave with values along the axis where you want a special label, and a text wave with the labels for each of those locations. You can read about user ticks: DisplayHelpTopic "User Ticks from Waves"
I used the button to create a value wave corresponding to even increments in time from the bottom axis. The contents of the text wave is mostly irrelevant since it is modified by the axis hook procedure. The way I wrote the axis hook procedure, you can change the number of ticks and their positions and the hook will generate the right labels based on your temperature wave.
I didn't spend a lot of time on this- the hook could have been written in a more general fashion, and perhaps more thought spent on formatting the tick labels, etc. But it should get you started.
Will this be something you want to do on a regular basis with other data sets, or is this a one-off?
December 18, 2018 at 09:32 am - Permalink
This is something I intend to to on a regular basis, It's connected to a series of experiments I have runned for 3 months and that I am planning to replicate next year.
December 18, 2018 at 09:38 am - Permalink
Here is a procedure that will create the axis and set up the waves required for the tick labels. I have re-thought the problem and concluded that the axis hook function is not really needed, and could be problematic. Instead, the function AddTemperatureTimeAxis() creates the waves needed, adds the axis, and sets up a dependency formula that updates the labels if you change the tick values wave.
To use my function, select Windows->New->Procedure. Select a good name for the procedure file. Copy the code below, paste it into your new procedure window. Select File->Save Procedure As and save to a disk file. If you save it in the Igor Procedures folder, it will always be loaded into Igor when you start up Igor. To learn about the Igor Procedures folder: DisplayHelpTopic "Special Folders"
To use the function, with your graph as the top graph window, execute a command like this:
AddTemperatureTimeAxis("", "", 0, 0, 500)
That command selects the first trace in the top graph (the first two inputs, "", ""), defaults that start and end times to the range of the bottom axis, and sets the time increment between the ticks to 500. You can re-execute the command any time to re-set the axis. You can also edit the time values wave to change the locations of the ticks and the dependency will re-compute the correct labels.
Here is the procedure code:
DFREF savedDF = GetDataFolderDFR()
if (strlen(graphName) == 0)
graphName = WinName(0,1) // default to top graph window
endif
if (strlen(traceName) == 0)
traceName = StringFromList(0, TraceNameList(graphName, ";", 1)) // default to first trace in the graph
endif
Variable npoints
NewDataFolder/O/S Packages
NewDataFolder/O/S TemperatureTimeAxis
NewDataFolder/O/S $graphName
String tinfo = TraceInfo(graphName, traceName, 0)
Wave ywave = traceNameToWaveRef(graphName, traceName)
Wave/Z xwave = XWaveRefFromTrace(graphName, traceName)
String xaxisname = StringByKey("XAXIS", tinfo)
String yaxisname = StringByKey("YAXIS", tinfo)
String temptimeaxisname = xaxisname+"_timetemp"
NewFreeAxis/T/O $temptimeaxisname
ModifyFreeAxis/Z $temptimeaxisname,master=$xaxisname//,hook=TempTimeAxisHook
if (starttime == 0 && stoptime == 0)
GetAxis/W=$graphName/Q $xaxisname
starttime = V_min
stoptime = V_max
endif
if (timeincrement == 0)
timeincrement = (stoptime - starttime)/10 // reasonable but arbitrary default
endif
npoints = ceil(((stoptime - starttime)/timeincrement))+1 // you can't have too many points
String labelWaveName = graphName+"_timeValues"
String valuesWaveName = graphName+"_temperatureLabels"
Make/N=(npoints)/D/O $labelWaveName/WAVE=values
Make/N=(npoints)/T/O $valuesWaveName/WAVE=labels
SetDataFolder savedDF
ModifyGraph userticks($temptimeaxisname)={values,labels}
ModifyGraph tkLblRot($temptimeaxisname)=90
ModifyGraph freePos($temptimeaxisname)={0,kwFraction}
values = p*timeincrement + starttime
labels = ComputeLabelsForTempTimeAxis(p, values, ywave, xwave)
String dependencyFormula = "ComputeLabelsForTempTimeAxis(p, "+GetWavesDataFolder(values, 2)+","+GetWavesDataFolder(ywave, 2)+","
if (WaveExists(xwave))
dependencyFormula += GetWavesDataFolder(xwave, 2)
else
dependencyFormula += "$\"\""
endif
dependencyFormula += ")"
SetFormula labels, dependencyFormula
end
Function/S ComputeLabelsForTempTimeAxis(Variable point, Wave tickwave, WAve temperatureWave, Wave/Z timeWave)
String retString = ""
if (WaveExists(timeWave))
Variable thePoint = BinarySearchInterp(timewave, tickwave[point])
if (numtype(thePoint))
retString = ""
else
retString = num2str(temperatureWave[thePoint])
endif
else
if (tickwave[point] < leftx(temperatureWave) || tickwave[point] > rightx(temperatureWave))
retString = ""
else
retString = num2str(temperatureWave(tickwave[point]))
endif
endif
return retString
end
December 18, 2018 at 12:07 pm - Permalink
Hi,
thanks a lot for the fantastic code, it's working!
I have just another favour to ask, can you change the procedure code so that it can work even when I plot the time axis as a left axis?
It would be really useful when I want to add this transformed axis as an additional vertical axis. ( it will always mirror the time axis)
I have tried in several ways but I working with swapping axis I loose the proper thicking, thanks in advance.
December 19, 2018 at 01:18 am - Permalink
I should probably make you study my code and figure it out :)
Can you clarify- if you use a left axis for time, then you want a right axis, and the temperature values are in the X wave?
December 19, 2018 at 09:20 am - Permalink
Sure I'm studying your code but there is something I miss when I try to swap the two axis....
Anyway, I use the left axis for time so I would like a right axis and possibly I would display just the right one. Temperature values are in the x wave.
thanks again ;)
December 20, 2018 at 12:52 am - Permalink
OK- you will note when you study the code :) that I took a pretty much brute-force approach to the problem of swapping axes. I took the opportunity also to check if you used top or bottom, left or right, and put the new axis in the opposite position. The function has a new input, "timeIsVertical". Set it to 1 if the time wave is displayed in the vertical direction. I can't swear to what might happen if you use ModifyGraph swapXY=1.
DFREF savedDF = GetDataFolderDFR()
if (strlen(graphName) == 0)
graphName = WinName(0,1) // default to top graph window
endif
if (strlen(traceName) == 0)
traceName = StringFromList(0, TraceNameList(graphName, ";", 1)) // default to first trace in the graph
endif
Variable npoints
NewDataFolder/O/S Packages
NewDataFolder/O/S TemperatureTimeAxis
NewDataFolder/O/S $graphName
String tinfo = TraceInfo(graphName, traceName, 0)
Wave ywave = traceNameToWaveRef(graphName, traceName)
Wave/Z xwave = XWaveRefFromTrace(graphName, traceName)
String xaxisname = StringByKey("XAXIS", tinfo)
String yaxisname = StringByKey("YAXIS", tinfo)
String temptimeaxisname, axinfo
String masterAxisName
if (timeIsVertical)
axinfo = AxisInfo(graphName, yaxisname)
Variable doLeft = 0
if (CmpStr(StringByKey("AXTYPE", axinfo), "right") == 0)
doLeft = 1
endif
temptimeaxisname = yaxisname+"_timetemp"
if (doLeft)
NewFreeAxis/L/O $temptimeaxisname
else
NewFreeAxis/R/O $temptimeaxisname
endif
masterAxisName = yaxisname
WAVE temperatureWave = xwave
WAVE timeWave = ywave
else
axinfo = AxisInfo(graphName, xaxisname)
Variable doBottom = 0
if (CmpStr(StringByKey("AXTYPE", axinfo), "top") == 0)
doBottom = 1
endif
temptimeaxisname = xaxisname+"_timetemp"
if (doBottom)
NewFreeAxis/B/O $temptimeaxisname
else
NewFreeAxis/T/O $temptimeaxisname
endif
masterAxisName = xaxisname
WAVE temperatureWave = ywave
WAVE timeWave = xwave
endif
ModifyFreeAxis/Z $temptimeaxisname,master=$masterAxisName
if (starttime == 0 && stoptime == 0)
GetAxis/W=$graphName/Q $masterAxisName
starttime = V_min
stoptime = V_max
endif
if (timeincrement == 0)
timeincrement = (stoptime - starttime)/10 // reasonable but arbitrary default
endif
npoints = ceil(((stoptime - starttime)/timeincrement))+1 // you can't have too many points
String labelWaveName = graphName+"_timeValues"
String valuesWaveName = graphName+"_temperatureLabels"
Make/N=(npoints)/D/O $labelWaveName/WAVE=values
Make/N=(npoints)/T/O $valuesWaveName/WAVE=labels
SetDataFolder savedDF
ModifyGraph userticks($temptimeaxisname)={values,labels}
if (!timeIsVertical)
ModifyGraph tkLblRot($temptimeaxisname)=90
endif
ModifyGraph freePos($temptimeaxisname)={0,kwFraction}
values = p*timeincrement + starttime
labels = ComputeLabelsForTempTimeAxis(p, values, temperatureWave, timeWave)
String dependencyFormula = "ComputeLabelsForTempTimeAxis(p, "+GetWavesDataFolder(values, 2)+","+GetWavesDataFolder(temperatureWave, 2)+","
if (WaveExists(xwave))
dependencyFormula += GetWavesDataFolder(timeWave, 2)
else
dependencyFormula += "$\"\""
endif
dependencyFormula += ")"
SetFormula labels, dependencyFormula
end
December 20, 2018 at 10:07 am - Permalink