Double horizontal axis (top/bottom) with different scale

Dear all,

I have three waves: Intensity, Time and Temperature. All waves have the same amount of points.
I would like to plot Intensity VS Time, where time is on the bottom axis, and then add a top axis
with the Temperature scale. The idea is that if, for example, Time 1000 correspond to Temperature 100,
than 100 have to be exactly on top of 1000 in the graph.

I tried adding the intensity vs time (bottom axis) and then intensity vs temperature (top axis), but
the curves do not overlap. I don't understand exactly why.

It seems it should be pretty straightforward, but I have been struggling to get the result I want.

Any suggestion?

Cheers,

Fabrizio
Hi John,

The temperature is not a strictly linear function of time.

Here's an experiment file.

Thanks

Fabrizio
Test.pxp (0 bytes)
Any time Igor makes a graph of something vs somethingelse, it lays out the axes in a linear fashion. Since your temperatures are not a linear function of time, then the Intensity vs Time plot simply doesn't match the Intensity vs Temperature plot. So you see it's not a straightforward problem- you need a mirror axis with the ticks at a nonlinear spacing.

BUT there is a solution. You can use the Transform Axis package to make a mirror axis that displays ticks that are a function of the ticks on the axis it mirrors. And I have just written a transformation function that uses a wave as the source of the transformation function.

The learn more about Transform Axis, select File->Example Experiments->Graphing Techniques->Transform Axis Demo.

The package can be tricky to understand, I strongly encourage you to look at the demo.

I have attached a modified version of your experiment file that uses Transform Axis to put a Temperature top axis on a graph of Intensity vs Times. To do that, I took these steps:

0) I wrote the function TransAx_fromWave() in the main Procedure window.

1) I made the graph of Intensity vs Times.

2) From the Graph menu, I chose Packages->Transform Axes

3) From the Graph menu, I chose Transform Axis->Transform Axis.

4) In the control panel, I selected these settings:
Function: fromWave
Axis: Bottom
Turned on the Make It a Mirror Axis checkbox
Selected Temperature as the Coefficient wave

5) Click Do It.

John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
TestJW.pxp (8.41 MB)
Hi,

I thought I'd post a question here seeing as this seems related to the problem I am attempting to tackle. Would you be able to help me out?

I have a graph of current density (y axis, left) which is a function of potential (x axis, bottom), but not linear. What I have been trying to figure out is how to plot time on the x axis (top).

The time is a linear function of the potential (as the potential is stepped at set time intervals).

I have been trying to see if this transform axis will do the trick, but cannot seem to get it to work. I have tried creating a wave with the time in correct intervals, but of course, I cannot plot potential vs time both on the horizontal axes alongside current density on the y axis. As Fabrizio said; it seems as though this would be a simple solution, but in fact it is not!

The attachment is a screenshot of the graph; ideally I would like to plot the time on the top axis.

Can you help?

Capture_0.JPG (132.21 KB) Capture_0.JPG (132.21 KB) Capture_0.JPG (132.21 KB)
r.clark1 wrote:

The attachment is a screenshot of the graph; ideally I would like to plot the time on the top axis.
Can you help?


If you attach the entire experiment, then perhaps we can see what's going wrong.

--Jim Prouty
Software Engineer, WaveMetrics, Inc.
If your potential is a linear function of time, it should be a simple matter to write your own transform function with the correct factors in it. See one of the temperature scale functions included in the TransformAxis package as a guide. Here is the function for Centigrade to Farenheight:
Function TransAx_DegreesCtoF(w, val)
    Wave/Z w            // a parameter wave, if desired. Argument must be present for FindRoots.
    Variable val
   
    return val*1.8+32
end

Replace "1.8" and "32" with the appropriate factors for your transformation. And give the function a new name; it MUST start with "TransAx_".

John Weeks
WaveMetrics, Inc.
support@wavemetrics.com

In reply to by johnweeks

UPDATE! 

I found the "TransAx_fromWave" using the procedure browser. 

 

Dear John, 

I want to use the option "TransAx_fromWave" option. I assume this is not available on the standard Transform graph package. 

I can't figure out from the TextJW.pxp file where you changed the procedure. 

I would highly appreciate it if you could help me out. 

Greetings, 

Siva 

 

 

Hi Everybody,

 I am dealing with the same issue as that discussed in this post. Specifically, I would like to add a secondary, non-linear, horizontal axis to a graph. However, I found the Transform Axis package to be confusing and therefore I would like to avoid using it. I considered ways to sidestep this procedure such as that described in the "Transform axis help" post but the function included in this second post seems to be more complicated than what I need.  Ultimately, the solution I settled on is to generate a new free axis and to define custom labels and ticks to be implemented for this axis using the "User ticks from waves" option. Unfortunately, I ran into a problem I do not how how to solve. This issue is illustrated by the test code presented below which generates a secondary horizontal axis and the corresponding custom labels and ticks position. The problem is that the secondary ticks and labels are not actually displayed.

I would appreciate any suggestions and comments on how to display the ticks and labels of the secondary horizontal axis.

Best,

Sebastian

 

function generate_test_plot()

make/o/n=1000 field, signal
wave signal, field

field  = x/100
signal = exp(-(x*0.01-5)^2)

display signal vs field

label bottom "field [ T ]"
label left "Signal [ mv ]"

ModifyGraph mirror(bottom)=2, mirror(left) = 2
SetAxis left -0.1,1.1

//generate and add secondary, non-linear, horizontal axis

add_secondary_horizantal_axis(field)

end


function add_secondary_horizantal_axis(inwave)

wave inwave
string name_g_wave = nameOfWave(inwave) +"_g_effective"
variable i

duplicate/o/w inwave effective_g_values

for(i=0;i<(numpnts(inwave));i++)
  effective_g_values[i] = 0.07146329*(300/inwave[i])
endfor

NewFreeAxis/T/O g_effective

 make/o/n=5/t g_eff_labels
 make/o/n=5   g_eff_position

for(i=0;i<5;i++)
  g_eff_labels[i]   = num2str(effective_g_values[ceil(i*numpnts(inwave)/5)])
  g_eff_position[i] = inwave[ceil(i*numpnts(inwave)/5)]
endfor

Label g_effective "g\Beffective"

ModifyGraph userticks(g_effective)={g_eff_position,g_eff_labels}
ModifyGraph  lblPos(g_effective)=43,freePos(g_effective)={0.0,kwFraction}

killwaves effective_g_values

end

 

 

 

I am not sure why TransformAxis fails for your case. In the meantime, here is the modified function that you need.

 

function add_secondary_horizantal_axis(inwave) 
    wave inwave

    string name_g_wave = nameOfWave(inwave) +"_g_effective"
   
    duplicate/o/w/FREE inwave effective_g_values
   
    effective_g_values = 0.07146329*(300/inwave[p])
   
    NewFreeAxis/T/O g_effective
   
    make/o/n=5/t g_eff_labels
    make/o/n=5/D   g_eff_position
   
    g_eff_labels   = num2str(effective_g_values[ceil(p*numpnts(inwave)/5)])
    g_eff_position = inwave[ceil(p*numpnts(inwave)/5)]
   
    Label g_effective "g\Beffective"
   
    ModifyGraph userticks(g_effective)={g_eff_position,g_eff_labels}
    ModifyGraph  lblPos(g_effective)=43,freePos(g_effective)={0.0,kwFraction}
    SetAxis g_effective 0,inwave[inf]
   
    return 0
end

 

Maybe if you could elaborate a bit more why TransformAxis is problematic we could point you in the right direction. Which version you are using by the way? The package got quite a bit more convenient with Igor 9.

In reply to by chozo

chozo wrote:

Maybe if you could elaborate a bit more why TransformAxis is problematic we could point you in the right direction. Which version you are using by the way? The package got quite a bit more convenient with Igor 9.

Thanks to chozo's efforts!

Your Generate_Test_Plot() fails to do what you need because the axis range for the truly free axis is not set. You have two options:

1) Set it to a fixed range:

SetAxis g_effective 0,10

2) Set the axis master to the bottom axis:

ModifyFreeAxis g_effective, master=bottom

Option 2 is probably the best, as it will cause your axis to follow the range of the bottom axis if it changes.

By the way, that's exactly what TransformAxis does. But TransformAxis tries to do it for any arbitrary transformation, which is really hard. And to make the general case a little more tractable, it doesn't handle infinities gracefully. The problem is that the inverse of your transformation is required to do the tick-spacing and nice-number computations. Singular functions are hard to deal with!

Hi Everybody,

 Thank you so much for your replies. Your combined insight and detailed explanations have helped me to better understand and troubleshoot my code.  Regarding chozo's question about the Transform Axis, as far I know there is nothing wrong with this procedure. I just did not study the documentation enough to be able to use it properly.

Best,

S

And as I mentioned previously, your particular transformation probably doesn't work with TransformAxis due to the need to include infinity.