Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Trying to understand Scan ... EndScan

Status
Not open for further replies.

testdev

Programmer
Jun 13, 2016
3
US
There is a table wdata where one field is simply called i

I am trying to understand what the following snippet of code is doing.


Code:
public it7, it6, it5, it4, it3, it2, it1

scan
    it7 = it6
    it6 = it5
    it5 = it4
    it4 = it3
    it3 = it2
    it2 = it1
    it1 = i

    if (it4 >= it3) and it4 >= it2)
      ....
    end if
endscan
 
First of all the code must be incomplete, because at variable initialisation variables are .F. and you get type errors if you would test .F.>=.F.
Edit 1: actually I'm wrong you can use > on logical values, too.
Edit 2: Once some iN are numeric and others still .F. you get type errors, though.

Let's assume the variables are inited with 0, then this construct of assignments is just memorizing i of the last 7 records scanned. You can thereby compare data of different records, while you only have access to one row per iteration normally. It's tricky, but also not as clever as you can get. You can open the same DBF with several aliases and have relations to previous records, then you could start with one alias at Recno()=8.

Bye, Olaf.
 
SCAN/ENDSCAN is similar to this:

Code:
Do While Not EOF()
   * do stuff
   Skip
Enddo

But that's an oversimplification.

SCAN/ENDSCAN is preferable in almost all situations because it it optimizable, and it is scoped to the workarea selected when it starts so no matter what happens during the loop the original workarea is SELECTed on the next iteration.

What the rest of that logic is, there's not enough here to tell but it looks like some sort of rolling balance calculation.
 
Appreciate the help.

Now I can go ahead and try to re-write it in VB.NET

 
You can port this to a new platform, but you're perpetuating a HORRIBLE design onto a brand new platform.

You have data elements named it1, it2 through it7. That's an embedded array which violates every basic principle of proper data design and the code that needs to be written to support such a transgression only grows in complexity over time.

I'd analyze the requirements and redesign the data structures using proper normalization. In the end, the code required to do the same job will be easier to write and maintain. But that's just me.
 
The code, as you have written it, is Not doing anything with Data Tables and their record field values.
(Note - you can declare memory variables PUBLIC, but not Data Table fields nor their varying values)
Consequently your code only shows working on memory variables and their values.
In fact your code does not even show where/how a Data Table might be utilized with the SCAN/ENDSCAN.

Now if your code is not really representative of what you are doing - OK

But if it is representative, then as Dan says above, you need to totally rethink what the code is supposed to be doing and write your VB.net code to optimally handle it.

Good Luck,
JRB-Bldr
 
JRB-Bldr,

the code doesn't show where the wdata table is opened and selected, but testdev stated this table is processed and it has a field i.

Bye, Olaf.
 
To amplify what JRB has said, what your code is doing is setting a bunch of variables to various values, and doing it n times, where n is the number of records in whatever table happens to be selected at the time.

The point is that SCAN/ENDSCAN does a pass of currently-selected table. For each record, it performs the processing between the SCAN and the ENDSCAN.

So, in your case, the code is doing nothing useful. It is setting some variables to the value of other variables; but those other variables haven't been given a value. So you will end up with all of them being set to .F. (which is the value of an unassigned variable), except it1, which will contain the value of the field i. And it will do that n times. So at the end of the code, it1 will contain the value of i in the last record.

I can't help thinking that this is not what you intended.

Mike





__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mike, in iteration 1 i1 will be i, the current records i. In iteration 2, i2 will become i1, the previous records i, and i1 is the current i. Overall after 7 iterations i7 is the i of RECNO()-6, i6 is the i of RECNO()-5, etc. I think you and many here have used similar trickery with report variables storing last rows data for comparison with this row or storing this rows data for comparison with next row.

More than that, the code is cut, implied by the ... (ellipsis). So it is not useless assignments, the comparison of certain rows is given, there seem to be more clauses in the if and more in the if body...

To tell what this code does overall, we'd need to see all of it, that's for sure.

Bye, Olaf.
 
Basically the table contains a field named i and another column named w.
Yeah, no thought given to appropriate names.

Anyhow, the more I ponder it, the more I have come to realize that it7, it6, it5, it4, it3, it2, it1 is a queue where the newest value of i is stuffed in it1.

It is being used to look for a peak value.

 
By peak value, do you mean maximum value? If so, in VFP, a query is a much better approach:

Code:
SELECT MAX(i) AS MaxI ;
  FROM YourTable ;
  INTO CURSOR aMaxVal

That results in a one-record cursor containing the max value of i.

In VB.Net, assuming that you're going to be talking to either VFP or SQL Server tables, the right answer is probably still a query like this, except that when you execute such code remotely, you don't need the INTO line.

Tamar
 
Yes, what Kevin said at MSDN forums. Queue is the right term. Since there is nothing like a queue in VFP as type or class, an array, as Kevin suggests, would perhaps be best fit, but also would need a loop to propaget the values. A queue with 7 elements perhaps would easiest be implemented by a cursor, where you add row by row and if arriving at recno 7 would update record 1 instead of insertint record 8. The head and tail of that queue would then move in the record number and at some point restart.

Mathematically finding peaks would rather be done by a convolution algorithm or a variant, though the most applications of convolution rather are about smoothing than finding peaks.

Converting such code by emulating cursors and iterations 1:1 may not be the best idea. You mainly have some numeric data and try to find peaks. Google peak detection algorithm and you surely find some ideas.

Bye, Olaf.
 
More on the math:

In a simple definition a peak in a series of measurements (or say stock prices) is accompanied by previous and next value both being lower (and a trough is accompanied by both previous and next values being higher).
In many cases you don't want all of these fine granular peaks, you could observe a range of more than just three values. Here 7 values are put into some comparison, I'm sure the IF has more level to take the other values into account.

The technique of convolution can help finding the more interesting peaks by first smoothing out the fine granular peaks you're not interested in.

Taking 7 values is more precise than only taking 3, but also lacks a bit of finesse as 7 values along for example a time axis can represent 7ms, seconds, minutes, hours, days... depending on the granularity of the data and what peaks you want to detect can vary much depending on the data granularity, so this code has potential to be reimplemented in a more general and better way.

Bye, Olaf.
 
Olaf said:
... and a valley is ...

Olaf, a very small correction to your English, if I may. When I am hiking in the Scottish Highlands, "valley" is indeed the opposite of "peak". But in a mathematical or statistical context, the correct word is "trough". Don't ask me why. It's just another wierdness of the language. (A "trough" is also something horses drink out of.)

Of course, this doesn't detract from your interesting exposée of convolution.

Mike




__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Who said valley? ;)

Thanks, Mike. I edited my post.

Convolution (or also deconvolution) or any more sophisticated math may be over the top for the specific problem at hand, but you can do quite nice things, eg compute a moving average or baselines and many more.
More stuff on this, for example:
Bye, Olaf.
 
Who said valley? ;)

Ah, I knew I should have taken a screen shot to submit in evidence.

I agree that the discussion of convolution is a bit over the top, but it is still very interesting - and most of it new to me.

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top