@@ -910,6 +910,179 @@ def test_find_shelling_scheme_array(bvals, exp_scheme, exp_bval_groups, exp_bval
910910 assert np .allclose (obt_bval_estimated , exp_bval_estimated )
911911
912912
913+ @pytest .mark .parametrize (
914+ "bvals" ,
915+ [
916+ np .asarray (
917+ [
918+ 5 ,
919+ 300 ,
920+ 305 ,
921+ 5 ,
922+ 1005 ,
923+ 995 ,
924+ 1000 ,
925+ 1005 ,
926+ 5 ,
927+ 995 ,
928+ 1000 ,
929+ 995 ,
930+ 995 ,
931+ 5 ,
932+ 2005 ,
933+ 2000 ,
934+ 2005 ,
935+ 2005 ,
936+ 1995 ,
937+ ]
938+ )
939+ ],
940+ )
941+ @pytest .mark .parametrize (
942+ "num_bins, multishell_nonempty_bin_count_thr, bval_cap, exp_scheme, exp_bval_groups, exp_bval_estimated" ,
943+ [
944+ # Low multi-shell bin count threshold value
945+ (
946+ 4 ,
947+ 3 ,
948+ 2500 ,
949+ "DSI" ,
950+ [
951+ [5 , 300 , 305 , 5 , 5 , 5 ],
952+ [995 , 1000 , 995 , 1000 , 995 , 995 ],
953+ [1005 , 1005 ],
954+ [2005 , 2000 , 2005 , 2005 , 1995 ],
955+ ],
956+ [5.0 , 995.0 , 1005.0 , 2005.0 ],
957+ ),
958+ (
959+ 5 ,
960+ 3 ,
961+ 2500 ,
962+ "DSI" ,
963+ [
964+ [5 , 300 , 305 , 5 , 5 , 5 ],
965+ [1005 , 995 , 1000 , 1005 , 995 , 1000 , 995 , 995 ],
966+ [2005 , 2000 , 2005 , 2005 , 1995 ],
967+ ],
968+ [5.0 , 997.5 , 2005.0 ],
969+ ),
970+ # Fewer bins: ensure function still returns a consistent scheme
971+ (
972+ 3 ,
973+ 3 ,
974+ 2500 ,
975+ "DSI" ,
976+ [
977+ [5 , 300 , 305 , 5 , 5 , 5 ],
978+ [1005 , 995 , 1000 , 1005 , 995 , 1000 , 995 , 995 ],
979+ [2005 , 2000 , 2005 , 2005 , 1995 ],
980+ ],
981+ [5.0 , 997.5 , 2005.0 ],
982+ ),
983+ # Tighter cap: high shells beyond cap should be handled
984+ (
985+ 5 ,
986+ 3 ,
987+ 1500 ,
988+ "DSI" ,
989+ [[5 , 5 , 5 , 5 ], [300 , 305 ], [1005 , 995 , 1000 , 1005 , 995 , 1000 , 995 , 995 ]],
990+ [5.0 , 302.5 , 997.5 ],
991+ ),
992+ # Increase threshold to determine as multi-shell
993+ (
994+ 3 ,
995+ 6 ,
996+ 2500 ,
997+ "multi-shell" ,
998+ [
999+ [5 , 300 , 305 , 5 , 5 , 5 ],
1000+ [1005 , 995 , 1000 , 1005 , 995 , 1000 , 995 , 995 ],
1001+ [2005 , 2000 , 2005 , 2005 , 1995 ],
1002+ ],
1003+ [5.0 , 997.5 , 2005.0 ],
1004+ ),
1005+ (
1006+ 4 ,
1007+ 10 ,
1008+ 2500 ,
1009+ "multi-shell" ,
1010+ [
1011+ [5 , 300 , 305 , 5 , 5 , 5 ],
1012+ [995 , 1000 , 995 , 1000 , 995 , 995 ],
1013+ [1005 , 1005 ],
1014+ [2005 , 2000 , 2005 , 2005 , 1995 ],
1015+ ],
1016+ [5.0 , 995.0 , 1005.0 , 2005.0 ],
1017+ ),
1018+ # Decrease num bins to determine as single-shell
1019+ (
1020+ 2 ,
1021+ 10 ,
1022+ 2500 ,
1023+ "single-shell" ,
1024+ [
1025+ [5 , 300 , 305 , 5 , 995 , 1000 , 5 , 995 , 1000 , 995 , 995 , 5 ],
1026+ [1005 , 1005 , 2005 , 2000 , 2005 , 2005 , 1995 ],
1027+ ],
1028+ [650.0 , 2000.0 ],
1029+ ),
1030+ # Limit high-shell cap
1031+ (
1032+ 2 ,
1033+ 10 ,
1034+ 1000 ,
1035+ "single-shell" ,
1036+ [[5 , 300 , 305 , 5 , 5 , 5 ], [995 , 1000 , 995 , 1000 , 995 , 995 ]],
1037+ [5.0 , 995.0 ],
1038+ ),
1039+ ],
1040+ )
1041+ def test_find_shelling_scheme_params (
1042+ bvals ,
1043+ num_bins ,
1044+ multishell_nonempty_bin_count_thr ,
1045+ bval_cap ,
1046+ exp_scheme ,
1047+ exp_bval_groups ,
1048+ exp_bval_estimated ,
1049+ ):
1050+ """Test find_shelling_scheme on the same bvals vector with different
1051+ parameter settings.
1052+
1053+ For the baseline parameter set we assert exact equality against the known expected
1054+ scheme, groups and estimated b-values. For other parameter sets we assert structural
1055+ invariants and basic sanity checks (no unexpected shapes, estimated b-values within
1056+ the provided cap when applicable, and that groups contain only b-values from the input).
1057+ """
1058+ obt_scheme , obt_bval_groups , obt_bval_estimated = find_shelling_scheme (
1059+ bvals ,
1060+ num_bins = num_bins ,
1061+ multishell_nonempty_bin_count_thr = multishell_nonempty_bin_count_thr ,
1062+ bval_cap = bval_cap ,
1063+ )
1064+
1065+ # Basic structural checks
1066+ assert obt_scheme == exp_scheme
1067+ assert isinstance (obt_bval_groups , list )
1068+ assert isinstance (obt_bval_estimated , list )
1069+
1070+ # Estimated values length should match number of groups
1071+ assert len (obt_bval_estimated ) == len (obt_bval_groups )
1072+
1073+ # Compare groups and estimated bvals: same number and same elements (order-preserving)
1074+ assert all (
1075+ np .allclose (obt_arr , exp_arr )
1076+ for obt_arr , exp_arr in zip (obt_bval_groups , exp_bval_groups , strict = True )
1077+ )
1078+
1079+ # If a finite bval_cap is given, make sure estimated bvals don't exceed it
1080+ if np .isfinite (bval_cap ):
1081+ for est in np .asarray (obt_bval_estimated ).ravel ():
1082+ assert est <= bval_cap + 1e-8 # Tiny tolerance
1083+ assert np .allclose (obt_bval_estimated , exp_bval_estimated )
1084+
1085+
9131086@pytest .mark .parametrize (
9141087 ("dwi_btable" , "exp_scheme" , "exp_bval_groups" , "exp_bval_estimated" ),
9151088 [
0 commit comments