rs_knit_coordsets(data_in, aux)
[data_out,aux_out]=rs_knit_coordsets(data_in,aux)
knits a dataset structure into a consensus, and provides and displays statistics
Each of the records in the dataset structure data_in should contain the same stimuli,
and in the same order, as determined by the strings in data_in.sas{k}.typenames for the record k.
Missing data (e.g., for the stimulus s labeled by data_in.sas{k}.typenames{s}) should be indicated by
NaN's in the row data_in.sets{k}{idim}(s,:), a row of length idim. The dataset structure returned by rs_align_coordsets
meets these requirements.
Input arguments:
-
data_in(struct) –dataset structureto be processed, with fieldsds(cell array) –coordinate structure, ds{k}{idim} is an array of [nstims idim] of coordinates for the kth recordsas(cell array) –stimulus metadata structure, sas{k} is the stimulus metadata for the kth recordsets(cell array) –set metadata structure, sets{k} is the response metadata for the kth record
-
aux(struct) –auxiliary inputs, may be omitted, with fields
opts_knit(struct) – options for knitting and consistency checking, with fields to controlallow_offset(int) – 1 to allow translational offset, 0 does not allow; default is 1allow_scale(int) – 1 to allow scaling of each dataset into the consensus, 0 does not allow; default is 0allow_reflection(int) – 1 to allow reflection, 0 does not allow; default is 1if_normscale(int) – 1 to normalize consensus to size ofdata_in(determined by geometric mean of scale factors for each dataset), 0 does not (no effect if allow_scale=0); default is allow_scaleif_pca(int) – 1 to rotate the consensus coordinates in data_out into its principal components, 0 does not; default is 0if_stats(int) – 1 to do statistics of variance explained, 0 does not; default is 0nshuffs(int) – number of shuffles for calculating statistics; default is 500 if if_stats=1, 0 if if_stats=0; see note below regarding statistics and plotsif_frozen(int) – random number control for shuffles and initialization; 1 for same numbers every run, 0 for different random numbers each run, negative integer for a fixed seed each run; default is 1; see notes below regarding statistics and Procrustes consensus algorithmdim_max_in(int) – maximum dimension of data_in.ds to use; default is maximum available across all datasetsdim_list_in(int 1-D array) – list of dimensions to use from data_in.ds, must be unique; default is [1:dim_max_in]dim_aug(int) – number of dimensions to add for knitted datasets in data_out.ds; default is 0; see note below regarding Procrustes consensus algorithmdim_list_out(int 1-D array) – list of dimensions to create in data_out.ds, must be same length as dim_list_in, no less than corresponding elements of dim_list_in, and unique; default is [1:dim_list_in]+dim_augif_dim_heuristics(int) – 1 to always show heuristics as to whether there are sufficient constraints for the requested dimensions, 0 only if insufficient constraints; default is 0if_plot(int) – 1 to plot statistics, 0 does not; default is if_statsshuff_quantiles(float 1-D array) – quantiles to plot; default is [0.01 0.05 0.5 0.95 0.99]if_remove_path_label(int) – 1 to remove path from filename when used as a label (in data_in.sets{:}.label), 0 does not; default is 1knit_stats(struct) – include to replot a previous analysis, otherwise omit; see note below regarding replottingknit_stats_setup(struct) – include to replot a previous analysis, otherwise omit; see note below regarding replottingif_log(int) – 1 to log progress, 0 to suppress; default is 1pcon_init_method(int or char) – typically omitted; default is 0, leading to 'pca' method for initializingprocrustes_consensus; see note below regarding Procrustes consensus algorithm for other optionsif_swarm(int) – 1 to enable swarm optimization (overriding pcon_init_method), 0 to disable; default is 0; see note below regarding swarm optimizationif_initpca_rot(int) – typically omitted, default is 1 unless any of dim_list_out>dim_list_in; see note below regarding Procrustes consensus algorithmmax_iters(int) – maximum number of iterations for Procrustes consensus; default is 1000; see note below regarding Procrustes consensus algorithmmax_rmstol(float) – maximum change ofcoordinates for consensus solution; default is 10^-5; see note below regarding Procrustes consensus algorithmkeep_details(int) – 1 to return details of Procrustes consensus minimization, 0 does not; default is 0; see note below regarding Procrustes consensus algorithmpcon_initial_guess(cell array) – specified initial guess for Proccrustes minimization, typically omitted; see note below regarding Procrustes consensus algorithmpcon_alignment(cell array) – specified alignment for Procrustes minimization, typically omitted; see note below regarding Procrustes consensus algorithmswarm(struct) – if present, sets options for swarm optimization (see note below regarding swarm optimization); fields areif_log(int) – 1 for logging swarm optimization, 0 to suppress; default is 0if_frozen(int) – 1 for same numbers each run, 0 for different random numbers each run, negative integer for a fixed seed each run; default is 1max_niters(int) – maximum number of iterations to determine best initialization for swarm; default is 50max_rmstol(float) – tolerance for stopping iterations to dtermine best initializatio for swarm; default is 10^-4nrand(int) – number of initial guesses based on random numbers; default is 10
Transformations
Statistics and shuffles
Dimension selection
Plotting and replotting
Logging and optimization
opts_check(struct) – options for consistency checking, with fieldif_warn(int) – 1 to show warnings when datasets are checked for consistency or sufficient overlaps, 0 to suppress; default is 1
opts_pca(struct) – options for principal components analysis of consensus, typically omitted, only relevant if if_pca=1opts_align(struct) – options for alignment of data, typically omitted; see note below regarding recalculation of alignmentopts_rays(struct) – options for rays, typically omitted; see note below regarding rayssa_pooled(struct) – include to avoid recalculation of alignment, otherwise omit; see note below regarding recalculation of alignmentdata_align(struct) – include to avoid recalculation of alignment, otherwise omit; see note below regarding recalculation of alignment
Output arguments:
-
data_out(struct) –dataset structurewith a single record consisting of the consensus coordinates fromdata_in, same format as asdata_in -
aux_out(struct) –auxiliary outputs and parameter values used
warnings(char) – warnings generated during consistency checkwarn_bad(int) – number of warnings that prevent further processingopts_knit(struct) – aux.opts_knit, with defaults filled inopts_check(struct) – aux.opts_check, with defaults filled inopts_pcon(cell array of struct) – opts_pcon{idim} are the options used in Procrustes alignment for model dimension idimopts_pca(struct) – aux.opts_pca, with defaults filled inopts_align(struct) – aux.opts_align, with defaults filled inopts_rays(cell array with one element) – opts_rays{1} is a structure which contains the options used for creating rays in data_outrayss(cell array with one element) – rayss{1} is theray structurefor data_out; see note below regarding rayscoords_havedata(int 2-D array) – coords_havedata(s,k)=1 if the stimulus data_out.sets{:}.typenames{s} is present and not NaN in record k ofdata_in, 0 otherwisecomponents(struct) – adataset structure, the kth record corresponds to the kth record ofdata_inafter transformation to the consensus; all stimuli in data_out will be included but coordinates for stimuli not in data_in.sas{k} will be NaNknit_stats(struct) – statistics of knitting; see notes below regarding statistics and replotting a previous analysisknit_stats_setup(struct) – parameters extracted from aux.opts_knit, along with the additional fields below; see note below regarding replotting a previous analysisnsets(int) – number of records indata_innstims(int) – number of stimulidataset_labels(cell array of char) – dataset labels, from data_in.sets{:}.labelstimulus_labels(cell array of char) – stimulus labels, from data_out.sas{1}.typenames
fig_handle(handle) – handle to figure created (present only if statistics are plotted)ts_pca(cell array) – ts_pca{idim}{k} is the transformation from data_in.ds{k}{idim} to the consensus, taking into account final pca; present only if aux.opts_knit.if_pca=1 The transformation is ts_pca{idim,k}.scaling*[data_in{k}{idim}]*ts_pca{idim}{k}.orthog+ts_pca{idim}{k}.translation. Note that translation may be nonzero even if allow_offset=0, since this is the best transformation from the original data to the consensus -- which may include a translation even if the consensus is calculated wthout allowing translation. If no translation is desired, then set this field to zeros(1,idim). If dim_list_out>dim_list_in, then data_in{k}{idim} needs to be right-padded by columns of zeros for missing dimensions.details(cell array of struct) – details{idim} contains details of the convergence towards knitting for data_in.ds{:}{idim}; present only if aux.opts_knit.keep_details=1; fields includets_cum(cell array) – ts_cum{m}{k} is the transformation found from record k, i.e., from data_in.ds{k}(istim,:), to the current consensus, on iteration mrms_change(float 1-D array) – rms_change(m) is the rms change of the consensus coordinates from the previous iterationconsensus(float 3-D array) – consensus(istim,:,m) are theconsensus coordinates on iteration mz(float 4-D array) – consensus(istim,:,k,m) are the coordinates data_in.ds{k}(istim,:) transformed to match the consensus on dimension mrms_dev(float 2-D array) – rms_dev(k,m) is the rms deviation of record k from the consensus, after the current transformationinitial_guess(float 2-D array) – initial_guess(istim,idim) are the coordinates of stimulus istim used for the initial guess for the consensusalignment(float 2-D array) – alignment(istim,idim) are the coordinates of stimulus istim used to align the consensusinitialize_use(int 1-D array) – initialize_use(istim,1) is the reocrd is used to initialize each point (if initialize_set>0)swarm(struct) – details from swarm optimization, present only if opts_knit.if_swarm=1 (see note regarding swarm optimization), with fieldsrms_dev_total_min(float) – root-mean-squared deviation for best alignment from preliminary swarm runsrms_dev_total_definitive(float) – root-mean-squared deviation for best alignment for definitive runclass_name_min(char) – the class that produced the best alignment in preliminary runsitry_min(int) – the instance in the class that produced the best alignment in preliminary runsopts_definitive(struct) – the options in opts_knit that produced the best alignment in preliminary runsif_def_eq_swarm(int) – 1 if halting parameters (max_niters, max_rmstol) for preliminary and definitive runs matchinit_components(struct) – results of swarm optimizations based on component datasetsinit_pca(struct) – results of swarm optimizations based on principal componentsinit_random(struct) – results of swarm optimizations based on random starts
Note regarding propagation of fields from data_in to data_out
- For all records with data_in.sets{k}.type='data', the strings in data_in.sets{k}.paradigm_type must agree.
- The 'type' field of data_in.sets{1} is propagated to data_out.sets{1}
- If present, the 'paradigm_type' field common to data_in.sets{:} for all k for which data_in.sets{k}.type='data' is propagated to data_out.sets{1}
-
The following fields of data_in.sets{:} are concatenated with + signs in between and propagated to data_out.sets{1}
- paradigm_name
- subj_id
- subj_id_short
- label_long
- label
- extra
-
pipeline field of data_out.sets{1}:
- data_out.sets{1}.pipeline.type='knit'.
- data_out.sets{1}.pipeline.sets_combined{:} contains metadata from all records of
data_in
Note regarding statistics and plots
-
If aux.opts_knit.if_stats=1, variance explained by the consensus coordinates are calculated and returned in aux_out.knit_stats, in the following fields (rmsd=root-mean-squared deviation):
- rmsdev_overall (float 1-D array): rmsdev_overall(idim) is the rmsd across all records and stimuli
- rmsdev_setwise (float 2-D array): rmsdev_setwise(idim,k): rmsd within record k, across stimuli
- rmsdev_stmwise (float 2-D array): rmsdev_stmwise(idim,istim): rmsd within stimulus istim, across records
-
The counts for each of these calculations are counts_[overall|setwise|stmwise], and the available rmsd (from zero) is given by rmsavail_[overall|setwise|stimwise].
- If aux.opts_knit.nshuffs>0 (default is 500), then a parallel computation is done after random shuffles of the stimulus labels within each record, and the results are returned in rmsdev_[overall|setwise|stimwise]_shuff.
- For the shuffled quantities, the first two dimensions are the same as the unshuffled quantities; dimension 3 is always 1; dimension 4 (length: nshuffs) is which shuffle; dimension 5 (length: 2) is the mode: 1 for last coordinate only shuffled, 2 for all coordinates shuffled. To control whether the same random number seed is used on each run, use aux.opts_knit.if_frozen (default is 1).
-
if aux.opts_knit.if_plot=1 (default if if_stats=1), then a figure is created, with four panels:
- a heatmap of rmsdev_setwise as a function of dimension
- a heatmap of rmsdev_stmwise as a function of dimension
- a comparison of the unexplained portion of rmsdev_overall (black) to quantiles of rmsdev_overall_shuff (mode 1: magenta, mode 2: red). Quantiles are specified by shuff_quantiles; if nshuffs=0, shuffled values will not be plotted
- a comparison of the explained rmsd, parallel to the above, with available rmsd in blue
-
Other fields in aux_out.knit_stats are the following. Note that ds_components and ts are analogus to the fields components and ts_pca] in aux_out, except that ds_components and ts do not include the rotation to principal components (if requested by aux.opt_knit.if_pca=1). This is not needed for the variance statistics. For a transformation that includes the rotation, see aux_out.ts_pca.
- opts_pcon (struct): supplied options for Procrustes consensus algorithm
- opts_pcon_eachdim (cell array of struct): opts_pcon_eachdim{idim} are the options used for dimension idim
- ds_knitted (cell array): ds_knitted{idim} are the consensus coordinates
- ds_components (cell array): ds_components{k}{idim} are the coordinates for record k that most closely match the consensus
- ts (cell array): ts{idim}{k} is the Procrustes transformation for record k. The transformation is
[ds_components{k}{idim}]=ts{idim}{k}.scaling*[data_in.ds{k}{idim}]*ts{idim}{k}.orthog+ts{idim}{k}.translation; see
transformation structuresfor further details. If dim_list_out>dim_list_in, then data_in.ds{k}{idim}] needs to be right-padded by columns of zeros for missing dimensions.
Note regarding recalculation of alignment
The first step in forming a consensus is alignment, which identifies the common stimuli among the records of data_in, and to
place them in the same order. By default, this is carried out in rs_knit_coordsets by a call to rs_align_coordsets, using options aux.align_opts.
This recalculation can be avoided by supplying aux_out from a
previous call to rs_align_coordsets, as follows: aux.sa_pooled=aux_out.sa_pooled, aux.data_align=aux_out.data_out
Note regarding Procrustes consensus algorithm
- To find a consensus set of coordinates, the coordinates in each record of
data_inare rotated, and optionally translated (if allow_offset=1), scaled (if allow_scale=1), and reflected (if allow_reflection=1). These transformations are carried out for separately for each set dimension for which coordinates are present in all of the records, i.e., for which data_in.ds{k}{idim} exists for all k. - The algorithm, in procrustes_consensus.m, is iterative. Briefly, after an initial guess is determined, a Procrustes transformation is found that minimizes the rms deviation between each record and the current guess. The guess is then revised by setting each stimulus' coordinates equal to the centroid of the coordinates of that stimulus across the records. To avoid drift of the updated guess, it is Procrustes-transformed for closest match to an alignment coordinate set (the alignment set, unless otherwise specified, is equal to the initial guess).
- The iteration ends when either the number of iterations exceeds max_niters (default=1000), or the rms change of the guess is less than max_rmstol (default=10^-5)
-
There are several choices for initialization and alignment.
- For most purposes, the default initialization method (pcon_init_method=0) can be used, which uses the principal components of all the stimulus coordinates in all of the records. These can be optionally forced to be centered (pcon_init_method=-1) or not (pcon_init_method=-2); if unspecified (default), centering is determined by allow_offset. For these choices, if_initpca_rot=1 rotates the initial guess to match the data, or not. The default for if_initpca_rot is 1 unless any of dim_list_out>dim_list_in, in which case it is 0. The heuristic for not rotating if dim_list_out>dim_list_in, i.e., two or more sets of coordinates are to be knit together to construct a coordinate set with a greater number of dimensions, is that without rotation, the principal components reflect projections of the coordinates that are present in any of the records.
- Alternatively, pcon_init_method=r, r>0, specifies that the coordinates in data_in{r}{idim} are used.
- If pcon_init_method='specify', then pcon_initial_guess{idim} is an array of size [npts ids] for the initial guess, and pcon_alignment{idim}, which defaults to pcon_initial_guess, is used for the alignment at the end of each iteration. pcon_initial_guess and pcon_alignment may be omitted, in which case random values are used. To control whether the same random number seed is used on each run, use if_frozen (default is 1, which uses the same random numbers on each run).
- The solution is only unique up to rotation (and translation and reflection, if these components are allowed). The ambiguity is resolved by matching the consensus solution to the initial guess (or, pcon_alignment{idim} if separately supplied with pcon_init_method=0), as described above.
-
Under some circumstances (e.g., several solutions that are nearly equally good), the solution found by the algorithm may depend on the initialization choice. A simple strategy to check for this is to compare the results with the default pcon_init_method=0 to the results with pcon_init_method='specify' and if_frozen=0. There are two ways that this dependency can happen.
- One is that the number of overlapping stimuli is too small. For example, at least m points are required to determine a rotation and translation in an m-dimensional space; if there are fewer overlaps, then a consensus will still be found but there are many other consensus datasets that fit equally well. Note that setting aux.opts_knit.if_dim_heuristics=1 will display heuristics concerning whether there are sufficient overlaps.
- A second way is that there are a sufficient number of points, but there are several solutions that are approximately equally good.
Under these circumstances, the algorithm may get stuck in a local minimum. This possibility only occurs when there are at least three records in
data_in, as the procedure reduces to the standard Procrustes algorithm, which finds the consensus when there are only two records, is deterministic other than does rotational ambiguity.
-
The swarm option (opts_knit.if_swarm=1) can be used to automatically step through several types of initialization methods, and choose the best.
- If allow_scale=1, then the optimal solution will depend not only on the data points that overlap, but also on the data points that are unique to individual components, since these contribute to determining tthe rescaling on each iteration
Note regarding replotting a previous analysis
-
To replot a previous calculation with additional customization or to make a composite figure, proceed as follows:
data_inshould be equal to that used in the previous calculation.- aux.knit_stats should be equal to aux_out.knit_stats from the previous calculation
- aux.knit_stats_setup should be equal to aux_out.knit_stats_setup from the previous calculation
-
The following modifications are allowed in fields of knit_stats_setup:
- dataset_labels (cell array of char): dataset labels; default is data_in.sets{:}.label
- stimulus_labels (cell array of char): stimulus labbels; default is data_out.sas{1}.typenames
- shuff_quantiles (float 1-d array): quantiles to show; default is 0.01 0.05 0.5 0.95 0.99
- fig_handle (handle): figure handle to plot into; figure will be created if not supplied
- row (int): row to plot into; default is 1
- nrows (int): number of rows in the figure; default is row
-
No further calculations are done
- On return, data_out will be empty, and aux_out.fig_handle will be the figure handle
- In creating a composite figure, rows should be plotted in order from top to bottom, as plotting the bottom row triggers an equalization of the color scale. See
rs_knit_coordsets_demofor an example.
Note regarding swarm optimization
- This is enabled by setting opts_knit.if_swarm=1.
- Preliminary runs are made with several classes of initial guesses, and stopping parameters based on max_niters and max_rmstol in opts_knit.swarm
- The choice that leads to the smallest rms deviation of the aligned coordinates is recorded in aux.details{idim}.swarm, and used for a definitive run, using the stopping parameters in opts_knit
-
The classes are
- init_components: the original component datasets are used; variants choose each component dataset in succession as the initial guess, advancing to the next dataset if a stimulus is missing
- init_pca: principal components of the datasets are used, with options (mean subtraction, rotation) as described in the note regarding the Procrustes alignment algorithm; variants consist of computing the principal components from the coordinates of stimuli present in increasing numbers of the datasets
- init_random: Gaussian random varibles are used as the initial guess; the number of variants is given by opts_knit.swarm.nrand; default is 10; these random numbers do not affect the random numbers used for permutation testing
-
Results from each class are recorded in aux.details{idim}.(class_name), including
- counts: the number of variants for each class
- rms_dev_totals: the rms deviation for each example of the class
- range: the range of rms deviations for each class
- itry_min: the optimal choice within each class
- opts: the options usef for the variant with the lowest rms deviation
Note regarding rays
- The
ray structuredescribes relationships among the simulus coordinates:rays, i.e., sets of stimuli that lie along an axis or a ray from the origin,rings, stimuli that lie at an approximately equal distance from the origin, and nearest neighbors. It is only created if there is a valid set of stimulus coordinates.
See also
rs_align_coordsets, rs_aux_customize, rs_check_coordsets, rs_findrays, PSG_ALIGN_COORDSETS, PSG_KNIT_STATS, PSG_REMNAN_COORDSETS, PSG_COORD_PIPE_UTIL, overlap_heuristics, procrustes_consensus, PSG_ALIGN_STATS_PLOT.
Source code in src/rs_knit_coordsets.m
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 | |