/* InspectStat.h		by Paul Kunz	December 1991
 * Controls binding of the plot axes with the columns of the tuple.
 *
 * Copyright (C)  1991  The Board of Trustees of
 * The Leland Stanford Junior University.  All Rights Reserved.
 */

#import <appkit/appkit.h>
#import "InspectStat.h"

const char InspectStat_h_rcsid[] = INSPECTSTAT_H_ID;
const char InspectStat_m_rcsid[] = "$Id: InspectStat.m,v 2.10 1993/08/04 18:54:09 mfg Exp $";

#import "HGraphicView.h"
#import "NewInspector.h"
#import "Plot.h"

#define XMEAN 0
#define XSDEV 1
#define YMEAN 2
#define YSDEV 3
#define CORR  4

@implementation InspectStat

- initInspFor:aDraw
{    
    NXBundle	*bundle;
    char	buffer[MAXPATHLEN+1];
    int		r;
        
    [super initInspFor:aDraw];
    
    bundle = [NXBundle bundleForClass:[self class]];
    if ( [bundle getPath:buffer forResource:"InspectStat" ofType:"nib"] ) {
    	[NXApp loadNibFile:buffer owner:self
                 withNames:NO  fromZone:[self zone]];
    }
    [theInspector addView:[contentBox contentView]
                  withName:"Plot Statistics" withSupervisor:self];
    [statHBox removeFromSuperview];

    for(r = 0; r < 5; r++) {
    	[[stat2ndMatrix cellAt:r :0] 
    	    setFloatingPointFormat:YES left:3 right:3];
    }

    return self;
}

- createImage:sender
{
    View	*statView;
    NXStream 	*s;
    NXRect	rect, prect;
    display	disp;
    graphtype_t	graphType;

    statView = [statBox contentView];
    selectedPlot = [graphicView firstPlot];
    if ( !selectedPlot ) {
        return self;
    }
    disp = [selectedPlot histDisplay];
    graphType = h_getDispType( disp );
    
    s = NXOpenMemory(NULL, 0, NX_READWRITE);
    if (s) {
        if ( graphType == HISTOGRAM ) {
	    [statHBox getFrame:&rect];	/* a subset of statView */
	} else {
    	    [statView getFrame:&rect];
	}
    	[statView copyPSCodeInside:&rect to:s]; 
    }
    NXSeek(s, 0L, NX_FROMSTART);
    [selectedPlot getBounds:&prect];
    [graphicView loadImageFromStream:s at:&prect.origin allowAlpha:YES];
    NXCloseMemory(s, NX_FREEBUFFER);
    return self;
}

- create2ndImage:sender
{
    View	*statView;
    NXStream 	*s;
    NXRect	rect, prect;
    display	disp;
    graphtype_t	graphType;

    statView = [stat2ndBox contentView];
    selectedPlot = [graphicView firstPlot];
    if ( !selectedPlot ) {
        return self;
    }
    disp = [selectedPlot histDisplay];
    graphType = h_getDispType( disp );
    
    s = NXOpenMemory(NULL, 0, NX_READWRITE);
    if (s) {
    	[statView getFrame:&rect];
    	[statView copyPSCodeInside:&rect to:s]; 
    }
    NXSeek(s, 0L, NX_FROMSTART);
    [selectedPlot getBounds:&prect];
    [graphicView loadImageFromStream:s at:&prect.origin allowAlpha:YES];
    NXCloseMemory(s, NX_FREEBUFFER);
    return self;
}

/* Methods for updating Inspector */
- updateView
{    
    [self showStats];
    return self;
}

- updateEmptySelection
{
    [self clearStats];
    return self;
}

- updateMultiSelection
{
    selectedPlot = nil;
    [self clearStats];
    return self;
}

- clearStats
{
    int		c, r;
    
    for( c = 0; c < 3; c++ ) {
        for( r = 0; r < 3; r++ ) {
	    [[statMatrix cellAt:r :c] setStringValue:""];
	}
    }
    [statMatrix setEnabled:NO];

    for(r = 0; r < 5; r++) {
	[[stat2ndMatrix cellAt:r :0] setStringValue:""];
    }
    [stat2ndMatrix setEnabled:NO];

    return self;
}

- showStats
{
    id		aCell;
    display	disp;
    graphtype_t	graphType;
    int		c, r;
    double 	xmean;
    double	ymean;
    double	temp;
    double 	xmoments[3];
    double	ymoments[3];
    float	xtemp[3];
    float	ytemp[3];
    float 	corr;
    BOOL	doCorr;
        
    selectedPlot = [graphicView firstPlot];
    if ( !selectedPlot ) {
        [self clearStats];
        return self;
    }
    disp = [selectedPlot histDisplay];
    graphType = h_getDispType( disp );

    [statMatrix setEnabled:YES];
    if (graphType == HISTOGRAM) {
         for ( r = 0; r < 4; r++ ) {
	     [[statRowLabels cellAt:r :0] setStringValue:""];
	 } 
	 for ( r = 0; r < 3; r++ ) {
		for ( c = 0; c < 3; c++ ) {
		    aCell = [statMatrix cellAt:r :c ];
		    if ( r == 0 ) {
		        [aCell setFloatValue:h_getTotal(disp,c,0) ];
		    } else {
		        [aCell setStringValue:""];
		    }
		}
	}
        
    } else {
	 [[statRowLabels cellAt:0 :0] setStringValue:"y/x"];
	 [[statRowLabels cellAt:1 :0] setStringValue:"over"];
	 [[statRowLabels cellAt:2 :0] setStringValue:"within"];
	 [[statRowLabels cellAt:3 :0] setStringValue:"under"];
	 for ( c = 0; c < 3; c++ )
	 {
	      for ( r = 0; r < 3; r++ )
	      {
		   aCell = [statMatrix cellAt:r :c];
		   [aCell setFloatValue:h_getTotal(disp,c,2-r) ];
	      }
	 }
         
    }
    if ((graphType == SCATTERPLOT) || 
    	(graphType == XYPLOT) || 
    	(graphType == STRIPCHART)) { 
	doCorr = YES;
	h_getXYMoments (disp, xtemp, ytemp, &corr);
    	for(r = 0; r < 3; r++) {
            xmoments[r] = xtemp[r];
            ymoments[r] = ytemp[r];
    	}
    } else {
	doCorr = NO;
    	for(r = 0; r < 3; r++) {
            xmoments[r] = h_getXMoments(disp)[r];
            ymoments[r] = h_getYMoments(disp)[r];
    	}
    }

    [stat2ndMatrix setEnabled:YES];
    if (xmoments[0] > 1.) {
        xmean = xmoments[1]/xmoments[0];
	[[stat2ndMatrix cellAt:XMEAN :0] setFloatValue:xmean];
        temp = sqrt((xmoments[2]*xmoments[0] - xmoments[1]*xmoments[1]) /
	    (xmoments[0]*(xmoments[0] - 1)));
	[[stat2ndMatrix cellAt:XSDEV :0] setFloatValue:temp];
    } else {
	[[stat2ndMatrix cellAt:XMEAN :0] setStringValue:""];
	[[stat2ndMatrix cellAt:XSDEV :0] setStringValue:""];

    }     
    if (ymoments[0] > 1.) {
        ymean = ymoments[1]/ymoments[0];
	[[stat2ndMatrix cellAt:YMEAN :0] setFloatValue:ymean];
        temp = sqrt((ymoments[2]*ymoments[0] - ymoments[1]*ymoments[1]) /
	    (ymoments[0]*(ymoments[0] - 1)));
	[[stat2ndMatrix cellAt:YSDEV :0] setFloatValue:temp];
    } else {
	[[stat2ndMatrix cellAt:YMEAN :0] setStringValue:""];
	[[stat2ndMatrix cellAt:YSDEV :0] setStringValue:""];
    }

    if (doCorr) {
	[[stat2ndMatrix cellAt:CORR :0] setFloatValue:corr];
    } else {
	[[stat2ndMatrix cellAt:CORR :0] setStringValue:""];
    }

    return self;
}
    
@end
