/* File: plot.c * Author: Richard Durbin (rd@mrc-lmb.cam.ac.uk) * Copyright (C) J Thierry-Mieg and R Durbin, 1992 * ------------------------------------------------------------------- * Acedb is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * or see the on-line version at http://www.gnu.org/copyleft/gpl.txt * ------------------------------------------------------------------- * This file is part of the ACEDB genome database package, written by * Richard Durbin (MRC LMB, UK) rd@mrc-lmb.cam.ac.uk, and * Jean Thierry-Mieg (CRBM du CNRS, France) mieg@kaa.cnrs-mop.fr * * Description: to plot various sorts of data * Exported functions: plotHisto() * HISTORY: * Last edited: May 6 10:23 2003 (edgrif) * * Apr 4 13:51 1995 (rd) * Created: Tue May 19 22:57:41 1992 (rd) * CVS info: $Id: plot.c,v 1.30 2003/05/06 13:13:13 edgrif Exp $ *------------------------------------------------------------------- */ #include #include #include #include #include static int PLOT_MAGIC = 237165; /* also use address as graphAss handle */ typedef struct LOOKstruct { int magic ; Array a, originalArray ; char title[48], subtitle[24] ; char fileName[FIL_BUFFER_SIZE] ; char dirName[DIR_BUFFER_SIZE] ; int xyBox, retBox, sBox, zoneBox,stepBox, titleBox, subtitleBox ; int s , minX, maxX, startStep, step ; /* mhmp 10.03.99 float shift + xMax */ float x, y, minY, maxY, shift, xMin, xEnd, xMax, scale, startScale ; int xMul, xDiv,facY ; char sBuffer [8], zoneBuffer [24], xBuffer [16], yBuffer [16], stepBuffer [10] ; BOOL reticule, isStepping, isSmoothing, plus1, isPrinting ; float oldx, oldy ; float Xmag, Ymag,axisShift ; float firstX, firstY ; int leftMargin, topMargin ; Graph graph ; } *LOOK ; #define LOOKGET(name) LOOK look ; \ if (!graphAssFind (&PLOT_MAGIC, &look)) \ messcrash ("graph not found in %s", name) ; \ if (look->magic != PLOT_MAGIC) \ messcrash ("%s received a wrong pointer",name) static Graph plotDisplay (void) ; static void logxTransform (void) ; static void logyTransform (void) ; static void plotCorrel (void) ; static Array convert (Array a) ; #define XX(_x) (look->leftMargin + (_x - look->firstX) * look->Xmag) #define YY(_y) (look->topMargin + (look->maxY - _y) * look->Ymag) static Array plotCurrHis = 0 ; /* to know the created Histo */ static int plotCurrNb ; static void plotCopy (void) ; static void plotSave (void) ; static void plotLoad (void) ; static void plotInit (void) ; static void plotLoadAscii (void) ; static void plotRefresh (void); static void smoothingBoxEntry (char *cp) ; static void zoneBoxEntry (char *cp) ; static void histoStatistics(void); static void histoExport (void); static void histoImport (void); static void plotPrint (void) ; /******************************************************************/ static MENUOPT histoMenu[]={ {graphDestroy, "Quit"}, {help, "Help"}, {plotPrint, "Print"}, {plotRefresh, "Refresh"}, {histoStatistics, "Statistics"}, {histoExport, "Export"}, {histoImport, "Import"}, {logyTransform, "log(y) :: x"}, {logxTransform, "y :: log(x)"}, {plotCorrel, "z(t)= y(x) y(x+t)"}, {plotCopy, "Duplicate"}, {plotSave, "Save"}, {plotLoad, "Load"}, {plotLoadAscii, "Load Ascii"}, {plotHistoRemove, "Kill all histograms"}, {0,0} }; /*************************************************************************/ /*************************************************************************/ static void plotDestroy(void) { LOOKGET("plotDestroy") ; look->magic = 0 ; arrayDestroy (look->a) ; arrayDestroy (look->originalArray) ; messfree (look) ; graphAssRemove (&PLOT_MAGIC) ; plotCurrNb-- ; if (!plotCurrNb) arrayDestroy(plotCurrHis) ; } /******************************************************************/ static void makeReticule(LOOK look) { /* mhmp 08.03.99 */ float x ; x = look->shift + look->x/look->scale ; sprintf (look->xBuffer, "%g", x/look->xDiv) ; sprintf (look->yBuffer, "%g", look->y) ; look->reticule = TRUE ; plotDisplay () ; } /******************************************************************/ static void moveReticule (int box, double x, double y, int modifier_unused) { LOOKGET("moveReticule") ; if (box == look->sBox) { graphTextEntry (look->sBuffer, 0, 0, 0, 0) ; return ; } if (box == look->stepBox) { graphTextEntry (look->stepBuffer, 0, 0, 0, 0) ; return ; } if (box == look->zoneBox) { graphTextEntry (look->zoneBuffer, 0, 0, 0, 0) ; return ; } if (box == look->titleBox) { graphTextEntry (look->title, 0, 0, 0, 0) ; return ; } if (box == look->subtitleBox) { graphTextEntry (look->subtitle, 0, 0, 0, 0) ; return ; } if(box != look->retBox ) return ; y -= 3 ; /* axis overhangs by 3 units */ y /= look->Ymag ; /* mhmp 28.04.99 x-0.5*/ x -= look->axisShift ; x /= look->Xmag ; x += look->firstX ; y = -y + look->maxY*look->facY ; /* coord is relative to the axis box */ if(x == look->x && y == look->y) return ; look->x = x ; look->y = y ; makeReticule(look) ; } /***************************************/ static void plotPrint (void) { Graph old = graphActive(); LOOKGET("plotPrint") ; look->isPrinting = TRUE ; plotDisplay () ; graphPrint () ; graphActivate (old); look->isPrinting = FALSE ; plotDisplay () ; } /*************************************************************************/ static void histoStatistics(void) { double s = 0, s1, y, yt = 0, ym, yt2 = 0, xt = 0, xt2 = 0, xm = 0 ; int x, x1 ; Array a ; LOOKGET("histoStatistics") ; a = look->a ; if (!a || !arrayMax(a)) return ; for (x = 0 ; x < arrayMax(a) ; ++x) if ((y = arr(a,x,float))) { yt += y ; yt2 += y*y ; x1 = x + look->shift ; xt += y*x1 ; xt2 += y*x1*x1 ; } for (x = 0 ; x < arrayMax(a) ; ++x) if ((y = arr(a,x,float) > 0)) { s1 = y/yt ; s -= s1 * log (s1) ; } s1 = 2.0 ; s /= log (s1) ; /* go to log base 2 */ ym = yt / (float)arrayMax(a) ; if (arrayMax(a) > 1) yt2 = sqrt ((yt2 - ym*yt) / (arrayMax(a)-1)) ; else yt2 = 0 ; xm = xt/yt ; if (yt > 1) xt2 = sqrt ((xt2 - xm*xm*yt) / (yt-1)) ; else xt2 = 0 ; messout (messprintf ("Cumulated x = %f Average x = %f, sigma = %f\n" "Cumulated y = %f Average y = %f, sigma = %f\n Entropy %g bit/pixel", xt, xm, xt2, yt, ym, yt2, s)) ; } /*************************************************************************/ static void histoExport (void) { int *fp ; int i ; ACEOUT histo_out; LOOKGET("histoExport") ; if (look->originalArray && arrayMax(look->originalArray)) { histo_out = aceOutCreateToChooser ("Histo export file", look->dirName, look->fileName, "", "w", 0); if (!histo_out) return; aceOutPrint (histo_out, "%g\n", look->shift) ; aceOutPrint (histo_out, "%g\n", look->xEnd) ; aceOutPrint (histo_out, "%g\n", look->startScale) ; aceOutPrint (histo_out, "%d\n", look->xMul) ; i = arrayMax (look->originalArray) ; fp = arrp(look->originalArray, 0, int) ; while (i--) aceOutPrint (histo_out, "%d\n", *fp++) ; aceOutDestroy (histo_out); } else messout ("Sorry, no histogram"); return; } /* histoExport */ /*************************************************************************/ static void histoImport (void) { int max=0, i ; Array a ; float ff ; int nn; ACEIN histo_in; LOOKGET("histoImport") ; look->title[0] = '\0' ; look->subtitle[0] = '\0' ; histo_in = aceInCreateFromChooser("Text File of Integers", look->dirName,look->fileName, "histo", "r", 0); if (!histo_in) return; a = arrayCreate (1000, int) ; if (aceInCard(histo_in) && aceInFloat(histo_in, &ff)) look->shift = ff ; if (aceInCard(histo_in) && aceInFloat(histo_in, &ff)) look->xEnd = ff ; if (aceInCard(histo_in) && aceInFloat(histo_in, &ff)) look->startScale = ff ; if (aceInCard(histo_in) && aceInInt(histo_in, &nn)) look->xMul = nn ; i = 0 ; while (aceInCard(histo_in)) { if (aceInInt(histo_in, &nn)) array (a, i++, int) = nn ; } max = arrayMax(a) ; aceInDestroy (histo_in); plotInit() ; if(!max) { messout("I read an empty file") ; arrayDestroy(a) ; return; } if (!look->title || !*look->title) sprintf(look->title, "%s", look->fileName) ; graphRetitle (look->title) ; arrayDestroy (look->originalArray) ; arrayDestroy (look->a) ; look->originalArray = a ; look->a = convert (a) ; look->minX = 0 ; /* included */ look->maxX = max ; /* excluded as usual in Arrays */ plotDisplay() ; return; } /* histoImport */ /******************************************************************/ static void logyTransform (void) { double x, log10 ; int k ; Array a ; LOOKGET("logTransform") ; a = look->a ; if (!a || arrayMax(a) < 10) return ; log10 = log((double)10.0) ; for (k = 0 ; k < arrayMax(a) ; k++ ) { x = arr (a, k, float) ; if (x < 1.0/1000) x = 1.0/1000 ; array (a, k, float) = log(x)/log10 ; } plotDisplay () ; } /*************************************************************************/ static void logxTransform (void) { float *fp ; double x ; int i, k, max ; Array a, b ; LOOKGET("logTransform") ; a = look->a ; if (!a || arrayMax(a) < 10) return ; if (!a || arrayMax(a) < 10) return ; max = arrayMax (a) ; b = arrayCreate (max, float) ; array (b, max - 1 , float) = 0 ; /* make room */ fp = arrp (b, 0, float) ; for (k = 100 ; k < arrayMax(a) ; k++ ) { x = k/100.0 ; i = 5000 * log10 (x) ; array (b, i, float) = arr (a, k, float) ; } arrayDestroy (look->a) ; look->a = b ; plotDisplay () ; } /*************************************************************************/ static void plotCorrel (void) { double x = 0 ; float *fp = 0, *fip, *fjp, fmax=0, fmin = 0 ; int i,j, t,max, *ip ; Array a, b ; LOOKGET("plotCorrel") ; a = look->a ; if (!a || arrayMax(a) < 10) return ; max = arrayMax (a) ; b = arrayCreate (max, float) ; array (b, max - 1 , float) = 0 ; /* make room */ fp = arrp (b, 0, float) ; fmax = 0 ; for (t = 0 ; t < max/2 ; t++) { x = 0 ; for (i = 0, j = t, fip = arrp (a, i, float), fjp = arrp (a, j, float); i < max ; i++, j++, fip++, fjp++) { if (j == max) fjp = arrp (a, 0, float) ; /* circularize to ensure normalisation */ x += (*fip) * (*fjp) ; } *fp++ = x ; if (!t) fmin = fmax = x ; if (x > fmax) fmax = x ; if (x < fmin) fmin = x ; } for (t = max/2; t < max ; t++) *fp++ = x ; for (t = 0, fp = arrp (b, 0, float); t < max ; fp++, ip++, t++) *fp *= 100.0/fmax ; arrayDestroy (look->a) ; look->a = b ; plotDisplay () ; } /*************************************************************************/ static void steppingBoxEntry (char *cp) { int s, step, level, i, j, maxa, maxb ; int *fa = 0 ; float *fb = 0, x = 0 ; Array a, b ; LOOKGET("steppingBoxEntry") ; a = look->originalArray ; if (!a || arrayMax(a) < 10) return ; level = freesettext (cp, "") ; freecard(level) ; s = -1 ; freeint (&s) ; freeclose (level) ; maxa = arrayMax (a) ; step = s/look->startStep ; s = step * look->startStep ; if ( step < 1 || step > maxa /2) { step = 1 ; s = look->startStep ; } look->plus1 = FALSE ; maxb = maxa/step ; if (maxa%step) { maxb++ ; look->plus1 = TRUE ; } b = arrayCreate (maxb, float) ; array (b, maxb - 1 , float) = 0 ; fb = arrp (b, 0, float) ; for (i=0 ; i < maxb ; i++) { x = 0 ; for (j = 0, fa = arrp (a, step*i + j, int) ; j < step && j + step*i < maxa; j ++, fa++) x += *fa ; *fb++ = x ; } arrayDestroy (look->a) ; look->a = b ; look->step = s ; look->scale = 1./(float)look->step ; look->isStepping = TRUE ; if(!(look->isSmoothing)) smoothingBoxEntry(look->sBuffer) ; look->isSmoothing = FALSE ; } /*************************************************************************/ static void smoothingBoxEntry (char *cp) { float *fp, *fjp, *ip ; int i, j, k , k1, k2, s, t, level, di, ifac ; Array a, b ; LOOKGET("smoothingBoxEntry") ; look->isSmoothing = TRUE ; if (!(look->isStepping)) steppingBoxEntry (look->stepBuffer) ; look->isStepping = FALSE ; a = look->a ; level = freesettext (cp, "") ; freecard(level) ; s = -1 ; freeint (&s) ; freeclose (level) ; s = s/2 + 1 ; if (s < 1) { plotDisplay() ; return ; } t = s * s ; /* sum of the triangle */ if (!a || arrayMax(a) < 2*s + 3) return ; if (!arrayMax (a)) return ; i = arrayMax (a) ; look->a = b = arrayCreate (i, float) ; array (b, i - 1 , float) = 0 ; /* make room */ for (k = - s + 1 ; k < s ; k++) { ip = arrp(a, k > 0 ? k : 0 , float) ; fp = arrp(b, k < 0 ? -k : 0 , float) ; k1 = k >= 0 ? k : - k ; i = arrayMax (a) - k1 ; k2 = s - k1 ; while (i--) *fp++ += k2 * (*ip++) ; } i = s -1 ; j = arrayMax(a) - s + 1 ; fjp = arrp(b, j, float) ; di = 2 ; ifac = 1 ; fp = arrp(b, i-1, float) ; while (i--){ *fp-- *= t/(float)(t-ifac) ; *fjp++ *= t/(float)(t-ifac) ; ifac += di ; di++ ; } i = arrayMax (b) ; fp = arrp(b, 0 , float) - 1 ; while (fp++, i--) *fp /= t ; if (s > 1) look->s = (s -1) *2 ; else look->s = 1 ; zoneBoxEntry(look->zoneBuffer) ; } /*************************************************************************/ static void zoneBoxEntry (char *cp) { int i, j, level, oldMin, oldMax, oldXmin, oldXmax ; int minX2, maxX2, k ; LOOKGET("zoneBoxEntry") ; look->reticule = FALSE ; oldMin = look->minX ; oldMax = look->maxX ; oldXmin = look->xMin ; oldXmax = look->xMax ; level = freesettext (cp, "") ; freecard(level) ; if (!freeint (&i) || !freeint (&j)) goto abort ; if (i> j) goto abort ; i *= look->xDiv ; j *= look->xDiv ; look->minX = (int)(look->scale * (i - look->shift)) ; look->maxX = (int)(look->scale * (j - look->shift)) ; if (look->minX >= look->maxX) goto abort ; if (look->minX < 0) look->minX = 0 ; if (look->maxX > arrayMax (look->a)) look->maxX = arrayMax (look->a) ; k = 0 ; minX2 = utArrondi(look->shift + look->minX/look->scale) ; while ((i != minX2) && (k < 50)) { if (i > minX2) (look->minX)++ ; else (look->minX)-- ; k++ ; minX2 = utArrondi(look->shift + look->minX/look->scale) ; } if (look->minX < 0) { look->minX = 0 ; look->xMin = utArrondi(look->shift) ; } else look->xMin = i ; k = 0 ; maxX2 = utArrondi(look->shift + look->maxX/look->scale) ; while ((j != maxX2 - 1) && k < 50){ if (j > maxX2 - 1) (look->maxX)++ ; else (look->maxX)-- ; k++ ; maxX2 = utArrondi(look->shift + look->maxX/look->scale) ; } if (look->maxX > arrayMax (look->a)) { look->maxX = arrayMax (look->a) ; look->xMax = utArrondi(look->xEnd) ; } else look->xMax = j ; if (look->minX >= look->maxX) goto abort ; if (look->xMin < look->shift) look->xMin = utArrondi(look->shift) ; if (look->xMax > look->xEnd) look->xMax = utArrondi(look->xEnd) ; if (look->xMax < look->xMin) look->xMax = look->xMin ; if ((look->plus1) && (look->maxX < arrayMax(look->a))) (look->maxX)++ ; plotDisplay () ; return ; abort: look->minX = oldMin ; look->maxX = oldMax ; look->xMin = oldXmin ; look->xMax = oldXmax ; plotDisplay () ; return ; } /*************************************************************************/ static void wholeButton (void) { LOOKGET("wholeButton") ; /* mhmp 10.03.99 */ look->minX = 0 ; look->xMin = utArrondi(look->shift) ; look->maxX = arrayMax (look->a) ; look->xMax = utArrondi(look->xEnd) ; look->reticule = FALSE ; plotDisplay () ; } /*************************************************************************/ static Graph plotDisplay(void) { char *cp ; register int i, j ; float x2=0, firstX=0, firstY=0 ; /* mhmp 05.03.99 */ int minX2, maxX2, i1, xDiv, i3, ddx, fac=1, isFac ; int zoneMin, zoneMax, oldi, facY ; float Xmag2=1 ; int dx, dy, nx, ny, maxX, minX, xofmax ; float minY=0 , maxY=0, tot = 0, fmax = 0 ; Array a ; float h, x0, lastX0=0, y0, Xmag, Ymag, *yp ; int bottomMargin ; LOOKGET("plotDisplay") ; graphClear() ; a = look->a ; maxX = look->maxX ; xofmax = minX = look->minX ; minY = maxY = arr(a, minX,float) ; for (i = minX, yp = arrp(a,i,float) ; i < maxX ; i++, yp++) { if (*yp > maxY) { maxY = *yp ; xofmax = i ;} if (*yp < minY) minY = *yp ; tot += *yp ; } look->maxY = maxY ; look->minY = minY; facY = 1; /* mhmp 19.04.99 maxY > 0 26.04 maxY < 2 /1 + maxY - minY*/ if ((maxY - minY> 0) && (maxY < 2)) { while ((maxY - minY)*facY < 1) facY *= 10 ; } /* mhmp 19.04.99 sorti du while */ look->facY = facY ; minY *= facY ; maxY *= facY ; look->minY *= facY ; look->maxY *= facY ; h = maxY - minY ; if (!h) h = 1; look->topMargin = 9 ; look->leftMargin = 7 ; bottomMargin = 5 ; graphFitBounds (&nx, &ny) ; if (ny < look->topMargin + bottomMargin + 6 || nx < look->leftMargin + 8) { graphText ("This graph is too small", 2, 2) ; graphRedraw () ; return graphActive () ; } if (maxX < minX) maxX = minX ; look->Xmag = Xmag = (nx - look->leftMargin - 3) / ((float)(maxX - minX + 1)) ; look->Ymag = Ymag = (ny - look->topMargin - bottomMargin) / ((float)(h)) ; minX2 = utArrondi(look->shift + minX/look->scale) ; maxX2 = utArrondi(look->shift + maxX/look->scale) ; if (maxX2 < minX2) maxX2 = minX2 ; fmax = look->shift + xofmax/look->scale ; Xmag2 = (nx - look->leftMargin - 3) / ((float)(maxX2 - minX2 + 1)) ; i = abs(maxX2) ; if (abs(minX2) > i) i = abs(minX2) ; oldi = i ; j = 1 ; while (i /= 10) j++ ; /* count chars */ dx = 5 * j / Xmag2 ; dx = utMainRoundPart(dx) ; if(dx <= 0) dx = 1; xDiv = 1 ; ddx = dx ; while (ddx && !(ddx % 10)) { xDiv *= 10 ; ddx /= 10 ; } if (xDiv > 1) xDiv /= 10 ; look->xDiv = xDiv ; if (xDiv > 1 ) { i = oldi/ xDiv ; j = 1 ; while (i /= 10) j++ ; dx = 5 * j / Xmag2 ; dx = utMainRoundPart(dx) ; if(dx <= 0) dx = 1; } for(i = i1 = utMainPart(minX2); i <= maxX2; i += dx) { i3 = utArrondi(i / (float)xDiv) ; x2 = (look->scale * ( i3 * xDiv - look->shift)) ; if (x2 >= minX) { i1 = i - dx ; break ; } } dy = utMainRoundPart((int)(5. / Ymag)) ; if(dy <= 0) dy = 1; for(i = utMainPart(minY) ; i <= maxY ; i += dy) if (i > minY) { firstY = i - dy ; look->firstY = firstY ; /* mhmp verifier le + 1 26.04.99*/ look->Ymag = Ymag = (ny - look->topMargin - bottomMargin) / ((float)(maxY- firstY)) ; break ; } firstX = -1000000 ; for(i = i1; i <= maxX2; i += dx) { /* 26.04.99 mhmp pb de -0.5 1.5 ---> -1 et 2*/ i3 = utArrondi(i / (float)xDiv + 0.0001) ; x2 = (look->scale * ( i3*xDiv - look->shift)) ; if (firstX < -100000){ firstX = x2 ; look->firstX = firstX ; look->Xmag = Xmag = (nx - look->leftMargin - 3) / ((float)(maxX - firstX + 1)) ; } graphText(messprintf("%d",i3), XX(x2) - .5, YY (firstY) + 1.1); /* mhmp 22.03.99 les tirets */ graphLine(XX(x2), YY (firstY)+ look->axisShift,XX(x2), YY (firstY)+look->axisShift + 0.5) ; } i3 = utArrondi(i / (float)xDiv) ; x2 = (look->scale * ( i3*xDiv - look->shift)) ; if (XX(x2) < XX(maxX) + 3) { graphText(messprintf("%d",i3), XX(x2) - .5, YY (firstY) + 1.1); graphLine(XX(x2), YY (firstY)+ look->axisShift, XX(x2), YY (firstY)+ look->axisShift + 0.5) ; } /* mhmp 19.04.99 -1 +1*/ /* totMin = utArrondi(look->shift/xDiv) ; if (totMin > look->shift/xDiv) totMin-- ; totMax = utArrondi(look->xEnd/xDiv) ; if (totMax < look->xEnd/xDiv) totMax++ ; graphText(messprintf("Total interval Min: %d Max: %d", totMin, totMax), 2, 4.7 ) ;*/ if (facY > 1) graphText (messprintf("scale y 1*%d", facY), 2, YY (firstY) + 2.2) ; for(i = firstY ; i <= maxY ; i += dy) { cp = messprintf("%d",i) ; /* mhmp 22.03.99 les tirets */ graphText(cp, look->leftMargin -1 - look->axisShift - strlen(cp) , YY(i) - .5) ; graphLine(XX(firstX)-look->axisShift, YY(i), XX(firstX)- look->axisShift - 0.8, YY(i)); } if (YY(i) > YY (maxY) - 3) { cp = messprintf("%d",i) ; graphText(cp, look->leftMargin - 1 - look->axisShift - strlen(cp) , YY(i) - .5) ; graphLine(XX(firstX)-look->axisShift, YY(i), XX(firstX)- look->axisShift - 0.8, YY(i)); } look->retBox = graphBoxStart () ; /*23.04.99 minX -> firstX */ graphLine(XX(firstX), YY(firstY)+look->axisShift, XX(maxX) + 3 , YY (firstY)+look->axisShift) ; /* x axis */ graphLine(XX(firstX)-look->axisShift, YY(firstY), XX(firstX)-look->axisShift , YY (maxY) - 3) ; /* y axis, the 3 is used in moveReticule() */ graphColor(BLUE) ; for(i = minX, x0 = XX(i), y0 = YY(0), yp = arrp (look->a, i, float) ; i < maxX - 1 ; x0 += Xmag, i++, yp++){ if (i == minX) graphLine(x0,YY(look->firstY)+ look->axisShift, x0, y0 - (*yp) * Ymag*facY) ; graphLine(x0, y0 - (*yp) * Ymag*facY, x0 + Xmag, y0 - (*yp) * Ymag*facY) ; graphLine(x0 + Xmag, y0 - (*yp) * Ymag*facY, x0 + Xmag, y0 - (*(yp + 1) * Ymag*facY)) ; lastX0 = x0 + Xmag ; } graphLine(lastX0, y0 - (*yp) * Ymag*facY, lastX0 + Xmag, y0 - (*yp) * Ymag*facY) ; graphLine(x0 + Xmag, y0 - (*yp) * Ymag*facY, x0 + Xmag, YY(look->firstY)+ look->axisShift) ; graphBoxEnd () ; graphBoxMenu (look->retBox, histoMenu); look->xyBox = graphBoxStart() ; if (look->reticule) { graphTextPtr (look->xBuffer, 6, 2.5 , 8) ; graphTextPtr (look->yBuffer, 6, 3.7 , 8) ; } graphBoxEnd () ; graphBoxMenu(look->xyBox, histoMenu); isFac = 0 ; if (look->xDiv > 1 || look->xMul > 1) { if (look->xDiv > look->xMul) { fac = look->xDiv / look->xMul ; isFac = 1 ; } else { fac = look->xMul / look->xDiv ; isFac = -1 ; } } /*mhmp 19.04.99 -1/+1*/ zoneMin = utArrondi(look->xMin/xDiv) ; if (zoneMin > look->xMin/xDiv) zoneMin-- ; zoneMax = utArrondi(look->xMax/xDiv) ; if (zoneMax < look->xMax/xDiv) zoneMax++ ; xofmax = fmax ; if (xofmax < zoneMin*xDiv) xofmax = zoneMin*xDiv ; if (xofmax > zoneMax*xDiv) xofmax = zoneMax*xDiv ; if (isFac < 0) graphText (messprintf ("scale x 1*%d", fac), XX(maxX) - 20, YY (firstY) + 2.2 ) ; else if (isFac > 0) graphText (messprintf ("scale x 1/%d", fac), XX(maxX) - 20, YY (firstY) + 2.2 ) ; i = graphBoxStart () ; graphText (messprintf ("In zone: total %g max y(%d) = %g", tot, xofmax, maxY/facY), 2, 1.3) ; graphBoxEnd () ; graphBoxDraw(i,RED,TRANSPARENT) ; graphBoxMenu (i, histoMenu); look->subtitleBox =graphTextEntry(look->subtitle, 23, XX(maxX) -20, YY(firstY) + 3.3, 0) ; if (look->reticule) { graphText("x = ", 2, 2.5) ; graphText("y = ", 2, 3.7) ; graphLine (XX(look->firstX)-look->axisShift,YY(look->y), XX(look->maxX), YY(look->y)) ; graphLine (XX(look->x), YY(look->firstY)+look->axisShift, XX(look->x), YY(look->maxY)) ; } minY /= facY ; maxY /= facY ; look->minY /= facY ; look->maxY /= facY ; sprintf(look->sBuffer, "%d", look->s) ; graphText ("Smoothing:", 21, 3.7) ; sprintf(look->stepBuffer, "%d", look->step) ; graphText ("Step:", 40, 3.7) ; look->sBox = graphTextEntry(look->sBuffer, 7, 32, 3.7, smoothingBoxEntry) ; look->stepBox = graphTextEntry(look->stepBuffer, 9, 46, 3.7, steppingBoxEntry) ; sprintf(look->zoneBuffer, "%d %d", zoneMin, zoneMax) ; graphText ("Active Zone:", 19, 2.5) ; look->zoneBox= graphTextEntry(look->zoneBuffer, 23, 32, 2.5, zoneBoxEntry) ; look->titleBox = graphTextEntry(look->title, 47, 2, 0.1, 0) ; if (!look->isPrinting) graphButton ("Whole", wholeButton, 12., 2.5) ; graphRedraw () ; return graphActive () ; } /******************************************************************/ static void plotRefresh (void) { LOOKGET ("plotRefresh") ; look->reticule = FALSE; plotDisplay() ; } /******************************************************************/ static Array convert (Array a) { int max = arrayMax (a) ; int *ip = max ? arrp (a, 0, int) : 0 ; Array b = arrayCreate(max, float) ; float *fp ; array (b, max - 1, float) = 0 ; fp = arrp (b, 0, float) ; while (max--) *fp++ = *ip++ ; return b ; } /******************************************************************/ /****************** public routine ********************************/ void plotHisto(char *title, Array histArray) { float max = (float)(arrayMax(histArray)-1) ; char *subtitle ; subtitle = "" ; plotShiftedHisto (title,subtitle,histArray, 0, max, (float) 1.0, 1) ; } /* mhmp 10.03.99 float shift */ void plotShiftedHisto(char *title, char *subtitle, Array histArray, float shift, float xMax, float scale, int xMul) { int i, max ; LOOK look ; if (!histArray) messcrash ("plotHisto(%s, array) received NULL array", title); if(histArray->size != sizeof(int)) messcrash("plotHisto received a wrong type of Array, should be int"); if(arrayMax(histArray) == 0) { arrayDestroy (histArray) ; messerror("plotHisto(%s,array) received a empty array", title); return ; } max = arrayMax(histArray); i = max - 1; while( !arr(histArray,i,int) && i-- ); max = i + 1 ; if(!max) { arrayDestroy (histArray) ; messerror("plotHisto(%s) received a null histogram", title); return ; } if(!displayCreate("DtHistogram")) { arrayDestroy (histArray) ; return ; } if (!plotCurrHis) { plotCurrHis = arrayCreate(32, Graph) ; plotCurrNb = 0 ; } array(plotCurrHis, arrayMax(plotCurrHis), Graph) = graphActive() ; plotCurrNb++ ; look = (LOOK)messalloc(sizeof(struct LOOKstruct)) ; graphAssociate (&PLOT_MAGIC, look) ; graphRegister (DESTROY, plotDestroy) ; /* mhmp 20.04.99 plotDisplay -> plotRefresh */ graphRegister (RESIZE, plotRefresh) ; graphRegister (PICK, moveReticule) ; if (title && *title) graphRetitle (title) ; graphMenu(histoMenu); look->magic = PLOT_MAGIC ; look->originalArray = histArray ; look->a = convert (histArray) ; if (title && *title) sprintf(look->title, "%s", title) ; else sprintf (look->title , "%s", "Histogram"); sprintf(look->subtitle, "%s", subtitle) ; look->reticule = FALSE ; look->isStepping = FALSE ; look->isSmoothing = FALSE ; look->isPrinting = FALSE ; look->plus1 = FALSE ; look->s = 1 ; look->scale = scale ; if (scale < 1) look->startStep = utArrondi(1./scale) ; else look->startStep = 1 ; look->step = look->startStep ; look->shift = shift ; look->xMin = utArrondi(shift) ; look->xEnd = xMax ; look->xMax = utArrondi(xMax) ; look->startScale = scale ; look->axisShift = 0.5 ; look->xMul = xMul ; look->minX = 0 ; /* included */ look->maxX = max ; /* excluded as usual in Arrays */ plotDisplay() ; return ; } /*************************************************************************/ void plotHistoRemove(void) { Graph *gp ; int i ; if (!plotCurrHis) return ; i = arrayMax(plotCurrHis) ; gp = arrp(plotCurrHis, 0, Graph) - 1 ; while(gp++, i--) if (graphActivate(*gp)) graphDestroy() ; arrayDestroy(plotCurrHis) ; plotCurrNb = 0 ; } /*************************************************************************/ /*************************************************************************/ static void plotCopy (void) { LOOKGET("plotCopy") ; /* we have to pass a copy of the original array, because it get's destroyed in plotDestroy, and if two graphs use the same array it'd get dest. twice */ /* mhmp 05.03.99*/ plotShiftedHisto (look->title, look->subtitle, arrayCopy(look->originalArray), look->shift, look->xEnd, look->startScale, look->xMul) ; } /*****************/ static float cleanScale(float scale) { int inter; inter = 1 ; if (scale < 1) { inter = 1./scale ; inter = utMainRoundPart (inter) ; return 1./inter ; } else scale = 1; return scale ; } /*****************/ static void plotDoLoad (BOOL isAscii) { void *vp ; int max=0, i ; unsigned int nb = 2000, nr, size = sizeof (int) , size2 = sizeof (float) ; Array a0, a ; int n, n1 ; float x = 0, scale = 0, xmin = 0, xmax = 0 ; ACEIN histo_in; LOOKGET("plotDoLoad") ; look->title[0] = '\0' ; look->subtitle[0] = '\0' ; histo_in = aceInCreateFromChooser (messprintf ("%s File of Integers", isAscii ? "Text" : "Binary"), look->dirName,look->fileName, "histo", "r", 0); if (!histo_in) return; a0 = arrayCreate (1000, int) ; a = arrayCreate (1000, int) ; if (isAscii) { int nn; i = 0 ; while (aceInCard(histo_in)) { if (aceInInt(histo_in, &nn)) array (a0, i++, int) = nn ; } aceInDestroy (histo_in); n = arrayMax(a0) ; scale = 0 ; xmin = 1; xmax = 0 ; while (n--) { x = array(a0, n, int) ; if (xmin > xmax) xmin = xmax = x ; else { if (xmin > x) xmin = x ; if(xmax < x) xmax = x ; } } if (xmax - xmin < 10000) scale = 1.0 ; else scale = 10000.0 / (utArrondi(xmax) - utArrondi(xmin)) ; scale = cleanScale (scale) ;/* mhmp 01.04.99 pour smooth */ n = arrayMax(a0) ; while (n--) { x = array(a0, n, int) ; n1 = (x - xmin ) * scale ; array(a, n1, int)++ ; } look->shift = xmin ; look->xEnd = xmax ; look->startScale = scale ; look->xMul = 1 ; max = arrayMax(a) ; arrayDestroy (a0) ; plotInit() ; } else /* Binary */ { FILE *fil = NULL; char *filename; filename = strnew (aceInGetURL(histo_in), 0); aceInDestroy (histo_in); if (filename) fil = filopen (filename, "", "r"); if (fil) { fread (look->title, sizeof (char), 47, fil) ; fread (look->subtitle, sizeof (char), 23, fil) ; fread (&look->shift, size2, 1, fil) ; fread (&look->xEnd, size2, 1, fil) ; fread (&look->startScale, size2, 1, fil) ; fread (&look->xMul, size, 1, fil) ; i = 0 ; do { array(a,(++i)*nb,int) = 0; /* to create space */ vp = arrp(a,nb*(i-1),int); /* possible relocation */ } while ((nr=fread(vp,size,nb,fil))==nb); arrayMax(a) -= nb - nr; /* artificial space removed */ i = arrayMax (a) - 1; if (i>=0) while( !arr(a,i,int) && i-- ); max = i + 1 ; arrayMax (a) = max ; filclose(fil) ; plotInit() ; } messfree (filename); } if(!max) { messout("I read an empty file") ; arrayDestroy(a) ; return; } if (!look->title || !*look->title) sprintf(look->title, "%s", look->fileName) ; graphRetitle (look->title) ; arrayDestroy (look->originalArray) ; arrayDestroy (look->a) ; look->originalArray = a ; look->a = convert (a) ; look->minX = 0 ; /* included */ look->maxX = max ; /* excluded as usual in Arrays */ plotDisplay() ; return; } /* plotDoLoad */ static void plotLoad (void) { plotDoLoad(FALSE) ; } static void plotLoadAscii (void) { plotDoLoad(TRUE) ; } static void plotSave (void) { FILE *fil; unsigned int size = sizeof (int) ; /* mhmp 18.05.99 */ unsigned int size2 = sizeof (float) ; LOOKGET("plotSave") ; if (!look->originalArray || ! arrayMax(look->originalArray)) return ; if (look->title != look->fileName) strcpy(look->fileName, look->title) ; fil = filqueryopen (look->dirName,look->fileName,"histo","wb", "Histogram Output File") ; if (!fil) return ; fwrite (look->title, sizeof (char), 47, fil) ; fwrite (look->subtitle, sizeof (char), 23, fil) ; fwrite (&look->shift, size2, 1, fil) ; fwrite (&look->xEnd, size2, 1, fil) ; fwrite (&look->startScale, size2, 1, fil) ; fwrite (&look->xMul, size, 1, fil) ; fwrite(arrp(look->originalArray,0,int),size, arrayMax(look->originalArray),fil); filclose(fil) ; return; } /* plotSave */ static void plotInit (void) { float scale = 1, shift = 0, xMax = 0 ; LOOKGET("plotInit") ; look->reticule = FALSE ; look->isStepping = FALSE ; look->isSmoothing = FALSE ; look->plus1 = FALSE ; look->s = 1 ; scale = look->startScale ; look->scale = scale ; if (scale < 1) look->startStep = utArrondi(1./scale) ; else look->startStep = 1 ; look->step = look->startStep ; shift = look->shift ; look->xMin = utArrondi(shift) ; xMax = look->xEnd ; look->xMax = utArrondi(xMax) ; look->startScale = scale ; look->axisShift = 0.5 ; } /*************************************************************************/ /*************************************************************************/