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;
|
|
}
|
|
}
|