Actual source code: bars.c
petsc-3.7.1 2016-05-15
Report Typos and Errors

      2: /*
      3:   Contains the data structure for plotting a bargraph in a window with an axis.
      4: */
      5: #include <petscdraw.h>         /*I "petscdraw.h" I*/
      6: #include <petsc/private/petscimpl.h>         /*I "petscsys.h" I*/
      7: #include <petscviewer.h>         /*I "petscviewer.h" I*/
      8: #include <../src/sys/classes/draw/utils/axisimpl.h>   /* so we can directly modify axis xticks */

     10: PetscClassId PETSC_DRAWBAR_CLASSID = 0;

     12: struct _p_PetscDrawBar {
     13:   PETSCHEADER(int);
     14:   PetscErrorCode (*destroy)(PetscDrawSP);
     15:   PetscErrorCode (*view)(PetscDrawSP,PetscViewer);
     16:   PetscDraw      win;
     17:   PetscDrawAxis  axis;
     18:   PetscReal      ymin,ymax;
     19:   int            numBins;
     20:   PetscReal      *values;
     21:   int            color;
     22:   char           **labels;
     23:   PetscBool      sort;
     24:   PetscReal      sorttolerance;
     25: };

     27: #define CHUNKSIZE 100

     31: /*@C
     32:    PetscDrawBarCreate - Creates a bar graph data structure.

     34:    Collective over PetscDraw

     36:    Input Parameters:
     37: .  draw  - The window where the graph will be made

     39:    Output Parameters:
     40: .  bar - The bar graph context

     42:    Level: intermediate

     44:    Concepts: bar graph^creating

     46: .seealso: PetscDrawBarDestroy()

     48: @*/
     49: PetscErrorCode  PetscDrawBarCreate(PetscDraw draw,PetscDrawBar *bar)
     50: {
     51:   PetscDrawBar   h;

     58:   PetscHeaderCreate(h,PETSC_DRAWBAR_CLASSID,"DrawBar","Bar Graph","Draw",PetscObjectComm((PetscObject)draw),PetscDrawBarDestroy,NULL);
     59:   PetscLogObjectParent((PetscObject)draw,(PetscObject)h);

     61:   PetscObjectReference((PetscObject)draw);
     62:   h->win = draw;

     64:   h->view        = NULL;
     65:   h->destroy     = NULL;
     66:   h->color       = PETSC_DRAW_GREEN;
     67:   h->ymin        = 0.;  /* if user has not set these then they are determined from the data */
     68:   h->ymax        = 0.;
     69:   h->numBins     = 0;

     71:   PetscDrawAxisCreate(draw,&h->axis);
     72:   h->axis->xticks = NULL;

     74:   *bar = h;
     75:   return(0);
     76: }

     80: /*@C
     81:    PetscDrawBarSetData

     83:    Logically Collective on PetscDrawBar

     85:    Input Parameter:
     86: +  bar - The bar graph context.
     87: .  bins  - number of items
     88: .  values - values of each item
     89: -  labels - optional label for each bar, NULL terminated array of strings

     91:    Level: intermediate

     94: @*/
     95: PetscErrorCode  PetscDrawBarSetData(PetscDrawBar bar,PetscInt bins,const PetscReal data[],const char *const *labels)
     96: {

    102:   if (bar->numBins != bins) {
    103:     PetscFree(bar->values);
    104:     PetscMalloc1(bins, &bar->values);
    105:     bar->numBins = bins;
    106:   }
    107:   PetscMemcpy(bar->values,data,bins*sizeof(PetscReal));
    108:   bar->numBins = bins;
    109:   if (labels) {
    110:     PetscStrArrayallocpy(labels,&bar->labels);
    111:   }
    112:   return(0);
    113: }

    117: /*@C
    118:   PetscDrawBarDestroy - Frees all space taken up by bar graph data structure.

    120:   Collective over PetscDrawBar

    122:   Input Parameter:
    123: . bar - The bar graph context

    125:   Level: intermediate

    127: .seealso:  PetscDrawBarCreate()
    128: @*/
    129: PetscErrorCode  PetscDrawBarDestroy(PetscDrawBar *bar)
    130: {

    134:   if (!*bar) return(0);
    136:   if (--((PetscObject)(*bar))->refct > 0) return(0);

    138:   PetscFree((*bar)->values);
    139:   PetscStrArrayDestroy(&(*bar)->labels);
    140:   PetscDrawAxisDestroy(&(*bar)->axis);
    141:   PetscDrawDestroy(&(*bar)->win);
    142:   PetscHeaderDestroy(bar);
    143:   return(0);
    144: }

    148: /*@
    149:   PetscDrawBarDraw - Redraws a bar graph.

    151:   Collective on PetscDrawBar

    153:   Input Parameter:
    154: . bar - The bar graph context

    156:   Level: intermediate

    158: @*/
    159: PetscErrorCode  PetscDrawBarDraw(PetscDrawBar bar)
    160: {
    161:   PetscDraw      draw;
    162:   PetscBool      isnull;
    163:   PetscReal      xmin,xmax,ymin,ymax,*values,binLeft,binRight;
    164:   PetscInt       numValues,i,bcolor,color,idx,*perm,nplot;
    165:   PetscMPIInt    rank;
    167:   char           **labels;

    171:   PetscDrawIsNull(bar->win,&isnull);
    172:   if (isnull) return(0);
    173:   MPI_Comm_rank(PetscObjectComm((PetscObject)bar),&rank);

    175:   if (bar->numBins < 1) return(0);

    177:   color = bar->color;
    178:   if (color == PETSC_DRAW_ROTATE) bcolor = PETSC_DRAW_BLACK+1;
    179:   else bcolor = color;

    181:   numValues = bar->numBins;
    182:   values    = bar->values;
    183:   if (bar->ymin == bar->ymax) {
    184:     /* user has not set bounds on bars so set them based on the data */
    185:     ymin = PETSC_MAX_REAL;
    186:     ymax = PETSC_MIN_REAL;
    187:     for (i=0; i<numValues; i++) {
    188:       ymin = PetscMin(ymin,values[i]);
    189:       ymax = PetscMax(ymax,values[i]);
    190:     }
    191:   } else {
    192:     ymin = bar->ymin;
    193:     ymax = bar->ymax;
    194:   }
    195:   nplot  = numValues;  /* number of points to actually plot; if some are lower than requested tolerance */
    196:   xmin   = 0.0;
    197:   xmax   = nplot;
    198:   labels = bar->labels;

    200:   if (bar->sort) {
    201:     PetscMalloc1(numValues,&perm);
    202:     for (i=0; i<numValues;i++) perm[i] = i;
    203:     PetscSortRealWithPermutation(numValues,values,perm);
    204:     if (bar->sorttolerance) {
    205:       for (i=0; i<numValues;i++) {
    206:         if (values[perm[numValues - i - 1]] < bar->sorttolerance) {
    207:           nplot = i;
    208:           break;
    209:         }
    210:       }
    211:     }
    212:   }

    214:   draw = bar->win;
    215:   PetscDrawCheckResizedWindow(draw);
    216:   PetscDrawClear(draw);

    218:   PetscDrawAxisSetLimits(bar->axis,xmin,xmax,ymin,ymax);
    219:   PetscDrawAxisDraw(bar->axis);

    221:   PetscDrawCollectiveBegin(draw);
    222:   if (!rank) { /* Draw bins */
    223:     for (i=0; i<nplot; i++) {
    224:       idx = (bar->sort ? perm[numValues - i - 1] : i);
    225:       binLeft  = xmin + i;
    226:       binRight = xmin + i + 1;
    227:       PetscDrawRectangle(draw,binLeft,ymin,binRight,values[idx],bcolor,bcolor,bcolor,bcolor);
    228:       PetscDrawLine(draw,binLeft,ymin,binLeft,values[idx],PETSC_DRAW_BLACK);
    229:       PetscDrawLine(draw,binRight,ymin,binRight,values[idx],PETSC_DRAW_BLACK);
    230:       PetscDrawLine(draw,binLeft,values[idx],binRight,values[idx],PETSC_DRAW_BLACK);
    231:       if (labels) {
    232:         PetscReal h;
    233:         PetscDrawStringGetSize(draw,NULL,&h);
    234:         PetscDrawStringCentered(draw,.5*(binLeft+binRight),ymin - 1.5*h,bcolor,labels[idx]);
    235:       }
    236:       if (color == PETSC_DRAW_ROTATE) bcolor++;
    237:       if (bcolor > PETSC_DRAW_BASIC_COLORS-1) bcolor = PETSC_DRAW_BLACK+1;
    238:     }
    239:   }
    240:   PetscDrawCollectiveEnd(draw);
    241:   if (bar->sort) {PetscFree(perm);}

    243:   PetscDrawFlush(draw);
    244:   PetscDrawPause(draw);
    245:   return(0);
    246: }

    250: /*@
    251:   PetscDrawBarSave - Saves a drawn image

    253:   Collective on PetscDrawBar

    255:   Input Parameters:
    256: . bar - The bar graph context

    258:   Level: intermediate

    260:   Concepts: bar graph^saving

    262: .seealso:  PetscDrawBarCreate(), PetscDrawBarGetDraw(), PetscDrawSetSave(), PetscDrawSave()
    263: @*/
    264: PetscErrorCode  PetscDrawBarSave(PetscDrawBar bar)
    265: {

    270:   PetscDrawSave(bar->win);
    271:   return(0);
    272: }

    276: /*@
    277:   PetscDrawBarSetColor - Sets the color the bars will be drawn with.

    279:   Logically Collective on PetscDrawBar

    281:   Input Parameters:
    282: + bar - The bar graph context
    283: - color - one of the colors defined in petscdraw.h or PETSC_DRAW_ROTATE to make each bar a
    284:           different color

    286:   Level: intermediate

    288: @*/
    289: PetscErrorCode  PetscDrawBarSetColor(PetscDrawBar bar, int color)
    290: {
    293:   bar->color = color;
    294:   return(0);
    295: }

    299: /*@
    300:   PetscDrawBarSort - Sorts the values before drawing the bar chart

    302:   Logically Collective on PetscDrawBar

    304:   Input Parameters:
    305: + bar - The bar graph context
    306: . sort - PETSC_TRUE to sort the values
    307: . tolerance - discard values less than tolerance

    309:   Level: intermediate

    311:   Concepts: bar graph^setting axis
    312: @*/
    313: PetscErrorCode  PetscDrawBarSort(PetscDrawBar bar, PetscBool sort, PetscReal tolerance)
    314: {
    317:   bar->sort          = sort;
    318:   bar->sorttolerance = tolerance;
    319:   return(0);
    320: }

    324: /*@
    325:   PetscDrawBarSetLimits - Sets the axis limits for a bar graph. If more
    326:   points are added after this call, the limits will be adjusted to
    327:   include those additional points.

    329:   Logically Collective on PetscDrawBar

    331:   Input Parameters:
    332: + bar - The bar graph context
    333: - y_min,y_max - The limits

    335:   Level: intermediate

    337:   Concepts: bar graph^setting axis
    338: @*/
    339: PetscErrorCode  PetscDrawBarSetLimits(PetscDrawBar bar, PetscReal y_min, PetscReal y_max)
    340: {
    343:   bar->ymin = y_min;
    344:   bar->ymax = y_max;
    345:   return(0);
    346: }

    350: /*@C
    351:   PetscDrawBarGetAxis - Gets the axis context associated with a bar graph.
    352:   This is useful if one wants to change some axis property, such as
    353:   labels, color, etc. The axis context should not be destroyed by the
    354:   application code.

    356:   Not Collective, PetscDrawAxis is parallel if PetscDrawBar is parallel

    358:   Input Parameter:
    359: . bar - The bar graph context

    361:   Output Parameter:
    362: . axis - The axis context

    364:   Level: intermediate

    366: @*/
    367: PetscErrorCode  PetscDrawBarGetAxis(PetscDrawBar bar,PetscDrawAxis *axis)
    368: {
    372:   *axis = bar->axis;
    373:   return(0);
    374: }

    378: /*@C
    379:   PetscDrawBarGetDraw - Gets the draw context associated with a bar graph.

    381:   Not Collective, PetscDraw is parallel if PetscDrawBar is parallel

    383:   Input Parameter:
    384: . bar - The bar graph context

    386:   Output Parameter:
    387: . draw  - The draw context

    389:   Level: intermediate

    391: @*/
    392: PetscErrorCode  PetscDrawBarGetDraw(PetscDrawBar bar,PetscDraw *draw)
    393: {
    397:   *draw = bar->win;
    398:   return(0);
    399: }

    403: /*@
    404:     PetscDrawBarSetFromOptions - Sets options related to the PetscDrawBar

    406:     Collective over PetscDrawBar

    408:     Options Database:
    409: .  -bar_sort - sort the entries before drawing the bar graph

    411:     Level: intermediate

    414: .seealso:  PetscDrawBarDestroy(), PetscDrawBarCreate()
    415: @*/
    416: PetscErrorCode  PetscDrawBarSetFromOptions(PetscDrawBar bar)
    417: {
    419:   PetscBool      set;

    424:   PetscOptionsHasName(((PetscObject)bar)->options,((PetscObject)bar)->prefix,"-bar_sort",&set);
    425:   if (set) {
    426:     PetscReal tol = bar->sorttolerance;
    427:     PetscOptionsGetReal(((PetscObject)bar)->options,((PetscObject)bar)->prefix,"-bar_sort",&tol,NULL);
    428:     PetscDrawBarSort(bar,PETSC_TRUE,tol);
    429:   }
    430:   return(0);
    431: }