Files
pcas/src/util/sydPlot.c
1991-05-03 11:33:33 +00:00

2467 lines
65 KiB
C
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* $Id$
* Author: Roger A. Cole
* Date: 12-04-90
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991, 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 mm-dd-yy rac version 2.0, installed in SCCS
*
* make options
* -DXWINDOWS makes a version for X11
* -DNDEBUG don't compile assert() checking
* -DDEBUG compile various debug code, including checks on
* malloc'd memory
*/
/*+/mod***********************************************************************
* TITLE sydPlot.c - plotting for synchronous data
*
* DESCRIPTION
*
* QUICK REFERENCE
*
* void sydPlotAxisAutoRange(pSlave)
* long sydPlotAxisSetAttr(pSlave, attr, value, pArg)
* attr = SYD_PLATTR_{GC}
* SYD_PL_SLAVE *sydPlotChanAdd(pMstr, pSChan)
* 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,LINE,MARK,MONO,POINT,SHOW,UNDER,WRAP}
* long sydPlotSetTitles(pMstr, top, left, bottom, right)
* long sydPlotWinLoop(pMstr)
* long sydPlotWinReplot(pMstr)
* BUGS
* o sydPlotInitUW doesn't support SUNVIEW
*
*-***************************************************************************/
#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
/*+/subr**********************************************************************
* NAME sydPlotAxisAutoRange - set axis ends to min and max data values
*
* DESCRIPTION
*
* RETURNS
*
* BUGS
* o text
*
* SEE ALSO
*
* EXAMPLE
*
*-*/
void
sydPlotAxisAutoRange(pSlave)
SYD_PL_SLAVE *pSlave;
{
pSlave->originVal = pSlave->pSChan->minDataVal;
pSlave->extentVal = pSlave->pSChan->maxDataVal;
}
/*+/subr**********************************************************************
* NAME sydPlotAxisSetAttr - set plot axis attributes
*
* DESCRIPTION
* Setting an attribute doesn't automatically reset other related
* attributes.
*
* sydPlotAxisSetAttr(pSlave, SYD_PLATTR_XCHAN, {0,1}, NULL)
* 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
*
* RETURNS
* void
*
* BUGS
* o text
*
* SEE ALSO
*
* EXAMPLE
*
*-*/
void
sydPlotAxisSetup(pSlave)
SYD_PL_SLAVE *pSlave;
{
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;
}
/*+/subr**********************************************************************
* NAME sydPlotChanAdd - add a 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; /* IO pointer to plot master */
SYD_CHAN *pSChan; /* I pointer to synchronous data channel structure */
{
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 *)GenMalloc(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->timeLabel[0] = '\0';
pSlave->xChan = 0;
pSlave->pArea = NULL;
pSlave->fg = 0;
pSlave->bg = 0;
pSlave->first = 1;
pSlave->xFracLeft = 0.;
pSlave->yFracBot = 0.;
pSlave->xFracRight = 0.;
pSlave->yFracTop = 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;
(void)sprintf(pSlave->timeLabel, "sec past %s", pMstr->refText);
return pSlave;
}
/*+/subr**********************************************************************
* NAME sydPlotDone - multiple x vs y rundown
*
* DESCRIPTION
*
* RETURNS
* S_syd_OK
*
* BUGS
* o text
*
* 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;
GenFree((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
*
* RETURNS
* S_syd_OK
*
* BUGS
* o text
*
* 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) {
pprAreaErase(pSlave->pArea, 1., 1., -1., -1.);
}
pSlave = pSlave->pNext;
}
return S_syd_OK;
}
static void sydPlotInit_common();
/*+/subr**********************************************************************
* NAME sydPlotInit - plotting initialization
*
* DESCRIPTION
* use sydPlotWinLoop for actual plotting
* `fullInit' results in initializing for a default window size and
* position. If fullInit is zero, then the size and position
* in the plot master are used.
*
* RETURNS
* S_syd_OK
*
* BUGS
* o need an sdrXxx call to initialize a master with caller-supplied
* or default size and position
*
* SEE ALSO
*
* EXAMPLE
*
*-*/
long
sydPlotInit(pMstr, pSspec, winType, dispName, winTitle, fullInit)
SYD_PL_MSTR *pMstr; /* IO 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 */
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);
assertAlways(pMstr->pWin != NULL);
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);
assertAlways(pMstr->pWin != NULL);
}
pMstr->winType = winType;
pMstr->plotAxis = SYD_PLAX_UNDEF;
pMstr->pSspec = pSspec;
sydPlotInit_common(pMstr);
return S_syd_OK;
}
static void
sydPlotInit_common(pMstr)
SYD_PL_MSTR *pMstr;
{
pMstr->linePlot = 1;
pMstr->pointPlot = 0;
pMstr->markPlot = 0;
pMstr->showStat = 0;
pMstr->fillUnder = 0;
if (pprWinIsMono(pMstr->pWin))
pMstr->noColor = 1;
else
pMstr->noColor = 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->refText[0] = '\0';
pMstr->pHead = NULL;
pMstr->pTail = NULL;
pMstr->nSlaves = 0;
pMstr->originVal = 0.;
pMstr->extentVal = 0.;
pMstr->wrapX = 0;
if (pMstr->pSspec->sampleCount >= 1) {
pMstr->extentVal =
pMstr->pSspec->pDeltaSec[pMstr->pSspec->sampleCount-1];
}
}
#ifdef XWINDOWS
/*+/subr**********************************************************************
* NAME sydPlotInitUW - plotting initialization, using User Window
*
* DESCRIPTION
* use sydPlotWinReplot for actual plotting
* sydPlotSamples can be used for incremental plotting
*
* RETURNS
* S_syd_OK
*
* BUGS
* o text
*
* SEE ALSO
*
* EXAMPLE
*
*-*/
long
sydPlotInitUW(pMstr, pSspec, pDisp, window, gc)
SYD_PL_MSTR *pMstr; /* IO 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);
pMstr->pDisp = pDisp;
pMstr->window = window;
return S_syd_OK;
}
#endif XWINDOWS
/*+/subr**********************************************************************
* NAME sydPlotSamples - plot one or more sync samples
*
* DESCRIPTION
*
* RETURNS
* void
*
* BUGS
* o text
*
* SEE ALSO
*
* 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_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_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_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 text
*
* SEE ALSO
*
* 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 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
*
* 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 sydPlotWinLoop - do the actual plotting
*
* DESCRIPTION
* for use with sydPlotInit
*
* RETURNS
* OK, or
* ERROR
*
* BUGS
* o text
*
* SEE ALSO
*
* EXAMPLE
*
*-*/
long
sydPlotWinLoop(pMstr)
SYD_PL_MSTR *pMstr; /* IO pointer to plot master structure */
{
SYD_PLAX pltTy = pMstr->plotAxis; /* type of plot desired */
long stat;
char refText[28];
int npts;
SYD_SPEC *pSspec = pMstr->pSspec;
npts = pSspec->sampleCount;
if (npts > 1 && pMstr->originVal != pMstr->extentVal) {
pprAutoEnds(pSspec->pDeltaSec[0], pSspec->pDeltaSec[npts-1],
&pMstr->originVal, &pMstr->extentVal);
pprAutoInterval(pMstr->originVal, pMstr->extentVal, &pMstr->nInt);
(void)tsStampToText(&pSspec->refTs, TS_TEXT_MMDDYY, refText);
(void)sprintf(pMstr->label, "sec past %s", refText);
(void)strcpy(pMstr->refText, refText);
}
else {
pMstr->originVal = 0.;
pMstr->extentVal = 100.;
strcpy(pMstr->label, "elapsed seconds");
pMstr->refText[0] = '\0';
pMstr->nInt = 5;
}
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
* for use with sydPlotInitUW
*
* RETURNS
* OK, or
* ERROR
*
* BUGS
* o text
*
* SEE ALSO
*
* EXAMPLE
*
*-*/
long
sydPlotWinReplot(pMstr)
SYD_PL_MSTR *pMstr; /* IO pointer to plot master structure */
{
char refText[28];
int npts;
SYD_SPEC *pSspec = pMstr->pSspec;
npts = pSspec->sampleCount;
if (npts > 1 && pMstr->originVal != pMstr->extentVal) {
pprAutoEnds(pSspec->pDeltaSec[0], pSspec->pDeltaSec[npts-1],
&pMstr->originVal, &pMstr->extentVal);
pprAutoInterval(pMstr->originVal, pMstr->extentVal, &pMstr->nInt);
(void)tsStampToText(&pSspec->refTs, TS_TEXT_MMDDYY, refText);
(void)sprintf(pMstr->label, "sec past %s", refText);
(void)strcpy(pMstr->refText, refText);
}
else {
pMstr->originVal = 0.;
pMstr->extentVal = 100.;
strcpy(pMstr->label, "elapsed seconds");
pMstr->refText[0] = '\0';
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
*
* RETURNS
*
* BUGS
* o text
*
* SEE ALSO
*
* 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_SMITH_IMP ||
pMstr->plotAxis == SYD_PLAX_SMITH_ADM ||
pMstr->plotAxis == SYD_PLAX_SMITH_IMM)
sydPlot_SmithPlot(pMstr);
else
assertAlways(0);
}
/*/subhead --------------------------------------------------------------------
*
*----------------------------------------------------------------------------*/
#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)) \
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)) \
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);
/*+/subr**********************************************************************
* 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. The caller is given the
* appropriate coordinates and sizes for the sub-plots.
*
* RETURNS
* void
*
* BUGS
* o handles only vertical subdividing of the plot window
*
*-*/
static void
sydPlot_setup(pMstr, nGrids, pXlo, pYlo, pXhi, pYhi, pYpart, pCh, pChX)
SYD_PL_MSTR *pMstr; /* I pointer to master plot structure */
double *pXlo, *pYlo, *pXhi, *pYhi, *pYpart, *pCh, *pChX;
int nGrids;
{
PPR_WIN *pWin; /* pointer to plot window structure */
double xlo, ylo, xhi, yhi, yPart, charHt, charHtX;
PPR_AREA *pArea;
TS_STAMP now;
char nowText[32];
pWin = pMstr->pWin;
xlo = 0.;
xhi = .98;
ylo = 0.;
yhi = .98;
charHt = .012;
charHtX = pprYFracToXFrac(pWin, charHt);
/*-----------------------------------------------------------------------------
* 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. - charHt;
pprText(pArea, .5, yhi, pMstr->title, PPR_TXT_CEN, charHt, 0.);
yhi -= 2. * charHt;
}
if (strlen(pMstr->lTitle) > 0) {
xlo = 2. * charHtX;
pprText(pArea, xlo, .5, pMstr->lTitle, PPR_TXT_CEN, charHt, 90.);
xlo += 2. * charHtX;
}
if (strlen(pMstr->bTitle) > 0) {
ylo = 2. * charHt;
pprText(pArea, .5, ylo, pMstr->bTitle, PPR_TXT_CEN, charHt, 0.);
ylo += 2. * charHt;
}
if (strlen(pMstr->rTitle) > 0) {
xhi = 1. - 2. * charHtX;
pprText(pArea, xhi, .5, pMstr->rTitle, PPR_TXT_CEN, charHt, 90.);
xhi -= 2. * charHtX;
}
pprAreaClose(pArea);
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;
}
/*+/subr**********************************************************************
* NAME sydPlot_SmithPlot - handle Smith Chart plots
*
* DESCRIPTION
*
* RETURNS
* void
*
* BUGS
* o text
*
* SEE ALSO
* sydPlot_SmithGrid, sydPlot_SmithSamples
*
* 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);
sydPlot_SmithSamples(pMstr, pSspec->firstData, pSspec->lastData, 0);
}
/*+/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
*
*-*/
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;
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);
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);
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
*
* 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_TYPlot - handle time vs Y plots
*
* DESCRIPTION
*
* RETURNS
* void
*
* BUGS
* o text
*
* SEE ALSO
*
* 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);
sydPlot_TYSamples(pMstr, pSspec->firstData, pSspec->lastData, 0);
}
/*+/subr**********************************************************************
* NAME sydPlot_TYGrid - draw a grid for a time vs Y plot
*
* 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
*
* 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;
int xNint;
double charHt, charHtX;
SYD_CHAN *pSChan;
TS_STAMP now;
char nowText[32];
int thick=3;
int nGrids;
pWin = pMstr->pWin;
nGrids = pMstr->nSlaves;
sydPlot_setup(pMstr, nGrids,
&xlo, &ylo, &xhi, &yhi, &yPart, &charHt, &charHtX);
xmin = pMstr->originVal;
xmax = pMstr->extentVal;
xNint = pMstr->nInt;
if (xmin == xmax) {
xmin = 0.;
xmax = 100.;
xNint = 5;
}
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->pArea != NULL)
pprAreaClose(pSlave->pArea);
pArea = pSlave->pArea = pprAreaOpen(pWin,
xlo+12.*charHtX, ylo+6.*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;
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);
}
pprGridLabel(pArea, pMstr->label, NULL,
pSlave->pSChan->label, pSlave->ppAnnot, 0.);
ylo += yPart;
yhi += yPart;
pSlave = pSlave->pNext;
}
}
/*+/subr**********************************************************************
* NAME sydPlot_TYSamples - plot one or more samples for a time vs Y plot
*
* DESCRIPTION
* the first channel in the plot spec is used for the X axis
*
* RETURNS
* void
*
* BUGS
* o text
*
* SEE ALSO
*
* 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;
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) {
if (pSChan->pFlags[i].missing)
skip = 1;
else if (first || skip || pSChan->pFlags[i].restart) {
oldX = pSspec->pDeltaSec[i];
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)
; /* no action */
else {
newX = pSspec->pDeltaSec[i];
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_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
*
* 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);
sydPlot_TYSamples(pMstr, pSspec->firstData, pSspec->lastData, 0);
}
/*+/subr**********************************************************************
* NAME sydPlot_TYYGrid - draw a grid for a time vs multiple Y plot
*
* DESCRIPTION
*
* RETURNS
* void
*
* BUGS
* o text
*
* SEE ALSO
*
* 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, yPart;
PPR_AREA *pArea;
double xmin, xmax, ymin, ymax;
int xNint;
double charHt, charHtX;
SYD_CHAN *pSChan;
TS_STAMP now;
char nowText[32];
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);
xlo += 6. * charHtX * (double)pMstr->nSlaves;
ylo += 6. * charHt;
xmin = pMstr->originVal;
xmax = pMstr->extentVal;
xNint = pMstr->nInt;
if (xmin == xmax) {
xmin = 0.;
xmax = 100.;
xNint = 5;
}
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, 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);
pprAnnotX_wc(pArea, 0,
xmin, xmax, xNint, 0, pMstr->label, NULL, 0.);
}
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 = pSlave->pNext;
}
}
/*+/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
*
* 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);
sydPlot_XYSamples(pMstr, pSspec->firstData, pSspec->lastData, 0);
}
/*+/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
*
* 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;
SYD_CHAN *pSChan;
SYD_CHAN *pSChanX;
int nGrids;
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);
pSlaveX->pArea = NULL;
pSChanX = pSlaveX->pSChan;
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->pArea != NULL)
pprAreaClose(pSlave->pArea);
pArea = pSlave->pArea = pprAreaOpen(pWin,
xlo+12.*charHtX, ylo+6.*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 + 6. * charHt;
pSlave->yFracTop = yhi;
if (pSlave->fg != 0 && pMstr->noColor == 0)
pprAreaSetAttr(pSlave->pArea, PPR_ATTR_FG, 0, &pSlave->fg);
pprGridLabel(pArea, pSlaveX->pSChan->label, NULL,
pSlave->pSChan->label, pSlave->ppAnnot, 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
*
* 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;
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) {
if (pSChan->pFlags[i].missing || pSChanX->pFlags[i].missing)
skip = 1;
else if (first || skip ||
pSChan->pFlags[i].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;
}
else if (pSChan->pFlags[i].filled)
; /* no action */
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;
}
}
/*+/internal******************************************************************
* NAME sydPlot_XYarray - plot array vs array
*
* DESCRIPTION
*
* RETURNS
*
* BUGS
* o text
*
* SEE ALSO
*
* 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
*
* 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);
sydPlot_XYSamples(pMstr, pSspec->firstData, pSspec->lastData, 0);
}
/*+/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
*
* 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;
SYD_CHAN *pSChan;
SYD_CHAN *pSChanX;
TS_STAMP now;
char nowText[32];
int offsetAnnotY=0;
int drawAxis=0;
int nGrids;
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);
xlo += 6. * charHtX * (double)(pMstr->nSlaves - 1);
ylo += 6. * charHt;
pSlaveX->pArea = NULL;
xmin = pSlaveX->originVal;
xmax = pSlaveX->extentVal;
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->pArea != NULL)
pprAreaClose(pSlave->pArea);
pArea = pSlave->pArea = pprAreaOpen(pWin, xlo, ylo, 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);
pprAnnotX_wc(pArea, 0, pSlaveX->originVal, pSlaveX->extentVal,
pSlaveX->nInt, 0, pSlaveX->pSChan->label, NULL, 0.);
}
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 = pSlave->pNext;
if (pSlave == pSlaveX)
pSlave = pSlave->pNext;
}
return;
}
/*+/subr**********************************************************************
* NAME sydPlot_YPlot - handle Y plots
*
* DESCRIPTION
*
* RETURNS
* void
*
* BUGS
* o text
*
* SEE ALSO
*
* 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);
sydPlot_YSamples(pMstr, pSspec->firstData, pSspec->lastData, 0);
}
/*+/subr**********************************************************************
* NAME sydPlot_YGrid - draw a grid for a Y plot
*
* DESCRIPTION
*
* RETURNS
* void
*
* BUGS
* o text
*
* SEE ALSO
*
* 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;
SYD_CHAN *pSChan;
TS_STAMP now;
char nowText[32];
int thick=3;
int nGrids;
pWin = pMstr->pWin;
nGrids = pMstr->nSlaves;
sydPlot_setup(pMstr, nGrids,
&xlo, &ylo, &xhi, &yhi, &yPart, &charHt, &charHtX);
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->pArea != NULL)
pprAreaClose(pSlave->pArea);
pArea = pSlave->pArea = pprAreaOpen(pWin,
xlo+12.*charHtX, ylo+6.*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;
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);
}
pprGridLabel(pArea, "", NULL,
pSlave->pSChan->label, pSlave->ppAnnot, 0.);
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
*
* 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;
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) {
if (pSChan->pFlags[i].missing)
skip = 1;
else if (first || skip || pSChan->pFlags[i].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)
; /* 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;
}
}
/*+/internal******************************************************************
* NAME sydPlot_Yarray - plot array vs array
*
* DESCRIPTION
*
* RETURNS
*
* BUGS
* o text
*
* SEE ALSO
*
* 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;
for (i=0; i<nEl; i++) {
newX = i;
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;
pSrcY += nByteY;
}
}
/*+/subr**********************************************************************
* NAME sydPlot_YYPlot - handle multiple Y plots
*
* DESCRIPTION
*
* RETURNS
* void
*
* BUGS
* o text
*
* SEE ALSO
*
* 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);
sydPlot_YSamples(pMstr, pSspec->firstData, pSspec->lastData, 0);
}
/*+/subr**********************************************************************
* NAME sydPlot_YYGrid - draw a grid for a multiple Y plot
*
* DESCRIPTION
*
* RETURNS
* void
*
* BUGS
* o text
*
* SEE ALSO
*
* 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;
SYD_CHAN *pSChan;
TS_STAMP now;
char nowText[32];
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);
xlo += 6. * charHtX * (double)pMstr->nSlaves;
ylo += 6. * charHt;
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, 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);
pprAnnotX_wc(pArea, 0, xmin, xmax, xNint, 0, "", NULL, 0.);
}
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 = pSlave->pNext;
}
}