silogarrett Posted April 25, 2012 Share Posted April 25, 2012 Hi Guru! In an effort to provide my user with a way to scale a graph in runtime, I am using sliders for both the X and Y axis. This works well, however nothing I do is as good as the "Autoscale both axis" command, which of course is not available in runtime. While I have successfully used the strScaleTo and the TimeWidth commands, and I've scoured the forum and the UserGuide for clues, I still cannot find the explicit script or combination of commands that accomplishes "Autoscale Both Axis". Could you please shed some light on how it works? Mike Link to comment Share on other sites More sharing options...
AzeoTech Posted April 25, 2012 Share Posted April 25, 2012 Well, first, you can do Auto-scale both Axes from runtime. The graph popup menu is still available from runtime, though a few options are eliminated. Simply right click on the graph at runtime. As for how its done, it basically takes the min / max values for the trace for the particular axis, then adds/subtracts 2% of the difference so that the min/max don't lie right at the edge of the graph. Its pretty easy if you have one trace: private myMin = min(myExpression) private myMax = max(myExpression) private dif = myMax - myMin component.myGraph.leftAxis1.strScaleFrom = myMin - dif * 0.02 component.myGraph.leftAxis1.strScaleTo = myMax + dif * 0.02 If you have multiple traces, you'll need to figure out the max / min of all the traces. Link to comment Share on other sites More sharing options...
silogarrett Posted April 25, 2012 Author Share Posted April 25, 2012 Guru, I apologize, I do not know why I thought the popup wasn't available at runtime. Anyway, THANKS! Your help adds to my body of knowledge. Great support from DF! Mike Link to comment Share on other sites More sharing options...
silogarrett Posted April 26, 2012 Author Share Posted April 26, 2012 Guru, Wait, what about the bottom axis? How do you grab the history length of the channel? Component.ChartName.BottomAxis.TimeWidth = ???? Sorry for the newbie questions. Mike Link to comment Share on other sites More sharing options...
AzeoTech Posted April 26, 2012 Share Posted April 26, 2012 You can get the history length by access the channel's member variables: myChannel.historyLength However, that won't really get what you want for a number of reasons, first you'd have to also use the Interval, second, you'd be assuming the data actually came in at that interval, and most importantly, it won't take into account what happens before the history is filled. The best way then is to access the first and last points and get their time: timeMin = myChannel.time[myChannel.numRows()-1] timeMax = myChannel.time[0] Then just apply the dif stuff I did before. Link to comment Share on other sites More sharing options...
silogarrett Posted April 26, 2012 Author Share Posted April 26, 2012 Hi Guru! I was able to solve this problem and I wanted to share it for those who may need it. I must qualify that my data set is a static, non-changing set of numbers (a control chart), although this may work in realtime as well. Attached is a screengrab of the page containing the graph. The channel data is loaded to the graph by selecting the channel number on the on-screen keypad. http://postimage.org/image/ykyedq0l9 The code is as follows: // Constants: Component.MyChart.DeleteAllTraces() Component.MyChart.AddTrace("MyTrace") Component.MyChart.MyTrace.Color = rgb(255,0,0) // I chose Red Component.MyChart.MyTrace.LineType = 10 // I chose Medium Solid Line Component.MyChart.MyTrace.PointType = 5 // I chose Diamond Component.MyChart.XAxisFrozen = 0 // Be sure to thaw the axis first Component.MyChart.YAxisFrozen = 0 // Be sure to thaw the axis first Component.MyChart.BottomAxis.UseTimeWidth = 0 Component.MyChart.LeftAxis1.strAutoScaleFrom = "" Component.MyChart.BottomAxis.strAutoScaleFrom = "" // Function: try switch case(MyVariable_1 == 1) Component.MyChart.MyTrace.StrYExpression = "MyChannel[]" Component.MyChart.MyTrace.StrXExpression = "MyChannel.Time" private timeMin = MyChannel.time[numRows(MyChannel)-1] private timeMax = MyChannel.Time[0] Component.MyChart.BottomAxis.strScaleFrom = timeMin Component.MyChart.BottomAxis.strScaleTo = timeMax Component.MyChart.LeftAxis1.strScaleFrom = (Min(MyChannel[]) - 50) Component.MyChart.LeftAxis1.strScaleTo = (Max(MyChannel[]) + 50) Component.MyChart.LowerBoundValue = (Mean(MyChannel[]) * 0.8) Component.MyChart.UpperBoundValue = (Mean(MyChannel[]) * 1.2) case(MyVariable_2 == 1) // Do the same for your other channels endcase catch() endcatch // End Sequence I execute my sequence when I switch to the page containing the graph, and it automatically autoscales for me. Link to comment Share on other sites More sharing options...
AzeoTech Posted April 27, 2012 Share Posted April 27, 2012 Thanks. Three comments, in increasing order of complexity: 1) you don't need [] after your channels. Just putting MyChannel is the same as MyChannel[] 2) in general, always put at least: ? strLastError inside a catch(). Otherwise, if you have a typo inside the try block, you'll never know what it is. DAQFactory will just quietly jump out of your script and you won't know why things didn't work like they should. 3) Whenever you are cutting / pasting code and just changing one item, you should think about how to make simplify. Since DAQFactory doesn't support pointers really, you often have to use a combination of execute() and evaluate() to do this. In your case, you could do this a couple ways. I personally would probably create an array with the channel names: private chans = {"", "MyChannel","MyOtherChannel"} Then, instead of the switch, index into chans based on MyVariable_1: private theChan = chans[myVariable_1] then use theChan and evaluate()/execute(). For example: Component.MyChart.MyTrace.StrYExpression = theChan Component.MyChart.MyTrace.StrYExpression = theChan + ".Time" private timeMin = evaluate(theChan + ".time[numrows(" + theChan + ") + 1]") etc. Actually, you don't need execute(), just evaluate(). Then you don't have to have these repetitive blocks of code that are essentially the same. You could also create a function that does the block of code for setting the graph trace based on a string parameter passed to it. Link to comment Share on other sites More sharing options...
silogarrett Posted April 27, 2012 Author Share Posted April 27, 2012 Hi Guru! Learning to code is one of the most challenging and satifying endeavors I've ever faced. Doing it well is something I really look forward to. This is what makes DF so great. I don't think I could have ever gotten this far with any other program. I will bone up on execute() and evaluate()...! Thanks for your support!! Mike Link to comment Share on other sites More sharing options...
echoi Posted May 29, 2012 Share Posted May 29, 2012 I'm not quite understanding, is there means to invoke a command/script something like components.mygraph.autoscale()? or refresh? Link to comment Share on other sites More sharing options...
AzeoTech Posted May 31, 2012 Share Posted May 31, 2012 Not that exact function, no. You'd have to do something like what I showed in post #2 above. Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.