MonkeyCantab - version_tracker.txt ---------------------------- Version numbers are stored in: (1) MonkeyCantab.iss (influences setup display, Control Panel) (2) MonkeyCantab_Cambridge.iss (3) .rc file (About box) (4) const CString strMonkeyCantabConfigVersion (in MonkeyCantabControllerConfig.cpp) -- CONFIG VERSION ONLY (5) g_strVersion1 (in MonkeyCantab.h) (6) help file (MonkeyCantab.hm3) (7) web site whatsnew.shtml (8) Inside the database. Version history: 0.1 - 23 Mar 2003: RNC started. - 8 Apr 2003: distributed to Innes with SWM task. 0.2 - 8 Apr 2003 0.3 - 30 Apr 2003 (for details see .HM3 help file) - Note that MS Access 97's Long Integer data type (4 bytes) is -2,147,483,648 to +2,147,483,647. Today I've got a system clock that's about 2,400,365,269, so although the text-based output is perfect, the Access fields read approx. -1894624040 - what's worse, the latencies are wrong and negative. -- NOT SURE I UNDERSTAND WHY. Anyway, DWORD is a 32-bit unsigned integer; timeGetTime() returns a DWORD. So size is right except for sign bit. I'd be happy with the absolute times appearing negative in Access, as long as the latencies are OK! Access's Decimal type (see "Data Type Summary" in the Access help) would be big enough (14 bytes), but can't be used as a variable type. The best alternative, therefore, is double (double-precision floating point). Aha. Found it; CRecordSetPALPresentationResults::DoFieldExchange was using RFX_Bool for the latency, rather than RFX_Long, and the data type in the header was BOOL not long. Fixed. There was some strangeness with this table! Many "Can't open record"-type errors, not sure why. Perhaps this was why... - (6 May 2003) Caching... worked gloriously. No problems. Kudos to Mike. 0.4 - 7 May 2003 Changes at Camcog's request - claim two additional output lines; REINFORCEMENT_INFO and STIMULUS_INFO. - REINFORCEMENT_INFO gives a 10ms high pulse upon reward. - REINFORCEMENT_INFO gives a 20ms high pulse upon punishment. - STIMULUS_INFO is high when stimuli are being displayed in ID/ED and reversal learning tasks. - Option to enforce that an empty box be the last to be displayed in the sample phase of PAL. - 26 May 2003 Changes at Laurence's and/or Camcog's request - record explicitly the stimulus location sequence chosen in SWM - 4-way grid option for PAL with middle-top, middle-left, middle-bottom, middle-right (Taffe et al 2002) and "4-way grid (corners)" to use corners of 9-way grid, rather than 4-way grid. - Record all background touches for SWM - Option to use offset grid sets in all tasks (though grids themselves not yet implemented) - drop-down lists in (e.g.) brush style are the wrong type. Can type in things, shouldn't be able to. (Dropdown should have been drop list.) - PAL option to re-present same trial but in different sample/choice order (Taffe et al 2002) - VERSION RELEASED to Innes. 0.5 - 4 June 2003: changes to CheckForStopping() code in CSimpleSchedules given discovery of bug in SimpleSchedules application (q.v.) - fix to CReinforcementSchedule::Description() for PR schedules - secure client authentication - RFX_Text(pFX, _T("[ObjectList]"), m_ObjectList, MEMO_LENGTH); modification where MEMO fields are used, to avoid "Data truncated" (AFX_SQL_ERROR_DATA_TRUNCATED) exceptions. - Fixed a bug in CPAL::NewTrial, if (m_iStimulusSelectionTechnique == PAL_SST_RANDOM) {... if (m_vTrialRecord[i].m_vPresentations[k].m_strStimulusPresented == vstrAvailableStimuli[i]) { should have read if (m_vTrialRecord[j].m_vPresentations[k].m_strStimulusPresented == vstrAvailableStimuli[i]) { 14 July 2003 - Horizontal scroll fixed in list box; see http://www.codeguru.com/listbox/hscroll_lb.html and CHScrollListBox. - about button - Initial pause to allow for Advantechs having only one monitor (achieved by starting with a Link). - General parameters / tone-square-sine... / drop list rather than drop down - Moved to read-only edit boxes from static text for objects, schemes, etc. screenshots - PAL done y - DMTS was fine anyway n/a - ReinfFamil was fine anyway n/a - Reversals done y - SimpleSchedules done y - SpatialWM done y - ThreeChoice done y - TouchTraining was fine anyway n/a - VDP done y - VDS done y - MonkeyCantab params done - Incidentally, inability to switch off C4786 warning is a known bug in VC++. FIX: C4786 Warning Is Not Disabled with #pragma Warning Microsoft KB article 167355. - "Select visual object" dialogue allows you to choose predefined as well. - Stimulus generator for PAL (see e-mails), and option to use it In CamCog version: - it certainly seems to alter colours on the predefined stimuli - Mpal_SetupStimuli() - loads in set of stimuli from one file, into stim_data (global) - calls randomise_array() to shuffle their order - for each stimulus, chooses a random offset; offsets all quadrants' colour by this amount; MOD 8 to keep them valid; does this until NOT(all quadrants are white). (Spastic code - could just choose a random number that wasn't white, and set all quadrants to this.) Oh no, sorry; they're non-identical to start with... - For each trial, get_stim_data() - has static current_stim variable (begins at 0) - fetches n stimuli from stim_data[] into current_stim_data[] - if current_stim reaches maximum, increments colour for all four quadrants by 1 (MOD 8) for all stimuli - if that makes the colour 7 (white), make the top-left and bottom-left quadrants red. ... then reset current_stim to 0. So then it'll permanently cycle round with the left-hand side one colour more than the right-hand side. This means that for n stimuli, we see them all in 6n uniform colours (not black, not white); then we see them again in 6n L/R split colours. So we get 12n. No check when we pass that number. Largest PAL database is set 0 (69 stimuli); so potential for 828 PAL stimuli max per session. - Stimuli never shown unmodified. In my version: - n stimuli from set - 7^4 variants by altering quadrant colour (= 2401 variants) - chooses at random. Like CamCog's version, goes through all shapes before moving to a new colour variation. Works fine, except stupidly slow - taking >1s (or several?) to update stimuli. Reason: network comms, I fear. For a maximum 9 stimuli, 4 quadrants, 64 pixels/quadrant, 3 messages (create + 2 events) per pixel, we have 6912 messages. Each is (e.g.) 50 chars; that's 345k of text. Argh. Here's some profiling: note the time spent in socket comms... Func Func+Child Hit Time % Time % Count Function --------------------------------------------------------- 145260.394 47.2 145270.603 47.3 3 CWnd::MessageBoxA(char const *,char const *,unsigned int) (mfc42d.dll) 78049.255 25.4 306936.277 99.8 17516 CWinThread::PumpMessage(void) (mfc42d.dll) 55674.471 18.1 55688.370 18.1 1 CFileDialog::DoModal(void) (mfc42d.dll) 9792.802 3.2 9792.802 3.2 16784 CSocket::Send(void const *,int,int) (mfcn42d.dll) 1159.937 0.4 1161.170 0.4 227 CSocket::PumpMessages(unsigned int) (mfcn42d.dll) 468.505 0.2 494.103 0.2 184 CRecordset::Move(long,unsigned short) (mfcd42d.dll) 445.063 0.1 960.860 0.3 265807 FindNode::operator()(class XML_Node const &) (displayattribute_brush.obj) 430.774 0.1 1591.398 0.5 16785 CSocket::Receive(void *,int,int) (mfcn42d.dll) One option: create a "CamcogPatternStimulus" type on the server. Probably the best. Yup, that worked well. - Stimulus generator for DMTS (see Camcog e-mails), and option to use it - DMTS - if (settings.stim_direct) norm_initialise_mdms(&nd); ... pattern_load(stm_src /*filename*/, stm); else if (settings.paired_stimuli) pair_initialise_mdms(filename,&pd); ... pattern_load(stimpath, &pd->stimdata); ... pd->stim_pairs = pd->stimdata.num/2; ... pd->stim_order[trials]=trials; else quad_initialise_mdms(filename,&qd); ... pattern_load(stimpath,&qd->stimdata); ... qd->stimdata.num... Options from the menu: My interpretation: Q1. Take stimuli direct from file (STIMULUS_DIRECT), or jumble quadrant shapes? They use v. complicated ways of jumbling the shapes. We want about 500,000 trials, so 2m stimuli. About 400 stimuli/set. So colour variation could only give us 1m stimuli. If we treated quadrants as fully independent (they aren't), we'd have 16 quadrants per 4 stimuli, and 16! = 20,922,789,888,000 ways of arranging them; x2400 = 20922789888000 = 50,214,695,731,200,000 = 50 trillion. [How many stimuli are in theory possible? 256 pixels, 8 colours... 8^256 = 1.5e231...) Stimuli do repeat partially, e.g. lots of "square" quadrants in DMTS set 0. But I don't think they repeat in the same position within a group of four stimuli. So a reasonable compromise is: - take 4 consecutive stimuli from the set. - variant level 1: top left quadrant for stimulus {1,2,3,4} is from original stimulus {1,2,3,4}. but top right is {1,2,3,4}...{2,3,4,1}...{3,4,1,2}, {4,1,2,3}... and bottom left is {1,2,3,4}...{2,3,4,1}...{3,4,1,2}, {4,1,2,3}... and bottom right is {1,2,3,4}...{2,3,4,1}...{3,4,1,2}, {4,1,2,3}... giving 4x4x4 = 64 variants. Why this pattern? To make sure that all stimuli are different, as long as no two corresponding quadrants are the same in any four consecutive stimuli. So AB CD EF GH IJ KL MN OP becomes AD CF EH GB on the first shuffle... IJ KL MN OP An alternative way would be to shuffle the quadrants within each stimulus, but that gives rather self-similar combinations) - variant level 2: colour (7^4 = 2401 variants) That gives us 153,664 variants or 61,465,600 stimuli from an original set of 400. Q2. Fiddle with colour: MULTICOLOURED: each quadrant has a different colour. (uses 2-4 stimuli per trial) 7^4 = 2401 colour variants Otherwise, a given stimulus has only one colour... MONOCHROME SHAPEDISCRIMINATION: distractor(s) have the same colour as the target, but different shape (uses two stimuli per trial) 7 colour variations MONOCHROME COLOURDISCRIMINATION: distractor(s) have the same shape as the target, but different colour (uses one stimulus per trial) 1 colour variation (w'd need 8 colours for 2 unique sets of colours) MONOCHROME MIXED: distractor 1 has different shape/colour to target; distractor 2 has different colour, same shape; distractor 3 has incorrect shape, correct colour (uses two stimuli per trial) 3 colour variations Q3. Stimulus set? 0, 5, 6, 7. (0 are harder, apparently, in that "one quadrant [of each pair?] is always the same in both shape and colour"; the Camcog task only allows MULTICOLOURED mode for stimulus set 0, the "paired" stimuli.) I think that's nonsense; it's set 5 that's hard(++). Even then quadrants not identical... Their manipulation functions: - Mdms_CompleteRandomisedStim() - if monochrome, does Mdms_MakeMonochrome(); else(nearly), does Mdms_MakeVariants() - Mdms_MakeMonochrome() - if settings.monochrome_mode = MDMS_MC_MIXED, { Mdms_HomogeniseStimuli(); if (max>2) Mdms_MakeVariants(); } - MDMS_MC_DIFFSHAPE: Mdms_SameColourDiffShape(stimuli, max); - MDMS_MC_DIFFCOLOUR: Mdms_DiffColourSameShape(stimuli, max) - Mdms_SameColourDiffShape() - for a set number of stimuli, make them all the same (random) colour - Mdms_DiffColourSameShape() - for a set (small!?) number of stimuli, make them all the same shape (the shape of the first one) but different colours - Mdms_HomogeniseStimuli() - for a set (small!?) number of stimuli, make them all monochrome by setting them to the colour of their top-left quadrant; but each stimulus a different colour - Mdms_MakeVariants() - takes two stimuli (+/-); generates two other distractors with (a) incorrect colour, correct shape; (b) incorrect shape, correct colour "Colour" is the colour map of all four quadrants. These all use randomise(7)+1, i.e. they allow white. - When running, - Mdms_RunTests()... pattern_item_t stimuli[4]; if (settings.stim_direct) norm_get_stim (nd, stimuli); ... copies stimuli in ... stimused = (settings.monochrome_mode==MDMS_MC_DIFFCOLOUR) ?1 :(settings.monochrome_mode==MDMS_MC_MIXED) ?2 :(settings.choice_patterns>2) ?4 :2; /* MDMS_MC_DIFFSHAPE */ ... bug (doesn't do anything) in stimulus cycling code? else if (settings.paired_stimuli) pair_get_stim (pd, trial, stimuli); ... complicated... ### else quad_get_stim (qd, trial, stimuli); ... complicated... ### - Mdms_SingleTest() called with current_stim set up to contain chosen stimuli - Checked for a good match to Camcog version: PAL ID/ED DMTS, except - theirs offers simultaneous stimulus presentation (so three things are on the screen). I offer zero delay, which I prefer. - their correction procedure repeats the trial until they get it right... 5-choice - pretty much; didn't implement their training scheme (it was just a simple version of this task; you can use mine to train, I'd have thought) - don't have the radial star graphic (but you can see the locations). - can't see locations before you've centred (I prefer the look of it this way) Schedules Reinforcement familiarization SWM Touch Training (v2) ----------------------------------------------- BUG IN random_shuffle() Posted to http://c2.com/cgi/wiki?LinearShuffle This may be implementation-specific, but I believe there is a bug in the STL implementation of random_shuffle of Microsoft Visual C++ 6. The implementation of supplied with VC++6 (dated 1995) has this: // TEMPLATE FUNCTION random_shuffle template inline void random_shuffle(_RI _F, _RI _L) {if (_F != _L) _Random_shuffle(_F, _L, _Dist_type(_F)); } template inline void _Random_shuffle(_RI _F, _RI _L, _Pd *) {const int _RBITS = 15; const int _RMAX = (1U << _RBITS) - 1; _RI _X = _F; for (_Pd _D = 1; ++_X != _L; ++_D) {unsigned long _Rm = _RMAX; unsigned long _Rn = rand() & _RMAX; for (; _Rm < _D && _Rm != ~0UL; _Rm = _Rm << _RBITS | _RMAX) _Rn = _Rn << _RBITS | _RMAX; iter_swap(_X, _F + _Pd(_Rn % _D)); }} template inline void random_shuffle(_RI _F, _RI _L, _Pf& _R) {if (_F != _L) _Random_shuffle(_F, _L, _R, _Dist_type(_F)); } template inline void _Random_shuffle(_RI _F, _RI _L, _Pf& _R, _Pd *) {_RI _X = _F; for (_Pd _D = 1; ++_X != _L; ++_D) iter_swap(_X, _F + _Pd(_R(_D))); } There are two random_shuffle function definitions, with and and without the option to supply your own random-number generator). If this code is tidied up to be legible, it reads: // TEMPLATE FUNCTION random_shuffle template inline void random_shuffle(_RandomAccessIterator _First, _RandomAccessIterator _Last) { if (_First != _Last) _Random_shuffle(_First, _Last, _Dist_type(_First)); } template inline void _Random_shuffle(_RandomAccessIterator _First, _RandomAccessIterator _Last, _Predicate *) { const int _RBITS = 15; const int _RMAX = (1U << _RBITS) - 1; _RandomAccessIterator _X = _First; for (_Predicate _D = 1; ++_X != _Last; ++_D) { unsigned long _Rm = _RMAX; unsigned long _RandomNumber = rand() & _RMAX; for (; _Rm < _D && _Rm != ~0UL; _Rm = _Rm << _RBITS | _RMAX) _RandomNumber = _RandomNumber << _RBITS | _RMAX; iter_swap(_X, _First + _Predicate(_RandomNumber % _D)); } } template inline void random_shuffle(_RandomAccessIterator _First, _RandomAccessIterator _Last, _PredicateFunction& _R) { if (_First != _Last) _Random_shuffle(_First, _Last, _R, _Dist_type(_First)); } template inline void _Random_shuffle(_RandomAccessIterator _First, _RandomAccessIterator _Last, _PredicateFunction& _R, _Predicate *) { _RandomAccessIterator _X = _First; for (_Predicate _D = 1; ++_X != _Last; ++_D) iter_swap(_X, _First + _Predicate(_R(_D))); } I believe this iterates too few times. For example, if you take a vector {1,2} and call random_shuffle(vector.begin(), vector.end()), then you *always* obtain {2,1}. If you shuffle {1,2,3}, you obtain {3,1,2} or {2,3,1} only, and so forth. To implement Don Dodson's algorithm (http://c2.com/cgi/wiki?LinearShuffle), the following seems to give better results: // TEMPLATE FUNCTION better_random_shuffle template inline void better_random_shuffle(_RandomAccessIterator _First, _RandomAccessIterator _Last) { if (_First != _Last) _better_Random_shuffle(_First, _Last, std::_Dist_type(_First)); } template inline void _better_Random_shuffle(_RandomAccessIterator _First, _RandomAccessIterator _Last, _Predicate *) { const int _RBITS = 15; const int _RMAX = (1U << _RBITS) - 1; _RandomAccessIterator _X = _First; _Predicate _N = _Last - _First; for (_Predicate _D = 0; _X != _Last; ++_D, ++_X) { unsigned long _Rm = _RMAX; unsigned long _RandomNumber = rand() & _RMAX; for (; _Rm < _D && _Rm != ~0UL; _Rm = _Rm << _RBITS | _RMAX) _RandomNumber = _RandomNumber << _RBITS | _RMAX; std::iter_swap(_X, _X + _Predicate(_RandomNumber % (_N - _D))); } } template inline void better_random_shuffle(_RandomAccessIterator _First, _RandomAccessIterator _Last, _PredicateFunction& _R) { if (_First != _Last) _better_Random_shuffle(_First, _Last, _R, std::_Dist_type(_First)); } template inline void _better_Random_shuffle(_RandomAccessIterator _First, _RandomAccessIterator _Last, _PredicateFunction& _R, _Predicate *) { _RandomAccessIterator _X = _First; _Predicate _N = _Last - _First; for (_Predicate _D = 0; _X != _Last; ++_D, ++_X) std::iter_swap(_X, _X + _Predicate(_R((_N - _D)))); } The code adds a few "std::" namespace handles (but could be written with a "using namespace" call instead). Rudolf Cardinal (rudolf@pobox.com), 29 July 2003. ----------------------------------------------- Note also an original STL implementation: http://www.sgi.com/tech/stl/stl_algo.h // random_shuffle template inline void random_shuffle(_RandomAccessIter __first, _RandomAccessIter __last) { __STL_REQUIRES(_RandomAccessIter, _Mutable_RandomAccessIterator); if (__first == __last) return; for (_RandomAccessIter __i = __first + 1; __i != __last; ++__i) iter_swap(__i, __first + __random_number((__i - __first) + 1)); } template void random_shuffle(_RandomAccessIter __first, _RandomAccessIter __last, _RandomNumberGenerator& __rand) { __STL_REQUIRES(_RandomAccessIter, _Mutable_RandomAccessIterator); if (__first == __last) return; for (_RandomAccessIter __i = __first + 1; __i != __last; ++__i) iter_swap(__i, __first + __rand((__i - __first) + 1)); } ... which is much the same as mine (not quite... loop 1-n not 0-n, +1 offset on swap...). ... looks like theirs disallows swapping-with-yourself, while mine allows it... ... anyway, it's different from Microsoft's. SUMMARY OF ALGORITHM: iterate through whole list swap each item with itself or a later one (chosen at random) ======================================================================================= ======================================================================================= ======================================================================================= 30 July 2003; done. - bugfix: StartMainSchedule() not always called in ReinfFamil. - bugfix in PAL.cpp: for (int k=0; k < m_vTrialRecord[j].m_vPresentations.size(); ++k) { (previously, [j] was [i]) - another bugfix in PAL.cpp: bJustErasedSomething code (prevents cock-up when i is invalidated) - ditto in DMTS.cpp - bugfix in simple schedules: fingeron code for when we're *not* visually marking responses - altered two-way grid so it's 5% at the edges, not 10%. Still 10% between the two stimuli. - logical error fixed re "Vanishing time must be greater than visual marker time" 22 Nov 2003 - writes version number and compilation date to summary file 19 Dec 2003 - for Chris Pryce (request received 17 Dec 2003) Subject: RE: FW: Monkey CANTAB From: "Pryce, Christopher Robert" To: "Rudolf Cardinal" Cc: "Mike Aitken" Dear Rudolf Many thanks for your mail. The situation is as follows: what we cannot do with the new system is re-create the sample and choice situation of the PAL test that we have been using with the DOS system. With the DOS system, when we set the following, number of locations = 2, number of patterns = 2, choice presentations where novel location used = 2 then we have a situation where if stimulus 1 is in corner A then stimulus 2 can be in corner B, C or D. Imagine that stimulus 2 is in corner B, then the distractor corner for stimulus 1 can only be C or D. Imagine that the distractor corner for stimulus 1 is C, then the distractor corner for stimulus 2 can only be D. That is, there is no overlap of sample or distractor locations for stimuli 1 and 2. Also, which stimulus, 1 or 2, is used first at the choice stage is randomly determined. We see this is a double, concurrent delayed match to position task. The marmoset can do it, and probably because it does not have to discriminate between stimuli, but only location of "a stimulus", on the basis of a 1-trial exposure. I think it was "by chance" that when we started using the DOS PAL test with the marmoset, it was possible to set the test up this way using the above settings. Your new version seems much more logical and flexible, but it does not allow us to do the above. ... The test we have been using with DOS is described in the proof I sent yesterday, if you need more information (the figure in the paper might make it a bit clearer). [ = Spinelli et al., Cognitive Brain Reseach 2003, in press] - Let's call it version 0.6 now, as something built v0.5. - Bugfix: copy constructor in MonkeyCantabControllerConfig didn't deal with m_bValidConfigVersion, and ReadXMLDefinition didn't either, so in *release* version it always thought it was loading the wrong version. It now announces which version it's got if it finds something unexpected. - Config version changed to 0.6. ========================= is now v0.6: released to Camcog ========================= ========================= v0.7 ========================= - New stimulus set for Merck, Sharpe, Dome (MSD) - Spencer Tye is contact. Julie requests new stimulus set consisting of the first 18 stimuli of the current PAL stimulus set 0. Call it PAL set 5. New config version (0.8). - Note that all the selection dialogue boxes need changing. Information that populates drop-down lists is stored in the .APS file, which is binary (MonkeyCantab.aps), not in the .rc file. Which is a pain, because you can't search for strings easily in it. Anyway, relevant dialogues for stimulus sets are: IDD_CHOOSE_PREDEFINED_OBJECT / IDC_CCHOOSEPREDEF_SET IDD_PAL_PARAMS / IDC_CPAL_STIMULUSSET IDD_DMTS_PARAMS / IDC_CDMTS_STIMULUSSET Current list (order MUST match enumPredefinedStimulusSets in PredefinedObjects.h): univcam_IDED_shape univcam_IDED_line camcog_pal0 camcog_pal1 camcog_pal2 camcog_pal3 camcog_pal4 camcog_mdms0 camcog_mdms5 camcog_mdms6 camcog_mdms7 camcog_star0 camcog_star1 camcog_star2 camcog_star3 camcog_star4 camcog_nedi0shape camcog_nedi0line camcog_nedi1shape camcog_nedi1line camcog_nedi2shape camcog_nedi2line camcog_nedi3shape camcog_nedi3line camcog_nedi4shape camcog_nedi4line camcog_nedi5shape camcog_nedi5line camcog_nedi6shape camcog_nedi6line camcog_nedi7shape camcog_nedi7line camcog_nedi8shape camcog_nedi8line camcog_pal5 ========================= v0.8 ========================= - further fix to ensure all stimuli visible from all menus; released to Camcog ========================= v0.9 (March 2004) ========================= - improvements to help - DMTS delays are in seconds (made clearer) - SimpleSchedules bug affecting PR schedule param entry: "int m_fParam3" should have been "float..." - PROGRATIO_DOUBLEINCREMENT schedule - PR schedules can end based on time since last response, not reward - bugfix: couldn't edit first point in a polygon list - change in method of centring stimuli. Up to now, has calculated object extent by calculating distance from (0,0) to maximum positive coordinate, halving that, and taking that point as the centre. That means the effect of adding positive and negative offsets is asymmetric at times (when coords go negative). It did allow arbitrary offsets, however. The alternative is to calculate object extent properly, and use its centre. That would mean that arbitrary offsets would be ignored (add 100 to all the coordinates and the program just recentres on the new centre), so offsets would have to be accomplished by adding an invisible background object. But it's a lot easier to explain, and perhaps that's the most important thing. Centring is what people really want, I suspect. And that method means that when people want to shift multi-component stimuli, they can just shift the background rather than having to alter each of the components. OK; let's do it. - Database error: "DMTS_Results... String data, right truncated (null)" error fixed by enlarging Phase1Stimulus and Phase2Stimuli text fields in DMTS from 50 to 255 characters. - store overall session length (end time) in database as well as in text-based results (MonkeyCantab_GeneralConfig.StartedAt and .FinishedAt) - SWM: record trial end time (so trial length can be calculated) - SWM: add latency to first lick in each trial - SWM: add total number of licks per trial - SWM: time at licker per trial - SWM: correction procedure (req. LDA): if subject gets a trial wrong, repeat trial until correct (up to a specified maximum number of repeats). Count each repetition towards the total maximum number of trials. - PAL_GRID_FOUR_CORNERS_EXTREME and PAL_GRID_FOUR_EDGES_EXTREME added to bring stimuli closer to the edge of the screen (req. Spencer Tye, Merck). ========================= v0.91 (May 2004) ========================= - Volume selection shouldn't be greyed out when WAV files are used - it still applies. Change help text and screenshot too. Done. - PAL stimulus order to match info provided by Camcog/Merck. Desired order: 18 (4 +) 04 (T) 08 (Rectangle Chequer) 09 (Two one diamond) 14 (-) 13 ( Arrow over rectangle) 17 ( Windmill) 16 ( Rectangle grid) 05 (Triangle) 06 (Rectangle maze) 15 (Chinese) 03 (Factory) 11 (Circle) 01 (+) 07 (Open Rectangle) 02 (Rectangle-inverse X) 10 (Rectangle "Snake") 12 (5 dots) ========================= v0.92 (May 2004) ========================= - Problem with SWM (a.k.a. SOSS). All touches punished if there's no "delaying tactic" (such as replacing the target with a marker for a while). Problem is that objects have TouchMove events as well as TouchDown events. That's good becuase it means subjects can slide onto stimuli, but it's not good in that v. tiny waggling (as is inevitable) also triggers events. We want to distinguish "MoveOnto" from "MoveOn", I suppose... Suppose we could keep a flag indicating "last touch was on the background"... Achieved with m_bTouchingSomethingOtherThanBackground / m_iObjectBeingTouched. N.B. server crashed once during debugging - ?possible to overload and crash the server if every touch event (e.g. background-touchmove) generates a whole load of messages from the client? Failed to replicate... ========================= v0.93 (4 June 2004) ========================= - Visual discriminations (both): SD, SR, CD, CR... (After the CR stage new exemplars are introduced so we can ignore that.) At present I have SD = A1+A2-, SR = A1-A2+, CD = A1B1+A2B2- and A1B2+A2B1-, CR = A2B1+A1B2- and A2B2+A1B1-. Weed et al (1999 Cog Brain Res 8: 185) keep the same stimulus correct going from SR to CD, i.e. SD A1+A2-, SR A1-A2+, CD A2B1+A1B2- and A2B2+A1B1-, CR A1B1+A2B2- and A1B2+A2B1-. Julie says the same's true of human CANTAB (same stimulus is correct going from SR to CD). The issue: that means that if you want an SR stage, you want your CD to be A2B1+A1B2- and A2B2+A1B1-, but if you don't want an SR stage, you want your CD stage to be A1B1+A2B2- and A1B2+A2B1- (and of course, the CR stage is simply the reverse of the CD stage). Apart from the dialogue boxes, all of the work is done in GetStimulusAssignments(). Of course, none of this is terribly important unless subjects progress to a new stage within a session (unusual for marmoset testing). - Visual discriminations (both): option to punish ITI touching by extending the ITI - Reversals: option to punish ITI touching by extending the ITI - DMTS: add "simultaneous" (SIM) task (Weed et al. 1999 Cog Brain Res 8: 185; Robbins et al. 1997 Psychopharm 134: 95). Code it as "delay < 0 => SIM, i.e. represent original stimulus in phase 2"? Seems easiest. (Actual delay between initial presentation and "simultaneous" test is zero.) But if the SIM option is used, must enforce that phase 1 locations can't be in phase 2 list. And in this task, touching the original stimulus is ignored (I presume). - SWM (req. LDA): We need a "probe trial" set. This is where an animal is on a single trial allowed to make a certain number of mistakes (perseverative responses to a box) before the trial is deemed incorrect and is terminated. The maximum number of mistakes allowed is the [ (number of boxes in a trial) x2 ]+1. 5 or 7 basically for 2 and 3 box trials. RNC Q: maximum numbers of errors per trial, or consecutive? e.g. if num errors are 3, and monkey does ABCBCBCBBB, does it fail on response 8 (the third persevative B) or response 10 (the third consecutive perseverative B)? LDA answer: we want maximum numbers of errors per trial, NOT consecutive errors. following the e.g. of responses of ABCBCBCBBB: with a max errors of 3, the trial would end following response 6. (for this example to make sense there would have to be 4 boxes present, ABC and D. sorry, should have made this clear - monkey can get the trial correct if done properly) ========================= v0.94 (25-29 June 2004) ========================= - 5-choice: option not to require a centring (Phase 1) response at all, to make it more of a continuous-performance (sustained attention) task. - 5-choice: option to require the subject to make the centring response *until* the target is displayed - 5-choice: option to ignore responses to target locations while the lever is pressed (while the observing response is being made) (m_bIgnoreResponsesDuringPhase1) - 5-choice: have some way (assuming centring responses are not being required) to make premature responses have no sensory consequences (req. Scott Baron @ Pfizer via Julie) - more specifically, "I would like the consequences of a premature response to be a resetting of the stimulus presentation delay." (SB) - 5-choice: ability to have distractor in a specified block of trials (e.g. trials 30-60) rather than p(distractor)=... - 5-choice: option to have target stimulus start long (0.6s) and decrease by (0.1 s) following (5) correct trials to a minimum of (0.1) s. - 5-choice: option to have delays within a min/max range, rather than from a list - 5-choice: ability to specify fixed number of trials with each stimulus-duration/delay-before-stimulus combination, rather than random [or other appropriate combinations] ========================= v0.95 (6 July 2004) ========================= - If config file is read-only (or some other error occurs on writing), pops up a warning. ========================= v0.96 (13 July 2004) ========================= - allow background colour to be other than black ========================= v0.97 (20 August 2004) ========================= - record *all* significant events from all tasks Options: (1) use server log facility, either with events only, or with all comms ... but would create thoroughly vast logs, what with all the graphics commands (2) have MonkeyCantab maintain the log, including things that it feels to be significant - from server: everything passing through CMonkeyCantabController::IncomingEvent - to server: all SwitchOn/SwitchOff/SetState commands - to server: summary of graphics displays (3) d/w MRFA: include significant stuff, but... - full log too big - fields as follows: TIME, EVENTTYPE (e.g. lick; touch on; touch off object touched; trial started; timer...), CAUSED_REINF, ... - as (e.g.) per SecondOrder - bug fixed: SimpleSchedules/ODBC writing didn't set a date/time variable to zero, so crashed in debug mode ========================= v0.98 (15 October 2004) ========================= - Bug fix, DMTS: first location recorded in tr.m_strPhase2Locations was the *index* of the location, not the location (discovered by Pfizer) - DMTS (for Pfizer): option to have no distractors in phase 2 (as a training task). Simply redefine DMTS_MINDISTRACTORS to 0 (and validation range in dialogue box). (Obviously, only applies to matching - must always have target + 1 distractor for nonmatching.) - DMTS correction procedure: fails if touchscreen used, because it doesn't (but should) wait for the finger to be removed before starting the correction phase. Instead, the previous touch just re-registers and the subject automatically fails the correction procedure. (Pfizer found this bug, 13-Oct-2004.) Fix: m_bFingerReleasedBeforeCorrection, m_bReadyToStartCorrectionWhenFingerReleased - Julie: "... another addition which needs to be made to the SOS/SWM task. In the Weed paper, they reward after every correct touch to make the task more difficult. Could you add this option to your program? They reward during the blanking period, so the reward option could be part of this." [Refers to Weed et al. 1999 Cog. Brain Res. 8:185, page 188 top right.] Implemented: m_bRewardEveryCorrectTouch - (Julie, MCSRTT) Hope all is well. I don't think your 'Ignore other responses during centring response' is working as it should. I am trying to use this to have any responses while the lever is pressed ignored, but to start with touches to the background are terminating the trial (though touches to the empty targets are ignored)... -- OK: if (!m_bIgnoreResponsesDuringPhase1 || m_iCentringResponseDevice==MULTIPLECHOICE_CENTRING_TOUCHSCREEN) { // 15-Oct-2004: was !=MULTIPLECHOICE_CENTRING_TOUCHSCREEN, should have been ==MULTIPLECHOICE_CENTRING_TOUCHSCREEN // ... m_objPhase1BackgroundObject.Display(m_pController); } ... and then once the stimulus appears touches are being treated as they would be if the lever had been released (correct rewarded, incorrect punished and background ignored). -- well, yes, that's what it's meant to do (once you've held on the lever for long enough for the target to appear, you can release the lever and touch the target or hold onto the lever and touch the target - although actually, once you've held the lever enough, the lever is *retracted*. I attach the config I am using. - (Julie, MCSRTT) There is also another difference from the DOS tests, which I think will need correcting. In the original and the human tests, the empty circles appear to signify the start of the trial (when you marker 1 sound is sounded). Once the lever is pressed there is no visual change, but the delay to stimulus presentation is then started as with your program. -- m_objPhase1PositionMarker0 etc. - DMTS stimulus changes? See e-mails... Upshot of request is this: ... they want to be able to ensure the incorrect stimuli are similar/dissimilar in specified ways (e.g. "shares one colour, no quadrant shapes", etc.) in the way that the DOS version did it. Implemented as DMTSCOLOUR_SEVENCOLOURSPERTRIAL. ========================= v0.99 (24 Oct - 13 Nov 2004) ========================= - 24 Oct 2004: ET_REV_OMISSION, ET_VD_OMISSION events - 24 Oct 2004: VDS/VDP, EDSHIFT stage: text instance of "B5A6(+)B6A6(-)" should have read "B5A6(+)B6A5(-)". No execution bug, just descriptive. - Database changed: MonkeyCantab_IndividualEvents.Box now long int, not byte (allows relationship from MonkeyCantab_GeneralConfig). CRecordSetIndividualEvents also changed. Tested with database still using BYTE format: works. - 4 Nov 2004: comma-delimited output for MCSRT misaligned (no comma between Phase1Given and Phase1Responded in header) ... spotted by Pfizer (Curt Christoffersen) - MCSRT params shrunk to fit an 800x600 screen (Curt Christoffersen, Pfizer) - DMTS was forcing to NINEGRID_MIDDLE_LEFT or NINEGRID_MIDDLE_RIGHT for Phase 1 if m_bAdjustForCentralFeeder was true, which wasn't the advertised behaviour - removed. Now behaves as advertised in the help (i.e. choose the Phase 1 locations yourself, and don't use central locations if you have a central feeder). To mimic previous behaviour closely, just enter those two locations manually (and use draw-without-replacement with multiplier of 1). Database boolean field of Phase1OnLeftIfCentralFeeder / "Only applicable if adjusting for a central feeder. Was the phase 1 stimulus on the left? If not, then it was on the right." also removed. But new database field of Phase1Location added. - Scott Baron (Pfizer) wants draw-without-replacement system for stimulus positioning in DMTS. Hasn't yet explained how he wants it to work when number of phase 2 presentations not known in advance (e.g. session limited by time not #trials, or subjects sometimes fail phase 1). Perhaps simplest solution is have these options: 1) choose location at random for each trial (draw with replacement) [implementation: vector of size n where n=number of possible locations; clear/populate vector afresh for each trial; choose at random] 2) draw without replacement [implementation: vector of size nx, where n=number of possible locations and x is specified by the user; clear vector at start; whenever vector is empty, populate with x copies each of n locations and shuffle vector; for each trial, draw without replacement; when vector empty, repopulate; try also to replace phase 2 location in vector if it ends up not being used] Helped by the fact that a location can't be used for both Phase 1 and Phase 2. Only one stimulus for Phase 1, so that's easy enough. Then consider what happens with multiple phase 2 stimuli... One possibility: the system described above is used to determine the location of the *correct* stimulus in phase 2, the others being chosen at random from the other possibles. That would be easy, and Pfizer's concerns re side bias are presumably primarily to do with the location of the correct stimulus. Otherwise, we'd have a slight difficulty: suppose the possible Phase 2 locations are {1,2,3}, and the multiplier is 2, so the initial vector is {1,2,3,1,2,3}. Suppose trial 1 draws {1,2}, leaving {3,1,2,3}. Suppose trial 2 also draws {1,2} - then we're left with {3,3}, which won't fly. A few possible solutions for this - but simplest is perhaps to make the *correct* stimulus location the thing that's drawn without replacement (venumAvailablePhase2TargetLocations). - Explicit Phase2TargetLocation field added to database. - in 3-choice task, premature hits is not counting accurately - dragging finger across target scores multiple hits (need to track when finger released, etc...) (Curt Christoffersen, Pfizer, who suspects the problem doesn't exist in the 1-choice version - ?) Solution: we don't want to register premature hits only when a finger starts to touch the screen, since we want to allow "sliding on" to stimuli. So we need to have a "touching stimulus" flag, set it when a stimulus is touched, and clear it when the stimulus is released, the background is touched, or the background is released. And allow new prematures only when this flag is false. Involved addition of m_objPhase2InitialPauseBackgroundObject, m_bFingerOnPrematureStimulus. - Were also a whole bunch of e.g. m_objPhase1PositionMarker0.Prepare( ... (m_bIgnoreResponsesDuringPhase1 ? strEvent : "") ... ... which were backwards. Fixed. - 15 Nov 2004: rnc_random_shuffle calls now use a different random number generator (insufficiently random before? Saw at least one duplicate set of DMTS locations over two runs, with ~8 identical binary choices and ~8 identical choices among four alternatives). Now uses Mersenne Twister. Seems fine. - THIS IS HOW TO DISABLE THE C4786 ERRORS: PUT THIS LINE EARLY IN THE HEADER FILES: #pragma warning(disable: 4786) // disable warning C4786 ("symbol greater than 255 characters") - OK to ignore ========================= v1.0 (17 Nov 2004) ========================= - more distractors in DMTS (up to 7) [Pfizer]. Note, however, that the stimulus generation process for DMTS often works in blocks of 4 stimuli, so the stimuli generated when <>4 total stimuli are used per trial is not guaranteed to follow the same rules as when 4 are used. - draw-without-replacement option for MCSRT target location [Pfizer] - record location of incorrect response in Phase 2/correction phase of DMTS (m_iPhase2ResponseLocation; m_iCorrectionResponseLocation) - note actually shipped with About file/internal version number at 0.99 by mistake. ========================= v1.1 (9 Dec 2004) ========================= - CDisplayComponent_Bitmap::GetBitmapSizeFromFile and thus improved CDisplayComponent_Bitmap::GetBottomRightPoint ... should improve bitmap positioning (if filenames are entered in such a way that both this program and the server can find the bitmap!) - ReinforcementFamiliarization (Merck) - "max no. reinfs" doesn't work with the lick-contingent FR1 option. Just no code to check the max. reinfs! Fixed. - Also bug in ReinforcementFamiliarization::IncomingEvent: "if (m_ePhase = RF_PHASE_MAINSCHEDULE)" should have been "==" (!). - ReinforcementFamiliarization (Merck) - background colour not set. Should create a document and call m_pController->SetBackgroundColour(). Done. - ThreeChoice (Pfizer) - The "max time to wait for response" is a fixed time regardless of the duration of the target signal. With multiple target signal durations during a session, this fixed time is a problem. Can the program be changed so that the "max time to wait for response" is equal to target signal duration + 2 sec.? - implement. Currently using m_fPhase2MaxResponseTimeSec. Critical line: m_pController->TimerSetEvent(strEvent_Phase2Omission, Seconds_ms(m_fPhase2MaxResponseTimeSec)); Just have a boolean: "maximum response time is absolute or time after stimulus has finished..." ... m_bPhase2MaxRespTimedFromEnd ... also m_bPhase2OmissionEventSet, to avoid clearing non-existent events (cosmetic) - ThreeChoice: bug: distractor *removed* a location from viNontargetLocations - so the final non-target pulled from an empty vector... ========================= v1.2 (26 Jan 2005) ========================= - DMTS (Pfizer): option to pick levels (delays) at random but without replacement from a list that is some multiple of the delay list (just as for the Phase 1 stimulus location and the Phase 2 stimulus location). If the list is emptied, it's then repopulated automatically, etc. - 5CSRT (Pfizer): option to pick pre-stimulus delay without replacement from the list, in the same way. - 5CSRT (Pfizer): option to pick stimulus duration without replacement from the list, in the same way. - dog version - - if CamCog sell a dog version, they may want an option to trigger trials upon a lever press, in all tasks. They'll let us know if they want this feature. We've agreed that such a modification would be about £100/h and that copyright would remain with us (i.e. CUTS) despite that. Primary coding: 26-Jan-2005, 1430 to 1615. Linking/docs: 28-Jan-2005, 0930 to 1100. Testing: 28-Jan-2005, 1130 to 1300. Total so far: 4.75h. - "4. We want to add an omnidirectional lever (it's usually an omni-switch with a plastic tube sticking up) to the apparatus, next to the reward tray. This should serve as the dog's response to the "trial ready" light, so the dog can initiate the start of each trial. Please let me know if this will be a programming problem, or if the system is already set up to handle this type of response. (I think the monkeys initiate, but I can't remember...)" She needs to have the Lever actuated for each trial on all tests including touch screen training. - Internally: GetLeverPressedEventString(), ExtendLever(), RetractLever(); Modified NewTrial() functions to call BeginTrialProperly() when appropriate. - Reinforcement familiarization ... lever ignored completely. - Simple schedules of reinforcement ... lever ignored completely. - MCSRT ... exactly as the present (monkey) lever. - correspondence of dog to monkey lever ... exactly the same (i.e. it's an on/off lever as far as the program is concerned and the program never needs to distinguish it from the lever used for the monkey tasks). - when a lever is required to start a trial: ... the houselight is on throughout a task and is not switched off during the ITI (unless the previous trial was failed and the punishment includes darkness) ... lever-activations are required to start each trial, rather than the task as a whole (correct?) ... the Marker 1 sound (where used), which presently often indicates the start of the trial, will indicate the opportunity to press a lever to start the trial ... when the lever is activated, the trial begins immediately ... if the lever is being held "on" when it's required, the program waits until it's released/activated again. - Touch training ... lever activation required to initiate trials. - spatial WM (SOSS) ... lever activation required to initiate trials. - PAL ... lever activation required to initiate trials. - DMTS ... lever activation required to initiate trials. - reversal learning ... lever activation required to initiate trials. - ID/ED (predefined/superimposed styles) ... lever activation required to initiate trials. ========================= v1.3 (10 Feb 2005) ========================= - Bug: CDMTS::IncreaseLevelIfNecessary() / DMTS_LEVELMETHOD_DWOR was counting level numbers from 0, not 1. ========================= v1.4 (21 Mar 2005 - 3 Apr 2005) ========================= - option to create quadpatterns directly (could already edit them) - quadpatterns loaded properly from XML - DMTS - Pfizer (Curt.Christoffersen@pfizer.com; Scott.Baron@pfizer.com): [CC] I have found a problem with the color choices when monochrome is chosen for the stimulus set. If there are 2 distracters or less, all the stimuli are the same color. However, If there are 3 or more distracters, one or two of the distracters is a different color. Currently with monochrome, shape only x7 colors, you cannot set the color to one choice. Can this be changed so we can set the color we would like for the stimulus? [SB] I would like to add that the use of different colors for each trial (e.g., blue for one trial, red for another; white for another : same color for sample and all comparators) is also a useful parameter- I believe that this is the intent of the current procedure. [CC] We would like to end up with the ability to use 7 distractors and a matching stimulus, all the same color. The colors can be chosen at random, a different color for each trial would be preferred. We are currently using camcog_star0, vary colours (#stim x 2401), as the stimulus set for DMTS. [CC] It has been suggested that if the matching and distractor stimuli were rotated 90 degrees (in either direction) from the sample stimulus, that the task would be much more difficult. Is this possible and how difficult of a programming job would it be to accomplish this? [CC] Will the solution for the monochrome issue with multiple distractors be sent with the stimulus rotation piece? The ability to use multiple monochrome distractors is our most urgent need. ... so will need to rewrite the stimulus-generating procedure from scratch, I think. So we have: - stimulus plus 0-7 distractors - current options: * unmodified from base stimuli * alter the colours * monochrome, shape-only * monochrome, colour-only * monochrome, mixed colour/shape * seven colours per trial - things to add: * rotate distractors Changes: - rewriting of stimulus generation code - ensuring that stimulus-within-subset (which replaces "... within quad") always starts at zero; no longer user-editable - option to rotate matching stimulus/distractors (m_bUseRotation) - option to jumble variants (m_bJumbleVariants) - Option to treat mouse input like touchscreen input (Marlenna Studtmann, marlenna@gmx.de). - do this by modifying CDisplayObject::Display() - and DisplaySetBackgroundEvent() calls and the like - m_bRespondToMouse - ThreeChoice - IIBR (ettie@iibr.gov.il) Rudolf Please see Ettie's email below. We have also had a more recent email which says that when she disconnects the lever, everything works fine. I am sending this to you as it appears that the program still responds to the lever, when the screen stimuli has been selected which I would not think should be the case. Julie Julie, Any suggestions to help Ettie? Do you think that the lever is permanently on and causing a problem? What's the position on the sound device? Greg Dear Greg, I am sorry to inform you that after working with the CANTAB for a few weeks, the program failed today and we cannot figure out what happened. We run the "Multiple choice serial reaction time". We are still in an early phase and use one stimulus for a target in phase two. We were using the touchscreen as the response device. The program now seems to works "at random": The 2nd phase stimulus appears at some of the trials and does not appear in others, regardless of what we do. In our attempts to figure out what went wrong we discovered that the lever seems to be operating eventhough we selected only "touchscreen" as the response device, and the lever does not bounce back after each press. We also discovered that the sound stimuli setup was not connected at all. Since this was not connected before the system was sent to you for repair, can you let me know if there is a reason to not attaching the sound device? [Ettie Grauer] - lever-handling functions are: CString GetLeverPressedEventString(); [only called in CThreeChoice::IncomingEvent x several] CString GetLeverReleasedEventString(); [only called in CThreeChoice::IncomingEvent x several] void ExtendLever(); [only called in CThreeChoice::NewTrial] void RetractLever(); [called in CThreeChoice::StartModule, CThreeChoice::IncomingEvent x several] - lever events are always set on the line, so it is the module's job to ignore them - the levers are meant to be retractable, but we consider that a luxury... - m_iCentringResponseDevice governs whether a lever should be being used - OK, added checks on m_iCentringResponseDevice whenever GetLeverPressedEventString is called ========================= v1.5 (21 Apr 2005) ========================= - ID/ED tasks now only make you enter stimuli you'll need - Problems with SimpleSchedules, including FR5 requiring >5 responses after first reward, and response object being visible during timeout - perhaps both a manifestation of response object being visible during timeout! More details below. Dear Alana and Chris (CC Julie), 1) To use the whole screen for the response/marker object, creating a large rectangle is optimal (though you don't need to start with e.g. a camcog_pal3 object and delete the quadpattern; you can just create a fresh stimulus from scratch and add a 1000x1000 rectangle to it). 2) You've observed that the marker object is sometimes the colour of the background. I suspect this is because the marker object is configured to be transparent; check the BRUSH settings for the rectangle component of the marker object and ensure that the brush is SOLID and set to the desired colour. 3) You've observed that on an FR-X schedule, X presses are required for the first "trial" or sequence, but >X are required afterwards. I think this is because some of those >X responses are during a timeout, or when the reinforcing device is busy, when responses are recorded but don't count towards the schedule. This behaviour has been changed (see below). 4) You've observed that some responses aren't followed by the marker object, though most are. I've observed this too. Responses that are followed by a schedule timeout were not marked; I've changed this. 5) You've observed that sometimes the response object persists during reinforcement. You thought this was a change from previous versions. Not sure what caused this, but in any case, the display code has been rewritten so this may have vanished in the wash. 6) You've observed that sometimes the screen turns black in the middle of a trial, for up to 30s, only returning to blue when the subject responds. You've disabled the computer's power saving and screen saver. NOT SURE WHY YET. I've not been able to reproduce this, and will continue to monitor it. If it happens with the new version, please send me the .XML config file so I can be sure I'm reproducing your setup exactly. Revised into SetAppropriateAppearance(), which now controls all visual appearances. For schedules *not* involving delayed reinforcement, ensure a manipulandum is not shown during the "reinforcer busy" state. Also indicate timeout states on console. - Further update from Julie, 6/5/5: Having talked to Chris some more, I am pretty sure the random going black is a hardware not a software problem, as it only happens on his newest unit. I am hopeful that it is a problem which I know we had with the very first of the new systems we built and can be solved by reloading the UPDD drivers after whisker is started. It appeared prolonged touches were registering as two touches. The problem was solved by changing the chip in the touch screen... I'll keep you informed. ========================= v1.6 (18 May 2005) ========================= - database assistance added via the separate DatabaseManager application - customer C5 wants 'require lever response to start each trial' option to terminate the Marker 1 sound when the lever is pressed (request via Terry Echard). - Implemented by adding m_pController->AudioSilenceAllDevices(); // cancel any ongoing Marker 1 sound before the call to BeginTrialProperly() that follows the initiating lever response. Done in DMTS, NewTouchTraining, PAL, Reversals, SpatialWM, VisualDiscrimPredefined, VisualDiscrimSuperimposed. Not relevant for non-trial-based tasks (ReinforcementFamil., SimpleSchedules). For MCSRT (ThreeChoice), also added (in IncomingEvent processor). - Touchscreen training: 'missing the stimulus (and touching the background) terminates the trial as a failure' doesn't do anything, says Terry Echard, using MonkeyCantab v1.5 - NewTouchTraining.cpp - Yes, it does, it terminates the trial. Works fine. Will send sample XML to Terry to find out what problem is. ========================= v1.7 (30 May 2005, 4 Sep 2005) ========================= - 3 decimal places for DMTS/ThreeChoice parameter dialogues displaying floating-point vectors, rather than 2 - NewTouchTraining - didn't allow user to determine whether subject collected reward. - added field TouchTraining_Results.LickLatency_ms, and appropriate code. - and field TouchTraining_Results.TrialEndTimeMs ========================= v1.8 (21 Sep 2005) ========================= - ReinfFamil - was inappropriately proceeding from "totally free juice" to FR1. ========================= v1.9 (8 Oct 2005) ========================= - Terry 3/10/5: If Harsh correction is ticked on in Visual Discriminations and Set-Shifting and an error (wrong choice) is made no further shapes are presented and no stimuli onset tone is heard. We do hear the punishment tone every timeout period. Attached are the module set up and the CANTAB Status messages of a simulation I ran. [= Harsh-MonkeyCantab-config.xml ] It would appear that the program is calling non-existent images. Images do appear once all the 'Harsh' repeated trials are exhausted via timeout. The problem was discovered by customer C5, who is using the Dog CANTAB systems. (Using their created images, not what I am using in the example.) BUG IDENTIFIED: correction procedure failing to copy information from previous trial. BeginTrialProperly() created a reference: CVisualDiscrimPredefinedTrialRecord& tr = m_vTrialRecord.back() Then it called GetNextTrialSettings(tr) to fill in details of tr... ... but GetNextTrialSettings() tried to use m_vTrialRecord.back() as the *previous* trial. Solution: make an explicit reference to prev trial. - MonkeyCantab_GeneralConfig.ModuleList changed from String(255) to Memo type with corresponding adjustment to RFX_Text call. ========================= v2.0 (7 Jan 2006) ========================= - stopwatch on main screen: "time elapsed since user clicked Start". (Hreq 21/9/5.) [?something similar implemented on five-choice task? q.v.] ... CMonkeyCantabDlg::m_strTimeSinceStart - Brief summary at end of task (session length, total trials, #correct, #incorrect) to status window, for: - reversals - VDP - VDS (Hreq 21/9/5.) - Curt Christoffersen: (1) I have encountered an unusual problem with one of our units. In the (MonkeyCantab) 5CSRT program when I enter 0.35 for a signal duration the program reads it as 0.349 when the test runs. If I change it to 0.351 it reads 0.351 and runs that way. // RNC: it seems to store/recall 0.349 fine just looking at the configuration dialogues. So is the conversion of 0.35 to 0.349 happening in the text file data output as well as in the database? (The reason I ask is that it's also possible that the rounding error is occurring in the database conversion - which wouldn't affect the text file output, but just the database.) // CC: I am referring to the monkey Cantab version of the 5-choice test. The conversion of 0.35 to 0.349 is happening in the text file data output from the 5-choice program. -- Occurs not in the "config" end of the database/textfile, but in the "results" section - the actual number of milliseconds used for the duration. Reason: DWORD testnumber1 = 0.350f * 1000; DWORD testnumber2 = 1000 * 0.350f; DWORD testnumber3 = 0.350f * 1000.0f; DWORD testnumber4 = 1000.0f * 0.350f; ... all give the value 349. So this is a consequence of floating-point arithmetic. However, DWORD testnumber1 = 0.350l * 1000; DWORD testnumber2 = 1000 * 0.350l; DWORD testnumber3 = 0.350l * 1000.0l; DWORD testnumber4 = 1000.0l * 0.350l; ... all give the value 350 (i.e. using long double, not float). And: DWORD testnumber1 = 0.350 * 1000; DWORD testnumber2 = 1000 * 0.350; DWORD testnumber3 = 0.350 * 1000.0; DWORD testnumber4 = 1000.0 * 0.350; ... all give 350. Now note: - floating-point constants are identified by a decimal point; - floating-point constants default to type double; - suffix "f" denotes "float" - no suffix, or suffix "l" denotes double - since "long double" is the same as "double" So plan: - remove all "f" suffixes; - change all "float" constants to "double" (also changed in WhiskerClientLib); - change all DDV_MinMaxFloat to DDV_MinMaxDouble. Note that "f" prefixes to variables not changed (no external consequences; too much hassle). - that new display feature implemented by Mike in the clientlib... debugview with -debugtouches Reason: Spencer Tye (Merck): Is there any way on the Whisker system that i can display all of the displays the subjects are seeing side by side on the server screen, basically i want to be able to see what the subjects are seeing so that i can monitor what they are all upto. I've only been able to do this one screen at a time so far. - Curt Christoffersen (Pfizer): re MCSRT: (2) We would also like to explore the possibility of having control over the location of the five boxes in the test. Is this possible and how long would it take to implement? I would like control over the target locations on the screen, not the location where the target appears. We have a few subjects that either will not respond when the target appears in a certain area of the screen or tend to keep their hand on an area of the screen which contains a target location and therefore continue to be "charged" with a premature response. - In the process, needed to introduce CMonkeyCantabModule::PreliminarySetController(). - Some stimuli - need a background (easily missed... only the drawing triangles are touchable...). Example: camcog_nedi8line_2. CPredefinedObjects::GetUnivcamTriangleStimulus gave a background rectangle (appropriately). But CPredefinedObjects::GetCamcogTriangleStimulus did not. Fixed. - Ettie (IIBR) 7/10/5: Consider stages of 5-choice task as (1) see centralizing stimulus; (2) touch it/it changes colour; (3) ... see target; (4) touch target. Then requests are: (A) with onset of second stage, option for a tone to be played. (Let's make it the Marker2 sound.) i.e. as the subject starts to make the centring response. ... m_bPhase1Marker2Sound - DONE. (B) to have two alternative target stimuli (in practice, large or small) presented within the same session, in random order, with the actual stimulus being used recorded in the output. ... m_strPhase2AlternativeStimulus; m_fPhase2PAlternativeStimulus - DONE. ========================= v2.1 (10 Jan 2006) ========================= - H 10/1/6: option to have stimuli persist on the screen for a while in NewTouchTraining, during reward, as for Reversals - m_bLeavingStimulusUpDuringReward. - H 10/1/6: option to have ITI touches punished by restarting the ITI in NewTouchTraining, as for Reversals... m_bPunishITITouches, m_iITITouches - Julie 9/1/6: While we are talking about upgrades to the existing software, I was training some people from Maccine, Singapore on Monkey CANTAB recently and it became obvious that it would be very useful to be able to copy modules. The particular case in question was with the SOSS task. The best way to duplicate some of Scripps work (section 2.4.2 SOSS probe tests in the Weed et al paper) is to have several modules running one after the other, each with slight changes. As far as I can see the only option is to add a blank module. Since we are using our own quite complex Schemes, it will be very time consuming to set the experiment as required. Even being able to save and load Schemes would help considerably. I attach here our Monkey CANTAB manual. The tests are described in section 6.4.2. I also attach my sample configs mentioned in that chapter. ... CMonkeyCantabParamsDlg::OnBcopymodule() and subsequent. This was hard to implement because of the VC++ derivation bug (see MonkeyCantabModule.h). Explicit ugly pointer casts required in CMonkeyCantabControllerConfig::NewModuleCopy. ========================= v2.2 (11 Jan 2006) ========================= - option to punish, not reward, touches in NewTouchTraining. ========================= v2.3 (13 Feb 2006) ========================= - 26/1/6: JV at Roche - ideally they'd like to be able to give "free reinforcers" at any point to a MCANTAB box & find it too fiddly and error prone to do so via the linestatus dialogs, as they are running 4 chambers simultaneously. Coded from 13/2/6. ========================= v2.4 (13 Feb 2006) ========================= - 15/2/6 Spencer Tye at Merck has a request. "I'd also be interested to know if some configs currently in the top level "general parameters" could be made module specific. I'm thinking specifically here that we might like to run modules in a session but to use different amounts of reinforcer or different durations of punishment timeout and so on for the different modules... eg a 30sec timeout for 5 choice and a 10sec time out for DMS." - RNC: Hard to do cleanly within current design. So the alternative is to chain two configs together. Turns out that batch files (.BAT) wait for Windows dialogue-based apps to finish before moving on to the next command (i.e. like UNIX "app", not "app&"). So that's handy. Therefore only modification necessary is to accept command-line parameters for automatic connect/claim box/load config/start. - Let's implement command-line parameters: -? } give syntax message -help } ... and others as explained in that syntax message. See CMonkeyCantabApp::InitInstance(). Obtaining access to cout/cerr is not automatic. By default, the program produces nothing unless you manually redirect (e.g. monkeycantab.exe >out.exe 2>err.txt). See http://www.codeproject.com/cpp/EditBin.asp and http://www.codeguru.com/Cpp/W-D/console/redirection/article.php/c3961/ and http://www.codeguru.com/Cpp/W-D/console/redirection/article.php/c3955 and http://dslweb.nwnexus.com/~ast/dload/guicon.htm and http://www.cygwin.com/ml/cygwin/2004-05/msg00215.html Best explanation: http://msdn.microsoft.com/msdnmag/issues/04/02/CQA/ - Coded from 15/2/6: autoexecution feature, requiring additional MONKEYCANTAB.COM as well as MONKEYCANTAB.EXE, with new project MonkeyCantab_console to create it. Note also custom build step to copy it to .EXE directory for debugging porpoises. ========================= v2.5 (21 Feb - 2 Mar 2006) ========================= - Request from Pfizer 17Feb2006: option to repeat entire DMTS trial following failure (either at phase 1 or at phase 2), until the subject gets it right. ========================= v2.6 (8 Apr 2006) ========================= - Bug (Merck): DMTS stuck intermittently at "... when finger removed" stage. Freeze during DNMTS. Status 1: Trial 6. Using level 1. Nonmatching. Status 2: About to start correction procedure (when finger --- _RecordNum 2497 DateTimeCode 3/28/2006 7:50:44 AM Subject 04R437 Box 2 ModuleNumber 1 Trial 6 TrialStartTimeMs 1597314 Level 1 Phase1Stimulus camcog_pal0_29_DM_SS_VC46209_1_2 Phase1Location 2 Phase2Stimuli camcog_pal0_29_DM_SS_VC46209_1_2:camcog_pal0_29_DM_SS_VC46209_0_2 Phase2TargetLocation 6 Phase2Locations 6:0 Phase1Responded Yes Phase1ResponseLatencyMs 1053 Phase1Succeeded Yes Phase1Rewarded No Phase1Punished No MemoryDelayMs 1 Phase2Given Yes Phase2StartTimeMs 1598370 -- note this is 1056 ms after trial start time Phase2Simultaneous No Phase2Responded Yes Phase2RespondedCorrectly No Phase2ResponseLocation 6 Phase2ResponseLatencyMs 1241 Phase2Rewarded No Phase2Punished Yes CorrectionGiven Yes -- default m_bCorrectionGiven(false) CorrectionStartTimeMs 8907909 -- default 0; note that this is 121 min after phase 2 began. CorrectionResponded Yes -- default false CorrectionRespondedCorrectly No -- default false CorrectionResponseLocation 6 -- default -1 CorrectionResponseLatencyMs 2754 -- default 0 CorrectionRewarded No -- default false CorrectionPunished Yes -- default false ITITimeMs 5000 -- default 0 TrialFailedNextTrialWillBeCorrection No TrialIsCorrectionTrial No --- These are the results for trial 6 (the one that froze). So results look as if correction procedure *has* been given. Ah, no - look at the correction start time; 2h later; this was operator rescue. Must be stuck in phase DMTS_PHASE_ABOUTTOSTARTCORRECTION. This phase is left only by the following code: if (m_bFingerReleasedBeforeCorrection && m_bReadyToStartCorrectionWhenFingerReleased && m_ePhase == DMTS_PHASE_ABOUTTOSTARTCORRECTION) { ... m_bReadyToStartCorrectionWhenFingerReleased likely to be true (set by timer strEvent_StartPhase3) ... only thing that could delay this is Therefore... m_bFingerReleasedBeforeCorrection likely to be false, and incorrectly so. Possible reasons: (1) touchscreen not sending "finger off" message (strEvent_FingerOffTouchscreen) ... should be sent by background release ... and all object releases... ... Aha! CLocatedDisplayObject* pTarget = new CLocatedDisplayObject(... didn't have a finger release message. So possible that if the subject touched the phase 2 target (= incorrect for DMTS), - as indeed it did in this trial (phase 2 target location 6, response location 6) - and then released it before it vanished, that the "finger off" message wouldn't have been sent. Physical/configuration touchscreen fault also possible. But definite possible cause identified here. FIXED. (2) finger off message arriving in wrong phase, i.e. before DMTS_PHASE_ABOUTTOSTARTCORRECTION set... ... but events are processed sequentially, and the code that initiates this wait looks like it moves seamlessly into the correct DMTS_PHASE_ABOUTTOSTARTCORRECTION phase (this is the code for an incorrect response in phase 2) - and this code responds to a touch start, and therefore a touch stop must be due. - ensure option that DMTS uses stimuli from its list in a consistent reproducible order with respect to S+/S- (Michael Weed, Johns Hopkins). - vstrAvailableStimuli is populated sequentially from the user-supplied list (or any other) - target is then picked as int iTargetObject = m_pController->RandomInt(0, vstrAvailableStimuli.size()-1); - ... so that's the reason. - If we add an option to pick the first as the target, not a random selection, we'd have our result. - Call it m_bPhase1StimulusIsFirstOfSet ========================= v2.7 (8 Apr 2006) ========================= - 29 Apr 2006: DMTS problem still not fixed - may well be a hardware fault. As a workaround, implement an optional feature: "wait for finger release before proceeding but never for more than X seconds (user can specify X)" ... m_fCorrectionPhaseMaxTimeToWaitForRelease ========================= v2.8 (24 May 2006) ========================= - autoupdate data filename on first entering subject ID - improve error message if two data summary files have the same name (by virtue of being started at the same time). ========================= v2.9 (July-August 2006) ========================= - "... we'd like to be able to vary the number of choice stimuli and choice delays independently between trials but within blocks of the DNMTS module. In the end we'd like a situation where, with 3 different delays and 3 different #s of choice stimuli, we can have 9 different trial types within a session. At the moment in the Phase 2 area of the DMTS config window if you pick matching it opens the # distractors dialog box and you can select a number between 0-7. What we'd like to have is something like the Delay dialog so that we could pick a number of different # of distractors and how they are presented, i.e. at random, in some increasing order etc." SUMMARY OF THAT: need flexibility in # distractors in DMTS (as for # delays). - LOST: m_iDistractors - GAINED: m_iDistractorMethod m_iDistractorDWORMultiplier m_iChangeDistractorCriterion m_viNumDistractors m_ctlDistractorList [dialogue] m_strDistractorDWORVectorSize [dialogue] ========================= v3.0 (9 Sep 2006) ========================= - Reversals: finish after n reversals (m_iMaxReversals) - Reversals: randomize side in draw-without-replacement, specify list size (m_iSpatialRandomizeDWORMultiplier) ========================= v3.1 (22 Dec 2006) ========================= For U Texas Health Science Center, 21-Dec-2006 (NZ): - "Even when I do not choose the option move box around once final size has been reached, the box starts moving around, after the final box size has been reached. More precisely, it starts moving around once it has been touched for the number of consecutive correct trials required earlier to make it shrink. I.e. if 2 correct trials were necessary to make it shrink, it would start moving around once the final size has been touched twice correctly. I thought this would only happen if the option move the box around was ticked." ... simple bug: incorrect logic for "m_bMovingNow = true;" command in NewTouchTraining.cpp - Ability to query the size of a stimulus (in units and as proportions of the active screen size). - "With the touch screen training module it is not necessary to remove the hand from the screen between trials to get a reward. I.e. if the ITI is set to 3 sec, the finger can be left on the screen and every 3 second another reward pellet will be delivered. This is in contrast to simple schedule modules, where the finger needs to be removed and put back onto the screen in order to get the next reward. Why is it not necessary to remove the finger between trials?" ... strEvent_FingerOffTouchscreen / m_bFingerOn code added to NewTouchTraining.cpp (cf. SimpleSchedules). For Roche: - Roche request 12-Dec-2006: all tasks: display on the home screen the time since the last (most recent) response. ... uses CMonkeyCantabController::NoteSubjectResponse() ReinforcementFamiliarization - done NewTouchTraining - done SimpleSchedules - done SpatialWM - done PAL - done DMTS - done ThreeChoice - done VisualDiscrimPredefined - done VisualDiscrimSuperimposed - done Reversals - done - Roche request 12-Dec-2006: DMTS: (1) Present stimulus in phase 1; wait for up to time LIMITED_HOLD; (2) If LIMITED_HOLD elapses without a response, end the trial and score an omission; (3) If the subject responds, accept the response, terminate the stimulus and move on to phase 2. ... = same as current, but allowing the user to specify Phase 1 and Phase 2 limited holds separately. ... m_fMaxResponseTimeSec becomes m_fMaxResponseTimePhase1Sec / m_fMaxResponseTimePhase2Sec - Roche request 12-Dec-2006: end session after a user-selected number of reinforcers / correct trials. "We are thinking for all tasks. The issue initially came up for DMTS, in which we wanted to maximize the training session opportunities based on motivation/satiation. So, instead of say 100-trials (total) which may result in 30-75% correct for a session, we wanted the flexibility to terminate the session at 100-reinforcers (correct trials) regardless of the total number of trials." ... m_iOverallMaxRewards ... bool CMonkeyCantabController::IsOverallRewardLimitReached() ReinforcementFamiliarization - done NewTouchTraining - done SimpleSchedules - done SpatialWM - done PAL - done DMTS - done ThreeChoice - done VisualDiscrimPredefined - done VisualDiscrimSuperimposed - done Reversals - done - Roche request 12-Dec-2006 (done 22 Dec 2006, 28 Dec 2006): "to freeze the program while it is recording input from the touchscreen" Observation: Subject doesnt remove hand from touchscreen between stimulus presentations (for example, using the screen as a place to hold his hand). This can result in the recording of errors when the new stimuli are presented where the monkey is holding his hand. Proposed fix: We want an option to freeze the program while it registers a touch - none of the programmed events occur (stimulus presentation, stimulus removal, RF delivery etc) until the monkey removes its hand. We would like this option to be available in all programs but it is most urgent for touchscreen training and delayed match. RNC alternative fix: responses are ignored unless hand is removed/replaced. That's what we were using anyway in SimpleSchedules, and have just implemented for NewTouchTraining. All use m_bStrictTouches, m_bFingerOn, strEvent_FingerOffTouchscreen, AllowTouches(). ReinforcementFamiliarization - NOT APPLICABLE = DONE - doesn't need retesting = TESTED NewTouchTraining - already done (just now, see above, as "Strict touches" option) - REDONE = DONE - TESTED SimpleSchedules - already done (previously) - already enforces strict touches with no option, but redone for the new "dodgy touchscreen safety timer" feature - redone = DONE - TESTED SpatialWM - DONE - TESTED PAL - DONE - TESTED DMTS - done - redone = DONE - TESTED ThreeChoice - (NB complex) - DONE - TESTED VisualDiscrimPredefined - DONE - TESTED VisualDiscrimSuperimposed - DONE - TESTED Reversals - DONE - TESTED Note also: previous problems with this facility - hardware issues (see 8 Apr 2006). Use MonkeyCantabController::SetFingerOn(), ::SetFingerOff(), ::IsFingerOn(), ::AllowTouches(). Option in General Parameters for strict touches, and "safety timer" in case of dodgy touchscreens. Separate finger on/off code from task code, within IncomingEvent parsers (so even "irrelevant" touches are noted). ========================= v3.2 (22-23 Jan 2007) ========================= - Merck (Spencer Tye) request Jan 2007: ST: Could I ask if it would be possible for us to request a black and white option for the delay (non)-matching paradigm. I guess in CANTAB nomenclatur e it would be "monochrome, shape-only discrimination (x1)" here the 1 colour would either be white, or selectable. RNC: I note as an aside that for the built-in DMTS stimuli, this would be a pretty hard task, and I presume that's the objective! ... ... The alternative, simpler from the user's point of view, requires additional coding, viz. a new colour option ("force to colour"), where that colour is specified (e.g. white)... With a given colour, this colour system would yield one "colour variation" per stimulus set (i.e. if you have a set with n stimuli, and you don't use shape-shuffling, you get n unique stimuli coming out, since you've forced them all to one colour; also, this relies on the stimulus sets having appropriately different shapes, obviously!). Multiplying this by the available number of colours gives the total number of "colour variations". Key portions of code are in CPredefinedObjects::GetDMTSVariantObjectName ... and making code letters/suffixes back-compatible CPredefinedObjects::GetPredefinedDMTSVariantNumber CPredefinedObjects::GetDMTSColourVariationMethod ... and the functions that follow it... CPredefinedObjects::GetDMTSVariantObject = core generation code CDMTS::JumbleVariant = to prevent variant jumbling... CDMTS::EnsureStimulusRational() = to prevent variant "ticking up" ... and the dialogue box This is the "MF" variation (monochrome, fixed colour). ... DMTSCOLOUR_MONOCHROME_FIXEDCOLOUR ... strDMTSMFSuffix ... DMTSCOLOUR_MONOCHROME_FIXEDCOLOUR_MAXCOLOUR ========================= v3.3 (27 Jan 2007) ========================= - bug in above... colours coming out wrong. DMTS calls CPredefinedObjects::GetDMTSVariantObjectName to synthesize the object name. DMTS calls CMonkeyCantabController::GetDisplayObject which calls CMonkeyCantabControllerConfig::GetDisplayObject which calls CPredefinedObjects::GetPredefinedDisplayObject which tries, in turn, GetPredefinedDisplayObjectNumber (which only succeeds if no variant number stuff is appended to name) GetPredefinedPALVariantNumber - this succeeds regardless of the actual stimulus set, as long as strPalVariantSuffix is there GetPredefinedDMTSVariantNumber - this succeeds regardless of the actual stimulus set, as long as a DMTS variant code is used ... and then, for DMTS stimuli, calls GetDMTSVariantObject BUG FOUND: in CPredefinedObjects::GetDMTSVariantObject - if shape-shuffling used, colour variant number goes wrong. int iShapeVariant = 0; if (bShuffleShapes) { iShapeVariant = iVariant % 64; iVariant = iVariant / 64; } int iColourVariant = iVariant; FIX METHOD: abandon use of variant number. Variant number remains as was. There is just 1 colour variant for this scheme. Separate parameter for "forcing" colour. Restored functions in CDMTS previously modified as above. m_iColourForce added as new parameter to DMTS. ========================= v3.4 (8-10 March 2007) ========================= - easier compilation for users - for Emmanuel Decamp (Motac): option to stop ID/ED tasks after subject completes X of last Y etc., not just to advance stage. We lose: m_bIncreaseStage We gain: m_iActionWhenCriterionReached We rename (database): IncreaseCriterionX/IncreaseCriterionX to CriterionX/CriterionX ========================= v3.5 (30 March 2007) ========================= - Reversals task: option to make it a side discrimination task (otherwise identical). Consequences: - three-way (ABC) discrimination: not available (force off) - "begin with B+ rather than A+": not available (irrelevant) - correction procedure: not available (force to "none") - the "spatial location of correct stimulus" option comes to mean "spatial location of stimulus A" instead Uses: m_bSideTask m_bBeginWithRight ========================= v3.6 (21 May 2007) ========================= - Bug in WM (SOSS) task. Noticed by Roche (JV) and Johns Hopkins (MW). Symptom: second touches to stimuli were sometimes ignored Cause: it was possible to remove the finger from the screen without this being noticed. Remedy: marker objects now have associated events Remedy: call to DisplayBlank from CSpatialWM::MarkResponse replaced with code that blanks the screen while still noticing finger removals. ========================= v3.7 (24 July 2007) ========================= - in CSimpleSchedules::End(), m_timeEndTime = m_pController->CurrentTime(); should have read m_timeEndTime = CTime::GetCurrentTime(); ========================= v3.8 (18 Aug 2007) ========================= - For Nicole Zurcher, UTHSCSA: SimpleSchedules always requires "strict" touches. But it also needs to use the user-specifiable option to assume a finger has been removed after a certain time (specified in General Parameters). ... Actually, this was happening anyway! But it was perhaps not obvious enough. Changes: (1) General parameters dialogue box makes this clearer. (2) strAssumeFingerRemoved events are explicitly recorded (globally), so users can see whether their touchscreen appears to be malfunctioning (because the purpose of this option is to assume that a release must have occurred and that problem is with the touchscreen, not the subject). Uses the ET_ASSUME_FINGER_REMOVED event code; textual equivalent in database is "Assume_Finger_Removed_And_Touchscreen_Missed_It". (3) Was possible to line up several assume-removed events (e.g. if two responses occurred in quick succession). CMonkeyCantabController::SetFingerOn() modified so that if a second arrives, the first event is cancelled and a second rescheduled (i.e. reset the timer from the last "on" response). ========================= v3.9 (14 Sep 2007) ========================= - For DSTL: Houselight off during tasks. > > Also would it be possible to have the option of switching the house light > > off when a task is running? (8) We should be able to do what you want with the houselight. Do you mean off all the time, or on during "links" but off during tasks? (If you want a quick-and-dirty way of getting the houselight off all the time, you can just Force it off from the Whisker console.) I will get them to force 'off' in whisker for now, they just want a tick box in the general parameters so that the light will not come on when the task is running. - Implemented m_bDisableHouselightDuringTasks - DATABASE CHANGE: this adds MonkeyCantab_GeneralConfig.DisableHouselightDuringTasks - Problem at DSTL: > >Basically we are getting a loud popping sound coming from the speakers. > > It appears to occur when stimuli are presented on the screen most of the > > time but sometimes very randomly. > >The popping sound never occurs at the same point in any task. > > > > We think we have found a way of stopping it by turning the level down to > > 0 for 'Marker 2' and 'Marker 3' in the general parameters, the duration > > for both is always set to 0. (1) Do the noises occur when no software is running, but the speakers have power? NO (2) Do the noises occur when Whisker is running, but MonkeyCantab is not? NO (3) Do the noises occur when MonkeyCantab is loaded and connected to Whisker, but not running? No only when a task is running (4) Do the noises ever occur in between MonkeyCantab tasks? NO (5) Could you send me the .XML configuration file, and any .WAV files you are using? I will get DSTL to send me one that we were using on site but it was doing it with all cinfig files so you could use any. No .WAV files are being used. (6) Do the noises occur whether or not the various markers are using .WAV files or not (and by "not", I mean specifying a frequency/sound type/duration etc.)? They are not using the markers so the duration is set to '0' on all 3 the olny way to stop the popping is to set the volume to '0' on markers 2 and 3 you can change the frequency and still get the same pop (7) Are the pops single, or do they come in clusters, and is there any other odd noise? Single pops - Relevant thoughts (re Windows audio bugs) in Whisker development were at version 2.8.03 RNC (2 Mar 2004). - THOUGHT: if it's unrelated to the timing of the Marker sounds, then it's almost certainly a sound card problem. (Though why it's then only during tasks is unclear; CPU load? Are they running a USB sound card?) - THOUGHT: is it something to do with the sound duration being zero? If so, you'd expect it to occur and the Marker times. - The fact that setting the Marker volume to zero gets rid of it makes the "pop" most likely to be a cut-off Marker. - SOLUTION ATTEMPT: Amended CMonkeyCantabController::PlaySoundForDuration to reject zero-length sounds. ========================= v4.0 (25 Oct-2 Nov 2007) ========================= - Impulsive Choice task added. See Help for details. - Database amended: - new entry in MonkeyCantab_LOOKUP_TaskTypes - new entries in MonkeyCantab_LOOKUP_EventTypes - new table: ImpulsiveChoice_Config - new table: ImpulsiveChoice_Results - Improved checks on sound parameters in general params. - Note, incidentally, bug in Access 97: I copied a table from one database to another with the Whisker Database Manager. Included amongst the fields were boolean (Yes/No) fields. These copied successfully, but were displayed as numbers (-1 for true, 0 for false) in Access. Changing them by hand to numeric fields and than back to Yes/No fields fixed the displays, so they were displayed as tick-boxes, as usual. But in another table, boolean fields were copied and displayed normally. ========================= v4.1 (21 Dec 2007) ========================= - Bug fix in SimpleSchedules: "assume finger removed" not always detected correctly. ========================= v4.2 (26 Dec 2007) ========================= - Two-choice option for MCSRTT. ========================= v4.3 (7 Mar 2008) ========================= - Flashing visual stimulus option for reward/punishment. ... New database fields in MonkeyCantab_GeneralConfig: MonkeyCantab_GeneralConfig.RewardGiveVisualStimulus MonkeyCantab_GeneralConfig.RewardVisualStimulusName MonkeyCantab_GeneralConfig.RewardVisualStimulusXCoord MonkeyCantab_GeneralConfig.RewardVisualStimulusYCoord MonkeyCantab_GeneralConfig.RewardVisualStimulusDurationSec MonkeyCantab_GeneralConfig.RewardVisualStimulusOnTimeSec MonkeyCantab_GeneralConfig.RewardVisualStimulusOffTimeSec MonkeyCantab_GeneralConfig.PunishmentGiveVisualStimulus MonkeyCantab_GeneralConfig.PunishmentVisualStimulusName MonkeyCantab_GeneralConfig.PunishmentVisualStimulusXCoord MonkeyCantab_GeneralConfig.PunishmentVisualStimulusYCoord MonkeyCantab_GeneralConfig.PunishmentVisualStimulusDurationSec MonkeyCantab_GeneralConfig.PunishmentVisualStimulusOnTimeSec MonkeyCantab_GeneralConfig.PunishmentVisualStimulusOffTimeSec ... and corresponding A/B reward information in ImpulsiveChoice_Config ImpulsiveChoice_Config.A_RewardGiveVisualStimulus ImpulsiveChoice_Config.A_RewardVisualStimulusName ImpulsiveChoice_Config.A_RewardVisualStimulusXCoord ImpulsiveChoice_Config.A_RewardVisualStimulusYCoord ImpulsiveChoice_Config.A_RewardVisualStimulusDurationSec ImpulsiveChoice_Config.A_RewardVisualStimulusOnTimeSec ImpulsiveChoice_Config.A_RewardVisualStimulusOffTimeSec ImpulsiveChoice_Config.A_RewardGiveVisualStimulus ImpulsiveChoice_Config.B_RewardVisualStimulusName ImpulsiveChoice_Config.B_RewardVisualStimulusXCoord ImpulsiveChoice_Config.B_RewardVisualStimulusYCoord ImpulsiveChoice_Config.B_RewardVisualStimulusDurationSec ImpulsiveChoice_Config.B_RewardVisualStimulusOnTimeSec ImpulsiveChoice_Config.B_RewardVisualStimulusOffTimeSec ... New variables: m_bRewardGiveVisualStimulus; m_strRewardVisualStimulusName; m_iRewardVisualStimulusXCoord; m_iRewardVisualStimulusYCoord; m_fRewardVisualStimulusDurationSec; m_fRewardVisualStimulusOnTimeSec; m_fRewardVisualStimulusOffTimeSec; m_bPunishmentGiveVisualStimulus; m_strPunishmentVisualStimulusName; m_iPunishmentVisualStimulusXCoord; m_iPunishmentVisualStimulusYCoord; m_fPunishmentVisualStimulusDurationSec; m_fPunishmentVisualStimulusOnTimeSec; m_fPunishmentVisualStimulusOffTimeSec; ... and corresponding A/B reward pairs in ImpulsiveChoice task: m_bARewardGiveVisualStimulus; m_strARewardVisualStimulusName; m_iARewardVisualStimulusXCoord; m_iARewardVisualStimulusYCoord; m_fARewardVisualStimulusDurationSec; m_fARewardVisualStimulusOnTimeSec; m_fARewardVisualStimulusOffTimeSec; m_bBRewardGiveVisualStimulus; m_strBRewardVisualStimulusName; m_iBRewardVisualStimulusXCoord; m_iBRewardVisualStimulusYCoord; m_fBRewardVisualStimulusDurationSec; m_fBRewardVisualStimulusOnTimeSec; m_fBRewardVisualStimulusOffTimeSec; ... added object event transparency handling to CDisplayObject ... rather more complex code to track changes via DisplayShowDocument() override, in case task changes the document while we're showing this thing ... bug emerged: SpatialWM was able to give rewards in rapid sequence (before the previous reward finished) in the specific case when every touch is being rewarded (hence: m_bRewarding). NOTE THAT TASKS MUST NOT CALL Reward() WHILE A REWARD IS IN PROGRESS. Currently not enforced by central controller, but implemented by all tasks. ========================= v4.4 (from 30 Apr 2008) ========================= - MAGAZINE_DOOR device and pellet collection latency in all tasks. All involve extra database fields in the relevant results table. - controller: DONE - Reinforcement Familiarization: DONE - RECORDED AS COUNT, NOT LATENCY (this task records individual events, not latencies, as it's not trial-based, but free-operant) - Touch Training: DONE - Visual Discriminations and Set Shifting (ID/ED task) - predefined: DONE - Visual Discriminations and Set Shifting (ID/ED task) - superimposed: DONE - Reversal Learning: DONE - Delayed Matching/Non-matching to Sample (D[N]MTS): DONE - Phase 1 latency, Phase 2 latency, Correction Phase latency - also lick latency for Phase 1, Phase 2, Correction Phase - note that if reward is not collected in phase 1, the latency "carries over" to phase 2 or subsequent, and likewise if reward is not collected in phase 2 (it can "carry over" to the correction phase) - Self-Ordered Search (SOS) (a.k.a. Spatial Working Memory, SWM): DONE - Five-Choice Serial Reaction Time (5CSRTT): DONE - inc. Phase 1 latency, Phase 2 latency - also lick latency for Phase 1, Phase 2 - note that if reward is not collected in phase 1, the latency "carries over" to phase 2 - Paired-Associates Learning (PAL): DONE - Simple Schedules of Reinforcement: NOTHING TO DO - free-operant task, so latency not meaningful - counts automatically recorded by controller - Impulsive Choice: DONE (both licks and pellet collection count as "collection" if pump/pellet respectively are part of the reward) - then test all the above... - controller: DONE - Reinforcement Familiarization: DONE - Touch Training: DONE - Visual Discriminations and Set Shifting (ID/ED task) - predefined: DONE - Visual Discriminations and Set Shifting (ID/ED task) - superimposed: DONE - Reversal Learning: DONE - Delayed Matching/Non-matching to Sample (D[N]MTS): DONE - Self-Ordered Search (SOS) (a.k.a. Spatial Working Memory, SWM): DONE - Five-Choice Serial Reaction Time (5CSRTT): DONE - Paired-Associates Learning (PAL): DONE - Simple Schedules of Reinforcement: NOTHING TO DO - Impulsive Choice: DONE - DWORD output of -1 using "<<" to text file gives a high positive integer (4294967295 = 0xffffffff): confusing. (Database fine: -1.) ... yes, that's appropriate, because DWORD is unsigned ... the bug was that SpatialWM was assigning -1 as a default for a DWORD - fixed (to 0). ========================= v4.5 (11 May 2008) ========================= - MAGAZINE_LAMP device and support in General Parameters. Adds database field: MonkeyCantab_GeneralConfig.RewardUsePelletMagazineLamp. ========================= v4.6 (24 Sep 2008) ========================= - change for ACR group: leave incorrect stimulus up on screen during punishment in the following tasks: - Reversals - VisualDiscrimSuperimposed - VisualDiscrimPredefined ... and also specify how long these stimuli are left up for. For each, add: m_bLeaveIncorrectStimUp; m_bLeaveCorrectStimUpForRewardDuration; m_bLeaveIncorrectStimUpForPunishDuration; m_fLeaveCorrectStimDurationSec; m_fLeaveIncorrectStimDurationSec; Database fields added to Reversals_Config, VisualDiscrimPredefined_Config, and VisualDiscrimSuperimposed_Config: LeaveIncorrectStimUp LeaveCorrectStimUpForRewardDuration LeaveIncorrectStimUpForPunishDuration LeaveCorrectStimDuration LeaveIncorrectStimDuration ========================= v4.7 (19 Oct 2008) ========================= - change for ACR group: reversal task: - option to have the misleading feedback specified in a pseudorandom fashion so the numbers of correct/ incorrect trials can be fixed, e.g. x% of every y trials is false-feedback. Since we can't know in advance whether subject will respond correctly/incorrectly, we must say instead that a% of every b correct trials is false-feedback, and c% of every d incorrect trials. - option to force matters such that you can't have two consecutive false-incorrect or two consecutive false-correct trials. - config variables: m_bFalseFeedbackPseudorandom; m_iFalsePseudoBlockSizeCorrect; m_iFalsePseudoBlockSizeIncorrect; m_bFalsePseudoNoTwoConsecutive; - database variables: Reversals_Config.FalseFeedbackPseudorandom Reversals_Config.FalsePseudoBlockSizeCorrect Reversals_Config.FalsePseudoBlockSizeIncorrect Reversals_Config.FalsePseudoNoTwoConsecutive ========================= v5.0 (12 Jan 2009) ========================= - default localhost, not loopback (for Windows Vista compatibility and more general standardization) - no events are requested of the server for object components that aren't touchable (the check that at least one component is touchable is already done, as a warning in the "Configure visual objects" dialogue) ========================= v5.1 (26 Apr 2009) ========================= - fix to probable "superbug" Sep 2008: programs compiled with Visual C++ 6.0, or VC2005 (but not VC2003), we think, exhibit intermittent (~14 per 100,000,000 iterations) errors in converting float to int values, when multiple sound cards are being accessed (as happens when Whisker accesses them) (!). Manifestation of bug: random number generator used by MonkeyCantab returned a silly value and the program seemed to wait for ever. Fix by changing compiler and RNG as below. - fix to minor problem in the help: some screenshot bitmaps show up in the HTML help but not in the PDF. Fix by changing to Help & Manual 5. - potential bug reported 15 Oct 2007: "I have had a small bug reported back to me from DSTL, this is not urgent and could be left as is... When watching the 'Time From Start' when the task is running when it reaches 8-9mins it flips back to 5mins and then back to 8-9mins again! it doesn't affect the running time of the task." - awaiting further details and XML config file 19/10/7 ... no response by 7/4/9; given that, problem closed. - Recompilation on VS2008 with a different RNG (from Boost); previous Mersenne Twister removed. - Define WINVER as 0x500; that excludes NT4 from now on, but allows Win2000. Search for _WIN32_WINNT_WIN2K to see all the numbers. - Local copy of XMLParamIO removed; now using XMLParamIO2. - In DMTS.h, m_fCorrectionPhaseMaxTimeToWaitForRelease changed from BOOL to float. - In database, Reversals_Config.SpatialRandomizedDWORMultiplier changed from Text to Long Integer. - CryptoPP upgraded to v5.6.0. - Conflict between MS default libraries and cryptlib.lib; e.g. msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: char const * __thiscall std::basic_string,class std::allocator >::c_str(void)const " (?c_str@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEPBDXZ) already defined in cryptlib.lib(default.obj) ... MonkeyCantab links MFC/runtime libraries dynamically: Project > Properties > Configuration Properties > C/C++ > Code Generation > Runtime Library = Multi-threaded Debug /MTd, or Multi-threaded /MT ... whereas CryptoPP links it statically: = Multi-threaded /MT ... so rebuild CryptoPP with /MD see http://social.msdn.microsoft.com/forums/en-US/vcgeneral/thread/f1e7a631-c73d-44fa-9165-845fe3adc5a2/ (only need to build the release version of cryptlib) - Then, exceptions being thrown by vector, specifically in its const_iterator begin() const ... called by "v[i]" where v is a vector and i=0 in CSpatialWMTrialSpecification::ConvertVectorToString ... is to do with having a mixture of debug/release libraries (i.e. CryptoPP was release, the rest debug) ... see e.g. http://social.microsoft.com/Forums/en-US/vcgeneral/thread/0f41b727-1146-4520-bfa9-9b88db5e93ab ... built CryptoPP and explicitly copied the output libraries to "cryptlib_debug.lib" and "cryptlib_release.lib" in the CryptoPP main directory in the Whisker tree ... that fixed it. - All seems to work. ========================= v5.2 (8 May 2009) ========================= - Still the sound card versus random number generator problem, it seems. Sanity checking on random number generator. Limits set on return values here (g_RandomNumberForShuffles) and in the random-number functions of WhiskerClientLib (now v3.6). - Craig thinks the problem occurs whenever (1) any program compiled using VC6 is running and (2) multiple sound cards are in use. - Other XML parsers choked on [] in tags, e.g. "m_vucBottomLeftPattern[0]" as a tag in CDisplayComponent_CamcogQuadPattern. ... write changed ... config version changed to 5.2 (strMonkeyCantabConfigVersion) ... read tries (1) new format, (2) old format, so it should still read old configs. - Optimization turned on from next version on. ========================= v5.3 (11 May 2009) ========================= - Reward darkness option for ACR group m_bRewardDarkness m_fRewardDarknessTimeSec - About 2h. ========================= v5.4 (11 May 2009 - 8 June 2009) ========================= - RVIP: Rapid Visual Information Processing task (for Michael Weed, BMS): RVIP.cpp - At this point, I'd like to comment that Microsoft have completely broken the ClassWizard from VC6. So now, adding a variable to a dialogue box doesn't create the DDX_ associations. How lame is that? I'm not the only one: http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/84671994-c294-407a-9e0a-d9c954e7be47 ... ah, no. The thing to do is not to untick "Control variable", but to change from "Control" to "Value" on the right-hand side of the Add Variable Wizard. Which isn't very wizardy. ========================= v5.5 (26 June 2009) ========================= - Amendment to five-choice task (Israeli Institute of Biomedical Research): Original request 26/8/8; final request "In the test: 5 choice reaction time add a "visual discrimination" step. Details: in the last step, instead of a single stimulus appearing in one of the target circles: 1. The 5 target circles appear (as in the original test) 2. Instead of a single stimulus signaling the correct target (response), stimuli will appear in all the target circles. One of the stimuli will be different from the others and will signal the correct response. The correct target will be selected at random. 3. The correct stimulus can be different from the rest on the same modality (e.g square vs circle) or on a different modality (a distinctive feature such as a line on the circle). The library of stimuli can be similar to that used in the visual discrimination/set shifting (ID/ED)" ... which translates to the coding end of things as: - The only change actually being requested, as far as I understand the request, is to have a "non-target" presented at the same time as the target. (The selection of the correct target location at random, and the ability to use any stimuli for target and indeed any stimuli, are already part of the system.) - m_strPhase2NonTargetStimulus ========================= v5.6 (26 June 2009-19 July 2009) ========================= - Modification to DMTS: memory delay now begins at START (not end) of phase 1 reward, if that is used. (Phase 1 reward is not a very sensible option!) - List-length (or list) DMS (for Michael Weed, BMS): ListDMS.cpp Note that the key difference is the ability to do a SAMPLE1-SAMPLE2-SAMPLE3-CHOICE3-CHOICE2-CHOICE1 sort of thing. The question is whether to modify DMS or start from scratch. The results structure (with the need for back-compatibility) more or less answers that. New task. Need: LongestSampleLength() // based on limited holds etc LongestChoiceLength() Then a trial occupies time from SampleStart to SampleStart + LongestSampleLength() and ChoiceStart to ChoiceStart + LongestChoiceLength() and Delay begins at the onset of the sample stimulus and ends at ChoiceStart. So if our first stimulus S1 begins at T1, then: ... the earliest time S1 will end (and the next stimulus can be scheduled) is T1 + InitiationLimHold + SampleResponseLimHold ... the earliest time its choice C1 can begin is T1+Delay, ... the latest time its choice C1 can end is T1+Delay+ChoiceResponseLimHold. For a given delay, we therefore know the temporal structure XXX--------------XXX. The problem is then to take a bunch of these structures and line them up so as to minimize the overall time. The outcome is an order of starts (with start times). For n stimuli, the number of possible orders is P(n,n) = n!. So for 100 trials, we're looking at 10^158 orderings. SEE THOUGHTS ON PAPER ABOUT ALGORITHM. Algorithm then implemented in ListDMSScheduler. - I think the Phase 1 reward option makes the timing too complicated, so I've removed it. Memory delay starts from response (which is when the stimuli vanish). Minimum first-part (sample) length, from the scheduler's point of view = 0 (subject sees stimulus, responds quickly, memory delay kicks off) Maximum first-part (sample) length, from the scheduler's point of view = (m_bRequireLeverToStartTrials ? Seconds_ms(m_fLeverWaitTimeSec) : 0) + (m_bMustTouchPhase1Stimulus ? Seconds_ms(m_fMaxResponseTimePhase1Sec) : Seconds_ms(m_fPhase1StimDurIfNoTouchReqdSec)) + max(m_pControllerConfig->GetMaxRewardTime(), m_pControllerConfig->GetMaxPunishmentTime() ) + Seconds_ms(m_fMinIntertrialTimeSec) (subject is tardy at kicking it off with the lever, then tardy touching, then is rewarded and the memory delay kicks off simultaneously, or is punished and Phase 2 is cancelled) Maximum second-part (choice) length = Seconds_ms(m_fMaxResponseTimePhase2Sec) + max(m_pControllerConfig->GetMaxRewardTime(), m_pControllerConfig->GetMaxPunishmentTime() ) + Seconds_ms(m_fMinIntertrialTimeSec) Therefore, scheduler must assume a full-length first part (in case it is), with the gap equal to the memory delay MINUS the first part Suppose memory delay = ....................... Suppose max first part length = AAAAAAA Suppose max second part length = BBBBBBBBBBB XXXXXXX----------------XXXXXXXXXXXXXXXXX AAAAAAA ^ subject c'd respond here ....................... memory delay takes us this far BBBBBBBBBBB ^ subject c'd respond here ....................... memory delay takes us this far BBBBBBBBBBB ^^^^^^^^^^^^^^^^ so this is the only space we can pre-plan to fit another trial element in THEREFORE, first element length = maximum Phase 1 time gap length = memory delay MINUS maximum Phase 1 time = memory delay MINUS first element length second element length = maximum Phase 2 time PLUS maximum Phase 1 time - enforce at least 1-second gap between trials (to address potential very slight overlaps: advance across-trial scheduling versus on-the-fly within-trial scheduling) - modification to DMTS: "number of trials to avoid repeats over" code was off by one (search for "19/7/9") - database: MonkeyCantab_IndividualEvents.ModuleNumber: BYTE changed to INTEGER new table ListDMS_ChronologicalOrder new table ListDMS_Config new table ListDMS_Results DMTS_Results.Phase2Stimuli: TEXT changed to MEMO ========================= v5.7 (July 2009- 1 Aug 2009) ========================= - Visual concurrent discrimination (RESTRICTED to ACR, Cambridge, at present): ConcurrentDiscrim.cpp Needs #define MONKEYCANTAB_CAMBRIDGE TASK DESCRIPTION IN SOURCE CODE (as this version_tracker is public). - Spatial concurrent discrimination (RESTRICTED to ACR, Cambridge, at present): SpatialDiscrim.cpp Needs #define MONKEYCANTAB_CAMBRIDGE TASK DESCRIPTION IN SOURCE CODE (as this version_tracker is public). - Also, ValidTouches() check added to RVIP. ========================= v5.8 (30-31 Aug 2009) ========================= - External tool convert_stm_to_monkeycantab_xml.pl - Help launcher fixed (after some change in Windows broke it): search for "30/8/2009". Launches the .CHM help file. - Option to stop visual discrimination tasks early. In visual discrimination tasks (VDP, VDS): m_bStopAfter, m_iStopAfterStage In database: VisualDiscrimPredefined_Config.StopAfter VisualDiscrimPredefined_Config.StopAfterStage VisualDiscrimSuperimposed_Config.StopAfter VisualDiscrimSuperimposed_Config.StopAfterStage ========================= v5.9 (Jan 2010) ========================= - fix ListDMS bug: occasionally sits there doing nothing in "In between segments or trials" phase ... caught by special strEvent_SessionEndedSafety, but with debug assert to find out why ... suspect this has been fixed (search for 23Jan2010) - fix ListDMS bug: process occasionally crashes ... found one potential error (search for 23Jan2010) in CListDMSTrialPlan::GetUnoptimizedLength() but suspect never called live with parameters that would crash it ... other found: scheduling failure example: 14:40:39,Client 12,TimerSetEvent 68040 0 StartPhase1_Trial_4 14:40:39,Client 12,TimerSetEvent 95050 0 StartPhase1_Trial_5 ... 14:41:47,Client 12,Event: StartPhase1_Trial_4 ... 14:41:47,Client 12,TimerSetEvent 5000 0 Phase1Omission 14:41:50,Client 12,Event: Phase1Touched 14:41:50,Client 12,TimerClearEvent Phase1Omission 14:41:50,Client 12,TimerSetEvent 20000 0 StartPhase2_Trial_4 14:42:10,Client 12,Event: StartPhase2_Trial_4 14:42:10,Client 12,TimerSetEvent 5000 0 Phase2Omission +++ 14:42:14,Client 12,Event: StartPhase1_Trial_5 14:42:15,Client 12,Event: Phase2Omission Trials are started 27 sec apart. But the first trial takes: up to 5 sec (actually 3 sec) for Phase 1 20 sec delay 5 sec Phase 2 omission ... so scheduler wrong (more precisely, durations sent to scheduler wrong). In this config, Phase 1 max wait = 5sec Phase 2 max wait = 5 sec SCHEDULE IS: Times are in ms. Elements represent trials with Phase 1&2 components (allowing also for subject response times). Element 0 (start1-end1 / start2-end2): 0-7009 / 20000-27009 (memory delay 20000, overall length 27010, second part order 0) Element 1 (start1-end1 / start2-end2): 7010-14019 / 27010-34019 (memory delay 20000, overall length 27010, second part order 1) Element 2 (start1-end1 / start2-end2): 34020-41029 / 54020-61029 (memory delay 20000, overall length 27010, second part order 2) Element 3 (start1-end1 / start2-end2): 41030-48039 / 61030-68039 (memory delay 20000, overall length 27010, second part order 3) +++ Element 4 (start1-end1 / start2-end2): 68040-75049 / 88040-95049 (memory delay 20000, overall length 27010, second part order 4) IT THINKS: firstbit = 7010; secondbit = 7010 ACTUAL: 68040-73040 if you call it 5 sec, then delay from 73030-93040... then 5 sec more... so overlap +++ Element 5 (start1-end1 / start2-end2): 95050-102059 / 105050-112059 (memory delay 10000, overall length 17010, second part order 5) Element 6 (start1-end1 / start2-end2): 112060-119069 / 122060-129069 (memory delay 10000, overall length 17010, second part order 6) Element 7 (start1-end1 / start2-end2): 129070-136079 / 139070-146079 (memory delay 10000, overall length 17010, second part order 7) Element 8 (start1-end1 / start2-end2): 146080-153089 / 156080-163089 (memory delay 10000, overall length 17010, second part order 8) Element 9 (start1-end1 / start2-end2): 163090-170099 / 173090-180099 (memory delay 10000, overall length 17010, second part order 9) Element 10 (start1-end1 / start2-end2): 180100-187109 / 187110-194119 (memory delay 2000, overall length 14020, second part order 10) Element 11 (start1-end1 / start2-end2): 194120-201129 / 201130-208139 (memory delay 2000, overall length 14020, second part order 11) Element 12 (start1-end1 / start2-end2): 208140-215149 / 215150-222159 (memory delay 2000, overall length 14020, second part order 12) Element 13 (start1-end1 / start2-end2): 222160-229169 / 229170-236179 (memory delay 2000, overall length 14020, second part order 13) Element 14 (start1-end1 / start2-end2): 236180-243189 / 243190-250199 (memory delay 2000, overall length 14020, second part order 14) Overall length: 250200. Before optimization, it was 290200. Optimized plan is 86.22% of the original length. (Length reached by Sizist algorithm: 250200. Length reached by Methodologist algorithm: 290200.) ... was a bug in CListDMS::GetScheduleTimings ... which calculated secondpart = max phase 2 length, instead of secondpart = firstpart + max phase 2 length After fix, same schedule: Times are in ms. Elements represent trials with Phase 1&2 components (allowing also for subject response times). Element 0 (start1-end1 / start2-end2): 0-7009 / 20000-34019 (memory delay 20000, overall length 34020, second part order 0) Element 1 (start1-end1 / start2-end2): 34020-41029 / 54020-68039 (memory delay 20000, overall length 34020, second part order 1) Element 2 (start1-end1 / start2-end2): 68040-75049 / 88040-102059 (memory delay 20000, overall length 34020, second part order 2) Element 3 (start1-end1 / start2-end2): 102060-109069 / 122060-136079 (memory delay 20000, overall length 34020, second part order 3) Element 4 (start1-end1 / start2-end2): 136080-143089 / 156080-170099 (memory delay 20000, overall length 34020, second part order 4) IT THINKS: firstbit = 7010; secondbit = 14020; that's better. Element 5 (start1-end1 / start2-end2): 170100-177109 / 180100-194119 (memory delay 10000, overall length 24020, second part order 5) Element 6 (start1-end1 / start2-end2): 194120-201129 / 204120-218139 (memory delay 10000, overall length 24020, second part order 6) Element 7 (start1-end1 / start2-end2): 218140-225149 / 228140-242159 (memory delay 10000, overall length 24020, second part order 7) Element 8 (start1-end1 / start2-end2): 242160-249169 / 252160-266179 (memory delay 10000, overall length 24020, second part order 8) Element 9 (start1-end1 / start2-end2): 266180-273189 / 276180-290199 (memory delay 10000, overall length 24020, second part order 9) Element 10 (start1-end1 / start2-end2): 290200-297209 / 297210-311229 (memory delay 2000, overall length 21030, second part order 10) Element 11 (start1-end1 / start2-end2): 311230-318239 / 318240-332259 (memory delay 2000, overall length 21030, second part order 11) Element 12 (start1-end1 / start2-end2): 332260-339269 / 339270-353289 (memory delay 2000, overall length 21030, second part order 12) Element 13 (start1-end1 / start2-end2): 353290-360299 / 360300-374319 (memory delay 2000, overall length 21030, second part order 13) Element 14 (start1-end1 / start2-end2): 374320-381329 / 381330-395349 (memory delay 2000, overall length 21030, second part order 14) Overall length: 395350. Before optimization, it was 395350. Optimized plan is 100.00% of the original length. (Length reached by Sizist algorithm: 395350. Length reached by Methodologist algorithm: 395350.) - AssertOrWarn() mechanism, currently only used by ListDMS - ListDMS: improvement to Sizist scheduler. - PAL: training option to present n samples and n choice phases, but on all but 1 of the choice phases, use only a single stimulus/location (i.e. not really a choice) so only one of them is difficult. - Have this stimulus picked at random. - This is easiest to implement as a global (not block specification) option. Database: Code: PAL_Config.TrainingOnlyOneRealChoice m_bTrainingOnlyOneRealChoice - PAL: training option in which incorrect choices are ignored (i.e. the stimuli stay on the screen until the subject touches the correct location). - This is easiest to implement as a global (not block specification) option. - Just think about the interaction with "maximum time to wait for responses". Database: Code: PAL_Config.TrainingIgnoreIncorrectChoices m_bTrainingIgnoreIncorrectChoices - MonkeyCantab RVIP task; "time without distractors" option; add option to have this begin at value A and increase by B when the last X trials were all correct (to a ceiling of C); Database: Code: RVIP_Config.TimeWithoutDistractorMethod m_iTimeWithoutDistractorMethod RVIP_Config.TWODStart m_fTWODStart RVIP_Config.TWODIncrement m_fTWODIncrement RVIP_Config.TWODCriterion m_iTWODCriterion RVIP_Config.TWODCeiling m_fTWODCeiling RVIP_Results.TWOD m_vTrialRecord[...].m_dwTWOD - MonkeyCantab MCSRT task; "time for which subject must respond" option in Phase 1; add option to have this begin at value A and increase by B when the last X trials were all correct (to a ceiling of C). [RNC: definition of "correct" is m_bPhase2RespondedCorrectly.] Database: Code: MultipleChoice_Config.Phase1HoldTimeMethod m_iPhase1HoldTimeMethod MultipleChoice_Config.P1HStart m_fP1HStart MultipleChoice_Config.P1HIncrement m_fP1HIncrement MultipleChoice_Config.P1HCriterion m_iP1HCriterion MultipleChoice_Config.P1HCeiling m_fP1HCeiling MultipleChoice_Results.Phase1HoldTimeMs m_vTrialRecord[...].m_dwPhase1HoldTimeMs - Fixed logic error in CThreeChoice::IncomingEvent: could process phase 1 "first response" events more than once. ========================= v6.0 (3 Feb 2010) ========================= - Tightening up the ListDMS scheduling safety margins. ========================= v6.1 (19 Feb 2010) ========================= - Alternative partially on-the-fly ListDMS scheduling system. Michael Weed, BMS. Wants option to set sequence in advance, then schedule nests on the fly, allowing the full use of the memory delay for nesting. What I'm thinking about is dynamic timing of a predetermined sequence. If I try to schedule a nest that doesn't fit, the scheduler rejects it in advance when I'm making the config. Therefore, the order of events is established prior to the start of the session, and we know everything fits. In this case the only thing the program keeps track of is the relationship between events and adjusts the timing of events accordingly. In some sense, it would have to reschedule in real time in that it would look at the time a given event occurred and then look up that event's relation to the next event and use that to determine when to do the next event. The reason it is more time efficient is just tha the gap length is longer, up to almost the whole memory delay with just whatever safety margin you need (you said something about 50 ms), and as we're finding out, shaving a second here and a second there means a lot in monkey land. I hope this doesn't seem pedantic here with my example, but I'm just having trouble conveying this idea, so maybe a concrete example will help: For argument's sake assume that 7 sec is the shortest time feasible for each element with 5 sec LH and one second for either reinforcement / punishment and one second for ITI. For brevity's sake assume no margin of error on timing events. So when you're putting in the delays in the config settings (aka schedule optimizer) it sets the sequence. Rejecting those that don't nest. Using 7 sec from above, the total time for a 2 sec memory delay is then 7+2+7 or roughly 16 sec. So we can nest this in side a 16 sec memory delay. and nest that inside a 30 sec delay. abbreviations: s1s onset = stimulus1 sample onset s1s off = stim1 sample offset (either touch or LH expire) s1c onset = stim1 choice onset s1c offset = stim 1 choice offset (leading to reward or punishment of same length of time) etc In this 3 sample nest the order of events is s1s onset (sample for 30 sec delay) s1s offset s2s onset (sample for 16 sec delay) s2s offset s3s onset (sample for 2 sec delay) s3s offset s3c onset (choice for 2 sec delay) s3c offset s2c onset (choice for 16 sec delay) s2c offset s1c onset (choice for 30 sec delay) s1c offset The order of these events is pre-determined. The timings have distinct parameters also known in advance that can be defined in advance with either fixed numbers (ITI=1sec, s2s onset = s1s offset + 1s) or derived numbers (s3c onset = s3s offset + s3 memory delay). So the program sets the timing of the next event by a look at the timestamp of the current event and either an addition of a fixed variable (i.e. ITI) or a relation to the timestamp of the previous event. This whole nest would be repeated through the session with the next nest starting an ITI after the previous one ends. made up example: s1=30sec, s2=16sec time event calculation 0s s1s onset 0s 3s s1s offset touch at 3s (3 sec lat) 4s s2s onset 3s +1s = 4s 4.5s s2s offset touch at 4.5s (0.5 sec lat) 5.5s s3s onset 4.5s + 1s =5.5s 6s s3s offset touch at 6s (0.5 sec lat) 8s s3c onset 6s + 2s = 8s 10s s3c offset touch at 10s (2 sec lat) reinforce or punish 20.5s s2c onset 4.5s + 16s = 20.5s 22s s2c offset touch at 22s (1.5 sec lat) reinforce or punish 33s s1c onset 3s +30s = 33s 35s s1c offset touch at 35s (2 sec lat) reinforce or punish 37s next nest We know there's always time for the LH to finish and punishment or reward, or the scheduller would reject the nest at the config stage. If I try to enter a nest or overlap that doesn't allow enough time, then the scheduler rejects it and says it won't work, try again. Frankly, if it's easier to program you can have check boxes for nest or overlap or current optimization routine to make this part easier. These monkeys have been training for a year and still can't work with 26 sec as the middle delay. But by next year they will likely need 30-60-90s and the year after that they'll probably need 30, 300, 600. RNC: - if we restrict to nesting (and stacking), we're fine in principle; it's just a question of detail. - overlaps are potentially much trickier. - phase 1 = "1", memory delay = ".", phase 2 = "2", conflict = "+": NEST: can fit second trial inside first's memory delay; actual start time depends on when trial 1 phase 2 ends: *Maximum* possible length of inner trial must fit inside first trial's memory delay. 1111...22 1.2 11...22 1.2 OVERLAP: variability in first trial's phase 1 works in principle: 1111....2222 1111....2222 1....2222 1111....2222 OVERLAP: variability in second trial's phase 1 causes a nightmare: 1111....2222 1111....2222 1....+++2 - is it possible to incorporate overlaps as well as nests, using different times for the two? e.g. 1111.............................................2222 XXXX-----------------------------------------XXXXXXXX ... or, could we schedule completely (nests and overlaps) as follows: FIRST ELEMENT = max phase 1 GAP = memory delay (RATHER THAN memory delay minus firstelementlength; we know that the full memory delay will occur) SECOND ELEMENT = max phase 2 (RATHER THAN max phase 1 plus max phase 1) Then we rustle up a full schedule. (Advantage: can use the same scheduler.) If all trials run to max phase 1 length, the trial proceeds as notionally planned. But whenever a phase 1 is shorter than the max, all subsequent times get brought forward by the amount of the difference. This would mean scheduling (with timers) the first trial off the bat, at time zero, then all other phase 1s could be set up, one by one, at the close of each phase 1. - That sounds feasible. - PROBLEM: as before, with overlaps... 11111...........................2222 1111.........222 1111.......................2222 becomes 11111...........................2222 1.........222 1111.......................+++2 Is the answer to prohibit overlaps for on-the-fly scheduling? Let's do that. - Option to force nests off. - Option to force overlaps off (enforced on for on-the-fly scheduling). - also, correction to Phase 1 latency calculation: was calculated from trial start time, should have been from phase 1 start time (the difference is only relevant for trials starting with a lever press). - the new system starts new trials so quickly that you can double-hit (e.g. start one phase 1 after the successful completion of another); therefore, introduce a minimum gap (equal to MinIntertrialTimeSec, as before) - so, phase1leftovers removed from gap - this system allows reintroduction of option to reward phase 1 (previously visible but nonfunctional as above) - ListDMS: Option to schedule a small list then make multiple copies of it (rather than schedule a large list). Database: Code: ListDMS_Config.ScheduleEachCopyIndependently m_bScheduleEachCopyIndependently ========================= v6.2 (28 Feb 2010) ========================= - fix to dumb bug in the on-the-fly ListDMS scheduler ... see above: "But whenever a phase 1 is shorter than the max, all subsequent times get brought forward by the amount of the difference." ... clearly wrong: schedule 11111...........................2222 1111.........2222 1111.......................2222 becomes 1...........................2222 1111.........2222 1111.......................2222 which should become 1...........................2222 1.........2222 1111.......................2222 but currently does become 1...........................2222 1.........2222 +++ 1111.......................2222 This manifests most readily by creating a nested set (e.g. delays 2, 16, 30 sec) then repeating it with each copy scheduled independently. Bug manifests as phase 2 going missing and warning appearing in the log. So what should we do? Advance all trials later than this one THAT ARE NOT OUTSIDE the innermost nest that the current trial is in. See CListDMS::FirstElementEndingSoScheduleNextIfNecessary. - were also warnings re: ListDMS: FirstElementEndingSoScheduleNextIfNecessary: scheduledfirstelementduration < thistrialfirstelementduration. PROBLEM. Problem is: a) scheduler looks at punishment timings; WAV files count for zero b) Punish() function calls PlayForDuration() and asks it for final duration c) PlayForDuration() returns whatever it's told d) ... so the non-WAV duration gets returned as the WAV length. So you can create this bug by scheduling a WAV file with a long "non-length". Solution: since we can't know the WAV length until the task's running (well, not easily), we can make it explicit that for WAV files, the duration is editable and is the "time the program will wait for the WAV" before moving on, not necessarily the WAV duration. ========================= v6.3 (5 Mar 2010) ========================= - additional "X correct" not "X correct consecutively" options for RVIP_Config.TimeWithoutDistractorMethod MultipleChoice_Config.Phase1HoldTimeMethod ========================= v6.4 (8 Mar 2010) ========================= - Database: ListDMS_Config.SchedulingStrategy (text) Internal: m_iSchedulingStrategy ========================= v6.5 (24 Apr 2010) ========================= - performance update to CPAL::WriteResultsToDatabase ... should have done it like CMonkeyCantabController::WriteEventsToDatabase ... i.e. should do Open / lots of Updates / Close, not lots of {Open/Update/Close}s. ========================= v6.6 (6 May 2010) ========================= - database performance updates for all other tasks ========================= v6.7 (15 May 2010) ========================= - NEW "SHAPE" INPUT REQUIRED. - This is used to deliver manual free rewards (see help). Debouncing to 10 ms (a value hardcoded into the program); see SHAPE_DEBOUNCE_TIME_MS. ========================= v6.8 (19 May 2010) ========================= - Option to enable "shape" digital input from command-line. ========================= v6.9 (29 July 2010) ========================= - per-subtask trial limit in ID/ED tasks ED, Motac: "What it does: the operator select the amount of total trials per SESSION and also stipulate which subtasks to be used (e.g. Sd, sdr, cd, cdr, ids, idsr, eds, edsr). The system allow us to set a criterion which is used to either [progress] from one subtask to another or stop if criterion not reached (e.g. If the animal did not respond corrrectly for 6 consecutive trials within the max 200 trials, stop there. If it did, go ahead with next subtask). What we want: be able to state a maximum amount of trials PER subtask. Thus if we set the total max trials to 200, the animal has a maximum of 200 trials to reach criterion at EACH subtask. If he fails at any subtask, the session is stop[p]ed." Implemented with: m_bMaxTrialsAppliesToSubtasks In database: VisualDiscrimPredefined_Config.MaxTrialsAppliesToSubtasks VisualDiscrimSuperimposed_Config.MaxTrialsAppliesToSubtasks - also fixed to out-by-one error for maximum #trials using harsh correction procedure ========================= v7.0 (21-30 Aug 2010) ========================= - Convert the rest for brevity (operator=, copy to/from dialogue, XML): TouchTraining.cpp SpatialWM.cpp ReinforcementFamiliarization.cpp NewTouchTraining.cpp SimpleSchedules.cpp Reversals.cpp ImpulsiveChoice.cpp MonkeyCantabControllerConfig.cpp - "Kick" function pending testing for potential bug. ========================= v7.1 (30 Aug-6 Sep 2010) ========================= - Latency measurements for non-retractable levers in multiple-choice serial reaction time task. The lever supplied by Campden/Lafayette (and predecessors) is not retractable (e-mail TE to RNC 2 Aug 2010), so the LEVERCONTROL line is usually a dummy. Requested by Motac: - (when "require phase 1 response" is on, and that response is on the lever... the subject must respond on the lever for a certain time...) Record time that subject actually releases lever (allowing calculation of reaction time [stimulus change to hand leaves lever] and movement time [hand leaves lever to hand arrives on target]) - IMPLEMENTATION: MultipleChoice_Config.LeverRetractable (default: true). If this is false, then MultipleChoice_Results.Phase1TimeHeldForMs is the actual hold time (whereas if it's true, or MultipleChoice_Config.CentringResponseDevice is the touchscreen, then the manipulandum, be it a lever or a touchscreen stimulus, vanishes, and so MultipleChoice_Results.Phase1TimeHeldForMs is capped at MultipleChoice_Results.Phase1HoldTimeMs). - In results: change to way MultipleChoice_Results.Phase1TimeHeldForMs is encoded addition of MultipleChoice_Results.Phase1ReleaseTimeMs (redundant but helpful) - To calculate "reaction"/"movement" times: pseudocode: IF MultipleChoice_Config.CentringResponseDevice = "Lever" AND NOT(MultipleChoice_Config.LeverRetractable) AND MultipleChoice_Config.Phase1RespondUntilTarget AND MultipleChoice_Results.Phase1Given AND MultipleChoice_Results.Phase1Responded AND MultipleChoice_Results.Phase2Given AND MultipleChoice_Results.Phase2Responded THEN: phase 1 release time = MultipleChoice_Results.Phase1ReleaseTimeMs overall phase 2 response latency = MultipleChoice_Results.Phase2ResponseLatencyMs reaction time = phase 1 release time - MultipleChoice_Results.Phase2StartTimeMs movement time = MultipleChoice_Results.Phase2ResponseLatencyMs - reaction time - in SQL: SELECT R.*, (R.Phase1ReleaseTimeMs - R.Phase2StartTimeMs) AS reaction_time, (R.Phase2ResponseLatencyMs - reaction_time) AS movement_time FROM MultipleChoice_Config C, MultipleChoice_Results R WHERE C.DateTimeCode = R.DateTimeCode AND C.Subject = R.Subject AND C.Box = R.Box AND C.ModuleNumber = R.ModuleNumber AND C.CentringResponseDevice = "Lever" AND NOT(C.LeverRetractable) AND C.Phase1RespondUntilTarget AND R.Phase1Given AND R.Phase1Responded AND R.Phase2Given AND R.Phase2Responded ; - PAL bug (Merck, emails from Matt Croxall 28/7/10, 4/8/10, 3/9/10) Display stimuli (camcogquadpatterns) displayed at negative coordinates at times, so invisible/partially off screen. Relevant functions: CPAL::NewPresentation -- see below CPAL::GetRectangle -- OK; one ASSERT added CMonkeyCantabController::GetLocationRectNinegrid -- ASSERTs added to all like this CMonkeyCantabController::GetDisplayObject -- OK, does almost nothing anyway CMonkeyCantabControllerConfig::GetDisplayObject -- OK CPredefinedObjects::GetPredefinedDisplayObject -- OK CPredefinedObjects::GetPredefinedPALVariantNumber -- OK CPredefinedObjects::GetPALVariantObject CPredefinedObjects::GetCamcogPatternStimulusModifyingColour -- OK CDisplayComponent_CamcogQuadPattern::SetAttributes -- OK CDisplayObject::AddComponent -- OK CDisplayComponent_CamcogQuadPattern::createCopy -- OK CDisplayComponent_CamcogQuadPattern::CDisplayComponent_CamcogQuadPattern -- OK CDisplayComponent_CamcogQuadPattern::operator= -- OK CLocatedDisplayObject::CLocatedDisplayObject -- does this class need a copy constructor/operator=? ... well, it only has simple objects (apart from e.g. a CDisplayObject member that copies itself) ... and it's handled by pointers in CPAL CLocatedDisplayObject::Display -- OK CDisplayObject::Display[1] -- OK; explanatory comments added [CDisplayObject::DisplaySpecifyingCentre] -- [OK] CDisplayObject::GetTopLeftPoint -- amended CDisplayComponent_CamcogQuadPattern::GetTopLeftPoint -- ASSERT added CDisplayObject::GetBottomRightPoint -- amended CDisplayComponent_CamcogQuadPattern::GetBottomRightPoint -- ASSERT added CDisplayObject::Display[2] -- OK CDisplayComponent_CamcogQuadPattern::GetDefinition -- ASSERT added some ASSERTs: see // TEMPORARY Removed all references to DISPLAYCOMPONENT_BIGGEST_X etc. and improved this. That's in CDisplayComponent_Polygon::GetTopLeftPoint CDisplayComponent_Polygon::GetBottomRightPoint CDisplayObject::GetTopLeftPoint CDisplayObject::GetBottomRightPoint The duff coordinates seen in the screenshots are -128,-1073741901 and -128,4. However, more interesting: The rest of the camcogquadpattern patterns pixel info is all 255. Is this is a dead object in some way. I don't think it was stimulus 48 (which is the solid one). The sequence inferred from the screenshots in both cases is: strEvent_NewPresentation arrives NewPresentation() called ClearObjects() strSampleObjectName used in the object name, so m_ePhase is PAL_PHASE_SAMPLE is one of the ASSERTs meant to be firing, but we're in a release mode, so a null pointer is being used? Changed all ASSERTs here to m_pController->AssertOrWarn() calls. The screenshot of the "part off screen" one (coords -128,4) is the first thing that happens in PAL. ... with no user responses so far ... first stimulus camcog_pal0_63 ... manual testing with this stimulus works fine, debug/release mode... The other follows some _MCC_AssumeFingerRemoved events... Not yet definitively found - not yet replicated! So in progress. - Other bug found: _MCC_AssumeFingerRemoved being sent with zero time ... shouldn't do this - CMonkeyCantabController::SetFingerOn amended. ========================= v7.2 (8-13 Sep 2010) ========================= - Ongoing re PAL stimulus positioning: One log yielded two of these: ~~~ WARNING ~~~ CPAL::NewPresentation - PAL_PHASE_SAMPLE - rect contains negative coordinates at top left [systime 517687961] [07-Sep-2010 (15:03)] Coordinates = -1,073,741,611, -1,073,741,901 In the debug heap, 0xCDCDCDCD Allocated in heap, but not initialized 0xDDDDDDDD Released heap memory. 0xFDFDFDFD "NoMansLand" fences automatically placed at boundary of heap memory. Should never be overwritten. If you do overwrite one, you're probably walking off the end of an array. 0xCCCCCCCC Allocated on stack, but not initialized but the error came from a release-mode program an int is -2,147,483,648 to +2,147,483,647 inclusive... Anyway. Can't find bug yet so: Further AssertOrWarn() calls added to hunt it down. - Add options whereby a touch resets the memory delay and/or time between trials for PAL and DNMTS. (This to cope with a problem with multiple touches, as a way of training subjects out of doing this; the current touchscreen hardware won't support multi-touch modes, otherwise an alternative would be to add UPDD-multitouch support to the Whisker server and ignore all but the first touch.) Database: PAL_Config.TouchResetsITI PAL_Config.TouchResetsDelay PAL_TrialResults.ITIExtendedByTouch PAL_TrialResults.ITITimeMsWithExtension PAL_TrialResults.MemoryDelayExtendedByTouch PAL_TrialResults.MemoryDelayMsWithExtension PAL_TrialResults.ITIStartTimeMs DMTS_Config.TouchResetsITI DMTS_Config.TouchResetsDelay DMTS_Results.ITIExtendedByTouch DMTS_Results.ITITimeMsWithExtension DMTS_Results.MemoryDelayExtendedByTouch DMTS_Results.MemoryDelayMsWithExtension DMTS_Results.ITIStartTimeMs CPAL: m_bTouchResetsITI [1] m_bTouchResetsDelay [2] ... and recording variables as above CDMTS: m_bTouchResetsITI [3] m_bTouchResetsDelay [4] ... and recording variables as above Also new event recording of background touches in PAL at all times (PAL_BackgroundTouched). ========================= v7.3 (7 Oct 2010) ========================= - F1 help works throughout added function CMonkeyCantabDlg::OnHelp that calls CMonkeyCantabApp::StandaloneWinHelp search for 7/10/10 - PAL negative coordinate error found occurring in CMonkeyCantabController::GetLocationRectNinegrid(), so additional warnings added to localize. ========================= v7.4 (14 Oct 2010) ========================= - Work in CMonkeyCantabController (q.v.) to address intermittent floating-point overflow error. ========================= v7.5 (4 Nov 2010) ========================= - More work in CMonkeyCantabController::GetLocationRectNinegrid (q.v.) to address intermittent floating-point overflow error. - Also, added sample PAL queries to database. ========================= v7.51 (5 Nov 2010) ========================= - Yet more work in CMonkeyCantabController::GetLocationRectNinegrid (q.v.) to address intermittent floating-point overflow error. // No errors seen to this point, and ones appear by the end of this function (14/10/10), // with execution going through one of the proper case statements. // Implies the ARITHMETIC is going wrong. // All errors seen are consistent copies of one of the following: // 1. ... contains negative values: l=-2147483648,r=-2147483648,t=-2147483648,b=-2147483448 (eLocationCode=0) [systime 2949712596] [13-Oct-2010 (12:51)] // 2. ... contains negative values: l=49,r=-2147483648,t=37,b=236 (eLocationCode=0) [systime 2950576243] [13-Oct-2010 (13:05)] // 3. ... contains negative values: l=-2147483648,r=-2147483648,t=37,b=-2147483648 (eLocationCode=2) [systime 2950246162] [13-Oct-2010 (13:00)] // 4. ... contains negative values: l=-2147483648,r=-2147483648,t=511,b=-2147483648 (eLocationCode=6) [systime 2951004844] [13-Oct-2010 (13:13)] // 5. ... contains negative values: l=49,r=-2147483648,t=511,b=-2147483648 (eLocationCode=6) [systime 2951435173] [13-Oct-2010 (13:20)] // 6. ... contains negative values: l=-2147483648,r=-2147483648,t=-2147483648,b=-2147483448 (eLocationCode=8) [systime 2949984360] [13-Oct-2010 (12:56)] // 7. ... contains negative values: l=682,r=-2147483648,t=511,b=710 (eLocationCode=8) [systime 2950292632] [13-Oct-2010 (13:01)] // // All contain -2147483648 except two that contain b=-2147483448 (200 different) // -2147483648 = 2^31 (overflow) // // In all cases, from these sort of calls: // m_rectDocumentSize = CRect(0, 0, MONKEYCANTAB_DOCWIDTH-1, MONKEYCANTAB_DOCHEIGHT-1); // we have: // rectWholeDocument.left == 0 // rectWholeDocument.top == 0 // rectWholeDocument.bottom = 749 // rectWholeDocument.right = 999 // width = 999 --- WOULD HAVE EXPECTED 1000... // height = 749 --- WOULD HAVE EXPECTED 750... // and note that I do this: // m_pController->DisplaySetDocumentSize(strPALDocName, MONKEYCANTAB_DOCWIDTH, MONKEYCANTAB_DOCHEIGHT); // so there is a mismatch happening here (internal versus what we tell Whisker) // The manual gives this example: // CRect rect(20, 30, 80, 70); // int nWid = rect.Width(); // // nWid is now 60 // ASSERT(nWid == 60); // So I should use // m_rectDocumentSize = CRect(0, 0, MONKEYCANTAB_DOCWIDTH, MONKEYCANTAB_DOCHEIGHT); // not // m_rectDocumentSize = CRect(0, 0, MONKEYCANTAB_DOCWIDTH-1, MONKEYCANTAB_DOCHEIGHT-1); // However, there's still an arithmetic error. // Error 1: // Error 2: // Error 3: // Error 4: // Error 5: // Error 6: // Error 7: loc=8=NINEGRID_BOTTOM_RIGHT: error is -2147483648 from 0 + (999 * 0.8/3); // // Project > MonkeyCantab Properties > Configuration Properties > C/C++ > Code Generation > Enable floating point exceptions // ... in all builds // ... http://msdn.microsoft.com/en-us/library/aa289157%28VS.71%29.aspx // ... and used "2.0" instead of "2" to force initial conversion to float, for all constants in these functions // And all rectangles made 750x1000, not 749x999 // // 4 Nov 2010: alter width/height to double; explicit casts to remove all compiler warnings here; // simplify switch statement. // 5 Nov 2010: all int changed to long (via definitions: CRect, struct tagRECT, LONG). // Conversion rules: http://msdn.microsoft.com/en-us/library/4bkbbzdx%28VS.90%29.aspx // and http://msdn.microsoft.com/en-us/library/aetzh118%28v=VS.90%29.aspx // Examples of unexpected behaviour: http://www.learncpp.com/cpp-tutorial/44-type-conversion-and-casting/ ========================= v7.6 (10-25 Nov 2010) ========================= - PAL "bug" above looks like it probably isn't a bug: likely FPU failure due to sound card kernel driver bugs (see MonkeyCantab v5.1 and WhiskerServer between v2.12.9 and v2.12.10). Standalone test code was: CRect m_rectDocumentSize = CRect(0, 0, MONKEYCANTAB_DOCWIDTH-1, MONKEYCANTAB_DOCHEIGHT-1); CRect arrayrect[9]; bool success = true; unsigned int numrepetitions = 30000000; for (unsigned int repetition=1; repetition<=numrepetitions; ++repetition) { for (unsigned int location=0; location<=8; ++location) { CRect rect = GetLocationRectNinegrid(m_rectDocumentSize, static_cast(location)); if (repetition == 1) { arrayrect[location].left = rect.left; arrayrect[location].right = rect.right; arrayrect[location].top = rect.top; arrayrect[location].bottom = rect.bottom; CString msg; msg.Format("First repetition of location %d: l=%d,r=%d,t=%d,b=%d", location,rect.left,rect.right,rect.top,rect.bottom); cout << msg << endl; } else { if (rect.left != arrayrect[location].left || rect.right != arrayrect[location].right || rect.top != arrayrect[location].top || rect.bottom != arrayrect[location].bottom) { success = false; CString msg; msg.Format("INCONSISTENCY! Location %d; new l=%d,r=%d,t=%d,b=%d", location,rect.left,rect.right,rect.top,rect.bottom); cout << msg << endl; } } } if (repetition % 100000 == 0) cout << "Completed repetition " << repetition << endl; } if (success) { cout << "Success; all repetitions consistent." << endl; } else { cout << "FAILURE; inconsistencies detected." << endl; } ... and this fails intermittently when Whisker/MonkeyCantab are running ... is likely a sound thing: testing with non-Whisker multiple sound pending - As a by-the-by, best descriptions of signed/unsigned mismatch problems: http://stackoverflow.com/questions/2262728/c89-signed-unsigned-mismatch "signed/unsigned mismatches" can be bad. In your question, you are asking about comparisons. When comparing two values of the same base type, but one signed and one unsigned, the signed value is converted to unsigned. So, int i = -1; unsigned int j = 10; if (i < j) printf("1\n"); else printf("2\n"); prints 2, not 1. This is because in i < j, i is converted to an unsigned int. (unsigned int)-1 is equal to UINT_MAX, a very large number. The condition thus evaluates to false, and you get to the else clause. For your particular example, argc is guaranteed to be non-negative, so you don't have to worry about the "mismatch". http://www.parashift.com/c++-faq-lite/newbie.html http://mu2e.fnal.gov/public/hep/computing/standards/C++FAQ.shtml#comparison - 17/11/10 Some further thoughts. There remains a possibility that we may be able to fix this in software, even though the problem is not in our software. What version of DirectX are you running? It may be worth ensuring that you have DirectX 10 or 11 or higher, as the quickest possible potential fix. The problem might be that DirectX (at least pre-version 10) is mucking up the FPU in some contexts (rather than the sound card drivers on their own), and this can certainly break independently running processes (awful bug though that is). Can't be certain that this is what we're seeing, but it's reasonably likely. The fix is setting CreateFlags.FpuPreserve before some DirectX calls, apparently. References: * example bug: http://www.ogre3d.org/forums/viewtopic.php?t=23155 * good article: http://www.tech-archive.net/Archive/Development/microsoft.public.win32.programmer.directx.graphics/2009-07/msg00009.html * example bug: http://www.gamedev.net/community/forums/topic.asp?topic_id=512463 * good article: http://www.virtualdub.org/blog/pivot/entry.php?id=53 * quick mention: http://ventspace.wordpress.com/2010/01/22/advisory-you-should-probably-use-fpupreserve/ * bug example: http://stackoverflow.com/questions/1967266/stopwatch-returns-integer-after-directx-device-creation * bug example: http://stackoverflow.com/questions/1060158/mdx-slimdx-messes-up-wpf-scrollbars * very clear bug example: http://www.developmentnow.com/g/17_2003_10_0_0_90445/Strange-behavior-with-DirectX.htm * fair article: http://blogs.msdn.com/b/tmiller/archive/2004/06/01/145596.aspx * good illustration: http://pollutingtheweb.blogspot.com/2008/07/managed-directx-forces-single-precision.html * another bug example: http://social.msdn.microsoft.com/Forums/en/gametechnologiesgeneral/thread/a501106c-e1c5-4f47-b867-1fc519fb25be Any fix based on this probably won't prevent other applications using DirectX (e.g. Windows Media Player or whatever) from causing problems, but it might sort out our immediate problems. - See also: http://msdn.microsoft.com/en-us/library/aa289157%28VS.71%29.aspx - re floating-point optimizations DDSCL_FPUPRESERVE as a flag to IDirectDraw7::SetCooperativeLevel: http://msdn.microsoft.com/en-us/library/gg426155%28VS.85%29.aspx ... but not for IDirectSound::SetCooperativeLevel? ... and not for IDirectDraw2::SetCooperativeLevel? C# example of CreateFlags.FpuPreserve: http://www.koders.com/csharp/fid7C3DF05F3DDCBA606F263BFDF865CE733CBE0675.aspx?s=mdef%3Afile - Ah, no... the DirectX stuff looks like it's per-process (see e-mails to/from MRFA 17/11/10), but it is perhaps this: http://msdn.microsoft.com/en-us/library/ff565388%28VS.85%29.aspx ... clear documentation that a kernel-mode driver that fail to wrap even very basic floating-point operations with special code can break "concurrent user-mode applications". ... i.e. a kernel-mode sound driver breaking this rule. FIXED: bug reproduced using Sound Recorder and their Creative Labs SoundBlaster card (exact spec pending) and the testprog1_crect program. MonkeyCantab stimulus presentation problem, and DirectDraw errors, go away when SoundBlaster card is disabled. Finger well and truly pointed. - Also: database bug, intermittent: intermittent error reported by SQL Server ("the supplied value is not a valid instance of type float") on receipt of information from MonkeyCantab via ODBC. - intermittent error with MonkeyCantab talking to an SQL Server database (converted from the supplied Access 97 one). As yet unclear whose fault it is: MonkeyCantab: Error accessing/writing to MonkeyCantab_GeneralConfig table ... The error reported by the database system was: The incoming tabular data stream (TDS) remote procedure call (RPC) protocol stream is incorrect. Parameter 31 (""): The supplied value is not a valid instance of data type float. Check the source data for invalid values. An example of an invalid value is data of numeric type with scale greater than precision. - actual parameter number varies; also seen with 72, 78 - no overlap between MonkeyCantab's RFX_Text calls for this table, and the (SQL Server) database's fields of type float - ?frequent when "when there is a hybrid experiment going on, i.e. 2-2-3-3 or such" (in PAL) ... but it's not coming from the PAL tables... - procedure: run SQL Server 2005 / Management Studio Express create database "CANTAB" execute SQL definition as supplied from Merck (which in turn was autoconverted from Access 97 database with Microsoft SQL Server Migration Assistant for Access v4.2) ... gives errors, but not critical ones add the database as an ODBC server, logging all queries longer than 1 ms (to try to capture all) ... instance of same floating-point problem? Awaiting outcome of sound card fix... they report it appears fixed. So again was an FPU being broken by somebody else. - fixed bug in CMonkeyCantabController::GetLocationRectNinegrid NINEGRID_BOTTOM_RIGHT gave same location as NINEGRID_BOTTOM_MIDDLE bug introduced in v7.5, fixed in v7.6 - ContinuousPerformance task (class CCPT). The database query for signal detection theory: In general: classify as hits, misses, false alarms, correct rejections hit rate H = P(response | target) false alarm rate F = P(response | non-target) Yes/no tasks (Macmillan & Creelman, 1991, "Detection Theory - A User's Guide", pp. 9 and 33): sensitivity d' = z(H) - z(F) bias or criterion c = -0.5[z(H) + z(F)] where z() is the inverse normal distribution function Two-alternative-forced-choice (2AFC) tasks (Macmillan & Creelman, 1991, "Detection Theory - A User's Guide", p. 121): d' = (1/sqrt(2))[z(H) - z(F)] c = as for yes/no tasks = -0.5[z(H) + z(F)] The CPT is an example of a yes/no task (only one stimulus offered at one time). Corrections for proportions of 0 and 1 (M&C p10): several methods are possible; we'll use 0 becomes 1/(2N) 1 becomes 1 - 1/(2N) Draft query CPT_SDT: SELECT DateTimeCode, Subject, Box, ModuleNumber, Stage, AttemptAtStage, COUNT(*) as NumTrials, SUM(IIF(Hit,1,0)) as Hits, SUM(IIF(Miss,1,0)) as Misses, SUM(IIF(FalseAlarm,1,0)) as FalseAlarms, SUM(IIF(CorrectRejection,1,0)) as CorrectRejections, Hits/(Hits+Misses) As HitRate, FalseAlarms/(FalseAlarms+CorrectRejections) As FalseAlarmRate, IIF(HitRate=0,1/(2*NumTrials),IIF(HitRate=1,1-1/(2*NumTrials),HitRate)) as CorrectedHitRate, IIF(FalseAlarmRate=0,1/(2*NumTrials),IIF(FalseAlarmRate=1,1-1/(2*NumTrials),FalseAlarmRate)) as CorrectedFalseAlarmRate, InverseNormalCDF(CorrectedHitRate) AS Z_H, InverseNormalCDF(CorrectedFalseAlarmRate) AS Z_F, (Z_H-Z_F) AS D, -0.5*(Z_H+Z_F) AS C FROM CPT_Results GROUP BY DateTimeCode, Subject, Box, ModuleNumber, Stage, AttemptAtStage ; - uncrustify config: in Visual Studio 2008: a quick and dirty way (NB risk of data loss if unsaved!): Tools > External Tools define one like this: NAME: Uncrustify current file (SAVE IT FIRST) COMMAND: C:\Program Files\universalindentgui\UniversalIndentGUI_win32\indenters\uncrustify.exe ARGUMENTS: -c d:\whisker\uncrustify-rnc.cfg --replace $(ItemPath) INITIAL DIR: $(ItemDir) - link no longer started if we've just finished the last module ========================= v7.7 (26 Mar 2010) ========================= - REINFORCEMENT_INFO_PUNISHMENT_PULSE_MS was 10, but version_tracker indicates it should be 20; changed to 20. ========================= v8.0 (14 Apr 2010 - 2 May 2011) ========================= Some major improvements - in particular, location configuration. - Config version (strMonkeyCantabConfigVersion) changed to 8.0 ... means that it will load, but warn about, older versions. - Slightly breaking changes to multiple XML formats, regrettably; CHECK ALL CONFIGS BEFORE USE (aspects may need re-entering). - Concurrent Discrimination: no longer restricted - Spatial Discrimination: no longer restricted - Generalization of reinforcement system: CReinforcer class ... Reinforcer dialogue ... REINFORCEMENT_INFO line now controlled here (and configurable) - Generalization of sound system: CSoundDetails class ... Sound details dialogue - General parameters dialogue rework - Generalization of location system: CLocationSet class ... Location set dialogue - Impulsive Choice ... reinforcers ... dialogue - coordinate generalization for ImpulsiveChoice (YC) - magazine initiation (with/without magazine light) (YC) ... IMPULSIVE_INITIATIONMETHOD_MAGAZINE ... m_bMagazineLightForInitiation - magazine light as a delay bridging signal (YC) ... m_bMagazineLightBridgesDelay ... CMonkeyCantabController::SetMagazineLampLock = lock to prevent lamp being turned off by the controller if the subject nosepokes in the delay - Better "end ellipsis" settings in dialogue boxes (cosmetic). - XML writing bugfix in ImpulsiveChoice (invalidates old configs re delay/probability vector) - stimulus-based trial initiation for ConcurrentDiscrimation (WFU) - stimulus-based trial initiation for SpatialDiscrimination (WFU) - Database changes: new table MonkeyCantab_SoundConfig new table MonkeyCantab_ReinforcerConfig new table MonkeyCantab_LocationConfig MonkeyCantab_GeneralConfig changed (sounds/reinforcers now defined in MonkeyCantab_SoundConfig/MonkeyCantab_ReinforcerConfig) ImpulsiveChoice_Config changed (reinforcers, magazine lamp) new fields in ConcurrentDiscrimination_Config new fields in SpatialDiscrimination_Config new table MST_Config new table MST_ConfigTargets new table MST_Results new table MST_ResultsStimuli ... and as below - Adjustment to internal scaling of University of Cambridge triangle-based stimuli (in CPredefinedObjects::GetUnivcamTriangleStimulus) to improve stimulus centre alignment. This change will not affect user copies of predefined stimuli (re-copy them from the predefined stimuli if you use copies and want to see the changes). - Multireinforcer Search Task (MST) (with new location system) - "Object test" display window now doesn't request DirectDraw (as a default for systems with buggy DirectDraw implementations, e.g. VirtualBox! DirectDraw implementation bug showed up as multiple copies of stimuli). - SimpleSchedules - convert to new location system (YC) - option to specify maximum and minimum session time (actual session time picked with flat PDF) (YC) ... database field SimpleSchedules_Config.MaxTimeMinutes_B ... MaxTimeMinutes_B is new lower limit ... existing MaxTimeMinutes becomes upper limit - Touch Training - convert to new location system (YC) ... database field TouchTraining_Config.Locations removed - option to deliver initial free reward at the start of the session (YC) ... m_bInitialFreeReward / TouchTraining_Config.InitialFreeReward - option to initiate trials when magazine door triggered (YC) ... m_bRequireLeverToStartTrials / TouchTraining_Config.RequireLeverToStartTrials REMOVED ... m_iInitiationMethod / TouchTraining_Config.InitiationMethod added - option to illuminate magazine light as trial initiation cue (YC) ... m_bMagazineLightForInitiation / TouchTraining_Config.MagazineLightForInitiation - potential bugfixes: some recent tasks had recordset code with "m_DateTimeCode;", not "m_DateTimeCode = CTime(0);" (the former is the buggy MFC default). - Also converted to new location system: Visual Discrimination - Predefined (YC) Visual Discrimination - Superimposed (YC) Reinforcement Familiarization - N/A, no visual stimuli Reversals (YC) ... m_iLeftLocationIfAdjustingForFeeder / Reversals_Results.LeftLocationIfAdjustingForFeeder REMOVED ... m_iMiddleLocationIfAdjustingForFeeder / Reversals_Results.MiddleLocationIfAdjustingForFeeder REMOVED ... m_iRightLocationIfAdjustingForFeeder / Reversals_Results.RightLocationIfAdjustingForFeeder REMOVED ... m_bThreeStimTaskUsedLocationSetB / Reversals_Results.ThreeStimTaskUsedLocationSetB added Concurrent Discrimination ... database field ConcurrentDiscrim_Config.Locations REMOVED ... database table ConcurrentDiscrim_Results altered significantly ... database table ConcurrentDiscrim_ResultsStimuli created Spatial Discrimination ... database table SpatialDiscrim_Results altered significantly ... database table SpatialDiscrim_ResultsStimuli created RVIP DMTS ListDMS MCSRTT (YC) ... database table MultipleChoice_Config - several location-related fields removed ... incidentally, "Too few parameters" from ODBC can mean that the task is trying to write fields that don't exist in the database. CPT ... also, m_fMaxPresentationTimeSec now constrained to be >0 - must be a finite limit to make sense for this task; 0 for "no limit" doesn't make sense (task just sits there waiting for a non-response) ... curious XML read bug (m_vIncorrectStimSpecs not being read) ... yes; if there are existing "NumElements" and "Element_0" nodes, then the XML load routine mis-loads if a second set appear. Probably parseNodes. I'm guessing it's only a problem when they're nested (given that I re-use variable names across tasks and have had no problems there). This is clearly a bug in ParamIO (or my VS2008 hack to it!), since it fails to load when Firefox displays the structure with no problem. Probably just easiest to get rid of the XMLPARAMIO_CLASSVECTORREAD stuff, or add a "uniqueify" string... ... could just use #vec as the uniqueify... yes; see shortcuts.h SWM PAL (YC) - and remove global adjust-for-central-feeder option m_bAdjustForCentralFeeder / MonkeyCantab_GeneralConfig.AdjustForCentralFeeder - and remove old internal grid code - compilation problem: repeated "cannot update program database" errors (for debug mode). Clean didn't help. VS restart didn't help. http://social.msdn.microsoft.com/Forums/en/vclanguage/thread/0ceac3c6-62f6-4fdf-82e1-d41e1b4fcd20 "I have this problem with VS2008 sometimes too. The easiest reliable workaround is to simply switch the debug info to C7 format instead of using the PDB. Find 'Project Options -> C/C++ -> General -> Debug Information Format' and set it to C7. [Project / Properties / Configuration Properties / C/C++ / General / Debug Information Format] - SVN problem: Commit Modified: D:\Whisker\CODE\clients\rnc - cambridge\MonkeyCANTAB\MonkeyCantab database (sample).mdb Sending content: D:\Whisker\CODE\clients\rnc - cambridge\MonkeyCANTAB\MonkeyCantab database (sample).mdb Commit failed (details follow): Checksum mismatch for 'D:\Whisker\CODE\clients\rnc - cambridge\MonkeyCANTAB\.svn\text-base\MonkeyCantab database (sample).mdb.svn-base'; expected: 'b0329a1251121e4ea9a1995a8a11a609', actual: '8f03d67f9f588b8085556d5dbc02cad7' Try a 'Cleanup'. If that doesn't work you need to do a fresh checkout. Proper ways: http://glob.bushi.net.nz/glob/2007/02/14/subversion-checksum-mismatch-easy-workaround/ ... worked Violent ways: http://maymay.net/blog/2008/06/17/fix-subversion-checksum-mismatch-error-by-editing-svnentries-file/ ... didn't work (subsequent checkin attempts failed). ========================= v8.1 (from 3 May 2011) ========================= - max()/min() macro side-effect bug fixed ... affected ConcurrentDiscrim, MST, Reversals, SpatialDiscrim, VDP, VDS ... rewards (though delivered once, thanks to Whisker) were counted twice for these tasks ... effect was that the global #reinforcer limit kicked in at half the number of expected reinforcers ... we had a mixture of those macros and _cpp_min()/_cpp_max(), which look slightly dubious ... now everything uses #define NOMINMAX, #include , then std::max() and std::min() ... note reasons: http://www.devx.com/tips/Tip/14540 Where are std::min() and std::max()? The Standard Library defines the two template functions std::min() and std::max() in the header. In general, you should use these template functions for calculating the min and max values of a pair. Unfortunately, Visual C++ does not define these function templates. This is because the names min and max clash with the traditional min and max macros defined in . As a workaround, Visual C++ defines two alternative templates with identical functionality called _cpp_min() and _cpp_max(). You can use them instead of std::min() and std::max().To disable the generation of the min and max macros in Visual C++, #define NOMINMAX before #including . http://forums.devx.com/archive/index.php/t-92352.html - an aside: when VS2008 loses the Find window: C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\devenv /resetsettings ... but that loses all sorts of other things (like search directories!) ... so probably better: Windows > Reset Window Layout - proper use of precompiled headers (/Yu) through stdafx.h: huge reduction in compilation time - C2471 errors: Note KB/hotfix: http://archive.msdn.microsoft.com/KB946040 http://support.microsoft.com/kb/946040 = link to the fix - Display caching for initiation stimulus, and fix to "finger on" detection code: ConcurrentDiscrim, SpatialDiscrim, MST - Reversals - option to illuminate magazine light as cue for trial initiation (YC) - support for magazine door trial initiation (YC) - initiation limited hold - initiation latency m_bRequireLeverToStartTrials / Reversals_Config.RequireLeverToStartTrials REMOVED m_iInitiationMethod / Reversals_Config.InitiationMethod ADDED m_bMagazineLightForInitiation / Reversals_Config.MagazineLightForInitiation ADDED m_fInitiationLimHold / Reversals_Config.InitiationLimHold ADDED m_bInitiated / Reversals_Results.Initiated ADDED m_dwInitiationLatency / Reversals_Results.InitiationLatencyMs ADDED - DMTS - option to illuminate magazine light as cue for trial initiation (YC) - support for magazine door trial initiation (YC) - initiation limited hold - initiation latency m_bRequireLeverToStartTrials / DMTS_Config.RequireLeverToStartTrials REMOVED m_iInitiationMethod / DMTS_Config.InitiationMethod ADDED m_bMagazineLightForInitiation / DMTS_Config.MagazineLightForInitiation ADDED m_fInitiationLimHold / DMTS_Config.InitiationLimHold ADDED m_bInitiated / DMTS_Results.Initiated ADDED m_dwInitiationLatency / DMTS_Results.InitiationLatencyMs ADDED - VDS - option to illuminate magazine light as cue for trial initiation (YC) - support for magazine door trial initiation (YC) - initiation limited hold - initiation latency m_bRequireLeverToStartTrials / VisualDiscrimSuperimposed_Config.RequireLeverToStartTrials REMOVED m_iInitiationMethod / VisualDiscrimSuperimposed_Config.InitiationMethod ADDED m_bMagazineLightForInitiation / VisualDiscrimSuperimposed_Config.MagazineLightForInitiation ADDED m_fInitiationLimHold / VisualDiscrimSuperimposed_Config.InitiationLimHold ADDED m_bInitiated / VisualDiscrimSuperimposed_Results.Initiated ADDED m_dwInitiationLatency / VisualDiscrimSuperimposed_Results.InitiationLatencyMs ADDED - VDP - option to illuminate magazine light as cue for trial initiation (YC) - support for magazine door trial initiation (YC) - initiation limited hold - initiation latency m_bRequireLeverToStartTrials / VisualDiscrimPredefined_Config.RequireLeverToStartTrials REMOVED m_iInitiationMethod / VisualDiscrimPredefined_Config.InitiationMethod ADDED m_bMagazineLightForInitiation / VisualDiscrimPredefined_Config.MagazineLightForInitiation ADDED m_fInitiationLimHold / VisualDiscrimPredefined_Config.InitiationLimHold ADDED m_bInitiated / VisualDiscrimPredefined_Results.Initiated ADDED m_dwInitiationLatency / VisualDiscrimPredefined_Results.InitiationLatencyMs ADDED - ConcurrentDiscrimination - support for magazine door trial initiation (YC) - option to illuminate magazine light as cue for trial initiation (YC) new method to m_iTrialInitiationMethod m_bMagazineLightForInitiation / ConcurrentDiscrim_Config.MagazineLightForInitiation ADDED m_fInitiationLimHold / ConcurrentDiscrim_Config.InitiationLimHold ADDED m_bInitiated / ConcurrentDiscrim_Results.Initiated ADDED m_dwInitiationLatency / ConcurrentDiscrim_Results.InitiationLatencyMs ADDED - option to lock correct:incorrect vectors together, so it can do 8-*pair* concurrent discrimination (i.e. fixed pairs) (YC inferred) - MCSRT - option to illuminate magazine light as cue for trial initiation (YC) - support for magazine door trial initiation (YC) new method to m_iCentringResponseDevice new method THREECHOICE_P1HMETHODS_BLIP m_bMagazineLightForInitiation / Reversals_Config.MagazineLightForInitiation ADDED - define a period of time when the response locations remain indicated on the screen, up to the point of reward collection (for systems where this definable) or for a defined time; so responses to them can be measured and classified as perseverative (YC); (RNC: ... after correct and incorrect trials, but not after omissions) - option to punish perseverative responding (YC); m_iNumPerseverative / MultipleChoice_Results.NumPerseverative m_strPerseverativeLocations / MultipleChoice_Results.PerseverativeLocations m_bPermitPerseverative / MultipleChoice_Config.PermitPerseverative m_iPerseverativeMethod / MultipleChoice_Config.PerseverativeMethod m_fPerseverativeTimeSec / MultipleChoice_Config.PerseverativeTimeSec m_bPunishPerseverative / MultipleChoice_Config.PunishPerseverative - new two-choice Conditional Visual Discrimination task (YC) - CVD - {if A, go left; if B, go right} - ADDITIONAL task methods capable of two-choice vigilance task: {target/nontarget stimulus appears... two flankers appear, which are response manipulanda... subject must respond left for targets and right for nontargets, or vice versa} ... can use a blank stimulus as a non-target ... for this task type, spontaneous trial manipulation is appropriate ... when trial starts, stimulus starts ... option for delay before manipulanda appear (can be zero for simultaneous) ... option to curtail stimulus before end of responding time (specify stimulus duration or 0 for "full") - reversal option (all "go-left" stimuli become "go-right" and vice versa) - correction trial procedure, as for existing reversal learning task - ImpulsiveChoice option to repeat omission trials: ImpulsiveChoice_Config.RepeatOmissionTrialsForced / m_bRepeatOmissionTrialsForced ImpulsiveChoice_Config.RepeatOmissionTrialsFree / m_bRepeatOmissionTrialsFree ImpulsiveChoice_Results.TrialOverallIgnoringRepetition / m_iTrialOverallIgnoringRepetition ImpulsiveChoice_Results.RepetitionTrial / m_bRepetitionTrial ImpulsiveChoice_Results.TrialInBlockIgnoringRepetition / m_iTrialInBlockIgnoringRepetition ========================= v8.2 (15 Aug 2011) ========================= - Stopping criterion for Concurrent Discrimination task. m_bStoppingCriterion; ConcurrentDiscrim_Config.StoppingCriterion m_iStoppingCriterionX; ConcurrentDiscrim_Config.StoppingCriterionX m_iStoppingCriterionY; ConcurrentDiscrim_Config.StoppingCriterionY CConcurrentDiscrim::PerformanceStoppingCriterionMet() ========================= v8.3 (22 Sep 2011 - 30 Oct 2011) ========================= - reinforcer-associated visual stimulus time wasn't contributing to maximum reinforcer time in CMonkeyCantabController::DeliverReinforcer - Date/time string stored in textfile now includes seconds fields. See g_strDateTimeFormat, g_strTimeFormat. - option to shuffle modules at main config screen - network traffic: removed redundant caching on/off statements: RVIP, ThreeChoice - network traffic: removed redundant ReportStatus() calls; see bInteresting - New task: stimulus-stimulus PAL (SSPAL); class CSSPAL. (Description e-mails: from CSC 13/10/11 onwards.) New database tables: SSPAL_Config SSPAL_Results SSPAL_StimulusPairs - in DMTS, m_iNumDistractors (Phase2NumDistractors in the output) was not copied correctly from the previous trial for correction trials. (Affects output only; a -1 was output; task unaffected.) ListDMS unaffected (no correction trials). ========================= v8.4 (1 Nov 2011 - 4 Nov 2011) ========================= - SSPAL: delay stimulus edit box now freely editable (so you can blank it) - SSPAL: make delay stimulus properly optional! =============================================================================== v8.5 (23 Nov 2011) =============================================================================== - bugfix: dialogue value of m_fLeaveUnsuccessfulStuffDurationSec in CVD was being converted to 1/0 - CVD config/result variables converted to X-macro style for autoconsistency - SWM/SOSS config/result variables converted to X-macro style for autoconsistency - SWM/SOSS: more flexibility in screen-blanking time (currently: m_bBlankScreen, m_fBlankScreenTimeSec) (see TE email 21 Nov 2011). They'd like a list of possible screen-blanking times (akin to the "Levels" section of DMTS), blanking time being fixed for a given trial but variable across trials, with the options (a) either to run them all in sequence or to pick randomly (in draw-without-replacement fashion), and (b) to multiply a short user-specified list by a fixed number (e.g. 10 in the example given). results: new field m_dwBlankScreenTimeMs = SpatialWM_Results.BlankScreenTimeMs config: removed m_bBlankScreen new fields m_iScreenBlankMethod = SpatialWM_Config.ScreenBlankMethod enum NONE, FIXED_TIME, SEQUENTIAL_FROM_LIST, SHUFFLED_FROM_LIST (FIXED_TIME uses existing m_fBlankScreenTimeSec) m_vfBlankingTimes = SpatialWM_Config.BlankingTimes m_iBlankingTimeDWORMultplier = SpatialWM_Config.BlankingTimeDWORMultplier - SWM/SOSS: correction procedure didn't seem very correcting (not an exact copy of previous trial); redone. - SWM/CVD: will silently revert enum options so CHECK after config load (variables renamed m_i* to m_e*). Config version increase was omitted. =============================================================================== v8.6 (1 Dec 2011 onwards) =============================================================================== - increase config version number to 8.6 - reverted SWM/CVD variable names (for config), so those who never used v8.5 won't notice and those who did will be warned - more X-macro conversion NOTE: if debugging problems, generate *.i files with preprocessor output: Project > Properties > ... Preprocessor - X-macro conversion: reinforcement familiarization - X-macro conversion: touch training - X-macro conversion: concurrent discrimination - X-macro conversion: CPT - X-macro conversion: DMTS - X-macro conversion: RVIP - RVIP changes m_strTargetAreaMarker becomes m_strTargetAreaMarker1 + m_strTargetAreaMarker2 in database table RVIP_Config, TargetAreaMarker replaced by TargetAreaMarker1 + TargetAreaMarker2 - X-macro conversion: ListDMS - X-macro conversion: VDP - X-macro conversion: VDS - X-macro conversion: impulsive choice - X-macro conversion: MST - X-macro conversion: Spatial Discrimination - X-macro conversion: SSPAL - X-macro conversion: MCSRT - X-macro conversion: SimpleSchedules checked screen update speed -- imperfections on console copy (you see some scale bars appear/disappear quickly) but fine on full-screen view (if this had been a problem, could have moved from document-switching to object-switching, but no need) - X-macro conversion: reversals also: new field in Reversals_Results: ReinforcementStartTimeMs - X-macro conversion: PAL =============================================================================== v8.7 (from 1 Jan 2012) =============================================================================== - SSPAL: (1) Cue presentation method becomes one of {await response / fixed time}. = new: m_iCuePresentationMethod / SSPAL_Config.CuePresentationMethod (2) If "fixed time" is selected, it behaves as the current task (using "Cue presentation time"). = existing m_fCuePresentationTimeSec (3) If "await response" is selected, then a limited hold; if the subject doesn't respond in that time, the trial is abandoned. = new: m_fCueLimitedHoldSec / SSPAL_Config.CueLimitedHoldSec (4) A set of appropriate recording variables (responded or not, latency, etc.) = new: m_bRespondedToCue / SSPAL_Results.RespondedToCue = new: m_dwCueResponseLatencyMs / SSPAL_Results.CueResponseLatencyMs = new: m_dwChoiceBeganAtMs / SSPAL_Results.ChoiceBeganAtMs Also removed spurious ET_DIGITALEVENT_IN_LEVERPRESSED event upon failure to initiate trial. Also, previous response latency (ResponseLatencyMs) was mistimed (from trial start, not choice start); fixed. =============================================================================== v8.8 (5 Jan 2012) =============================================================================== - bug fixed in SWM symptom was: crash immediately upon starting SWM with non-scheme method m_vTrialRecord.back() was used with an empty vector, in CSpatialWM::NewTrial() =============================================================================== v8.9 (from 19 Jan 2012) =============================================================================== - cosmetic changes to CPT dialogue to clarify "Number of correct trials per block" to "Number of correct-stimulus trials presented per block". - CPT bugfix: running out of time on a stage didn't end the whole task (and should have). - CPT bugfix: loose stage timer (so the stage after a successful stage could die prematurely). - CPT: addition of "Time limit for each attempt". CCPTStage::m_fAttemptTimeLimitSec / CPT_ConfigStages.AttemptTimeLimitSec strEvent_EndAttempt =============================================================================== v9.0 (24-27 Jan 2012) =============================================================================== - 23 Jan 2012: "-1.#IND" appearing in XML config files for RVIP. See http://www.johndcook.com/IEEE_exceptions_in_cpp.html Seen on one computer only. Seen in: m_fLimitedHoldSec, m_fMinTimeWithoutDistractorsSec, m_fMaxSessionTimeMin. Seen in MonkeyCantab v8.6 and a preceding version (?arising spontaneously in both, or with old config files?). MW suspects that loading a config works variably. Detection code added; however, it looks like the XML load procedure already preconverts this to -1. UNDER INVESTIGATION: could be floating-point problem on one specific computer, rather than a bug (note previous floating-point corruption by a sound driver; see 10-25 Nov 2010). - CPT bugfix: loose attempt timer (still) on change of stage. =============================================================================== v9.1 (22 Mar 2012) =============================================================================== - Fixed a bug introduced into Reversals: the HARSH correction procedure failed to show any stimuli (mis-reference to the previous trial by CReversals::GetNextTrialSettings(). =============================================================================== v9.2 (to 22 May 2012) =============================================================================== - 29 May 2012: Code changes (no functional change) to reflect WhiskerClientLib v4.1. Moved many functions to WhiskerSDK's support.* from MonkeyCantab's shortcuts.* - Generates no compiler warnings now. - CPT bugfix: CCPT::IsCriterionPassed() didn't restrict "consecutive correct" checking to current attempt. - CPT bugfix: if the stage timed out in the ITI immediately following the correct response that should have passed the stage, the timeout trumped the win (incorrectly). Fixed in logic of CCPT::NewTrial(). =============================================================================== v9.3 (from 15 June 2012) =============================================================================== - Reversals: progression criterion for the first reversal, separate from subsequent - m_iReverseCriterionXFirst, Reversals_Config.ReverseCriterionXFirst - m_iReverseCriterionYFirst, Reversals_Config.ReverseCriterionYFirst - Reversals: summary information for each discrimination within a session - m_iReversalsSoFar, Reversals_Results.ReversalsSoFar - demo query Reversal_QuickSummary - elaborated CReversals::GetEndingString() for on-screen summary - Reversals: after reinforcement, distinguish touches to the stimulus (when left on screen) from touches to the background. (NB: previously, "leftover stimulus touches" were just ignored.) - m_iLeftoverStimulusTouches, Reversals_Results.LeftoverStimulusTouches =============================================================================== v9.4 (from 17 July 2012) =============================================================================== - Database recording of trial repeat (Y/N and repeat number) in PAL. - Support for STIMULUS_INFO line in CPT - search for StimulusInfoOn() - Support for STIMULUS_INFO line in DMTS - search for StimulusInfoOn() =============================================================================== v9.5 (from 14 Aug 2012) =============================================================================== - Block/m_iBlock field for PAL. - TrialGroup/m_iTrialGroup field for PAL. Note that RepeatNum is a "trial within group" field. - TrialGroupWithinBlock/m_iTrialGroupInBlock field for PAL. - Query PAL_AttemptsPerTrialGroup SELECT T.DateTimeCode, T.Subject, T.Box, T.ModuleNumber, T.TrialGroup, T.NumStimuli, T.NumExtraChoiceLocations, MAX(T.RepeatNum) + 1 AS NumAttempts FROM PAL_TrialResults AS T GROUP BY T.DateTimeCode, T.Subject, T.Box, T.ModuleNumber, T.TrialGroup, T.NumStimuli, T.NumExtraChoiceLocations ; - Query PAL_FindFirstAndLastAttempt ~~~ NOTE THAT THE FIRST AND LAST ATTEMPT CAN BE THE SAME TRIAL! BEWARE, FOR STATISTICS ~~~ SELECT T.DateTimeCode, T.Subject, T.Box, T.Trial, T.TrialGroup, T.NumStimuli, T.NumExtraChoiceLocations, T.ChoiceCorrect, T.ChoiceIncorrect, T.ChoiceOmissions, A.NumAttempts, IIF(T.RepeatNum = 0, 1, NULL) AS IsFirst, IIF(T.RepeatNum = A.NumAttempts - 1, 1, NULL) AS IsLast FROM PAL_TrialResults AS T, PAL_AttemptsPerTrialGroup AS A WHERE T.DateTimeCode = A.DateTimeCode AND T.Subject = A.Subject AND T.Box = A.Box AND T.ModuleNumber = A.ModuleNumber AND T.TrialGroup = A.TrialGroup ; - Query PAL_OverallAccuracyAndOmissions SELECT Subject, NumStimuli, NumExtraChoiceLocations, 100 * SUM(ChoiceCorrect) / SUM(ChoiceCorrect + ChoiceIncorrect) AS PctCorrect, SUM(ChoiceOmissions) AS TotalChoiceOmissions FROM PAL_TrialResults GROUP BY Subject, NumStimuli, NumExtraChoiceLocations ; - Query PAL_AccuracyAndOmissionsAtFirstAndLastAttempt +++ NOTE THAT THE FIRST AND LAST ATTEMPT CAN BE THE SAME TRIAL! BEWARE, FOR STATISTICS +++ SELECT Subject, NumStimuli, NumExtraChoiceLocations, SUM( IIF(IsFirst, ChoiceCorrect, 0) ) AS ChoiceCorrect_First, SUM( IIF(IsFirst, ChoiceIncorrect, 0) ) AS ChoiceIncorrect_First, 100 * ChoiceCorrect_First / (ChoiceCorrect_First + ChoiceIncorrect_First) AS PctCorrect_First, SUM( IIF(IsFirst, ChoiceOmissions, 0) ) AS TotalChoiceOmissions_First, SUM( IIF(IsLast, ChoiceCorrect, 0) ) AS ChoiceCorrect_Last, SUM( IIF(IsLast, ChoiceIncorrect, 0) ) AS ChoiceIncorrect_Last, 100 * ChoiceCorrect_Last / (ChoiceCorrect_Last + ChoiceIncorrect_Last) AS PctCorrect_Last, SUM( IIF(IsLast, ChoiceOmissions, 0)) AS TotalChoiceOmissions_Last FROM PAL_FindFirstAndLastAttempt WHERE IsFirst OR IsLast GROUP BY Subject, NumStimuli, NumExtraChoiceLocations ; - Query PAL_AttemptsByTrialType SELECT Subject, NumStimuli, NumExtraChoiceLocations, AVG(NumAttempts) AS AvgNumAttempts FROM PAL_AttemptsPerTrialGroup GROUP BY Subject, NumStimuli, NumExtraChoiceLocations ; - Query PAL_RT_by_trial_type SELECT T.Subject, T.NumStimuli, T.NumExtraChoiceLocations, AVG(P.ResponseLatencyMs) AS AvgResponseLatencyMs FROM PAL_TrialResults AS T INNER JOIN PAL_IndividualPresentations AS P ON ( T.DateTimeCode = P.DateTimeCode AND T.Subject = P.Subject AND T.Box = P.Box AND T.ModuleNumber = P.ModuleNumber AND T.Trial = P.Trial ) WHERE P.Responded GROUP BY T.Subject, T.NumStimuli, T.NumExtraChoiceLocations ; - JV notes that SSPAL task can mimic Sakai & Miyashita (1991) = PMID 1944594. - SSPAL (cosmetic): relabel choice limited hold slightly (m_fMaxResponseTimeSec) - SSPAL: touching something other than a stimulus can abort the trial as a failure m_bBackgroundTouchesAbort / SSPAL_Config.BackgroundTouchesAbort - SSPAL: options to repeat failed trials up to n times m_bRepeatFailedTrials / SSPAL_Config.RepeatFailedTrials m_iRepeatFailedTrialsUpTo / SSPAL_Config.RepeatFailedTrialsUpTo m_bTrialFailed / SSPAL_Results.TrialFailed m_bTrialSucceeded / SSPAL_Results.TrialSucceeded m_bIsRepeat / SSPAL_Results.IsRepeat m_iRepeatNum / SSPAL_Results.RepeatNum m_iTrialGroup / SSPAL_Results.TrialGroup m_bFailedForBackgroundTouch / SSPAL_Results.FailedForBackgroundTouch =============================================================================== v9.6 (from 25 Sep 2012) =============================================================================== - Option to reward cue presentation in SSPAL (see emails 24-26 Sep 2012). IDC_CSSPAL_REWARDCUERESPONSE m_bRewardCueResponse SSPAL_Config.RewardCueResponse - SSPAL: re option where background touches terminate the trial: this applied to moves on the background, not just first touches, and that meant the task was oversensitive: when the cue was removed, the finger is usually then on the background through no fault of the subject. So only background NEW TOUCHES (not slides/moves) are now punished in that way. ... background "moves" also no longer count towards the ITITouches total - AmbiguousCue task (restricted) ... modified CMonkeyCantabController::DeliverReinforcer and added CMonkeyCantabController::AbortReinforcer CMonkeyCantabController::StopSound in DeliverReinforcer, added missing: t = std::max(t, dwPump2Time); ... and some other minor changes - SVN revisions around 1673. =============================================================================== v9.7 (to 21 Nov 2012) =============================================================================== - rename AmbiguousCue probe stimuli when probes are deleted/moved up/moved down ... done in CAmbiguousCueParamsDlg::UpdateProbeList() - fixed PAL bug (introduced with changes in grid configuration): inappropriate "This block has no valid trials" message. Message is a consequence of CPALBlockSpecification::IsValid() Invalid data member was CPALBlockSpecification::m_iGridSize ... default constructor value 0; default copy constructor ... written by CPALBlockSpecification::SetGridSize ... called by (a) CPALParamsDlg::ResetSchemeGridSizes and (b) CPAL::ResetSchemeGridSizes ... (a) called by CPALParamsDlg::OnBpalDefineGrid() ... (b) called by CPAL::SetGridConstants() ... called by CPAL::CPAL() and CPAL::ReadXMLDefinition() ... the call to IsValid() from CPalBlockSpecDlg::EnsureAppropriateThingsUpdated() works fine for a new blockspec ... because it makes its own CPALBlockSpecification with a grid size of m_locsets[m_iGridType].Size() PROBLEM IS: CPALBlockSpecification::UserEditDefinition() not writing m_iGridSize =============================================================================== v9.8 (5 Dec 2012) =============================================================================== - PAL: ability to duplicate/randomize blocks. ... in PalDefineSchemeDlg.cpp ... button "Manifold blocks" (verb "make maifold, multiple; multiply impressions or copies of" ... button "Shuffle blocks" - PAL_SampleCorrectAndOmissions query =============================================================================== v9.9 (from 13 Feb 2013) =============================================================================== - These changes PARTIALLY BREAK old CPT config files; YOU SHOULD RECHECK ALL CONFIGS MANUALLY AFTER LOADING. Config version changed to 9.9, so the program will warn you. - The database table CPT_ConfigIncorrectStimuli is RENAMED CPT_ConfigStimuli. - CPT: more flexibility for "maximum stimulus presentation time" ... logical consequence of which, to avoid losing any flexibility, is: ... change so that a list of stimuli is specified, each with (correct? stimulus? #trials? max presentation time?) - CPT: response can occur after stimulus offset (i.e. option to have constant response window regardless of varying stimulus duration) ... m_fMinResponseWindowSec / CPT_Results.MinResponseWindowMs - CPT: background stimulus throughout session ... configured as a per-stage option, as that allows maximum flexibility ... CCPTStage::m_strBackgroundStimulus / CPT_ConfigStages.BackgroundStimulus - CPT: there was some oddness: help said you could specify maximum time for stage, but if you didn't (0), you had to specify a maximum time limit "for each stimulus" -- but that didn't make sense; you have to be able to not-respond, so you always have to have a maximum time per stimulus -- should have said "per attempt" (i.e. overall stage limit, or a time limit for each attempt). =============================================================================== v10.0 (28 Feb 2013) =============================================================================== - trivial bugfix: SSPAL started the Marker 1 sound twice at the start of a trial. =============================================================================== v10.1 (1 Apr 2013 to 21 May 2013) ===============================================================================vh - all tasks: autostop facility ... plus user alert for all stops (garish yellow dialogue box + sound) - CPT: strEvent_StimulusOverButContinueToAllowResponding wasn't being cleared (see "2013-04-15") - CPT: still unsure why 14.157s response was accepted ... ET_CPT_STIMULUSTOUCHED then ET_CPT_STIMULUSENDED at 14.157s in trial ... suggests tr.m_dwMaxStimulusDurationMs too large ... let's retry with that event being cleared properly - strict touch support verified/added (and documented in the help) for: ACT - OK CD - tweaked (minor), OK CVD - tweaked (minor), OK CPT - added, now OK IC - added, now OK ListDMS - tweaked (minor), OK MST - tweaked (minor), OK RVIP - tweaked (minor), OK SpatialDiscrim - tweaked (minor), OK SSPAL - tweaked, OK Strict touch support equates to appropriate use of AllowTouches(), SetFingerOn(), SetFingerOff() - Touch training bug fixed: lick/pellet latencies were only being recorded in the ITI, not during the reinforcement phase. =============================================================================== v10.2 (4 Jun 2013) =============================================================================== - Database transaction support (BeginTrans, CommitTrans, Rollback) =============================================================================== v10.3 (18 Jun 2013) =============================================================================== - bugfix to monkeycantab.com, the pre-launcher =============================================================================== v10.4 (2 Sep 2013) =============================================================================== - removed all "using namespace std;" calls, even sub-function -- should fix compilation problem with identity versus std::identity - SSPAL option: background touches in ITI restart ITI - m_bITIBackgroundTouchesRestartITI, ITIBackgroundTouchesRestartITI - ITITimeMs renamed ITITimeMsPlanned - new field ITITimeMsActual =============================================================================== v10.5 (20 May 2014 to 1 June 2014) =============================================================================== - ship PDB - "using" directives - moved to CryptoPP 5.6.2 - code cleanup - compile with /W4 cleanly - ImpulsiveChoice: RecordInitiation, RecordChoice, RecordCollection had -1 rather than 0 as the default for the latency when there was no response (= signed/unsigned mismatch). Fixed to 0 (also the constructor default). - RAII methods, inc. check for new/delete/malloc/free - uncrustify - cosmetic file headers - cppcheck --force *.h *.cpp - ISO-8601 format for textual date output (but timezone format is poor so omitted) - ModuleFactory - HAMMOND_CONTINGENCY schedule (restricted) - FrequencyHz() and musical note dialogue - Possible Reversals bug: some trials failing to initiate spontaneously (apparently always the first one of a session). - Soak test: start @ 2014-05-31T20:32 period about 4 seconds no problems to 22:01 = approx. 1,335 cycles ... POTENTIALLY STILL A PROBLEM: MONITOR. ... no further reports to 2021-11-23. (Likely related to FPU corruption/dodgy kernel sound driver?) - Occasional debug-mode on-exit-only crash: 0xfeeefeee access violation from ~CMclCritSec, called from CWhiskerTask, used as a temporary in CReinforcementSchedule Probably this: http://stackoverflow.com/questions/3373193/why-is-vector-deleting-destructor-being-called-as-a-result-of-a-scalar-delete Hm. Maybe a module is being copied, and therefore its CReinforcementSchedule is being copied, and the CWhiskerTask implements a crappy member-wise copy so it breaks. If so, switching to a shared_ptr would be a quick hack to make this problem go away, probably. And the better answer would be to implement a proper copy constructor for CWhiskerTask. SEEMS TO HAVE HELPED. - *** OUTSTANDING: improve CWhiskerTask copy constructor. - ConcurrentSchedules task (restricted) - NOTE that to implement a single-reinforcer contingent schedule and a second noncontingent schedule, you can do that (either with no manipulandum required, or for schedules that can be jointly contingent and noncontingent, with that schedule configured for P(outcome | action) = 0 and a blank manipulandum. - NOTE: this task IGNORES ANY POTENTIAL FOR CROSS-SCHEDULE REINFORCER CONFLICTS (i.e. if you use the same device on both schedules, it's your lookout). - CReinforcementSchedule no longer tracks timeout information (pointlessly). - Rephrase. Dialogue said "timeout following reinforcement", but the timeout began at the start of reinforcement. (However, beginning at the start of reinforcement is logical, because otherwise there's an asymmetry in the way that ticks are blocked [during timeouts] or not [during reinforcement], so we unify it by thinking of the timeout as the "tick-blocking and response- blocking time", and the user can choose the timing. - CSimpleSchedules core task code simplified and brought closer to CConcurrentSchedules. =============================================================================== v10.6 (3 June 2014) =============================================================================== - Bugfix: ConcurrentSchedules crashed at startup when only one schedule in use (null pointer access). =============================================================================== v10.7 (10 June 2014) =============================================================================== - exclusions to compile cleanly in the absence of the "restrictedtasks" directory for non-Cambridge builds - NoCrypto_Debug and NoCrypto_Release builds for easy compilation from source distributed without cryptographic keys - bugfix affecting ConcurrentSchedules: non-unique stimulus names when objects are used for two purposes ... applies to several CDisplayObject::DisplaySpecifyingCentre() calls ... and CLocatedDisplayObject::Prepare() calls ... don't want to see those calls based purely on the object's name ThreeChoice still uses some internal name-sharing, but not based on the object's name. =============================================================================== v10.8 (1 Jul 2014) =============================================================================== - stdafx.h #ifdef for cryptography library - for some reason, the local version released as 10.7 doesn't seem to have the bugfixes described above as 10.7; not sure why; re-releasing as 10.8 =============================================================================== v10.9 (1 Jul 2014) =============================================================================== - problem above was a renaming of the build directories (so InnoSetup was seeing an old version; "Cambridge Release" versus "CambridgeRelease"). Fixed. =============================================================================== v11.0 (27 Aug 2014) =============================================================================== - Fixed bug in CListDMSTrialPlan::Update() introduced in rev. 1762 (~21 May 2014). Symptom was: create new ListDMS schedule, click "View Schedule", program crashed immediately. - Overt RNG test. (Which works fine.) - Live insight into the inner workings of schedules. CReinforcementSchedule::ExtraLiveInfo() - New contingency schedule (Jackson). JACKSON_CONTINGENCY integer parameters 5-7 for reinforcement schedules =============================================================================== v11.1 (4 Sep 2014) =============================================================================== - JACKSON_CONTINGENCY schedule: option to disable either part of the schedule =============================================================================== v11.2 (7 Oct 2014 - 5 Dec 2014) =============================================================================== - MonkeyCantab_ObjectConfig.Description field changed from VARCHAR(255) to MEMO; wasn't long enough for some users. - Reversals starting bug as per v10.5 details above. - This program doesn't multithread; incoming socket messages are handled via the Windows message pump, on the same thread as general Windows messages and therefore the task starting code, via CMonkeyCantabDlg::OnBstart() CMonkeyCantabController::StartModuleList() CReversals::StartModule() So it's not that a Whisker message can arrive before the task starting code has completed, as far as I can see. - However, the Whisker log suggests that an "Initiated_Trial" message is sent to MonkeyCantab but does nothing, i.e. strEventInitiatedSpontaneously. - Suggests CReversals::IncomingEvent not being called, or "m_ePhase == REVERSALS_PHASE_WAITINGFORINITIATION" test is failing. - NO DEFINITIVE CAUSE FOUND YET. AssertOrWarn() calls added. (Likely related to FPU corruption/dodgy kernel sound driver?) - Passing note: closing up braces: FIND: foreachindex\({:i}, {:i}\)\n:b*\{\n REPLACE: foreachindex(\1, \2) \{\n - Note option to show 80-column line in Visual Studio: http://stackoverflow.com/questions/84209/adding-a-guideline-to-the-editor-in-visual-studio HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\Text Editor\Guides = "RGB(200,200,200), 80" - One session where NewTouchTraining reported "Awaiting response" and then appeared to ignore all events including licks; that was from MonkeyCantab v11.1. - More warnings when events ignored, in CMonkeyCantabController::IncomingEvent CMonkeyCantabController::HandleControllerEvents_DuringLink. - NO DEFINITIVE CAUSE FOUND YET. Warn() calls added. (Likely related to FPU corruption/dodgy kernel sound driver?) - Option for a whole-session time limit (in General Parameters). - Request from SJ, 26 Nov 2014. - m_bOverallTimeLimit, m_fOverallTimeLimitMin - MonkeyCantab_GeneralConfig.OverallTimeLimit, MonkeyCantab_GeneralConfig.OverallTimeLimitMin - Record individual module start/end times: MonkeyCantab_ModuleOverview table - Write warnings to database: MonkeyCantab_Warnings table - lick triggered both pumps at one point in ConcurrentSchedule with lick- contingent pumping - more explicit pump 1 naming to ease comparison - bug but ?not the right one: AbortReinforcer switched off pump 1, not 2 ... but not sure that explains how pump 2 got on in the first place - bug in CReinforcer::GetMaxTimeMs: dwStimulusTime and dwPump2Time weren't being counted; is this more likely the source? No. - AbortReinforcer wasn't clearing m_bLickContingentPump1InProgress or m_bLickContingentPump2InProgress. That's it. So the bug occurred where one reinforcer started before another had finished, and the clearing process failed. - Yup, that was it. - summarize #contingent and #noncontingent reinforcements for ConcurrentSchedules SimpleSchedules ... via CReinforcementSchedule =============================================================================== 11.3 (24 Feb 2015) =============================================================================== - Jackson schedule under ConcurrentSchedules: option to prevent noncontingent reinforcement when the *other* schedule has had a response. m_bJacksonNoncontingentRestriction - Bugfix: m_bPrimeFirstInterval was being ignored in CReinforcementSchedule creation. =============================================================================== 11.4 (12 Apr 2015) =============================================================================== - Rebuild with latest WhiskerClientLib to fix potential socket problem (causing sporadic initiation failure). - Bugfix: delayed reinforcers were probably not being given on the RIGHT schedule. =============================================================================== 11.5 (from 13 June 2015) =============================================================================== - Concern about 11.4 crashing ("not responding") at the end of a session without creating a text log, under Win7 64-bit (with Whisker 4.6.2), McGill (May 2015); however, MonkeyCantab won't start without creating a text log so this may have been due to over-the-network file storage or something similar. Not yet reproducible under 32-bit Windows XP (VirtualBox) or 64-bit Windows 8.1 (native). Concern would obviously fall on socket code, given changes in 11.4 (and given that it worked in 11.3) but also failure was after trial 106. - Modification to ImpulsiveChoice task to specify 'B' stimuli on a block-by-block basis. m_bB_SameStimulusForAll -- default true m_vstrBStimuli - VS2008 regex: from foreachindex\({:i}, {:i}\)\n:b*\{ to foreachindex(\1, \2) { - New fields: ImpulsiveChoice_Config.B_SameStimulusForAll ImpulsiveChoice_Config.B_Stimuli ImpulsiveChoice_Results.StimulusA ImpulsiveChoice_Results.StimulusB - New task: Variable Delayed Response (VDR) = delayed matching to position (DMTP). =============================================================================== 11.6 (21 July 2015) =============================================================================== - Database execption: the MonkeyCantab_ModuleOverview.ModuleType field, which was VARCHAR(50), was too short to contain the string "Visual Discrimination and Set Shifting (Superimposed Style)" (59 characters). A CDBException was raised with the error "String data, right truncated". In full, the error (from the MonkeyCantab text file) was: Opened database: ODBC;DSN=MonkeyCantab_main;DBQ=D:\whisker\CODE\clients\RNC_Cambridge\MonkeyCANTAB\MonkeyCantab database (sample).mdb;DriverId=281;FIL=MS Access;MaxBufferSize=2048;PageTimeout=5; Using transactions Writing general config Writing config for task 0 (VisualDiscrimSuperimposed) Writing results for task 0 (VisualDiscrimSuperimposed) Writing individual events Writing module overview CAUGHT EXCEPTION. CDBException: error number -1 ERROR WAS: String data, right truncated (null) More ODBC details: State:22001,Native:31,Origin:[Microsoft][ODBC Microsoft Access Driver] Changed field to VARCHAR(100) - worked immediately and on the fly. Is this a reason for recent crashes elsewhere - with some sort of dodgy ODBC system that crashes rather than raising an exception properly? The field length isn't stored in MonkeyCantab, just in the database. Check: run with the short field and Release mode: same behaviour. - Found: CMonkeyCantabModule::StatusMessage() called itself with StatusMessage(), when it should have called m_pController->StatusMessage(). ??? Why wasn't that obvious earlier? ... in the case of the VisualDiscrimSuperimposed task, our crashing one, it was using m_pController->SetModuleStatus() for its normal status messages, and only calling StatusMessage(strEndingMessage) the once. But other tasks used StatusMessage() more freely. - Versions 11.4 and 11.5 removed from download area as potentially hazardous. (Though I'm not quite sure when that bug crept in, that's when crashes were noticed.) - cppcheck --force *.h *.cpp >/dev/null (a) MonkeyCantab -- pass (b) WhiskerClientLib -- pass (c) WhiskerServer -- pass (except two IO board non-errors, cleaned up) - clean rebuild =============================================================================== 11.7 (26 Nov 2015) =============================================================================== - Bugfix to VDR: required n+1 locations (rather than n) for n responses (CVDRStage::IsConfigValid) - VDR results CSV output: columns were confused because m_strPossibleResponseLocations was using "identity" as its CSV output function but this string can contain commas; changed to an updated version of QuotedString. - Checking for IntVectorToCSVString (the most common source of such strings) finds: - lots of others in the config outputs, which is OK - some uses of UIntVectorToSemicolonString for CSV output ... which is in support.h from WhiskerClientLib - In fact, it's rather better to store a proper vector and use these mapping functions for output, as it reduces the number of variables kicking around. - McGill requests (Lawrence Oprea), boiling down to ImpulsiveChoice changes: - specify A stimulus/delay/prob for each block - randomize trials across (not just within) blocks, i.e. treat blocks as "possible combinations" rather than true blocks Not easy at all to do without a breaking config change. =============================================================================== 11.8 (9-10 Dec 2015) =============================================================================== - ImpulsiveChoice changes as above. Breaking config change. - strMonkeyCantabConfigVersion changed from v9.9 to v11.8 - Block summaries removed from output; too fiddly now; Don't Repeat Yourself; trial output is there; that's why we have SQL. - VDR: randomize sequence of stages (each specifying a delay) - VDR: punish cue touch - VDR: punish touch during delay - Database changes: In ImpulsiveChoice_Config: NEW: A_SameStimulusForAll / m_bASameStimulusForAll NEW: A_Stimuli / m_vstrAStimuli NEW: A_Delays / m_vfADelays NEW: A_Probabilities / m_vfAProbabilities NEW: ShuffleWithinBlock / m_bShuffleWithinBlock NEW: ShuffleOverall / m_bShuffleOverall REMOVED: A_Delay (replaced by A_Delays) / m_fADelay REMOVED: A_Probability (replaced by A_Probabilities) / m_fAProbability REMOVED: Shuffle (replaced by ShuffleWithinBlock) / m_bShuffle CHANGED: B_Delays (length changed from 50 to 255) CHANGED: B_Probabilities (length changed from 50 to 255) In VDR_Config: NEW: VDR_Config.ShuffleStages / m_bShuffleStages NEW: VDR_Config.PunishCueTouch / m_bPunishCueTouch NEW: VDR_Config.PunishDelayTouch / m_bPunishDelayTouch In VDR_Results StageIndex =============================================================================== 11.9 (16 Dec 2015) =============================================================================== - Bughunting in VDR. - VDR: renamed in CSV output: Stage number (from order in config) -> Stage Stage index (sequence from 0 within run) -> StageIndex - Bug was that an omission timer wasn't being cleared. =============================================================================== 11.91 (25 Mar 2016) =============================================================================== - VDR: option to punish background touches during cue. m_bPunishBackgroundTouchDuringCue VDR_Config.PunishBackgroundTouchDuringCue =============================================================================== 11.92 (19 Jan 2017) =============================================================================== - REVIEW re CPT: report it was starting spurious brief extra trials with short intertrial intervals (<3s in the test config, bugtest_2017_01_16_OG4CPTnoreward.xml). ... BEHAVIOUR IS AS PER SPECIFICATION, and user's config file was unusual. See e-mail from me 19 Jan 2017. No changes made. No release. Version number remains live. - 18 Feb 2017: updated to use Whisker SDK v4.9, which returns to the STL implementation of random_shuffle (now fixed by Microsoft). - 13 Mar 2017: Probabilistic Concurrent Discrimination (PCD) task. =============================================================================== 11.93 (13 Oct 2017) =============================================================================== - Database change only: in SpatialWM_Results table: StimulusLocations } changed from TEXT(255) to MEMO Responses } ResponseTimesRelTrialStartMs } ResponseLocations } ... because ResponseTimesRelTrialStartMs overflowed 255-char limit when using SpatialWM in probe mode. =============================================================================== 11.94 (5-7 Dec 2017) =============================================================================== - SWM change for Sebastian Axelsson. See correspondence around 2 Oct 2017. - Previously, n stimuli were offered, and all n must be responded to, in some sort of sequence (without responding to any twice). - In this new version, n + x stimuli are offered, and n must be responded to in sequence, without repetition. At that point, the subject wins, even though there are x left to be responded to. (A common value for x might be 1; x=0 is equivalent to the normal task.) - The psychologically interesting moment is when you increase x, holding n constant, whilst including all previous locations and adding x new ones. (Does the subject stick with the previously learned locations? Will they explore the new ones?) - The increase is manual (between sessions). We just need to allow the user to specify x. They can already specify the locations. - We can either specify as n_required + x_extra (as above) or n_plus_x_total - x_free_hits -- this is probably simpler for other aspects of the config! Let's do this. (Specifically, when you specify the locations of all stimuli, you need to be specifying the larger of the two numbers!) - Simplest way is to specify: "NUMBER OF 'FREE HITS': STIMULI TO WHICH RESPONDING IS NOT REQUIRED", with default 0. - NEW DATABASE FIELDS: SpatialWM_Config.NFreeHits SpatialWM_Results.NumStimuliToBeTouched =============================================================================== DATABASE TROUBLESHOOTING NOTE 2019-02-11 =============================================================================== - Problem encountered: - Windows 7, 64-bit (see: Control Panel -> System) - Office 2016 with Access, 64-bit (see: File -> Account) ----------------------------------------------------------------------------- (a) It's confusing whether you're using the 32-bit or the 64-bit ODBC manager. ----------------------------------------------------------------------------- - It's very confusing. - Both show the same DSNs, or an overlapping set. - On a 64-bit Windows OS: The 64-bit version is C:\Windows\system32\odbcad32.exe ^^ ^^ 64 bit! Really! The 32-bit version is C:\Windows\SysWOW64\odbcad32.exe ^^ ^^ 32 bit! Not confusing at all! - Don't take my word for it: https://answers.microsoft.com/en-us/msoffice/forum/all/need-64-bit-odbc-driver-for-access-2013/390d9cc0-47d0-427c-a21a-d4b7b90ed6f9 - On a 32-bit Windows OS: The only (32-bit) version is C:\Windows\system32\odbcad32.exe ^^ ^^ 32 bit this time! ----------------------------------------------------------------------------- (b) MonkeyCantab is a 32-bit application, so needs the 32-bit drivers. ----------------------------------------------------------------------------- - Run the 32-bit ODBC Administrator. - Add a DSN -- this will be a 32-bit DSN (even if it's also later visible from the 64-bit ODBC Administrator). ... both kinds of DSN may be shown: https://support.microsoft.com/en-gb/help/942976/odbc-administrator-tool-displays-both-the-32-bit-and-the-64-bit-user-d - But if the driver you need is missing (e.g. you have an Access 2016 .accdb file, and you're only offered drivers for the old .mdb format)... ----------------------------------------------------------------------------- (c) Access 2016 is installed with 64-bit drivers only, and the 32-bit drivers complain and fail to install. ----------------------------------------------------------------------------- So: 1. Download the Microsoft Access Database Engine 2016 Redistributable from https://www.microsoft.com/en-us/download/details.aspx?id=54920 . (Or the correct version for your Access installation!) 2. At the second download stage, choose AccessDatabaseEngine.exe (32-bit), not AccessDatabaseEngine_X64.exe (64-bit). 3. Fire up a command prompt and use the /passive switch: AccessDatabaseEngine.exe /passive ... which is necessary to force the 32-bit drivers onto a system with the 64-bit edition already installed. - Considered altering Whisker Database Manager -- but under Windows 10, it launches the 32-bit version (which is clearly marked in Windows 10) even though ostensibly the same command from the command-line launches the 64-bit version... so probably best users handle this themselves. Note that the Whisker Database Manager uses this sort of launch command: rundll32.exe shell32.dll,Control_RunDLL C:\Windows\System32\odbccp32.cpl or similar. =============================================================================== 11.95 (14 Sep 2019) =============================================================================== - PROGRATIO_DOUBLEINCREMENT_FLOATSTOP schedule =============================================================================== 11.96 (6 Dec 2020) =============================================================================== - PAL task supports STIMULUS_INFO line. =============================================================================== 12.00 (6-14 Feb 2021) =============================================================================== - ACT task: two edit boxes made read-only (were incorrectly editable). - New DRACT task. See DRACT.cpp for details. Completed: - Description of full task logic. - Dialog box resource: main - Dialog box resource: stimulus - dialog box class: main - dialog box class: stimulus - config recordset skeleton class - results recordset skeleton class - task config variables - reinforcer/sound defaults - database table: config: DRACT_Config - task result variables - database table: results: DRACT_Results - task - check dialogues etc. [and try a run, but not there yet] - make stimulus class self-handling for XML - ensure stimulus vector written to database via WriteConfigToDatabase - stimulus class recordset - enforce the names of auditory stimuli (but NB only needs to be unique within a module) - help - fix: storing sound stimuli to database - core task testing - ensure everything works fine with no auditory and/or no visual stimulus - create/implement all relevant event types - clean database =============================================================================== 12.01 (14 Nov 2021) =============================================================================== - PAL: add option to offer multiple samples and a single choice. - Motivation: 2-back is causing difficulty; uncertain if a location strategy is being used in a 1-back version. So, option will be (for example): present A, present B, test either A or B (pseudorandomly), giving mix of 1-back and 2-back. - Implementation: this is basically m_bTrainingOnlyOneRealChoice but also eliminating all other options. Call it m_bTrainingOnlyOneChoice. ^^^^^^^^^^^^^^^^^^^^^^^^ - Needs to be pseudorandom, not random. So also add m_iTrainingOneChoiceDWORMultiplier (affecting both ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ m_bTrainingOnlyOneRealChoice and m_bTrainingOnlyOneChoice). - Selecting m_bTrainingOnlyOneChoice disables m_bTrainingOnlyOneRealChoice. It should really be a radio button but I can't be bothered. - PAL: Add a distractor, in the sense of a consistent thing that you have to respond to (but at a location not used in the task). It's to avoid a positional strategy, where the subject sits at a location. Always using a consistent response stimulus. So not really a "distractor", but a "centering response". When? e.g. one stimulus: sample -> centre -> choice many stimuli: sample, sample, sample -> centre -> choice, choice, choice That is: always between the last sample and the first choice. Always unrewarded. (Uses standard time to wait for a response.) - Implementation: separate single-location grid for this. - m_bCentreBeforeChoice, and grid location defined by PAL_GRID_CENTRE_RESPONSE. ^^^^^^^^^^^^^^^^^^^^^ - Phase PAL_PHASE_CENTRE_BEFORE_CHOICE - Event types ET_PAL_REQUIRE_CENTRE_RESPONSE, ET_PAL_CENTRE_RESPONSE, ET_PAL_CENTRE_RESPONSE_OMISSION. - Implementation: - Database: TrainingOnlyOneChoice, TrainingOneChoiceDWORMultiplier, CentreBeforeChoice - Header: m_bTrainingOnlyOneChoice, m_iTrainingOneChoiceDWORMultiplier, m_bCentreBeforeChoice - Recordset: automatic - Config GUI: m_bTrainingOnlyOneChoice, m_iTrainingOneChoiceDWORMultiplier, grid location - Task: m_bTrainingOnlyOneChoice, m_iTrainingOneChoiceDWORMultiplier, distractor - Trial record: m_bCentreResponseOmission (database: CentreResponseOmission) - Help: text; screenshot. - Test: done - Distinguish ET_PAL_CHOICE_OMISSION (new) from ET_PAL_SAMPLEOMISSION (previously used for sample + choice omissions). =============================================================================== 12.02 (1 Mar 2022) =============================================================================== - PAL: option to reward centring response (see v12.01). Code: m_bRewardCentringResponseBeforeChoice Database: PAL_Config.RewardCentringResponseBeforeChoice =============================================================================== 12.03 (15-16 Apr 2022) =============================================================================== - DRACT task (for UCam) - Current training protocol involves single-stimulus training, then mixed-stimulus training. - NEW OPTIONS: correction procedure. That is: - OPTION: If the subject gets a trial wrong, repeat the trial exactly. - OPTION: If the subject omits a trial (either stimulus omission or choice omission), repeat the trial exactly. - Constraints: - "Error" correction procedures not offered if "training mode" enabled, since only one response is offered.) [Implemented for the user by disabling the option in the dialogue box.] - There is no rationale for a correction procedure on an ambiguous trial, where P(A correct) is between 0 and 1. It is highly unlikely that a correction procedure would be enabled in a "mixed" session (where there are ambiguous trials). So: let's say that it is prohibited to have a "error" correction procedure enabled if an ambiguous cue is present. [Implemented as a config validity check.] =============================================================================== 12.1 (10 Jul 2022) =============================================================================== - VDR sample stimulus disappearing when touched (* = new option): - If (*), then if the subject touches the cue, the cue vanishes, and the delay starts immediately. (If the subject does not touch the cue, the cue remains for its normal duration; touching the cue is not mandatory.) - This is incompatible with . - It is set as a task-level (not stage-level) variable. - VDR correction procedure (* = new option): - If (*): - If subject makes (*) responses to one location within the last (*) trials (indicating a positional bias) [not including previous correction procedure trials]: - If , i.e. subject must respond to location of cue: - Position the cue (and thus position the correct response location) ANYWHERE BUT the subject's preferred location... (With two response options, "avoid the preferred location" equates to "pick the other one". But the "matching" version of the task can have >1 alternative response locations.) Otherwise (for the non-matching version of the task), where there will always be only one alternative (non-cue) location: - Position the cue (and thus position the correct response location) AT the subject's preferred location... - ... until it makes (*) correct responses in a row. [Extra note: within the correction procedure!] - The correction procedure is cancelled when a stage ends, i.e. it operates per-stage and only within a stage. - The settings are configured for the task as a whole (not per stage), i.e. different correction procedures cannot operate for different stages. =============================================================================== 12.2 (17 Jan 2024-28 Mar 2024) =============================================================================== - Additional schedules for Concurrent Schedules task, permitting up to dual concurrency (two schedules for each manipulandum). - Several new output/database variables, both for config and results: ConcurrentSchedules_Config.S3_Use ConcurrentSchedules_Config.Schedule3 ConcurrentSchedules_Config.S3_UseTimeout ConcurrentSchedules_Config.S3_TimeoutDurationSec ConcurrentSchedules_Config.S3_MaxReinfs ConcurrentSchedules_Config.S4_Use ConcurrentSchedules_Config.Schedule4 ConcurrentSchedules_Config.S4_UseTimeout ConcurrentSchedules_Config.S4_TimeoutDurationSec ConcurrentSchedules_Config.S4_MaxReinfs ConcurrentSchedules_Events.S1_Should ConcurrentSchedules_Events.S1_Was ConcurrentSchedules_Events.S2_Should ConcurrentSchedules_Events.S2_Was ConcurrentSchedules_Events.S3_Should ConcurrentSchedules_Events.S3_Was ConcurrentSchedules_Events.S4_Should ConcurrentSchedules_Events.S4_Was ConcurrentSchedules_ResultSummary.S1and3_TotalResponses ConcurrentSchedules_ResultSummary.S2and4_TotalResponses - Note the importance of output variables S1and3_TotalResponses and S2and4_TotalResponses, to avoid double-counting if multiple schedules operate from a single manipulandum (which is conceptually complex). See help. - Internally, removed m_bUsingTwoSchedules, which was redundant/unused. - DRACT: option not to show the original stimulus at the moment of choice. - New database variable: DRACT_Config.PresentCueAtChoice =============================================================================== 12.3 (5 June 2024) =============================================================================== - Bugfix. If multiple modules, of the same kind (e.g. two ConcurrentSchedules modules), ran consecutively, some sound elements (e.g. reinforcer-associated sounds) would "blend" with their predecessor (e.g. a reinforcer-associated sound from module 1 would be inappropriately played along with the corresponding one from module 2). - They shared names (e.g. ConcurrentSchedules_Reinf2_sound) and a proper clearance did not happen at the end of the first module. - The "_sound" suffix here comes from CReinforcer::SetLabel(); the rest from e.g. strCS_Reinf1Label. - The only Whisker-based sound prep is in CMonkeyCantabController::PrepareSound(). - The appropriate place to clear things is CMonkeyCantabController::ResetState(). So we clear, and we separate out the controller's own setup into CMonkeyCantabController::PrepareControllerSounds() and re-call that after we clear on Whisker. (Individual modules prepare their sounds when they start, not at constructor time.) Also check validity for reinforcers 3/4 (see changes for v12.2) in CConcurrentSchedules::IsConfigValid(). - Option for multiple reinforcers per schedule in ConcurrentSchedules. Selection among the options is at random, as requested. - New x-macro X_CONFIGREINFORCER_VECTOR. - Config version (strMonkeyCantabConfigVersion) changed from 11.8 to 12.3 ... means that it will load, but warn about, older versions. - Discriminated via new database columns: ConcurrentSchedules_Events.S1_ReinfNum ConcurrentSchedules_Events.S2_ReinfNum ConcurrentSchedules_Events.S3_ReinfNum ConcurrentSchedules_Events.S4_ReinfNum - Database referential integrity also enforced for Concurrent Schedules; was missing. - Internal bugfix to status.Format("%s...", status, ...). =============================================================================== 12.4 (19 June 2024) =============================================================================== - ConcurrentSchedules: bugfix to live status display of schedules (would only show "extra" schedule status for "extra left" schedule, not either). Fix is to CConcurrentSchedules::GetSchedulePairStatus(). =============================================================================== THINGS TO DO =============================================================================== - copy constructors/assignment is not handled with current best practice: http://stackoverflow.com/questions/1734628 - rule of three, rule of five, rule of zero: http://stackoverflow.com/questions/20571886 http://flamingdangerzone.com/cxx11/2012/08/15/rule-of-zero.html NB also some aspects specific to C++11 - how to encapsulate things like Windows resources: http://stackoverflow.com/questions/14865919/wheres-the-proper-resource-handling-rule-of-zero =============================================================================== MAYBE THINGS TO DO, DEPENDING ON OTHER PEOPLE: =============================================================================== - stop-signal reaction time task e.g. Eagle & Robbins (2003) BBR 146:131. staircase method: http://www.psy.vanderbilt.edu/faculty/logan/Verbruggenetal_2008_BRM.pdf - Consider change of default database, away from MS Access. Engine choice: MySQL, PostgresSQL, SQLite. MonkeyCantab interface: MySQL: Windows ODBC (ODBC connector comes with MySQL) SQLite: ? Data query client interface: Windows ODBC; unixODBC (under Linux); direct MySQL access SQLite Studio Client choice: free: includes MySQL Workbench (currently: data editor not great); many others commercial: best found so far is Navicat (which, on Windows editions, also imports/exports MS Access and speaks standard SQL). Conversion: one-off: consider my MDB-to-MySQL conversion script Database supply: ideally as standard SQL, with tools to create MS Access back-compatible databases - if Campden add a "jammed pellet" detector device ("Our equipment broke..."), add a feature that beeps and flags a status message saying "WARNING -- pellet dispenser may be jammed" (but don't interfere with the task). They'll let us know if/when such a thing happens. See e-mails Julie 12/1/6 (with partial details of hardware), Terry 12/1/6, RNC 15/1/6. - customer C5 (dogs) wanted "pause" facilities. Certainly would need to be implemented on a task-by-task basis (e.g. pause between trials). MRFA put it well: "I think we could define 'sensible points' to restart, and do a 'pause' at these points if required. It doesn't make sense to pause at any point, you could be in the middle of a shock, or tone, or whatever, but I can see the advantage of pausing a session 'at the end of a trial'; possibly also aborting the trial." - as documented, "avoid central feeder" does nothing in touch training - it may be that Pfizer want this to do something else (though the obvious thing is to pick noncentral locations in the configuration). - could update text dialogue to support vertical/horizontal centreing (but little point really!) - stop-signal task - =============================================================================== NOT THINGS TO DO =============================================================================== - (LDA request) Facility to cancel (and restart) task without closing program (requested 30 April 2003). Will think about this; one implementation method w'd be to ensure main dialogue has pointer to task; cancellation should shut task, create new, copy config, delete old, restore dialogue state. This implementation would require automatic server disconnection/reconnection. Otherwise, would have to cascade the cancellation command down through task and probably all modules. (Too complex to bother with, I think.)