diff --git a/readme.md b/readme.md deleted file mode 100755 index 1a98020..0000000 --- a/readme.md +++ /dev/null @@ -1,57 +0,0 @@ -BehaviorMate -====== - - -## Operating systems: -Windows, Linux, OSX - -## Installation - -* Download and install Arduino IDE - -Add Arduino Due to the existing boards in : - -``` -Tools > Board > Boards Manager -``` - -Install the following library in - -``` -Sketch -> Include Library -> Manage Libraries... -``` -: -``` -ArduinoJson -``` -Make sure you select version **5.13.2** - -# Acknowledgements - -Special thanks to the following people - -* - - -# Questions, comments, issues - -Please use the [GitLab's issue tracker](https://gitlab.com/losonczylab/BehaviorMate/issues) for questions and comments and create an issue for any bugs you might encounter. - - - -# License - -Unless otherwise specified in individual files, all code is -Copyright (C) 2016 The Trustees of Columbia University in the City of New -York. 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 for more -details. - -You should have received a copy of the GNU General Public License along with -this program. If not, see . \ No newline at end of file diff --git a/src/BasicContextList.java b/src/BasicContextList.java index 10eae37..f9a350e 100644 --- a/src/BasicContextList.java +++ b/src/BasicContextList.java @@ -224,7 +224,7 @@ public UdpClient getComm() { * ? */ public void sendCreateMessages() { - // comm may be null for certian subclasses of ContextList which to not + // comm may be null for certain subclasses of ContextList which to not // need to talk to the behavior arduino if (comm != null) { context_info.setString("action", "create"); @@ -242,7 +242,7 @@ public void sendCreateMessages() { int valve_pin = valves.getInt(i); JSONObject valve_json; - // frequency causes this singal to oscillate in order to play a + // frequency causes this signal to oscillate in order to play a // tone if (!context_info.isNull("frequency")) { valve_json = TreadmillController.setup_valve_json(valve_pin, diff --git a/src/FileWriter.java b/src/FileWriter.java index 316484f..b8f2ffd 100644 --- a/src/FileWriter.java +++ b/src/FileWriter.java @@ -148,7 +148,7 @@ public class WriterThread extends Thread { * Placeholder */ public void run() { - messageBuffer = writeQueue.poll(); + messageBuffer = writeQueue.peek(); while (this.run || messageBuffer != null) { if (messageBuffer != null) { try { @@ -173,11 +173,17 @@ public void run() { alert += ("\n" + elements[i].toString()); } if (tl != null) { - tl.exception(alert); + //tl.exception(alert); + tl.alert("FileWriter: Error logging message:\n" + + messageBuffer); + try { + Thread.sleep(25); + } catch (InterruptedException ie) {} } break; } - messageBuffer = writeQueue.poll(); + writeQueue.poll(); + messageBuffer = writeQueue.peek(); } try { @@ -194,7 +200,7 @@ public void run() { Thread.sleep(25); } catch (InterruptedException e) {} - messageBuffer = writeQueue.poll(); + messageBuffer = writeQueue.peek(); } } diff --git a/src/TimedITIContextDecorator.java b/src/TimedITIContextDecorator.java index 74337c9..68ed337 100644 --- a/src/TimedITIContextDecorator.java +++ b/src/TimedITIContextDecorator.java @@ -27,12 +27,12 @@ public class TimedITIContextDecorator extends SuspendableContextDecorator { /** * ? */ - protected int iti_time_min; + protected float iti_time_min; /** * ? */ - protected int iti_time_max; + protected float iti_time_max; /** * ? @@ -73,6 +73,7 @@ public TimedITIContextDecorator(TreadmillController tc, this.random_iti = context_info.getBoolean("random_iti", false); if (this.random_iti) { + this.random = new Random(); this.iti_time_min = context_info.getInt("iti_time_min"); this.iti_time_max = context_info.getInt("iti_time_max"); } else { @@ -134,8 +135,8 @@ public boolean check_suspend(float position, float time, int lap, int lick_count if (this.long_delay_laps.contains(this.start_lap)) { this.next_start = time + this.long_delay; } else if (this.random_iti) { - this.next_start = time + random.nextInt( - (this.iti_time_max - this.iti_time_min + 1)) + this.iti_time_min; + this.next_start = time + this.random.nextFloat() * + (this.iti_time_max - this.iti_time_min) + this.iti_time_min; } else { this.next_start = time + this.iti_time; } diff --git a/src/TreadmillController.java b/src/TreadmillController.java index 6777950..582e3a9 100755 --- a/src/TreadmillController.java +++ b/src/TreadmillController.java @@ -94,6 +94,10 @@ public class TreadmillController extends PApplet { */ ArrayList comms; + // List to store behavior comms that haven't confirmed creation. Used to verify + // system is ready to start an experiment + ArrayList unset_contexts; + /** * Time (ms) of the last comms check */ @@ -502,6 +506,10 @@ public boolean Start(String mouse_name, String experiment_group) { testComms(); + if (unset_contexts.size() > 0) { + trialListener.alert("Failed to create Contexts\n" + String.join(", ", unset_contexts)); + } + trialListener.started(fWriter.getFile()); timer.startTimer(); @@ -922,6 +930,9 @@ void configure_rewards() throws Exception { if (context.getString("id").equals(reward_context)) { JSONArray valve_list = context.getJSONArray("valves"); reward_valve = valve_list.getInt(0); + if (context.getString("type").equals("operant")) { + lickport_pin = context.getInt("sensor"); + } return; } } @@ -939,6 +950,10 @@ void configure_rewards() throws Exception { reward_info.setJSONArray("valves", context_valves); } + if (!reward_info.isNull("sensor")) { + lickport_pin = reward_info.getInt("sensor"); + } + if (!reward_info.isNull("drop_size")) { JSONArray context_duration = new JSONArray(); context_duration.append(reward_info.getInt("drop_size")); @@ -1011,6 +1026,7 @@ void reload_settings(String filename, String tag) throws Exception { */ void startComms() throws Exception { comms = new ArrayList(); + unset_contexts = new ArrayList(); position_comm = null; behavior_comm = null; reset_comm = null; @@ -1178,10 +1194,11 @@ void reconfigureExperiment() throws Exception { } if (!settings_json.isNull("contexts")) { + unset_contexts.clear(); delay(10); - VrContextList2 vr_context = null; - ArrayList cue_lists = - new ArrayList(); + //VrContextList2 vr_context = null; + //ArrayList cue_lists = + // new ArrayList(); JSONArray contexts_array = settings_json.getJSONArray("contexts"); for (int i = 0; i < contexts_array.size(); i++) { @@ -1199,6 +1216,10 @@ void reconfigureExperiment() throws Exception { " failed to connect to comm"); } display.setContextLocations(context_list); + + if ((behavior_comm != null) && (context_list.getComm() == behavior_comm)) { + unset_contexts.add(context_list.getId()); + } } for (ContextList context : this.contexts) { @@ -1670,10 +1691,19 @@ protected void updateBehavior(float time) { String action = sensorJson.getString("action", "stop"); if (action.equals("start")) { display.setSensorState(sensor_pin, 1); - sensor_counts.put(sensor_pin, - sensor_counts.get(sensor_pin) + 1); + if (sensor_counts.containsKey(sensor_pin)) { + sensor_counts.put(sensor_pin, + sensor_counts.get(sensor_pin) + 1); + } + if (sensor_pin == lickport_pin) { + display.addLick(started); + lick_count++; + } } else if (action.equals("stop")) { display.setSensorState(sensor_pin, -1); + if (sensor_pin == lickport_pin) { + display.lickStop(); + } } else if (action.equals("created")) { sensor_counts.put(sensor_pin, 0); display.setSensorState(sensor_pin, -1); @@ -1712,17 +1742,15 @@ protected void updateBehavior(float time) { if (!context_json.isNull("id")) { String context_id = context_json.getString("id"); if (!context_json.isNull("action")) { + String action = context_json.getString("action"); for (int j=0; j < contexts.size(); j++) { if (contexts.get(j).getId().equals(context_id)) { - if (context_json.getString("action").equals( - "start")) { - + if (action.equals("start")) { contexts.get(j).setStatus("started"); - } else if ( - context_json.getString("action").equals( - "stop")) { - + } else if (action.equals("stop")) { contexts.get(j).setStatus("stopped"); + } else if (action.equals("created")) { + unset_contexts.remove(context_id); } break; diff --git a/src/UdpClient.java b/src/UdpClient.java index cca1c9a..029b892 100755 --- a/src/UdpClient.java +++ b/src/UdpClient.java @@ -29,6 +29,8 @@ class UdpClient extends PApplet { */ ReceiveThread rt; + SendThread st; + /** * ? */ @@ -71,6 +73,7 @@ public UdpClient(int arduinoPort, int receivePort, String id) throws IOException mL = new FileWriter("logs/" + ip + "." + receivePort + ".log"); rt = new ReceiveThread(udpSocket, receivePort, this.mL); rt.start(); + this.st = new SendThread(udpSocket, arduinoAddress, this.mL); } /** @@ -103,6 +106,7 @@ public UdpClient(String ip, int arduinoPort, int receivePort, String id) throws mL = new FileWriter("logs/" + ip + "." + receivePort + ".log"); rt = new ReceiveThread(udpSocket, receivePort, this.mL); rt.start(); + this.st = new SendThread(udpSocket, arduinoAddress, this.mL); } /** @@ -114,7 +118,7 @@ public UdpClient(String ip, int arduinoPort, int receivePort, String id) throws * @throws IOException */ public UdpClient(String ip, int arduinoPort, String id) throws IOException { - arduinoAddress = new InetSocketAddress(ip,arduinoPort); + arduinoAddress = new InetSocketAddress(ip, arduinoPort); this.address = ip; this.status = true; @@ -125,6 +129,8 @@ public UdpClient(String ip, int arduinoPort, String id) throws IOException { this.status = false; throw new IOException("error connecting to " + this.address); } + + this.st = new SendThread(udpSocket, arduinoAddress, this.mL); } public String getId() { @@ -145,18 +151,8 @@ public void setStatus(boolean status) { * @param message ? */ void sendMessage(String message) { - message = message.replaceAll("[\r|\n|\\s]", ""); - - try { - this.mL.write("[SEND] " + message); - byte[] sendData = message.getBytes("UTF-8"); - DatagramPacket sendPacket = new DatagramPacket(sendData, 0, - sendData.length, arduinoAddress); - udpSocket.send(sendPacket); - } catch (IOException e) { - println("error sending to " + this.address + ": " + message); - println(e); - } + message = message.replaceAll("[\r|\n|\\s]", ""); + this.st.queue_message(message); } /** @@ -182,6 +178,96 @@ public boolean receiveMessage(JSONBuffer json) { return false; } + /** + * ? + */ + public class SendThread extends Thread { + private Thread t; + /** + * ? + */ + private DatagramSocket sock; + /** + * ? + */ + private ConcurrentLinkedQueue sendQueue; + //private byte[] receiveData; + /** + * ? + */ + private boolean run; + private boolean debug; + private SocketAddress sendAddr; + /** + * ? + */ + private FileWriter mL; + + /** + * ? + * + * @param sock ? + * @param receivePort ? + * @param mL ? + */ + SendThread(DatagramSocket sock, SocketAddress address, FileWriter mL) { + this.run = false; + this.debug = false; + this.mL = mL; + this.sendAddr = address; + this.sock = sock; + this.sendQueue = new ConcurrentLinkedQueue(); + } + + public void queue_message(String message) { + sendQueue.add(message); + if (!this.run) { + this.run = true; + start(); + } + } + + public void run() { + while (this.run) { + int count = 0; + String message = this.sendQueue.poll(); + while (message != null) { + try { + this.mL.write("[SEND] " + message); + + byte[] sendData = message.getBytes("UTF-8"); + DatagramPacket sendPacket = new DatagramPacket(sendData, 0, + sendData.length, this.sendAddr); + this.sock.send(sendPacket); + } catch (IOException e) { + println("error sending to " + this.sendAddr + ": " + message); + println(e); + } + count++; + if (count > 5) { + try { + Thread.sleep(4); + } catch (InterruptedException e) {System.out.println("Exception"); } + } + message = sendQueue.poll(); + } + } + } + + public void start() { + if (t == null) { + t = new Thread (this, "name " + System.nanoTime()); + t.start(); + } + } + + public void stop_thread() { + this.run = false; + this.t = null; + } + } + + /** * ? */ @@ -281,6 +367,7 @@ void flushBuffer() { void closeSocket() { if (rt != null) { rt.stop_thread(); + st.stop_thread(); } else { udpSocket.close(); }