<< Chapter < Page
  Digital signal processing - dsp     Page 27 / 27
Chapter >> Page >
Listing 37. PlotALot03.java.
/*File PlotALot03.java Copyright 2005, R.G.BaldwinThis program is an update to the program named PlotALot02. This program is designed to plotlarge amounts of time-series data for two channels on alternating horizontal axes. One setof data is plotted using the color black. The other set of data is plotted using the color red.See PlotALot02 for a class that plots two channels of data in black and red superimposed onthe same axes. See PlotALot01.java for a one-channel program.Note that by carefully adjusting the plotting parameters, this program could also be used toplot large quantities of spectral data in a waterfall display.The class provides a main method so that the class can be run as an application to testitself. There are three steps involved in the use of thisclass for plotting time series data: 1. Instantiate a plotting object of typePlotALot03 using one of two overloaded constructors.2. Feed pairs of data values that are to be plotted to the plotting object by calling thefeedData method once for each pair of data values. The first value in the pair will beplotted in black on one axis. The second value in the pair will be plotted in red on anaxis below that axis. 3. call one of two overloaded plotData methodson the plotting object once all of the data has been fed to the object. This causes allof the data to be plotted.A using program can instantiate as many plotting objects as are needed to plot all of thedifferent pairs of time series that need to be plotted. Each plotting object can be used toplot as many pairs of data values as need be plotted until the program runs out of availablememory. The plotting object of type PlotALot03 owns oneor more Page objects that extend the Frame class. The plotting object can own as many Page objectsas are necessary to plot all of the pairs of data that are fed to that plotting object.The program produces a graphic output consisting of a stack of Page objects on the screen, withthe data plotted on a Canvas object contained by the Page object. The Page showing the earliestdata is on the top of the stack and the Page showing the latest data is on the bottom of thestack. The Page objects on the top of the stack must be physically moved in order to see thePage objects on the bottom of the stack. Each Page object contains two or more horizontalaxes on which the data is plotted. The program will terminate if the number of axes on the pageis an odd number. The two time series are plotted on alternatingaxes with the data from one time series being plotted in black on one axis and the data fromthe other time series being plotted in red on the axis below that axis.The earliest data is plotted on the pair of axes nearest the top of the Page moving from left toright across the page. Positive data values are plotted above the axis and negative valuesare plotted below the axis. When the right end of an axis is reached, the next data value isplotted on the left end of the second axis below it skipping one axis in the process. Whenthe right end of the last pair of axes on the Page is reached, a new Page object is created andthe next pair of data values are plotted at the left end of the top pair of axes on that new Pageobject. A mentioned above, there are two overloadedversions of the constructor for the PlotALot03 class. One overloaded version accepts severalincoming parameters allowing the user to control various aspects of the plotting format. A secondoverloaded version accepts a title string only and sets all of the plotting parameters todefault values. You can easily modify these default values and recompile the class if youprefer different default values. The parameters for the version of the constructorthat accepts plotting format information are: String title: Title for the Frame object. Thistitle is concatenated with the page number and the result appears in the banner at the top ofthe Frame. int frameWidth:The Frame width in pixels.int frameHeight: The Frame height in pixels. int traceSpacing: Distance between trace axes inpixels. int sampSpace: Number of pixels dedicated to eachdata sample in pixels per sample. Must be 1 or greater.int ovalWidth: Width of an oval that is used to mark each sample value on the plot.int ovalHeight: Height of an oval that is used to mark each sample value on the plot.For test purposes, the main method instantiates a single plotting object and feeds two time seriesto that plotting object. Plotting parameters are specified for the plotting object by using theoverloaded version of the constructor that accepts plotting parameters.The data that is fed to the plotting object is white random noise. One of the time series isthe sequence of values obtained from a random number generator. The other time series is thesame as the first. Thus, the pairs of black and red time series that are plotted should have thesame shape making it easy to confirm that the process of plotting the two time series isbehaving the same in both cases. Fifteen of the data values for each time seriesare not random. Seven of the values for each of the time series are set to values of 0,0,25,-25,25,0,0. This is done to confirm the proper transition from the end of one page to thebeginning of the next page. In addition, eight of the values for each timeseries are set to 0,0,20,20,-20,-20,0,0. This is done in order to confirm the proper transitionfrom one trace to the next trace on the same page.These specific values and the locations in the data where they are placed provide visibleconfirmation that the transitions mentioned aboveare handled correctly. Note, however that these are the correct locations for an AWT Frame objectunder WinXP. A Frame may have different inset values under other operating systems, which maycause these specific locations to be incorrect for that operating system. In that case, thevalues will be plotted but they won't confirm the proper transition.The following information about the plotting parameters is displayed on the command linescreen when the class is used for plotting. The values shown below result from the execution ofthe main method of the class for test purposes. Title: AFrame width: 158 Frame height: 270Page width: 150 Page height: 243Trace spacing: 36 Sample spacing: 5Traces per page: 6 Samples per page: 90There are two overloaded versions of the plotData method. One version allows the user to specifythe location on the screen where the stack of plotted pages will appear. This version requirestwo parameters, which are coordinate values in pixels. The first parameter specifies thehorizontal coordinate of the upper left corner of the stack of pages relative to the upper leftcorner of the screen. The second parameter specifies the vertical coordinate of the upperleft corner of the stack of pages relative to the upper left corner of the screen. Specifyingcoordinate values of 0,0 causes the stack to be located in the upper left corner of the screen.The other overloaded version of plotData places the stack of pages in the upper left corner ofthe screen by default. The main method in this class uses the second version causing the stackof pages to appear in the upper left corner of the screen by default.Each page has a WindowListener that willterminate the program if the user clicks the close button on the Frame.The program was tested using J2SE 5.0 and WinXP. Requires J2SE 5.0 to support generics.************************************************/ import java.awt.*;import java.awt.event.*; import java.util.*;public class PlotALot03{ //This main method is provided so that the// class can be run as an application to test // itself.public static void main(String[] args){//Instantiate a plotting object using the // version of the constructor that allows for// controlling the plotting parameters. PlotALot03 plotObjectA =new PlotALot03("A",158,270,36,5,4,4);//Feed pairs of data values to the plotting // object.for(int cnt = 0;cnt<175;cnt++){ //Plot some white random noise Note that// fifteen of the values for each time // series are not random. See the opening// comments for a discussion of the reasons // why. Cause the values for the second// time series to be the same as the // values for the first time series.double valBlack = (Math.random() - 0.5)*25; double valRed = valBlack;//Feed pairs of values to the plotting // object by calling the feedData method// once for each pair of data values. if(cnt == 87){plotObjectA.feedData(0,0); }else if(cnt == 88){plotObjectA.feedData(0,0); }else if(cnt == 89){plotObjectA.feedData(25,25); }else if(cnt == 90){plotObjectA.feedData(-25,-25); }else if(cnt == 91){plotObjectA.feedData(25,25); }else if(cnt == 92){plotObjectA.feedData(0,0); }else if(cnt == 93){plotObjectA.feedData(0,0); }else if(cnt == 26){plotObjectA.feedData(0,0); }else if(cnt == 27){plotObjectA.feedData(0,0); }else if(cnt == 28){plotObjectA.feedData(20,20); }else if(cnt == 29){plotObjectA.feedData(20,20); }else if(cnt == 30){plotObjectA.feedData(-20,-20); }else if(cnt == 31){plotObjectA.feedData(-20,-20); }else if(cnt == 32){plotObjectA.feedData(0,0); }else if(cnt == 33){plotObjectA.feedData(0,0); }else{plotObjectA.feedData(valBlack,valRed); }//end else}//end for loop //Cause the data to be plotted in the default// screen location. plotObjectA.plotData();}//end main //-------------------------------------------//String title; int frameWidth;int frameHeight; int traceSpacing;//pixels between tracesint sampSpacing;//pixels between samples int ovalWidth;//width of sample marking ovalint ovalHeight;//height of sample marking ovalint tracesPerPage; int samplesPerPage;int pageCounter = 0; int sampleCounter = 0;ArrayList<Page>pageLinks = new ArrayList<Page>();//There are two overloaded versions of the // constructor for this class. This// overloaded version accepts several incoming // parameters allowing the user to control// various aspects of the plotting format. A // different overloaded version accepts a title// string only and sets all of the plotting // parameters to default values.PlotALot03(String title,//Frame title int frameWidth,//in pixelsint frameHeight,//in pixels int traceSpacing,//in pixelsint sampSpace,//in pixels per sample int ovalWidth,//sample marker widthint ovalHeight)//sample marker hite {//constructor//Specify sampSpace as pixels per sample. // Should never be less than 1. Convert to// pixels between samples for purposes of // computation.this.title = title; this.frameWidth = frameWidth;this.frameHeight = frameHeight; this.traceSpacing = traceSpacing;//Convert to pixels between samples. this.sampSpacing = sampSpace - 1;this.ovalWidth = ovalWidth; this.ovalHeight = ovalHeight;//The following object is instantiated solely // to provide information about the width and// height of the canvas. This information is // used to compute a variety of other// important values. Page tempPage = new Page(title);int canvasWidth = tempPage.canvas.getWidth(); int canvasHeight =tempPage.canvas.getHeight(); //Display information about this plotting// object. System.out.println("\nTitle: " + title);System.out.println( "Frame width: " + tempPage.getWidth());System.out.println( "Frame height: " + tempPage.getHeight());System.out.println( "Page width: " + canvasWidth);System.out.println( "Page height: " + canvasHeight);System.out.println( "Trace spacing: " + traceSpacing);System.out.println( "Sample spacing: " + (sampSpacing + 1));if(sampSpacing<0){ System.out.println("Terminating");System.exit(0); }//end if//Get rid of this temporary page. tempPage.dispose();//Now compute the remaining important values. tracesPerPage = canvasHeight/traceSpacing -traceSpacing/2/traceSpacing; System.out.println("Traces per page: "+ tracesPerPage); if((tracesPerPage == 0) ||(tracesPerPage%2 != 0) ){ System.out.println("Terminating program");System.exit(0); }//end ifsamplesPerPage = canvasWidth * tracesPerPage/ (sampSpacing + 1)/2;System.out.println("Samples per page: " + samplesPerPage);//Now instantiate the first usable Page // object and store its reference in the// list. pageLinks.add(new Page(title));}//end constructor //-------------------------------------------//PlotALot03(String title){//call the other overloaded constructor // passing default values for all but the// title. this(title,400,410,50,2,2,2);}//end overloaded constructor //-------------------------------------------////call this method once for each pair of data// values to be plotted. void feedData(double valBlack,double valRed){if((sampleCounter) == samplesPerPage){ //ifthe page is full, increment the page // counter, create a new empty page, and// reset the sample counter. pageCounter++;sampleCounter = 0; pageLinks.add(new Page(title));}//end if //Store the sample values in the MyCanvas// object to be used later to paint the // screen. Then increment the sample// counter. The sample values pass through // the page object into the current MyCanvas// object. pageLinks.get(pageCounter).putData(valBlack,valRed,sampleCounter); sampleCounter++;}//end feedData //-------------------------------------------////There are two overloaded versions of the// plotData method. One version allows the // user to specify the location on the screen// where the stack of plotted pages will // appear. The other version places the stack// in the upper left corner of the screen.//call one of the overloaded versions of // this method once when all data has been fed// to the plotting object in order to rearrange // the order of the pages with page 0 at the// top of the stack on the screen.//For this overloaded version, specify xCoor // and yCoor to control the location of the// stack on the screen. Values of 0,0 will // place the stack at the upper left corner of// the screen. Also see the other overloaded // version, which places the stack at the upper// left corner of the screen by default. void plotData(int xCoor,int yCoor){Page lastPage = pageLinks.get(pageLinks.size() - 1);//Delay until last page becomes visible. while(!lastPage.isVisible()){//Loop until last page becomes visible }//end while loopPage tempPage = null;//Make all pages invisible for(int cnt = 0;cnt<(pageLinks.size()); cnt++){tempPage = pageLinks.get(cnt); tempPage.setVisible(false);}//end for loop//Now make all pages visible in reverse order // so that page 0 will be on top of the// stack on the screen. for(int cnt = pageLinks.size() - 1;cnt>= 0; cnt--){tempPage = pageLinks.get(cnt); tempPage.setLocation(xCoor,yCoor);tempPage.setVisible(true); }//end for loop}//end plotData(int xCoor,int yCoor) //-------------------------------------------////This overloaded version of the method causes// the stack to be located in the upper left // corner of the screen by defaultvoid plotData(){ plotData(0,0);//call overloaded version}//end plotData() //-------------------------------------------////Inner class. A PlotALot03 object may // have as many Page objects as are required// to plot all of the data values. The // reference to each Page object is stored// in an ArrayList object belonging to the // PlotALot03 object.class Page extends Frame{ MyCanvas canvas;int sampleCounter; Page(String title){//constructorcanvas = new MyCanvas(); add(canvas);setSize(frameWidth,frameHeight); setTitle(title + " Page: " + pageCounter);setVisible(true);//---------------------------------------// //Anonymous inner class to terminate the// program when the user clicks the close // button on the Frame.addWindowListener( new WindowAdapter(){public void windowClosing( WindowEvent e){System.exit(0);//terminate program }//end windowClosing()}//end WindowAdapter );//end addWindowListener//---------------------------------------// }//end constructor//=========================================////This method receives a pair of sample // values of type double and stores each of// them in a separate array object belonging // to the MyCanvas object.void putData(double valBlack,double valRed, int sampleCounter){canvas.blackData[sampleCounter] = valBlack;canvas.redData[sampleCounter] = valRed;//Save the sample counter in an instance // variable to make it available to the// overridden paint method. This value is // needed by the paint method so it will// know how many samples to plot on the // final page which probably won't be full.this.sampleCounter = sampleCounter; }//end putData//=========================================////Inner class class MyCanvas extends Canvas{double [] blackData =new double[samplesPerPage];double [] redData =new double[samplesPerPage];//Override the paint methodpublic void paint(Graphics g){ //Draw horizontal axes, one for each// trace. for(int cnt = 0;cnt<tracesPerPage; cnt++){g.drawLine(0, (cnt+1)*traceSpacing,this.getWidth(), (cnt+1)*traceSpacing);}//end for loop//Plot the points if there are any to be // plotted.if(sampleCounter>0){ for(int cnt = 0;cnt<= sampleCounter; cnt++){//Begin by plotting the values from// the blackData array object. g.setColor(Color.BLACK);//Compute a vertical offset to locate// the black data on the odd numbered // axes on the page.int yOffset = ((1 + cnt*(sampSpacing + 1)/this.getWidth())*2*traceSpacing) - traceSpacing;//Draw an oval centered on the sample // value to mark the sample in the// plot. It is best if the dimensions // of the oval are evenly divisible// by 2 for centering purposes. //Reverse the sign of the sample// value to cause positive sample // values to be plotted above the// axis. g.drawOval(cnt*(sampSpacing + 1)%this.getWidth() - ovalWidth/2, yOffset - (int)blackData[cnt]- ovalHeight/2,ovalWidth, ovalHeight);//Connect the sample values with// straight lines. Do not draw a // line connecting the last sample in// one trace to the first sample in // the next trace.if(cnt*(sampSpacing + 1)% this.getWidth()>= sampSpacing + 1){g.drawLine( (cnt - 1)*(sampSpacing + 1)%this.getWidth(), yOffset - (int)blackData[cnt-1], cnt*(sampSpacing + 1)%this.getWidth(), yOffset - (int)blackData[cnt]); }//end if//Now plot the data stored in the// redData array object. g.setColor(Color.RED);//Compute a vertical offset to locate // the red data on the even numbered// axes on the page. yOffset = (1 + cnt*(sampSpacing + 1)/this.getWidth())*2*traceSpacing;//Draw the ovals as described above. g.drawOval(cnt*(sampSpacing + 1)%this.getWidth() - ovalWidth/2, yOffset - (int)redData[cnt]- ovalHeight/2,ovalWidth, ovalHeight);//Connect the sample values with// straight lines as described above. if(cnt*(sampSpacing + 1)%this.getWidth()>= sampSpacing + 1){g.drawLine((cnt - 1)*(sampSpacing + 1)% this.getWidth(),yOffset - (int)redData[cnt-1],cnt*(sampSpacing + 1)% this.getWidth(),yOffset - (int)redData[cnt]);}//end if}//end for loop }//end if for sampleCounter>0 }//end overridden paint method}//end inner class MyCanvas }//end inner class Page}//end class PlotALot03 //=============================================//
Listing 38. PlotALot04.java.
/*File PlotALot04.java Copyright 2005, R.G.BaldwinThis program is an update to the program named PlotALot03. This program is designed to plotlarge amounts of time-series data for three channels on separate horizontal axes. One setof data is plotted using the color black. The second set of data is plotted using the colorred. The third set of data is plotted using the color blue.See PlotALot03 for a class that plots two channels of data in black and red on alternatingaxes. See PlotALot02 for a class that plots twochannels of data in black and red superimposed on the same axes.See PlotALot01.java for a one-channel program. The class provides a main method so that theclass can be run as an application to test itself.There are three steps involved in the use of this class for plotting time series data:1. Instantiate a plotting object of type PlotALot04 using one of two overloadedconstructors. 2. Feed triplets of data values that are to beplotted to the plotting object by calling the feedData method once for each triplet of datavalues. The first value in the triplet will be plotted in black on one axis. The secondvalue in the triplet will be plotted in red on an axis below that axis. The third value inthe triplet will be plotted in blue on an axis below that one.3. call one of two overloaded plotData methods on the plotting object once all of the datahas been fed to the object. This causes all of the data to be plotted.A using program can instantiate as many plottingobjects as are needed to plot all of the different triplets of data that need to beplotted. Each plotting object can be used to plot as many triplets of data values as need beplotted until the program runs out of available memory.The plotting object of type PlotALot04 owns one or more Page objects that extend the Frame class.The plotting object can own as many Page objects as are necessary to plot all of the triplets ofdata that are fed to that plotting object. The program produces a graphic output consistingof a stack of Page objects on the screen, with the data plotted on a Canvas object contained bythe Page object. The Page showing the earliest data is on the top of the stack and the Pageshowing the latest data is on the bottom of the stack. The Page objects on the top of the stackmust be physically moved in order to see the Page objects on the bottom of the stack.Each Page object contains three or more horizontal axes on which the data is plotted. Theprogram will terminate if the number of axes on the page is not evenly divisible by 3.The three time series are plotted on separate axes with the data from one time series beingplotted in black on one axis, the data from the second time series being plotted in red onthe axis below that axis, and the data from the third time series being plotted in blue on theaxis below that axis. The earliest data is plotted on the three axesnearest the top of the Page moving from left to right across the page. Positive data valuesare plotted above the axis and negative values are plotted below the axis. When the right endof an axis is reached, the next data value is plotted on the left end of the third axisbelow it skipping two axes in the process. When the right end of the last triplet of axes on thePage is reached, a new Page object is created and the next triplet of data values are plotted atthe left end of the top three axes on that new Page object.A mentioned above, there are two overloaded versions of the constructor for the PlotALot04class. One overloaded version accepts several incoming parameters allowing the user to controlvarious aspects of the plotting format. A second overloaded version accepts a title string onlyand sets all of the plotting parameters to default values. You can easily modify thesedefault values and recompile the class if you prefer different default values.The parameters for the version of the constructor that accepts plotting format information are:String title: Title for the Frame object. This title is concatenated with the page number andthe result appears in the banner at the top of the Frame.int frameWidth:The Frame width in pixels. int frameHeight: The Frame height in pixels.int traceSpacing: Distance between trace axes in pixels.int sampSpace: Number of pixels dedicated to each data sample in pixels per sample. Must be 1 orgreater. int ovalWidth: Width of an oval that is used tomark each sample value on the plot. int ovalHeight: Height of an oval that is used tomark each sample value on the plot. For test purposes, the main method instantiates asingle plotting object and feeds three time series to that plotting object. Plottingparameters are specified for the plotting object by using the overloaded version of theconstructor that accepts plotting parameters. The data that is fed to the plotting object iswhite random noise. One of the time series is the sequence of values obtained from a randomnumber generator. The other two time series are the same as the first. Thus, the triplets ofblack, red, and blue time series that are plotted should have the same shape making it easy toconfirm that the process of plotting the three time series is behaving the same in all threecases. Fifteen of the data values for each time seriesare not random. Seven of the values for each of the time series are set to values of 0,0,25,-25,25,0,0. This is done to confirm the proper transition from the end of one page to thebeginning of the next page. In addition, eight of the values for each timeseries are set to 0,0,20,20,-20,-20,0,0. This is done in order to confirm the proper transitionfrom one trace to the next trace on the same page.These specific values and the locations in the data where they are placed provide visibleconfirmation that the transitions mentioned above are handled correctly. Note, however that theseare the correct locations for an AWT Frame object under WinXP. A Frame may have different insetvalues under other operating systems, which may cause these specific locations to be incorrectfor that operating system. In that case, the values will be plotted but they won't confirmthe proper transition. The following information about the plottingparameters is displayed on the command line screen when the class is used for plotting. Thevalues shown below result from the execution of the main method of the class for test purposes.Title: A Frame width: 158Frame height: 270 Page width: 150Page height: 243 Trace spacing: 36Sample spacing: 5 Traces per page: 6Samples per page: 60 There are two overloaded versions of the plotDatamethod. One version allows the user to specify the location on the screen where the stack ofplotted pages will appear. This version requires two parameters, which are coordinate values inpixels. The first parameter specifies the horizontal coordinate of the upper left corner ofthe stack of pages relative to the upper left corner of the screen. The secondparameter specifies the vertical coordinate of the upperleft corner of the stack of pages relative to the upper left corner of the screen. Specifyingcoordinate values of 0,0 causes the stack to be located in the upper left corner of the screen.The other overloaded version of plotData places the stack of pages in the upper left corner ofthe screen by default. The main method in this class uses the second version causing the stackof pages to appear in the upper left corner of the screen by default.Each page has a WindowListener that willterminate the program if the user clicks the close button on the Frame.The program was tested using J2SE 5.0 and WinXP. Requires J2SE 5.0 to support generics.************************************************/ import java.awt.*;import java.awt.event.*; import java.util.*;public class PlotALot04{ //This main method is provided so that the// class can be run as an application to test // itself.public static void main(String[] args){//Instantiate a plotting object using the // version of the constructor that allows for// controlling the plotting parameters. PlotALot04 plotObjectA =new PlotALot04("A",158,270,36,5,4,4);//Feed triplets of data values to the // plotting object.for(int cnt = 0;cnt<115;cnt++){ //Plot some white random noise. Note that// fifteen of the values for each time // series are not random. See the opening// comments for a discussion of the reasons // why.double valBlack = (Math.random() - 0.5)*25; double valRed = valBlack;double valBlue = valBlack; //Feed triplets of values to the plotting// object by calling the feedData method // once for each triplet of data values.if(cnt == 57){ plotObjectA.feedData(0,0,0);}else if(cnt == 58){ plotObjectA.feedData(0,0,0);}else if(cnt == 59){ plotObjectA.feedData(25,25,25);}else if(cnt == 60){ plotObjectA.feedData(-25,-25,-25);}else if(cnt == 61){ plotObjectA.feedData(25,25,25);}else if(cnt == 62){ plotObjectA.feedData(0,0,0);}else if(cnt == 63){ plotObjectA.feedData(0,0,0);}else if(cnt == 26){ plotObjectA.feedData(0,0,0);}else if(cnt == 27){ plotObjectA.feedData(0,0,0);}else if(cnt == 28){ plotObjectA.feedData(20,20,20);}else if(cnt == 29){ plotObjectA.feedData(20,20,20);}else if(cnt == 30){ plotObjectA.feedData(-20,-20,-20);}else if(cnt == 31){ plotObjectA.feedData(-20,-20,-20);}else if(cnt == 32){ plotObjectA.feedData(0,0,0);}else if(cnt == 33){ plotObjectA.feedData(0,0,0);}else{ plotObjectA.feedData(valBlack,valRed, valBlue);}//end else }//end for loop//Cause the data to be plotted in the default // screen location.plotObjectA.plotData(); }//end main//-------------------------------------------// String title;int frameWidth; int frameHeight;int traceSpacing;//pixels between traces int sampSpacing;//pixels between samplesint ovalWidth;//width of sample marking oval int ovalHeight;//height of sample marking ovalint tracesPerPage;int samplesPerPage; int pageCounter = 0;int sampleCounter = 0; ArrayList<Page>pageLinks = new ArrayList<Page>();//There are two overloaded versions of the // constructor for this class. This// overloaded version accepts several incoming // parameters allowing the user to control// various aspects of the plotting format. A // different overloaded version accepts a title// string only and sets all of the plotting // parameters to default values.PlotALot04(String title,//Frame title int frameWidth,//in pixelsint frameHeight,//in pixels int traceSpacing,//in pixelsint sampSpace,//in pixels per sample int ovalWidth,//sample marker widthint ovalHeight)//sample marker hite {//constructor//Specify sampSpace as pixels per sample. // Should never be less than 1. Convert to// pixels between samples for purposes of // computation.this.title = title; this.frameWidth = frameWidth;this.frameHeight = frameHeight; this.traceSpacing = traceSpacing;//Convert to pixels between samples. this.sampSpacing = sampSpace - 1;this.ovalWidth = ovalWidth; this.ovalHeight = ovalHeight;//The following object is instantiated solely // to provide information about the width and// height of the canvas. This information is // used to compute a variety of other// important values. Page tempPage = new Page(title);int canvasWidth = tempPage.canvas.getWidth(); int canvasHeight =tempPage.canvas.getHeight(); //Display information about this plotting// object. System.out.println("\nTitle: " + title);System.out.println( "Frame width: " + tempPage.getWidth());System.out.println( "Frame height: " + tempPage.getHeight());System.out.println( "Page width: " + canvasWidth);System.out.println( "Page height: " + canvasHeight);System.out.println( "Trace spacing: " + traceSpacing);System.out.println( "Sample spacing: " + (sampSpacing + 1));if(sampSpacing<0){ System.out.println("Terminating");System.exit(0); }//end if//Get rid of this temporary page. tempPage.dispose();//Now compute the remaining important values. tracesPerPage = canvasHeight/traceSpacing -traceSpacing/2/traceSpacing; System.out.println("Traces per page: "+ tracesPerPage); if((tracesPerPage == 0) ||(tracesPerPage%3 != 0) ){ System.out.println("Terminating program");System.exit(0); }//end ifsamplesPerPage = canvasWidth * tracesPerPage/ (sampSpacing + 1)/3;System.out.println("Samples per page: " + samplesPerPage);//Now instantiate the first usable Page // object and store its reference in the// list. pageLinks.add(new Page(title));}//end constructor //-------------------------------------------//PlotALot04(String title){//call the other overloaded constructor // passing default values for all but the// title. this(title,400,410,50,2,2,2);}//end overloaded constructor //-------------------------------------------////call this method once for each triplet of// data values to be plotted. void feedData(double valBlack,double valRed, double valBlue){if((sampleCounter) == samplesPerPage){ //if the page is full, increment the page// counter, create a new empty page, and // reset the sample counter.pageCounter++; sampleCounter = 0;pageLinks.add(new Page(title)); }//end if//Store the sample values in the MyCanvas // object to be used later to paint the// screen. Then increment the sample // counter. The sample values pass through// the page object into the current MyCanvas // object.pageLinks.get(pageCounter).putData( valBlack,valRed, valBlue,sampleCounter); sampleCounter++;}//end feedData //-------------------------------------------////There are two overloaded versions of the// plotData method. One version allows the // user to specify the location on the screen// where the stack of plotted pages will // appear. The other version places the stack// in the upper left corner of the screen.//call one of the overloaded versions of // this method once when all data has been fed // to the plotting object in order to rearrange// the order of the pages with page 0 at the // top of the stack on the screen.//For this overloaded version, specify xCoor// and yCoor to control the location of the // stack on the screen. Values of 0,0 will// place the stack at the upper left corner of // the screen. Also see the other overloaded// version, which places the stack at the upper // left corner of the screen by default.void plotData(int xCoor,int yCoor){ Page lastPage =pageLinks.get(pageLinks.size() - 1); //Delay until last page becomes visible.while(!lastPage.isVisible()){ //Loop until last page becomes visible}//end while loopPage tempPage = null; //Make all pages invisiblefor(int cnt = 0;cnt<(pageLinks.size()); cnt++){tempPage = pageLinks.get(cnt); tempPage.setVisible(false);}//end for loop//Now make all pages visible in reverse order // so that page 0 will be on top of the// stack on the screen. for(int cnt = pageLinks.size() - 1;cnt>= 0; cnt--){tempPage = pageLinks.get(cnt); tempPage.setLocation(xCoor,yCoor);tempPage.setVisible(true); }//end for loop}//end plotData(int xCoor,int yCoor) //-------------------------------------------////This overloaded version of the method causes// the stack to be located in the upper left // corner of the screen by defaultvoid plotData(){ plotData(0,0);//call overloaded version}//end plotData() //-------------------------------------------////Inner class. A PlotALot04 object may // have as many Page objects as are required// to plot all of the data values. The // reference to each Page object is stored// in an ArrayList object belonging to the // PlotALot04 object.class Page extends Frame{ MyCanvas canvas;int sampleCounter; Page(String title){//constructorcanvas = new MyCanvas(); add(canvas);setSize(frameWidth,frameHeight); setTitle(title + " Page: " + pageCounter);setVisible(true);//---------------------------------------// //Anonymous inner class to terminate the// program when the user clicks the close // button on the Frame.addWindowListener( new WindowAdapter(){public void windowClosing( WindowEvent e){System.exit(0);//terminate program }//end windowClosing()}//end WindowAdapter );//end addWindowListener//---------------------------------------// }//end constructor//=========================================////This method receives a triplet of sample // values of type double and stores each of// them in a separate array object belonging // to the MyCanvas object.void putData(double valBlack, double valRed,double valBlue, int sampleCounter){canvas.blackData[sampleCounter] = valBlack;canvas.redData[sampleCounter] = valRed;canvas.blueData[sampleCounter] = valBlue;//Save the sample counter in an instance // variable to make it available to the// overridden paint method. This value is // needed by the paint method so it will// know how many samples to plot on the // final page which probably won't be full.this.sampleCounter = sampleCounter; }//end putData//=========================================////Inner class class MyCanvas extends Canvas{double [] blackData =new double[samplesPerPage];double [] redData =new double[samplesPerPage];double [] blueData =new double[samplesPerPage];//Override the paint methodpublic void paint(Graphics g){ //Draw horizontal axes, one for each// trace. for(int cnt = 0;cnt<tracesPerPage; cnt++){g.drawLine(0, (cnt+1)*traceSpacing,this.getWidth(), (cnt+1)*traceSpacing);}//end for loop//Plot the points if there are any to be // plotted.if(sampleCounter>0){ for(int cnt = 0;cnt<= sampleCounter; cnt++){//Begin by plotting the values from// the blackData array object. g.setColor(Color.BLACK);//Compute a vertical offset to locate// the black data on every third axis // on the page.int yOffset = ((1 + cnt*(sampSpacing + 1)/this.getWidth())*3*traceSpacing) - 2*traceSpacing;//Draw an oval centered on the sample // value to mark the sample in the// plot. It is best if the dimensions // of the oval are evenly divisible// by 2 for centering purposes. //Reverse the sign of the sample// value to cause positive sample // values to be plotted above the// axis. g.drawOval(cnt*(sampSpacing + 1)%this.getWidth() - ovalWidth/2, yOffset - (int)blackData[cnt]- ovalHeight/2,ovalWidth, ovalHeight);//Connect the sample values with// straight lines. Do not draw a // line connecting the last sample in// one trace to the first sample in // the next trace.if(cnt*(sampSpacing + 1)% this.getWidth()>= sampSpacing + 1){g.drawLine( (cnt - 1)*(sampSpacing + 1)%this.getWidth(), yOffset - (int)blackData[cnt-1], cnt*(sampSpacing + 1)%this.getWidth(), yOffset - (int)blackData[cnt]); }//end if//Now plot the data stored in the // redData array object.g.setColor(Color.RED); //Compute a vertical offset to locate// the red data on every third axis // on the page.yOffset = (1 + cnt*(sampSpacing + 1)/ this.getWidth())*3*traceSpacing- traceSpacing;//Draw the ovals as described above. g.drawOval(cnt*(sampSpacing + 1)%this.getWidth() - ovalWidth/2, yOffset - (int)redData[cnt]- ovalHeight/2,ovalWidth, ovalHeight);//Connect the sample values with// straight lines as described above. if(cnt*(sampSpacing + 1)%this.getWidth()>= sampSpacing + 1){g.drawLine( (cnt - 1)*(sampSpacing + 1)%this.getWidth(), yOffset - (int)redData[cnt-1], cnt*(sampSpacing + 1)%this.getWidth(), yOffset - (int)redData[cnt]);}//end if//Now plot the data stored in the // blueData array object.g.setColor(Color.BLUE); //Compute a vertical offset to locate// the blue data on every third axis // on the page.yOffset = (1 + cnt*(sampSpacing + 1)/ this.getWidth())*3*traceSpacing;//Draw the ovals as described above.g.drawOval(cnt*(sampSpacing + 1)%this.getWidth() - ovalWidth/2, yOffset - (int)blueData[cnt]- ovalHeight/2,ovalWidth, ovalHeight);//Connect the sample values with// straight lines as described above. if(cnt*(sampSpacing + 1)%this.getWidth()>= sampSpacing + 1){g.drawLine( (cnt - 1)*(sampSpacing + 1)%this.getWidth(), yOffset - (int)blueData[cnt-1], cnt*(sampSpacing + 1)%this.getWidth(), yOffset - (int)blueData[cnt]); }//end if}//end for loop }//end if for sampleCounter>0 }//end overridden paint method}//end inner class MyCanvas }//end inner class Page}//end class PlotALot04 //=============================================//

Miscellaneous

This section contains a variety of miscellaneous information.

Housekeeping material
  • Module name: Java1492-Plotting Large Quantities of Data using Java
  • File: Java1492.htm
  • Published: 08/23/15

Learn how to use Java to plot millions of multi-channel data values in an easy-to-view format with very little programming effort.

Disclaimers:

Financial : Although the Connexions site makes it possible for you to download a PDF file for thismodule at no charge, and also makes it possible for you to purchase a pre-printed version of the PDF file, you should beaware that some of the HTML elements in this module may not translate well into PDF.

I also want you to know that, I receive no financial compensation from the Connexions website even if you purchase the PDF version of the module.

In the past, unknown individuals have copied my modules from cnx.org, converted them to Kindle books, and placed them for sale on Amazon.com showing me as the author. Ineither receive compensation for those sales nor do I know who does receive compensation. If you purchase such a book, please beaware that it is a copy of a module that is freely available on cnx.org and that it was made and published withoutmy prior knowledge.

Affiliation : I am a professor of Computer Information Technology at Austin Community College in Austin, TX.

-end-

Get Jobilize Job Search Mobile App in your pocket Now!

Get it on Google Play Download on the App Store Now




Source:  OpenStax, Digital signal processing - dsp. OpenStax CNX. Jan 06, 2016 Download for free at https://legacy.cnx.org/content/col11642/1.38
Google Play and the Google Play logo are trademarks of Google Inc.

Notification Switch

Would you like to follow the 'Digital signal processing - dsp' conversation and receive update notifications?

Ask