xref: /petsc/src/sys/classes/draw/utils/axisc.c (revision fbf9dbe564678ed6eff1806adbc4c4f01b9743f4)
1 #include <petsc/private/drawimpl.h> /*I   "petscdraw.h"  I*/
2 
3 #define PETSC_DRAW_AXIS_MAX_SEGMENTS 20
4 PetscClassId PETSC_DRAWAXIS_CLASSID = 0;
5 
6 /*@
7    PetscDrawAxisCreate - Generate the axis data structure.
8 
9    Collective
10 
11    Input Parameter:
12 .  win - `PetscDraw` object where axis to to be made
13 
14    Output Parameter:
15 .  axis - the axis datastructure
16 
17    Note:
18    The MPI communicator that owns the underlying draw object owns the `PetscDrawAxis` object, but calls to set `PetscDrawAxis` options are
19    ignored by all processes except the first MPI rank in the communicator
20 
21    Level: advanced
22 
23 .seealso: `PetscDrawLGCreate()`, `PetscDrawLG`, `PetscDrawSPCreate()`, `PetscDrawSP`, `PetscDrawHGCreate()`, `PetscDrawHG`, `PetscDrawBarCreate()`, `PetscDrawBar`, `PetscDrawLGGetAxis()`, `PetscDrawSPGetAxis()`,
24           `PetscDrawHGGetAxis()`, `PetscDrawBarGetAxis()`, `PetscDrawAxis`, `PetscDrawAxisDestroy()`, `PetscDrawAxisSetColors()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetLimits()`, `PetscDrawAxisGetLimits()`, `PetscDrawAxisSetHoldLimits()`,
25           `PetscDrawAxisDraw()`
26 @*/
27 PetscErrorCode PetscDrawAxisCreate(PetscDraw draw, PetscDrawAxis *axis)
28 {
29   PetscDrawAxis ad;
30 
31   PetscFunctionBegin;
32   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
33   PetscValidPointer(axis, 2);
34 
35   PetscCall(PetscHeaderCreate(ad, PETSC_DRAWAXIS_CLASSID, "DrawAxis", "Draw Axis", "Draw", PetscObjectComm((PetscObject)draw), PetscDrawAxisDestroy, NULL));
36 
37   PetscCall(PetscObjectReference((PetscObject)draw));
38   ad->win = draw;
39 
40   ad->xticks    = PetscADefTicks;
41   ad->yticks    = PetscADefTicks;
42   ad->xlabelstr = PetscADefLabel;
43   ad->ylabelstr = PetscADefLabel;
44   ad->ac        = PETSC_DRAW_BLACK;
45   ad->tc        = PETSC_DRAW_BLACK;
46   ad->cc        = PETSC_DRAW_BLACK;
47   ad->xlabel    = NULL;
48   ad->ylabel    = NULL;
49   ad->toplabel  = NULL;
50 
51   *axis = ad;
52   PetscFunctionReturn(PETSC_SUCCESS);
53 }
54 
55 /*@
56     PetscDrawAxisDestroy - Frees the space used by an axis structure.
57 
58     Collective
59 
60     Input Parameter:
61 .   axis - the axis context
62 
63     Level: advanced
64 
65 .seealso: `PetscDraw`, `PetscDrawAxisCreate()`, `PetscDrawAxis`
66 @*/
67 PetscErrorCode PetscDrawAxisDestroy(PetscDrawAxis *axis)
68 {
69   PetscFunctionBegin;
70   if (!*axis) PetscFunctionReturn(PETSC_SUCCESS);
71   PetscValidHeaderSpecific(*axis, PETSC_DRAWAXIS_CLASSID, 1);
72   if (--((PetscObject)(*axis))->refct > 0) {
73     *axis = NULL;
74     PetscFunctionReturn(PETSC_SUCCESS);
75   }
76 
77   PetscCall(PetscFree((*axis)->toplabel));
78   PetscCall(PetscFree((*axis)->xlabel));
79   PetscCall(PetscFree((*axis)->ylabel));
80   PetscCall(PetscDrawDestroy(&(*axis)->win));
81   PetscCall(PetscHeaderDestroy(axis));
82   PetscFunctionReturn(PETSC_SUCCESS);
83 }
84 
85 /*@
86     PetscDrawAxisSetColors -  Sets the colors to be used for the axis,
87                          tickmarks, and text.
88 
89     Logically Collective
90 
91     Input Parameters:
92 +   axis - the axis
93 .   ac - the color of the axis lines
94 .   tc - the color of the tick marks
95 -   cc - the color of the text strings
96 
97     Level: advanced
98 
99 .seealso: `PetscDraw`, `PetscDrawAxisCreate()`, `PetscDrawAxis`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisDraw()`, `PetscDrawAxisSetLimits()`
100 @*/
101 PetscErrorCode PetscDrawAxisSetColors(PetscDrawAxis axis, int ac, int tc, int cc)
102 {
103   PetscFunctionBegin;
104   PetscValidHeaderSpecific(axis, PETSC_DRAWAXIS_CLASSID, 1);
105   PetscValidLogicalCollectiveInt(axis, ac, 2);
106   PetscValidLogicalCollectiveInt(axis, tc, 3);
107   PetscValidLogicalCollectiveInt(axis, cc, 4);
108   axis->ac = ac;
109   axis->tc = tc;
110   axis->cc = cc;
111   PetscFunctionReturn(PETSC_SUCCESS);
112 }
113 
114 /*@C
115     PetscDrawAxisSetLabels -  Sets the x and y axis labels.
116 
117     Logically Collective
118 
119     Input Parameters:
120 +   axis - the axis
121 .   top - the label at the top of the image
122 -   xlabel,ylabel - the labes for the x and y axis
123 
124     Level: advanced
125 
126     Notes:
127     Must be called before `PetscDrawAxisDraw()` or `PetscDrawLGDraw()`
128 
129     There should be no newlines in the arguments
130 
131 .seealso: `PetscDraw`, `PetscDrawAxisCreate()`, `PetscDrawAxis`, `PetscDrawAxisSetColors()`, `PetscDrawAxisDraw()`, `PetscDrawAxisSetLimits()`
132 @*/
133 PetscErrorCode PetscDrawAxisSetLabels(PetscDrawAxis axis, const char top[], const char xlabel[], const char ylabel[])
134 {
135   PetscFunctionBegin;
136   PetscValidHeaderSpecific(axis, PETSC_DRAWAXIS_CLASSID, 1);
137   PetscCall(PetscFree(axis->xlabel));
138   PetscCall(PetscFree(axis->ylabel));
139   PetscCall(PetscFree(axis->toplabel));
140   PetscCall(PetscStrallocpy(xlabel, &axis->xlabel));
141   PetscCall(PetscStrallocpy(ylabel, &axis->ylabel));
142   PetscCall(PetscStrallocpy(top, &axis->toplabel));
143   PetscFunctionReturn(PETSC_SUCCESS);
144 }
145 
146 /*@
147     PetscDrawAxisSetLimits -  Sets the limits (in user coords) of the axis
148 
149     Logically Collective
150 
151     Input Parameters:
152 +   axis - the axis
153 .   xmin,xmax - limits in x
154 -   ymin,ymax - limits in y
155 
156     Options Database Key:
157 .   -drawaxis_hold - hold the initial set of axis limits for future plotting
158 
159     Level: advanced
160 
161 .seealso: `PetscDrawAxisSetHoldLimits()`, `PetscDrawAxisGetLimits()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetColors()`
162 @*/
163 PetscErrorCode PetscDrawAxisSetLimits(PetscDrawAxis axis, PetscReal xmin, PetscReal xmax, PetscReal ymin, PetscReal ymax)
164 {
165   PetscFunctionBegin;
166   PetscValidHeaderSpecific(axis, PETSC_DRAWAXIS_CLASSID, 1);
167   if (axis->hold) PetscFunctionReturn(PETSC_SUCCESS);
168   axis->xlow  = xmin;
169   axis->xhigh = xmax;
170   axis->ylow  = ymin;
171   axis->yhigh = ymax;
172   PetscCall(PetscOptionsHasName(((PetscObject)axis)->options, ((PetscObject)axis)->prefix, "-drawaxis_hold", &axis->hold));
173   PetscFunctionReturn(PETSC_SUCCESS);
174 }
175 
176 /*@
177     PetscDrawAxisGetLimits -  Gets the limits (in user coords) of the axis
178 
179     Not Collective
180 
181     Input Parameters:
182 +   axis - the axis
183 .   xmin,xmax - limits in x
184 -   ymin,ymax - limits in y
185 
186     Level: advanced
187 
188 .seealso: `PetscDrawAxisCreate()`, `PetscDrawAxis`, `PetscDrawAxisSetHoldLimits()`, `PetscDrawAxisSetLimits()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetColors()`
189 @*/
190 PetscErrorCode PetscDrawAxisGetLimits(PetscDrawAxis axis, PetscReal *xmin, PetscReal *xmax, PetscReal *ymin, PetscReal *ymax)
191 {
192   PetscFunctionBegin;
193   PetscValidHeaderSpecific(axis, PETSC_DRAWAXIS_CLASSID, 1);
194   if (xmin) *xmin = axis->xlow;
195   if (xmax) *xmax = axis->xhigh;
196   if (ymin) *ymin = axis->ylow;
197   if (ymax) *ymax = axis->yhigh;
198   PetscFunctionReturn(PETSC_SUCCESS);
199 }
200 
201 /*@
202     PetscDrawAxisSetHoldLimits -  Causes an axis to keep the same limits until this is called
203         again
204 
205     Logically Collective
206 
207     Input Parameters:
208 +   axis - the axis
209 -   hold - `PETSC_TRUE` - hold current limits, `PETSC_FALSE` allow limits to be changed
210 
211     Level: advanced
212 
213     Note:
214         Once this has been called with `PETSC_TRUE` the limits will not change if you call
215      `PetscDrawAxisSetLimits()` until you call this with `PETSC_FALSE`
216 
217 .seealso: `PetscDrawAxisCreate()`, `PetscDrawAxis`, `PetscDrawAxisGetLimits()`, `PetscDrawAxisSetLimits()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetColors()`
218 @*/
219 PetscErrorCode PetscDrawAxisSetHoldLimits(PetscDrawAxis axis, PetscBool hold)
220 {
221   PetscFunctionBegin;
222   PetscValidHeaderSpecific(axis, PETSC_DRAWAXIS_CLASSID, 1);
223   PetscValidLogicalCollectiveBool(axis, hold, 2);
224   axis->hold = hold;
225   PetscFunctionReturn(PETSC_SUCCESS);
226 }
227 
228 /*@
229     PetscDrawAxisDraw - draws an axis.
230 
231     Collective
232 
233     Input Parameter:
234 .   axis - `PetscDrawAxis` structure
235 
236     Level: advanced
237 
238     Note:
239     This draws the actual axis.  The limits etc have already been set.
240     By picking special routines for the ticks and labels, special
241     effects may be generated.  These routines are part of the Axis
242     structure (axis).
243 
244 .seealso: `PetscDrawAxisCreate()`, `PetscDrawAxis`, `PetscDrawAxisGetLimits()`, `PetscDrawAxisSetLimits()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetColors()`
245 @*/
246 PetscErrorCode PetscDrawAxisDraw(PetscDrawAxis axis)
247 {
248   int         i, ntick, numx, numy, ac, tc, cc;
249   PetscMPIInt rank;
250   size_t      len, ytlen = 0;
251   PetscReal   coors[4], tickloc[PETSC_DRAW_AXIS_MAX_SEGMENTS], sep, tw, th;
252   PetscReal   xl, xr, yl, yr, dxl = 0, dyl = 0, dxr = 0, dyr = 0;
253   char       *p;
254   PetscDraw   draw;
255   PetscBool   isnull;
256 
257   PetscFunctionBegin;
258   PetscValidHeaderSpecific(axis, PETSC_DRAWAXIS_CLASSID, 1);
259   PetscCall(PetscDrawIsNull(axis->win, &isnull));
260   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
261   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)axis), &rank));
262 
263   draw = axis->win;
264 
265   ac = axis->ac;
266   tc = axis->tc;
267   cc = axis->cc;
268   if (axis->xlow == axis->xhigh) {
269     axis->xlow -= .5;
270     axis->xhigh += .5;
271   }
272   if (axis->ylow == axis->yhigh) {
273     axis->ylow -= .5;
274     axis->yhigh += .5;
275   }
276 
277   PetscDrawCollectiveBegin(draw);
278   if (rank) goto finally;
279 
280   /* get canonical string size */
281   PetscCall(PetscDrawSetCoordinates(draw, 0, 0, 1, 1));
282   PetscCall(PetscDrawStringGetSize(draw, &tw, &th));
283   /* lower spacing */
284   if (axis->xlabelstr) dyl += 1.5 * th;
285   if (axis->xlabel) dyl += 1.5 * th;
286   /* left spacing */
287   if (axis->ylabelstr) dxl += 7.5 * tw;
288   if (axis->ylabel) dxl += 2.0 * tw;
289   /* right and top spacing */
290   if (axis->xlabelstr) dxr = 2.5 * tw;
291   if (axis->ylabelstr) dyr = 0.5 * th;
292   if (axis->toplabel) dyr = 1.5 * th;
293   /* extra spacing */
294   dxl += 0.7 * tw;
295   dxr += 0.5 * tw;
296   dyl += 0.2 * th;
297   dyr += 0.2 * th;
298   /* determine coordinates */
299   xl = (dxl * axis->xhigh + dxr * axis->xlow - axis->xlow) / (dxl + dxr - 1);
300   xr = (dxl * axis->xhigh + dxr * axis->xlow - axis->xhigh) / (dxl + dxr - 1);
301   yl = (dyl * axis->yhigh + dyr * axis->ylow - axis->ylow) / (dyl + dyr - 1);
302   yr = (dyl * axis->yhigh + dyr * axis->ylow - axis->yhigh) / (dyl + dyr - 1);
303   PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr));
304   PetscCall(PetscDrawStringGetSize(draw, &tw, &th));
305 
306   /* PetscDraw the axis lines */
307   PetscCall(PetscDrawLine(draw, axis->xlow, axis->ylow, axis->xhigh, axis->ylow, ac));
308   PetscCall(PetscDrawLine(draw, axis->xlow, axis->ylow, axis->xlow, axis->yhigh, ac));
309   PetscCall(PetscDrawLine(draw, axis->xlow, axis->yhigh, axis->xhigh, axis->yhigh, ac));
310   PetscCall(PetscDrawLine(draw, axis->xhigh, axis->ylow, axis->xhigh, axis->yhigh, ac));
311 
312   /* PetscDraw the top label */
313   if (axis->toplabel) {
314     PetscReal x = (axis->xlow + axis->xhigh) / 2, y = axis->yhigh + 0.5 * th;
315     PetscCall(PetscDrawStringCentered(draw, x, y, cc, axis->toplabel));
316   }
317 
318   /* PetscDraw the X ticks and labels */
319   if (axis->xticks) {
320     numx = (int)(.15 * (axis->xhigh - axis->xlow) / tw);
321     numx = PetscClipInterval(numx, 2, 6);
322     PetscCall((*axis->xticks)(axis->xlow, axis->xhigh, numx, &ntick, tickloc, PETSC_DRAW_AXIS_MAX_SEGMENTS));
323     /* PetscDraw in tick marks */
324     for (i = 0; i < ntick; i++) {
325       PetscCall(PetscDrawLine(draw, tickloc[i], axis->ylow, tickloc[i], axis->ylow + .5 * th, tc));
326       PetscCall(PetscDrawLine(draw, tickloc[i], axis->yhigh, tickloc[i], axis->yhigh - .5 * th, tc));
327     }
328     /* label ticks */
329     if (axis->xlabelstr) {
330       for (i = 0; i < ntick; i++) {
331         if (i < ntick - 1) sep = tickloc[i + 1] - tickloc[i];
332         else if (i > 0) sep = tickloc[i] - tickloc[i - 1];
333         else sep = 0.0;
334         PetscCall((*axis->xlabelstr)(tickloc[i], sep, &p));
335         PetscCall(PetscDrawStringCentered(draw, tickloc[i], axis->ylow - 1.5 * th, cc, p));
336       }
337     }
338   }
339   if (axis->xlabel) {
340     PetscReal x = (axis->xlow + axis->xhigh) / 2, y = axis->ylow - 1.5 * th;
341     if (axis->xlabelstr) y -= 1.5 * th;
342     PetscCall(PetscDrawStringCentered(draw, x, y, cc, axis->xlabel));
343   }
344 
345   /* PetscDraw the Y ticks and labels */
346   if (axis->yticks) {
347     numy = (int)(.50 * (axis->yhigh - axis->ylow) / th);
348     numy = PetscClipInterval(numy, 2, 6);
349     PetscCall((*axis->yticks)(axis->ylow, axis->yhigh, numy, &ntick, tickloc, PETSC_DRAW_AXIS_MAX_SEGMENTS));
350     /* PetscDraw in tick marks */
351     for (i = 0; i < ntick; i++) {
352       PetscCall(PetscDrawLine(draw, axis->xlow, tickloc[i], axis->xlow + .5 * tw, tickloc[i], tc));
353       PetscCall(PetscDrawLine(draw, axis->xhigh, tickloc[i], axis->xhigh - .5 * tw, tickloc[i], tc));
354     }
355     /* label ticks */
356     if (axis->ylabelstr) {
357       for (i = 0; i < ntick; i++) {
358         if (i < ntick - 1) sep = tickloc[i + 1] - tickloc[i];
359         else if (i > 0) sep = tickloc[i] - tickloc[i - 1];
360         else sep = 0.0;
361         PetscCall((*axis->ylabelstr)(tickloc[i], sep, &p));
362         PetscCall(PetscStrlen(p, &len));
363         ytlen = PetscMax(ytlen, len);
364         PetscCall(PetscDrawString(draw, axis->xlow - (len + .5) * tw, tickloc[i] - .5 * th, cc, p));
365       }
366     }
367   }
368   if (axis->ylabel) {
369     PetscReal x = axis->xlow - 2.0 * tw, y = (axis->ylow + axis->yhigh) / 2;
370     if (axis->ylabelstr) x -= (ytlen + .5) * tw;
371     PetscCall(PetscStrlen(axis->ylabel, &len));
372     PetscCall(PetscDrawStringVertical(draw, x, y + len * th / 2, cc, axis->ylabel));
373   }
374 
375   PetscCall(PetscDrawGetCoordinates(draw, &coors[0], &coors[1], &coors[2], &coors[3]));
376 finally:
377   PetscDrawCollectiveEnd(draw);
378   PetscCallMPI(MPI_Bcast(coors, 4, MPIU_REAL, 0, PetscObjectComm((PetscObject)draw)));
379   PetscCall(PetscDrawSetCoordinates(draw, coors[0], coors[1], coors[2], coors[3]));
380   PetscFunctionReturn(PETSC_SUCCESS);
381 }
382 
383 /*
384     Removes all zeros but one from .0000
385 */
386 PetscErrorCode PetscStripe0(char *buf)
387 {
388   size_t    n;
389   PetscBool flg;
390   char     *str = NULL;
391 
392   PetscFunctionBegin;
393   PetscCall(PetscStrlen(buf, &n));
394   PetscCall(PetscStrendswith(buf, "e00", &flg));
395   if (flg) buf[n - 3] = 0;
396   PetscCall(PetscStrstr(buf, "e0", &str));
397   if (str) {
398     buf[n - 2] = buf[n - 1];
399     buf[n - 1] = 0;
400   }
401   PetscCall(PetscStrstr(buf, "e-0", &str));
402   if (str) {
403     buf[n - 2] = buf[n - 1];
404     buf[n - 1] = 0;
405   }
406   PetscFunctionReturn(PETSC_SUCCESS);
407 }
408 
409 /*
410     Removes all zeros but one from .0000
411 */
412 PetscErrorCode PetscStripAllZeros(char *buf)
413 {
414   size_t i, n;
415 
416   PetscFunctionBegin;
417   PetscCall(PetscStrlen(buf, &n));
418   if (buf[0] != '.') PetscFunctionReturn(PETSC_SUCCESS);
419   for (i = 1; i < n; i++) {
420     if (buf[i] != '0') PetscFunctionReturn(PETSC_SUCCESS);
421   }
422   buf[0] = '0';
423   buf[1] = 0;
424   PetscFunctionReturn(PETSC_SUCCESS);
425 }
426 
427 /*
428     Removes trailing zeros
429 */
430 #if (PETSC_SIZEOF_SIZE_T == 8)
431   #define MAX_SIZE_T PETSC_INT64_MAX
432 #else
433   #define MAX_SIZE_T INT_MAX
434 #endif
435 PetscErrorCode PetscStripTrailingZeros(char *buf)
436 {
437   char  *found = NULL;
438   size_t i, n, m = MAX_SIZE_T;
439 
440   PetscFunctionBegin;
441   /* if there is an e in string DO NOT strip trailing zeros */
442   PetscCall(PetscStrchr(buf, 'e', &found));
443   if (found) PetscFunctionReturn(PETSC_SUCCESS);
444 
445   PetscCall(PetscStrlen(buf, &n));
446   /* locate decimal point */
447   for (i = 0; i < n; i++) {
448     if (buf[i] == '.') {
449       m = i;
450       break;
451     }
452   }
453   /* if not decimal point then no zeros to remove */
454   if (m == MAX_SIZE_T) PetscFunctionReturn(PETSC_SUCCESS);
455   /* start at right end of string removing 0s */
456   for (i = n - 1; i > m; i++) {
457     if (buf[i] != '0') PetscFunctionReturn(PETSC_SUCCESS);
458     buf[i] = 0;
459   }
460   PetscFunctionReturn(PETSC_SUCCESS);
461 }
462 
463 /*
464     Removes leading 0 from 0.22 or -0.22
465 */
466 PetscErrorCode PetscStripInitialZero(char *buf)
467 {
468   size_t i, n;
469 
470   PetscFunctionBegin;
471   PetscCall(PetscStrlen(buf, &n));
472   if (buf[0] == '0') {
473     for (i = 0; i < n; i++) buf[i] = buf[i + 1];
474   } else if (buf[0] == '-' && buf[1] == '0') {
475     for (i = 1; i < n; i++) buf[i] = buf[i + 1];
476   }
477   PetscFunctionReturn(PETSC_SUCCESS);
478 }
479 
480 /*
481      Removes the extraneous zeros in numbers like 1.10000e6
482 */
483 PetscErrorCode PetscStripZeros(char *buf)
484 {
485   size_t i, j, n;
486 
487   PetscFunctionBegin;
488   PetscCall(PetscStrlen(buf, &n));
489   if (n < 5) PetscFunctionReturn(PETSC_SUCCESS);
490   for (i = 1; i < n - 1; i++) {
491     if (buf[i] == 'e' && buf[i - 1] == '0') {
492       for (j = i; j < n + 1; j++) buf[j - 1] = buf[j];
493       PetscCall(PetscStripZeros(buf));
494       PetscFunctionReturn(PETSC_SUCCESS);
495     }
496   }
497   PetscFunctionReturn(PETSC_SUCCESS);
498 }
499 
500 /*
501       Removes the plus in something like 1.1e+2 or 1.1e+02
502 */
503 PetscErrorCode PetscStripZerosPlus(char *buf)
504 {
505   size_t i, j, n;
506 
507   PetscFunctionBegin;
508   PetscCall(PetscStrlen(buf, &n));
509   if (n < 5) PetscFunctionReturn(PETSC_SUCCESS);
510   for (i = 1; i < n - 2; i++) {
511     if (buf[i] == '+') {
512       if (buf[i + 1] == '0') {
513         for (j = i + 1; j < n; j++) buf[j - 1] = buf[j + 1];
514         PetscFunctionReturn(PETSC_SUCCESS);
515       } else {
516         for (j = i + 1; j < n + 1; j++) buf[j - 1] = buf[j];
517         PetscFunctionReturn(PETSC_SUCCESS);
518       }
519     } else if (buf[i] == '-') {
520       if (buf[i + 1] == '0') {
521         for (j = i + 1; j < n; j++) buf[j] = buf[j + 1];
522         PetscFunctionReturn(PETSC_SUCCESS);
523       }
524     }
525   }
526   PetscFunctionReturn(PETSC_SUCCESS);
527 }
528