WorldViz User Forum  

Go Back   WorldViz User Forum > Vizard

Reply
 
Thread Tools Rate Thread Display Modes
  #1  
Old 02-04-2016, 07:47 AM
jelly jelly is offline
Member
 
Join Date: Feb 2016
Posts: 38
playing sound and displaying picture - condition within loop

Dear all,

I am a programming beginner and I started using Vizard because I am trying to design a little experiment for my studies. Here is what is supposed to happen and below is what I have so far:

The screen should show an upper and a lower window. Each window will receive a simple texture (.png or .jpeg) to display two different pictures. In the upper window, there would be the task instruction and in the lower window, there would be a "default" picture. At the same time, a beep sound will play 10 times at random intervals (from 1 to 4 seconds). What I want: 7 out of ten random times, just as a sound cue plays, the lower screen should change from the default picture to Picture A and 3 out of 10 random times to Picture B.

Code:
#Set background colour to white:
viz.clearcolor(viz.WHITE)

taskpic = 'instruction.jpg'
pictureA = 'picA.jpg'
pictureB = 'picB.jpg'
picturedefault = 'default.png'
cue = viz.addAudio('dong.wav')
SoundDuration = cue.getDuration()

import viz 															
import time
import viztask
import random														
viz.go()

def exp(): #this is the function that triggers my experiment

	screen2 = viz.addTexQuad(size=0.5)            #upper screen window
	screen2.setPosition([0,2.1,1.3])
	screen2.setSize([0.4, 0.4])

	screen3 = viz.addTexQuad(size=0.5)            #lower screen window
	screen3.setPosition([0,1.6,1.3])
	screen3.setSize([0.4, 0.4])

	picture_task = viz.add(taskpic)
	defaultpic = viz.add(default)

	screen2.texture(picture_task)			#picture with instruction is added as a texture to upper screen
	screen3.texture(defaultpic)			#default picture is added as a texture to upper screen
	
	def playCueLoop():
		count = 0
		while count < 10:
			count += 1
			for x in count:
				if x <= 7:
					cue.play()
					yield viztask.waitTime(SoundDuration+random.randrange(1,4))
					cue.stop()
					PicA = viz.add(PictureA)
					screen3.texture(PicA)
					yield viztask.waitTime()
				elif x <= 3:
					cue.play()
					yield viztask.waitTime(SoundDuration+random.randrange(1,4))
					cue.stop()
					PicB = viz.add(PictureB)
					screen3.texture(PicB)
					yield viztask.waitTime()
				
	#viztask.schedule(playCueLoop)

viztask.schedule(exp)
I know there must be a lot of things wrong in this code (apart from the if statement - maybe the rationale behind the changing of the screen windows?), but it sort of worked until I had the if condition (7 and 3 out of 10). I've played around with it and sometimes I still get the sound to play, but at no point have I managed to change the lower screen, even without a complex condition attached to it.

I would be happy to receive some pointers in the right direction! At the moment there are probably a lot of things to improve and it is impossible for me to isolate one aspect to test it around.

Thank you very much in advance for your help!
Reply With Quote
  #2  
Old 02-04-2016, 11:47 PM
Jeff Jeff is offline
WorldViz Team Member
 
Join Date: Aug 2008
Posts: 2,471
In general, debugging custom code is beyond the scope of what we can help with on the forum. When posting code it's best to create the simplest possible example that can be run directly and reproduces the issue. See the guidelines for posting Vizard code for more information.
Reply With Quote
  #3  
Old 02-05-2016, 01:30 AM
Erikvdb Erikvdb is offline
Member
 
Join Date: May 2013
Posts: 63
I agree with Jeff that we shouldn't fix entire programs here, and there is indeed a lot wrong with your code

The main issue here is that your for loop inside the while loop makes absolutely no sense and your "x <= 3" will never trigger because if x is smaller than 3, it's also smaller than 7.
For a proper random chance calculation (with a given chance), use something like:
Code:
if random.random() < 0.7
Or if you want to make sure that it is always going to be exactly 7 out of 10, make a list with 7 "A"s and 3 "B"s, random.shuffle() the list and iterate over that.
Reply With Quote
  #4  
Old 02-06-2016, 01:51 PM
jelly jelly is offline
Member
 
Join Date: Feb 2016
Posts: 38
Thanks! I have made some advancements yesterday, now at least the logic with the changing the screen works. My next step is that loop so thanks for the useful pointers. I'll post an update soon.
Reply With Quote
  #5  
Old 02-07-2016, 10:08 AM
jelly jelly is offline
Member
 
Join Date: Feb 2016
Posts: 38
Hello again!

I got the lower window exchange to work. That alone taught me some things about global variables and how to think about those TexQuads. Now on to the next problem: Exchanging the picture in the lower window 7 out of 10 times with one picture and 3 times with another (randomly).

I tried the list strategy, as suggested by Erikvdb, I've consulted all my resources, and I managed to implement it. However, the problem is that sometimes it shows the picture C 3 random times (as it should), other times, only 1 or 2 times. Almost as if it's randomly picking from the list 10 times. However, I want it to go through the entire list once. I am wondering if my list implementation is correct? Maybe I should not put several identical elements in a list? Or it's a problem regarding the implementation inside the "while loop"

I tried to simplify the code and create this as a separate script with the simplest form of the issue, as suggested by Jeff. Rather than code debugging I am hoping that someone might link me to a relevant example of a list within a loop. Obviously I am lacking the logic behind it especially when things get nested.


Code:
## Import Vizard modules ##

import viz 																														
import viztask							
import random							

#Start Vizard:															
viz.go()

## STIMULI ##

#pictures
pictureA = viz.add('picA.jpg')
default = viz.add('default.png')

#sound
cue = viz.addAudio('dong.wav')

#list (7 times picture B and 3 times picture C)
pictureList = ['picB.png', 'picB.png', 'picB.png', 'picB.png', 'picB.png', 'picB.png', 'picC.png', 'picC.png', 'picC.png']


#Make a screen window:
screen1 = viz.addTexQuad(size=0.5)            
screen1.setPosition([0,2.1,1.3])
screen1.setSize([0.4, 0.4])

#Make a second screen window:
screen2 = viz.addTexQuad(size=0.5)            
screen2.setPosition([0,1.6,1.3])
screen2.setSize([0.4, 0.4])

## TASK##

def task():
	screen1.texture(pictureA)
	screen2.texture(default)

	def playCueLoop():  # default picture is shown in lower window + 10 times, at randomly intersperced intervals, a sound beep plays & each time that happens, the lower window replaces the default picture randomly with 7 times picB and 3 times pic C
		count = 0
		while count < 10:
			count += 1
			cue.play()
			pictureIndex = 0
			random.shuffle(pictureList)
			picture = viz.add(pictureList[pictureIndex])
			screen2.texture(picture)
			pictureIndex += 1
			yield viztask.waitTime(0.5)
			screen2.texture(default)
			yield viztask.waitTime(0)
			yield viztask.waitTime(random.randrange(1,4))	
	viztask.schedule (playCueLoop())

viztask.schedule(task())
My only resource is a huge code with one list example (but there is no loop) - this is just a snippet:

Code:
photoList = ['A1.jpg','A2.jpg','A3.jpg','A4.jpg','A5.jpg','A6.jpg','A7.jpg','A8.jpg','A9.jpg','A10.jpg']
random.shuffle(photoList)

photo = viz.add('Pictures\\' + photoList[photoIndex])
photoFrame.texture(photo)
photoIndex += 1
I would be very greatful for any help or pointers!

P.S. I know Erikvdb suggested in another thread to stop the sound as well, however I left that out for now, to simplify the code
Reply With Quote
  #6  
Old 02-11-2016, 05:33 AM
Erikvdb Erikvdb is offline
Member
 
Join Date: May 2013
Posts: 63
Only shuffle once, BEFORE the loop, not INSIDE the loop. Now the list gets constantly shuffled again before every pick

Also not crucial, but a helpful little housekeeping:
- use a for loop to iterate over the list. It's cleaner and easier.
- load your textures beforehand, not inside the loop, to improve performance.
Reply With Quote
  #7  
Old 02-11-2016, 10:13 AM
jelly jelly is offline
Member
 
Join Date: Feb 2016
Posts: 38
turns out it happened because the shuffling was done inside the while loop. the index should be a global variable as well. it now works!
Reply With Quote
  #8  
Old 02-11-2016, 10:14 AM
jelly jelly is offline
Member
 
Join Date: Feb 2016
Posts: 38
Oh Erikvdb, I had not seen your answer! Great, thank you, I will try the "for loop", that I have not implemented yet and I do want my code to become cleaner! Thanks!
Reply With Quote
  #9  
Old 02-15-2016, 09:26 AM
jelly jelly is offline
Member
 
Join Date: Feb 2016
Posts: 38
Smile

Hello again,

I hope I managed to implement what you meant, Erikvdb. I changed the while loop with a for loop and I loaded two of the screen textures outside of the loop, however, some textures I need to leave inside the loop, because it won't work otherwise. The screen 2 which is changing its picture, for example. I also tried adding the "picture = viz.add(pictureList[pictureIndex])" right after the pictureList and shuffling bit, but it won't work, it seems to want to be in the loop.

I did not really understand why I have to make the PictureIndex a global variable within the function, since I have defined it outside the function (which to my understanding already makes it a global variable), but it won't work otherwise.


Code:
import viz 																														
import viztask							
import random							

#Start Vizard:															
viz.go()

## STIMULI ##

#pictures
pictureA = viz.add('picA.jpg')
default = viz.add('default.png')

#sound
cue = viz.addAudio('dong.wav')

#list (7 times picture B and 3 times picture C)
pictureList = ['picB.png', 'picB.png', 'picB.png', 'picB.png', 'picB.png', 'picB.png', 'picB.png', 'picC.png', 'picC.png', 'picC.png']
random.shuffle(pictureList)
pictureIndex = 0

#Make a screen window:
screen1 = viz.addTexQuad(size=0.5)            
screen1.setPosition([0,2.1,1.3])
screen1.setSize([0.4, 0.4])

#Make a second screen window:
screen2 = viz.addTexQuad(size=0.5)            
screen2.setPosition([0,1.6,1.3])
screen2.setSize([0.4, 0.4])

screen1.texture(pictureA)
screen2.texture(default)
	
## TASK##

def task():
	screen1
	screen2

	def playCueLoop():  # default picture is shown in lower window + 10 times, at randomly intersperced intervals, a sound beep plays & each time that happens, the lower window replaces the default picture randomly with 7 times picB and 3 times pic C
		global pictureIndex
		for x in range(10):
			cue.play()
			yield viztask.waitTime(random.randrange(1,4))
			picture = viz.add(pictureList[pictureIndex])
			screen2.texture(picture)
			pictureIndex += 1
			yield viztask.waitTime(0.5)
			screen2.texture(default)
			yield viztask.waitTime(0)
	viztask.schedule (playCueLoop())

viztask.schedule(task())
Reply With Quote
Reply

Tags
condition, loop, picture, sound

Thread Tools
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
playing a sound multiple times at different timings jelly Vizard 3 02-04-2016 03:39 AM


All times are GMT -7. The time now is 01:02 AM.


Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Copyright 2002-2023 WorldViz LLC