Date: 2022-08-02T03:13:19+00:00

Actual source code: dscatter.c

      1: /*
      2:        Contains the data structure for drawing scatter plots
      3:     graphs in a window with an axis. This is intended for scatter
      4:     plots that change dynamically.
      5: */

      7: #include <petscdraw.h>
      8: #include <petsc/private/drawimpl.h>

     10: PetscClassId PETSC_DRAWSP_CLASSID = 0;

     12: /*@C
     13:     PetscDrawSPCreate - Creates a scatter plot data structure.

     15:     Collective on PetscDraw

     17:     Input Parameters:
     18: +   win - the window where the graph will be made.
     19: -   dim - the number of sets of points which will be drawn

     21:     Output Parameters:
     22: .   drawsp - the scatter plot context

     24:    Level: intermediate

     26:    Notes:
     27:     Add points to the plot with PetscDrawSPAddPoint() or PetscDrawSPAddPoints(); the new points are not displayed until PetscDrawSPDraw() is called.

     29:    PetscDrawSPReset() removes all the points that have been added

     31:    The MPI communicator that owns the PetscDraw owns this PetscDrawSP, but the calls to set options and add points are ignored on all processes except the
     32:    zeroth MPI process in the communicator. All MPI processes in the communicator must call PetscDrawSPDraw() to display the updated graph.

     34: .seealso:  PetscDrawLGCreate(), PetscDrawLG, PetscDrawBarCreate(), PetscDrawBar, PetscDrawHGCreate(), PetscDrawHG, PetscDrawSPDestroy(), PetscDraw, PetscDrawSP, PetscDrawSPSetDimension(), PetscDrawSPReset(),
     35:            PetscDrawSPAddPoint(), PetscDrawSPAddPoints(), PetscDrawSPDraw(), PetscDrawSPSave(), PetscDrawSPSetLimits(), PetscDrawSPGetAxis(),PetscDrawAxis, PetscDrawSPGetDraw()
     36: @*/
     37: PetscErrorCode  PetscDrawSPCreate(PetscDraw draw,int dim,PetscDrawSP *drawsp)
     38: {
     39:   PetscDrawSP    sp;

     45:   PetscHeaderCreate(sp,PETSC_DRAWSP_CLASSID,"DrawSP","Scatter Plot","Draw",PetscObjectComm((PetscObject)draw),PetscDrawSPDestroy,NULL);
     46:   PetscLogObjectParent((PetscObject)draw,(PetscObject)sp);

     48:   PetscObjectReference((PetscObject)draw);
     49:   sp->win = draw;

     51:   sp->view      = NULL;
     52:   sp->destroy   = NULL;
     53:   sp->nopts     = 0;
     54:   sp->dim       = dim;
     55:   sp->xmin      = 1.e20;
     56:   sp->ymin      = 1.e20;
     57:   sp->xmax      = -1.e20;
     58:   sp->ymax      = -1.e20;
     59:   sp->zmax      = 1.;
     60:   sp->zmin      = 1.e20;
     61:   sp->colorized = PETSC_FALSE;

     63:   PetscMalloc3(dim*PETSC_DRAW_SP_CHUNK_SIZE,&sp->x,dim*PETSC_DRAW_SP_CHUNK_SIZE,&sp->y,dim*PETSC_DRAW_SP_CHUNK_SIZE,&sp->z);
     64:   PetscLogObjectMemory((PetscObject)sp,2*dim*PETSC_DRAW_SP_CHUNK_SIZE*sizeof(PetscReal));

     66:   sp->len     = dim*PETSC_DRAW_SP_CHUNK_SIZE;
     67:   sp->loc     = 0;

     69:   PetscDrawAxisCreate(draw,&sp->axis);
     70:   PetscLogObjectParent((PetscObject)sp,(PetscObject)sp->axis);

     72:   *drawsp = sp;
     73:   return 0;
     74: }

     76: /*@
     77:    PetscDrawSPSetDimension - Change the number of sets of points  that are to be drawn.

     79:    Logically Collective on PetscDrawSP

     81:    Input Parameters:
     82: +  sp - the line graph context.
     83: -  dim - the number of curves.

     85:    Level: intermediate

     87: .seealso: PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPAddPoint(), PetscDrawSPAddPoints()

     89: @*/
     90: PetscErrorCode  PetscDrawSPSetDimension(PetscDrawSP sp,int dim)
     91: {
     94:   if (sp->dim == dim) return 0;

     96:   PetscFree2(sp->x,sp->y);
     97:   sp->dim = dim;
     98:   PetscMalloc2(dim*PETSC_DRAW_SP_CHUNK_SIZE,&sp->x,dim*PETSC_DRAW_SP_CHUNK_SIZE,&sp->y);
     99:   PetscLogObjectMemory((PetscObject)sp,2*dim*PETSC_DRAW_SP_CHUNK_SIZE*sizeof(PetscReal));
    100:   sp->len = dim*PETSC_DRAW_SP_CHUNK_SIZE;
    101:   return 0;
    102: }

    104: /*@
    105:    PetscDrawSPReset - Clears line graph to allow for reuse with new data.

    107:    Logically Collective on PetscDrawSP

    109:    Input Parameter:
    110: .  sp - the line graph context.

    112:    Level: intermediate

    114: .seealso: PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPAddPoint(), PetscDrawSPAddPoints(), PetscDrawSPDraw()
    115: @*/
    116: PetscErrorCode  PetscDrawSPReset(PetscDrawSP sp)
    117: {
    119:   sp->xmin  = 1.e20;
    120:   sp->ymin  = 1.e20;
    121:   sp->zmin  = 1.e20;
    122:   sp->xmax  = -1.e20;
    123:   sp->ymax  = -1.e20;
    124:   sp->zmax  = -1.e20;
    125:   sp->loc   = 0;
    126:   sp->nopts = 0;
    127:   return 0;
    128: }

    130: /*@C
    131:    PetscDrawSPDestroy - Frees all space taken up by scatter plot data structure.

    133:    Collective on PetscDrawSP

    135:    Input Parameter:
    136: .  sp - the line graph context

    138:    Level: intermediate

    140: .seealso:  PetscDrawSPCreate(), PetscDrawSP, PetscDrawSPReset()

    142: @*/
    143: PetscErrorCode  PetscDrawSPDestroy(PetscDrawSP *sp)
    144: {
    145:   if (!*sp) return 0;
    147:   if (--((PetscObject)(*sp))->refct > 0) {*sp = NULL; return 0;}

    149:   PetscFree3((*sp)->x,(*sp)->y,(*sp)->z);
    150:   PetscDrawAxisDestroy(&(*sp)->axis);
    151:   PetscDrawDestroy(&(*sp)->win);
    152:   PetscHeaderDestroy(sp);
    153:   return 0;
    154: }

    156: /*@
    157:    PetscDrawSPAddPoint - Adds another point to each of the scatter plots.

    159:    Logically Collective on PetscDrawSP

    161:    Input Parameters:
    162: +  sp - the scatter plot data structure
    163: -  x, y - two arrays of length dim containing the new x and y coordinate values for each of the curves. Here  dim is the number of curves passed to PetscDrawSPCreate()

    165:    Level: intermediate

    167:    Notes:
    168:     the new points will not be displayed until a call to PetscDrawSPDraw() is made

    170: .seealso: PetscDrawSPAddPoints(), PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPReset(), PetscDrawSPDraw(), PetscDrawSPAddPointColorized()

    172: @*/
    173: PetscErrorCode  PetscDrawSPAddPoint(PetscDrawSP sp,PetscReal *x,PetscReal *y)
    174: {
    175:   PetscInt       i;

    179:   if (sp->loc+sp->dim >= sp->len) { /* allocate more space */
    180:     PetscReal *tmpx,*tmpy;
    181:     PetscMalloc2(sp->len+sp->dim*PETSC_DRAW_SP_CHUNK_SIZE,&tmpx,sp->len+sp->dim*PETSC_DRAW_SP_CHUNK_SIZE,&tmpy);
    182:     PetscLogObjectMemory((PetscObject)sp,2*sp->dim*PETSC_DRAW_SP_CHUNK_SIZE*sizeof(PetscReal));
    183:     PetscArraycpy(tmpx,sp->x,sp->len);
    184:     PetscArraycpy(tmpy,sp->y,sp->len);
    185:     PetscFree2(sp->x,sp->y);
    186:     sp->x    = tmpx;
    187:     sp->y    = tmpy;
    188:     sp->len += sp->dim*PETSC_DRAW_SP_CHUNK_SIZE;
    189:   }
    190:   for (i=0; i<sp->dim; i++) {
    191:     if (x[i] > sp->xmax) sp->xmax = x[i];
    192:     if (x[i] < sp->xmin) sp->xmin = x[i];
    193:     if (y[i] > sp->ymax) sp->ymax = y[i];
    194:     if (y[i] < sp->ymin) sp->ymin = y[i];

    196:     sp->x[sp->loc]   = x[i];
    197:     sp->y[sp->loc++] = y[i];
    198:   }
    199:   sp->nopts++;
    200:   return 0;
    201: }

    203: /*@C
    204:    PetscDrawSPAddPoints - Adds several points to each of the scatter plots.

    206:    Logically Collective on PetscDrawSP

    208:    Input Parameters:
    209: +  sp - the LineGraph data structure
    210: .  xx,yy - points to two arrays of pointers that point to arrays
    211:            containing the new x and y points for each curve.
    212: -  n - number of points being added

    214:    Level: intermediate

    216:    Notes:
    217:     the new points will not be displayed until a call to PetscDrawSPDraw() is made

    219: .seealso: PetscDrawSPAddPoint(), PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPReset(), PetscDrawSPDraw(), PetscDrawSPAddPointColorized()
    220: @*/
    221: PetscErrorCode  PetscDrawSPAddPoints(PetscDrawSP sp,int n,PetscReal **xx,PetscReal **yy)
    222: {
    223:   PetscInt       i,j,k;
    224:   PetscReal      *x,*y;

    228:   if (sp->loc+n*sp->dim >= sp->len) { /* allocate more space */
    229:     PetscReal *tmpx,*tmpy;
    230:     PetscInt  chunk = PETSC_DRAW_SP_CHUNK_SIZE;
    231:     if (n > chunk) chunk = n;
    232:     PetscMalloc2(sp->len+sp->dim*chunk,&tmpx,sp->len+sp->dim*chunk,&tmpy);
    233:     PetscLogObjectMemory((PetscObject)sp,2*sp->dim*PETSC_DRAW_SP_CHUNK_SIZE*sizeof(PetscReal));
    234:     PetscArraycpy(tmpx,sp->x,sp->len);
    235:     PetscArraycpy(tmpy,sp->y,sp->len);
    236:     PetscFree2(sp->x,sp->y);

    238:     sp->x    = tmpx;
    239:     sp->y    = tmpy;
    240:     sp->len += sp->dim*PETSC_DRAW_SP_CHUNK_SIZE;
    241:   }
    242:   for (j=0; j<sp->dim; j++) {
    243:     x = xx[j]; y = yy[j];
    244:     k = sp->loc + j;
    245:     for (i=0; i<n; i++) {
    246:       if (x[i] > sp->xmax) sp->xmax = x[i];
    247:       if (x[i] < sp->xmin) sp->xmin = x[i];
    248:       if (y[i] > sp->ymax) sp->ymax = y[i];
    249:       if (y[i] < sp->ymin) sp->ymin = y[i];

    251:       sp->x[k] = x[i];
    252:       sp->y[k] = y[i];
    253:       k       += sp->dim;
    254:     }
    255:   }
    256:   sp->loc   += n*sp->dim;
    257:   sp->nopts += n;
    258:   return 0;
    259: }

    261: /*@
    262:    PetscDrawSPAddPointColorized - Adds another point to each of the scatter plots as well as a numeric value to be used to colorize the scatter point.

    264:    Logically Collective on PetscDrawSP

    266:    Input Parameters:
    267: +  sp - the scatter plot data structure
    268: . x, y - two arrays of length dim containing the new x and y coordinate values for each of the curves. Here  dim is the number of curves passed to PetscDrawSPCreate()
    269: - z - array of length dim containing the numeric values that will be mapped to [0,255] and used for scatter point colors.

    271:    Level: intermediate

    273:    Notes:
    274:     the new points will not be displayed until a call to PetscDrawSPDraw() is made

    276: .seealso: PetscDrawSPAddPoints(), PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPReset(), PetscDrawSPDraw(), PetscDrawSPAddPoint()

    278: @*/
    279: PetscErrorCode  PetscDrawSPAddPointColorized(PetscDrawSP sp,PetscReal *x,PetscReal *y,PetscReal *z)
    280: {
    281:   PetscInt       i;

    284:   sp->colorized = PETSC_TRUE;
    285:   if (sp->loc+sp->dim >= sp->len) { /* allocate more space */
    286:     PetscReal *tmpx,*tmpy,*tmpz;
    287:     PetscMalloc3(sp->len+sp->dim*PETSC_DRAW_SP_CHUNK_SIZE,&tmpx,sp->len+sp->dim*PETSC_DRAW_SP_CHUNK_SIZE,&tmpy,sp->len+sp->dim*PETSC_DRAW_SP_CHUNK_SIZE,&tmpz);
    288:     PetscLogObjectMemory((PetscObject)sp,2*sp->dim*PETSC_DRAW_SP_CHUNK_SIZE*sizeof(PetscReal));
    289:     PetscArraycpy(tmpx,sp->x,sp->len);
    290:     PetscArraycpy(tmpy,sp->y,sp->len);
    291:     PetscArraycpy(tmpz,sp->z,sp->len);
    292:     PetscFree3(sp->x,sp->y,sp->z);
    293:     sp->x    = tmpx;
    294:     sp->y    = tmpy;
    295:     sp->z    = tmpz;
    296:     sp->len += sp->dim*PETSC_DRAW_SP_CHUNK_SIZE;
    297:   }
    298:   for (i=0; i<sp->dim; i++) {
    299:     if (x[i] > sp->xmax) sp->xmax = x[i];
    300:     if (x[i] < sp->xmin) sp->xmin = x[i];
    301:     if (y[i] > sp->ymax) sp->ymax = y[i];
    302:     if (y[i] < sp->ymin) sp->ymin = y[i];
    303:     if (z[i] < sp->zmin) sp->zmin = z[i];
    304:     if (z[i] > sp->zmax) sp->zmax = z[i];
    305:     // if (z[i] > sp->zmax && z[i] < 5.) sp->zmax = z[i];

    307:     sp->x[sp->loc]   = x[i];
    308:     sp->y[sp->loc]   = y[i];
    309:     sp->z[sp->loc++] = z[i];
    310:   }
    311:   sp->nopts++;
    312:   return 0;
    313: }

    315: /*@
    316:    PetscDrawSPDraw - Redraws a scatter plot.

    318:    Collective on PetscDrawSP

    320:    Input Parameters:
    321: +  sp - the line graph context
    322: -  clear - clear the window before drawing the new plot

    324:    Level: intermediate

    326: .seealso: PetscDrawLGDraw(), PetscDrawLGSPDraw(), PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPReset(), PetscDrawSPAddPoint(), PetscDrawSPAddPoints()

    328: @*/
    329: PetscErrorCode  PetscDrawSPDraw(PetscDrawSP sp, PetscBool clear)
    330: {
    331:   PetscReal      xmin,xmax,ymin,ymax;
    332:   PetscMPIInt    rank;
    333:   PetscInt       color;
    334:   PetscBool      isnull;
    335:   PetscDraw      draw;

    339:   PetscDrawIsNull(sp->win,&isnull);
    340:   if (isnull) return 0;
    341:   MPI_Comm_rank(PetscObjectComm((PetscObject)sp),&rank);

    343:   if (sp->xmin > sp->xmax || sp->ymin > sp->ymax) return 0;
    344:   if (sp->nopts < 1) return 0;

    346:   draw = sp->win;
    347:   if (clear) {
    348:     PetscDrawCheckResizedWindow(draw);
    349:     PetscDrawClear(draw);
    350:   }

    352:   xmin = sp->xmin; xmax = sp->xmax; ymin = sp->ymin; ymax = sp->ymax;
    353:   PetscDrawAxisSetLimits(sp->axis,xmin,xmax,ymin,ymax);
    354:   PetscDrawAxisDraw(sp->axis);

    356:   PetscDrawCollectiveBegin(draw);
    357:   if (rank == 0) {
    358:     int i,j,dim=sp->dim,nopts=sp->nopts;
    359:     for (i=0; i<dim; i++) {
    360:       for (j=0; j<nopts; j++) {
    361:         if (sp->colorized) {
    362:           color = PetscDrawRealToColor(sp->z[j*dim],sp->zmin,sp->zmax);
    363:           PetscDrawPoint(draw,sp->x[j*dim+i],sp->y[j*dim+i],color);
    364:         } else {
    365:           PetscDrawPoint(draw,sp->x[j*dim+i],sp->y[j*dim+i],PETSC_DRAW_RED);
    366:         }
    367:       }
    368:     }
    369:   }
    370:   PetscDrawCollectiveEnd(draw);

    372:   PetscDrawFlush(draw);
    373:   PetscDrawPause(draw);
    374:   return 0;
    375: }

    377: /*@
    378:    PetscDrawSPSave - Saves a drawn image

    380:    Collective on PetscDrawSP

    382:    Input Parameter:
    383: .  sp - the scatter plot context

    385:    Level: intermediate

    387: .seealso:  PetscDrawSPCreate(), PetscDrawSPGetDraw(), PetscDrawSetSave(), PetscDrawSave()
    388: @*/
    389: PetscErrorCode  PetscDrawSPSave(PetscDrawSP sp)
    390: {
    392:   PetscDrawSave(sp->win);
    393:   return 0;
    394: }

    396: /*@
    397:    PetscDrawSPSetLimits - Sets the axis limits for a scatter plot If more
    398:    points are added after this call, the limits will be adjusted to
    399:    include those additional points.

    401:    Logically Collective on PetscDrawSP

    403:    Input Parameters:
    404: +  xsp - the line graph context
    405: -  x_min,x_max,y_min,y_max - the limits

    407:    Level: intermediate

    409: .seealso: PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPDraw(), PetscDrawSPAddPoint(), PetscDrawSPAddPoints(), PetscDrawSPGetAxis()
    410: @*/
    411: PetscErrorCode  PetscDrawSPSetLimits(PetscDrawSP sp,PetscReal x_min,PetscReal x_max,PetscReal y_min,PetscReal y_max)
    412: {
    414:   sp->xmin = x_min;
    415:   sp->xmax = x_max;
    416:   sp->ymin = y_min;
    417:   sp->ymax = y_max;
    418:   return 0;
    419: }

    421: /*@C
    422:    PetscDrawSPGetAxis - Gets the axis context associated with a line graph.
    423:    This is useful if one wants to change some axis property, such as
    424:    labels, color, etc. The axis context should not be destroyed by the
    425:    application code.

    427:    Not Collective, if PetscDrawSP is parallel then PetscDrawAxis is parallel

    429:    Input Parameter:
    430: .  sp - the line graph context

    432:    Output Parameter:
    433: .  axis - the axis context

    435:    Level: intermediate

    437: .seealso: PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPDraw(), PetscDrawSPAddPoint(), PetscDrawSPAddPoints(), PetscDrawAxis, PetscDrawAxisCreate()

    439: @*/
    440: PetscErrorCode  PetscDrawSPGetAxis(PetscDrawSP sp,PetscDrawAxis *axis)
    441: {
    444:   *axis = sp->axis;
    445:   return 0;
    446: }

    448: /*@C
    449:    PetscDrawSPGetDraw - Gets the draw context associated with a line graph.

    451:    Not Collective, PetscDraw is parallel if PetscDrawSP is parallel

    453:    Input Parameter:
    454: .  sp - the line graph context

    456:    Output Parameter:
    457: .  draw - the draw context

    459:    Level: intermediate

    461: .seealso: PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPDraw(), PetscDraw
    462: @*/
    463: PetscErrorCode  PetscDrawSPGetDraw(PetscDrawSP sp,PetscDraw *draw)
    464: {
    467:   *draw = sp->win;
    468:   return 0;
    469: }