private List <SMParameterValue> changeBoundaries(int exptID, int defID, RatControlDataContext db) { int?FirstRCEID = null; int?LastRCEID = null; db.GetFirstRCE(exptID, defID, ref FirstRCEID); db.GetLastRCE(exptID, defID, ref LastRCEID); if (FirstRCEID == null || LastRCEID == null) { Trace.WriteLine("RCEIDs are null"); } else { var Features = db.ExecuteQuery <double?>(@"SELECT Details.value('(//SetRewardPluginDetails/@Feature)[1]', 'float') AS A1 FROM RatControlEvents WHERE ExptID = {0} AND RatEventsID >= {1} AND RatEventsID <= {2} AND Details.value('(//SetRewardPluginDetails/@RandOn)[1]', 'bit') = 0 AND EventType = 9 ORDER BY A1 DESC", exptID.ToString(), FirstRCEID.ToString(), LastRCEID.ToString()).ToArray(); var Completed = db.ExecuteQuery <int?>(@"SELECT Details.value('(//SetRewardPluginDetails/@Completed)[1]', 'int') AS A1 FROM RatControlEvents WHERE ExptID = {0} AND RatEventsID >= {1} AND RatEventsID <= {2} AND Details.value('(//SetRewardPluginDetails/@RandOn)[1]', 'bit') = 0 AND EventType = 9 ORDER BY A1 DESC", exptID.ToString(), FirstRCEID.ToString(), LastRCEID.ToString()).ToArray(); int nevents = Features.Count(); int n = 0; for (int i = 0; i < nevents; i++) { if ((Features[i] != null) & (Completed[i] == 1)) { n++; } } // Convert angles into distance from target angle Double[] Dists = new double[n]; n = 0; for (int i = 0; i < nevents; i++) { if ((Features[i] != null) & (Completed[i] == 1)) { Dists[n] = Math.Abs(T - (double)Features[i]); n++; } } // Sort the distances from closest to farthest Array.Sort(Dists); // Find the distance of the 35% farthest one int psampnum = (int)Math.Round(n * pTarget / 100); var w = Dists[psampnum]; LB = T - w; UB = T + w; } List <SMParameterValue> newParams = updateSMParams(); return(newParams); }
private void jumpTarget(int exptID, int defID, RatControlDataContext db) { int?FirstRCEID = null; int?LastRCEID = null; db.GetFirstRCE(exptID, defID, ref FirstRCEID); db.GetLastRCE(exptID, defID, ref LastRCEID); if (FirstRCEID == null || LastRCEID == null) { Trace.WriteLine("RCEIDs are null"); } else { double upperEdge = TargetEdgeDist; double lowerEdge = -TargetEdgeDist; double prevT = T; // Record previous target location before updating it. double bound1 = lowerEdge; // Bounds of available intervals double bound2 = prevT - MinJumpDist; double bound3 = prevT + MinJumpDist; double bound4 = upperEdge; double intvLen1 = 0; // Length of lower available interval made up by bound1 to bound2 double intvLen2 = 0; // Length of upper available interval made up by bound3 to bound4 // Keep interval length as zero if target is too close to the edge if (bound2 > bound1) { // previous target is very close to the upper edge intvLen1 = bound2 - bound1; } if (bound4 > bound3) { // previous target is very close to the lower edge intvLen2 = bound4 - bound3; } // Pick a random location within the two intervals Random random = new Random(); double randomTargetLoc = random.NextDouble() * (intvLen1 + intvLen2); if (randomTargetLoc > intvLen1) { // previous target is very close to the upper edge T = bound3 + randomTargetLoc - intvLen1; } else { // previous target is very close to the lower edge T = bound1 + randomTargetLoc; } } }
private Status evaluatePerformance(int exptID, int defID, RatControlDataContext db) { int?FirstRCEID = null; int?LastRCEID = null; db.GetFirstRCE(exptID, defID, ref FirstRCEID); db.GetLastRCE(exptID, defID, ref LastRCEID); int numOfRewardedTrials; double percentRewarded; // number of trials in previous session int[] query1 = db.ExecuteQuery <int>(@"SELECT RatEventsID AS param6 FROM RatControlEvents WHERE ExptID = {0} AND RatEventsID >= {1} AND RatEventsID <= {2} AND Details.value('(//SetRewardPluginDetails/@RandOn)[1]', 'bit') = 0", ExptID.ToString(), FirstRCEID.ToString(), LastRCEID.ToString()).ToArray(); int numOfTrials = query1.Count(); // int numOfTrials = ScriptHelper.CountNumEntries(exptID, JSPressState, defID, JSPressSubFSM, db); Trace.WriteLine("Number of Trials: " + numOfTrials); // Evaluate number of trials and percentage if (numOfTrials < MinNumOfTrials) { return(Status.Good); Trace.WriteLine("Too Few Trials"); } else { int[] query2 = db.ExecuteQuery <int>(@"SELECT RatEventsID AS param6 FROM RatControlEvents WHERE ExptID = {0} AND RatEventsID >= {1} AND RatEventsID <= {2} AND Details.value('(//SetRewardPluginDetails/@RandOn)[1]', 'bit') = 0 AND Details.value('(//SetRewardPluginDetails/@Reward)[1]', 'int') > 0", ExptID.ToString(), FirstRCEID.ToString(), LastRCEID.ToString()).ToArray(); numOfRewardedTrials = query2.Count(); // numOfRewardedTrials = ScriptHelper.CountNumEntries(exptID, RewardState, defID, RewardSubFSM, db); percentRewarded = (double)numOfRewardedTrials / (double)numOfTrials * 100; Trace.WriteLine("Percentage Rewarded: " + percentRewarded + "%"); if (percentRewarded < MinRewarded) { return(Status.Hard); } else if (percentRewarded > MaxRewarded) { return(Status.Easy); } else { return(Status.Good); } } }
public override SMCompletionStatus IsComplete(out List <SMParameterValue> newParams) { Status status = Status.Good; newParams = null; if (!SMStarted) { using (RatControlDataContext db = new RatControlDataContext()) { int exptIDEval = ExptID; // exptID used for evaluating performance int defIDEval = 0; // defID used for evaluating performance // First check to see if there was a previous session in this experiment var defIDs = ScriptHelper.GetStageDefIDs(ExptID, null, false, db); if ((defIDs.Count() > 0) & Shaping) { int DefID = defIDs.Max(); exptIDEval = ExptID; defIDEval = DefID; status = evaluatePerformance(exptIDEval, defIDEval, db); } else { newParams = useScriptParameters(); // use script parameters } //////////// Random Reward Code //////////// int[] defidcount = db.ExecuteQuery <int>(@"SELECT COUNT(Definition.value('(//@TrialBlock)[1]', 'int')) AS param6 FROM StateMachines WHERE ExptID = {0} AND Type = 4 AND Definition.value('(//@NormalTrials)[1]', 'int') > 0", ExptID.ToString()).ToArray(); // Retrieve old script parameters if (defidcount[0] > 0) { // Recover block parameters passed from previous session var sql = db.ExecuteQuery <Parameter>(@"SELECT Definition.value('(//@TrialBlock)[1]', 'int') AS param6, Definition.value('(//@Order0)[1]', 'int') AS param7, Definition.value('(//@Order1)[1]', 'int') AS param8, Definition.value('(//@Order2)[1]', 'int') AS param9 FROM StateMachines WHERE ExptID = {0} AND Type = 4 AND Definition.value('(//@NormalTrials)[1]', 'int') > 0", ExptID.ToString()).ToArray(); int lindex = sql.Length - 1; // Current block number trblock = sql[lindex].param6; // These are the block numbers of the blocks that will have random reward blockorder[0] = sql[lindex].param7; blockorder[1] = sql[lindex].param8; blockorder[2] = sql[lindex].param9; } Random rnd = new Random(); // Initialize block numbers if (trblock == 0) { // initialize block order double[] tmpOrder = new double[numBlocks]; int[] tmpVals = new int[numBlocks]; // initialize block order for (int i = 0; i < numBlocks; i++) { tmpOrder[i] = rnd.NextDouble(); tmpVals[i] = i; } // Find the indices of the lowest 3. These will be the random reward blocks Array.Sort(tmpOrder, tmpVals); blockorder[0] = tmpVals[0]; blockorder[1] = tmpVals[1]; blockorder[2] = tmpVals[2]; string tmpString = "Block Sequence: "; for (int i = 0; i < 3; i++) { tmpString = tmpString + blockorder[i]; if (i < numBlocks - 1) { tmpString = tmpString + " "; } } Trace.WriteLine(tmpString); } // Add some randomness to the number of normal and prob trials: +- 10 NormTrials = defNormTrials + (int)Math.Round(2 * BlockJitter * rnd.NextDouble()) - BlockJitter; ProbTrials = defProbTrials + (int)Math.Round(2 * BlockJitter * rnd.NextDouble()) - BlockJitter; // Set reward probability, if the current block is one of the 3 reward blocks if (blockorder[0] == trblock) { RandomReward = true; RewardProb = RewardProb1 / 100; } else if (blockorder[1] == trblock) { RandomReward = true; RewardProb = RewardProb2 / 100; } else if (blockorder[2] == trblock) { RandomReward = true; RewardProb = RewardProb3 / 100; } else { RandomReward = false; RewardProb = -1; } Trace.WriteLine("Reward Probability = " + RewardProb); // Update trblock if (trblock == (numBlocks - 1)) { trblock = 0; } else { trblock++; } ////////////////////////////////// switch (status) { case Status.Good: Trace.WriteLine("Good"); if ((LB == 0) || (UB == 0)) { newParams = useScriptParameters(); } else { newParams = updateSMParams(); } break; case Status.Easy: if ((LB == 0) || (UB == 0)) { newParams = useScriptParameters(); } else { newParams = changeBoundaries(exptIDEval, defIDEval, db); if ((UB - LB) / 2 < BoundThreshJump) // check for jump { Trace.WriteLine("Jumping Target"); jumpTarget(exptIDEval, defIDEval, db); newParams = changeBoundaries(exptIDEval, defIDEval, db); } else // just easy { Trace.WriteLine("Too Easy"); } } break; case Status.Hard: Trace.WriteLine("Too Hard"); if ((LB == 0) || (UB == 0)) { newParams = useScriptParameters(); } else { newParams = changeBoundaries(exptIDEval, defIDEval, db); } break; default: newParams = updateSMParams(); break; } Trace.WriteLine("New Upper Bound = " + UB + ", New Lower Bound = " + LB + ", Target = " + T); SMStarted = true; return(SMCompletionStatus.SubStageComplete); } } else { return(SMCompletionStatus.Incomplete); } }