4082 lines
116 KiB
C
4082 lines
116 KiB
C
/* base/src/util $Id$
|
||
* Author: Roger A. Cole
|
||
* Date: 12-04-90
|
||
*
|
||
* Experimental Physics and Industrial Control System (EPICS)
|
||
*
|
||
* Copyright 1991-93, the Regents of the University of California,
|
||
* and the University of Chicago Board of Governors.
|
||
*
|
||
* This software was produced under U.S. Government contracts:
|
||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||
*
|
||
* Initial development by:
|
||
* The Controls and Automation Group (AT-8)
|
||
* Ground Test Accelerator
|
||
* Accelerator Technology Division
|
||
* Los Alamos National Laboratory
|
||
*
|
||
* Co-developed with
|
||
* The Controls and Computing Group
|
||
* Accelerator Systems Division
|
||
* Advanced Photon Source
|
||
* Argonne National Laboratory
|
||
*
|
||
* Modification Log:
|
||
* -----------------
|
||
* .01 12-04-90 rac initial version
|
||
* .02 06-30-91 rac installed in SCCS
|
||
* .03 09-06-91 rac change pprAreaErase to pprRegionErase; add
|
||
* documentation
|
||
* .04 10-01-91 rac properly handle channels which aren't connected yet
|
||
* .05 10-20-91 rac avoid an abort on printing a plot to
|
||
* PostScript; for non-user-window plotting,
|
||
* defer the pprWinIsMono call until after
|
||
* the window is mapped
|
||
* .06 12-03-91 rac add some intelligence to auto ranging
|
||
* .07 01-23-92 rac don't take log10 of zero value
|
||
* .08 03-31-92 rac fix plotting of filled channels; set time axis
|
||
* scaling based on firstData to lastData rather
|
||
* than 0 to sampleCount; handle plotting mean and
|
||
* standard deviation; handle plotting restricted set
|
||
* of data; better annotate time axes; support a time
|
||
* cursor on a plot; add sydPlotChan_event to determine
|
||
* which channel a mouse event applies to;
|
||
* .09 08-27-92 rac add user-specified range for AutoRange; add more
|
||
* smarts to AutoRange; have only one X-axis annotation;
|
||
* add strip chart; discontinue use of special malloc;
|
||
* .10 10-01-92 rac continued work on strip chart; use pprWave routines;
|
||
* .11 01-12-93 rac get StripYY routines in sync with StripY routines
|
||
* .12 05-04-94 pg HPUX port changes.
|
||
*
|
||
* make options
|
||
* -DXWINDOWS makes a version for X11
|
||
* -DNDEBUG don't compile assert() checking
|
||
* -DDEBUG compile various debug code
|
||
*/
|
||
/*+/mod***********************************************************************
|
||
* TITLE sydPlot.c - plotting for synchronous data
|
||
*
|
||
* DESCRIPTION
|
||
* These routines provide high-level plotting capability in conjunction
|
||
* with the sydSubr.c routines. The data acquired by the sydSubr
|
||
* routines are accepted directly by these plotting routines.
|
||
*
|
||
* These routines support plotting in either batch or incremental mode.
|
||
* In batch mode, all the samples exist at the time of plotting; for
|
||
* incremental mode, only part (or none) of the samples exist when
|
||
* plotting starts, and additional samples are to be plotted as they
|
||
* arrive.
|
||
*
|
||
* Some windowing events, such as expose and resize, are transparently
|
||
* handled by these routines. Hard copy of plots to a PostScript
|
||
* printer is easily available.
|
||
*
|
||
* QUICK REFERENCE
|
||
*
|
||
* #include <sydDefs.h>
|
||
* #include <sydPlotDefs.h>
|
||
*
|
||
* void sydPlotAxisAutoRange(pSlave, minVal, maxVal)
|
||
* long sydPlotAxisSetAttr(pSlave, attr, value, pArg)
|
||
* attr = SYD_PLATTR_{GC}
|
||
* SYD_PL_SLAVE *sydPlotChanAdd(pMstr, pSChan)
|
||
* SYD_PL_SLAVE *sydPlotChan_event(pMstr, x, y)
|
||
* long sydPlotDone(pMstr, quitFlag)
|
||
* long sydPlotEraseSamples(pMstr)
|
||
* long sydPlotInit(pMstr, pSspec, winType, dispName, winTitle,
|
||
* fullInit)
|
||
* long sydPlotInitUW(pMstr, pSspec, pDisp, window, gc)
|
||
* long sydPlotSamples(pMstr, begin, end, incrFlag)
|
||
* long sydPlotSetAttr(pMstr, attr, value, pArg)
|
||
* attr = SYD_PLATTR_{FG1,FG2,INCR,LINE,MARK,MONO,POINT,SHOW,
|
||
* UNDER,WRAP}
|
||
* long sydPlotSetTitles(pMstr, top, left, bottom, right)
|
||
* long sydPlotTimeCursor(pMstr, pStamp, pSlave)
|
||
* long sydPlotWinLoop(pMstr)
|
||
* long sydPlotWinReplot(pMstr)
|
||
*
|
||
* DESCRIPTION, continued
|
||
* These routines generally work with the concepts of `plot master'
|
||
* and `plot slave'. The plot master structure roughly corresponds
|
||
* to a plotting surface (i.e., X11 window or PostScript sheet) and
|
||
* contains most of the information necessary to perform plotting.
|
||
* The plot master contains a list of plot slave structures, each of
|
||
* which is analogous to a data channel. A plot slave structure
|
||
* contains channel specific information, including data. Time
|
||
* stamp information is provided via the plot master, through the
|
||
* use of its connection to synchronous sample structures.
|
||
*
|
||
* BUGS
|
||
* o sydPlotInitUW doesn't support SunView; some other routines have
|
||
* questionable support
|
||
* o there is no counterpart for sydTimeCursor for other than time-based
|
||
* plots
|
||
* o knows and uses many intimate details of the ppr structures
|
||
*
|
||
*-***************************************************************************/
|
||
#include <genDefs.h>
|
||
#include <sydDefs.h>
|
||
#include <tsDefs.h>
|
||
#ifdef XWINDOWS
|
||
# include <X11/Xlib.h>
|
||
# include <X11/Xutil.h>
|
||
#endif
|
||
#define SYD_PLOT_PRIVATE
|
||
#include <sydPlotDefs.h>
|
||
|
||
#ifdef vxWorks
|
||
/*----------------------------------------------------------------------------
|
||
* includes and defines for VxWorks compile
|
||
*---------------------------------------------------------------------------*/
|
||
# include <vxWorks.h>
|
||
# include <stdioLib.h>
|
||
# include <strLib.h>
|
||
# include <ctype.h>
|
||
#else
|
||
/*----------------------------------------------------------------------------
|
||
* includes and defines for Sun compile
|
||
*---------------------------------------------------------------------------*/
|
||
# include <stdio.h>
|
||
# include <string.h>
|
||
# include <strings.h>
|
||
# include <ctype.h>
|
||
# include <math.h>
|
||
#endif
|
||
|
||
# ifdef _HPUX_SOURCE
|
||
# ifndef nint
|
||
# define nint(value) (value>=0 ? (int)((value)+.5) : (int)((value)-.5))
|
||
# endif
|
||
# ifndef exp10
|
||
# define exp10(value) (exp(value * log(10.)))
|
||
# endif
|
||
# endif
|
||
|
||
/*-----------------------------------------------------------------------------
|
||
* prototypes
|
||
*----------------------------------------------------------------------------*/
|
||
void sydPlot_SmithPlot();
|
||
void sydPlot_SmithGrid();
|
||
void sydPlot_SmithSamples();
|
||
void sydPlot_SmithStats();
|
||
void sydPlot_StripYPlot();
|
||
void sydPlot_StripYGrid();
|
||
void sydPlot_StripYRedisplay();
|
||
void sydPlot_StripYSamples();
|
||
void sydPlot_StripYYPlot();
|
||
void sydPlot_StripYYGrid();
|
||
void sydPlot_StripYYRedisplay();
|
||
void sydPlot_StripYYSamples();
|
||
void sydPlot_TYPlot();
|
||
void sydPlot_TYGrid();
|
||
void sydPlot_TYSamples();
|
||
void sydPlot_TYStats();
|
||
void sydPlot_TYYPlot();
|
||
void sydPlot_TYYGrid();
|
||
void sydPlot_XYPlot();
|
||
void sydPlot_XYGrid();
|
||
void sydPlot_XYSamples();
|
||
void sydPlot_XYStats();
|
||
void sydPlot_XYarray();
|
||
void sydPlot_XYYPlot();
|
||
void sydPlot_XYYGrid();
|
||
void sydPlot_YPlot();
|
||
void sydPlot_YGrid();
|
||
void sydPlot_YSamples();
|
||
void sydPlot_YStats();
|
||
void sydPlot_Yarray();
|
||
void sydPlot_YYPlot();
|
||
void sydPlot_YYGrid();
|
||
|
||
/*+/internal******************************************************************
|
||
* NAME sydAnnotVal - generate an array of value axis annotations
|
||
*
|
||
*-*/
|
||
static void
|
||
sydAnnotVal(pSlave, pAnnot, annot)
|
||
SYD_PL_SLAVE *pSlave; /* pointer to individual slave struct */
|
||
char *pAnnot[];
|
||
char annot[20][28];
|
||
{
|
||
int i;
|
||
double val, tick;
|
||
|
||
assert(pSlave->nInt < 20);
|
||
|
||
tick = (pSlave->extentVal - pSlave->originVal) / pSlave->nInt;
|
||
|
||
for (i=0, val=pSlave->originVal; i<=pSlave->nInt; i++, val+=tick) {
|
||
if (i == pSlave->nInt)
|
||
val = pSlave->extentVal;
|
||
cvtDblToTxt(annot[i], 6, val, pSlave->decPl);
|
||
pAnnot[i] = annot[i];
|
||
}
|
||
}
|
||
|
||
|
||
/*+/internal******************************************************************
|
||
* NAME logGetOK - get log of minimum allowable tick size
|
||
*
|
||
* DESCRIPTION
|
||
* Find the minimum tick size based on a field width of 6 using
|
||
* cvtDblToTxt using for printing.
|
||
*
|
||
*-*/
|
||
static int logGetOK(val)
|
||
double val;
|
||
{
|
||
int logVal, logTickVal;
|
||
logVal = val != 0. ? nint(floor(log10(fabs(val)))) : -10;
|
||
if (val >= 0.) {
|
||
if (1 <= logVal && logVal <= 4) logTickVal = logVal - 4;
|
||
else if (logVal == 5) logTickVal = 0;
|
||
else if (logVal == -1) logTickVal = -4;
|
||
else logTickVal = logVal - 2;
|
||
}
|
||
else {
|
||
if (1 <= logVal && logVal <= 3) logTickVal = logVal - 3;
|
||
else if (logVal == 4) logTickVal = 0;
|
||
else if (logVal == 0) logTickVal = -3;
|
||
else if (logVal == -1) logTickVal = -4;
|
||
else logTickVal = logVal - 1;
|
||
}
|
||
return logTickVal;
|
||
}
|
||
|
||
/*+/internal******************************************************************
|
||
* NAME moveVal - move a value to it's tick mark
|
||
*
|
||
*-*/
|
||
static double moveVal(val, tick, minFlag)
|
||
double val, tick;
|
||
int minFlag;
|
||
{
|
||
double moved;
|
||
int awayFrom=0;
|
||
double temp;
|
||
|
||
if (val < 0 && minFlag) awayFrom = 1;
|
||
else if (val > 0 && !minFlag) awayFrom = 1;
|
||
if (val > -1. * tick && val < tick && awayFrom == 0)
|
||
return 0.;
|
||
temp = fmod(val, tick);
|
||
moved = val - temp;
|
||
if (awayFrom && temp != 0.) {
|
||
if (val <= 0.) { if (moved > val) moved -= tick; }
|
||
else { if (moved < val) moved += tick; }
|
||
}
|
||
return moved;
|
||
}
|
||
|
||
/*+/internal******************************************************************
|
||
* NAME autoRange - compute auto range for an axis
|
||
*
|
||
*-*/
|
||
static void
|
||
autoRange(pOrigin, pExtent, pNTicks, pTick, pDecPl)
|
||
double *pOrigin, *pExtent, *pTick;
|
||
int *pNTicks, *pDecPl;
|
||
{
|
||
double origin, extent;
|
||
double min, min1, max, max1, logD, tick;
|
||
int logTick, logTickMin, logTickMax, logTickOK;
|
||
double maxVal;
|
||
int nTicks, decPl;
|
||
|
||
#define MIN(a,b) (a<=b?a:b)
|
||
#define MAX(a,b) (a<=b?b:a)
|
||
|
||
min = MIN(*pOrigin, *pExtent);
|
||
max = MAX(*pOrigin, *pExtent);
|
||
if (min == max)
|
||
min -= .001, max += .001;
|
||
min1 = min; max1 = max;
|
||
/*-----------------------------------------------------------------------------
|
||
* First, determine tick size and number of intervals without regard
|
||
* to the number of divisions which would result. Round the min
|
||
* and max to tick boundaries.
|
||
*----------------------------------------------------------------------------*/
|
||
logD = floor(log10(max-min));
|
||
tick = exp10(logD);
|
||
min = moveVal(min, tick, 1);
|
||
max = moveVal(max, tick, 0);
|
||
|
||
nTicks = nint((max - min) / tick);
|
||
if (nTicks == 10) nTicks = 5, tick *= 2.;
|
||
else if (nTicks == 1) nTicks = 5, tick /= 5.;
|
||
else if (nTicks == 2) nTicks = 4, tick /= 2.;
|
||
else if (nTicks == 8) nTicks = 4, tick *= 2.;
|
||
else if (nTicks == 9) nTicks = 3, tick *= 3.;
|
||
/*-----------------------------------------------------------------------------
|
||
* Next, make sure the tick size is consistent with printing in a
|
||
* six character field with 3 significant digits. For example, if the
|
||
* max is 1000000, it will print as 100E4, allowing a minimum tick
|
||
* size of 10000.
|
||
*----------------------------------------------------------------------------*/
|
||
logTick = nint(floor(log10(tick)));
|
||
logTickMax = logGetOK(max);
|
||
logTickMin = logGetOK(min);
|
||
logTickOK = MAX(logTickMin, logTickMax);
|
||
if (logTickOK > logTick) {
|
||
tick = exp10((double)logTickOK);
|
||
min = moveVal(min1, tick, 1);
|
||
max = moveVal(max1, tick, 0);
|
||
nTicks = 1;
|
||
}
|
||
/*-----------------------------------------------------------------------------
|
||
* Now, figure how many decimal places can be printed, based on the
|
||
* biggest endpoint, assuming a field width of 6 characters.
|
||
*----------------------------------------------------------------------------*/
|
||
maxVal = fabs(max) > fabs(min) ? max : min;
|
||
if (maxVal >= 10000. || maxVal <= -1000.) decPl = 0;
|
||
else if (maxVal >= 1000. || maxVal <= -100.) decPl = 1;
|
||
else if (maxVal >= 100. || maxVal <= -10.) decPl = 2;
|
||
else if (maxVal >= 10. || maxVal <= -1.) decPl = 3;
|
||
else decPl = 4;
|
||
if (*pOrigin <= *pExtent) {
|
||
*pTick = tick;
|
||
*pOrigin = min;
|
||
*pExtent = max;
|
||
}
|
||
else {
|
||
*pOrigin = max;
|
||
*pExtent = min;
|
||
*pTick = 0. - tick;
|
||
}
|
||
*pNTicks = nTicks;
|
||
*pDecPl = decPl;
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlotAxisAutoRange - set axis ends to min and max data values
|
||
*
|
||
* DESCRIPTION
|
||
* Sets the endpoints of the axis for the plot slave structure to
|
||
* `nice' values based on the minimum and maximum of the data for the
|
||
* slave. The number of intervals to divide the axis is also set.
|
||
*
|
||
* If the minimum and maximum values specified in the call aren't equal,
|
||
* they are used for scaling, rather than the min and max of the data.
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* SEE ALSO
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlotAxisAutoRange(pSlave, minVal, maxVal)
|
||
SYD_PL_SLAVE *pSlave; /* I pointer to plot slave structure */
|
||
double minVal; /* I minimum value, for setting scaling */
|
||
double maxVal; /* I maximum value, for setting scaling */
|
||
{
|
||
SYD_CHAN *pSChan=pSlave->pSChan;
|
||
double origin=pSlave->pSChan->restrictMinDataVal;
|
||
double extent=pSlave->pSChan->restrictMaxDataVal;
|
||
int nInt, decPl;
|
||
double tick;
|
||
|
||
if (pSChan->dbrType == DBR_TIME_ENUM)
|
||
return;
|
||
if (minVal != maxVal) {
|
||
origin = minVal;
|
||
extent = maxVal;
|
||
}
|
||
|
||
autoRange(&origin, &extent, &nInt, &tick, &decPl);
|
||
pSlave->originVal = origin;
|
||
pSlave->extentVal = extent;
|
||
pSlave->nInt = nInt;
|
||
pSlave->decPl = decPl;
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlotAxisSetAttr - set plot axis attributes
|
||
*
|
||
* DESCRIPTION
|
||
* Setting an attribute doesn't automatically reset other related
|
||
* attributes.
|
||
*
|
||
* Declare a slave to be used as the x-axis channel when x vs. y
|
||
* plotting is done:
|
||
* sydPlotAxisSetAttr(pSlave, SYD_PLATTR_XCHAN, {0,1}, NULL)
|
||
*
|
||
* Set the background and/or foreground pixel values for X11 for
|
||
* a slave:
|
||
* sydPlotAxisSetAttr(pSlave, SYD_PLATTR_BG, 0, pBgPixelValue)
|
||
* sydPlotAxisSetAttr(pSlave, SYD_PLATTR_FG, 0, pFgPixelValue)
|
||
*
|
||
* RETURNS
|
||
* S_syd_OK
|
||
*
|
||
* BUGS
|
||
* o text
|
||
*
|
||
* SEE ALSO
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
long
|
||
sydPlotAxisSetAttr(pSlave, attr, value, pArg)
|
||
SYD_PL_SLAVE *pSlave; /* I pointer to plot slave structure */
|
||
SYD_PLATTR attr; /* I attribute selector--one of SYD_PLATTR_xxx */
|
||
int value; /* I value for attribute */
|
||
void *pArg; /* I pointer for value for attribute */
|
||
{
|
||
if (attr == SYD_PLATTR_XCHAN) pSlave->xChan = value;
|
||
#ifdef XWINDOWS
|
||
else if (attr == SYD_PLATTR_BG)
|
||
pSlave->bg = *(unsigned long *)pArg;
|
||
else if (attr == SYD_PLATTR_FG)
|
||
pSlave->fg = *(unsigned long *)pArg;
|
||
#endif
|
||
else assertAlways(0);
|
||
|
||
return S_syd_OK;
|
||
}
|
||
|
||
/*+/internal******************************************************************
|
||
* NAME sydPlotAxisSetup - set up axis information for a channel
|
||
*
|
||
* DESCRIPTION
|
||
* Set up axis information.
|
||
* o the axis endpoints are set to LOPR and HOPR. If LOPR==HOPR,
|
||
* then minimum and maximum data values are used for endpoints.
|
||
* If min==max, then arbitrary values are used.
|
||
* o number of major intervals is set to 5
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* BUGS
|
||
* o in pathological cases, the setup is overly arbitrary
|
||
* o number of intervals is fixed at 5
|
||
*
|
||
* SEE ALSO
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlotAxisSetup(pSlave)
|
||
SYD_PL_SLAVE *pSlave; /* I pointer to plot slave structure */
|
||
{
|
||
SYD_CHAN *pSChan=pSlave->pSChan;
|
||
double originVal, extentVal;
|
||
int nInt=5;
|
||
|
||
if (pSChan->dbrType == DBR_TIME_FLOAT) {
|
||
originVal = pSChan->grBuf.gfltval.lower_disp_limit;
|
||
extentVal = pSChan->grBuf.gfltval.upper_disp_limit;
|
||
}
|
||
else if (pSChan->dbrType == DBR_TIME_SHORT) {
|
||
originVal = pSChan->grBuf.gshrtval.lower_disp_limit;
|
||
extentVal = pSChan->grBuf.gshrtval.upper_disp_limit;
|
||
}
|
||
else if (pSChan->dbrType == DBR_TIME_DOUBLE) {
|
||
originVal = pSChan->grBuf.gdblval.lower_disp_limit;
|
||
extentVal = pSChan->grBuf.gdblval.upper_disp_limit;
|
||
}
|
||
else if (pSChan->dbrType == DBR_TIME_LONG) {
|
||
originVal = pSChan->grBuf.glngval.lower_disp_limit;
|
||
extentVal = pSChan->grBuf.glngval.upper_disp_limit;
|
||
}
|
||
else if (pSChan->dbrType == DBR_TIME_CHAR) {
|
||
originVal = pSChan->grBuf.gchrval.lower_disp_limit;
|
||
extentVal = pSChan->grBuf.gchrval.upper_disp_limit;
|
||
}
|
||
else if (pSChan->dbrType == DBR_TIME_ENUM) {
|
||
nInt = pSChan->grBuf.genmval.no_str-1;
|
||
originVal = 0;
|
||
extentVal = nInt;
|
||
if (originVal >= extentVal) {
|
||
if (nInt < 0)
|
||
(void)strcpy(pSChan->grBuf.genmval.strs[0], " ");
|
||
extentVal = nInt = 1;
|
||
pSChan->grBuf.genmval.no_str = 2;
|
||
(void)strcpy(pSChan->grBuf.genmval.strs[1], " ");
|
||
}
|
||
}
|
||
if (originVal == extentVal) {
|
||
originVal = pSlave->pSChan->minDataVal;
|
||
extentVal = pSlave->pSChan->maxDataVal;
|
||
}
|
||
if (originVal == extentVal) {
|
||
if (originVal == 0.)
|
||
extentVal = 10.;
|
||
else if (originVal < 0.)
|
||
extentVal = 0;
|
||
else
|
||
originVal = 0.;
|
||
}
|
||
pSlave->originVal = originVal;
|
||
pSlave->extentVal = extentVal;
|
||
pSlave->nInt = nInt;
|
||
pSlave->nSubInt = 0;
|
||
pSlave->decPl = 3;
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlotChanAdd - add a plot slave
|
||
*
|
||
* DESCRIPTION
|
||
* Adds a slave to a master plot structure. Some of the items needed
|
||
* for actual plotting are set up by this routine:
|
||
*
|
||
* o endpoints for plotting. If HOPR and LOPR are present for the
|
||
* channel, they are used as the plotting endpoints. If they
|
||
* aren't present (or if they are equal), then some relatively
|
||
* arbitrary endpoints are picked. For DBF_ENUM channels, the
|
||
* endpoints are determined by the states.
|
||
* o number of major tick intervals. For DBF_ENUM channels, the
|
||
* number of states determines the number of intervals.
|
||
* o a default plot mark to be used for mark plotting
|
||
* o a default line key to be used for monochrome plotting. This
|
||
* line key also establishes a default color to be used for
|
||
* color plotting; the default color can be overridden using
|
||
* sydPlotAxisSetAttr.
|
||
*
|
||
* RETURNS
|
||
* SYD_PL_SLAVE *, or
|
||
* NULL
|
||
*
|
||
* BUGS
|
||
* o the scheme for establishing mark and key numbers won't work if
|
||
* deleting and re-adding plot channels is allowed
|
||
*
|
||
*-*/
|
||
SYD_PL_SLAVE *
|
||
sydPlotChanAdd(pMstr, pSChan)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to plot master */
|
||
SYD_CHAN *pSChan; /* I pointer to synchronous data channel structure,
|
||
as from sydChanOpen */
|
||
{
|
||
SYD_PL_SLAVE *pSlave; /* pointer to slave structure */
|
||
int i;
|
||
|
||
assert(pMstr != NULL);
|
||
|
||
if (dbr_type_is_STRING(pSChan->dbrType)) {
|
||
(void)printf("sydPlotChanAdd: can't plot DBF_STRING values\n");
|
||
return NULL;
|
||
}
|
||
if ((pSlave = (SYD_PL_SLAVE *)malloc(sizeof(SYD_PL_SLAVE))) == NULL) {
|
||
(void)printf("sydPlotChanAdd: can't get memory\n");
|
||
return NULL;
|
||
}
|
||
|
||
pSlave->pSChan = pSChan;
|
||
pMstr->nSlaves++;
|
||
pSlave->markNum = pMstr->nSlaves - 1;
|
||
pSlave->lineKey = pMstr->nSlaves;
|
||
pSlave->xChan = 0;
|
||
pSlave->pArea = NULL;
|
||
pSlave->fg = pSlave->bg = 0;
|
||
pSlave->first = 1;
|
||
pSlave->xFracLeft = pSlave->xFracRight = 0.;
|
||
pSlave->yFracBot = pSlave->yFracTop = 0.;
|
||
pSlave->annotXFL = pSlave->annotXFR = 0.;
|
||
pSlave->annotYFB = pSlave->annotYFT = 0.;
|
||
|
||
DoubleListAppend(pSlave, pMstr->pHead, pMstr->pTail);
|
||
sydPlotAxisSetup(pSlave);
|
||
if (dbr_type_is_ENUM(pSChan->dbrType)) {
|
||
for (i=0; i<=pSlave->extentVal; i++)
|
||
pSlave->pAnnot[i] = pSChan->grBuf.genmval.strs[i];
|
||
pSlave->ppAnnot = pSlave->pAnnot;
|
||
}
|
||
else
|
||
pSlave->ppAnnot = NULL;
|
||
|
||
return pSlave;
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlotChan_event - find the plot slave corresponding to an event
|
||
*
|
||
* DESCRIPTION
|
||
* The x and y position for the event are used to find the corresponding
|
||
* plot slave. This search examines the bounding box for the grid and
|
||
* the annotation area.
|
||
*
|
||
* For a shared grid plot, the result will be ambiguous.
|
||
*
|
||
* RETURNS
|
||
* SYD_PL_SLAVE *, or
|
||
* NULL
|
||
*
|
||
*-*/
|
||
SYD_PL_SLAVE *
|
||
sydPlotChan_event(pMstr, x, y)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to plot master */
|
||
int x, y; /* I the x and y position from the event */
|
||
{
|
||
SYD_PL_SLAVE *pSlave; /* pointer to slave structure */
|
||
int i;
|
||
double xFrac, yFrac;
|
||
|
||
assert(pMstr != NULL);
|
||
|
||
xFrac = PprPixXToXFrac(pMstr->pWin, x);
|
||
yFrac = PprPixYToYFrac(pMstr->pWin, y);
|
||
for (pSlave=pMstr->pHead; pSlave!=NULL; pSlave=pSlave->pNext) {
|
||
if (xFrac >= pSlave->xFracLeft && xFrac <= pSlave->xFracRight &&
|
||
yFrac >= pSlave->yFracBot && yFrac <= pSlave->yFracTop)
|
||
return pSlave;
|
||
if (xFrac >= pSlave->annotXFL && xFrac <= pSlave->annotXFR &&
|
||
yFrac >= pSlave->annotYFB && yFrac <= pSlave->annotYFT)
|
||
return pSlave;
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlotDone - plotting rundown
|
||
*
|
||
* DESCRIPTION
|
||
* Wrap up processing for a plot. Each slave is closed. The present
|
||
* size and position of the plot window are saved in the plot master
|
||
* structure.
|
||
*
|
||
* RETURNS
|
||
* S_syd_OK
|
||
*
|
||
* SEE ALSO
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
long
|
||
sydPlotDone(pMstr, quitFlag)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
int quitFlag; /* I use 0 for replot, 1 for total rundown */
|
||
{
|
||
SYD_PL_SLAVE *pSlave; /* pointer to individual slave struct */
|
||
SYD_PL_SLAVE *pSlave1; /* pointer to individual slave struct */
|
||
|
||
assert(pMstr != NULL);
|
||
|
||
if (quitFlag) {
|
||
pSlave = pMstr->pHead;
|
||
while (pSlave != NULL) {
|
||
pMstr->nSlaves--;
|
||
DoubleListRemove(pSlave, pMstr->pHead, pMstr->pTail);
|
||
if (pSlave->pArea != NULL)
|
||
pprAreaClose(pSlave->pArea);
|
||
pSlave1 = pSlave;
|
||
pSlave = pSlave->pNext;
|
||
free((char *)pSlave1);
|
||
}
|
||
pprWinInfo(pMstr->pWin, &pMstr->x, &pMstr->y,
|
||
&pMstr->width, &pMstr->height);
|
||
pprWinClose(pMstr->pWin);
|
||
}
|
||
|
||
return S_syd_OK;
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlotEraseSamples - erase samples from the screen
|
||
*
|
||
* DESCRIPTION
|
||
* Erase the plot areas for the plot master.
|
||
*
|
||
* RETURNS
|
||
* S_syd_OK
|
||
*
|
||
* SEE ALSO
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
long
|
||
sydPlotEraseSamples(pMstr)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
{
|
||
SYD_PL_SLAVE *pSlave; /* pointer to individual slave struct */
|
||
|
||
assert(pMstr != NULL);
|
||
|
||
pSlave = pMstr->pHead;
|
||
while (pSlave != NULL) {
|
||
pSlave->first = 1;
|
||
if (pSlave->pArea != NULL) {
|
||
pprRegionErase(pSlave->pArea, 1., 1., -1., -1.);
|
||
}
|
||
pSlave = pSlave->pNext;
|
||
}
|
||
|
||
return S_syd_OK;
|
||
}
|
||
|
||
static void sydPlotInit_common();
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlotInit - plotting initialization
|
||
*
|
||
* DESCRIPTION
|
||
* Initialize for plotting, using an automatically created window:
|
||
* o the window is created
|
||
* o if full initialization is requested, then the default window
|
||
* size and position are used; otherwise, the size and position
|
||
* in the plot master (as saved by sydPlotDone) are used.
|
||
*
|
||
* This routine doesn't perform any plotting--sydPlotWinLoop must
|
||
* be called to do the actual plotting.
|
||
*
|
||
* The type of plotting which is done depends both on the window type
|
||
* specified in the call to this routine and on the way that the plot
|
||
* master is set up at the time of the call to sydPlotWinLoop.
|
||
*
|
||
* RETURNS
|
||
* S_syd_OK, or
|
||
* S_syd_ERROR if initialization can't be completed
|
||
*
|
||
* BUGS
|
||
* o need an sdrXxx call to initialize a master with caller-supplied
|
||
* or default size and position
|
||
*
|
||
* SEE ALSO
|
||
* sydPlotInitUW, sydPlotDone, sydPlotWinLoop
|
||
* sydPlotSetAttr
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
long
|
||
sydPlotInit(pMstr, pSspec, winType, dispName, winTitle, fullInit)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to plot master structure */
|
||
SYD_SPEC *pSspec; /* I pointer to synchronous set spec */
|
||
PPR_WIN_TY winType; /* I type of "plot window": PPR_WIN_xxx
|
||
PPR_WIN_SCREEN for an X11 window
|
||
PPR_WIN_POSTSCRIPT for a PostScript file
|
||
PPR_WIN_EPS for an Encapsulated PostScript file
|
||
char *dispName; /* I name of "plot window"--display, PostScript
|
||
file, EPS file, or NULL */
|
||
char *winTitle; /* I title for window title bar and icon */
|
||
int fullInit; /* I 0 or 1 to do partial or full initialization */
|
||
{
|
||
if (fullInit) {
|
||
pMstr->pWin = pprWinOpen(winType, dispName, winTitle, 0,0,0,0);
|
||
if (pMstr->pWin == NULL)
|
||
return S_syd_ERROR;
|
||
pprWinInfo(pMstr->pWin, &pMstr->x, &pMstr->y, &pMstr->width,
|
||
&pMstr->height);
|
||
}
|
||
else {
|
||
pMstr->pWin = pprWinOpen(winType, dispName, winTitle,
|
||
pMstr->x, pMstr->y, pMstr->width, pMstr->height);
|
||
if (pMstr->pWin == NULL)
|
||
return S_syd_ERROR;
|
||
}
|
||
|
||
pMstr->winType = winType;
|
||
pMstr->plotAxis = SYD_PLAX_UNDEF;
|
||
pMstr->pSspec = pSspec;
|
||
sydPlotInit_common(pMstr);
|
||
return S_syd_OK;
|
||
}
|
||
/*+/internal******************************************************************
|
||
* NAME sydPlotInit_common
|
||
*
|
||
*-*/
|
||
static void
|
||
sydPlotInit_common(pMstr)
|
||
SYD_PL_MSTR *pMstr;
|
||
{
|
||
pMstr->linePlot = 1;
|
||
pMstr->pointPlot = 0;
|
||
pMstr->markPlot = 0;
|
||
pMstr->showStat = 0;
|
||
pMstr->fillUnder = 0;
|
||
pMstr->noColor = 0;
|
||
pMstr->errBar = 0;
|
||
#ifdef XWINDOWS
|
||
pMstr->pDisp = NULL;
|
||
pMstr->window = NULL;
|
||
pMstr->bg = 0;
|
||
pMstr->fg = 0;
|
||
pMstr->altPixel1 = 0;
|
||
pMstr->altPixel2 = 0;
|
||
#endif
|
||
pMstr->label[0] = '\0';
|
||
pMstr->title[0] = '\0';
|
||
pMstr->lTitle[0] = '\0';
|
||
pMstr->bTitle[0] = '\0';
|
||
pMstr->rTitle[0] = '\0';
|
||
pMstr->pHead = NULL;
|
||
pMstr->pTail = NULL;
|
||
pMstr->nSlaves = 0;
|
||
pMstr->originVal = 0.;
|
||
pMstr->extentVal = 0.;
|
||
pMstr->nInt = 1;
|
||
pMstr->nSubInt = 0;
|
||
pMstr->stripIncr = .2;
|
||
pMstr->wrapX = 0;
|
||
if (pMstr->pSspec->sampleCount >= 1) {
|
||
pMstr->originVal =
|
||
pMstr->pSspec->pDeltaSec[pMstr->pSspec->restrictFirstData] -
|
||
pMstr->pSspec->restrictDeltaSecSubtract;
|
||
pMstr->extentVal =
|
||
pMstr->pSspec->pDeltaSec[pMstr->pSspec->restrictLastData] -
|
||
pMstr->pSspec->restrictDeltaSecSubtract;
|
||
}
|
||
}
|
||
|
||
#ifdef XWINDOWS
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlotInitUW - plotting initialization, using User Window
|
||
*
|
||
* DESCRIPTION
|
||
* Initialize for plotting, using a user-supplied window.
|
||
*
|
||
* This routine doesn't perform any actual plotting. When an expose
|
||
* or resize event occurs (or when additional samples are received
|
||
* when plotting in incremental mode), one of the following routines
|
||
* must be called to perform plotting:
|
||
*
|
||
* sydPlotWinReplot--plots all the samples in the synchronous data
|
||
* set.
|
||
*
|
||
* sydPlotSamples--plots the indicated subset of the samples in the
|
||
* synchronous data set.
|
||
*
|
||
* RETURNS
|
||
* S_syd_OK
|
||
*
|
||
* BUGS
|
||
* o available only for X11
|
||
*
|
||
* SEE ALSO
|
||
* sydPlotInit, sydPlotDone, sydPlotWinReplot, sydPlotSamples
|
||
* sydPlotSetAttr
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
long
|
||
sydPlotInitUW(pMstr, pSspec, pDisp, window, gc)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to plot master structure */
|
||
SYD_SPEC *pSspec; /* I pointer to synchronous set spec */
|
||
Display *pDisp; /* I X11 display pointer */
|
||
Window window; /* I X11 window handle */
|
||
GC gc; /* I X11 gc handle */
|
||
{
|
||
long stat;
|
||
|
||
pMstr->pWin = pprWinOpenUW(&pDisp, &window, &gc, NULL);
|
||
assertAlways(pMstr->pWin != NULL);
|
||
|
||
pMstr->winType = PPR_WIN_SCREEN;
|
||
pMstr->plotAxis = SYD_PLAX_UNDEF;
|
||
pMstr->pSspec = pSspec;
|
||
sydPlotInit_common(pMstr);
|
||
if (pprWinIsMono(pMstr->pWin))
|
||
pMstr->noColor = 1;
|
||
else
|
||
pMstr->noColor = 0;
|
||
pMstr->pDisp = pDisp;
|
||
pMstr->window = window;
|
||
|
||
return S_syd_OK;
|
||
}
|
||
#endif XWINDOWS
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlotSamples - plot one or more sync samples
|
||
*
|
||
* DESCRIPTION
|
||
* Plot one or more samples in the synchronous sample set (whose
|
||
* handle is held by the plot master). The sample range is specified
|
||
* as sample numbers within the sync sample set.
|
||
*
|
||
* This routine is for use only with sydPlotInitUW. When this routine
|
||
* is called, the sydPlot_xxx routine indicated by the .plotAxis
|
||
* member of the plot master structure is called.
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* BUGS
|
||
* o text
|
||
*
|
||
* SEE ALSO
|
||
* sydPlotInitUW, sydPlotSetAttr, sydPlot_xxx
|
||
*
|
||
* NOTES
|
||
* 1. The `incrFlag' argument allows plotting in either batch or
|
||
* incremental mode. If incrFlag is 1, then this set of samples will
|
||
* be treated as a continuation of a prior set of samples. This is
|
||
* important primarily for line plots. Both sydPlotChanAdd and
|
||
* sydPlotEraseSamples set the flag (for one or all slaves, respectively)
|
||
* indicating there was no prior set of samples; this might be used
|
||
* to avoid having to change incrFlag back and forth.
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlotSamples(pMstr, begin, end, incrFlag)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
int begin; /* I number of begin sample to plot */
|
||
int end; /* I number of end sample to plot */
|
||
int incrFlag; /* I 0,1 for batch,incremental plotting */
|
||
{
|
||
if (pMstr->plotAxis == SYD_PLAX_TY)
|
||
sydPlot_TYSamples(pMstr, begin, end, incrFlag);
|
||
else if (pMstr->plotAxis == SYD_PLAX_TYY)
|
||
sydPlot_TYSamples(pMstr, begin, end, incrFlag);
|
||
else if (pMstr->plotAxis == SYD_PLAX_XY)
|
||
sydPlot_XYSamples(pMstr, begin, end, incrFlag);
|
||
else if (pMstr->plotAxis == SYD_PLAX_XYY)
|
||
sydPlot_XYSamples(pMstr, begin, end, incrFlag);
|
||
else if (pMstr->plotAxis == SYD_PLAX_Y)
|
||
sydPlot_YSamples(pMstr, begin, end, incrFlag);
|
||
else if (pMstr->plotAxis == SYD_PLAX_YY)
|
||
sydPlot_YSamples(pMstr, begin, end, incrFlag);
|
||
else if (pMstr->plotAxis == SYD_PLAX_STRIP_Y)
|
||
sydPlot_StripYSamples(pMstr, begin, end, incrFlag);
|
||
else if (pMstr->plotAxis == SYD_PLAX_STRIP_YY)
|
||
sydPlot_StripYSamples(pMstr, begin, end, incrFlag);
|
||
else if (pMstr->plotAxis == SYD_PLAX_SMITH_IMP ||
|
||
pMstr->plotAxis == SYD_PLAX_SMITH_ADM ||
|
||
pMstr->plotAxis == SYD_PLAX_SMITH_IMM)
|
||
sydPlot_SmithSamples(pMstr, begin, end, incrFlag);
|
||
else
|
||
assertAlways(0);
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlotSetAttr - set plot attributes
|
||
*
|
||
* DESCRIPTION
|
||
* Setting an attribute doesn't automatically reset other related
|
||
* attributes.
|
||
*
|
||
* sydPlotSetAttr(pMstr, SYD_PLATTR_FG1, 0, &fgPixVal)
|
||
* sydPlotSetAttr(pMstr, SYD_PLATTR_FG2, 0, &fgPixVal)
|
||
* sydPlotSetAttr(pMstr, SYD_PLATTR_INCR, 0, &stripIncr_sec)
|
||
* sydPlotSetAttr(pMstr, SYD_PLATTR_LINE, {0,1}, NULL)
|
||
* sydPlotSetAttr(pMstr, SYD_PLATTR_MARK, {0,1}, NULL)
|
||
* sydPlotSetAttr(pMstr, SYD_PLATTR_MONO, {0,1}, NULL)
|
||
* sydPlotSetAttr(pMstr, SYD_PLATTR_POINT, {0,1}, NULL)
|
||
* sydPlotSetAttr(pMstr, SYD_PLATTR_SHOW, {0,1}, NULL)
|
||
* sydPlotSetAttr(pMstr, SYD_PLATTR_STDDEV, {0,1}, NULL)
|
||
* sydPlotSetAttr(pMstr, SYD_PLATTR_UNDER, {0,1}, NULL)
|
||
* sydPlotSetAttr(pMstr, SYD_PLATTR_WRAP, {0,1}, NULL)
|
||
* sydPlotSetAttr(pMstr, SYD_PLATTR_XLAB, {0,1}, NULL)
|
||
* sydPlotSetAttr(pMstr, SYD_PLATTR_XANN, {0,1}, NULL)
|
||
* sydPlotSetAttr(pMstr, SYD_PLATTR_YLAB, {0,1}, NULL)
|
||
* sydPlotSetAttr(pMstr, SYD_PLATTR_YANN, {0,1}, NULL)
|
||
*
|
||
* RETURNS
|
||
* S_syd_OK
|
||
*
|
||
* BUGS
|
||
* o there should be a SYD_PLATTR_AXIS_TYPE, rather than having to
|
||
* explicitly set the .plotAxis member of the plot master structure
|
||
*
|
||
* SEE ALSO
|
||
* sydPlotSetTitles, sydPlotInit, sydPlotInitUW
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
long
|
||
sydPlotSetAttr(pMstr, attr, value, pArg)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to plot master structure */
|
||
SYD_PLATTR attr; /* I attribute selector--one of SYD_PLATTR_xxx */
|
||
int value; /* I value for attribute */
|
||
void *pArg; /* I pointer for value for attribute */
|
||
{
|
||
#ifdef XWINDOWS
|
||
if (attr == SYD_PLATTR_FG1) pMstr->altPixel1 = *(unsigned long *)pArg;
|
||
else if (attr == SYD_PLATTR_FG2) pMstr->altPixel2 = *(unsigned long *)pArg;
|
||
else
|
||
#endif
|
||
if (attr == SYD_PLATTR_LINE) pMstr->linePlot = value;
|
||
else if (attr == SYD_PLATTR_MARK) pMstr->markPlot = value;
|
||
else if (attr == SYD_PLATTR_POINT) pMstr->pointPlot = value;
|
||
else if (attr == SYD_PLATTR_SHOW) pMstr->showStat = value;
|
||
else if (attr == SYD_PLATTR_UNDER) pMstr->fillUnder = value;
|
||
else if (attr == SYD_PLATTR_WRAP) pMstr->wrapX = value;
|
||
else if (attr == SYD_PLATTR_XLAB) pMstr->useXlabel = value;
|
||
else if (attr == SYD_PLATTR_XANN) pMstr->useXannot = value;
|
||
else if (attr == SYD_PLATTR_YLAB) pMstr->useYlabel = value;
|
||
else if (attr == SYD_PLATTR_YANN) pMstr->useYannot = value;
|
||
else if (attr == SYD_PLATTR_MONO) pMstr->noColor = value;
|
||
else if (attr == SYD_PLATTR_STDDEV) {
|
||
if (value == 1)
|
||
pMstr->errBar = SYD_PLATTR_STDDEV;
|
||
else
|
||
pMstr->errBar = 0;
|
||
}
|
||
else if (attr == SYD_PLATTR_INCR) pMstr->stripIncr = *(float *)pArg;
|
||
else assertAlways(0);
|
||
|
||
return S_syd_OK;
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlotSetTitles - establish or change titles for a plot
|
||
*
|
||
* DESCRIPTION
|
||
* Set the titles for a plot.
|
||
*
|
||
* By default, there are no titles for a plot. If the argument
|
||
* for a particular title isn't NULL, then that title is changed.
|
||
*
|
||
* RETURNS
|
||
* S_syd_OK
|
||
*
|
||
* BUGS
|
||
* o text
|
||
*
|
||
* SEE ALSO
|
||
* sydPlot_setup, sydPlotSetAttr
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
long
|
||
sydPlotSetTitles(pMstr, top, left, bottom, right)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to plot master structure */
|
||
char *top; /* I title for top of plot, or NULL */
|
||
char *left; /* I title for left of plot, or NULL */
|
||
char *bottom; /* I title for bottom of plot, or NULL */
|
||
char *right; /* I title for right of plot, or NULL */
|
||
{
|
||
if (top != NULL) {
|
||
assert(strlen(top) < sizeof(pMstr->title));
|
||
strcpy(pMstr->title, top);
|
||
}
|
||
if (left != NULL) {
|
||
assert(strlen(left) < sizeof(pMstr->lTitle));
|
||
strcpy(pMstr->lTitle, left);
|
||
}
|
||
if (bottom != NULL) {
|
||
assert(strlen(bottom) < sizeof(pMstr->bTitle));
|
||
strcpy(pMstr->bTitle, bottom);
|
||
}
|
||
if (right != NULL) {
|
||
assert(strlen(right) < sizeof(pMstr->rTitle));
|
||
strcpy(pMstr->rTitle, right);
|
||
}
|
||
|
||
return S_syd_OK;
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlotTimeCursor - plot a time `cursor'
|
||
*
|
||
* DESCRIPTION
|
||
* Draws or erases a vertical line corresponding to the specified
|
||
* time stamp. If a plot slave is specified, its annotation area
|
||
* is outlined (or the outline is erased).
|
||
*
|
||
* The drawing is done using the X GXxor function, so that the first
|
||
* call for a time stamp draws a line and the next call for the
|
||
* same time stamp erases the line.
|
||
*
|
||
* RETURNS
|
||
* S_syd_OK
|
||
*
|
||
* NOTES
|
||
* 1. Since alternate calls to this routine draw and erase, speciall
|
||
* handling is needed by the caller who wants to draw several time
|
||
* cursors and also outline the annotation area for a plot slave.
|
||
* For this case, the pointer to the plot slave should be used in only
|
||
* _one_ of the calls to this routine.
|
||
*
|
||
*-*/
|
||
long
|
||
sydPlotTimeCursor(pMstr, pStamp, pSlave)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to plot master structure */
|
||
TS_STAMP *pStamp; /* I time stamp to position cursor */
|
||
SYD_PL_SLAVE *pSlave; /* I pointer to plot slave structure, or NULL */
|
||
{
|
||
SYD_SPEC *pSspec = pMstr->pSspec;
|
||
double diff; /* offset of stamp from reference stamp */
|
||
PPR_AREA *pArea;
|
||
|
||
if (pMstr->plotAxis != SYD_PLAX_TY && pMstr->plotAxis != SYD_PLAX_TYY)
|
||
return S_syd_OK;
|
||
|
||
TsDiffAsDouble(&diff, pStamp, &pSspec->restrictRefTs);
|
||
if (diff < pMstr->originVal || diff > pMstr->extentVal)
|
||
return S_syd_OK;
|
||
pArea = pprAreaOpen(pMstr->pWin,
|
||
pMstr->originFrac, 0., pMstr->extentFrac, 1.,
|
||
pMstr->originVal, 0., pMstr->extentVal, 1.,
|
||
1, 1, 0.);
|
||
assertAlways(pArea != NULL);
|
||
XSetFunction(pArea->pWin->pDisp, pArea->attr.gc, GXinvert);
|
||
XSetPlaneMask(pArea->pWin->pDisp, pArea->attr.gc, 1);
|
||
pprLineSegD(pArea, diff, 0., diff, 1.);
|
||
pprAreaClose(pArea);
|
||
pArea = pprAreaOpen(pMstr->pWin, 0.,0.,1.,1., 0.,0.,1.,1., 1, 1, 0.);
|
||
assertAlways(pArea != NULL);
|
||
XSetFunction(pArea->pWin->pDisp, pArea->attr.gc, GXinvert);
|
||
XSetPlaneMask(pArea->pWin->pDisp, pArea->attr.gc, 1);
|
||
if (pSlave != NULL) {
|
||
double inX, inY; /* insets into the annot area */
|
||
inX = (pSlave->annotXFR - pSlave->annotXFL) * .05;
|
||
inY = (pSlave->annotYFT - pSlave->annotYFB) * .05;
|
||
pprMoveD(pArea, pSlave->annotXFL+inX, pSlave->annotYFB+inY, 0);
|
||
pprMoveD(pArea, pSlave->annotXFL+inX, pSlave->annotYFT-inY, 1);
|
||
pprMoveD(pArea, pSlave->annotXFR-inX, pSlave->annotYFT-inY, 1);
|
||
pprMoveD(pArea, pSlave->annotXFR-inX, pSlave->annotYFB+inY, 1);
|
||
pprMoveD(pArea, pSlave->annotXFL+inX, pSlave->annotYFB+inY, 1);
|
||
}
|
||
pprAreaClose(pArea);
|
||
|
||
return S_syd_OK;
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlotWinLoop - do the actual plotting
|
||
*
|
||
* DESCRIPTION
|
||
* Perform the actual plotting for a plot master which was set up
|
||
* using sydPlotInit.
|
||
*
|
||
* This routine is for use only with sydPlotInit. When this routine
|
||
* is called, the sydPlot_xxx routine indicated by the .plotAxis
|
||
* member of the plot master structure is called.
|
||
*
|
||
* This routine creates and maps a window and draws the plot. This
|
||
* routine retains control (for processing expose and resize events)
|
||
* until the mouse pointer is placed in the plot window and the right
|
||
* button is clicked.
|
||
*
|
||
* RETURNS
|
||
* S_syd_OK
|
||
*
|
||
* BUGS
|
||
* o text
|
||
*
|
||
* SEE ALSO
|
||
* sydPlotInit, sydPlotSetAttr, sydPlot_xxx
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
long
|
||
sydPlotWinLoop(pMstr)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to plot master structure */
|
||
{
|
||
SYD_PLAX pltTy = pMstr->plotAxis; /* type of plot desired */
|
||
long stat;
|
||
int npts, beg, end;
|
||
SYD_SPEC *pSspec = pMstr->pSspec;
|
||
|
||
npts = pSspec->sampleCount;
|
||
beg = pSspec->restrictFirstData;
|
||
end = pSspec->restrictLastData;
|
||
if (npts <= 1 || pMstr->originVal == pMstr->extentVal) {
|
||
pMstr->originVal = 0.;
|
||
pMstr->extentVal = 100.;
|
||
strcpy(pMstr->label, "elapsed seconds");
|
||
pMstr->nInt = 5;
|
||
}
|
||
|
||
if (pprWinMap(pMstr->pWin) != 0)
|
||
return S_syd_ERROR;
|
||
if (pprWinIsMono(pMstr->pWin))
|
||
pMstr->noColor = 1;
|
||
else
|
||
pMstr->noColor = 0;
|
||
stat = pprWinLoop(pMstr->pWin, sydPlot, pMstr);
|
||
if (stat != OK)
|
||
return S_syd_ERROR;
|
||
|
||
pprWinInfo(pMstr->pWin, &pMstr->x, &pMstr->y,&pMstr->width,&pMstr->height);
|
||
|
||
return S_syd_OK;
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlotWinReplot - do the actual plotting
|
||
*
|
||
* DESCRIPTION
|
||
* Perform the actual plotting for a plot master which was set up
|
||
* using sydPlotInitUW. This routine calls the sydPlot_xxx routine
|
||
* indicated by the .plotAxis member of the plot master structure.
|
||
*
|
||
* RETURNS
|
||
* S_syd_OK
|
||
*
|
||
* BUGS
|
||
* o text
|
||
*
|
||
* SEE ALSO
|
||
* sydPlotInitUW, sydPlotSamples, sydPlot_xxx
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
long
|
||
sydPlotWinReplot(pMstr)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to plot master structure */
|
||
{
|
||
int npts, beg, end;
|
||
SYD_SPEC *pSspec = pMstr->pSspec;
|
||
|
||
npts = pSspec->sampleCount;
|
||
beg = pSspec->restrictFirstData;
|
||
end = pSspec->restrictLastData;
|
||
if (npts <= 1 || pMstr->originVal == pMstr->extentVal) {
|
||
pMstr->originVal = 0.;
|
||
pMstr->extentVal = 100.;
|
||
strcpy(pMstr->label, "elapsed seconds");
|
||
pMstr->nInt = 5;
|
||
}
|
||
|
||
pprWinErase(pMstr->pWin);
|
||
pprWinReplot(pMstr->pWin, sydPlot, pMstr);
|
||
|
||
return S_syd_OK;
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlot - call the plot routine appropriate for plot type
|
||
*
|
||
* DESCRIPTION
|
||
* Provides a generic interface for doing the actual plotting. This
|
||
* routine calls the specific plotting routine as dictated by the
|
||
* set up for the plot master. That routine will draw the grid(s)
|
||
* and plot the data.
|
||
*
|
||
* Prior to calling this routine, the caller must set several values
|
||
* in the plot master structure to control how plotting is done. Except
|
||
* for the .plotAxis member, the preferred method for setting the
|
||
* values is with the sydPlotSetAttr routine.
|
||
*
|
||
* .plotAxis--the type of axis used in plotting:
|
||
* SYD_PLAX_TY value vs time, separate grids
|
||
* SYD_PLAX_TYY value vs time, shared grid
|
||
* SYD_PLAX_XY value vs value, separate grids
|
||
* SYD_PLAX_XYY value vs value, shared grid
|
||
* SYD_PLAX_Y value vs bin number, separate grids
|
||
* SYD_PLAX_YY value vs bin number, shared grid
|
||
* SYD_PLAX_STRIP_Y value vs delta time, separate grids
|
||
* SYD_PLAX_STRIP_YY value vs delta time, shared grid
|
||
* SYD_PLAX_SMITH_IMP value vs value, with Smith impedance overlay
|
||
* SYD_PLAX_SMITH_ADM value vs value, with Smith admittance overlay
|
||
* SYD_PLAX_SMITH_IMM value vs value, with Smith immitance overlay
|
||
*
|
||
* .linePlot--1 to connect data points with lines, else 0
|
||
* .markPlot--1 to plot a mark at each data point, else 0
|
||
* .pointPlot--1 to plot a point at each data point, else 0
|
||
* .showStat--1 to plot a status indicator at each data point, else 0
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* BUGS
|
||
* o text
|
||
*
|
||
* SEE ALSO
|
||
* sydPlotSetAttr, specific sydPlot_xxx routines
|
||
*
|
||
* NOTES
|
||
* 1. This routine isn't intended to be called directly.
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlot(pWin, pMstr)
|
||
PPR_WIN *pWin; /* I pointer to plot window structure */
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
{
|
||
pprWinInfo(pWin, &pMstr->x, &pMstr->y, &pMstr->width, &pMstr->height);
|
||
if (pMstr->plotAxis == SYD_PLAX_TY)
|
||
sydPlot_TYPlot(pMstr);
|
||
else if (pMstr->plotAxis == SYD_PLAX_TYY)
|
||
sydPlot_TYYPlot(pMstr);
|
||
else if (pMstr->plotAxis == SYD_PLAX_XY)
|
||
sydPlot_XYPlot(pMstr);
|
||
else if (pMstr->plotAxis == SYD_PLAX_XYY)
|
||
sydPlot_XYYPlot(pMstr);
|
||
else if (pMstr->plotAxis == SYD_PLAX_Y)
|
||
sydPlot_YPlot(pMstr);
|
||
else if (pMstr->plotAxis == SYD_PLAX_YY)
|
||
sydPlot_YYPlot(pMstr);
|
||
else if (pMstr->plotAxis == SYD_PLAX_STRIP_Y)
|
||
sydPlot_StripYPlot(pMstr);
|
||
else if (pMstr->plotAxis == SYD_PLAX_STRIP_YY)
|
||
sydPlot_StripYYPlot(pMstr);
|
||
else if (pMstr->plotAxis == SYD_PLAX_SMITH_IMP ||
|
||
pMstr->plotAxis == SYD_PLAX_SMITH_ADM ||
|
||
pMstr->plotAxis == SYD_PLAX_SMITH_IMM)
|
||
sydPlot_SmithPlot(pMstr);
|
||
else
|
||
assertAlways(0);
|
||
}
|
||
|
||
/*/macro-----------------------------------------------------------------------
|
||
* NAME FetchIthValInto - space saver for getting value as a double
|
||
*
|
||
*----------------------------------------------------------------------------*/
|
||
#define FetchIthValInto(pSChan, dbl) \
|
||
if (dbr_type_is_FLOAT(pSChan->dbrType)) \
|
||
dbl = (double)((float *)pSChan->pData)[i]; \
|
||
else if (dbr_type_is_SHORT(pSChan->dbrType)) { \
|
||
if (pSChan->isRVAL) \
|
||
dbl = (double)((unsigned short *)pSChan->pData)[i]; \
|
||
else \
|
||
dbl = (double)((short *)pSChan->pData)[i]; \
|
||
} \
|
||
else if (dbr_type_is_DOUBLE(pSChan->dbrType)) \
|
||
dbl = (double)((double *)pSChan->pData)[i]; \
|
||
else if (dbr_type_is_LONG(pSChan->dbrType)) { \
|
||
if (pSChan->isRVAL) \
|
||
dbl = (double)((unsigned long *)pSChan->pData)[i]; \
|
||
else \
|
||
dbl = (double)((long *)pSChan->pData)[i]; \
|
||
} \
|
||
else if (dbr_type_is_CHAR(pSChan->dbrType)) \
|
||
dbl = (double)((char *)pSChan->pData)[i]; \
|
||
else if (dbr_type_is_ENUM(pSChan->dbrType)) \
|
||
dbl = (double)((short *)pSChan->pData)[i]; \
|
||
else \
|
||
assertAlways(0);
|
||
#if 0
|
||
dbl = (double)((short *)pSChan->pData)[i];
|
||
#endif
|
||
|
||
|
||
/*+/internal******************************************************************
|
||
* NAME sydPlot_setup - set up titles and margins for a plot window
|
||
*
|
||
* DESCRIPTION
|
||
* Plots whatever titles are present in the plot master, reserving
|
||
* an appropriate margin when necessary.
|
||
*
|
||
* All slaves can be plotted in a shared grid, or separate grids
|
||
* can be used. This is controlled by the `nGrids' argument.
|
||
*
|
||
* This routine returns information to allow easily intermixing calls
|
||
* to the pprPlot routines with calls to sydPlot routines.
|
||
*
|
||
* If plotting is for PostScript, date and time are plotted in the
|
||
* upper right corner of the window.
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* BUGS
|
||
* o handles only vertical subdividing of the plot window (i.e., into
|
||
* long horizontal strips)
|
||
*
|
||
*-*/
|
||
static void
|
||
sydPlot_setup(pMstr, nGrids, pXlo,pYlo,pXhi,pYhi, pYpart, pCh,pChX,pChTY,pChTX)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
int nGrids; /* I number of grids */
|
||
double *pXlo; /* O pointer to X position of lower left corner of
|
||
first grid, as fraction of window width */
|
||
double *pYlo; /* O pointer to Y position of lower left corner of
|
||
first grid, as fraction of window height */
|
||
double *pXhi; /* O pointer to X position of upper right corner of
|
||
first grid, as fraction of window width */
|
||
double *pYhi; /* O pointer to Y position of upper right corner of
|
||
first grid, as fraction of window height */
|
||
double *pYpart; /* O pointer to fraction of window height occupied
|
||
by a single grid (all grids are equal) */
|
||
double *pCh; /* O pointer to character height, as fraction
|
||
of window height */
|
||
double *pChX; /* O pointer to character height for rotated text,
|
||
as fraction of window width */
|
||
double *pChTY; /* O pointer to title character height, as fraction
|
||
of window height */
|
||
double *pChTX; /* O pointer to title character height for rotated
|
||
text, as fraction of window width */
|
||
{
|
||
PPR_WIN *pWin; /* pointer to plot window structure */
|
||
double xlo, ylo, xhi, yhi, yPart, charHtTY, charHtTX, charHt, charHtX;
|
||
PPR_AREA *pArea;
|
||
TS_STAMP now;
|
||
char nowText[32];
|
||
|
||
pWin = pMstr->pWin;
|
||
xlo = 0.;
|
||
xhi = .98;
|
||
ylo = 0.;
|
||
yhi = .98;
|
||
charHtTY = .012;
|
||
charHtTX = pprYFracToXFrac(pWin, charHtTY);
|
||
/*-----------------------------------------------------------------------------
|
||
* initialize a plot area covering the whole window, with diagonal corners
|
||
* of 0,0 1,1 for plotting the titles
|
||
*
|
||
* for PostScript, plot current date and time
|
||
* plot the titles which aren't empty
|
||
*----------------------------------------------------------------------------*/
|
||
pArea = pprAreaOpen(pWin, 0.,0., 1.,1., 0.,0., 1.,1., 1, 1, 0.);
|
||
assertAlways(pArea != NULL);
|
||
if (pMstr->winType == PPR_WIN_POSTSCRIPT) {
|
||
(void)tsLocalTime(&now);
|
||
(void)tsStampToText(&now, TS_TEXT_MONDDYYYY, nowText);
|
||
pprText(pArea, .98, .995, nowText, PPR_TXT_RJ, .008, 0.);
|
||
}
|
||
if (strlen(pMstr->title) > 0) {
|
||
yhi = 1. - charHtTY;
|
||
pprText(pArea, .5, yhi, pMstr->title, PPR_TXT_CEN, charHtTY, 0.);
|
||
yhi -= 2. * charHtTY;
|
||
}
|
||
if (strlen(pMstr->lTitle) > 0) {
|
||
xlo = 2. * charHtTX;
|
||
pprText(pArea, xlo, .5, pMstr->lTitle, PPR_TXT_CEN, charHtTX, 90.);
|
||
xlo += 2. * charHtTX;
|
||
}
|
||
if (strlen(pMstr->bTitle) > 0) {
|
||
ylo = 2. * charHtTY;
|
||
pprText(pArea, .5, ylo, pMstr->bTitle, PPR_TXT_CEN, charHtTY, 0.);
|
||
ylo += 2. * charHtTY;
|
||
}
|
||
if (strlen(pMstr->rTitle) > 0) {
|
||
xhi = 1. - 2. * charHtTX;
|
||
pprText(pArea, xhi, .5, pMstr->rTitle, PPR_TXT_CEN, charHtTX, 90.);
|
||
xhi -= 2. * charHtTX;
|
||
}
|
||
pprAreaClose(pArea);
|
||
|
||
ylo += 4. * charHtTY; /* allow for x axis label and annotation */
|
||
|
||
yPart = (yhi - ylo)/(double)nGrids;
|
||
yhi = yPart + ylo;
|
||
charHt = PprDfltCharHt(ylo, yhi);
|
||
charHtX = pprYFracToXFrac(pWin, charHt);
|
||
|
||
*pXlo = xlo;
|
||
*pXhi = xhi;
|
||
*pYlo = ylo;
|
||
*pYhi = yhi;
|
||
*pYpart = yPart;
|
||
*pCh = charHt;
|
||
*pChX = charHtX;
|
||
*pChTY = charHtTY;
|
||
*pChTX = charHtTX;
|
||
}
|
||
|
||
/*-----------------------------------------------------------------------------
|
||
* structure for annotating time axis
|
||
*----------------------------------------------------------------------------*/
|
||
static struct {
|
||
unsigned long threshold; /* seconds for start of partition */
|
||
unsigned long modForEnds; /* rounding interval for axis ends */
|
||
short firstForEnds; /* index in mm/dd/yy hh:mm:ss.msec */
|
||
short nCharForEnds; /* # char from mm/dd/... for end label */
|
||
unsigned long modForTicks; /* rounding interval for axis tick marks */
|
||
short nSubInt; /* number of subintervals */
|
||
short firstForTicks; /* index in mm/dd/yy hh:mm:ss.msec */
|
||
short nCharForTicks; /* # char from mm/dd/... for tick label */
|
||
} timeCal[]={
|
||
7*86400+1, 86400, 0, 5, 86400, 24, 0, 5, /* more than 7 days */
|
||
43201, 86400, 0, 5, 43200, 12, 9, 5, /* more than 12 hours */
|
||
3601, 3600, 9, 5, 3600, 6, 9, 5, /* more than 1 hour */
|
||
601, 600, 9, 5, 600, 10, 9, 5, /* more than 10 minutes */
|
||
61, 60, 12, 5, 60, 6, 12, 5, /* more than 60 seconds */
|
||
11, 10, 12, 5, 10, 10, 12, 5, /* more than 10 seconds */
|
||
0, 1, 15, 6, 1, 0, 15, 6 /* <= 10 seconds */
|
||
};
|
||
/*+/internal******************************************************************
|
||
* NAME sydPlot_setupTime - handle time axis
|
||
*
|
||
*-*/
|
||
sydPlot_setupTime(pMstr, pAnnot, annot)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
char *pAnnot[20], annot[20][28];
|
||
{
|
||
SYD_SPEC *pSspec = pMstr->pSspec;
|
||
unsigned long xminUL, xmaxUL, elapsedUL, xTickDeltaUL;
|
||
TS_STAMP stamp, refStamp, xminTs, xmaxTs, elapsedTs;
|
||
char xminText[28], xmaxText[28], stampText[28];
|
||
int xNint;
|
||
double xtemp, xdelta, xmin, xmax, ymin, ymax;
|
||
int i, calNum;
|
||
/*-----------------------------------------------------------------------------
|
||
* get start and end times (as set by sydPlotInit) referenced to the
|
||
* restrictRefTs. Round them to something `sane' based on the total
|
||
* time range, then build the table of annotation labels. The rounding
|
||
* is based on local time, rather than UTC.
|
||
*----------------------------------------------------------------------------*/
|
||
if (pSspec->restrictRefTs.secPastEpoch > 0) {
|
||
tsAddDouble(&xminTs, &pSspec->restrictRefTs, pMstr->originVal);
|
||
xminTs.nsec = 0;
|
||
tsAddDouble(&xmaxTs, &pSspec->restrictRefTs, pMstr->extentVal);
|
||
if (xmaxTs.nsec > 0) {
|
||
xmaxTs.secPastEpoch++;
|
||
xmaxTs.nsec = 0;
|
||
}
|
||
TsDiffAsStamp(&elapsedTs, &xmaxTs, &xminTs);
|
||
for (calNum=0; ; calNum++) {
|
||
if (timeCal[calNum].threshold <= elapsedTs.secPastEpoch)
|
||
break;
|
||
}
|
||
tsRoundDownLocal(&xminTs, timeCal[calNum].modForEnds);
|
||
tsRoundUpLocal(&xmaxTs, timeCal[calNum].modForEnds);
|
||
|
||
if (xminTs.secPastEpoch == xmaxTs.secPastEpoch)
|
||
xmaxTs.secPastEpoch += timeCal[calNum].modForEnds;
|
||
refStamp = xminTs;
|
||
|
||
xminUL = xminTs.secPastEpoch;
|
||
xmaxUL = xmaxTs.secPastEpoch;
|
||
elapsedUL = xmaxUL - xminUL;
|
||
xTickDeltaUL = timeCal[calNum].modForTicks;
|
||
xNint = (xmaxUL - xminUL) / xTickDeltaUL;
|
||
if (xNint >= 20) {
|
||
xNint = 5;
|
||
xTickDeltaUL = elapsedUL / xNint;
|
||
}
|
||
pMstr->nInt = xNint;
|
||
pMstr->nSubInt = timeCal[calNum].nSubInt;
|
||
for (i=0; i<=xNint; i++) {
|
||
tsStampToText(&refStamp, TS_TEXT_MMDDYY, stampText);
|
||
if (i == 0 || i == xNint) {
|
||
strcpy(annot[i], &stampText[timeCal[calNum].firstForEnds]);
|
||
annot[i][timeCal[calNum].nCharForEnds] = '\0';
|
||
if (i == 0)
|
||
TsDiffAsDouble(&xmin, &refStamp, &pSspec->restrictRefTs);
|
||
else
|
||
TsDiffAsDouble(&xmax, &refStamp, &pSspec->restrictRefTs);
|
||
}
|
||
else {
|
||
strcpy(annot[i], &stampText[timeCal[calNum].firstForTicks]);
|
||
annot[i][timeCal[calNum].nCharForTicks] = '\0';
|
||
}
|
||
pAnnot[i] = annot[i];
|
||
refStamp.secPastEpoch += xTickDeltaUL;
|
||
}
|
||
|
||
(void)tsStampToText(&xminTs, TS_TEXT_MMDDYY, xminText);
|
||
(void)tsStampToText(&xmaxTs, TS_TEXT_MMDDYY, xmaxText);
|
||
(void)sprintf(pMstr->label, "%s to %s", xminText, xmaxText);
|
||
}
|
||
else {
|
||
xmin = pMstr->originVal;
|
||
xmax = pMstr->extentVal;
|
||
if (xmin == xmax)
|
||
xmax += 10.;
|
||
pprAutoEnds(xmin, xmax, &xmin, &xmax);
|
||
pprAutoInterval(xmin, xmax, &xNint);
|
||
if (xNint > 19)
|
||
xNint = 19;
|
||
xdelta = (xmax - xmin) / xNint;
|
||
for (i=0, xtemp=xmin; i<=xNint; i++,xtemp+=xdelta) {
|
||
if (i == xNint)
|
||
xtemp=xmax;
|
||
pprCvtDblToTxt(annot[i], 8, xtemp, 2);
|
||
pAnnot[i] = annot[i];
|
||
}
|
||
(void)sprintf(pMstr->label, "delta seconds");
|
||
}
|
||
pMstr->originVal = xmin;
|
||
pMstr->extentVal = xmax;
|
||
pMstr->nInt = xNint;
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlot_SmithPlot - handle Smith Chart plots
|
||
*
|
||
* DESCRIPTION
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* BUGS
|
||
* o text
|
||
*
|
||
* SEE ALSO
|
||
* sydPlot_SmithGrid, sydPlot_SmithSamples
|
||
*
|
||
* NOTES
|
||
* 1. This routine isn't intended to be called directly.
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlot_SmithPlot(pMstr)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
{
|
||
SYD_SPEC *pSspec;
|
||
|
||
assert(pMstr != NULL);
|
||
pSspec = pMstr->pSspec;
|
||
assert(pSspec != NULL);
|
||
|
||
sydPlot_SmithGrid(pMstr);
|
||
if (pSspec->useStats == 0) {
|
||
sydPlot_SmithSamples(pMstr,
|
||
pSspec->restrictFirstData, pSspec->restrictLastData, 0);
|
||
}
|
||
else
|
||
sydPlot_SmithStats(pMstr, 0, pSspec->statCount-1);
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlot_SmithGrid - draw a Smith chart overlay
|
||
*
|
||
* DESCRIPTION
|
||
* Draws a Smith chart overlay, to be used in plotting X vs Y data.
|
||
* Three overlays are available, with axis type controlling which is
|
||
* drawn:
|
||
*
|
||
* SYD_PLAX_SMITH_IMP results in an impedance overlay, with
|
||
* circles tangent on the right. If SYD_PLATTR_FG1 has been
|
||
* used to set an alternate foreground pixel value, then, on
|
||
* color displays, the overlay is drawn using that pixel value.
|
||
* SYD_PLAX_SMITH_ADM results in an admittance overlay, with
|
||
* circles tangent on the left. If SYD_PLATTR_FG2 has been
|
||
* used to set an alternate foreground pixel value, then, on
|
||
* color displays, the overlay is drawn using that pixel value.
|
||
* SYD_PLAX_SMITH_IMM results in an "immittance" overlay, which is
|
||
* a combination of the impedance overlay on top of the
|
||
* admittance overlay. On color displays when alternate
|
||
* foreground pixel values have been specified, the overlays
|
||
* are drawn as described above. On monochrome displays, or
|
||
* when no alternate foreground pixel values are specified,
|
||
* the impedance overlay is drawn with a solid line and the
|
||
* admittance overlay is drawn with a dashed line.
|
||
*
|
||
* On color displays, if no alternate foreground pixel values have been
|
||
* set, then the overlays are drawn using the color of the plot window.
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* BUGS
|
||
* o channel names aren't displayed
|
||
* o colors are done only under X11
|
||
*
|
||
* NOTES
|
||
* 1. This routine isn't intended to be called directly.
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlot_SmithGrid(pMstr)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
{
|
||
PPR_WIN *pWin;
|
||
PPR_AREA *pArea;
|
||
double incr=5.; /* use 5 degree increments */
|
||
double x, y, rad;
|
||
int r;
|
||
static char *xTxt[]={"5","2","1","0.5","0.2","0"};
|
||
double xlo, ylo, xhi, yhi;
|
||
double xmin, ymin, xmax, ymax;
|
||
double yPart;
|
||
double charHt, charHtX, charHtTY, charHtTX;
|
||
SYD_PL_SLAVE *pSlave; /* pointer to individual slave struct */
|
||
SYD_PL_SLAVE *pSlaveX; /* pointer to X axis slave struct */
|
||
|
||
pWin = pMstr->pWin;
|
||
|
||
sydPlot_setup(pMstr, 1, &xlo, &ylo, &xhi, &yhi, &yPart,
|
||
&charHt, &charHtX, &charHtTY, &charHtTX);
|
||
|
||
xlo += 3. * charHtX;
|
||
ylo += 2. * charHt;
|
||
xhi -= charHt;
|
||
yhi -= 2. * charHt;
|
||
|
||
pSlaveX = pMstr->pHead;
|
||
while (1) {
|
||
if (pSlaveX->xChan)
|
||
break;
|
||
pSlaveX = pSlaveX->pNext;
|
||
if (pSlaveX == NULL) {
|
||
pSlaveX = pMstr->pHead;
|
||
break;
|
||
}
|
||
}
|
||
if (pSlaveX == pMstr->pHead)
|
||
pSlave = pSlaveX->pNext;
|
||
else
|
||
pSlave = pMstr->pHead;
|
||
|
||
pArea = pprAreaOpen(pWin, xlo,ylo, xhi,yhi, 0.,0., 1.,1., 1, 1, 0.);
|
||
|
||
if (pMstr->plotAxis == SYD_PLAX_SMITH_ADM ||
|
||
pMstr->plotAxis == SYD_PLAX_SMITH_IMM) {
|
||
/*-----------------------------------------------------------------------------
|
||
* admittance overlay, with circles tangent at x=0,y=.5
|
||
*
|
||
* For immitance plots, with this as a secondary overlay, a dashed
|
||
* line pattern is used if the screen is monochrome. The outer
|
||
* circle isn't drawn and annotations aren't drawn.
|
||
*----------------------------------------------------------------------------*/
|
||
#ifdef XWINDOWS
|
||
if (pMstr->noColor == 0 && pMstr->altPixel2 != 0)
|
||
pprAreaSetAttr(pArea, PPR_ATTR_FG, 0, &pMstr->altPixel2);
|
||
else {
|
||
#else
|
||
if (1) {
|
||
#endif
|
||
if (pMstr->plotAxis == SYD_PLAX_SMITH_IMM || pMstr->noColor == 0)
|
||
pprAreaSetAttr(pArea, PPR_ATTR_KEYNUM, 1, NULL);
|
||
}
|
||
if (pMstr->plotAxis == SYD_PLAX_SMITH_ADM)
|
||
pprLineSegD(pArea, 0.,.5, 1.,.5);
|
||
y = .5;
|
||
for (r=6; r>0; r--) {
|
||
rad = (double)r / 12.;
|
||
x = rad;
|
||
if (r != 6 || pMstr->plotAxis == SYD_PLAX_SMITH_ADM)
|
||
pprArcD(pArea, x, y, rad, 0., 360., incr);
|
||
if (pMstr->plotAxis == SYD_PLAX_SMITH_ADM)
|
||
pprText(pArea, x+rad+.015, y, xTxt[r-1], PPR_TXT_LJ, 0., 0.);
|
||
}
|
||
x = 0.;
|
||
rad = .25, y = .5 + rad;
|
||
pprArcD(pArea, x, y, rad, 270., 37., incr);
|
||
if (pMstr->plotAxis == SYD_PLAX_SMITH_ADM)
|
||
pprText(pArea, .19, .92, "2", PPR_TXT_RJ, 0., 0.);
|
||
y = .5 - rad;
|
||
pprArcD(pArea, x, y, rad, 323., 90., incr);
|
||
if (pMstr->plotAxis == SYD_PLAX_SMITH_ADM)
|
||
pprText(pArea, .19, .08, "2", PPR_TXT_RJ, 0., 0.);
|
||
rad = .5, y = .5 + rad;
|
||
pprArcD(pArea, x, y, rad, 270., 0., incr);
|
||
if (pMstr->plotAxis == SYD_PLAX_SMITH_ADM)
|
||
pprText(pArea, .5, 1.02, "1", PPR_TXT_CEN, 0., 0.);
|
||
y = .5 - rad;
|
||
pprArcD(pArea, x, y, rad, 0., 90., incr);
|
||
if (pMstr->plotAxis == SYD_PLAX_SMITH_ADM)
|
||
pprText(pArea, .5, -.02, "1", PPR_TXT_CEN, 0., 0.);
|
||
rad = 1., y = .5 + rad;
|
||
pprArcD(pArea, x, y, rad, 270., 323., incr);
|
||
if (pMstr->plotAxis == SYD_PLAX_SMITH_ADM)
|
||
pprText(pArea, .81, .92, "0.5", PPR_TXT_LJ, 0., 0.);
|
||
y = .5 - rad;
|
||
pprArcD(pArea, x, y, rad, 37., 90., incr);
|
||
if (pMstr->plotAxis == SYD_PLAX_SMITH_ADM)
|
||
pprText(pArea, .81, .08, "0.5", PPR_TXT_LJ, 0., 0.);
|
||
}
|
||
if (pMstr->plotAxis == SYD_PLAX_SMITH_IMP ||
|
||
pMstr->plotAxis == SYD_PLAX_SMITH_IMM) {
|
||
/*-----------------------------------------------------------------------------
|
||
* impedance overlay, with circles tangent at x=1,y=.5
|
||
*----------------------------------------------------------------------------*/
|
||
#ifdef XWINDOWS
|
||
if (pMstr->noColor == 0 && pMstr->altPixel1 != 0)
|
||
pprAreaSetAttr(pArea, PPR_ATTR_FG, 0, &pMstr->altPixel1);
|
||
else {
|
||
#else
|
||
if (1) {
|
||
#endif
|
||
pprAreaSetAttr(pArea, PPR_ATTR_KEYNUM, 0, NULL);
|
||
}
|
||
pprLineSegD(pArea, 0.,.5, 1.,.5);
|
||
y = .5;
|
||
for (r=6; r>0; r--) {
|
||
rad = (double)r / 12.;
|
||
x = 1. - rad;
|
||
pprArcD(pArea, x, y, rad, 0., 360., incr);
|
||
pprText(pArea, x-rad-.015, y, xTxt[r-1], PPR_TXT_RJ, 0., 0.);
|
||
}
|
||
x = 1.;
|
||
rad = .25, y = .5 + rad;
|
||
pprArcD(pArea, x, y, rad, 143., 270., incr);
|
||
pprText(pArea, .81, .92, "2", PPR_TXT_LJ, 0., 0.);
|
||
y = .5 - rad;
|
||
pprArcD(pArea, x, y, rad, 90., 217., incr);
|
||
pprText(pArea, .81, .08, "2", PPR_TXT_LJ, 0., 0.);
|
||
rad = .5, y = .5 + rad;
|
||
pprArcD(pArea, x, y, rad, 180., 270., incr);
|
||
pprText(pArea, .5, 1.02, "1", PPR_TXT_CEN, 0., 0.);
|
||
y = .5 - rad;
|
||
pprArcD(pArea, x, y, rad, 90., 180., incr);
|
||
pprText(pArea, .5, -.02, "1", PPR_TXT_CEN, 0., 0.);
|
||
rad = 1., y = .5 + rad;
|
||
pprArcD(pArea, x, y, rad, 217., 270., incr);
|
||
pprText(pArea, .19, .92, "0.5", PPR_TXT_RJ, 0., 0.);
|
||
y = .5 - rad;
|
||
pprArcD(pArea, x, y, rad, 90., 143., incr);
|
||
pprText(pArea, .19, .08, "0.5", PPR_TXT_RJ, 0., 0.);
|
||
}
|
||
pprAreaClose(pArea);
|
||
|
||
pSlaveX->pArea = NULL;
|
||
xmin = pSlaveX->originVal;
|
||
xmax = pSlaveX->extentVal;
|
||
while (pSlave != NULL) {
|
||
ymin = pSlave->originVal;
|
||
ymax = pSlave->extentVal;
|
||
if (pSlave->pArea != NULL)
|
||
pprAreaClose(pSlave->pArea);
|
||
pArea = pSlave->pArea = pprAreaOpen(pWin,
|
||
xlo,ylo, xhi,yhi, xmin, ymin, xmax, ymax, 1, 1, 0.);
|
||
assertAlways(pArea != NULL);
|
||
pSlave->xFracLeft = xlo + 12. * charHtX;
|
||
pSlave->xFracRight = xhi;
|
||
pSlave->yFracBot = ylo + 6. * charHt;
|
||
pSlave->yFracTop = yhi;
|
||
pSlave->annotXFL = xlo;
|
||
pSlave->annotXFR = pSlave->xFracLeft;
|
||
pSlave->annotYFB = pSlave->yFracBot;
|
||
pSlave->annotYFT = yhi;
|
||
if (pSlave->fg != 0 && pMstr->noColor == 0)
|
||
pprAreaSetAttr(pSlave->pArea, PPR_ATTR_FG, 0, &pSlave->fg);
|
||
pSlave = pSlave->pNext;
|
||
if (pSlave == pSlaveX)
|
||
pSlave = pSlave->pNext;
|
||
}
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlot_SmithSamples - plot one or more samples for a Smith Chart plot
|
||
*
|
||
* DESCRIPTION
|
||
* the first channel in the plot spec is used for the X axis
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* BUGS
|
||
* o this isn't a true Smith chart plot--the caller must have transformed
|
||
* the data into simple X vs Y data
|
||
*
|
||
* SEE ALSO
|
||
*
|
||
* NOTES
|
||
* 1. This routine isn't intended to be called directly.
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlot_SmithSamples(pMstr, begin, end, incr)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
int begin; /* I number of begin sample to plot */
|
||
int end; /* I number of end sample to plot */
|
||
int incr; /* I 0,1 for batch,incremental plotting */
|
||
{
|
||
sydPlot_XYSamples(pMstr, begin, end, incr);
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlot_SmithStats - plot one or more snapshots for a Smith Chart plot
|
||
*
|
||
* DESCRIPTION
|
||
* the first channel in the plot spec is used for the X axis
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* BUGS
|
||
* o this isn't a true Smith chart plot--the caller must have transformed
|
||
* the data into simple X vs Y data
|
||
*
|
||
* SEE ALSO
|
||
*
|
||
* NOTES
|
||
* 1. This routine isn't intended to be called directly.
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlot_SmithStats(pMstr, begin, end)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
int begin; /* I number of begin snapshot to plot */
|
||
int end; /* I number of end snapshot to plot */
|
||
{
|
||
sydPlot_XYStats(pMstr, begin, end);
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlot_StripYPlot - handle strip chart, Y plots
|
||
*
|
||
* DESCRIPTION
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* BUGS
|
||
* o text
|
||
*
|
||
* SEE ALSO
|
||
*
|
||
* NOTES
|
||
* 1. This routine isn't intended to be called directly.
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlot_StripYPlot(pMstr)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
{
|
||
SYD_SPEC *pSspec;
|
||
|
||
assert(pMstr != NULL);
|
||
pSspec = pMstr->pSspec;
|
||
assert(pSspec != NULL);
|
||
|
||
sydPlot_StripYGrid(pMstr);
|
||
sydPlot_StripYSamples(pMstr,
|
||
pSspec->restrictFirstData, pSspec->restrictLastData, 0);
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlot_StripYGrid - draw a grid for a strip chart, Y plot
|
||
*
|
||
* DESCRIPTION
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* SEE ALSO
|
||
*
|
||
* NOTES
|
||
* 1. This routine isn't intended to be called directly.
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlot_StripYGrid(pMstr)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
{
|
||
PPR_WIN *pWin; /* pointer to plot window structure */
|
||
SYD_PL_SLAVE *pSlave; /* pointer to individual slave struct */
|
||
double xlo, ylo, xhi, yhi;
|
||
double yPart;
|
||
PPR_AREA *pArea;
|
||
double xmin, xmax, ymin, ymax;
|
||
char **ppAnnotVal, *pAnnotVal[20], annotVal[20][28];
|
||
double charHt, charHtX, charHtTY, charHtTX;
|
||
SYD_SPEC *pSspec = pMstr->pSspec;
|
||
SYD_CHAN *pSChan;
|
||
int thick=3;
|
||
int nGrids;
|
||
int i;
|
||
|
||
pWin = pMstr->pWin;
|
||
|
||
nGrids = pMstr->nSlaves;
|
||
sydPlot_setup(pMstr, nGrids, &xlo, &ylo, &xhi, &yhi, &yPart,
|
||
&charHt, &charHtX, &charHtTY, &charHtTX);
|
||
if (pMstr->pSspec->sampleCount > 0) {
|
||
xmax = pMstr->pSspec->pDeltaSec[pMstr->pSspec->lastData];
|
||
xmin = xmax - pMstr->stripIncr * pMstr->pSspec->reqCount;
|
||
}
|
||
else if (pMstr->winType == PPR_WIN_SCREEN) {
|
||
xmin = -1. * (pMstr->stripIncr * pMstr->pSspec->reqCount);
|
||
xmax = 0.;
|
||
}
|
||
else {
|
||
xmin = 0.;
|
||
xmax = pMstr->stripIncr * pMstr->pSspec->reqCount;
|
||
}
|
||
|
||
pSlave = pMstr->pHead;
|
||
while (pSlave != NULL) {
|
||
/*-----------------------------------------------------------------------------
|
||
* for each channel, initialize a plot area.
|
||
*
|
||
* plot a perimeter with grid lines
|
||
*----------------------------------------------------------------------------*/
|
||
pSChan = pSlave->pSChan;
|
||
ymin = pSlave->originVal;
|
||
ymax = pSlave->extentVal;
|
||
if (pSlave->ppAnnot == NULL) {
|
||
sydAnnotVal(pSlave, pAnnotVal, annotVal);
|
||
ppAnnotVal = pAnnotVal;
|
||
}
|
||
else
|
||
ppAnnotVal = pSlave->ppAnnot;
|
||
if (pSlave->pArea != NULL)
|
||
pprAreaClose(pSlave->pArea);
|
||
pArea = pSlave->pArea = pprAreaOpen(pWin,
|
||
xlo+12.*charHtX, ylo+2.*charHt, xhi, yhi,
|
||
xmin, ymin, xmax, ymax, 1, pSlave->nInt, charHt);
|
||
assertAlways(pArea != NULL);
|
||
pSlave->xFracLeft = xlo + 12. * charHtX;
|
||
pSlave->xFracRight = xhi;
|
||
pSlave->yFracBot = ylo + 2.*charHt;
|
||
pSlave->yFracTop = yhi;
|
||
pSlave->annotXFL = xlo;
|
||
pSlave->annotXFR = pSlave->xFracLeft;
|
||
pSlave->annotYFB = pSlave->yFracBot;
|
||
pSlave->annotYFT = yhi;
|
||
if (pSlave->fg != 0 && pMstr->noColor == 0)
|
||
pprAreaSetAttr(pSlave->pArea, PPR_ATTR_FG, 0, &pSlave->fg);
|
||
else if (pMstr->linePlot) {
|
||
if (dbr_type_is_ENUM(pSChan->dbrType))
|
||
pprAreaSetAttr(pArea, PPR_ATTR_LINE_THICK, thick, NULL);
|
||
}
|
||
pprAnnotY(pArea, 0, ymin, ymax, pSlave->nInt, 0,
|
||
pSlave->pSChan->label, ppAnnotVal, 0.);
|
||
if (pSlave == pMstr->pHead) {
|
||
pArea->charHt = charHtTY * pWin->height;
|
||
pprAnnotX(pArea, 0, xmin, xmax, 1, 0, "delta seconds", NULL, 0.);
|
||
pArea->charHt = charHt * pWin->height;
|
||
}
|
||
pprAreaSetAttr(pSlave->pArea, PPR_ATTR_STRIP, 1, NULL);
|
||
pprGrid(pArea);
|
||
ylo += yPart;
|
||
yhi += yPart;
|
||
pSlave = pSlave->pNext;
|
||
}
|
||
pSlave = pMstr->pHead;
|
||
pMstr->originFrac = pSlave->xFracLeft;
|
||
pMstr->extentFrac = pSlave->xFracRight;
|
||
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlot_StripYSamples - plot samples for a strip chart, Y plot
|
||
*
|
||
* DESCRIPTION
|
||
*
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* BUGS
|
||
* o text
|
||
*
|
||
* SEE ALSO
|
||
*
|
||
* NOTES
|
||
* 1. This routine isn't intended to be called directly.
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlot_StripYSamples(pMstr, begin, end, incr)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
int begin; /* I number of begin sample to plot */
|
||
int end; /* I number of end sample to plot */
|
||
int incr; /* I 0,1 for batch,incremental plotting */
|
||
{
|
||
PPR_WIN *pWin; /* pointer to plot window structure */
|
||
SYD_PL_SLAVE *pSlave; /* pointer to individual slave struct */
|
||
PPR_AREA *pArea;
|
||
int i, j;
|
||
SYD_SPEC *pSspec;
|
||
SYD_CHAN *pSChan;
|
||
double oldX, oldY, newX, newY;
|
||
int skip;
|
||
int showStat; /* 1 to show status code on plot */
|
||
int pointPlot; /* 1 for point plot */
|
||
int linePlot; /* 1 to connect points with lines */
|
||
int markPlot; /* 1 to draw marks at points */
|
||
int markNum; /* number of mark to use */
|
||
int nEl; /* number of array elements */
|
||
int first; /* ==1 if this is the first sample */
|
||
float shift; /* amount to shift the strip chart(s) */
|
||
int pixEnd; /* pixel coordinate for end time */
|
||
|
||
assert(pMstr != NULL);
|
||
pSspec = pMstr->pSspec;
|
||
assert(pSspec != NULL);
|
||
pWin = pMstr->pWin;
|
||
|
||
linePlot = pMstr->linePlot;
|
||
pointPlot = pMstr->pointPlot;
|
||
markPlot = pMstr->markPlot;
|
||
showStat = pMstr->showStat;
|
||
|
||
pArea = pMstr->pHead->pArea;
|
||
pixEnd = pArea->xPixRight +
|
||
.5 + (pSspec->pDeltaSec[end] - pArea->xRight) * pArea->xScale;
|
||
if (pixEnd >= pArea->xPixRight) {
|
||
shift = pSspec->pDeltaSec[end] - pMstr->pHead->pArea->xRight;
|
||
if (shift < pMstr->stripIncr)
|
||
shift = pMstr->stripIncr;
|
||
}
|
||
else
|
||
shift = 0.;
|
||
pSlave = pMstr->pHead;
|
||
while (pSlave != NULL) {
|
||
pArea = pSlave->pArea;
|
||
pSChan = pSlave->pSChan;
|
||
markNum = pSlave->markNum;
|
||
|
||
if (pSChan->pData == NULL || pSChan->dataChan == 0)
|
||
; /* no action if never connected or not data channel */
|
||
else {
|
||
if (shift > 0.) {
|
||
pprAreaShiftLeft(pArea, shift);
|
||
if (pArea == pMstr->pHead->pArea) {
|
||
pMstr->originVal = pArea->xLeft;
|
||
pMstr->extentVal = pArea->xRight;
|
||
}
|
||
}
|
||
|
||
nEl = pSChan->elCount;
|
||
|
||
i = begin;
|
||
if (!incr)
|
||
first = 1;
|
||
else {
|
||
first = pSlave->first;
|
||
oldX = pSlave->oldX;
|
||
oldY = pSlave->oldY;
|
||
skip = pSlave->skip;
|
||
}
|
||
while (i >= 0) {
|
||
int restart, restart1;
|
||
restart = restart1 = 0;
|
||
if (pSChan->pFlags[i].restart) {
|
||
if (!pSChan->pFlags[i].snapstart)
|
||
restart = 1;
|
||
else if (!pSChan->pFlags[i].snapend)
|
||
restart = 1;
|
||
}
|
||
if (i != end && pSChan->pFlags[i+1].restart) {
|
||
if (!pSChan->pFlags[i+1].snapstart)
|
||
restart1 = 1;
|
||
else if (!pSChan->pFlags[i+1].snapend)
|
||
restart1 = 1;
|
||
}
|
||
if (pSChan->pFlags[i].missing)
|
||
skip = 1;
|
||
else if (first || skip || restart) {
|
||
oldX = pSspec->pDeltaSec[i] -
|
||
pMstr->pSspec->restrictDeltaSecSubtract;
|
||
if (oldX >= pArea->xLeft) {
|
||
FetchIthValInto(pSChan, oldY)
|
||
if (markPlot)
|
||
pprMarkD(pArea, oldX, oldY, markNum);
|
||
if (showStat && pSChan->pDataCodeR[i] != ' ') {
|
||
pprChar(pArea, oldX, oldY,
|
||
pSChan->pDataCodeR[i], 0., 0.);
|
||
}
|
||
else if (pointPlot)
|
||
pprPointD(pArea, oldX, oldY);
|
||
skip = 0;
|
||
}
|
||
}
|
||
else if (pSChan->pFlags[i].filled && restart1 == 0 && i != end)
|
||
; /* no action */
|
||
else {
|
||
newX = pSspec->pDeltaSec[i] -
|
||
pMstr->pSspec->restrictDeltaSecSubtract;
|
||
if (linePlot && dbr_type_is_ENUM(pSChan->dbrType)) {
|
||
if (oldX >= pArea->xLeft)
|
||
pprLineSegD(pArea, oldX, oldY, newX, oldY);
|
||
oldX = newX;
|
||
}
|
||
FetchIthValInto(pSChan, newY)
|
||
if (oldX >= pArea->xLeft) {
|
||
if (linePlot)
|
||
pprLineSegD(pArea, oldX, oldY, newX, newY);
|
||
if (markPlot)
|
||
pprMarkD(pArea, newX, newY, markNum);
|
||
if (showStat && pSChan->pDataCodeR[i] != ' ') {
|
||
pprChar(pArea, newX, newY,
|
||
pSChan->pDataCodeR[i], 0., 0.);
|
||
}
|
||
else if (pointPlot)
|
||
pprPointD(pArea, newX, newY);
|
||
}
|
||
oldX = newX;
|
||
oldY = newY;
|
||
}
|
||
if (i == end)
|
||
i = -1;
|
||
else if (++i >= pSspec->dataDim)
|
||
i = 0;
|
||
first = 0;
|
||
}
|
||
}
|
||
pSlave->first = first;
|
||
pSlave->oldX = oldX;
|
||
pSlave->oldY = oldY;
|
||
pSlave->skip = skip;
|
||
pSlave = pSlave->pNext;
|
||
}
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlot_StripYYPlot - handle strip chart, multiple Y plots
|
||
*
|
||
* DESCRIPTION
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* BUGS
|
||
* o labeling of x axis is un-esthetic. It should be time based, with
|
||
* some intelligent adaptation, based on time interval for X
|
||
*
|
||
* SEE ALSO
|
||
*
|
||
* NOTES
|
||
* 1. This routine isn't intended to be called directly.
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlot_StripYYPlot(pMstr)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
{
|
||
SYD_SPEC *pSspec;
|
||
|
||
assert(pMstr != NULL);
|
||
pSspec = pMstr->pSspec;
|
||
assert(pSspec != NULL);
|
||
|
||
sydPlot_StripYYGrid(pMstr);
|
||
sydPlot_StripYSamples(pMstr,
|
||
pSspec->restrictFirstData, pSspec->restrictLastData, 0);
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlot_StripYYGrid - draw a grid for a strip chart, multiple Y plot
|
||
*
|
||
* DESCRIPTION
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* BUGS
|
||
* o text
|
||
*
|
||
* SEE ALSO
|
||
*
|
||
* NOTES
|
||
* 1. This routine isn't intended to be called directly.
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlot_StripYYGrid(pMstr)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
{
|
||
PPR_WIN *pWin; /* pointer to plot window structure */
|
||
SYD_PL_SLAVE *pSlave; /* pointer to individual slave struct */
|
||
double xlo, ylo, xhi, yhi;
|
||
double yPart;
|
||
PPR_AREA *pArea;
|
||
double xmin, xmax, ymin, ymax;
|
||
double charHt, charHtX, charHtTY, charHtTX;
|
||
char **ppAnnotVal, *pAnnotVal[20], annotVal[20][28];
|
||
SYD_SPEC *pSspec = pMstr->pSspec;
|
||
SYD_CHAN *pSChan;
|
||
int thick=3;
|
||
int nGrids;
|
||
int i, calNum;
|
||
int offsetAnnotY=0;
|
||
int drawAxis=0;
|
||
|
||
pWin = pMstr->pWin;
|
||
|
||
nGrids = 1;
|
||
sydPlot_setup(pMstr, nGrids, &xlo, &ylo, &xhi, &yhi, &yPart,
|
||
&charHt, &charHtX, &charHtTY, &charHtTX);
|
||
if (pMstr->pSspec->sampleCount > 0) {
|
||
xmax = pMstr->pSspec->pDeltaSec[pMstr->pSspec->lastData];
|
||
xmin = xmax - pMstr->stripIncr * pMstr->pSspec->reqCount;
|
||
}
|
||
else if (pMstr->winType == PPR_WIN_SCREEN) {
|
||
xmin = -1. * (pMstr->stripIncr * pMstr->pSspec->reqCount);
|
||
xmax = 0.;
|
||
}
|
||
else {
|
||
xmin = 0.;
|
||
xmax = pMstr->stripIncr * pMstr->pSspec->reqCount;
|
||
}
|
||
|
||
xlo += 6. * charHtX * (double)pMstr->nSlaves;
|
||
|
||
pSlave = pMstr->pHead;
|
||
while (pSlave != NULL) {
|
||
/*-----------------------------------------------------------------------------
|
||
* for the first channel:
|
||
* initialize a plot area; its fractional size depends on how many
|
||
* "sub-plots" there are
|
||
* plot a perimeter with grid lines
|
||
* for the other channels:
|
||
* initialize an overlapping plot area
|
||
* set a dashed line pattern (unless this is a mark or point plot)
|
||
* draw a "floating" Y axis
|
||
*----------------------------------------------------------------------------*/
|
||
pSChan = pSlave->pSChan;
|
||
ymin = pSlave->originVal;
|
||
ymax = pSlave->extentVal;
|
||
if (pSlave->ppAnnot == NULL) {
|
||
sydAnnotVal(pSlave, pAnnotVal, annotVal);
|
||
ppAnnotVal = pAnnotVal;
|
||
}
|
||
else
|
||
ppAnnotVal = pSlave->ppAnnot;
|
||
if (pSlave->pArea != NULL)
|
||
pprAreaClose(pSlave->pArea);
|
||
pArea = pSlave->pArea = pprAreaOpen(pWin, xlo, ylo+2.*charHt, xhi, yhi,
|
||
xmin, ymin, xmax, ymax, pMstr->nInt, pSlave->nInt, charHt);
|
||
assertAlways(pArea != NULL);
|
||
pSlave->xFracLeft = xlo;
|
||
pSlave->xFracRight = xhi;
|
||
pSlave->yFracBot = ylo;
|
||
pSlave->yFracTop = yhi;
|
||
if (pSlave->fg != 0 && pMstr->noColor == 0)
|
||
pprAreaSetAttr(pSlave->pArea, PPR_ATTR_FG, 0, &pSlave->fg);
|
||
else if (pMstr->linePlot) {
|
||
if (dbr_type_is_ENUM(pSChan->dbrType))
|
||
pprAreaSetAttr(pArea, PPR_ATTR_LINE_THICK, thick, NULL);
|
||
if (pSlave->lineKey > 1 || pMstr->noColor == 0)
|
||
pprAreaSetAttr(pArea, PPR_ATTR_KEYNUM, pSlave->lineKey, NULL);
|
||
}
|
||
else if (pMstr->noColor == 0)
|
||
pprAreaSetAttr(pArea, PPR_ATTR_COLORNUM, pSlave->lineKey, NULL);
|
||
pprAnnotY(pArea, offsetAnnotY, pSlave->originVal, pSlave->extentVal,
|
||
pSlave->nInt, drawAxis,
|
||
pSlave->pSChan->label, ppAnnotVal, 90.);
|
||
if (drawAxis == 0) {
|
||
if (pSlave == pMstr->pHead) {
|
||
pArea->charHt = charHtTY * pWin->height;
|
||
pprAnnotX(pArea, 0, xmin,xmax,1,0,"delta seconds",NULL,0.);
|
||
pArea->charHt = charHt * pWin->height;
|
||
}
|
||
pprAreaSetAttr(pArea, PPR_ATTR_STRIP, 1, NULL);
|
||
pprGrid(pArea);
|
||
}
|
||
else
|
||
pprAreaSetAttr(pArea, PPR_ATTR_STRIP, 1, pMstr->pHead->pArea);
|
||
if (pMstr->markPlot)
|
||
pprAnnotYMark(pArea, offsetAnnotY, pSlave->markNum);
|
||
offsetAnnotY += 6;
|
||
drawAxis = 1; /* draw an "auxiliary" axis next time */
|
||
pSlave->annotXFL = xlo - offsetAnnotY * charHtX;
|
||
pSlave->annotXFR = pSlave->annotXFL + 6. * charHtX;
|
||
pSlave->annotYFB = ylo;
|
||
pSlave->annotYFT = yhi;
|
||
pSlave = pSlave->pNext;
|
||
}
|
||
pSlave = pMstr->pHead;
|
||
pMstr->originFrac = pSlave->xFracLeft;
|
||
pMstr->extentFrac = pSlave->xFracRight;
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlot_TYPlot - handle time vs Y plots
|
||
*
|
||
* DESCRIPTION
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* BUGS
|
||
* o text
|
||
*
|
||
* SEE ALSO
|
||
*
|
||
* NOTES
|
||
* 1. This routine isn't intended to be called directly.
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlot_TYPlot(pMstr)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
{
|
||
SYD_SPEC *pSspec;
|
||
|
||
assert(pMstr != NULL);
|
||
pSspec = pMstr->pSspec;
|
||
assert(pSspec != NULL);
|
||
|
||
sydPlot_TYGrid(pMstr);
|
||
if (pSspec->useStats == 0) {
|
||
sydPlot_TYSamples(pMstr,
|
||
pSspec->restrictFirstData, pSspec->restrictLastData, 0);
|
||
}
|
||
else
|
||
sydPlot_TYStats(pMstr, 0, pSspec->statCount-1);
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlot_TYGrid - draw a grid for a time vs Y plot
|
||
*
|
||
* DESCRIPTION
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* SEE ALSO
|
||
*
|
||
* NOTES
|
||
* 1. This routine isn't intended to be called directly.
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlot_TYGrid(pMstr)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
{
|
||
PPR_WIN *pWin; /* pointer to plot window structure */
|
||
SYD_PL_SLAVE *pSlave; /* pointer to individual slave struct */
|
||
double xlo, ylo, xhi, yhi;
|
||
double yPart;
|
||
PPR_AREA *pArea;
|
||
double xmin, xmax, ymin, ymax;
|
||
char *pAnnot[20], annot[20][28]; /* annot for time axis */
|
||
char **ppAnnotVal, *pAnnotVal[20], annotVal[20][28];
|
||
double charHt, charHtX, charHtTY, charHtTX;
|
||
SYD_SPEC *pSspec = pMstr->pSspec;
|
||
SYD_CHAN *pSChan;
|
||
int thick=3;
|
||
int nGrids;
|
||
int i;
|
||
|
||
pWin = pMstr->pWin;
|
||
|
||
nGrids = pMstr->nSlaves;
|
||
sydPlot_setup(pMstr, nGrids, &xlo, &ylo, &xhi, &yhi, &yPart,
|
||
&charHt, &charHtX, &charHtTY, &charHtTX);
|
||
sydPlot_setupTime(pMstr, pAnnot, annot);
|
||
xmin = pMstr->originVal;
|
||
xmax = pMstr->extentVal;
|
||
|
||
pSlave = pMstr->pHead;
|
||
while (pSlave != NULL) {
|
||
/*-----------------------------------------------------------------------------
|
||
* for each channel, initialize a plot area.
|
||
*
|
||
* plot a perimeter with grid lines
|
||
*----------------------------------------------------------------------------*/
|
||
pSChan = pSlave->pSChan;
|
||
ymin = pSlave->originVal;
|
||
ymax = pSlave->extentVal;
|
||
if (pSlave->ppAnnot == NULL) {
|
||
sydAnnotVal(pSlave, pAnnotVal, annotVal);
|
||
ppAnnotVal = pAnnotVal;
|
||
}
|
||
else
|
||
ppAnnotVal = pSlave->ppAnnot;
|
||
if (pSlave->pArea != NULL)
|
||
pprAreaClose(pSlave->pArea);
|
||
pArea = pSlave->pArea = pprAreaOpen(pWin,
|
||
xlo+12.*charHtX, ylo+2.*charHt, xhi, yhi,
|
||
xmin, ymin, xmax, ymax, pMstr->nInt, pSlave->nInt, charHt);
|
||
assertAlways(pArea != NULL);
|
||
pSlave->xFracLeft = xlo + 12. * charHtX;
|
||
pSlave->xFracRight = xhi;
|
||
pSlave->yFracBot = ylo + 2.*charHt;
|
||
pSlave->yFracTop = yhi;
|
||
pSlave->annotXFL = xlo;
|
||
pSlave->annotXFR = pSlave->xFracLeft;
|
||
pSlave->annotYFB = pSlave->yFracBot;
|
||
pSlave->annotYFT = yhi;
|
||
if (pSlave->fg != 0 && pMstr->noColor == 0)
|
||
pprAreaSetAttr(pSlave->pArea, PPR_ATTR_FG, 0, &pSlave->fg);
|
||
else if (pMstr->linePlot) {
|
||
if (dbr_type_is_ENUM(pSChan->dbrType))
|
||
pprAreaSetAttr(pArea, PPR_ATTR_LINE_THICK, thick, NULL);
|
||
}
|
||
pprGrid(pArea);
|
||
pprAnnotY(pArea, 0, ymin, ymax, pSlave->nInt, 0,
|
||
pSlave->pSChan->label, ppAnnotVal, 0.);
|
||
if (pSlave == pMstr->pHead) {
|
||
pArea->charHt = charHtTY * pWin->height;
|
||
pArea->xNsubint = pMstr->nSubInt;
|
||
pprAnnotX(pArea, 0, xmin, xmax, pMstr->nInt, 0,
|
||
pMstr->label, pAnnot, 0.);
|
||
pArea->charHt = charHt * pWin->height;
|
||
}
|
||
ylo += yPart;
|
||
yhi += yPart;
|
||
pSlave = pSlave->pNext;
|
||
}
|
||
pSlave = pMstr->pHead;
|
||
pMstr->originFrac = pSlave->xFracLeft;
|
||
pMstr->extentFrac = pSlave->xFracRight;
|
||
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlot_TYSamples - plot one or more samples for a time vs Y plot
|
||
*
|
||
* DESCRIPTION
|
||
*
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* BUGS
|
||
* o text
|
||
*
|
||
* SEE ALSO
|
||
*
|
||
* NOTES
|
||
* 1. This routine isn't intended to be called directly.
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlot_TYSamples(pMstr, begin, end, incr)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
int begin; /* I number of begin sample to plot */
|
||
int end; /* I number of end sample to plot */
|
||
int incr; /* I 0,1 for batch,incremental plotting */
|
||
{
|
||
PPR_WIN *pWin; /* pointer to plot window structure */
|
||
SYD_PL_SLAVE *pSlave; /* pointer to individual slave struct */
|
||
PPR_AREA *pArea;
|
||
int i, j;
|
||
SYD_SPEC *pSspec;
|
||
SYD_CHAN *pSChan;
|
||
double oldX, oldY, newX, newY;
|
||
int skip;
|
||
int showStat; /* 1 to show status code on plot */
|
||
int pointPlot; /* 1 for point plot */
|
||
int linePlot; /* 1 to connect points with lines */
|
||
int markPlot; /* 1 to draw marks at points */
|
||
int markNum; /* number of mark to use */
|
||
int nEl; /* number of array elements */
|
||
int first; /* ==1 if this is the first sample */
|
||
|
||
assert(pMstr != NULL);
|
||
pSspec = pMstr->pSspec;
|
||
assert(pSspec != NULL);
|
||
pWin = pMstr->pWin;
|
||
|
||
linePlot = pMstr->linePlot;
|
||
pointPlot = pMstr->pointPlot;
|
||
markPlot = pMstr->markPlot;
|
||
showStat = pMstr->showStat;
|
||
|
||
pSlave = pMstr->pHead;
|
||
while (pSlave != NULL) {
|
||
pArea = pSlave->pArea;
|
||
pSChan = pSlave->pSChan;
|
||
markNum = pSlave->markNum;
|
||
|
||
if (pSChan->pData == NULL || pSChan->dataChan == 0)
|
||
; /* no action if never connected or not data channel */
|
||
else {
|
||
nEl = pSChan->elCount;
|
||
|
||
i = begin;
|
||
if (!incr)
|
||
first = 1;
|
||
else {
|
||
first = pSlave->first;
|
||
oldX = pSlave->oldX;
|
||
oldY = pSlave->oldY;
|
||
skip = pSlave->skip;
|
||
}
|
||
while (i >= 0) {
|
||
int restart, restart1;
|
||
restart = restart1 = 0;
|
||
if (pSChan->pFlags[i].restart) {
|
||
if (!pSChan->pFlags[i].snapstart)
|
||
restart = 1;
|
||
else if (!pSChan->pFlags[i].snapend)
|
||
restart = 1;
|
||
}
|
||
if (i != end && pSChan->pFlags[i+1].restart) {
|
||
if (!pSChan->pFlags[i+1].snapstart)
|
||
restart1 = 1;
|
||
else if (!pSChan->pFlags[i+1].snapend)
|
||
restart1 = 1;
|
||
}
|
||
if (pSChan->pFlags[i].missing)
|
||
skip = 1;
|
||
else if (first || skip || restart) {
|
||
oldX = pSspec->pDeltaSec[i] -
|
||
pMstr->pSspec->restrictDeltaSecSubtract;
|
||
if (pMstr->wrapX) {
|
||
while (oldX > pMstr->extentVal)
|
||
oldX -= pMstr->extentVal;
|
||
}
|
||
FetchIthValInto(pSChan, oldY)
|
||
if (markPlot)
|
||
pprMarkD(pArea, oldX, oldY, markNum);
|
||
if (showStat && pSChan->pDataCodeR[i] != ' ') {
|
||
pprChar(pArea, oldX,oldY, pSChan->pDataCodeR[i],0.,0.);
|
||
}
|
||
else if (pointPlot)
|
||
pprPointD(pArea, oldX, oldY);
|
||
skip = 0;
|
||
}
|
||
else if (pSChan->pFlags[i].filled && restart1 == 0 && i != end)
|
||
; /* no action */
|
||
else {
|
||
newX = pSspec->pDeltaSec[i] -
|
||
pMstr->pSspec->restrictDeltaSecSubtract;
|
||
if (pMstr->wrapX) {
|
||
while (newX > pMstr->extentVal)
|
||
newX -= pMstr->extentVal;
|
||
}
|
||
if (linePlot && dbr_type_is_ENUM(pSChan->dbrType)) {
|
||
pprLineSegD(pArea, oldX, oldY, newX, oldY);
|
||
oldX = newX;
|
||
}
|
||
FetchIthValInto(pSChan, newY)
|
||
if (linePlot)
|
||
pprLineSegD(pArea, oldX, oldY, newX, newY);
|
||
if (markPlot)
|
||
pprMarkD(pArea, newX, newY, markNum);
|
||
if (showStat && pSChan->pDataCodeR[i] != ' ') {
|
||
pprChar(pArea, newX,newY, pSChan->pDataCodeR[i],0.,0.);
|
||
}
|
||
else if (pointPlot)
|
||
pprPointD(pArea, newX, newY);
|
||
oldX = newX;
|
||
oldY = newY;
|
||
}
|
||
if (i == end)
|
||
i = -1;
|
||
else if (++i >= pSspec->dataDim)
|
||
i = 0;
|
||
first = 0;
|
||
}
|
||
}
|
||
pSlave->first = first;
|
||
pSlave->oldX = oldX;
|
||
pSlave->oldY = oldY;
|
||
pSlave->skip = skip;
|
||
pSlave = pSlave->pNext;
|
||
}
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlot_TYStats - plot one or more snapshots for a time vs Y plot
|
||
*
|
||
* DESCRIPTION
|
||
*
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* NOTES
|
||
* 1. This routine isn't intended to be called directly.
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlot_TYStats(pMstr, begin, end)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
int begin; /* I number of begin snapshot to plot */
|
||
int end; /* I number of end snapshot to plot */
|
||
{
|
||
SYD_PL_SLAVE *pSlave; /* pointer to individual slave struct */
|
||
PPR_AREA *pArea;
|
||
int i;
|
||
SYD_SPEC *pSspec;
|
||
SYD_CHAN *pSChan;
|
||
double oldX, oldY, newX, newY, err;
|
||
|
||
assert(pMstr != NULL);
|
||
pSspec = pMstr->pSspec;
|
||
assert(pSspec != NULL);
|
||
|
||
for (pSlave=pMstr->pHead; pSlave!=NULL; pSlave=pSlave->pNext) {
|
||
pArea = pSlave->pArea;
|
||
pSChan = pSlave->pSChan;
|
||
for (i=begin; i<=end; i++) {
|
||
if (i == begin) {
|
||
oldX = pSspec->pStatDeltaSec[i] -
|
||
pMstr->pSspec->restrictDeltaSecSubtract;
|
||
if (pMstr->wrapX) {
|
||
while (oldX > pMstr->extentVal)
|
||
oldX -= pMstr->extentVal;
|
||
}
|
||
oldY = pSChan->pStats[i].mean;
|
||
}
|
||
else {
|
||
newX = pSspec->pStatDeltaSec[i] -
|
||
pMstr->pSspec->restrictDeltaSecSubtract;
|
||
if (pMstr->wrapX) {
|
||
while (newX > pMstr->extentVal)
|
||
newX -= pMstr->extentVal;
|
||
}
|
||
newY = pSChan->pStats[i].mean;
|
||
if (pMstr->linePlot)
|
||
pprLineSegD(pArea, oldX, oldY, newX, newY);
|
||
oldX = newX;
|
||
oldY = newY;
|
||
}
|
||
if (pMstr->markPlot)
|
||
pprMarkD(pArea, oldX, oldY, pSlave->markNum);
|
||
else
|
||
pprPointD(pArea, oldX, oldY);
|
||
if (pMstr->errBar == SYD_PLATTR_STDDEV) {
|
||
err = pSChan->pStats[i].stdDev;
|
||
pprErrorBar(pArea, oldX, oldY-err, oldX, oldY+err);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlot_TYYPlot - handle time vs multiple Y plots
|
||
*
|
||
* DESCRIPTION
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* BUGS
|
||
* o labeling of x axis is un-esthetic. It should be time based, with
|
||
* some intelligent adaptation, based on time interval for X
|
||
*
|
||
* SEE ALSO
|
||
*
|
||
* NOTES
|
||
* 1. This routine isn't intended to be called directly.
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlot_TYYPlot(pMstr)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
{
|
||
SYD_SPEC *pSspec;
|
||
|
||
assert(pMstr != NULL);
|
||
pSspec = pMstr->pSspec;
|
||
assert(pSspec != NULL);
|
||
|
||
sydPlot_TYYGrid(pMstr);
|
||
if (pSspec->useStats == 0) {
|
||
sydPlot_TYSamples(pMstr,
|
||
pSspec->restrictFirstData, pSspec->restrictLastData, 0);
|
||
}
|
||
else
|
||
sydPlot_TYStats(pMstr, 0, pSspec->statCount-1);
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlot_TYYGrid - draw a grid for a time vs multiple Y plot
|
||
*
|
||
* DESCRIPTION
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* BUGS
|
||
* o text
|
||
*
|
||
* SEE ALSO
|
||
*
|
||
* NOTES
|
||
* 1. This routine isn't intended to be called directly.
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlot_TYYGrid(pMstr)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
{
|
||
PPR_WIN *pWin; /* pointer to plot window structure */
|
||
SYD_PL_SLAVE *pSlave; /* pointer to individual slave struct */
|
||
double xlo, ylo, xhi, yhi;
|
||
double yPart;
|
||
PPR_AREA *pArea;
|
||
double xmin, xmax, ymin, ymax;
|
||
char *pAnnot[20], annot[20][28]; /* annot for time axis */
|
||
double charHt, charHtX, charHtTY, charHtTX;
|
||
SYD_SPEC *pSspec = pMstr->pSspec;
|
||
SYD_CHAN *pSChan;
|
||
int thick=3;
|
||
int nGrids;
|
||
int i, calNum;
|
||
int offsetAnnotY=0;
|
||
int drawAxis=0;
|
||
char **ppAnnotVal, *pAnnotVal[20], annotVal[20][28];
|
||
|
||
pWin = pMstr->pWin;
|
||
|
||
nGrids = 1;
|
||
sydPlot_setup(pMstr, nGrids, &xlo, &ylo, &xhi, &yhi, &yPart,
|
||
&charHt, &charHtX, &charHtTY, &charHtTX);
|
||
sydPlot_setupTime(pMstr, pAnnot, annot);
|
||
xmin = pMstr->originVal;
|
||
xmax = pMstr->extentVal;
|
||
|
||
xlo += 6. * charHtX * (double)pMstr->nSlaves;
|
||
|
||
pSlave = pMstr->pHead;
|
||
while (pSlave != NULL) {
|
||
/*-----------------------------------------------------------------------------
|
||
* for the first channel:
|
||
* initialize a plot area; its fractional size depends on how many
|
||
* "sub-plots" there are
|
||
* plot a perimeter with grid lines
|
||
* for the other channels:
|
||
* initialize an overlapping plot area
|
||
* set a dashed line pattern (unless this is a mark or point plot)
|
||
* draw a "floating" Y axis
|
||
*----------------------------------------------------------------------------*/
|
||
pSChan = pSlave->pSChan;
|
||
ymin = pSlave->originVal;
|
||
ymax = pSlave->extentVal;
|
||
if (pSlave->ppAnnot == NULL) {
|
||
sydAnnotVal(pSlave, pAnnotVal, annotVal);
|
||
ppAnnotVal = pAnnotVal;
|
||
}
|
||
else
|
||
ppAnnotVal = pSlave->ppAnnot;
|
||
if (pSlave->pArea != NULL)
|
||
pprAreaClose(pSlave->pArea);
|
||
pArea = pSlave->pArea = pprAreaOpen(pWin, xlo, ylo+2.*charHt, xhi, yhi,
|
||
xmin, ymin, xmax, ymax, pMstr->nInt, pSlave->nInt, charHt);
|
||
assertAlways(pArea != NULL);
|
||
pSlave->xFracLeft = xlo;
|
||
pSlave->xFracRight = xhi;
|
||
pSlave->yFracBot = ylo;
|
||
pSlave->yFracTop = yhi;
|
||
if (pSlave->fg != 0 && pMstr->noColor == 0)
|
||
pprAreaSetAttr(pSlave->pArea, PPR_ATTR_FG, 0, &pSlave->fg);
|
||
else if (pMstr->linePlot) {
|
||
if (dbr_type_is_ENUM(pSChan->dbrType))
|
||
pprAreaSetAttr(pArea, PPR_ATTR_LINE_THICK, thick, NULL);
|
||
if (pSlave->lineKey > 1 || pMstr->noColor == 0)
|
||
pprAreaSetAttr(pArea, PPR_ATTR_KEYNUM, pSlave->lineKey, NULL);
|
||
}
|
||
else if (pMstr->noColor == 0)
|
||
pprAreaSetAttr(pArea, PPR_ATTR_COLORNUM, pSlave->lineKey, NULL);
|
||
if (drawAxis == 0) {
|
||
pprGrid(pArea);
|
||
if (pSlave == pMstr->pHead) {
|
||
pArea->charHt = charHtTY * pWin->height;
|
||
pArea->xNsubint = pMstr->nSubInt;
|
||
pprAnnotX_wc(pArea, 0,
|
||
xmin, xmax, pMstr->nInt, 0, pMstr->label, pAnnot, 0.);
|
||
pArea->charHt = charHt * pWin->height;
|
||
}
|
||
}
|
||
pprAnnotY(pArea, offsetAnnotY, pSlave->originVal, pSlave->extentVal,
|
||
pSlave->nInt, drawAxis,
|
||
pSlave->pSChan->label, ppAnnotVal, 90.);
|
||
if (pMstr->markPlot)
|
||
pprAnnotYMark(pArea, offsetAnnotY, pSlave->markNum);
|
||
offsetAnnotY += 6;
|
||
drawAxis = 1; /* draw an "auxiliary" axis next time */
|
||
pSlave->annotXFL = xlo - offsetAnnotY * charHtX;
|
||
pSlave->annotXFR = pSlave->annotXFL + 6. * charHtX;
|
||
pSlave->annotYFB = ylo;
|
||
pSlave->annotYFT = yhi;
|
||
pSlave = pSlave->pNext;
|
||
}
|
||
pSlave = pMstr->pHead;
|
||
pMstr->originFrac = pSlave->xFracLeft;
|
||
pMstr->extentFrac = pSlave->xFracRight;
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlot_XYPlot - handle X vs Y plots
|
||
*
|
||
* DESCRIPTION
|
||
* the first channel in the plot spec is used for the X axis
|
||
*
|
||
* alarm state of the "X" channel is not displayed
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* BUGS
|
||
* o text
|
||
*
|
||
* SEE ALSO
|
||
*
|
||
* NOTES
|
||
* 1. This routine isn't intended to be called directly.
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlot_XYPlot(pMstr)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
{
|
||
SYD_SPEC *pSspec;
|
||
|
||
assert(pMstr != NULL);
|
||
pSspec = pMstr->pSspec;
|
||
assert(pSspec != NULL);
|
||
|
||
sydPlot_XYGrid(pMstr);
|
||
if (pSspec->useStats == 0) {
|
||
sydPlot_XYSamples(pMstr,
|
||
pSspec->restrictFirstData, pSspec->restrictLastData, 0);
|
||
}
|
||
else
|
||
sydPlot_XYStats(pMstr, 0, pSspec->statCount-1);
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlot_XYGrid - draw a grid for an X vs Y plot
|
||
*
|
||
* DESCRIPTION
|
||
* the first channel in the plot spec is used for the X axis
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* BUGS
|
||
* o text
|
||
*
|
||
* SEE ALSO
|
||
*
|
||
* NOTES
|
||
* 1. This routine isn't intended to be called directly.
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlot_XYGrid(pMstr)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
{
|
||
PPR_WIN *pWin; /* pointer to plot window structure */
|
||
SYD_PL_SLAVE *pSlave; /* pointer to individual slave struct */
|
||
SYD_PL_SLAVE *pSlaveX; /* pointer to X axis slave struct */
|
||
double xlo, ylo, xhi, yhi;
|
||
double yPart;
|
||
PPR_AREA *pArea;
|
||
double xmin, xmax, ymin, ymax;
|
||
double charHt, charHtX, charHtTY, charHtTX;
|
||
SYD_CHAN *pSChan;
|
||
SYD_CHAN *pSChanX;
|
||
int nGrids;
|
||
char **ppAnnotVal, *pAnnotVal[20], annotVal[20][28];
|
||
char **ppAnnotXVal, *pAnnotXVal[20], annotXVal[20][28];
|
||
int first=1;
|
||
|
||
pWin = pMstr->pWin;
|
||
|
||
pSlaveX = pMstr->pHead;
|
||
while (1) {
|
||
if (pSlaveX->xChan)
|
||
break;
|
||
pSlaveX = pSlaveX->pNext;
|
||
if (pSlaveX == NULL) {
|
||
pSlaveX = pMstr->pHead;
|
||
break;
|
||
}
|
||
}
|
||
if (pSlaveX == pMstr->pHead)
|
||
pSlave = pSlaveX->pNext;
|
||
else
|
||
pSlave = pMstr->pHead;
|
||
nGrids = pMstr->nSlaves - 1;
|
||
sydPlot_setup(pMstr, nGrids, &xlo, &ylo, &xhi, &yhi, &yPart,
|
||
&charHt, &charHtX, &charHtTY, &charHtTX);
|
||
|
||
pSlaveX->pArea = NULL;
|
||
pSChanX = pSlaveX->pSChan;
|
||
if (pSlaveX->ppAnnot == NULL) {
|
||
sydAnnotVal(pSlaveX, pAnnotXVal, annotXVal);
|
||
ppAnnotXVal = pAnnotXVal;
|
||
}
|
||
else
|
||
ppAnnotVal = pSlave->ppAnnot;
|
||
xmin = pSlaveX->originVal;
|
||
xmax = pSlaveX->extentVal;
|
||
while (pSlave != NULL) {
|
||
/*-----------------------------------------------------------------------------
|
||
* for each Y channel, plot a perimeter with grid lines
|
||
*----------------------------------------------------------------------------*/
|
||
pSChan = pSlave->pSChan;
|
||
ymin = pSlave->originVal;
|
||
ymax = pSlave->extentVal;
|
||
if (pSlave->ppAnnot == NULL) {
|
||
sydAnnotVal(pSlave, pAnnotVal, annotVal);
|
||
ppAnnotVal = pAnnotVal;
|
||
}
|
||
else
|
||
ppAnnotVal = pSlave->ppAnnot;
|
||
if (pSlave->pArea != NULL)
|
||
pprAreaClose(pSlave->pArea);
|
||
pArea = pSlave->pArea = pprAreaOpen(pWin,
|
||
xlo+12.*charHtX, ylo+2.*charHt, xhi, yhi,
|
||
xmin, ymin, xmax, ymax, pSlaveX->nInt, pSlave->nInt, charHt);
|
||
assertAlways(pArea != NULL);
|
||
pSlave->xFracLeft = xlo + 12. * charHtX;
|
||
pSlave->xFracRight = xhi;
|
||
pSlave->yFracBot = ylo + 2. * charHt;
|
||
pSlave->yFracTop = yhi;
|
||
pSlave->annotXFL = xlo;
|
||
pSlave->annotXFR = pSlave->xFracLeft;
|
||
pSlave->annotYFB = pSlave->yFracBot;
|
||
pSlave->annotYFT = yhi;
|
||
if (pSlave->fg != 0 && pMstr->noColor == 0)
|
||
pprAreaSetAttr(pSlave->pArea, PPR_ATTR_FG, 0, &pSlave->fg);
|
||
pprGrid(pArea);
|
||
pprAnnotY(pArea, 0, ymin, ymax, pSlave->nInt, 0,
|
||
pSlave->pSChan->label, ppAnnotVal, 0.);
|
||
if (first) {
|
||
pArea->charHt = charHtTY * pWin->height;
|
||
pprAnnotX(pArea, 0, xmin, xmax, pSlaveX->nInt, 0,
|
||
pSlaveX->pSChan->label, ppAnnotXVal, 0.);
|
||
pArea->charHt = charHt * pWin->height;
|
||
first = 0;
|
||
}
|
||
ylo += yPart;
|
||
yhi += yPart;
|
||
pSlave = pSlave->pNext;
|
||
if (pSlave == pSlaveX)
|
||
pSlave = pSlave->pNext;
|
||
}
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlot_XYSamples - plot one or more samples for an X vs Y plot
|
||
*
|
||
* DESCRIPTION
|
||
* the first channel in the plot spec is used for the X axis
|
||
*
|
||
* alarm state of the "X" channel is not displayed
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* BUGS
|
||
* o line plot isn't handled
|
||
*
|
||
* SEE ALSO
|
||
*
|
||
* NOTES
|
||
* 1. This routine isn't intended to be called directly.
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlot_XYSamples(pMstr, begin, end, incr)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
int begin; /* I number of begin sample to plot */
|
||
int end; /* I number of end sample to plot */
|
||
int incr; /* I 0,1 for batch,incremental plotting */
|
||
{
|
||
PPR_WIN *pWin; /* pointer to plot window structure */
|
||
SYD_PL_SLAVE *pSlave; /* pointer to individual slave struct */
|
||
SYD_PL_SLAVE *pSlaveX; /* pointer to X axis slave struct */
|
||
PPR_AREA *pArea;
|
||
int i, j;
|
||
SYD_SPEC *pSspec;
|
||
SYD_CHAN *pSChan;
|
||
SYD_CHAN *pSChanX;
|
||
double oldX, oldY, newX, newY;
|
||
int skip;
|
||
int showStat; /* 1 to show status code on plot */
|
||
int pointPlot; /* 1 for point plot */
|
||
int linePlot; /* 1 to connect points with lines */
|
||
int markPlot; /* 1 to draw marks at points */
|
||
int markNum; /* number of mark to use */
|
||
int nEl; /* number of array elements */
|
||
int first; /* ==1 if this is the first sample */
|
||
|
||
assert(pMstr != NULL);
|
||
pSspec = pMstr->pSspec;
|
||
assert(pSspec != NULL);
|
||
pWin = pMstr->pWin;
|
||
|
||
linePlot = pMstr->linePlot;
|
||
pointPlot = pMstr->pointPlot;
|
||
markPlot = pMstr->markPlot;
|
||
showStat = pMstr->showStat;
|
||
|
||
pSlaveX = pMstr->pHead;
|
||
while (1) {
|
||
if (pSlaveX->xChan)
|
||
break;
|
||
pSlaveX = pSlaveX->pNext;
|
||
if (pSlaveX == NULL) {
|
||
pSlaveX = pMstr->pHead;
|
||
break;
|
||
}
|
||
}
|
||
if (pSlaveX == pMstr->pHead)
|
||
pSlave = pSlaveX->pNext;
|
||
else
|
||
pSlave = pMstr->pHead;
|
||
pSChanX = pSlaveX->pSChan;
|
||
while (pSlave != NULL) {
|
||
pArea = pSlave->pArea;
|
||
pSChan = pSlave->pSChan;
|
||
if (pSChan->pData == NULL || pSChan->dataChan == 0)
|
||
; /* no action if never connected or not data channel */
|
||
else {
|
||
markNum = pSlave->markNum;
|
||
|
||
nEl = pSChanX->elCount;
|
||
if (nEl > pSChan->elCount)
|
||
nEl = pSChan->elCount;
|
||
|
||
i = begin;
|
||
if (!incr)
|
||
first = 1;
|
||
else {
|
||
first = pSlave->first;
|
||
oldX = pSlave->oldX;
|
||
oldY = pSlave->oldY;
|
||
skip = pSlave->skip;
|
||
}
|
||
while (i >= 0) {
|
||
int restart, restart1;
|
||
restart = restart1 = 0;
|
||
if (pSChan->pFlags[i].restart) {
|
||
if (!pSChan->pFlags[i].snapstart)
|
||
restart = 1;
|
||
else if (!pSChan->pFlags[i].snapend)
|
||
restart = 1;
|
||
}
|
||
if (i != end && pSChan->pFlags[i+1].restart) {
|
||
if (!pSChan->pFlags[i+1].snapstart)
|
||
restart1 = 1;
|
||
else if (!pSChan->pFlags[i+1].snapend)
|
||
restart1 = 1;
|
||
}
|
||
if (pSChan->pFlags[i].missing || pSChanX->pFlags[i].missing)
|
||
skip = 1;
|
||
else if (first || skip || restart ||
|
||
pSChanX->pFlags[i].restart) {
|
||
if (nEl == 1) {
|
||
FetchIthValInto(pSChanX, oldX)
|
||
FetchIthValInto(pSChan, oldY)
|
||
if (markPlot)
|
||
pprMarkD(pArea, oldX, oldY, markNum);
|
||
if (showStat && pSChan->pDataCodeR[i] != ' ') {
|
||
pprChar(pArea,
|
||
oldX, oldY, pSChan->pDataCodeR[i], 0., 0.);
|
||
}
|
||
else if (pointPlot)
|
||
pprPointD(pArea, oldX, oldY);
|
||
}
|
||
else {
|
||
sydPlot_XYarray(pArea, pSChanX, pSChan, i);
|
||
}
|
||
skip = 0;
|
||
}
|
||
#if 0 /* don't "optimize" filled--show each x,y */
|
||
else if (pSChan->pFlags[i].filled && i != end &&
|
||
pSChan->pFlags[i+1].restart == 0)
|
||
; /* no action */
|
||
#endif
|
||
else {
|
||
if (nEl == 1) {
|
||
FetchIthValInto(pSChanX, newX)
|
||
FetchIthValInto(pSChan, newY)
|
||
if (linePlot)
|
||
pprLineSegD(pArea, oldX, oldY, newX, newY);
|
||
if (markPlot)
|
||
pprMarkD(pArea, newX, newY, markNum);
|
||
if (showStat && pSChan->pDataCodeR[i] != ' ') {
|
||
pprChar(pArea,
|
||
newX, newY, pSChan->pDataCodeR[i], 0., 0.);
|
||
}
|
||
else if (pointPlot)
|
||
pprPointD(pArea, newX, newY);
|
||
oldX = newX;
|
||
oldY = newY;
|
||
}
|
||
else {
|
||
sydPlot_XYarray(pArea, pSChanX, pSChan, i);
|
||
}
|
||
}
|
||
if (i == end)
|
||
i = -1;
|
||
else if (++i >= pSspec->dataDim)
|
||
i = 0;
|
||
first = 0;
|
||
}
|
||
}
|
||
pSlave->first = first;
|
||
pSlave->oldX = oldX;
|
||
pSlave->oldY = oldY;
|
||
pSlave->skip = skip;
|
||
pSlave = pSlave->pNext;
|
||
if (pSlave == pSlaveX)
|
||
pSlave = pSlave->pNext;
|
||
}
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlot_XYStats - plot one or more snapshots for an X vs Y plot
|
||
*
|
||
* DESCRIPTION
|
||
* the first channel in the plot spec is used for the X axis
|
||
*
|
||
* alarm state of the "X" channel is not displayed
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* BUGS
|
||
* o line plot isn't handled
|
||
*
|
||
* SEE ALSO
|
||
*
|
||
* NOTES
|
||
* 1. This routine isn't intended to be called directly.
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlot_XYStats(pMstr, begin, end)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
int begin; /* I number of begin snapshots to plot */
|
||
int end; /* I number of end snapshots to plot */
|
||
{
|
||
SYD_PL_SLAVE *pSlave; /* pointer to individual slave struct */
|
||
SYD_PL_SLAVE *pSlaveX; /* pointer to X axis slave struct */
|
||
PPR_AREA *pArea;
|
||
int i;
|
||
SYD_SPEC *pSspec;
|
||
SYD_CHAN *pSChan;
|
||
SYD_CHAN *pSChanX;
|
||
double oldX, oldY, newX, newY, err;
|
||
|
||
assert(pMstr != NULL);
|
||
pSspec = pMstr->pSspec;
|
||
assert(pSspec != NULL);
|
||
|
||
pSlaveX = pMstr->pHead;
|
||
while (1) {
|
||
if (pSlaveX->xChan)
|
||
break;
|
||
pSlaveX = pSlaveX->pNext;
|
||
if (pSlaveX == NULL) {
|
||
pSlaveX = pMstr->pHead;
|
||
break;
|
||
}
|
||
}
|
||
if (pSlaveX == pMstr->pHead)
|
||
pSlave = pSlaveX->pNext;
|
||
else
|
||
pSlave = pMstr->pHead;
|
||
pSChanX = pSlaveX->pSChan;
|
||
while (pSlave != NULL) {
|
||
pArea = pSlave->pArea;
|
||
pSChan = pSlave->pSChan;
|
||
for (i=begin; i<=end; i++) {
|
||
if (i == begin) {
|
||
oldX = pSChanX->pStats[i].mean;
|
||
oldY = pSChan->pStats[i].mean;
|
||
}
|
||
else {
|
||
newX = pSChanX->pStats[i].mean;
|
||
newY = pSChan->pStats[i].mean;
|
||
if (pMstr->linePlot)
|
||
pprLineSegD(pArea, oldX, oldY, newX, newY);
|
||
oldX = newX;
|
||
oldY = newY;
|
||
}
|
||
if (pMstr->markPlot)
|
||
pprMarkD(pArea, oldX, oldY, pSlave->markNum);
|
||
else
|
||
pprPointD(pArea, oldX, oldY);
|
||
if (pMstr->errBar == SYD_PLATTR_STDDEV) {
|
||
err = pSChan->pStats[i].stdDev;
|
||
pprErrorBar(pArea, oldX, oldY-err, oldX, oldY+err);
|
||
err = pSChanX->pStats[i].stdDev;
|
||
pprErrorBar(pArea, oldX-err, oldY, oldX+err, oldY);
|
||
}
|
||
}
|
||
pSlave = pSlave->pNext;
|
||
if (pSlave == pSlaveX)
|
||
pSlave = pSlave->pNext;
|
||
}
|
||
}
|
||
|
||
/*+/internal******************************************************************
|
||
* NAME sydPlot_XYarray - plot array vs array
|
||
*
|
||
* DESCRIPTION
|
||
*
|
||
* RETURNS
|
||
*
|
||
* BUGS
|
||
* o text
|
||
*
|
||
* SEE ALSO
|
||
*
|
||
* NOTES
|
||
* 1. This routine isn't intended to be called directly.
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
static void
|
||
sydPlot_XYarray(pArea, pSChanX, pSChan, sub)
|
||
PPR_AREA *pArea;
|
||
SYD_CHAN *pSChan;
|
||
SYD_CHAN *pSChanX;
|
||
int sub;
|
||
{
|
||
int nEl, nElX, nElY, i;
|
||
char *pSrcX, *pSrcY;
|
||
double newX, newY, oldX, oldY;
|
||
int nByteX, nByteY;
|
||
|
||
nEl = nElX = pSChanX->elCount;
|
||
nElY = pSChan->elCount;
|
||
if (nElX > nElY)
|
||
nEl = nElY;
|
||
nByteX = dbr_value_size[pSChanX->dbrType];
|
||
pSrcX = (char *)pSChanX->pData + sub * nByteX * nElX;
|
||
nByteY = dbr_value_size[pSChan->dbrType];
|
||
pSrcY = (char *)pSChan->pData + sub * nByteY * nElY;
|
||
for (i=0; i<nEl; i++) {
|
||
if (dbr_type_is_FLOAT(pSChanX->dbrType))
|
||
newX = *(float *)pSrcX;
|
||
else if (dbr_type_is_SHORT(pSChanX->dbrType))
|
||
newX = *(short *)pSrcX;
|
||
else if (dbr_type_is_DOUBLE(pSChanX->dbrType))
|
||
newX = *(double *)pSrcX;
|
||
else if (dbr_type_is_LONG(pSChanX->dbrType))
|
||
newX = *(long *)pSrcX;
|
||
else if (dbr_type_is_CHAR(pSChanX->dbrType))
|
||
newX = *(unsigned char *)pSrcX;
|
||
else if (dbr_type_is_ENUM(pSChanX->dbrType))
|
||
newX = *(short *)pSrcX;
|
||
if (dbr_type_is_FLOAT(pSChan->dbrType))
|
||
newY = *(float *)pSrcY;
|
||
else if (dbr_type_is_SHORT(pSChan->dbrType))
|
||
newY = *(short *)pSrcY;
|
||
else if (dbr_type_is_DOUBLE(pSChan->dbrType))
|
||
newY = *(double *)pSrcY;
|
||
else if (dbr_type_is_LONG(pSChan->dbrType))
|
||
newY = *(long *)pSrcY;
|
||
else if (dbr_type_is_CHAR(pSChan->dbrType))
|
||
newY = *(unsigned char *)pSrcY;
|
||
else if (dbr_type_is_ENUM(pSChan->dbrType))
|
||
newY = *(short *)pSrcY;
|
||
if (i > 0)
|
||
pprLineSegD(pArea, oldX, oldY, newX, newY);
|
||
oldX = newX;
|
||
oldY = newY;
|
||
pSrcX += nByteX;
|
||
pSrcY += nByteY;
|
||
}
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlot_XYYPlot - handle X vs multiple Y plots
|
||
*
|
||
* DESCRIPTION
|
||
* the first channel in the plot spec is used for the X axis
|
||
*
|
||
* alarm state of the "X" channel is not displayed
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* BUGS
|
||
* o text
|
||
*
|
||
* SEE ALSO
|
||
*
|
||
* NOTES
|
||
* 1. This routine isn't intended to be called directly.
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlot_XYYPlot(pMstr)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
{
|
||
SYD_SPEC *pSspec;
|
||
|
||
assert(pMstr != NULL);
|
||
pSspec = pMstr->pSspec;
|
||
assert(pSspec != NULL);
|
||
|
||
sydPlot_XYYGrid(pMstr);
|
||
if (pSspec->useStats == 0) {
|
||
sydPlot_XYSamples(pMstr,
|
||
pSspec->restrictFirstData, pSspec->restrictLastData, 0);
|
||
}
|
||
else
|
||
sydPlot_XYStats(pMstr, 0, pSspec->statCount-1);
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlot_XYYGrid - draw a grid for an X vs multiple Y plot
|
||
*
|
||
* DESCRIPTION
|
||
* the first channel in the plot spec is used for the X axis
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* BUGS
|
||
* o text
|
||
*
|
||
* SEE ALSO
|
||
*
|
||
* NOTES
|
||
* 1. This routine isn't intended to be called directly.
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlot_XYYGrid(pMstr)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
{
|
||
PPR_WIN *pWin; /* pointer to plot window structure */
|
||
SYD_PL_SLAVE *pSlave; /* pointer to individual slave struct */
|
||
SYD_PL_SLAVE *pSlaveX; /* pointer to X axis slave struct */
|
||
double xlo, ylo, xhi, yhi, yPart;
|
||
PPR_AREA *pArea;
|
||
double xmin, xmax, ymin, ymax;
|
||
double charHt, charHtX, charHtTY, charHtTX;
|
||
SYD_CHAN *pSChan;
|
||
SYD_CHAN *pSChanX;
|
||
int offsetAnnotY=0;
|
||
int drawAxis=0;
|
||
int nGrids;
|
||
char **ppAnnotVal, *pAnnotVal[20], annotVal[20][28];
|
||
char **ppAnnotXVal, *pAnnotXVal[20], annotXVal[20][28];
|
||
|
||
pWin = pMstr->pWin;
|
||
|
||
pSlaveX = pMstr->pHead;
|
||
while (1) {
|
||
if (pSlaveX->xChan)
|
||
break;
|
||
pSlaveX = pSlaveX->pNext;
|
||
if (pSlaveX == NULL) {
|
||
pSlaveX = pMstr->pHead;
|
||
break;
|
||
}
|
||
}
|
||
if (pSlaveX == pMstr->pHead)
|
||
pSlave = pSlaveX->pNext;
|
||
else
|
||
pSlave = pMstr->pHead;
|
||
pSChanX = pSlaveX->pSChan;
|
||
|
||
nGrids = 1;
|
||
sydPlot_setup(pMstr, nGrids, &xlo, &ylo, &xhi, &yhi, &yPart,
|
||
&charHt, &charHtX, &charHtTY, &charHtTX);
|
||
xlo += 6. * charHtX * (double)(pMstr->nSlaves - 1);
|
||
|
||
pSlaveX->pArea = NULL;
|
||
xmin = pSlaveX->originVal;
|
||
xmax = pSlaveX->extentVal;
|
||
if (pSlaveX->ppAnnot == NULL) {
|
||
sydAnnotVal(pSlaveX, pAnnotXVal, annotXVal);
|
||
ppAnnotXVal = pAnnotXVal;
|
||
}
|
||
else
|
||
ppAnnotXVal = pSlaveX->ppAnnot;
|
||
pSlaveX->yFracBot = pSlaveX->yFracTop = 0.;
|
||
while (pSlave != NULL) {
|
||
/*-----------------------------------------------------------------------------
|
||
* for the first Y channel:
|
||
* initialize a plot area; its fractional size depends on how many
|
||
* "sub-plots" there are
|
||
* plot a perimeter with grid lines
|
||
* set for solid line
|
||
* for the other channels:
|
||
* initialize an overlapping plot area
|
||
* set a dashed line pattern (unless this is a mark or point plot)
|
||
* draw a "floating" Y axis
|
||
*----------------------------------------------------------------------------*/
|
||
pSChan = pSlave->pSChan;
|
||
ymin = pSlave->originVal;
|
||
ymax = pSlave->extentVal;
|
||
if (pSlave->ppAnnot == NULL) {
|
||
sydAnnotVal(pSlave, pAnnotVal, annotVal);
|
||
ppAnnotVal = pAnnotVal;
|
||
}
|
||
else
|
||
ppAnnotVal = pSlave->ppAnnot;
|
||
if (pSlave->pArea != NULL)
|
||
pprAreaClose(pSlave->pArea);
|
||
pArea = pSlave->pArea = pprAreaOpen(pWin, xlo, ylo+2.*charHt, xhi, yhi,
|
||
xmin, ymin, xmax, ymax, pSlaveX->nInt, pSlave->nInt, charHt);
|
||
assertAlways(pArea != NULL);
|
||
pSlave->xFracLeft = xlo;
|
||
pSlave->xFracRight = xhi;
|
||
pSlave->yFracBot = ylo;
|
||
pSlave->yFracTop = yhi;
|
||
if (pSlave->fg != 0 && pMstr->noColor == 0)
|
||
pprAreaSetAttr(pSlave->pArea, PPR_ATTR_FG, 0, &pSlave->fg);
|
||
else if (pMstr->linePlot) {
|
||
/* set keynum if color is being used or if this is auxiliary axis */
|
||
if (drawAxis || pMstr->noColor == 0)
|
||
pprAreaSetAttr(pArea, PPR_ATTR_KEYNUM, pSlave->lineKey, NULL);
|
||
}
|
||
else if (pMstr->noColor == 0)
|
||
pprAreaSetAttr(pArea, PPR_ATTR_COLORNUM, pSlave->lineKey, NULL);
|
||
if (drawAxis == 0) {
|
||
pprGrid(pArea);
|
||
pArea->charHt = charHtTY * pWin->height;
|
||
pprAnnotX_wc(pArea, 0, pSlaveX->originVal, pSlaveX->extentVal,
|
||
pSlaveX->nInt, 0, pSlaveX->pSChan->label, ppAnnotXVal, 0.);
|
||
pArea->charHt = charHt * pWin->height;
|
||
}
|
||
pprAnnotY(pArea, offsetAnnotY, pSlave->originVal, pSlave->extentVal,
|
||
pSlave->nInt, drawAxis, pSlave->pSChan->label, ppAnnotVal, 90.);
|
||
if (pMstr->markPlot)
|
||
pprAnnotYMark(pArea, offsetAnnotY, pSlave->markNum);
|
||
offsetAnnotY += 6;
|
||
drawAxis = 1; /* draw an "auxiliary" axis next time */
|
||
pSlave->annotXFL = xlo - offsetAnnotY * charHtX;
|
||
pSlave->annotXFR = pSlave->annotXFL + 6. * charHtX;
|
||
pSlave->annotYFB = ylo;
|
||
pSlave->annotYFT = yhi;
|
||
pSlave = pSlave->pNext;
|
||
if (pSlave == pSlaveX)
|
||
pSlave = pSlave->pNext;
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlot_YPlot - handle Y plots
|
||
*
|
||
* DESCRIPTION
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* BUGS
|
||
* o text
|
||
*
|
||
* SEE ALSO
|
||
*
|
||
* NOTES
|
||
* 1. This routine isn't intended to be called directly.
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlot_YPlot(pMstr)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
{
|
||
SYD_SPEC *pSspec;
|
||
|
||
assert(pMstr != NULL);
|
||
pSspec = pMstr->pSspec;
|
||
assert(pSspec != NULL);
|
||
|
||
sydPlot_YGrid(pMstr);
|
||
if (pSspec->useStats == 0) {
|
||
sydPlot_YSamples(pMstr,
|
||
pSspec->restrictFirstData, pSspec->restrictLastData, 0);
|
||
}
|
||
else
|
||
sydPlot_YStats(pMstr, 0, pSspec->statCount-1);
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlot_YGrid - draw a grid for a Y plot
|
||
*
|
||
* DESCRIPTION
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* BUGS
|
||
* o text
|
||
*
|
||
* SEE ALSO
|
||
*
|
||
* NOTES
|
||
* 1. This routine isn't intended to be called directly.
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlot_YGrid(pMstr)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
{
|
||
PPR_WIN *pWin; /* pointer to plot window structure */
|
||
SYD_PL_SLAVE *pSlave; /* pointer to individual slave struct */
|
||
double xlo, ylo, xhi, yhi;
|
||
double yPart;
|
||
PPR_AREA *pArea;
|
||
double xmin, xmax, ymin, ymax;
|
||
int xNint;
|
||
double charHt, charHtX, charHtTY, charHtTX;
|
||
SYD_CHAN *pSChan;
|
||
int thick=3;
|
||
int nGrids;
|
||
char **ppAnnotVal, *pAnnotVal[20], annotVal[20][28];
|
||
|
||
pWin = pMstr->pWin;
|
||
|
||
nGrids = pMstr->nSlaves;
|
||
sydPlot_setup(pMstr, nGrids, &xlo, &ylo, &xhi, &yhi, &yPart,
|
||
&charHt, &charHtX, &charHtTY, &charHtTX);
|
||
|
||
xmin = xmax = 0.;
|
||
pSlave = pMstr->pHead;
|
||
while (pSlave != NULL) {
|
||
if (pSlave->pSChan->elCount > xmax)
|
||
xmax = pSlave->pSChan->elCount;
|
||
pSlave = pSlave->pNext;
|
||
}
|
||
xNint = 1;
|
||
if (xmax == 1.)
|
||
xmax = pMstr->pSspec->reqCount - 1;
|
||
|
||
pSlave = pMstr->pHead;
|
||
while (pSlave != NULL) {
|
||
/*-----------------------------------------------------------------------------
|
||
* for each channel, initialize a plot area.
|
||
*
|
||
* plot a perimeter with grid lines
|
||
*----------------------------------------------------------------------------*/
|
||
pSChan = pSlave->pSChan;
|
||
ymin = pSlave->originVal;
|
||
ymax = pSlave->extentVal;
|
||
charHt = PprDfltCharHt(ylo, yhi);
|
||
charHtX = pprYFracToXFrac(pWin, charHt);
|
||
if (pSlave->ppAnnot == NULL) {
|
||
sydAnnotVal(pSlave, pAnnotVal, annotVal);
|
||
ppAnnotVal = pAnnotVal;
|
||
}
|
||
else
|
||
ppAnnotVal = pSlave->ppAnnot;
|
||
if (pSlave->pArea != NULL)
|
||
pprAreaClose(pSlave->pArea);
|
||
pArea = pSlave->pArea = pprAreaOpen(pWin,
|
||
xlo+12.*charHtX, ylo+2.*charHt, xhi, yhi,
|
||
xmin, ymin, xmax, ymax, xNint, pSlave->nInt, charHt);
|
||
assertAlways(pArea != NULL);
|
||
pSlave->xFracLeft = xlo + 12. * charHtX;
|
||
pSlave->xFracRight = xhi;
|
||
pSlave->yFracBot = ylo + 6. * charHt;
|
||
pSlave->yFracTop = yhi;
|
||
pSlave->annotXFL = xlo;
|
||
pSlave->annotXFR = pSlave->xFracLeft;
|
||
pSlave->annotYFB = pSlave->yFracBot;
|
||
pSlave->annotYFT = yhi;
|
||
if (pSlave->fg != 0 && pMstr->noColor == 0)
|
||
pprAreaSetAttr(pSlave->pArea, PPR_ATTR_FG, 0, &pSlave->fg);
|
||
else if (pMstr->linePlot) {
|
||
if (dbr_type_is_ENUM(pSChan->dbrType))
|
||
pprAreaSetAttr(pArea, PPR_ATTR_LINE_THICK, thick, NULL);
|
||
}
|
||
pprGrid(pArea);
|
||
pprAnnotY(pArea, 0, ymin, ymax, pSlave->nInt, 0,
|
||
pSlave->pSChan->label, ppAnnotVal, 0.);
|
||
if (pSlave == pMstr->pHead) {
|
||
pArea->charHt = charHtTY * pWin->height;
|
||
pprAnnotX(pArea, 0, xmin, xmax, xNint, 0, "bin number", NULL, 0.);
|
||
pArea->charHt = charHt * pWin->height;
|
||
}
|
||
ylo += yPart;
|
||
yhi += yPart;
|
||
pSlave = pSlave->pNext;
|
||
}
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlot_YSamples - plot one or more samples for a Y plot
|
||
*
|
||
* DESCRIPTION
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* BUGS
|
||
* o text
|
||
*
|
||
* SEE ALSO
|
||
*
|
||
* NOTES
|
||
* 1. This routine isn't intended to be called directly.
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlot_YSamples(pMstr, begin, end, incr)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
int begin; /* I number of begin sample to plot */
|
||
int end; /* I number of end sample to plot */
|
||
int incr; /* I 0,1 for batch,incremental plotting */
|
||
{
|
||
PPR_WIN *pWin; /* pointer to plot window structure */
|
||
SYD_PL_SLAVE *pSlave; /* pointer to individual slave struct */
|
||
PPR_AREA *pArea;
|
||
int i, j;
|
||
SYD_SPEC *pSspec;
|
||
SYD_CHAN *pSChan;
|
||
double oldX, oldY, newX, newY;
|
||
int skip;
|
||
int showStat; /* 1 to show status code on plot */
|
||
int pointPlot; /* 1 for point plot */
|
||
int linePlot; /* 1 to connect points with lines */
|
||
int markPlot; /* 1 to draw marks at points */
|
||
int markNum; /* number of mark to use */
|
||
int nEl; /* number of array elements */
|
||
int first; /* ==1 if this is the first sample */
|
||
|
||
assert(pMstr != NULL);
|
||
pSspec = pMstr->pSspec;
|
||
assert(pSspec != NULL);
|
||
pWin = pMstr->pWin;
|
||
|
||
linePlot = pMstr->linePlot;
|
||
pointPlot = pMstr->pointPlot;
|
||
markPlot = pMstr->markPlot;
|
||
showStat = pMstr->showStat;
|
||
|
||
pSlave = pMstr->pHead;
|
||
while (pSlave != NULL) {
|
||
pArea = pSlave->pArea;
|
||
pSChan = pSlave->pSChan;
|
||
if (pSChan->pData == NULL || pSChan->dataChan == 0)
|
||
; /* no action if never connected or not data channel */
|
||
else {
|
||
markNum = pSlave->markNum;
|
||
|
||
nEl = pSChan->elCount;
|
||
|
||
i = begin;
|
||
if (!incr)
|
||
first = 1;
|
||
else {
|
||
first = pSlave->first;
|
||
oldX = pSlave->oldX;
|
||
oldY = pSlave->oldY;
|
||
skip = pSlave->skip;
|
||
}
|
||
while (i >= 0) {
|
||
int restart, restart1;
|
||
restart = restart1 = 0;
|
||
if (pSChan->pFlags[i].restart) {
|
||
if (!pSChan->pFlags[i].snapstart)
|
||
restart = 1;
|
||
else if (!pSChan->pFlags[i].snapend)
|
||
restart = 1;
|
||
}
|
||
if (i != end && pSChan->pFlags[i+1].restart) {
|
||
if (!pSChan->pFlags[i+1].snapstart)
|
||
restart1 = 1;
|
||
else if (!pSChan->pFlags[i+1].snapend)
|
||
restart1 = 1;
|
||
}
|
||
if (pSChan->pFlags[i].missing)
|
||
skip = 1;
|
||
else if (first || skip || restart) {
|
||
if (nEl == 1) {
|
||
oldX = i;
|
||
FetchIthValInto(pSChan, oldY)
|
||
if (markPlot)
|
||
pprMarkD(pArea, oldX, oldY, markNum);
|
||
if (showStat && pSChan->pDataCodeR[i] != ' ') {
|
||
pprChar(pArea, oldX, oldY,
|
||
pSChan->pDataCodeR[i], 0., 0.);
|
||
}
|
||
else if (pointPlot)
|
||
pprPointD(pArea, oldX, oldY);
|
||
}
|
||
else {
|
||
sydPlot_Yarray(pArea, pSChan, i);
|
||
}
|
||
skip = 0;
|
||
}
|
||
else if (pSChan->pFlags[i].filled && restart1 == 0 && i != end)
|
||
; /* no action */
|
||
else {
|
||
if (nEl == 1) {
|
||
newX = i;
|
||
if (linePlot && dbr_type_is_ENUM(pSChan->dbrType)) {
|
||
pprLineSegD(pArea, oldX, oldY, newX, oldY);
|
||
oldX = newX;
|
||
}
|
||
FetchIthValInto(pSChan, newY)
|
||
if (linePlot)
|
||
pprLineSegD(pArea, oldX, oldY, newX, newY);
|
||
if (markPlot)
|
||
pprMarkD(pArea, newX, newY, markNum);
|
||
if (showStat && pSChan->pDataCodeR[i] != ' ') {
|
||
pprChar(pArea, newX, newY,
|
||
pSChan->pDataCodeR[i], 0., 0.);
|
||
}
|
||
else if (pointPlot)
|
||
pprPointD(pArea, newX, newY);
|
||
oldX = newX;
|
||
oldY = newY;
|
||
}
|
||
else {
|
||
sydPlot_Yarray(pArea, pSChan, i);
|
||
}
|
||
}
|
||
if (i == end)
|
||
i = -1;
|
||
else if (++i >= pSspec->dataDim)
|
||
i = 0;
|
||
first = 0;
|
||
}
|
||
}
|
||
pSlave->first = first;
|
||
pSlave->oldX = oldX;
|
||
pSlave->oldY = oldY;
|
||
pSlave->skip = skip;
|
||
pSlave = pSlave->pNext;
|
||
}
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlot_YStats - plot one or more snapshots for a Y plot
|
||
*
|
||
* DESCRIPTION
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* NOTES
|
||
* 1. This routine isn't intended to be called directly.
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlot_YStats(pMstr, begin, end)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
int begin; /* I number of begin snapshots to plot */
|
||
int end; /* I number of end snapshots to plot */
|
||
{
|
||
SYD_PL_SLAVE *pSlave; /* pointer to individual slave struct */
|
||
PPR_AREA *pArea;
|
||
int i;
|
||
SYD_SPEC *pSspec;
|
||
SYD_CHAN *pSChan;
|
||
double oldX, oldY, newX, newY, err;
|
||
|
||
assert(pMstr != NULL);
|
||
pSspec = pMstr->pSspec;
|
||
assert(pSspec != NULL);
|
||
|
||
for (pSlave=pMstr->pHead; pSlave!=NULL; pSlave=pSlave->pNext) {
|
||
pArea = pSlave->pArea; pSChan = pSlave->pSChan;
|
||
for (i=begin; i<=end; i++) {
|
||
if (i == begin) {
|
||
oldX = i; oldY = pSChan->pStats[i].mean;
|
||
}
|
||
else {
|
||
newX = i; newY = pSChan->pStats[i].mean;
|
||
if (pMstr->linePlot)
|
||
pprLineSegD(pArea, oldX, oldY, newX, newY);
|
||
oldX = newX; oldY = newY;
|
||
}
|
||
if (pMstr->markPlot)
|
||
pprMarkD(pArea, oldX, oldY, pSlave->markNum);
|
||
else
|
||
pprPointD(pArea, oldX, oldY);
|
||
if (pMstr->errBar == SYD_PLATTR_STDDEV) {
|
||
err = pSChan->pStats[i].stdDev;
|
||
pprErrorBar(pArea, oldX, oldY-err, oldX, oldY+err);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/*+/internal******************************************************************
|
||
* NAME sydPlot_Yarray - plot array vs array
|
||
*
|
||
* NOTES
|
||
* 1. This routine isn't intended to be called directly.
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
static void
|
||
sydPlot_Yarray(pArea, pSChan, sub)
|
||
PPR_AREA *pArea;
|
||
SYD_CHAN *pSChan;
|
||
int sub;
|
||
{
|
||
int nEl, nElY, i;
|
||
char *pSrcY;
|
||
double newX, newY, oldX, oldY;
|
||
int nByteY;
|
||
|
||
nEl = nElY = pSChan->elCount;
|
||
nByteY = dbr_value_size[pSChan->dbrType];
|
||
pSrcY = (char *)pSChan->pData + sub * nByteY * nElY;
|
||
if (dbr_type_is_FLOAT(pSChan->dbrType))
|
||
pprWaveF(pArea, 1., (float *)pSrcY, nEl);
|
||
else if (dbr_type_is_SHORT(pSChan->dbrType))
|
||
pprWaveS(pArea, 1, (short *)pSrcY, nEl);
|
||
else if (dbr_type_is_DOUBLE(pSChan->dbrType))
|
||
pprWaveD(pArea, 1., (double *)pSrcY, nEl);
|
||
else if (dbr_type_is_LONG(pSChan->dbrType))
|
||
pprWaveL(pArea, 1, (long *)pSrcY, nEl);
|
||
else if (dbr_type_is_ENUM(pSChan->dbrType))
|
||
pprWaveS(pArea, 1, (short *)pSrcY, nEl);
|
||
else if (dbr_type_is_CHAR(pSChan->dbrType)) {
|
||
for (i=0; i<nEl; i++) {
|
||
newX = i;
|
||
newY = *(unsigned char *)pSrcY;
|
||
if (i > 0)
|
||
pprLineSegD(pArea, oldX, oldY, newX, newY);
|
||
oldX = newX;
|
||
oldY = newY;
|
||
pSrcY += nByteY;
|
||
}
|
||
}
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlot_YYPlot - handle multiple Y plots
|
||
*
|
||
* DESCRIPTION
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* BUGS
|
||
* o text
|
||
*
|
||
* SEE ALSO
|
||
*
|
||
* NOTES
|
||
* 1. This routine isn't intended to be called directly.
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlot_YYPlot(pMstr)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
{
|
||
SYD_SPEC *pSspec;
|
||
|
||
assert(pMstr != NULL);
|
||
pSspec = pMstr->pSspec;
|
||
assert(pSspec != NULL);
|
||
|
||
sydPlot_YYGrid(pMstr);
|
||
if (pSspec->useStats == 0) {
|
||
sydPlot_YSamples(pMstr,
|
||
pSspec->restrictFirstData, pSspec->restrictLastData, 0);
|
||
}
|
||
else
|
||
sydPlot_YStats(pMstr, 0, pSspec->statCount-1);
|
||
}
|
||
|
||
/*+/subr**********************************************************************
|
||
* NAME sydPlot_YYGrid - draw a grid for a multiple Y plot
|
||
*
|
||
* DESCRIPTION
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
* BUGS
|
||
* o text
|
||
*
|
||
* SEE ALSO
|
||
*
|
||
* NOTES
|
||
* 1. This routine isn't intended to be called directly.
|
||
*
|
||
* EXAMPLE
|
||
*
|
||
*-*/
|
||
void
|
||
sydPlot_YYGrid(pMstr)
|
||
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
|
||
{
|
||
PPR_WIN *pWin; /* pointer to plot window structure */
|
||
SYD_PL_SLAVE *pSlave; /* pointer to individual slave struct */
|
||
double xlo, ylo, xhi, yhi, yPart;
|
||
PPR_AREA *pArea;
|
||
double xmin, xmax, ymin, ymax;
|
||
int xNint;
|
||
double charHt, charHtX, charHtTY, charHtTX;
|
||
SYD_CHAN *pSChan;
|
||
int offsetAnnotY=0;
|
||
int drawAxis=0;
|
||
int thick=3;
|
||
int nGrids;
|
||
|
||
pWin = pMstr->pWin;
|
||
|
||
nGrids = 1;
|
||
sydPlot_setup(pMstr, nGrids, &xlo, &ylo, &xhi, &yhi, &yPart,
|
||
&charHt, &charHtX, &charHtTY, &charHtTX);
|
||
xlo += 6. * charHtX * (double)pMstr->nSlaves;
|
||
|
||
xmin = xmax = 0.;
|
||
pSlave = pMstr->pHead;
|
||
while (pSlave != NULL) {
|
||
if (pSlave->pSChan->elCount > xmax)
|
||
xmax = pSlave->pSChan->elCount;
|
||
pSlave = pSlave->pNext;
|
||
}
|
||
xNint = 1;
|
||
if (xmax == 1.)
|
||
xmax = pMstr->pSspec->reqCount - 1;
|
||
|
||
pSlave = pMstr->pHead;
|
||
while (pSlave != NULL) {
|
||
/*-----------------------------------------------------------------------------
|
||
* for the first channel:
|
||
* initialize a plot area; its fractional size depends on how many
|
||
* "sub-plots" there are
|
||
* plot a perimeter with grid lines
|
||
* for the other channels:
|
||
* initialize an overlapping plot area
|
||
* set a dashed line pattern (unless this is a mark or point plot)
|
||
* draw a "floating" Y axis
|
||
*----------------------------------------------------------------------------*/
|
||
pSChan = pSlave->pSChan;
|
||
ymin = pSlave->originVal;
|
||
ymax = pSlave->extentVal;
|
||
if (pSlave->pArea != NULL)
|
||
pprAreaClose(pSlave->pArea);
|
||
pArea = pSlave->pArea = pprAreaOpen(pWin, xlo, ylo+2.*charHt, xhi, yhi,
|
||
xmin, ymin, xmax, ymax, xNint, pSlave->nInt, charHt);
|
||
assertAlways(pArea != NULL);
|
||
pSlave->xFracLeft = xlo;
|
||
pSlave->xFracRight = xhi;
|
||
pSlave->yFracBot = ylo;
|
||
pSlave->yFracTop = yhi;
|
||
if (pSlave->fg != 0 && pMstr->noColor == 0)
|
||
pprAreaSetAttr(pSlave->pArea, PPR_ATTR_FG, 0, &pSlave->fg);
|
||
else if (pMstr->linePlot) {
|
||
if (dbr_type_is_ENUM(pSChan->dbrType))
|
||
pprAreaSetAttr(pArea, PPR_ATTR_LINE_THICK, thick, NULL);
|
||
if (pSlave->lineKey > 1 || pMstr->noColor == 0)
|
||
pprAreaSetAttr(pArea, PPR_ATTR_KEYNUM, pSlave->lineKey, NULL);
|
||
}
|
||
else if (pMstr->noColor == 0)
|
||
pprAreaSetAttr(pArea, PPR_ATTR_COLORNUM, pSlave->lineKey, NULL);
|
||
if (drawAxis == 0) {
|
||
pprGrid(pArea);
|
||
pArea->charHt = charHtTY * pWin->height;
|
||
pprAnnotX_wc(pArea, 0, xmin, xmax, xNint, 0, "bin number", NULL,0.);
|
||
pArea->charHt = charHt * pWin->height;
|
||
}
|
||
pprAnnotY(pArea, offsetAnnotY, pSlave->originVal, pSlave->extentVal,
|
||
pSlave->nInt, drawAxis,
|
||
pSlave->pSChan->label, pSlave->ppAnnot, 90.);
|
||
if (pMstr->markPlot)
|
||
pprAnnotYMark(pArea, offsetAnnotY, pSlave->markNum);
|
||
offsetAnnotY += 6;
|
||
drawAxis = 1; /* draw an "auxiliary" axis next time */
|
||
pSlave->annotXFL = xlo - offsetAnnotY * charHtX;
|
||
pSlave->annotXFR = pSlave->annotXFL + 6. * charHtX;
|
||
pSlave->annotYFB = ylo;
|
||
pSlave->annotYFT = yhi;
|
||
pSlave = pSlave->pNext;
|
||
}
|
||
}
|