def test_mapper_vs_zscore(): """Test by comparing to results of elderly z-score function """ # data: 40 sample feature line in 20d space (40x20; samples x features) dss = [ dataset_wizard(np.concatenate( [np.arange(40) for i in range(20)]).reshape(20,-1).T, targets=1, chunks=1), ] + datasets.values() for ds in dss: ds1 = deepcopy(ds) ds2 = deepcopy(ds) zsm = ZScoreMapper(chunks_attr=None) assert_raises(RuntimeError, zsm.forward, ds1.samples) idhashes = (idhash(ds1), idhash(ds1.samples)) zsm.train(ds1) idhashes_train = (idhash(ds1), idhash(ds1.samples)) assert_equal(idhashes, idhashes_train) # forward dataset ds1z_ds = zsm.forward(ds1) idhashes_forwardds = (idhash(ds1), idhash(ds1.samples)) # must not modify samples in place! assert_equal(idhashes, idhashes_forwardds) # forward samples explicitly ds1z = zsm.forward(ds1.samples) idhashes_forward = (idhash(ds1), idhash(ds1.samples)) assert_equal(idhashes, idhashes_forward) zscore(ds2, chunks_attr=None) assert_array_almost_equal(ds1z, ds2.samples) assert_array_equal(ds1.samples, ds.samples)
def __was_data_changed(self, key, entry, update=True): """Check if given entry was changed from what known prior. If so -- store only the ones needed for retrainable beastie """ idhash_ = idhash(entry) __idhashes = self.__idhashes changed = __idhashes[key] != idhash_ if __debug__ and 'CHECK_RETRAIN' in debug.active: __trained = self.__trained changed2 = entry != __trained[key] if isinstance(changed2, np.ndarray): changed2 = changed2.any() if changed != changed2 and not changed: raise RuntimeError, \ 'idhash found to be weak for %s. Though hashid %s!=%s %s, '\ 'estimates %s!=%s %s' % \ (key, idhash_, __idhashes[key], changed, entry, __trained[key], changed2) if update: __trained[key] = entry if __debug__ and changed: debug('CLF_', "Changed %s from %s to %s.%s", (key, __idhashes[key], idhash_, ('', 'updated')[int(update)])) if update: __idhashes[key] = idhash_ return changed
def __was_data_changed(self, key, entry, update=True): """Check if given entry was changed from what known prior. If so -- store only the ones needed for retrainable beastie """ idhash_ = idhash(entry) __idhashes = self.__idhashes changed = __idhashes[key] != idhash_ if __debug__ and 'CHECK_RETRAIN' in debug.active: __trained = self.__trained changed2 = entry != __trained[key] if isinstance(changed2, np.ndarray): changed2 = changed2.any() if changed != changed2 and not changed: raise RuntimeError, \ 'idhash found to be weak for %s. Though hashid %s!=%s %s, '\ 'estimates %s!=%s %s' % \ (key, idhash_, __idhashes[key], changed, entry, __trained[key], changed2) if update: __trained[key] = entry if __debug__ and changed: debug('CLF_', "Changed %s from %s to %s.%s", (key, __idhashes[key], idhash_, ('','updated')[int(update)])) if update: __idhashes[key] = idhash_ return changed
def test_mapper_vs_zscore(): """Test by comparing to results of elderly z-score function """ # data: 40 sample feature line in 20d space (40x20; samples x features) dss = [ dataset_wizard(np.concatenate([np.arange(40) for i in range(20)]).reshape(20, -1).T, targets=1, chunks=1), ] + datasets.values() for ds in dss: ds1 = deepcopy(ds) ds2 = deepcopy(ds) zsm = ZScoreMapper(chunks_attr=None) assert_raises(RuntimeError, zsm.forward, ds1.samples) idhashes = (idhash(ds1), idhash(ds1.samples)) zsm.train(ds1) idhashes_train = (idhash(ds1), idhash(ds1.samples)) assert_equal(idhashes, idhashes_train) # forward dataset ds1z_ds = zsm.forward(ds1) idhashes_forwardds = (idhash(ds1), idhash(ds1.samples)) # must not modify samples in place! assert_equal(idhashes, idhashes_forwardds) # forward samples explicitly ds1z = zsm.forward(ds1.samples) idhashes_forward = (idhash(ds1), idhash(ds1.samples)) assert_equal(idhashes, idhashes_forward) zscore(ds2, chunks_attr=None) assert_array_almost_equal(ds1z, ds2.samples) assert_array_equal(ds1.samples, ds.samples)
def test_hyperalignment_measure(self): ref_ds = 0 fsha = FeatureSelectionHyperalignment() ds_orig, dss_rotated, dss_rotated_clean, Rs = self.get_testdata() # Lets test two scenarios -- in one with no noise -- we should get # close to perfect reconstruction. If noisy features were added -- not so good for noisy, dss in ((False, dss_rotated_clean), (True, dss_rotated)): # to verify that original datasets didn't get changed by # Hyperalignment store their idhashes of samples idhashes = [idhash(ds.samples) for ds in dss] idhashes_targets = [idhash(ds.targets) for ds in dss] mappers = fsha(dss) mappers = [StaticProjectionMapper(proj=m, recon=m.T) for m in mappers] idhashes_ = [idhash(ds.samples) for ds in dss] idhashes_targets_ = [idhash(ds.targets) for ds in dss] self.assertEqual( idhashes, idhashes_, msg="Hyperalignment must not change original data.") self.assertEqual( idhashes_targets, idhashes_targets_, msg="Hyperalignment must not change original data targets.") # Map data back dss_clean_back = [m.forward(ds_) for m, ds_ in zip(mappers, dss)] _ = [zscore(sd, chunks_attr=None) for sd in dss_clean_back] nddss = [] ndcss = [] nf = ds_orig.nfeatures ds_norm = np.linalg.norm(dss[ref_ds].samples[:, :nf]) ds_orig_Rref = np.dot(ds_orig.samples, Rs[ref_ds]) \ * np.sign(dss_rotated_clean[ref_ds].a.random_scale) zscore(ds_orig_Rref, chunks_attr=None) for ds_back in dss_clean_back: ndcs = np.diag(np.corrcoef(ds_back.samples.T[:nf, ], ds_orig_Rref.T)[nf:, :nf], k=0) ndcss += [ndcs] dds = ds_back.samples[:, :nf] - ds_orig_Rref ndds = np.linalg.norm(dds) / ds_norm nddss += [ndds] # First compare correlations snoisy = ('clean', 'noisy')[int(noisy)] self.assertTrue( np.all(np.array(ndcss) >= (0.9, 0.85)[int(noisy)]), msg="Should have reconstructed original dataset more or" " less. Got correlations %s in %s case." % (ndcss, snoisy)) # normed differences self.assertTrue( np.all(np.array(nddss) <= (.2, 3)[int(noisy)]), msg="Should have reconstructed original dataset more or" " less for all. Got normed differences %s in %s case." % (nddss, snoisy)) self.assertTrue( nddss[ref_ds] <= (.1, 0.3)[int(noisy)], msg="Should have reconstructed original dataset quite " "well even with zscoring. Got normed differences %s " "in %s case." % (nddss, snoisy)) self.assertTrue( np.all(np.array(nddss) / nddss[ref_ds] >= (0.95, 0.8)[int(noisy)]), msg="Should have reconstructed orig_ds best of all. " "Got normed differences %s in %s case with ref_ds=%d." % (nddss, snoisy, ref_ds)) # Testing feature selection within the measure using fraction and count # same features fsha_fsf = FeatureSelectionHyperalignment(featsel=0.5) fsha_fsn = FeatureSelectionHyperalignment(featsel=4) fsha_fsf_same = FeatureSelectionHyperalignment(featsel=0.5, use_same_features=True) fsha = FeatureSelectionHyperalignment(full_matrix=False) # check for valueerror if full_matrix=False and no roi_seed fa self.assertRaises(ValueError, fsha, dss_rotated) fsha = FeatureSelectionHyperalignment() dss_rotated[ref_ds].fa['roi_seed'] = [1, 0, 0, 0, 0, 0, 0, 0] mappers_fsf = fsha_fsf(dss_rotated) mappers_fsf_same = fsha_fsf_same(dss_rotated) mappers_fsn = fsha_fsn(dss_rotated) mappers = fsha(dss_rotated_clean) mappers_diffsizedss = fsha_fsf([sd[:, nfs] for nfs, sd in zip([np.arange(5), np.random.permutation(np.arange(8)), np.arange(8)[::-1], np.arange(8)], dss_rotated)]) # Testing that most of noisy features are eliminated from reference data assert_true(np.alltrue([np.sum(m[:4, :4].std(0) > 0) > 2 for m in mappers_fsf])) # using same features make it most likely to eliminate all noisy features assert_true(np.alltrue([np.sum(m[:4, :4].std(0) > 0) == 4 for m in mappers_fsf_same])) assert_true(np.alltrue([np.sum(m[:4, :4].std(0) > 0) > 2 for m in mappers_fsn])) # And it correctly maps the selected features if they are selected if np.alltrue([np.all(m[4:, :4] == 0) for m in mappers_fsf]): for m, mfs in zip(mappers, mappers_fsf): assert_array_equal(m, mfs[:4, :4]) if np.alltrue([np.all(m[4:, :4] == 0) for m in mappers_fsf_same]): for m, mfs in zip(mappers, mappers_fsf_same): assert_array_equal(m, mfs[:4, :4]) # testing roi_seed forces feature selection dss_rotated[ref_ds].fa['roi_seed'] = [0, 0, 0, 0, 0, 0, 0, 1] fsha_fsf = FeatureSelectionHyperalignment(featsel=0.5) mappers_fsf = fsha_fsf(dss_rotated) assert(np.alltrue([np.sum(m[7, :] == 0) == 4 for m in mappers_fsf]))
def test_basic_functioning(self, ref_ds, zscore_common, zscore_all): ha = Hyperalignment(ref_ds=ref_ds, zscore_all=zscore_all, zscore_common=zscore_common) if ref_ds is None: ref_ds = 0 # by default should be this one # get a dataset with some prominent trends in it ds4l = datasets['uni4large'] # lets select for now only meaningful features ds_orig = ds4l[:, ds4l.a.nonbogus_features] nf = ds_orig.nfeatures n = 4 # # of datasets to generate Rs, dss_rotated, dss_rotated_clean, random_shifts, random_scales \ = [], [], [], [], [] # now lets compose derived datasets by using some random # rotation(s) for i in xrange(n): ## if False: # i == ref_ds: # # Do not rotate the target space so we could check later on # # if we transform back nicely # R = np.eye(ds_orig.nfeatures) ## else: ds_ = random_affine_transformation(ds_orig, scale_fac=100, shift_fac=10) Rs.append(ds_.a.random_rotation) # reusing random data from dataset itself random_scales += [ds_.a.random_scale] random_shifts += [ds_.a.random_shift] random_noise = ds4l.samples[:, ds4l.a.bogus_features[:4]] ## if (zscore_common or zscore_all): ## # for later on testing of "precise" reconstruction ## zscore(ds_, chunks_attr=None) dss_rotated_clean.append(ds_) ds_ = ds_.copy() ds_.samples = ds_.samples + 0.1 * random_noise dss_rotated.append(ds_) # Lets test two scenarios -- in one with no noise -- we should get # close to perfect reconstruction. If noise was added -- not so good for noisy, dss in ((False, dss_rotated_clean), (True, dss_rotated)): # to verify that original datasets didn't get changed by # Hyperalignment store their idhashes of samples idhashes = [idhash(ds.samples) for ds in dss] idhashes_targets = [idhash(ds.targets) for ds in dss] mappers = ha(dss) idhashes_ = [idhash(ds.samples) for ds in dss] idhashes_targets_ = [idhash(ds.targets) for ds in dss] self.assertEqual( idhashes, idhashes_, msg="Hyperalignment must not change original data.") self.assertEqual( idhashes_targets, idhashes_targets_, msg="Hyperalignment must not change original data targets.") self.assertEqual(ref_ds, ha.ca.chosen_ref_ds) # Map data back dss_clean_back = [ m.forward(ds_) for m, ds_ in zip(mappers, dss_rotated_clean) ] ds_norm = np.linalg.norm(dss[ref_ds].samples) nddss = [] ndcss = [] ds_orig_Rref = np.dot(ds_orig.samples, Rs[ref_ds]) \ * random_scales[ref_ds] \ + random_shifts[ref_ds] if zscore_common or zscore_all: zscore(Dataset(ds_orig_Rref), chunks_attr=None) for ds_back in dss_clean_back: # if we used zscoring of common, we cannot rely # that range/offset could be matched, so lets use # corrcoef ndcs = np.diag(np.corrcoef(ds_back.samples.T, ds_orig_Rref.T)[nf:, :nf], k=0) ndcss += [ndcs] dds = ds_back.samples - ds_orig_Rref ndds = np.linalg.norm(dds) / ds_norm nddss += [ndds] snoisy = ('clean', 'noisy')[int(noisy)] do_labile = cfg.getboolean('tests', 'labile', default='yes') if not noisy or do_labile: # First compare correlations self.assertTrue( np.all(np.array(ndcss) >= (0.9, 0.85)[int(noisy)]), msg="Should have reconstructed original dataset more or" " less. Got correlations %s in %s case." % (ndcss, snoisy)) if not (zscore_all or zscore_common): # if we didn't zscore -- all of them should be really close self.assertTrue( np.all(np.array(nddss) <= (1e-10, 1e-1)[int(noisy)]), msg="Should have reconstructed original dataset well " "without zscoring. Got normed differences %s in %s case." % (nddss, snoisy)) elif do_labile: # otherwise they all should be somewhat close self.assertTrue( np.all(np.array(nddss) <= (.2, 3)[int(noisy)]), msg="Should have reconstructed original dataset more or" " less for all. Got normed differences %s in %s case." % (nddss, snoisy)) self.assertTrue( np.all(nddss[ref_ds] <= .09), msg="Should have reconstructed original dataset quite " "well even with zscoring. Got normed differences %s " "in %s case." % (nddss, snoisy)) # yoh: and leave 5% of difference for a chance and numerical # fluctuations ;) self.assertTrue( np.all(np.array(nddss) >= 0.95 * nddss[ref_ds]), msg="Should have reconstructed orig_ds best of all. " "Got normed differences %s in %s case with ref_ds=%d." % (nddss, snoisy, ref_ds)) # Lets see how well we do if asked to compute residuals ha = Hyperalignment( ref_ds=ref_ds, level2_niter=2, enable_ca=['training_residual_errors', 'residual_errors']) mappers = ha(dss_rotated_clean) self.assertTrue( np.all(ha.ca.training_residual_errors.sa.levels == ['1', '2:0', '2:1'])) rterrors = ha.ca.training_residual_errors.samples # just basic tests: self.assertEqual(rterrors[0, ref_ds], 0) self.assertEqual(rterrors.shape, (3, n)) rerrors = ha.ca.residual_errors.samples self.assertEqual(rerrors.shape, (1, n))
def test_basic_functioning(self, ref_ds, zscore_common, zscore_all): ha = Hyperalignment(ref_ds=ref_ds, zscore_all=zscore_all, zscore_common=zscore_common) if ref_ds is None: ref_ds = 0 # by default should be this one # get a dataset with some prominent trends in it ds4l = datasets['uni4large'] # lets select for now only meaningful features ds_orig = ds4l[:, ds4l.a.nonbogus_features] nf = ds_orig.nfeatures n = 4 # # of datasets to generate Rs, dss_rotated, dss_rotated_clean, random_shifts, random_scales \ = [], [], [], [], [] # now lets compose derived datasets by using some random # rotation(s) for i in xrange(n): ## if False: # i == ref_ds: # # Do not rotate the target space so we could check later on # # if we transform back nicely # R = np.eye(ds_orig.nfeatures) ## else: ds_ = random_affine_transformation(ds_orig, scale_fac=100, shift_fac=10) Rs.append(ds_.a.random_rotation) # reusing random data from dataset itself random_scales += [ds_.a.random_scale] random_shifts += [ds_.a.random_shift] random_noise = ds4l.samples[:, ds4l.a.bogus_features[:4]] ## if (zscore_common or zscore_all): ## # for later on testing of "precise" reconstruction ## zscore(ds_, chunks_attr=None) dss_rotated_clean.append(ds_) ds_ = ds_.copy() ds_.samples = ds_.samples + 0.1 * random_noise dss_rotated.append(ds_) # Lets test two scenarios -- in one with no noise -- we should get # close to perfect reconstruction. If noise was added -- not so good for noisy, dss in ((False, dss_rotated_clean), (True, dss_rotated)): # to verify that original datasets didn't get changed by # Hyperalignment store their idhashes of samples idhashes = [idhash(ds.samples) for ds in dss] idhashes_targets = [idhash(ds.targets) for ds in dss] mappers = ha(dss) idhashes_ = [idhash(ds.samples) for ds in dss] idhashes_targets_ = [idhash(ds.targets) for ds in dss] self.assertEqual(idhashes, idhashes_, msg="Hyperalignment must not change original data.") self.assertEqual(idhashes_targets, idhashes_targets_, msg="Hyperalignment must not change original data targets.") self.assertEqual(ref_ds, ha.ca.chosen_ref_ds) # Map data back dss_clean_back = [m.forward(ds_) for m, ds_ in zip(mappers, dss_rotated_clean)] ds_norm = np.linalg.norm(dss[ref_ds].samples) nddss = [] ndcss = [] ds_orig_Rref = np.dot(ds_orig.samples, Rs[ref_ds]) \ * random_scales[ref_ds] \ + random_shifts[ref_ds] if zscore_common or zscore_all: zscore(Dataset(ds_orig_Rref), chunks_attr=None) for ds_back in dss_clean_back: # if we used zscoring of common, we cannot rely # that range/offset could be matched, so lets use # corrcoef ndcs = np.diag(np.corrcoef(ds_back.samples.T, ds_orig_Rref.T)[nf:, :nf], k=0) ndcss += [ndcs] dds = ds_back.samples - ds_orig_Rref ndds = np.linalg.norm(dds) / ds_norm nddss += [ndds] snoisy = ('clean', 'noisy')[int(noisy)] do_labile = cfg.getboolean('tests', 'labile', default='yes') if not noisy or do_labile: # First compare correlations self.assertTrue(np.all(np.array(ndcss) >= (0.9, 0.85)[int(noisy)]), msg="Should have reconstructed original dataset more or" " less. Got correlations %s in %s case." % (ndcss, snoisy)) if not (zscore_all or zscore_common): # if we didn't zscore -- all of them should be really close self.assertTrue(np.all(np.array(nddss) <= (1e-10, 1e-1)[int(noisy)]), msg="Should have reconstructed original dataset well " "without zscoring. Got normed differences %s in %s case." % (nddss, snoisy)) elif do_labile: # otherwise they all should be somewhat close self.assertTrue(np.all(np.array(nddss) <= (.2, 3)[int(noisy)]), msg="Should have reconstructed original dataset more or" " less for all. Got normed differences %s in %s case." % (nddss, snoisy)) self.assertTrue(np.all(nddss[ref_ds] <= .09), msg="Should have reconstructed original dataset quite " "well even with zscoring. Got normed differences %s " "in %s case." % (nddss, snoisy)) # yoh: and leave 5% of difference for a chance and numerical # fluctuations ;) self.assertTrue(np.all(np.array(nddss) >= 0.95*nddss[ref_ds]), msg="Should have reconstructed orig_ds best of all. " "Got normed differences %s in %s case with ref_ds=%d." % (nddss, snoisy, ref_ds)) # Lets see how well we do if asked to compute residuals ha = Hyperalignment(ref_ds=ref_ds, level2_niter=2, enable_ca=['training_residual_errors', 'residual_errors']) mappers = ha(dss_rotated_clean) self.assertTrue(np.all(ha.ca.training_residual_errors.sa.levels == ['1', '2:0', '2:1'])) rterrors = ha.ca.training_residual_errors.samples # just basic tests: self.assertEqual(rterrors[0, ref_ds], 0) self.assertEqual(rterrors.shape, (3, n)) rerrors = ha.ca.residual_errors.samples self.assertEqual(rerrors.shape, (1, n))
def test_hyperalignment_measure(self): ref_ds = 0 fsha = FeatureSelectionHyperalignment() ds_orig, dss_rotated, dss_rotated_clean, Rs = self.get_testdata() # Lets test two scenarios -- in one with no noise -- we should get # close to perfect reconstruction. If noisy features were added -- not so good for noisy, dss in ((False, dss_rotated_clean), (True, dss_rotated)): # to verify that original datasets didn't get changed by # Hyperalignment store their idhashes of samples idhashes = [idhash(ds.samples) for ds in dss] idhashes_targets = [idhash(ds.targets) for ds in dss] mappers = fsha(dss) mappers = [ StaticProjectionMapper(proj=m, recon=m.T) for m in mappers ] idhashes_ = [idhash(ds.samples) for ds in dss] idhashes_targets_ = [idhash(ds.targets) for ds in dss] self.assertEqual( idhashes, idhashes_, msg="Hyperalignment must not change original data.") self.assertEqual( idhashes_targets, idhashes_targets_, msg="Hyperalignment must not change original data targets.") # Map data back dss_clean_back = [m.forward(ds_) for m, ds_ in zip(mappers, dss)] _ = [zscore(sd, chunks_attr=None) for sd in dss_clean_back] nddss = [] ndcss = [] nf = ds_orig.nfeatures ds_norm = np.linalg.norm(dss[ref_ds].samples[:, :nf]) ds_orig_Rref = np.dot(ds_orig.samples, Rs[ref_ds]) \ * np.sign(dss_rotated_clean[ref_ds].a.random_scale) zscore(ds_orig_Rref, chunks_attr=None) for ds_back in dss_clean_back: ndcs = np.diag(np.corrcoef(ds_back.samples.T[:nf, ], ds_orig_Rref.T)[nf:, :nf], k=0) ndcss += [ndcs] dds = ds_back.samples[:, :nf] - ds_orig_Rref ndds = np.linalg.norm(dds) / ds_norm nddss += [ndds] # First compare correlations snoisy = ('clean', 'noisy')[int(noisy)] self.assertTrue( np.all(np.array(ndcss) >= (0.9, 0.8)[int(noisy)]), msg="Should have reconstructed original dataset more or" " less. Got correlations %s in %s case." % (ndcss, snoisy)) # normed differences self.assertTrue( np.all(np.array(nddss) <= (.2, 3)[int(noisy)]), msg="Should have reconstructed original dataset more or" " less for all. Got normed differences %s in %s case." % (nddss, snoisy)) self.assertTrue( nddss[ref_ds] <= (.1, 0.4)[int(noisy)], msg="Should have reconstructed original dataset quite " "well even with zscoring. Got normed differences %s " "in %s case." % (nddss, snoisy)) self.assertTrue( np.all( np.array(nddss) / nddss[ref_ds] >= (0.95, 0.8)[int(noisy)]), msg="Should have reconstructed orig_ds best of all. " "Got normed differences %s in %s case with ref_ds=%d." % (nddss, snoisy, ref_ds)) # Testing feature selection within the measure using fraction and count # same features fsha_fsf = FeatureSelectionHyperalignment(featsel=0.5) fsha_fsn = FeatureSelectionHyperalignment(featsel=4) fsha_fsf_same = FeatureSelectionHyperalignment(featsel=0.5, use_same_features=True) fsha = FeatureSelectionHyperalignment(full_matrix=False) # check for valueerror if full_matrix=False and no roi_seed fa self.assertRaises(ValueError, fsha, dss_rotated) fsha = FeatureSelectionHyperalignment() dss_rotated[ref_ds].fa['roi_seed'] = [1, 0, 0, 0, 0, 0, 0, 0] mappers_fsf = fsha_fsf(dss_rotated) mappers_fsf_same = fsha_fsf_same(dss_rotated) mappers_fsn = fsha_fsn(dss_rotated) mappers = fsha(dss_rotated_clean) mappers_diffsizedss = fsha_fsf([ sd[:, nfs] for nfs, sd in zip([ np.arange(5), np.random.permutation(np.arange(8)), np.arange(8)[::-1], np.arange(8) ], dss_rotated) ]) # Testing that most of noisy features are eliminated from reference data assert_true( np.alltrue([np.sum(m[:4, :4].std(0) > 0) > 2 for m in mappers_fsf])) # using same features make it most likely to eliminate all noisy features assert_true( np.alltrue( [np.sum(m[:4, :4].std(0) > 0) == 4 for m in mappers_fsf_same])) assert_true( np.alltrue([np.sum(m[:4, :4].std(0) > 0) > 2 for m in mappers_fsn])) # And it correctly maps the selected features if they are selected if np.alltrue([np.all(m[4:, :4] == 0) for m in mappers_fsf]): for m, mfs in zip(mappers, mappers_fsf): assert_array_equal(m, mfs[:4, :4]) if np.alltrue([np.all(m[4:, :4] == 0) for m in mappers_fsf_same]): for m, mfs in zip(mappers, mappers_fsf_same): assert_array_equal(m, mfs[:4, :4]) # testing roi_seed forces feature selection dss_rotated[ref_ds].fa['roi_seed'] = [0, 0, 0, 0, 0, 0, 0, 1] fsha_fsf = FeatureSelectionHyperalignment(featsel=0.5) mappers_fsf = fsha_fsf(dss_rotated) assert (np.alltrue([np.sum(m[7, :] == 0) == 4 for m in mappers_fsf]))