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: struct _p_DrawHG {
 10:   PETSCHEADER(int)
 11:   int           (*destroy)(PetscDrawSP);
 12:   int           (*view)(PetscDrawSP,PetscViewer);
 13:   PetscDraw     win;
 14:   PetscDrawAxis axis;
 15:   PetscReal     xmin,xmax;
 16:   PetscReal     ymin,ymax;
 17:   int           numBins;
 18:   PetscReal     *bins;
 19:   int           numValues;
 20:   int           maxValues;
 21:   PetscReal     *values;
 22:   int           color;
 23: };

 25: #define CHUNKSIZE 100

 27: /*@C
 28:    PetscDrawHGCreate - Creates a histogram data structure.

 30:    Collective over PetscDraw

 32:    Input Parameters:
 33: +  draw  - The window where the graph will be made
 34: -  bins - The number of bins to use

 36:    Output Parameters:
 37: .  hist - The histogram context

 39:    Level: intermediate

 41:    Contributed by: Matthew Knepley

 43:    Concepts: histogram^creating

 45: .seealso: PetscDrawHGDestroy()

 47: @*/
 48: int PetscDrawHGCreate(PetscDraw draw,int bins,PetscDrawHG *hist)
 49: {
 50:   int         ierr;
 51:   PetscTruth  isnull;
 52:   PetscObject obj = (PetscObject)draw;
 53:   PetscDrawHG h;

 58:   PetscTypeCompare(obj,PETSC_DRAW_NULL,&isnull);
 59:   if (isnull) {
 60:     PetscDrawOpenNull(obj->comm,(PetscDraw*)hist);
 61:     return(0);
 62:   }
 63:   PetscHeaderCreate(h,_p_DrawHG,int,DRAWHG_COOKIE,0,"PetscDrawHG",obj->comm,PetscDrawHGDestroy,0);
 64:   h->view      = 0;
 65:   h->destroy   = 0;
 66:   h->win       = draw;
 67:   h->color     = PETSC_DRAW_GREEN;
 68:   h->xmin      = PETSC_MAX;
 69:   h->xmax      = PETSC_MIN;
 70:   h->ymin      = 0.;
 71:   h->ymax      = 1.;
 72:   h->numBins   = bins;
 73:   PetscMalloc(bins*sizeof(PetscReal),&h->bins);
 74:   h->numValues = 0;
 75:   h->maxValues = CHUNKSIZE;
 76:   ierr         = PetscMalloc(h->maxValues*sizeof(PetscReal),&h->values);
 77:   PetscLogObjectMemory(h,bins*sizeof(PetscReal) + h->maxValues*sizeof(PetscReal));
 78:   PetscDrawAxisCreate(draw,&h->axis);
 79:   PetscLogObjectParent(h,h->axis);
 80:   *hist = h;
 81:   return(0);
 82: }

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

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

 89:    Input Parameter:
 90: +  hist - The histogram context.
 91: -  dim  - The number of curves.

 93:    Level: intermediate

 95:   Contributed by: Matthew Knepley

 97:    Concepts: histogram^setting number of bins

 99: @*/
100: int PetscDrawHGSetNumberBins(PetscDrawHG hist,int bins)
101: {

105:   if (hist && hist->cookie == PETSC_DRAW_COOKIE) return(0);

108:   if (hist->numBins == bins) return(0);

110:   ierr          = PetscFree(hist->bins);
111:   PetscMalloc(bins*sizeof(PetscReal),&hist->bins);
112:   PetscLogObjectMemory(hist,(bins - hist->numBins) * sizeof(PetscReal));
113:   hist->numBins = bins;
114:   return(0);
115: }

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

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

122:   Input Parameter:
123: . hist - The histogram context.

125:    Level: intermediate

127:   Contributed by: Matthew Knepley

129:    Concepts: histogram^resetting

131: @*/
132: int PetscDrawHGReset(PetscDrawHG hist)
133: {
135:   if (hist && hist->cookie == PETSC_DRAW_COOKIE) return(0);
137:   hist->xmin      = PETSC_MAX;
138:   hist->xmax      = PETSC_MIN;
139:   hist->ymin      = 0;
140:   hist->ymax      = 0;
141:   hist->numValues = 0;
142:   return(0);
143: }

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

148:   Collective over PetscDrawHG

150:   Input Parameter:
151: . hist - The histogram context

153:    Level: intermediate

155:   Contributed by: Matthew Knepley

157: .seealso:  PetscDrawHGCreate()
158: @*/
159: int PetscDrawHGDestroy(PetscDrawHG hist)
160: {


166:   if (--hist->refct > 0) return(0);
167:   if (hist->cookie == PETSC_DRAW_COOKIE){
168:     PetscDrawDestroy((PetscDraw) hist);
169:     return(0);
170:   }

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

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

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

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

189:    Level: intermediate

191:   Contributed by: Matthew Knepley

193:   Concepts: histogram^adding values

195: .seealso: PetscDrawHGAddValues()
196: @*/
197: int PetscDrawHGAddValue(PetscDrawHG hist,PetscReal value)
198: {
200:   if (hist && hist->cookie == PETSC_DRAW_COOKIE) return(0);

203:   /* Allocate more memory if necessary */
204:   if (hist->numValues >= hist->maxValues) {
205:     PetscReal *tmp;
206:     int     ierr;

208:     PetscMalloc((hist->maxValues+CHUNKSIZE)*sizeof(PetscReal),&tmp);
209:     PetscLogObjectMemory(hist,CHUNKSIZE * sizeof(PetscReal));
210:     PetscMemcpy(tmp,hist->values,hist->maxValues * sizeof(PetscReal));
211:     PetscFree(hist->values);
212:     hist->values     = tmp;
213:     hist->maxValues += CHUNKSIZE;
214:   }
215:   if (!hist->numValues) {
216:     hist->xmin = value;
217:     hist->xmax = value;
218:   } else if (hist->numValues == 1) {
219:     /* Update limits -- We need to overshoot the largest value somewhat */
220:     if (value > hist->xmax)
221:       hist->xmax = value + 0.001*(value - hist->xmin)/hist->numBins;
222:     if (value < hist->xmin)
223:     {
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) {
230:       hist->xmax = value + 0.001*(hist->xmax - hist->xmin)/hist->numBins;
231:     }
232:     if (value < hist->xmin) {
233:       hist->xmin = value;
234:     }
235:   }

237:   hist->values[hist->numValues++] = value;
238:   return(0);
239: }

241: /*@
242:   PetscDrawHGDraw - Redraws a histogram.

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

246:   Input Parameter:
247: . hist - The histogram context

249:    Level: intermediate

251:   Contributed by: Matthew Knepley

253: @*/
254: int PetscDrawHGDraw(PetscDrawHG hist)
255: {
256:   PetscDraw   draw;
257:   PetscReal   xmin,xmax,ymin,ymax,*bins,*values,binSize,binLeft,binRight,maxHeight;
258:   int         numBins,numValues,i,p,ierr,bcolor,color,rank;

261:   if (hist && hist->cookie == PETSC_DRAW_COOKIE) return(0);
263:   if ((hist->xmin >= hist->xmax) || (hist->ymin >= hist->ymax)) return(0);
264:   if (hist->numValues < 1) return(0);

266:   MPI_Comm_rank(hist->comm,&rank);
267:   if (rank) return(0);

269:   color = hist->color;
270:   if (color == PETSC_DRAW_ROTATE) {bcolor = 2;} else {bcolor = color;}
271:   draw       = hist->win;
272:   xmin      = hist->xmin;
273:   xmax      = hist->xmax;
274:   ymin      = hist->ymin;
275:   ymax      = hist->ymax;
276:   numBins   = hist->numBins;
277:   bins      = hist->bins;
278:   numValues = hist->numValues;
279:   values    = hist->values;
280:   binSize   = (xmax - xmin)/numBins;

282:   PetscDrawClear(draw);
283:   /* Calculate number of points in each bin */
284:   PetscMemzero(bins,numBins * sizeof(PetscReal));
285:   maxHeight = 0;
286:   for (i = 0; i < numBins; i++) {
287:     binLeft   = xmin + binSize*i;
288:     binRight  = xmin + binSize*(i+1);
289:     for(p = 0; p < numValues; p++) {
290:       if ((values[p] >= binLeft) && (values[p] < binRight)) bins[i]++;
291:     }
292:     maxHeight = PetscMax(maxHeight,bins[i]);
293:   }
294:   if (maxHeight > ymax) ymax = hist->ymax = maxHeight;
295:   PetscDrawAxisSetLimits(hist->axis,xmin,xmax,ymin,ymax);
296:   PetscDrawAxisDraw(hist->axis);
297:   /* PetscDraw bins */
298:   for (i = 0; i < numBins; i++) {
299:     binLeft   = xmin + binSize*i;
300:     binRight  = xmin + binSize*(i+1);
301:     PetscDrawRectangle(draw,binLeft,ymin,binRight,bins[i],bcolor,bcolor,bcolor,bcolor);
302:     if (color == PETSC_DRAW_ROTATE && bins[i]) bcolor++; if (bcolor > 31) bcolor = 2;
303:     PetscDrawLine(draw,binLeft,ymin,binLeft,bins[i],PETSC_DRAW_BLACK);
304:     PetscDrawLine(draw,binRight,ymin,binRight,bins[i],PETSC_DRAW_BLACK);
305:     PetscDrawLine(draw,binLeft,bins[i],binRight,bins[i],PETSC_DRAW_BLACK);
306:   }
307:   PetscDrawFlush(draw);
308:   PetscDrawPause(draw);
309:   return(0);
310: }
311: 
312: /*@
313:   PetscDrawHGSetColor - Sets the color the bars will be drawn with.

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

317:   Input Parameters:
318: + hist - The histogram context
319: - color - one of the colors defined in petscdraw.h or PETSC_DRAW_ROTATE to make each bar a 
320:           different color

322:   Level: intermediate

324: @*/
325: int PetscDrawHGSetColor(PetscDrawHG hist,int color)
326: {
328:   if (hist && hist->cookie == PETSC_DRAW_COOKIE) return(0);
330:   hist->color = color;
331:   return(0);
332: }

334: /*@
335:   PetscDrawHGSetLimits - Sets the axis limits for a histogram. If more
336:   points are added after this call, the limits will be adjusted to
337:   include those additional points.

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

341:   Input Parameters:
342: + hist - The histogram context
343: - x_min,x_max,y_min,y_max - The limits

345:   Level: intermediate

347:   Contributed by: Matthew Knepley

349:   Concepts: histogram^setting axis

351: @*/
352: int PetscDrawHGSetLimits(PetscDrawHG hist,PetscReal x_min,PetscReal x_max,int y_min,int y_max)
353: {
355:   if (hist && hist->cookie == PETSC_DRAW_COOKIE) return(0);
357:   hist->xmin = x_min;
358:   hist->xmax = x_max;
359:   hist->ymin = y_min;
360:   hist->ymax = y_max;
361:   return(0);
362: }
363: 
364: /*@C
365:   PetscDrawHGGetAxis - Gets the axis context associated with a histogram.
366:   This is useful if one wants to change some axis property, such as
367:   labels, color, etc. The axis context should not be destroyed by the
368:   application code.

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

372:   Input Parameter:
373: . hist - The histogram context

375:   Output Parameter:
376: . axis - The axis context

378:   Level: intermediate

380:   Contributed by: Matthew Knepley

382: @*/
383: int PetscDrawHGGetAxis(PetscDrawHG hist,PetscDrawAxis *axis)
384: {
386:   if (hist && hist->cookie == PETSC_DRAW_COOKIE) {
387:     *axis = 0;
388:     return(0);
389:   }
391:   *axis = hist->axis;
392:   return(0);
393: }

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

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

400:   Input Parameter:
401: . hist - The histogram context

403:   Output Parameter:
404: . win  - The draw context

406:   Level: intermediate

408:   Contributed by: Matthew Knepley

410: @*/
411: int PetscDrawHGGetDraw(PetscDrawHG hist,PetscDraw *win)
412: {
415:   if (hist && hist->cookie == PETSC_DRAW_COOKIE) {
416:     *win = (PetscDraw)hist;
417:   } else {
418:     *win = hist->win;
419:   }
420:   return(0);
421: }