Actual source code: hists.c

  1: /*$Id: hists.c,v 1.26 2001/04/10 19:34:23 bsmith Exp $*/

  3: /*
  4:   Contains the data structure for plotting a histogram in a window with an axis.
  5: */

 7:  #include petsc.h

  9: int DRAWHG_COOKIE;

 11: struct _p_DrawHG {
 12:   PETSCHEADER(int)
 13:   int           (*destroy)(PetscDrawSP);
 14:   int           (*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:   PetscTruth    calcStats;
 27:   PetscTruth    integerBins;
 28: };

 30: #define CHUNKSIZE 100

 32: #undef __FUNCT__  
 34: /*@C
 35:    PetscDrawHGCreate - Creates a histogram data structure.

 37:    Collective over PetscDraw

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

 43:    Output Parameters:
 44: .  hist - The histogram context

 46:    Level: intermediate

 48:    Contributed by: Matthew Knepley

 50:    Concepts: histogram^creating

 52: .seealso: PetscDrawHGDestroy()

 54: @*/
 55: int PetscDrawHGCreate(PetscDraw draw, int bins, PetscDrawHG *hist) {
 56:   PetscDrawHG h;
 57:   MPI_Comm    comm;
 58:   PetscTruth  isnull;
 59:   int         ierr;

 64:   PetscObjectGetComm((PetscObject) draw, &comm);
 65:   PetscHeaderCreate(h, _p_DrawHG, int, DRAWHG_COOKIE, 0, "PetscDrawHG", comm, PetscDrawHGDestroy, PETSC_NULL);
 66:   h->view        = PETSC_NULL;
 67:   h->destroy     = PETSC_NULL;
 68:   h->win         = draw;
 69:   PetscObjectReference((PetscObject) draw);
 70:   h->color       = PETSC_DRAW_GREEN;
 71:   h->xmin        = PETSC_MAX;
 72:   h->xmax        = PETSC_MIN;
 73:   h->ymin        = 0.;
 74:   h->ymax        = 1.;
 75:   h->numBins     = bins;
 76:   h->maxBins     = bins;
 77:   PetscMalloc(h->maxBins * sizeof(PetscReal), &h->bins);
 78:   h->numValues   = 0;
 79:   h->maxValues   = CHUNKSIZE;
 80:   h->calcStats   = PETSC_FALSE;
 81:   h->integerBins = PETSC_FALSE;
 82:   PetscMalloc(h->maxValues * sizeof(PetscReal), &h->values);
 83:   PetscLogObjectMemory(h, (h->maxBins + h->maxValues)*sizeof(PetscReal));
 84:   PetscTypeCompare((PetscObject) draw, PETSC_DRAW_NULL, &isnull);
 85:   if (isnull == PETSC_FALSE) {
 86:     PetscDrawAxisCreate(draw, &h->axis);
 87:     PetscLogObjectParent(h, h->axis);
 88:   } else {
 89:     h->axis = PETSC_NULL;
 90:   }
 91:   *hist = h;
 92:   return(0);
 93: }

 95: #undef __FUNCT__  
 97: /*@
 98:    PetscDrawHGSetNumberBins - Change the number of bins that are to be drawn.

100:    Not Collective (ignored except on processor 0 of PetscDrawHG)

102:    Input Parameter:
103: +  hist - The histogram context.
104: -  dim  - The number of curves.

106:    Level: intermediate

108:   Contributed by: Matthew Knepley

110:    Concepts: histogram^setting number of bins

112: @*/
113: int PetscDrawHGSetNumberBins(PetscDrawHG hist, int bins) {

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

128: #undef __FUNCT__  
130: /*@
131:   PetscDrawHGReset - Clears histogram to allow for reuse with new data.

133:   Not Collective (ignored except on processor 0 of PetscDrawHG)

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

138:   Level: intermediate

140:   Contributed by: Matthew Knepley

142:   Concepts: histogram^resetting
143: @*/
144: int PetscDrawHGReset(PetscDrawHG hist)
145: {
148:   hist->xmin      = PETSC_MAX;
149:   hist->xmax      = PETSC_MIN;
150:   hist->ymin      = 0;
151:   hist->ymax      = 0;
152:   hist->numValues = 0;
153:   return(0);
154: }

156: #undef __FUNCT__  
158: /*@C
159:   PetscDrawHGDestroy - Frees all space taken up by histogram data structure.

161:   Collective over PetscDrawHG

163:   Input Parameter:
164: . hist - The histogram context

166:   Level: intermediate

168:   Contributed by: Matthew Knepley

170: .seealso:  PetscDrawHGCreate()
171: @*/
172: int PetscDrawHGDestroy(PetscDrawHG hist)
173: {


179:   if (--hist->refct > 0) return(0);
180:   if (hist->axis != PETSC_NULL) {
181:     PetscDrawAxisDestroy(hist->axis);
182:   }
183:   PetscDrawDestroy(hist->win);
184:   PetscFree(hist->bins);
185:   PetscFree(hist->values);
186:   PetscLogObjectDestroy(hist);
187:   PetscHeaderDestroy(hist);
188:   return(0);
189: }

191: #undef __FUNCT__  
193: /*@
194:   PetscDrawHGAddValue - Adds another value to the histogram.

196:   Not Collective (ignored except on processor 0 of PetscDrawHG)

198:   Input Parameters:
199: + hist  - The histogram
200: - value - The value 

202:   Level: intermediate

204:   Contributed by: Matthew Knepley

206:   Concepts: histogram^adding values

208: .seealso: PetscDrawHGAddValues()
209: @*/
210: int PetscDrawHGAddValue(PetscDrawHG hist, PetscReal value)
211: {
214:   /* Allocate more memory if necessary */
215:   if (hist->numValues >= hist->maxValues) {
216:     PetscReal *tmp;
217:     int        ierr;

219:     PetscMalloc((hist->maxValues+CHUNKSIZE) * sizeof(PetscReal), &tmp);
220:     PetscLogObjectMemory(hist, CHUNKSIZE * sizeof(PetscReal));
221:     PetscMemcpy(tmp, hist->values, hist->maxValues * sizeof(PetscReal));
222:     PetscFree(hist->values);
223:     hist->values     = tmp;
224:     hist->maxValues += CHUNKSIZE;
225:   }
226:   /* I disagree with the original Petsc implementation here. There should be no overshoot, but rather the
227:      stated convention of using half-open intervals (always the way to go) */
228:   if (!hist->numValues) {
229:     hist->xmin = value;
230:     hist->xmax = value;
231: #if 1
232:   } else {
233:     /* Update limits */
234:     if (value > hist->xmax)
235:       hist->xmax = value;
236:     if (value < hist->xmin)
237:       hist->xmin = value;
238: #else
239:   } else if (hist->numValues == 1) {
240:     /* Update limits -- We need to overshoot the largest value somewhat */
241:     if (value > hist->xmax) {
242:       hist->xmax = value + 0.001*(value - hist->xmin)/hist->numBins;
243:     }
244:     if (value < hist->xmin) {
245:       hist->xmin = value;
246:       hist->xmax = hist->xmax + 0.001*(hist->xmax - hist->xmin)/hist->numBins;
247:     }
248:   } else {
249:     /* Update limits -- We need to overshoot the largest value somewhat */
250:     if (value > hist->xmax) {
251:       hist->xmax = value + 0.001*(hist->xmax - hist->xmin)/hist->numBins;
252:     }
253:     if (value < hist->xmin) {
254:       hist->xmin = value;
255:     }
256: #endif
257:   }

259:   hist->values[hist->numValues++] = value;
260:   return(0);
261: }

263: #undef __FUNCT__  
265: /*@
266:   PetscDrawHGDraw - Redraws a histogram.

268:   Not Collective (ignored except on processor 0 of PetscDrawHG)

270:   Input Parameter:
271: . hist - The histogram context

273:   Level: intermediate

275:   Contributed by: Matthew Knepley
276: @*/
277: int PetscDrawHGDraw(PetscDrawHG hist)
278: {
279:   PetscDraw  draw = hist->win;
280:   PetscTruth isnull;
281:   PetscReal  xmin,xmax,ymin,ymax,*bins,*values,binSize,binLeft,binRight,maxHeight,mean,var;
282:   char       title[256];
283:   char       xlabel[256];
284:   int        numBins,numBinsOld,numValues,initSize,i,p,ierr,bcolor,color;

288:   PetscTypeCompare((PetscObject) draw, PETSC_DRAW_NULL, &isnull);
289:   if (isnull == PETSC_TRUE) return(0);
290:   if ((hist->xmin >= hist->xmax) || (hist->ymin >= hist->ymax)) return(0);
291:   if (hist->numValues < 1) return(0);

293: #if 0
294:   MPI_Comm_rank(hist->comm,&rank);
295:   if (rank) return(0);
296: #endif

298:   color     = hist->color;
299:   if (color == PETSC_DRAW_ROTATE) {bcolor = 2;} else {bcolor = color;}
300:   xmin      = hist->xmin;
301:   xmax      = hist->xmax;
302:   ymin      = hist->ymin;
303:   ymax      = hist->ymax;
304:   numValues = hist->numValues;
305:   values    = hist->values;
306:   mean      = 0.0;
307:   var       = 0.0;
308: 
309:   PetscDrawClear(draw);
310:   if (xmin == xmax) {
311:     /* Calculate number of points in each bin */
312:     bins    = hist->bins;
313:     bins[0] = 0;
314:     for(p = 0; p < numValues; p++) {
315:       if (values[p] == xmin) bins[0]++;
316:       mean += values[p];
317:       var  += values[p]*values[p];
318:     }
319:     maxHeight = bins[0];
320:     if (maxHeight > ymax) ymax = hist->ymax = maxHeight;
321:     xmax = xmin + 1;
322:     PetscDrawAxisSetLimits(hist->axis, xmin, xmax, ymin, ymax);
323:     if (hist->calcStats) {
324:       mean /= numValues;
325:       if (numValues > 1) {
326:         var = (var - numValues*mean*mean) / (numValues-1);
327:       } else {
328:         var = 0.0;
329:       }
330:       sprintf(title,  "Mean: %g  Var: %g", mean, var);
331:       sprintf(xlabel, "Total: %d", numValues);
332:       ierr  = PetscDrawAxisSetLabels(hist->axis, title, xlabel, PETSC_NULL);
333:     }
334:     PetscDrawAxisDraw(hist->axis);
335:     /* Draw bins */
336:     binLeft   = xmin;
337:     binRight  = xmax;
338:     PetscDrawRectangle(draw,binLeft,ymin,binRight,bins[0],bcolor,bcolor,bcolor,bcolor);
339:     if (color == PETSC_DRAW_ROTATE && bins[0]) bcolor++; if (bcolor > 31) bcolor = 2;
340:     PetscDrawLine(draw,binLeft,ymin,binLeft,bins[0],PETSC_DRAW_BLACK);
341:     PetscDrawLine(draw,binRight,ymin,binRight,bins[0],PETSC_DRAW_BLACK);
342:     PetscDrawLine(draw,binLeft,bins[0],binRight,bins[0],PETSC_DRAW_BLACK);
343:   } else {
344:     numBins    = hist->numBins;
345:     numBinsOld = hist->numBins;
346:     if ((hist->integerBins == PETSC_TRUE) && (((int) xmax - xmin) + 1.0e-05 > xmax - xmin)) {
347:       initSize = (int) ((int) xmax - xmin)/numBins;
348:       while (initSize*numBins != (int) xmax - xmin) {
349:         initSize = PetscMax(initSize - 1, 1);
350:         numBins  = (int) ((int) xmax - xmin)/initSize;
351:         ierr     = PetscDrawHGSetNumberBins(hist, numBins);
352:       }
353:     }
354:     binSize = (xmax - xmin)/numBins;
355:     bins    = hist->bins;

357:     PetscMemzero(bins, numBins * sizeof(PetscReal));
358:     maxHeight = 0;
359:     for (i = 0; i < numBins; i++) {
360:       binLeft   = xmin + binSize*i;
361:       binRight  = xmin + binSize*(i+1);
362:       for(p = 0; p < numValues; p++) {
363:         if ((values[p] >= binLeft) && (values[p] < binRight)) bins[i]++;
364:         /* Handle last bin separately */
365:         if ((i == numBins-1) && (values[p] == binRight)) bins[i]++;
366:         if (i == 0) {
367:           mean += values[p];
368:           var  += values[p]*values[p];
369:         }
370:       }
371:       maxHeight = PetscMax(maxHeight, bins[i]);
372:     }
373:     if (maxHeight > ymax) ymax = hist->ymax = maxHeight;

375:     PetscDrawAxisSetLimits(hist->axis, xmin, xmax, ymin, ymax);
376:     if (hist->calcStats) {
377:       mean /= numValues;
378:       if (numValues > 1) {
379:         var = (var - numValues*mean*mean) / (numValues-1);
380:       } else {
381:         var = 0.0;
382:       }
383:       sprintf(title, "Mean: %g  Var: %g", mean, var);
384:       sprintf(xlabel, "Total: %d", numValues);
385:       ierr  = PetscDrawAxisSetLabels(hist->axis, title, xlabel, PETSC_NULL);
386:     }
387:     PetscDrawAxisDraw(hist->axis);
388:     /* Draw bins */
389:     for (i = 0; i < numBins; i++) {
390:       binLeft   = xmin + binSize*i;
391:       binRight  = xmin + binSize*(i+1);
392:       PetscDrawRectangle(draw,binLeft,ymin,binRight,bins[i],bcolor,bcolor,bcolor,bcolor);
393:       if (color == PETSC_DRAW_ROTATE && bins[i]) bcolor++; if (bcolor > 31) bcolor = 2;
394:       PetscDrawLine(draw,binLeft,ymin,binLeft,bins[i],PETSC_DRAW_BLACK);
395:       PetscDrawLine(draw,binRight,ymin,binRight,bins[i],PETSC_DRAW_BLACK);
396:       PetscDrawLine(draw,binLeft,bins[i],binRight,bins[i],PETSC_DRAW_BLACK);
397:     }
398:     PetscDrawHGSetNumberBins(hist, numBinsOld);
399:   }
400:   PetscDrawSynchronizedFlush(draw);
401:   PetscDrawPause(draw);
402:   return(0);
403: }

405: #undef __FUNCT__  
407: /*@
408:   PetscDrawHGPrint - Prints the histogram information.

410:   Not collective

412:   Input Parameter:
413: . hist - The histogram context

415:   Level: beginner

417:   Contributed by: Matthew Knepley

419: .keywords:  draw, histogram
420: @*/
421: int PetscDrawHGPrint(PetscDrawHG hist)
422: {
423:   PetscReal xmax,xmin,*bins,*values,binSize,binLeft,binRight,mean,var;
424:   int       numBins,numBinsOld,numValues,initSize,i,p,ierr;

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

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

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

486:   if (hist->calcStats) {
487:     mean /= numValues;
488:     if (numValues > 1) {
489:       var = (var - numValues*mean*mean) / (numValues-1);
490:     } else {
491:       var = 0.0;
492:     }
493:     PetscPrintf(hist->comm, "Mean: %g  Var: %gn", mean, var);
494:     PetscPrintf(hist->comm, "Total: %dn", numValues);
495:   }
496:   return(0);
497: }
498: 
499: #undef __FUNCT__  
501: /*@
502:   PetscDrawHGSetColor - Sets the color the bars will be drawn with.

504:   Not Collective (ignored except on processor 0 of PetscDrawHG)

506:   Input Parameters:
507: + hist - The histogram context
508: - color - one of the colors defined in petscdraw.h or PETSC_DRAW_ROTATE to make each bar a 
509:           different color

511:   Level: intermediate

513: @*/
514: int PetscDrawHGSetColor(PetscDrawHG hist, int color)
515: {
518:   hist->color = color;
519:   return(0);
520: }

522: #undef __FUNCT__  
524: /*@
525:   PetscDrawHGSetLimits - Sets the axis limits for a histogram. If more
526:   points are added after this call, the limits will be adjusted to
527:   include those additional points.

529:   Not Collective (ignored except on processor 0 of PetscDrawHG)

531:   Input Parameters:
532: + hist - The histogram context
533: - x_min,x_max,y_min,y_max - The limits

535:   Level: intermediate

537:   Contributed by: Matthew Knepley

539:   Concepts: histogram^setting axis
540: @*/
541: int PetscDrawHGSetLimits(PetscDrawHG hist, PetscReal x_min, PetscReal x_max, int y_min, int y_max)
542: {
545:   hist->xmin = x_min;
546:   hist->xmax = x_max;
547:   hist->ymin = y_min;
548:   hist->ymax = y_max;
549:   return(0);
550: }

552: #undef __FUNCT__  
554: /*@
555:   PetscDrawHGCalcStats - Turns on calculation of descriptive statistics

557:   Not collective

559:   Input Parameters:
560: + hist - The histogram context
561: - calc - Flag for calculation

563:   Level: intermediate

565:   Contributed by: Matthew Knepley

567: .keywords:  draw, histogram, statistics

569: @*/
570: int PetscDrawHGCalcStats(PetscDrawHG hist, PetscTruth calc)
571: {
574:   hist->calcStats = calc;
575:   return(0);
576: }

578: #undef __FUNCT__  
580: /*@
581:   PetscDrawHGIntegerBins - Turns on integer width bins

583:   Not collective

585:   Input Parameters:
586: + hist - The histogram context
587: - ints - Flag for integer width bins

589:   Level: intermediate

591:   Contributed by: Matthew Knepley

593: .keywords:  draw, histogram, statistics
594: @*/
595: int PetscDrawHGIntegerBins(PetscDrawHG hist, PetscTruth ints)
596: {
599:   hist->integerBins = ints;
600:   return(0);
601: }

603: #undef __FUNCT__  
605: /*@C
606:   PetscDrawHGGetAxis - Gets the axis context associated with a histogram.
607:   This is useful if one wants to change some axis property, such as
608:   labels, color, etc. The axis context should not be destroyed by the
609:   application code.

611:   Not Collective (ignored except on processor 0 of PetscDrawHG)

613:   Input Parameter:
614: . hist - The histogram context

616:   Output Parameter:
617: . axis - The axis context

619:   Level: intermediate

621:   Contributed by: Matthew Knepley
622: @*/
623: int PetscDrawHGGetAxis(PetscDrawHG hist, PetscDrawAxis *axis)
624: {
627:   *axis = hist->axis;
628:   return(0);
629: }

631: #undef __FUNCT__  
633: /*@C
634:   PetscDrawHGGetDraw - Gets the draw context associated with a histogram.

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

638:   Input Parameter:
639: . hist - The histogram context

641:   Output Parameter:
642: . win  - The draw context

644:   Level: intermediate

646:   Contributed by: Matthew Knepley
647: @*/
648: int PetscDrawHGGetDraw(PetscDrawHG hist, PetscDraw *win)
649: {
652:   *win = hist->win;
653:   return(0);
654: }