/* File: plot2d.c * Author: Danielle et Jean Thierry-Mieg (mieg@mrc-lmb.cam.ac.uk) * Copyright (C) J Thierry-Mieg and R Durbin, 1993 * ------------------------------------------------------------------- * 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: * Exported functions: * plot2d(char *title, Array a) * where a is an Array of pairs of float. * HISTORY: * Last edited: May 6 10:23 2003 (edgrif) * Created: Mon Apr 5 16:00:10 1993 (mieg) * CVS info: $Id: plot2d.c,v 1.7 2003/05/06 13:13:14 edgrif Exp $ *------------------------------------------------------------------- */ #include #include #include static magic_t Plot2d_MAGIC = "Plot2d"; /*************************************************************************/ typedef struct p2dstuff { magic_t *magic ; STORE_HANDLE handle ; char title[48], subtitleX[24], subtitleY[24] ; int titleBox, subtitleXbox, subtitleYbox ; Graph graph ; Array xy ; float xMin, xMax, yMin, yMax ; float x, y ; float xCentre, yCentre, xMag, yMag, oldXmag, oldYmag, startXmag ; int nx, ny ; int leftMargin, topMargin, bottomMargin, rightMargin ; int retBox, xyBox ; float xStart, yStart ; BOOL reticule, regress, isPrinting ; char xBuffer [16], yBuffer [16] ; double a, b, r, w ; float axisShift ; } *P2D ; static void plot2dZoomIn (void) ; static void plot2dZoomOut (void) ; static void plot2dWhole (void) ; static void plot2dDraw (P2D p2d) ; static void plot2dInit (P2D p2d) ; static void plot2dReticule (int box, double x, double y, int modifier_unused) ; static void plot2dCentre (double x, double y) ; static void linearRegression(Array xy, double *ap, double *bp, double *rp, double *wp); static void plot2dRegression (void) ; static void plot2dPrint (void) ; /*************************************************************************/ #define XGRAPH2MAP(x) (p2d->xCentre + p2d->xMag * ((float)(x) - p2d->leftMargin - p2d->nx/2.)) #define XMAP2GRAPH(x) (((x) - p2d->xCentre) / p2d->xMag + p2d->leftMargin + p2d->nx/2.) #define YGRAPH2MAP(y) (p2d->yCentre - p2d->yMag * ((float)(y) - p2d->topMargin - p2d->ny/2.)) #define YMAP2GRAPH(y) ((-(y) + p2d->yCentre) / p2d->yMag + p2d->topMargin + p2d->ny/2.) /*************************************************************************/ /*************************************************************************/ static MENUOPT plot2dMenu[] = { {graphDestroy, "Quit"}, {help,"Help"}, {plot2dPrint,"Print"}, {plot2dZoomIn, "ZoomIn"}, {plot2dZoomOut, "ZoomOut"}, {plot2dWhole, "Whole"}, {plot2dRegression, "Lin.Reg."}, {0, 0} } ; /*************************************************************************/ static P2D currentP2d (char *caller) { P2D p2d = 0 ; if (!graphAssFind (&Plot2d_MAGIC,&p2d)) messcrash("%s() could not find Plot2d on graph", caller); if (!p2d) messcrash("%s() received NULL Plot2d pointer", caller); if (p2d->magic != &Plot2d_MAGIC) messcrash("%s() received non-magic pointer", caller); return p2d ; } /* currentVerticalMap */ /*************************************************************************/ /*********** action routines *************/ /*************************************************************************/ static void plot2dResize (void) { P2D p2d = currentP2d ("plot2dResize") ; plot2dDraw (p2d) ; } /***************************************/ static void plot2dDestroy(void) { P2D p2d = currentP2d ("plot2dDestroy") ; if (p2d) { p2d->magic = 0 ; arrayDestroy (p2d->xy) ; messfree (p2d->handle) ; } } /********* start off with some utility routines ********/ static BOOL getNxNy(P2D p2d) { int nx, ny ; graphFitBounds (&nx, &ny) ; nx = nx - p2d->leftMargin - p2d->rightMargin ; ny = ny - p2d->topMargin - p2d->bottomMargin ; if (nx > 0 && ny > 0) { p2d->nx = nx ; p2d->ny = ny ; return TRUE ; } p2d->nx = p2d->ny = 3 ; /* arbitrary non stupid values */ return FALSE ; } /***************************************/ static void plot2dWhole (void) { BOOL regress ; P2D p2d = currentP2d ("plot2dWhole") ; regress = p2d->regress ; plot2dInit (p2d) ; p2d->regress = regress ; plot2dDraw (p2d) ; } /***************************************/ static void plot2dZoomOut (void) { P2D p2d = currentP2d ("plot2dZoomIn") ; p2d->xMag = p2d->oldXmag ; p2d->yMag = p2d->oldYmag ; if (p2d->xMag < 4.* p2d->startXmag) { p2d->xMag *= 2 ; p2d->yMag *= 2 ; } plot2dDraw (p2d) ; } /***************************************/ static void plot2dZoomIn (void) { P2D p2d = currentP2d ("plot2dZoomIn") ; p2d->xMag = p2d->oldXmag ; p2d->yMag = p2d->oldYmag ; if (p2d->xMag > 1.E-5) { p2d->xMag /= 2 ; p2d->yMag /= 2 ; } plot2dDraw (p2d) ; } /***************************************/ static void plot2dPrint (void) { P2D p2d = currentP2d ("plot2dPrint") ; Graph old = graphActive(); p2d->isPrinting = TRUE ; plot2dDraw (p2d) ; graphPrint () ; graphActivate (old); p2d->isPrinting = FALSE ; plot2dDraw (p2d) ; } /***************************************/ static void plot2dReticule (int box, double x, double y, int modifier_unused) { float x1, y1, x2, y2 ; P2D p2d = currentP2d ("plot2dReticule") ; if (box == p2d->titleBox) { graphTextEntry (p2d->title, 0, 0, 0, 0) ; return ; } if (box == p2d->subtitleXbox) { graphTextEntry (p2d->subtitleX, 0, 0, 0, 0) ; return ; } if (box == p2d->subtitleYbox) { graphTextEntry (p2d->subtitleY, 0, 0, 0, 0) ; return ; } if (box != p2d->retBox){ if (p2d->reticule) { p2d->xMag = p2d->oldXmag ; p2d->yMag = p2d->oldYmag ; p2d->reticule = FALSE ; plot2dDraw (p2d) ; } return ; } graphBoxDim (p2d->retBox, &x1, &y1, &x2, &y2) ; p2d->x = XGRAPH2MAP(x + x1) ; p2d->y = YGRAPH2MAP(y + y1) ; sprintf (p2d->xBuffer, "%g", p2d->x) ; sprintf (p2d->yBuffer, "%g", p2d->y) ; p2d->reticule = TRUE ; p2d->xMag = p2d->oldXmag ; p2d->yMag = p2d->oldYmag ; plot2dDraw (p2d) ; } /***************************************/ static void plot2dCentre (double x, double y) { float x1, y1, x2, y2 ; P2D p2d = currentP2d ("plot2dCentre") ; graphBoxDim (p2d->retBox, &x1, &y1, &x2, &y2) ; if ( x >= x1 && x <= x2 && y >= y1 && y <= y2) { p2d->xCentre = XGRAPH2MAP(x) ; p2d->yCentre = YGRAPH2MAP(y) ; p2d->xMag = p2d->oldXmag ; p2d->yMag = p2d->oldYmag ; plot2dDraw (p2d) ; } else return ; } /**************************************************/ /**************************************************/ static void plot2dXscale (P2D p2d) { float x, xp1, start, end, xMag, sdx ; float xPos, yPos, fin ; double xx, iDeb, iFin, xxp1 ; int xDiv, dx, ddx, i, j, oldi, nx, ny ; int xxx ; int xMul, isScale, scale= 1 ; yPos = p2d->topMargin + p2d->ny ; xPos = (p2d->leftMargin + p2d->nx) * 0.75 ; start = XGRAPH2MAP(p2d->leftMargin) ; end = XGRAPH2MAP(p2d->leftMargin + p2d->nx) ; p2d->xStart = start ; graphFitBounds (&nx, &ny) ; xMul = 1. ; if (start == end) end = start + 1 ; while ((end - start) * xMul < 1.) xMul *= 10 ; start *= xMul ; end *= xMul ; if (abs(end) > abs(start)) i = abs(end) ; else i = abs(start) ; oldi = i ; j = 1 ; while (i /= 10) j++ ; /* count chars */ xMag = (nx - p2d->leftMargin) / (end - start); dx = 5 * j / xMag ; dx = freeMainRoundPart(dx) ; if(dx <= 0) dx = 1; xDiv = 1 ; ddx = dx ; while (ddx && !(ddx % 10)) { xDiv *= 10 ; ddx /= 10 ; } if (xDiv > 1) xDiv /= 10 ; if (xDiv > 1 ) { i = oldi/ xDiv ; j = 1 ; while (i /= 10) j++ ; dx = 5 * j / xMag ; dx = freeMainRoundPart(dx) ; if(dx <= 0) dx = 1; } /* mhmp 04.05.98 */ if (dx * xMag < 2.5) dx *= 2 ; isScale = 0 ; if (xDiv > 1 || xMul > 1) { if (xDiv > xMul) { scale = xDiv / xMul ; isScale = 1 ; } else { scale = xMul / xDiv ; isScale = -1 ; } } if (isScale >= 0) /* mhmp 06.07.99 > ---> >= */ graphText (messprintf ("scale x: 1/%d", scale), xPos, yPos + 3.0) ; else graphText (messprintf ("scale x: 1*%d", scale), xPos, yPos + 3.0) ; iDeb = utMainPart(utArrondi(start)) ; iFin = end ; /*recalage a gauche */ if (end - iDeb > dx * 100000) iDeb = start ; else for (xx = iDeb ; xx < end ; xx += dx) if (xx > start) { iDeb = xx - dx ; iFin = 2*p2d->xCentre * xMul - iDeb ; break ; } fin = XMAP2GRAPH((float)iFin/xMul) ; p2d->oldXmag = p2d->xMag ; p2d->xMag = (p2d->xCentre - (float)iDeb/xMul) / (p2d->nx/2.) ; if (p2d->xMag < 1.E-5) return ; for (xx = iDeb ; xx <= iFin ; xx += dx) { x = XMAP2GRAPH((float)xx /xMul) ; if (x >= p2d->leftMargin - 0.0001) { xxx = utArrondi((float)xx / xDiv + 0.0001); graphLine (x, yPos + 1.5, x, yPos + 0.5) ; graphText (messprintf ("%d",xxx), x, yPos + 2.0) ; /*tirets*/ xxp1 = xx + dx ; xp1 = XMAP2GRAPH((float)xxp1 /xMul ) ; sdx = (xp1 - x) / 5. ; for (i = 0 ; i < 4 ; i++) { x += sdx ; if (x <= fin + 0.0001) graphLine (x, yPos + 1., x, yPos + 0.5) ; } } } graphLine (XMAP2GRAPH((float)iDeb/xMul), yPos + p2d->axisShift, fin, yPos + p2d->axisShift) ; } /**************************************************/ static void plot2dYscale (P2D p2d) { float y, yp1, start, end, yMag, sdy ; float xPos, yPos, fin ; double yy, iDeb, iFin, yyp1 ; int yDiv, dy, ddy, nx, ny, i ; int yyy ; int yMul, isScale, scale = 1 ; char *cp ; xPos = p2d->leftMargin ; yPos = p2d->topMargin + p2d->ny ; start = YGRAPH2MAP(p2d->topMargin + p2d->ny) ; p2d->yStart = start ; end = YGRAPH2MAP(p2d->topMargin) ; graphFitBounds (&nx, &ny) ; yMul = 1. ; if (start == end) end = start + 1 ; while ((end - start) * yMul < 1.) yMul *= 10 ; start *= yMul ; end *= yMul ; yMag = (ny - p2d->topMargin - p2d->bottomMargin) / (end - start) ; dy = 5. / yMag ; dy = freeMainRoundPart (dy) ; if(dy <= 0) dy = 1; if (dy * yMag < 2.5) dy *= 2 ; yDiv = 1 ; ddy = dy ; while (ddy && !(ddy % 10)) { yDiv *= 10 ; ddy /= 10 ; } if (yDiv > 1) yDiv /= 10 ; isScale = 0 ; if (yDiv > 1 || yMul > 1) { if (yDiv > yMul) { scale = yDiv / yMul ; isScale = 1 ; } else { scale = yMul / yDiv ; isScale = -1 ; } } if (isScale >= 0) /* mhmp 06.07.99 > ---> >= */ graphText (messprintf ("scale y: 1/%d", scale), 2,yPos + 3) ; else graphText (messprintf ("scale y: 1*%d", scale), 2,yPos + 3) ; iDeb = utMainPart(utArrondi(start)) ; iFin = end ; /* recalage en bas */ if (end - iDeb > dy * 100000) iDeb = start ; else for (yy = iDeb ; yy < end ; yy += dy) if (yy > start) { iDeb = yy - dy ; iFin = 2*p2d->yCentre * yMul - iDeb ; break ; } fin = YMAP2GRAPH((float)iFin/yMul) ; if (fin < p2d->topMargin) fin = p2d->topMargin ; p2d->oldYmag = p2d->yMag ; p2d->yMag = (p2d->yCentre - (float)iDeb/yMul) / (p2d->ny/2.) ; if (p2d->yMag < 1.E-5) return ; for (yy = iDeb ; yy <= iFin ; yy += dy) { y = YMAP2GRAPH((float)yy / yMul) ; if (y <= p2d->topMargin + p2d->ny + 0.0001) { yyy = utArrondi((float)yy / yDiv + 0.0001); graphLine (xPos - 1.5, y, xPos - 0.5, y) ; cp = messprintf ("%d", yyy) ; graphText (cp, p2d->leftMargin - strlen(cp)-1.5,y-.5) ; /*tirets*/ yyp1 = yy + dy ; yp1 = YMAP2GRAPH((float)yyp1 /yMul ) ; sdy = (yp1 - y) / 5. ; for (i = 0 ; i < 4 ; i++) { y += sdy ; if (y >= fin - 0.0001) graphLine (xPos - 1., y, xPos - 0.5, y) ; } } } graphLine (xPos - p2d->axisShift, YMAP2GRAPH((float)iDeb/yMul), xPos - p2d->axisShift, fin) ; } /***************************************/ /* intersection de la droite de regression avec le cadre */ /* y = ax + b topMargin (+ ny) leftMargin (+ nx) */ static void regressInit (P2D p2d, float *x1, float *x2, float *y1, float *y2, int *nbInterp) { float x, y ; int nbInter ; nbInter = 0 ; x = XMAP2GRAPH((YGRAPH2MAP(p2d->topMargin) - p2d->b) / p2d->a ); if (x >= p2d->leftMargin && x <= p2d->leftMargin + p2d->nx) { nbInter++ ; *x1 = x ; *y1 = p2d->topMargin ; } x = XMAP2GRAPH((YGRAPH2MAP(p2d->topMargin + p2d->ny) - p2d->b) / p2d->a) ; if (x >= p2d->leftMargin && x <= p2d->leftMargin + p2d->nx) { nbInter++ ; if (nbInter < 2) { *x1 = x ; *y1 = p2d->topMargin + p2d->ny ; } else { *x2 = x ; *y2 = p2d->topMargin + p2d->ny; *nbInterp = nbInter ; return ; } } y = YMAP2GRAPH(p2d->a * XGRAPH2MAP(p2d->leftMargin) + p2d->b) ; if ( y >= p2d->topMargin && y <= p2d->topMargin + p2d->ny) { nbInter++ ; if (nbInter < 2) { *x1 = p2d->leftMargin ; *y1 = y ; } else { *x2 = p2d->leftMargin ; *y2 = y ; *nbInterp = nbInter ; return ; } } y = YMAP2GRAPH(p2d->a * XGRAPH2MAP(p2d->leftMargin + p2d->nx) + p2d->b) ; if ( y >= p2d->topMargin && y <= p2d->topMargin + p2d->ny) { nbInter++ ; *x2 = p2d->leftMargin + p2d->nx ; *y2 = y ; *nbInterp = nbInter ; } } /***************************************/ static void plot2dDraw (P2D p2d) { int box ; int i ; POINT2D *pp ; int nbInter ; float x = 0, y = 0, eps = 0.1, shift; float xPos = 0, yPos = 0, x1, x2, y1, y2 ; graphClear () ; if (!getNxNy (p2d)) { graphRedraw() ; return ; } xPos = (p2d->leftMargin + p2d->nx) * 0.75 ; yPos = p2d->topMargin + p2d->ny ; p2d->titleBox = graphTextEntry(p2d->title, 47, 2, 0.1, 0) ; /* mhmp 06.07.99 xPos <--> 2 Xbox <-> Ybox */ p2d->subtitleXbox = graphTextEntry(p2d->subtitleX, 23, xPos, yPos + 4., 0) ; p2d->subtitleYbox = graphTextEntry(p2d->subtitleY, 23, 2, yPos + 4., 0) ; if (!p2d->isPrinting) graphButtons (plot2dMenu, 2, 1.8, p2d->nx) ; box = graphBoxStart () ; graphBoxEnd() ; /* les axes */ plot2dXscale (p2d) ; if (p2d->xMag < 1.E-5) goto fin ; plot2dYscale (p2d) ; if (p2d->yMag < 1.E-5) goto fin ; /* le cadre */ x1 = p2d->leftMargin ; x2 = p2d->leftMargin + p2d->nx ; p2d->retBox = graphBoxStart() ; shift = p2d->axisShift ; graphLine (x1 - shift/2, p2d->topMargin - shift, x2 + shift, p2d->topMargin - shift) ; graphLine (x2 + shift, p2d->topMargin - shift, x2 + shift, p2d->topMargin + p2d->ny + shift/2) ; /* les points */ for (i = 0 , pp = arrp (p2d->xy, 0, POINT2D) ; i < arrayMax (p2d->xy) ; i++, pp++) { x = XMAP2GRAPH(pp->x) ; y = YMAP2GRAPH(pp->y) ; if (x >= p2d->leftMargin - eps && x <= p2d->leftMargin + p2d->nx + eps && y >= p2d->topMargin - eps && y <= p2d->topMargin + p2d->ny + eps) graphCircle (x, y, 0.02) ; } /* droite de regression mhmp 25.05.99 */ if (p2d->regress) { regressInit (p2d, &x1, &x2, &y1, &y2, &nbInter) ; if (nbInter == 2) { graphColor (RED) ; graphLine (x1, y1, x2, y2) ; graphColor (BLACK) ; } graphBoxStart() ; graphColor (RED) ; graphText (messprintf("Regression y = %g * x + %g", p2d->a, p2d->b), 20, 3) ; graphText (messprintf ("r = %g w = %g", p2d->r, p2d->w), 31, 4) ; graphColor (BLACK) ; graphBoxEnd() ; } graphBoxEnd() ; /* le reticule */ if (p2d->reticule) { graphText("x = ", 2, 3) ; graphText("y = ", 2, 4) ; p2d->xyBox = graphBoxStart() ; graphTextPtr (p2d->xBuffer, 6, 3 , 8) ; graphTextPtr (p2d->yBuffer, 6, 4 , 8) ; graphBoxEnd () ; graphBoxMenu(p2d->xyBox, plot2dMenu); x = XMAP2GRAPH(p2d->x); y = YMAP2GRAPH(p2d->y) ; graphLine (x - 1, y, x + 1, y) ; graphLine (x, y - 1, x, y + 1) ; } graphRedraw() ; return ; fin: { graphText ("You are a little zoom-zoom!", 2, 5) ; graphRedraw () ; } } /**************************************************************/ static void plot2dInit (P2D p2d) { float l, xMin, xMax , yMin, yMax ; int i ; POINT2D *pp ; if (0) { /*test petites valeurs */ pp = arrp(p2d->xy, 0, POINT2D) ; for (i=0; i< arrayMax(p2d->xy) ; i++, pp++) { pp->x = 35 + pp->x / 10000 ; pp->y *= 100000 ; } } pp = arrp(p2d->xy, 0, POINT2D) ; xMin = xMax = pp->x ; yMin = yMax = pp->y ; for (i=0; i< arrayMax(p2d->xy) ; i++, pp++) { if (pp->x > xMax) xMax = pp->x ; if (pp->x < xMin) xMin = pp->x ; if (pp->y > yMax) yMax = pp->y ; if (pp->y < yMin) yMin = pp->y ; } p2d->xMin = xMin ; p2d->xMax = xMax ; p2d->yMin = yMin ; p2d->yMax = yMax ; getNxNy(p2d) ; l = p2d->xMax - p2d->xMin ; p2d->xCentre = p2d->xMin + l/2.0 ; /* p2d->xMag = l/ (.9 * p2d->nx) ;mhmp 29.04*/ p2d->xMag = l/ (1.0 * p2d->nx) ; p2d->oldXmag = p2d->xMag ; p2d->startXmag = p2d->xMag ; l = p2d->yMax - p2d->yMin ; p2d->yCentre = p2d->yMin + l/2.0 ; /* p2d->yMag = l/ (.9 * p2d->ny) ;mhmp 29.04*/ p2d->yMag = l/ (1.0 * p2d->ny) ; p2d->oldYmag = p2d->yMag ; p2d->reticule = FALSE ; p2d->regress = FALSE ; p2d->isPrinting = FALSE ; p2d->axisShift = 0.5 ; } /*****************************************/ void plot2d (char *title, char *subtitleX, char *subtitleY, Array xy) { P2D p2d = 0 ; STORE_HANDLE hh = 0 ; if (!arrayExists (xy) || !arrayMax(xy) || xy->size != sizeof (POINT2D)) return ; hh = handleCreate () ; p2d = (P2D) halloc (sizeof (struct p2dstuff), hh) ; p2d->handle = hh ; if (!title || !*title) title = "Plot" ; sprintf(p2d->title, "%s", title) ; sprintf(p2d->subtitleX, "%s", subtitleX) ; sprintf(p2d->subtitleY, "%s", subtitleY) ; p2d->xy = xy ; p2d->topMargin = 6 ;/* mhmp 17.03.99 was 5*/ p2d->bottomMargin = 5 ;/* mhmp 21.05.99 was 4*/ p2d->leftMargin = 10 ; /* mhmp 25.05.99 was 4 */ p2d->rightMargin = 2 ; if (graphExists(p2d->graph)) { graphActivate(p2d->graph) ; graphPop() ; } else { if (!graphCreate(TEXT_FIT,title,.2,.2,.6,.5)) return ; graphRetitle (title) ; p2d->graph = graphActive() ; p2d->magic = &Plot2d_MAGIC ; graphAssociate (&Plot2d_MAGIC,p2d) ; graphRegister (DESTROY,plot2dDestroy) ; graphRegister (RESIZE,plot2dResize) ; graphRegister (PICK, plot2dReticule) ; graphRegister (MIDDLE_DOWN, plot2dCentre) ; /* graphRegister (MIDDLE_DRAG, plot2dDrag) ; graphRegister (MIDDLE_UP, plot2dUp) ; */ graphMenu (plot2dMenu) ; } plot2dInit (p2d) ; /* sets ->centre, ->mag */ linearRegression (p2d->xy, &p2d->a, &p2d->b, &p2d->r, &p2d->w) ; plot2dDraw (p2d) ; } /*************************************************************************/ /*************************************************************************/ /* Solves, y = a x + b , in a and b a defaults to *ap if too few data given */ static void linearRegression(Array xy, double *ap, double *bp, double *rp, double *wp) { int i, max ; double r, w, xm,ym,xym , x2m, y2m ,b, a; if(!xy || !(max = arrayMax(xy))) { messout("linearRegression received a null array") ; *ap = * bp = *rp = *wp = 0 ; return; } if(xy->size != sizeof(POINT2D)) messcrash( "linearRegression received a wrong type of Array, should be a pair of doubles ") ; i = max ; xm = ym = xym = 0 ; while (i--) { xm += arr(xy,i,POINT2D).x ; ym += arr(xy,i,POINT2D).y; } xm /= max ; ym /= max; x2m = y2m =xym =0; i = max ; while (i--) { xym += (arr(xy,i,POINT2D).x-xm) *( arr(xy,i,POINT2D).y-ym) ; x2m += (arr(xy,i,POINT2D).x-xm) *( arr(xy,i,POINT2D).x-xm) ; y2m += (arr(xy,i,POINT2D).y-ym) *( arr(xy,i,POINT2D).y-ym) ; } if(max >3 && x2m>0 && y2m >0) { r = xym / sqrt((double)x2m * y2m) ; if (r >= 1) /* mhmp 28.05.99 */ w = 0.999 ; else w = r; i = max - 3 ; w = .5 * log((1+w) / (1-w)) * sqrt((double) i) ; } else r = w = 0 ; i = max ; a = 0 ; while (i--) a += (arr(xy,i,POINT2D).x - xm) * arr(xy,i,POINT2D).y ; if (x2m) a /= x2m ; else a = *ap ; /* default */ b = ym - a*xm ; *ap = a ; *bp = b ; *rp = r ; *wp = w ; } static void plot2dRegression (void) { P2D p2d = currentP2d ("plot2dRegression") ; p2d->regress = !p2d->regress ; p2d->xMag = p2d->oldXmag ; p2d->yMag = p2d->oldYmag ; plot2dDraw (p2d) ; } /*************************************************************************/ /*************************************************************************/