/* * OrientationDiscrimination.java * * Copyright (C) 2005-2012 Huseyin Boyaci. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This program 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 version 2 for more details * (a copy is included in the LICENSE file that accompanied this code) * (also available at http://www.gnu.org) 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. * */ import static java.lang.Math.PI; import java.awt.Color; import java.awt.Font; import java.awt.event.KeyEvent; import java.awt.image.BufferedImage; import java.io.FileNotFoundException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import javax.sound.sampled.LineUnavailableException; import psychWithJava.Extras; import psychWithJava.FullScreen; import psychWithJava.PixelOutOfRangeException; /** * Implements a simple forced-choice experiment with method of constant stimuli * * * @see FullScreen * * @author Huseyin Boyaci * @since 2012-3-15 * */ public class OrientationDiscrimination extends FullScreen implements Runnable{ /** pixel value of the background */ static final int MEAN = 127; /** frequency of the sinusoidal grating, in cycles per pixel */ static final double CPP = 0.02; /** determines the horizontal shift of the sinusoidal grating */ static final double PHASE = 0; static final double ONE_DEGREE = PI/180; /** orientations, vertical = 0 */ static final double[] ORIENTATION = { 0.5*ONE_DEGREE,-0.5*ONE_DEGREE, ONE_DEGREE,-ONE_DEGREE, 1.5*ONE_DEGREE,-1.5*ONE_DEGREE, 2*ONE_DEGREE,-2*ONE_DEGREE, 2.5*ONE_DEGREE,-2.5*ONE_DEGREE }; /** determines the spread of the Gaussian envelope */ static final int SIGMA = 24; /* Experimental procedure parameters */ static final double CONTRAST = 0.5; static final int N_TRIALS = 10; static PrintWriter outputFile; public static void main(String[] args){ // Open the output file for saving the data try { outputFile = Extras.setOutputFile("data"); } catch (FileNotFoundException e) { e.printStackTrace(); } OrientationDiscrimination gd = new OrientationDiscrimination(); new Thread(gd).start(); } public void run() { try{ setNBuffers(2); setBackground(new Color(MEAN,MEAN,MEAN)); setFont(new Font("SansSerif", Font.BOLD, 26)); displayText(100, 200, "Task:"); displayText(100, 300, " Indicate the orientation of"); displayText(100, 350, " the Gabor patch"); displayText(100, 400, " (Use the Left/Right arrows)"); displayText(100, 500, "Now press any key to continue"); updateScreen(); getKeyPressed(-1); blankScreen(); updateScreen(); hideCursor(); /* First put the elements of ORIENTATION in an ArrayList object */ ArrayList orientations = new ArrayList(); for(double o: ORIENTATION) orientations.add(o); for(int trial=0; trial it = orientations.iterator(); /* Next one by one get elements from that iterator, until no elements left */ while(it.hasNext()){ double stimulusLevel = it.next(); outputFile.printf("%3.5f ",stimulusLevel); BufferedImage gbr = Extras.gabor(MEAN, CPP, CONTRAST, PHASE, SIGMA, stimulusLevel); blankScreen(); displayImage(gbr); updateScreen(); flushKeyPressed(); Thread.sleep(250); blankScreen(); updateScreen(); int response = getKeyPressed(-1).getKey(); /* wait until a left or right arrow is pressed */ while(!(response== KeyEvent.VK_LEFT || response==KeyEvent.VK_RIGHT)) response=getKeyPressed(-1).getKey(); if((response == KeyEvent.VK_LEFT && stimulusLevel<0) || (response == KeyEvent.VK_RIGHT && stimulusLevel>0) ){ Extras.beep(300,200); outputFile.println("correct"); } else{ Extras.beep(3800,200); outputFile.println("incorrect"); } outputFile.flush(); Thread.sleep(1000); } } } catch (PixelOutOfRangeException e) { e.printStackTrace(); } catch (LineUnavailableException e) { e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); Thread.currentThread().interrupt(); } finally { closeScreen(); } } }