| T O P I C R E V I E W |
| bubbas |
Posted - 02/07/2007 : 05:04:54 AM Origin Version (Select Help-->About Origin): 7.5E SR6 Operating System: Win Xp Pro
Hey,
i want to let the user manually select a datapoint from a plot. The y-value of this datapoint is then used for later calculations.
So first i want to maximize the Graph where the user should select the Point.
For that i use a modified function found here in the forum:
void getdatapointfromgraph(string graphname, double& max, int& indexofpoint) { GraphPage pg; pg = Project.GraphPages(graphname); if( pg.IsValid() ) { string setcmd; GraphLayer gl = pg.Layers(); // Get active layer printf("%s has %d layer(s)\n", pg.GetName(), pg.Layers.Count()); setcmd.Format("win -a %s", graphname); LT_execute(setcmd); //Set graph active setcmd.Format("win -z %s", graphname); LT_execute(setcmd); //Maximize Graph //DataPlot dp = gl.DataPlots(0); //dp.SetActive(0,20);
int nPts=1; // Declare vectors to hold coordinates vector vecX, vecY, vecIndex; // Call function to get points int iRet = get_screen_reader_points(nPts, vecX, vecY, vecIndex, graphname); if( iRet < 0 ) printf("Function call to get screen points returned error: %d\n", iRet);
printf("User clicked on %d points\n", iRet); if( 0 != iRet ) { printf("X, Y coordinates of points are:\n"); for(int ii = 0; ii < iRet; ii++) { indexofpoint = vecIndex[ii]; max=vecY[ii]; printf(" %d: X = %f, Y = %f Index= %d\n", ii, vecX[ii], vecY[ii], indexofpoint); } } setcmd.Format("win -ia %s", graphname); LT_execute(setcmd); //Minimize Graph and activate previous window } else { printf("Invalid Graphwindow (%s) for selecting Maximum ", graphname) }
}
static int get_screen_reader_points(int nPts, vector& vecX, vector& vecY, vector& vecIndex, string graphname) { // Return error if number of points not appropriate // Arbitrary upper limit of 99 - change as desired if( nPts < 1 || nPts > 99) return -1;
// Run the LabTalk section in this file to give user control to click points string strThisFile = __FILE__; string strCMD; strCMD.Format("run.section(%s,GetScreenPts,%d,%s)", strThisFile, nPts, graphname); LT_execute(strCMD);
// On return, the LabTalk variable tmp_scr_count has number of points user clicked + 1 double dCount; LT_get_var("tmp_scr_count", &dCount); int nCount = (int) (dCount - 1); if( 0 == nCount ) return 0;
// Get values of x, y coordinates from LabTalk variables and delete the vars vecX.SetSize(nCount); vecY.SetSize(nCount); vecIndex.SetSize(nCount); string strX, strY, strIndex; double dX, dY, dIndex; for(int ii = 1; ii <= nCount; ii++) { strX.Format("tmp_scr_pos_x%d", ii); strY.Format("tmp_scr_pos_y%d", ii); strIndex.Format("tmp_scr_pos_index%d", ii); LT_get_var(strX, &vecX[ii - 1]); LT_get_var(strY, &vecY[ii - 1]); LT_get_var(strIndex, &vecIndex[ii - 1]); strCMD.Format("del -v %s", strX); LT_execute(strCMD); strCMD.Format("del -v %s", strY); LT_execute(strCMD); strCMD.Format("del -v %s", strIndex); LT_execute(strCMD); }
// Delete the count LabTalk variable LT_execute("del -v tmp_scr_count;");
// Return the number of points clicked by user return nCount; }
// This section of LabTalk will be ignored by compiler since it is contained within an ifdef block. // The section of script within this block can then be successfully called by a run.section LabTalk command. #ifdef LABTALK [GetScreenPts] // Number of points to get is passed as 1st parameter // Select screen reader tool dotool 3; // 2 screen Reader, 3 data reader
// Main loop to accept points tmp_scr_count = 1; def quittoolbox { // Check if user has clicked required number of points if( 1 == tmp_scr_count ) done = 1; if( %1 != tmp_scr_count ) return; }
// Get points and store in temp string variables def pointproc { tmp_scr_pos_x$(tmp_scr_count)=x; tmp_scr_pos_y$(tmp_scr_count)=y; tmp_scr_pos_index$(tmp_scr_count)=index; if( tmp_scr_count >= %1 ) { dotool 0; // Set the variable to break the infinite loop done = 1; } tmp_scr_count += 1; }
// Set up an "infinite loop" so code waits for user to click points for( done = 0; done == 0; ) { // wait a while sec -p 0.1; } #endif
But i have got the problem. That the Graph to select the point appears maximized, but if i try to select a datapoint it is not possible. It doesn't accept a doubleclick on the curve. It always selects a point far away from where i click. If i minimize the graph manually i can select without a problem, but that is not a solution ... Tried to minimize/maximize from script but it doesn't helps.
Thanks in advance
greetings
bubbas
|
| 13 L A T E S T R E P L I E S (Newest First) |
| bubbas |
Posted - 02/08/2007 : 11:55:40 AM yes :)
thank you, that did the job now, finally ;)
didn't knew about SetPage. Thank you!
now i can think about other things *g*
Regards
bubbas |
| Mike Buess |
Posted - 02/08/2007 : 09:49:40 AM Hi bubbas,
Beginning the LabTalk section with a brief delay appears to fix the problem...
[GetScreenPts] // Number of points to get is passed as 1st parameter // Select screen reader tool sec -p 0.1; // wait dotool 3; // 2 screen Reader, 3 data reader // more commands
Your testdataget() and getdatapointfromgraph() functions both work and the latter works regardless of the initial state (normal, minimized or maximized) of the graph window.
FYI: Your script was apparently written for Origin 7. While it still works in 7.5 a few shortcuts are now available. For example, you can use PageBase::SetShow to minimize or maximize a window.
GraphPage pg(graphname); pg.SetShow(PAGE_MAXIMIZED); pg.SetShow(PAGE_MINIMIZED);
Mike Buess Origin WebRing Member
Edited by - Mike Buess on 02/08/2007 09:50:36 AM |
| bubbas |
Posted - 02/08/2007 : 04:53:23 AM hi my getdatapointfromgraph(string graphname, double& max, int& indexofpoint) function is called by another originC function xrmr_ausl() ...
xrmr_ausl() is then called via script window but doesn't contain any & referenced arguments.
In my reduced version of the problem i would call testdataget() from script window. later i wan't to call it from a button on a worksheet via labtalk.
thx
bubbas |
| Mike Buess |
Posted - 02/07/2007 : 2:40:21 PM Hi bubbas,
I can finally reproduce your problem using your original script. If the graph is minimized or maximized the script works fine. If graph is in between (restored) then I see the behaviour you described. Haven't figured out why yet.
One question: do you normally execute the function from the script window or another Origin C function. Must be the latter because I just get command error if I try from the script window. That's because of the referenced arguments: double& max, int& indexofpoint. Ampersands (&) must be removed for use in script window.
Mike Buess Origin WebRing Member |
| bubbas |
Posted - 02/07/2007 : 11:39:19 AM Yes sometimes ;) But i couldn't forget about it *g*
So i have reduced the problem to the minimum code i think!
void testdataget() { //Create wks Worksheet wks1; wks1.Create(); wks1.GetPage().Rename("wks1"); //Fill col1 Dataset ds1(wks1,0); wks1.Columns(0).SetName("col1"); ds1.SetSize(20); for(int ii=0; ii<20; ii++) { ds1[ii] = ii; }
//Fill col2 Dataset ds2(wks1,1); wks1.Columns(1).SetName("col2"); ds2.SetSize(20); for(ii=0; ii<20; ii++) { ds2[ii] = ii; } string strTemplate = "origin.otp" ; GraphPage grphData; bool thegrph = grphData.Create(strTemplate); GraphLayer grphLayer = grphData.Layers(); Curve crvData(wks1, 0, 1); int nPlot = grphLayer.AddPlot(crvData, IDM_PLOT_LINE); grphLayer.Rescale(); grphData.Rename("Graph1"); LT_execute("win -a Graph1"); LT_execute("win -z Graph1"); read_screen_points();
}
void read_screen_points(int nPts = 1) { // Declare vectors to hold coordinates vector vecX, vecY; // Call function to get points int iRet = get_screen_reader_points(nPts, vecX, vecY); if( iRet < 0 ) printf("Function call to get screen points returned error: %d\n", iRet);
printf("User clicked on %d points\n", iRet); if( 0 != iRet ) { printf("X, Y coordinates of points are:\n"); for(int ii = 0; ii < iRet; ii++) printf(" %d: X = %f, Y = %f\n", ii, vecX[ii], vecY[ii]); } }
// This static function handles calling LabTalk to get user to click on the screen. // Parameters: // nPts: no. of points that user should click // vecX: vector to hold x coordinates of points, passed by reference // vecX: vector to hold y coordinates of points, passed by reference // Return: // -1: no. of points inappropriate // >=0: no. of points user actually clicked static int get_screen_reader_points(int nPts, vector& vecX, vector& vecY) { // Return error if number of points not appropriate // Arbitrary upper limit of 99 - change as desired if( nPts < 1 || nPts > 99) return -1;
// Run the LabTalk section in this file to give user control to click points string strThisFile = __FILE__; string strCMD; strCMD.Format("run.section(%s,GetScreenPts,%d)", strThisFile, nPts); LT_execute(strCMD);
// On return, the LabTalk variable tmp_scr_count has number of points user clicked + 1 double dCount; LT_get_var("tmp_scr_count", &dCount); int nCount = (int) (dCount - 1); if( 0 == nCount ) return 0;
// Get values of x, y coordinates from LabTalk variables and delete the vars vecX.SetSize(nCount); vecY.SetSize(nCount); string strX, strY; double dX, dY; for(int ii = 1; ii <= nCount; ii++) { strX.Format("tmp_scr_pos_x%d", ii); strY.Format("tmp_scr_pos_y%d", ii); LT_get_var(strX, &vecX[ii - 1]); LT_get_var(strY, &vecY[ii - 1]); strCMD.Format("del -v %s", strX); LT_execute(strCMD); strCMD.Format("del -v %s", strY); LT_execute(strCMD); }
// Delete the count LabTalk variable LT_execute("del -v tmp_scr_count;");
// Return the number of points clicked by user return nCount; }
// This section of LabTalk will be ignored by compiler since it is contained within an ifdef block. // The section of script within this block can then be successfully called by a run.section LabTalk command. #ifdef LABTALK [GetScreenPts] // Number of points to get is passed as 1st parameter // Select screen reader tool dotool 3;
// Main loop to accept points tmp_scr_count = 1; def quittoolbox { // Check if user has clicked required number of points if( 1 == tmp_scr_count ) done = 1; if( %1 != tmp_scr_count ) return; }
// Get points and store in temp string variables def pointproc { tmp_scr_pos_x$(tmp_scr_count)=x; tmp_scr_pos_y$(tmp_scr_count)=y; if( tmp_scr_count >= %1 ) { dotool 0; // Set the variable to break the infinite loop done = 1; } tmp_scr_count += 1; } // Set up an "infinite loop" so code waits for user to click points for( done = 0; done == 0; ) { // wait a while sec -p 0.1; } #endif
The data on the curve is not selectable! if i minimize and maximize again manually then it is. Its really strange. Without setting a template it doesn't seem to appear .. but i need a template in the real project ...
thx again
bubbas |
| Mike Buess |
Posted - 02/07/2007 : 10:00:54 AM Sometimes it helps to put it aside and look at it later with fresh eyes. :)
Mike Buess Origin WebRing Member |
| bubbas |
Posted - 02/07/2007 : 09:52:20 AM ok thx anyway. perhaps i rewrite tomorrow the code hoping to find the mistake.
bye
bubbas |
| Mike Buess |
Posted - 02/07/2007 : 09:24:26 AM Sorry bubba, your correction is OK but I still can't reproduce your problem. Some other bug must have crept into your code.
Mike Buess Origin WebRing Member |
| bubbas |
Posted - 02/07/2007 : 09:19:08 AM string strThisFile = __FILE__; string strCMD; strCMD.Format("run.section(%s,GetScreenPts,%d)", strThisFile, nPts); LT_execute(strCMD);
I made the correction ... I can remove the graphname option passed and it still behaves the same :(
thx
bubbas |
| Mike Buess |
Posted - 02/07/2007 : 09:11:08 AM I don't think you made the correction. After pasting your original code to a new C file it behaved for me as you described. After removing the comma I can double-click on a point after which the graph will minimize and the following message is printed to the script window...
User clicked on 1 points X, Y coordinates of points are: 0: X = 10.000000, Y = 10.000000 Index= 10
The coordinates are correct.
...The comma should be replaced by a space ' '.
Mike Buess Origin WebRing Member
Edited by - Mike Buess on 02/07/2007 09:16:47 AM |
| bubbas |
Posted - 02/07/2007 : 08:21:12 AM no that didn't help ...
i think it is related to something y did before ... if( MessageBox( GetWindow(), "Manual Selection of Maxima?", "Attention!" , MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON1 ) == IDYES ) { setmanual=1; } if (setmanual==1) { double maxN=0; int indexN=0; double maxS=0; int indexS=0; //Korrfkt Nord LT_execute("win -a grph_Ausl_AbsTheta_Nord"); LT_execute("win -z grph_Ausl_AbsTheta_Nord"); getdatapointfromgraph("grph_Ausl_AbsTheta_Nord", maxN, indexN); printf("Maximum N Y=%f Index=%d\n", maxN, indexN); dsXRMRKorrfktN_AbsTheta=dsXRMRnormAuslN_AbsTheta/maxN; int iRowN=indexN; int sizeN=dsXRMRKorrfktN_AbsTheta.GetSize(); for (int ii = iRowN+1; ii < sizeN ; ii++) { dsXRMRKorrfktN_AbsTheta[ii] = 1.0; } // Korrfkt Sued LT_execute("win -a grph_Ausl_AbsTheta_Sued"); LT_execute("win -z grph_Ausl_AbsTheta_Sued"); getdatapointfromgraph("grph_Ausl_AbsTheta_Sued", maxS, indexS); printf("Maximum S Y=%f Index=%d\n", maxS, indexS); dsXRMRKorrfktS_AbsTheta=dsXRMRnormAuslS_AbsTheta/maxS; int iRowS=indexS; int sizeS=dsXRMRKorrfktS_AbsTheta.GetSize(); for (ii = iRowS+1; ii < sizeS ; ii++) { dsXRMRKorrfktS_AbsTheta[ii] = 1.0; } //Doubleplot of the functions used to normalize colx = wks2.Columns("AbsTheta"); coly1 = wks2.Columns("Korrfkt.N"); coly2 = wks2.Columns("Korrfkt.S"); strColNameX = colx.GetName(); strColNameY1 = coly1.GetName(); strColNameY2 = coly2.GetName(); GraphTemplate = "Ausl"; GraphName = "Ausl_SAbs_KorrFkt"; xColNum = colx.GetIndex(); y1ColNum = coly1.GetIndex(); y2ColNum = coly2.GetIndex(); CreateDoublePlot(wks2, xColNum, y1ColNum, y2ColNum, GraphName, GraphTemplate, strPathToTemplate); } else { dsXRMRKorrfktN_AbsTheta=dsXRMRnormAuslN_AbsTheta; dsXRMRKorrfktS_AbsTheta=dsXRMRnormAuslS_AbsTheta; }
Previously i called the getdatapointfromgraph() function from the
if( MessageBox( GetWindow(), "Manual Selection of Maxima?", "Attention!" , MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON1 ) == IDYES )
I thought it could be a problem of the appearing messagebox. so i have put it now separate. The first call now works well:
LT_execute("win -a grph_Ausl_AbsTheta_Nord"); LT_execute("win -z grph_Ausl_AbsTheta_Nord"); getdatapointfromgraph("grph_Ausl_AbsTheta_Nord", maxN, indexN); The window appears maximized and accepts the selection. The next call LT_execute("win -a grph_Ausl_AbsTheta_Sued"); LT_execute("win -z grph_Ausl_AbsTheta_Sued"); getdatapointfromgraph("grph_Ausl_AbsTheta_Sued", maxS, indexS);
doesn't work . The window appears maximized but i can't click on the curve. If I click somewhere else it accepts a point which is not on the curve. Moving the point around with the cursors shows that it walks on a curve which is shifted towards the curve shown on the graph. i don't know if it is the right one or one of the other graphs in the background perhaps ??
thx in advance
bubbas |
| bubbas |
Posted - 02/07/2007 : 07:54:46 AM Oh thank you!
I will try that :)
Yes i only need one point to be selected. But didn't had time to change it everywhere. So i just set nPts = 1.
Regards
Bubbas |
| Mike Buess |
Posted - 02/07/2007 : 05:55:14 AM Hi bubbas,
The odd data reader behaviour is due to an extra comma in the get_screen_reader_points function...
string strCMD; //strCMD.Format("run.section(%s,GetScreenPts,%d,%s)", strThisFile, nPts, graphname); // wrong: red comma doesn't belong strCMD.Format("run.section(%s,GetScreenPts,%d %s)", strThisFile, nPts, graphname); // correct: replace red comma with space
BTW, you declare int nPts=1 in the getdatapointfromgraph function and do not change it later. That means you can only get one point a time. Is that intentional?
Mike Buess Origin WebRing Member |
|
|