package info.istlab.Zemi01.numeric; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.Random; import javax.swing.JFrame; import javax.swing.JPanel; import info.istlab.Zemi01.Launcher; import info.istlab.Zemi01.miuramath.Ttest; /** * 正規分布、ガウス分布 */ public class WelchTtest extends JPanel implements MouseListener, MouseMotionListener, KeyListener { private static final long serialVersionUID = -919448575666487391L; public static JFrame jf; /** * @param args */ public static void main(String[] args) { jf = new JFrame("正規分布、ガウス分布"); jf.getContentPane().add(new WelchTtest()); jf.pack(); jf.setVisible(true); jf.setLocation(Launcher.centerOfScreen(jf.getSize())); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); System.out.println("正規分布、ガウス分布 "); System.out.println("つかいかた:(1)右クリックで、点を追加 (2)左ドラッグで、点移動 or グラフ移動 (3) 点の上で右クリックすると、点が消えます。"); } Point2D offset; ND[] normdist = new ND[2]; Dimension dim; Point2D pointingPmath; Point2D pressP; static int psize = 10; public Dimension getPreferredSize() { return dim; } public WelchTtest() { offset = new Point2D.Double(0, 100); dim = new Dimension(500, 400); addMouseListener(this); addMouseMotionListener(this); addKeyListener(this); this.setFocusable(true); this.requestFocusInWindow(); normdist[0] = new ND(Color.blue, 0, 0); normdist[1] = new ND(Color.green, 20, -30); setBackground(Color.white); setForeground(Color.black); updateNormDist(); } public void paint(Graphics g) { paintComponent(g); } public void paintComponent(Graphics g) { Graphics2D g2d = (Graphics2D) g; RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setRenderingHints(rh); // g2d.setBackground(Color.white); // g2d.setColor(Color.black); g2d.clearRect(0, 0, getWidth(), getHeight()); paintGrid(g2d); if (pointingPmath != null) { g2d.setColor(Color.red); paintPoint(g2d, pointingPmath); } for (ND nd : normdist) { nd.paintND(g2d, this); } if (p2 < 0.05) { g2d.setColor(Color.cyan); } else { g2d.setColor(Color.YELLOW); } for (int i = -2; i < 3; i++) for (int j = -2; j < 3; j++) { // g2d.drawRect(10, 50, 100, 10); g2d.drawString("t (" + String.format("%4.2f", df2) + ") = " + String.format("%5.3f", welch_t), (int) (-getWidth() / 2 + 30 - offset.getX() + i), (int) (-getHeight() / 2 + 320 - offset.getY()) + j); g2d.drawString("p = " + String.format("%5.3f", p2), (int) (-getWidth() / 2 + 30 - offset.getX() + i), (int) (-getHeight() / 2 + 345 - offset.getY()) + j); } if (p2 < 0.05) { g2d.setColor(Color.blue); } else { g2d.setColor(Color.red); } // g2d.drawRect(10, 50, 100, 10); g2d.drawString("t (" + String.format("%4.2f", df2) + ") = " + String.format("%5.3f", welch_t), (int) (-getWidth() / 2 + 30 - offset.getX()), (int) (-getHeight() / 2 + 320 - offset.getY())); g2d.drawString("p = " + String.format("%5.3f", p2), (int) (-getWidth() / 2 + 30 - offset.getX()), (int) (-getHeight() / 2 + 345 - offset.getY())); } private void updateNormDist() { for (ND nd : normdist) { nd.updateNormDist(); } updateTdist(); } double welch_t; double df2; double p2; private void updateTdist() { welch_t = Ttest.welch_t(normdist[1].data(), normdist[0].data()); df2 = Ttest.welch_degree_of_freedom(normdist[1].data(), normdist[0].data()); p2 = Ttest.tdist(welch_t, df2, 2); // System.out.println("p2 = "+p2); } public void paintPoint(Graphics2D g2d, Point2D p) { g2d.setColor(Color.red); g2d.fillOval((int) (p.getX() - WelchTtest.psize / 2), (int) (-(p.getY() + WelchTtest.psize / 2)), WelchTtest.psize, WelchTtest.psize); // g2d.drawString(String.valueOf(num), (int)p.getX()+10, (int)p.getY()); } public void paintGrid(Graphics2D g2d) { g2d.setColor(new Color(230, 230, 230)); g2d.translate(getWidth() / 2 + offset.getX(), getHeight() / 2 + offset.getY()); // System.out.println(g2d.getTransform().getTranslateX()+" // "+g2d.getTransform().getTranslateY()); for (int i = 0; i < getWidth(); i += 20) { g2d.drawLine(i, -getHeight(), i, getHeight()); g2d.drawLine(-i, -getHeight(), -i, getHeight()); } for (int i = 0; i < getHeight(); i += 20) { g2d.drawLine(-getWidth(), i, getWidth(), i); g2d.drawLine(-getWidth(), -i, getWidth(), -i); } g2d.setColor(Color.black); g2d.drawLine(0, getHeight() * 3, 0, -getHeight() * 3); g2d.drawLine(-getWidth() * 3, 0, getWidth() * 3, 0); // g2d.translate(-(getWidth()/2+offset.getX()), -(getHeight()/2+offset.getY())); } public Point2D scr2math(Point2D p) { double x = p.getX(); double y = p.getY(); x = x - offset.getX() - getWidth() / 2; y = y - offset.getY() - getHeight() / 2; y = -y; // System.out.println("scr2math "+x+", "+y); return new Point2D.Double(x, y); } public Point2D math2scr(Point2D p) { return new Point2D.Double(p.getX(), -p.getY()); } public void mouseClicked(MouseEvent e) { if (e.getButton() == 3) { Point2D pointing = findPointing(e.getPoint()); if (pointing == null) normdist[0].points.add(scr2math(e.getPoint())); else { if (normdist[0].points.size() > 2) normdist[0].points.remove(pointing); } updateNormDist(); repaint(); } } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public Point2D findPointing(Point2D mp) { // Point2D nearest = null; Point2D mPmath = scr2math(mp); Point2D nP = null; for (ND n : normdist) { nP = n.nearestPoint(mPmath); if (nP != null) break; } return nP; // pointingPmath = nP; // for (Point2D p : points) { // if (mPmath.distance(p) < 8) { // nearest = p; // } // } // return nearest; } public void mousePressed(MouseEvent e) { mouseMoved(e); } public void mouseReleased(MouseEvent e) { pointingPmath = null; repaint(); } public void mouseDragged(MouseEvent e) { if (pointingPmath != null) { pointingPmath.setLocation(scr2math(e.getPoint())); updateNormDist(); repaint(); } else { // e.translatePoint((int)offset.getX(), (int)offset.getY()); offset.setLocation(offset.getX() + (e.getPoint().getX() - pressP.getX()), offset.getY() + (e.getPoint().getY() - pressP.getY())); pressP = e.getPoint(); updateNormDist(); repaint(); } } public void mouseMoved(MouseEvent e) { scr2math(e.getPoint()); pressP = e.getPoint(); Point2D pressPmath = scr2math(pressP); Point2D nP = null; for (ND n : normdist) { nP = n.nearestPoint(pressPmath); if (nP != null) break; } pointingPmath = nP; updateNormDist(); repaint(); } @Override public void keyTyped(KeyEvent e) { // TODO Auto-generated method stub } @Override public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ENTER) { System.out.println(e.getKeyCode()); normdist[0] = new ND(Color.blue, 0, 0); normdist[1] = new ND(Color.green, 20, -30); updateNormDist(); repaint(); } } @Override public void keyReleased(KeyEvent e) { // TODO Auto-generated method stub } } class ND { ArrayList<Point2D> points; Color color; int offsetx = 0; int offsety = 0; public ND(Color c, int _offsetx, int _offsety) { color = c; offsetx = _offsetx; offsety = _offsety; points = new ArrayList<Point2D>(); Random rand = new Random(); for (int i = 0; i < 7; i++) { int randx = rand.nextInt(-40 + offsetx, 40 + offsetx); int randy = rand.nextInt(-10 + offsety, offsety); points.add(new Point2D.Double(randx, randy)); } updateNormDist(); } double[] ddat; public double[] data() { return ddat; } // 平均と分散 double xavg = 0; double xvarp = 1; /** * ガウス関数、ただし、μとσ^2は、xavg, xvarp から計算する * * @param x * @return */ public double gauss_function(double x) { double d1 = 1.0 / Math.sqrt(2 * Math.PI * xvarp); double d2 = Math.exp(-Math.pow(x - xavg, 2) / (2 * xvarp)); double ret = d1 * d2 * 10000; // System.out.println(ret); return ret; } /** * 点のx座標から、ガウス関数のパラメータ μとσ^2は、xavg, xvarp を更新する */ public void updateNormDist() { ddat = new double[points.size()]; int i = 0; for (Point2D p : points) { ddat[i] = p.getX(); i++; } // 平均値を更新する xavg = Ttest.avg(ddat); // 標準偏差を更新する xvarp = Ttest.varp(ddat); // System.out.println("μ " + xavg + " σ^2 " + xvarp); } public void paintND(Graphics2D g2d, WelchTtest wtest) { g2d.setColor(Color.black); for (Point2D p : points) { paintPoint(g2d, p); } Point2D prep = null; g2d.setColor(color); for (double x = -wtest.getWidth() / 2 - wtest.offset.getX(); x < wtest.getWidth() / 2 - wtest.offset.getX(); x += 1.0) { Point2D p1 = wtest.math2scr(new Point2D.Double(x, gauss_function(x))); if (prep == null) prep = p1; g2d.drawLine((int) p1.getX(), (int) p1.getY(), (int) prep.getX(), (int) prep.getY()); prep = p1; } if (offsetx > 10) { g2d.drawString("μ = " + String.format("%6.4f", xavg), (int) (wtest.getWidth() / 5 - wtest.offset.getX()), (int) (-wtest.getHeight() / 2 + 20 - wtest.offset.getY())); g2d.drawString("σ = " + String.format("%6.4f", Math.sqrt(xvarp)), (int) (wtest.getWidth() / 5 - wtest.offset.getX()), (int) (-wtest.getHeight() / 2 + 38 - wtest.offset.getY())); g2d.drawString("σ^2 = " + String.format("%6.4f", xvarp), (int) (wtest.getWidth() / 5 - wtest.offset.getX()), (int) (-wtest.getHeight() / 2 + 56 - wtest.offset.getY())); } else { g2d.drawString("μ = " + String.format("%6.4f", xavg), (int) (-wtest.getWidth() / 2 + 10 - wtest.offset.getX()), (int) (-wtest.getHeight() / 2 + 20 - wtest.offset.getY())); g2d.drawString("σ = " + String.format("%6.4f", Math.sqrt(xvarp)), (int) (-wtest.getWidth() / 2 + 10 - wtest.offset.getX()), (int) (-wtest.getHeight() / 2 + 38 - wtest.offset.getY())); g2d.drawString("σ^2 = " + String.format("%6.4f", xvarp), (int) (-wtest.getWidth() / 2 + 10 - wtest.offset.getX()), (int) (-wtest.getHeight() / 2 + 56 - wtest.offset.getY())); } } public void paintPoint(Graphics2D g2d, Point2D p) { g2d.fillOval((int) (p.getX() - WelchTtest.psize / 2), (int) (-(p.getY() + WelchTtest.psize / 2)), WelchTtest.psize, WelchTtest.psize); // g2d.drawString(String.valueOf(num), (int)p.getX()+10, (int)p.getY()); } public Point2D nearestPoint(Point2D pressPmath) { Point2D nearest = null; for (Point2D p : points) { if (pressPmath.distance(p) < 8) { nearest = p; } } return nearest; } }