Actual source code: hists.c

      2: /*
      3:   Contains the data structure for plotting a histogram in a window with an axis.
      4: */
      5: #include <petscdraw.h>
      6: #include <petsc/private/petscimpl.h>
      7: #include <petscviewer.h>

      9: PetscClassId PETSC_DRAWHG_CLASSID = 0;

     11: struct _p_PetscDrawHG {
     12:   PETSCHEADER(int);
     13:   PetscErrorCode (*destroy)(PetscDrawSP);
     14:   PetscErrorCode (*view)(PetscDrawSP,PetscViewer);
     15:   PetscDraw      win;
     16:   PetscDrawAxis  axis;
     17:   PetscReal      xmin,xmax;
     18:   PetscReal      ymin,ymax;
     19:   int            numBins;
     20:   int            maxBins;
     21:   PetscReal      *bins;
     22:   int            numValues;
     23:   int            maxValues;
     24:   PetscReal      *values;
     25:   int            color;
     26:   PetscBool      calcStats;
     27:   PetscBool      integerBins;
     28: };

     30: #define CHUNKSIZE 100

     32: /*@C
     33:    PetscDrawHGCreate - Creates a histogram data structure.

     35:    Collective on PetscDraw

     37:    Input Parameters:
     38: +  draw  - The window where the graph will be made
     39: -  bins - The number of bins to use

     41:    Output Parameters:
     42: .  hist - The histogram context

     44:    Notes:
     45:     The difference between a bar chart, PetscDrawBar, and a histogram, PetscDrawHG, is explained here https://stattrek.com/statistics/charts/histogram.aspx?Tutorial=AP

     47:    The histogram is only displayed when PetscDrawHGDraw() is called.

     49:    The MPI communicator that owns the PetscDraw owns this PetscDrawHG, but the calls to set options and add data are ignored on all processes except the
     50:    zeroth MPI process in the communicator. All MPI processes in the communicator must call PetscDrawHGDraw() to display the updated graph.

     52:    Level: intermediate

     54: .seealso: PetscDrawHGDestroy(), PetscDrawHG, PetscDrawBarCreate(), PetscDrawBar, PetscDrawLGCreate(), PetscDrawLG, PetscDrawSPCreate(), PetscDrawSP,
     55:           PetscDrawHGSetNumberBins(), PetscDrawHGReset(), PetscDrawHGAddValue(), PetscDrawHGDraw(), PetscDrawHGSave(), PetscDrawHGView(), PetscDrawHGSetColor(),
     56:           PetscDrawHGSetLimits(), PetscDrawHGCalcStats(), PetscDrawHGIntegerBins(), PetscDrawHGGetAxis(), PetscDrawAxis, PetscDrawHGGetDraw()

     58: @*/
     59: PetscErrorCode  PetscDrawHGCreate(PetscDraw draw,int bins,PetscDrawHG *hist)
     60: {
     61:   PetscDrawHG    h;

     67:   PetscHeaderCreate(h,PETSC_DRAWHG_CLASSID,"DrawHG","Histogram","Draw",PetscObjectComm((PetscObject)draw),PetscDrawHGDestroy,NULL);
     68:   PetscLogObjectParent((PetscObject)draw,(PetscObject)h);

     70:   PetscObjectReference((PetscObject)draw);
     71:   h->win = draw;

     73:   h->view        = NULL;
     74:   h->destroy     = NULL;
     75:   h->color       = PETSC_DRAW_GREEN;
     76:   h->xmin        = PETSC_MAX_REAL;
     77:   h->xmax        = PETSC_MIN_REAL;
     78:   h->ymin        = 0.;
     79:   h->ymax        = 1.;
     80:   h->numBins     = bins;
     81:   h->maxBins     = bins;

     83:   PetscMalloc1(h->maxBins,&h->bins);

     85:   h->numValues   = 0;
     86:   h->maxValues   = CHUNKSIZE;
     87:   h->calcStats   = PETSC_FALSE;
     88:   h->integerBins = PETSC_FALSE;

     90:   PetscMalloc1(h->maxValues,&h->values);
     91:   PetscLogObjectMemory((PetscObject)h,(h->maxBins + h->maxValues)*sizeof(PetscReal));

     93:   PetscDrawAxisCreate(draw,&h->axis);
     94:   PetscLogObjectParent((PetscObject)h,(PetscObject)h->axis);

     96:   *hist = h;
     97:   return 0;
     98: }

    100: /*@
    101:    PetscDrawHGSetNumberBins - Change the number of bins that are to be drawn.

    103:    Logically Collective on PetscDrawHG

    105:    Input Parameters:
    106: +  hist - The histogram context.
    107: -  bins  - The number of bins.

    109:    Level: intermediate

    111: .seealso: PetscDrawHGCreate(), PetscDrawHG, PetscDrawHGDraw(), PetscDrawHGIntegerBins()

    113: @*/
    114: PetscErrorCode  PetscDrawHGSetNumberBins(PetscDrawHG hist, int bins)
    115: {

    119:   if (hist->maxBins < bins) {
    120:     PetscFree(hist->bins);
    121:     PetscMalloc1(bins, &hist->bins);
    122:     PetscLogObjectMemory((PetscObject)hist, (bins - hist->maxBins) * sizeof(PetscReal));
    123:     hist->maxBins = bins;
    124:   }
    125:   hist->numBins = bins;
    126:   return 0;
    127: }

    129: /*@
    130:   PetscDrawHGReset - Clears histogram to allow for reuse with new data.

    132:   Logically Collective on PetscDrawHG

    134:   Input Parameter:
    135: . hist - The histogram context.

    137:   Level: intermediate

    139: .seealso: PetscDrawHGCreate(), PetscDrawHG, PetscDrawHGDraw(), PetscDrawHGAddValue()

    141: @*/
    142: PetscErrorCode  PetscDrawHGReset(PetscDrawHG hist)
    143: {

    146:   hist->xmin      = PETSC_MAX_REAL;
    147:   hist->xmax      = PETSC_MIN_REAL;
    148:   hist->ymin      = 0.0;
    149:   hist->ymax      = 0.0;
    150:   hist->numValues = 0;
    151:   return 0;
    152: }

    154: /*@C
    155:   PetscDrawHGDestroy - Frees all space taken up by histogram data structure.

    157:   Collective on PetscDrawHG

    159:   Input Parameter:
    160: . hist - The histogram context

    162:   Level: intermediate

    164: .seealso:  PetscDrawHGCreate(), PetscDrawHG
    165: @*/
    166: PetscErrorCode  PetscDrawHGDestroy(PetscDrawHG *hist)
    167: {
    168:   if (!*hist) return 0;
    170:   if (--((PetscObject)(*hist))->refct > 0) {*hist = NULL; return 0;}

    172:   PetscFree((*hist)->bins);
    173:   PetscFree((*hist)->values);
    174:   PetscDrawAxisDestroy(&(*hist)->axis);
    175:   PetscDrawDestroy(&(*hist)->win);
    176:   PetscHeaderDestroy(hist);
    177:   return 0;
    178: }

    180: /*@
    181:   PetscDrawHGAddValue - Adds another value to the histogram.

    183:   Logically Collective on PetscDrawHG

    185:   Input Parameters:
    186: + hist  - The histogram
    187: - value - The value

    189:   Level: intermediate

    191: .seealso: PetscDrawHGCreate(), PetscDrawHG, PetscDrawHGDraw(), PetscDrawHGAddValue(), PetscDrawHGReset()
    192: @*/
    193: PetscErrorCode  PetscDrawHGAddValue(PetscDrawHG hist, PetscReal value)
    194: {

    197:   /* Allocate more memory if necessary */
    198:   if (hist->numValues >= hist->maxValues) {
    199:     PetscReal      *tmp;

    201:     PetscMalloc1(hist->maxValues+CHUNKSIZE, &tmp);
    202:     PetscLogObjectMemory((PetscObject)hist, CHUNKSIZE * sizeof(PetscReal));
    203:     PetscArraycpy(tmp, hist->values, hist->maxValues);
    204:     PetscFree(hist->values);

    206:     hist->values     = tmp;
    207:     hist->maxValues += CHUNKSIZE;
    208:   }
    209:   /* I disagree with the original Petsc implementation here. There should be no overshoot, but rather the
    210:      stated convention of using half-open intervals (always the way to go) */
    211:   if (!hist->numValues && (hist->xmin == PETSC_MAX_REAL) && (hist->xmax == PETSC_MIN_REAL)) {
    212:     hist->xmin = value;
    213:     hist->xmax = value;
    214: #if 1
    215:   } else {
    216:     /* Update limits */
    217:     if (value > hist->xmax) hist->xmax = value;
    218:     if (value < hist->xmin) hist->xmin = value;
    219: #else
    220:   } else if (hist->numValues == 1) {
    221:     /* Update limits -- We need to overshoot the largest value somewhat */
    222:     if (value > hist->xmax) hist->xmax = value + 0.001*(value - hist->xmin)/hist->numBins;
    223:     if (value < hist->xmin) {
    224:       hist->xmin = value;
    225:       hist->xmax = hist->xmax + 0.001*(hist->xmax - hist->xmin)/hist->numBins;
    226:     }
    227:   } else {
    228:     /* Update limits -- We need to overshoot the largest value somewhat */
    229:     if (value > hist->xmax) hist->xmax = value + 0.001*(hist->xmax - hist->xmin)/hist->numBins;
    230:     if (value < hist->xmin) hist->xmin = value;
    231: #endif
    232:   }

    234:   hist->values[hist->numValues++] = value;
    235:   return 0;
    236: }

    238: /*@
    239:   PetscDrawHGDraw - Redraws a histogram.

    241:   Collective on PetscDrawHG

    243:   Input Parameter:
    244: . hist - The histogram context

    246:   Level: intermediate

    248: .seealso: PetscDrawHGCreate(), PetscDrawHG, PetscDrawHGDraw(), PetscDrawHGAddValue(), PetscDrawHGReset()

    250: @*/
    251: PetscErrorCode  PetscDrawHGDraw(PetscDrawHG hist)
    252: {
    253:   PetscDraw      draw;
    254:   PetscBool      isnull;
    255:   PetscReal      xmin,xmax,ymin,ymax,*bins,*values,binSize,binLeft,binRight,maxHeight,mean,var;
    256:   char           title[256];
    257:   char           xlabel[256];
    258:   PetscInt       numBins,numBinsOld,numValues,initSize,i,p,bcolor,color;
    259:   PetscMPIInt    rank;

    263:   PetscDrawIsNull(hist->win,&isnull);
    264:   if (isnull) return 0;
    265:   MPI_Comm_rank(PetscObjectComm((PetscObject)hist),&rank);

    267:   if ((hist->xmin >= hist->xmax) || (hist->ymin >= hist->ymax)) return 0;
    268:   if (hist->numValues < 1) return 0;

    270:   color = hist->color;
    271:   if (color == PETSC_DRAW_ROTATE) bcolor = PETSC_DRAW_BLACK+1;
    272:   else bcolor = color;

    274:   xmin      = hist->xmin;
    275:   xmax      = hist->xmax;
    276:   ymin      = hist->ymin;
    277:   ymax      = hist->ymax;
    278:   numValues = hist->numValues;
    279:   values    = hist->values;
    280:   mean      = 0.0;
    281:   var       = 0.0;

    283:   draw = hist->win;
    284:   PetscDrawCheckResizedWindow(draw);
    285:   PetscDrawClear(draw);

    287:   if (xmin == xmax) {
    288:     /* Calculate number of points in each bin */
    289:     bins    = hist->bins;
    290:     bins[0] = 0.;
    291:     for (p = 0; p < numValues; p++) {
    292:       if (values[p] == xmin) bins[0]++;
    293:       mean += values[p];
    294:       var  += values[p]*values[p];
    295:     }
    296:     maxHeight = bins[0];
    297:     if (maxHeight > ymax) ymax = hist->ymax = maxHeight;
    298:     xmax = xmin + 1;
    299:     PetscDrawAxisSetLimits(hist->axis, xmin, xmax, ymin, ymax);
    300:     if (hist->calcStats) {
    301:       mean /= numValues;
    302:       if (numValues > 1) var = (var - numValues*mean*mean) / (numValues-1);
    303:       else var = 0.0;
    304:       PetscSNPrintf(title, 256, "Mean: %g  Var: %g", (double)mean, (double)var);
    305:       PetscSNPrintf(xlabel,256, "Total: %" PetscInt_FMT, numValues);
    306:       PetscDrawAxisSetLabels(hist->axis, title, xlabel, NULL);
    307:     }
    308:     PetscDrawAxisDraw(hist->axis);
    309:     PetscDrawCollectiveBegin(draw);
    310:     if (rank == 0) { /* Draw bins */
    311:       binLeft  = xmin;
    312:       binRight = xmax;
    313:       PetscDrawRectangle(draw,binLeft,ymin,binRight,bins[0],bcolor,bcolor,bcolor,bcolor);
    314:       PetscDrawLine(draw,binLeft,ymin,binLeft,bins[0],PETSC_DRAW_BLACK);
    315:       PetscDrawLine(draw,binRight,ymin,binRight,bins[0],PETSC_DRAW_BLACK);
    316:       PetscDrawLine(draw,binLeft,bins[0],binRight,bins[0],PETSC_DRAW_BLACK);
    317:     }
    318:     PetscDrawCollectiveEnd(draw);
    319:   } else {
    320:     numBins    = hist->numBins;
    321:     numBinsOld = hist->numBins;
    322:     if (hist->integerBins && (((int) xmax - xmin) + 1.0e-05 > xmax - xmin)) {
    323:       initSize = (int) ((int) xmax - xmin)/numBins;
    324:       while (initSize*numBins != (int) xmax - xmin) {
    325:         initSize = PetscMax(initSize - 1, 1);
    326:         numBins  = (int) ((int) xmax - xmin)/initSize;
    327:         PetscDrawHGSetNumberBins(hist, numBins);
    328:       }
    329:     }
    330:     binSize = (xmax - xmin)/numBins;
    331:     bins    = hist->bins;

    333:     PetscArrayzero(bins, numBins);

    335:     maxHeight = 0.0;
    336:     for (i = 0; i < numBins; i++) {
    337:       binLeft  = xmin + binSize*i;
    338:       binRight = xmin + binSize*(i+1);
    339:       for (p = 0; p < numValues; p++) {
    340:         if ((values[p] >= binLeft) && (values[p] < binRight)) bins[i]++;
    341:         /* Handle last bin separately */
    342:         if ((i == numBins-1) && (values[p] == binRight)) bins[i]++;
    343:         if (!i) {
    344:           mean += values[p];
    345:           var  += values[p]*values[p];
    346:         }
    347:       }
    348:       maxHeight = PetscMax(maxHeight, bins[i]);
    349:     }
    350:     if (maxHeight > ymax) ymax = hist->ymax = maxHeight;

    352:     PetscDrawAxisSetLimits(hist->axis, xmin, xmax, ymin, ymax);
    353:     if (hist->calcStats) {
    354:       mean /= numValues;
    355:       if (numValues > 1) var = (var - numValues*mean*mean) / (numValues-1);
    356:       else var = 0.0;
    357:       PetscSNPrintf(title, 256,"Mean: %g  Var: %g", (double)mean, (double)var);
    358:       PetscSNPrintf(xlabel,256, "Total: %" PetscInt_FMT, numValues);
    359:       PetscDrawAxisSetLabels(hist->axis, title, xlabel, NULL);
    360:     }
    361:     PetscDrawAxisDraw(hist->axis);
    362:     PetscDrawCollectiveBegin(draw);
    363:     if (rank == 0) { /* Draw bins */
    364:       for (i = 0; i < numBins; i++) {
    365:         binLeft  = xmin + binSize*i;
    366:         binRight = xmin + binSize*(i+1);
    367:         PetscDrawRectangle(draw,binLeft,ymin,binRight,bins[i],bcolor,bcolor,bcolor,bcolor);
    368:         PetscDrawLine(draw,binLeft,ymin,binLeft,bins[i],PETSC_DRAW_BLACK);
    369:         PetscDrawLine(draw,binRight,ymin,binRight,bins[i],PETSC_DRAW_BLACK);
    370:         PetscDrawLine(draw,binLeft,bins[i],binRight,bins[i],PETSC_DRAW_BLACK);
    371:         if (color == PETSC_DRAW_ROTATE && bins[i]) bcolor++;
    372:         if (bcolor > PETSC_DRAW_BASIC_COLORS-1) bcolor = PETSC_DRAW_BLACK+1;
    373:       }
    374:     }
    375:     PetscDrawCollectiveEnd(draw);
    376:     PetscDrawHGSetNumberBins(hist,numBinsOld);
    377:   }

    379:   PetscDrawFlush(draw);
    380:   PetscDrawPause(draw);
    381:   return 0;
    382: }

    384: /*@
    385:   PetscDrawHGSave - Saves a drawn image

    387:   Collective on PetscDrawHG

    389:   Input Parameter:
    390: . hist - The histogram context

    392:   Level: intermediate

    394: .seealso:  PetscDrawHGCreate(), PetscDrawHGGetDraw(), PetscDrawSetSave(), PetscDrawSave(), PetscDrawHGDraw()
    395: @*/
    396: PetscErrorCode  PetscDrawHGSave(PetscDrawHG hg)
    397: {
    399:   PetscDrawSave(hg->win);
    400:   return 0;
    401: }

    403: /*@
    404:   PetscDrawHGView - Prints the histogram information.

    406:   Not collective

    408:   Input Parameter:
    409: . hist - The histogram context

    411:   Level: beginner

    413: .seealso:  PetscDrawHGCreate(), PetscDrawHGGetDraw(), PetscDrawSetSave(), PetscDrawSave(), PetscDrawHGDraw()

    415: @*/
    416: PetscErrorCode  PetscDrawHGView(PetscDrawHG hist,PetscViewer viewer)
    417: {
    418:   PetscReal      xmax,xmin,*bins,*values,binSize,binLeft,binRight,mean,var;
    419:   PetscInt       numBins,numBinsOld,numValues,initSize,i,p;

    423:   if ((hist->xmin > hist->xmax) || (hist->ymin >= hist->ymax)) return 0;
    424:   if (hist->numValues < 1) return 0;

    426:   if (!viewer) {
    427:     PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)hist),&viewer);
    428:   }
    429:   PetscObjectPrintClassNamePrefixType((PetscObject)hist,viewer);
    430:   xmax      = hist->xmax;
    431:   xmin      = hist->xmin;
    432:   numValues = hist->numValues;
    433:   values    = hist->values;
    434:   mean      = 0.0;
    435:   var       = 0.0;
    436:   if (xmax == xmin) {
    437:     /* Calculate number of points in the bin */
    438:     bins    = hist->bins;
    439:     bins[0] = 0.;
    440:     for (p = 0; p < numValues; p++) {
    441:       if (values[p] == xmin) bins[0]++;
    442:       mean += values[p];
    443:       var  += values[p]*values[p];
    444:     }
    445:     /* Draw bins */
    446:     PetscViewerASCIIPrintf(viewer, "Bin %2d (%6.2g - %6.2g): %.0g\n", 0, (double)xmin, (double)xmax, (double)bins[0]);
    447:   } else {
    448:     numBins    = hist->numBins;
    449:     numBinsOld = hist->numBins;
    450:     if (hist->integerBins && (((int) xmax - xmin) + 1.0e-05 > xmax - xmin)) {
    451:       initSize = (int) ((int) xmax - xmin)/numBins;
    452:       while (initSize*numBins != (int) xmax - xmin) {
    453:         initSize = PetscMax(initSize - 1, 1);
    454:         numBins  = (int) ((int) xmax - xmin)/initSize;
    455:         PetscDrawHGSetNumberBins(hist, numBins);
    456:       }
    457:     }
    458:     binSize = (xmax - xmin)/numBins;
    459:     bins    = hist->bins;

    461:     /* Calculate number of points in each bin */
    462:     PetscArrayzero(bins, numBins);
    463:     for (i = 0; i < numBins; i++) {
    464:       binLeft  = xmin + binSize*i;
    465:       binRight = xmin + binSize*(i+1);
    466:       for (p = 0; p < numValues; p++) {
    467:         if ((values[p] >= binLeft) && (values[p] < binRight)) bins[i]++;
    468:         /* Handle last bin separately */
    469:         if ((i == numBins-1) && (values[p] == binRight)) bins[i]++;
    470:         if (!i) {
    471:           mean += values[p];
    472:           var  += values[p]*values[p];
    473:         }
    474:       }
    475:     }
    476:     /* Draw bins */
    477:     for (i = 0; i < numBins; i++) {
    478:       binLeft  = xmin + binSize*i;
    479:       binRight = xmin + binSize*(i+1);
    480:       PetscViewerASCIIPrintf(viewer, "Bin %2d (%6.2g - %6.2g): %.0g\n", (int)i, (double)binLeft, (double)binRight, (double)bins[i]);
    481:     }
    482:     PetscDrawHGSetNumberBins(hist, numBinsOld);
    483:   }

    485:   if (hist->calcStats) {
    486:     mean /= numValues;
    487:     if (numValues > 1) var = (var - numValues*mean*mean) / (numValues-1);
    488:     else var = 0.0;
    489:     PetscViewerASCIIPrintf(viewer, "Mean: %g  Var: %g\n", (double)mean, (double)var);
    490:     PetscViewerASCIIPrintf(viewer, "Total: %" PetscInt_FMT "\n", numValues);
    491:   }
    492:   return 0;
    493: }

    495: /*@
    496:   PetscDrawHGSetColor - Sets the color the bars will be drawn with.

    498:   Logically Collective on PetscDrawHG

    500:   Input Parameters:
    501: + hist - The histogram context
    502: - color - one of the colors defined in petscdraw.h or PETSC_DRAW_ROTATE to make each bar a
    503:           different color

    505:   Level: intermediate

    507: .seealso:  PetscDrawHGCreate(), PetscDrawHGGetDraw(), PetscDrawSetSave(), PetscDrawSave(), PetscDrawHGDraw(), PetscDrawHGGetAxis()

    509: @*/
    510: PetscErrorCode  PetscDrawHGSetColor(PetscDrawHG hist,int color)
    511: {

    514:   hist->color = color;
    515:   return 0;
    516: }

    518: /*@
    519:   PetscDrawHGSetLimits - Sets the axis limits for a histogram. If more
    520:   points are added after this call, the limits will be adjusted to
    521:   include those additional points.

    523:   Logically Collective on PetscDrawHG

    525:   Input Parameters:
    526: + hist - The histogram context
    527: - x_min,x_max,y_min,y_max - The limits

    529:   Level: intermediate

    531: .seealso:  PetscDrawHGCreate(), PetscDrawHGGetDraw(), PetscDrawSetSave(), PetscDrawSave(), PetscDrawHGDraw(), PetscDrawHGGetAxis()

    533: @*/
    534: PetscErrorCode  PetscDrawHGSetLimits(PetscDrawHG hist, PetscReal x_min, PetscReal x_max, int y_min, int y_max)
    535: {

    538:   hist->xmin = x_min;
    539:   hist->xmax = x_max;
    540:   hist->ymin = y_min;
    541:   hist->ymax = y_max;
    542:   return 0;
    543: }

    545: /*@
    546:   PetscDrawHGCalcStats - Turns on calculation of descriptive statistics

    548:   Not collective

    550:   Input Parameters:
    551: + hist - The histogram context
    552: - calc - Flag for calculation

    554:   Level: intermediate

    556: .seealso:  PetscDrawHGCreate(), PetscDrawHGAddValue(), PetscDrawHGView(), PetscDrawHGDraw()

    558: @*/
    559: PetscErrorCode  PetscDrawHGCalcStats(PetscDrawHG hist, PetscBool calc)
    560: {

    563:   hist->calcStats = calc;
    564:   return 0;
    565: }

    567: /*@
    568:   PetscDrawHGIntegerBins - Turns on integer width bins

    570:   Not collective

    572:   Input Parameters:
    573: + hist - The histogram context
    574: - ints - Flag for integer width bins

    576:   Level: intermediate

    578: .seealso:  PetscDrawHGCreate(), PetscDrawHGAddValue(), PetscDrawHGView(), PetscDrawHGDraw(), PetscDrawHGSetColor()

    580: @*/
    581: PetscErrorCode  PetscDrawHGIntegerBins(PetscDrawHG hist, PetscBool ints)
    582: {

    585:   hist->integerBins = ints;
    586:   return 0;
    587: }

    589: /*@C
    590:   PetscDrawHGGetAxis - Gets the axis context associated with a histogram.
    591:   This is useful if one wants to change some axis property, such as
    592:   labels, color, etc. The axis context should not be destroyed by the
    593:   application code.

    595:   Not Collective, PetscDrawAxis is parallel if PetscDrawHG is parallel

    597:   Input Parameter:
    598: . hist - The histogram context

    600:   Output Parameter:
    601: . axis - The axis context

    603:   Level: intermediate

    605: .seealso:  PetscDrawHGCreate(), PetscDrawHGAddValue(), PetscDrawHGView(), PetscDrawHGDraw(), PetscDrawHGSetColor(), PetscDrawAxis, PetscDrawHGSetLimits()

    607: @*/
    608: PetscErrorCode  PetscDrawHGGetAxis(PetscDrawHG hist,PetscDrawAxis *axis)
    609: {
    612:   *axis = hist->axis;
    613:   return 0;
    614: }

    616: /*@C
    617:   PetscDrawHGGetDraw - Gets the draw context associated with a histogram.

    619:   Not Collective, PetscDraw is parallel if PetscDrawHG is parallel

    621:   Input Parameter:
    622: . hist - The histogram context

    624:   Output Parameter:
    625: . draw  - The draw context

    627:   Level: intermediate

    629: .seealso:  PetscDrawHGCreate(), PetscDrawHGAddValue(), PetscDrawHGView(), PetscDrawHGDraw(), PetscDrawHGSetColor(), PetscDrawAxis, PetscDrawHGSetLimits()

    631: @*/
    632: PetscErrorCode  PetscDrawHGGetDraw(PetscDrawHG hist,PetscDraw *draw)
    633: {
    636:   *draw = hist->win;
    637:   return 0;
    638: }