File Coverage

blib/lib/PDL/Algorithm/Center.pm
Criterion Covered Total %
statement 214 229 93.4
branch 56 82 68.2
condition 24 40 60.0
subroutine 33 34 97.0
pod 2 2 100.0
total 329 387 85.0


line stmt bran cond sub pod time code
1             package PDL::Algorithm::Center;
2              
3             # ABSTRACT: Various methods of finding the center of a sample
4              
5 2     2   438539 use strict;
  2         5  
  2         89  
6 2     2   12 use warnings;
  2         6  
  2         212  
7              
8             require v5.10;
9              
10 2     2   15 use feature 'state';
  2         4  
  2         479  
11              
12             our $VERSION = '0.15';
13              
14 2     2   18 use Carp;
  2         5  
  2         176  
15              
16 2     2   1145 use Try::Tiny;
  2         5679  
  2         158  
17 2     2   1342 use Safe::Isa;
  2         1520  
  2         356  
18 2     2   1388 use Ref::Util qw< is_arrayref is_ref is_coderef is_hashref >;
  2         7342  
  2         298  
19              
20 2     2   1949 use Hash::Wrap ( { -as => '_wrap_hash' } );
  2         12993  
  2         18  
21              
22 2     2   5043 use PDL::Algorithm::Center::Failure ':all';
  2         8  
  2         360  
23              
24 2     2   1070 use PDL::Algorithm::Center::Types -all;
  2         12  
  2         35  
25 2     2   27214 use Types::Standard qw[ Optional ArrayRef Undef CodeRef Num ];
  2         4  
  2         18  
26 2     2   8353 use Types::Common::Numeric -types;
  2         56855  
  2         21  
27 2     2   6938 use Type::Params qw[ compile_named ];
  2         10751  
  2         23  
28              
29 2     2   1924 use PDL::Lite ();
  2         158492  
  2         70  
30              
31 2     2   16 use Exporter 'import';
  2         4  
  2         130  
32              
33             our @EXPORT_OK = qw[ sigma_clip iterate ];
34              
35             # as of Types::Standard 1.003_003, Bool coerces any value into a boolean,
36             # which we don't want.
37 2     2   13 use constant Bool => Types::Standard::Bool->no_coercions();
  2         3  
  2         13  
38              
39             sub _weighted_mean_center {
40 538     538   8526 my ( $coords, $mask, $weight, $total_weight ) = @_;
41              
42 538         2513 my $wmask = $mask * $weight;
43              
44 538   66     245222 $total_weight //= $wmask->dsum;
45              
46 538 50       3548 iteration_empty_failure->throw( 'weighted mean center: all elements excluded or sum(weight) == 0' )
47             if $total_weight == 0;
48              
49 538         65474 return ( $coords * $wmask->dummy( 0 ) )->xchg( 0, 1 )->dsumover / $total_weight;
50             }
51              
52             sub _distance {
53              
54 525     525   1620 my ( $prev, $current ) = @_;
55              
56 525         14225 return sqrt( ( ( $prev->center - $current->center )**2 )->dsum );
57             }
58              
59             sub _sigma_clip_initialize { ## no critic (Subroutines::ProhibitManyArgs)
60              
61 20     20   75 my ( $init_clip, undef, $coords, $mask, $weight, $current, $work ) = @_;
62              
63             # initialize the sigma_clip specific fields the docs promise will be there
64 20         70 $current->{dist} = undef;
65 20         79 $current->{clip} = $init_clip;
66              
67 20         142 my $r2 = $work->{r2} = PDL->null;
68 20         900 $r2 .= ( ( $coords - $current->center )**2 )->dsumover;
69              
70 20 100       178022 $mask *= ( $r2 <= $init_clip**2 )
71             if defined $init_clip;
72              
73 20         2105 my $wmask = $work->{wmask} = $mask * $weight;
74              
75 20         5804 $current->total_weight( $wmask->dsum );
76 20         3637 $current->nelem( $mask->sum );
77              
78 20 50       3350 if ( $current->total_weight == 0 ) {
79 0         0 $current->{sigma} = undef;
80 0         0 iteration_empty_failure->throw( 'sigma_clip initialize: all elements excluded or sum(weight) == 0',
81             );
82             }
83              
84 20         2759 $current->{sigma} = sqrt( ( $wmask * $r2 )->dsum / $current->total_weight );
85              
86 20         6158 return;
87             }
88              
89             sub _sigma_clip_calc_wmask { ## no critic (Subroutines::ProhibitManyArgs)
90              
91 530     530   1937 my ( $nsigma, $coords, $mask, $weight, $iter, $work ) = @_;
92              
93 530         1650 my $r2 = $work->{r2};
94 530         10764 $r2 .= ( ( $coords - $iter->center )**2 )->dsumover;
95              
96 530         7416539 $iter->clip( $nsigma * $iter->sigma );
97              
98 530         64315 $mask *= $r2 < $iter->clip**2;
99              
100 530         430159 $iter->total_weight( ( $mask * $weight )->dsum );
101 530         398927 $iter->nelem( $mask->sum );
102              
103 530         94666 my $wmask = $work->{wmask};
104 530         2749 $wmask .= $mask * $weight;
105              
106 530 100       372115 iteration_empty_failure->throw( 'sigma_clip calc_wmask: all elements excluded or sum(weight) == 0' )
107             if $iter->total_weight == 0;
108              
109 525         72311 $iter->sigma( sqrt( ( $wmask * $r2 )->dsum / $iter->total_weight ) );
110              
111 525         306962 return;
112             }
113              
114             sub _sigma_clip_is_converged { ## no critic (Subroutines::ProhibitManyArgs)
115              
116 525     525   2361 my ( undef, $dtol, undef, undef, undef, $prev, $current ) = @_;
117              
118 525         2891 $current->{dist} = undef;
119              
120             # stop if standard deviations and centers haven't changed
121              
122 525 100 66     11329 if ( $current->sigma == $prev->sigma
123             && PDL::all( $current->center == $prev->center ) )
124             {
125              
126 5 50       2437 $current->dist( _distance( $prev, $current ) )
127             if defined $dtol;
128              
129 5         1397 return 1;
130             }
131              
132             # or, if a tolerance was defined, stop if distance from old
133             # to new centers is less than the tolerance.
134 520 50       57779 if ( defined $dtol ) {
135 520         2335 $current->dist( _distance( $prev, $current ) );
136 520 100       81014 return 1 if $current->dist <= $dtol;
137             }
138              
139 510         52661 return 0;
140             }
141              
142             sub _sigma_clip_log_iteration {
143              
144 0     0   0 my $iter = shift;
145              
146             # iter n clip sigma x y
147             # xxxx xxxxxxx xxxxxxxxxx xxxxxxxxxx xxxxxxxxxx xxxxxxxxxx
148              
149 0         0 my $ncoords = $iter->center->nelem;
150 0 0       0 if ( $iter->iter == 0 ) {
151              
152 0         0 my $fmt = '%4s %7s' . ' %10s' x ( 3 + $ncoords ) . "\n";
153              
154             printf $fmt, @$_
155 0         0 for [ qw{ iter nelem weight clip sigma }, map { 'q$_' } 1 .. $ncoords, ],
  0         0  
156             [ qw{ ---- ------- ---------- ---------- ----------}, ( '----------' ) x $ncoords, ];
157             }
158              
159 0         0 my @fmt = ( '%4d', '%7d', ( '%10.6g' ) x ( 3 + $ncoords ) );
160 0 0       0 $fmt[3] = '%10s' if !defined $iter->clip;
161              
162 0   0     0 printf(
163             join( q{ }, @fmt ) . "\n",
164             $iter->iter, $iter->nelem, $iter->total_weight, $iter->clip // 'undef',
165             $iter->sigma, $iter->center->list,
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             sub _to_json {
452 9     9   19432 my $obj = shift;
453              
454 9         812 require Data::Visitor::Tiny;
455 9         1477 require Data::Clone;
456 9         1145 require Scalar::Util;
457              
458             # remove outer blessed hash and clone everything except for the
459             # objects.
460 9         17 my $hash = Data::Clone::clone( { %{$obj} } );
  9         231  
461              
462             # now replace the included objects
463             Data::Visitor::Tiny::visit(
464             $hash,
465             sub {
466 78 100   78   1433 return unless Scalar::Util::blessed( my $object = ${ $_[1] } );
  78         236  
467 54 100       672 ${ $_[1] }
  54 50       192  
    100          
468             = defined( $object->can( 'TO_JSON' ) )
469             ? $object->TO_JSON
470             : $object->isa( 'PDL' ) ? $object->dims == 0
471             ? $object->unpdl->[0]
472             : $object->unpdl
473             : "$object";
474             },
475 9         109 $hash,
476             );
477 9         139 return $hash;
478             }
479              
480             use Hash::Wrap ( {
481             -as => '_new_iteration',
482             -class => 'PDL::Algorithm::Center::Iteration',
483             -clone => sub {
484 550         9203 my $hash = shift;
485              
486             ## no critic (BuiltinFunctions::ProhibitComplexMappings)
487             return {
488             map {
489 550         3748 my $value = $hash->{$_};
  3790         6664  
490 3790 100       9926 $value = $value->copy if $value->$_isa( 'PDL' );
491 3790         110423 ( $_, $value )
492             } keys %$hash,
493             };
494             },
495 2         65 -methods => { TO_JSON => \&_to_json },
496             },
497             {
498             -as => '_return_iterate_results',
499             -class => 'PDL::Algorithm::Center::Iterate::Results',
500             -methods => { TO_JSON => \&_to_json },
501 2     2   4346 } );
  2         5  
502              
503             sub sigma_clip {
504              
505 41     41 1 1137557 state $check = compile_named(
506             center => Optional [ ArrayRef [ Num | Undef ] | Center | CodeRef ],
507             clip => Optional [PositiveNum],
508             coords => Optional [Coords],
509             dtol => PositiveNum,
510             iterlim => Optional [PositiveInt],
511             log => Optional [ Bool | CodeRef ],
512             mask => Optional [ Undef | Piddle_min1D_ne ],
513             save_mask => Optional [Bool],
514             save_weight => Optional [Bool],
515             nsigma => PositiveNum,
516             weight => Optional [ Undef | Piddle_min1D_ne ],
517             );
518              
519 41         262112 my $opt;
520 41         253 my @argv = @_;
521             try {
522 41     41   2370 my %opt = %{ $check->( @argv ); };
  41         213  
523 23         5651 $opt = _wrap_hash( \%opt );
524             }
525             catch {
526 18     18   16961 parameter_failure->throw( $_ );
527 41         446 };
528              
529 23   100     953 $opt->{iterlim} //= 10;
530              
531 23 50 33     125 if ( defined $opt->{log} && !is_coderef( $opt->log ) ) {
532 0 0       0 $opt->{log} = $opt->log ? \&_sigma_clip_log_iteration : undef;
533             }
534              
535             #---------------------------------------------------------------
536              
537             # now, see what kind of data we have, and ensure that all dimensions
538             # are consistent
539              
540 23 100       85 if ( defined $opt->{coords} ) {
    100          
541              
542 21         73 for my $name ( 'mask', 'weight' ) {
543              
544 41         110 my $value = $opt->{$name};
545 41 100       135 next unless defined $value;
546              
547 6 50       36 parameter_failure->throw( "<$name> must be a 1D piddle if is specified" )
548             if $value->ndims != 1;
549              
550 6         28 my $nelem_c = $value->getdim( -1 );
551 6         185 my $nelem_p = $opt->coords->getdim( -1 );
552              
553 6 100       108 parameter_failure->throw(
554             "number of elements in <$name> ($nelem_p) ) must be the same as in ($nelem_c)", )
555             if $nelem_c != $nelem_p;
556             }
557              
558             }
559              
560             elsif ( defined $opt->{weight} ) {
561              
562 1         28 $opt->{coords} = $opt->weight->ndcoords( PDL::indx );
563              
564 1 50       204 if ( defined $opt->{mask} ) {
565 0 0       0 parameter_failure->throw( "mask must have same shape as weight\n" )
566             if $opt->mask->shape != $opt->weight->shape;
567              
568 0         0 $opt->mask( $opt->mask->flat );
569             }
570              
571 1         34 $opt->weight( $opt->weight->flat );
572             }
573              
574             else {
575              
576 1         7 parameter_failure->throw( 'must specify one of or ' );
577             }
578              
579 20         597 my ( $ndims ) = $opt->coords->dims;
580              
581 20 100 100     1216 if ( defined $opt->{center} && is_arrayref( $opt->center ) ) {
582              
583 5         79 my $icenter = PDL->pdl( @{ $opt->center } );
  5         99  
584              
585 5 50       452 parameter_failure->throw( "
must have $ndims elements" )
586             unless $icenter->nelem == $ndims;
587              
588 5         16 my $defined = PDL->pdl( map { defined } @{ $opt->center } );
  9         74  
  5         119  
589              
590 5 100       460 if ( $defined->not->any ) {
591              
592 3         284 $icenter = $icenter->where( $defined )->sever;
593              
594             $opt->{center} = sub {
595              
596 3     3   189 my ( $coords, $wmask, $weight ) = @_;
597 3         21 my $center = _weighted_mean_center( $coords, $wmask, $weight );
598 3         11651 $center->where( $defined ) .= $icenter;
599              
600 3         952 return $center;
601 3         581 };
602             }
603             }
604             else {
605              
606 15   100     151 $opt->{center} //= \&_weighted_mean_center;
607             }
608              
609 20         384 my $nsigma = delete $opt->{nsigma};
610             $opt->{calc_wmask} //= sub {
611 530     530   24517 _sigma_clip_calc_wmask( $nsigma, @_ );
612 525         1639 return;
613 20   33     214 };
614              
615             $opt->{calc_center} //= sub {
616 525     525   24619 my ( $coords, $mask, $weight, $iter ) = @_;
617              
618 525         11058 _weighted_mean_center( $coords, $mask, $weight, $iter->total_weight );
619 20   33     151 };
620              
621 20         64 my ( $clip, $dtol ) = delete @{$opt}{ 'clip', 'dtol' };
  20         86  
622             $opt->{initialize} = sub {
623 20     20   1585 _sigma_clip_initialize( $clip, $dtol, @_ );
624 20         139 };
625              
626             $opt->{is_converged} = sub {
627 525     525   26070 _sigma_clip_is_converged( $clip, $dtol, @_ );
628 20         93 };
629              
630 20         110 delete @{$opt}{ grep { !defined $opt->{$_} } keys %$opt };
  20         44  
  145         306  
631              
632 20         128 iterate( %$opt );
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              
666              
667              
668              
669              
670              
671              
672              
673              
674              
675              
676              
677              
678              
679              
680              
681              
682              
683              
684              
685              
686              
687              
688              
689              
690              
691              
692              
693              
694              
695              
696              
697              
698              
699              
700              
701              
702              
703              
704              
705              
706              
707              
708              
709              
710              
711              
712              
713              
714              
715              
716              
717              
718              
719              
720              
721              
722              
723              
724              
725              
726              
727              
728              
729              
730              
731              
732              
733              
734              
735              
736              
737              
738              
739              
740              
741              
742              
743              
744              
745              
746              
747              
748              
749              
750              
751              
752              
753              
754              
755              
756              
757              
758              
759              
760              
761              
762              
763              
764              
765              
766              
767              
768              
769              
770              
771              
772              
773              
774              
775              
776              
777              
778              
779              
780              
781              
782              
783              
784              
785              
786              
787              
788              
789              
790              
791              
792              
793              
794              
795              
796              
797              
798              
799              
800              
801              
802              
803              
804              
805              
806              
807              
808              
809              
810              
811              
812              
813              
814              
815              
816              
817              
818              
819              
820              
821              
822              
823              
824              
825              
826              
827              
828              
829              
830              
831              
832              
833              
834              
835              
836              
837              
838              
839              
840              
841              
842              
843              
844              
845              
846              
847              
848              
849              
850              
851              
852              
853              
854              
855              
856              
857              
858              
859              
860              
861              
862              
863              
864              
865              
866              
867              
868              
869              
870              
871              
872              
873              
874              
875              
876              
877              
878              
879              
880              
881              
882              
883              
884              
885              
886              
887              
888              
889              
890              
891              
892              
893              
894              
895              
896              
897              
898              
899              
900              
901              
902              
903              
904              
905              
906              
907              
908              
909              
910              
911              
912              
913              
914              
915              
916              
917              
918              
919              
920              
921              
922              
923              
924              
925              
926              
927              
928              
929              
930              
931              
932              
933              
934              
935              
936              
937              
938              
939              
940              
941              
942              
943              
944              
945              
946              
947              
948              
949              
950              
951              
952              
953              
954              
955              
956              
957              
958              
959              
960              
961              
962              
963              
964              
965              
966              
967              
968              
969              
970              
971              
972              
973              
974              
975              
976              
977              
978              
979              
980              
981              
982              
983              
984              
985              
986              
987              
988              
989              
990              
991              
992              
993              
994              
995              
996              
997              
998              
999              
1000              
1001              
1002              
1003              
1004              
1005              
1006              
1007              
1008              
1009              
1010              
1011              
1012              
1013              
1014              
1015              
1016              
1017              
1018              
1019              
1020              
1021              
1022              
1023              
1024              
1025              
1026              
1027              
1028              
1029              
1030              
1031              
1032              
1033              
1034              
1035              
1036              
1037              
1038              
1039              
1040              
1041              
1042              
1043              
1044              
1045              
1046              
1047              
1048              
1049              
1050              
1051              
1052              
1053              
1054              
1055              
1056              
1057              
1058              
1059              
1060              
1061              
1062              
1063              
1064              
1065              
1066              
1067              
1068              
1069              
1070              
1071              
1072              
1073              
1074              
1075              
1076              
1077              
1078              
1079              
1080              
1081              
1082              
1083              
1084              
1085              
1086              
1087              
1088              
1089              
1090              
1091              
1092              
1093              
1094              
1095              
1096              
1097              
1098              
1099              
1100              
1101              
1102              
1103              
1104              
1105              
1106              
1107              
1108              
1109              
1110              
1111              
1112              
1113              
1114              
1115              
1116              
1117              
1118              
1119              
1120              
1121              
1122              
1123              
1124              
1125              
1126              
1127              
1128              
1129              
1130              
1131              
1132              
1133              
1134              
1135              
1136              
1137              
1138              
1139              
1140              
1141              
1142              
1143              
1144              
1145              
1146              
1147              
1148              
1149              
1150              
1151              
1152              
1153              
1154              
1155              
1156              
1157              
1158              
1159              
1160              
1161              
1162             sub iterate {
1163              
1164 20     20 1 46 state $check = compile_named(
1165             center => Center | CodeRef,
1166             initialize => CodeRef,
1167             calc_center => CodeRef,
1168             calc_wmask => CodeRef,
1169             is_converged => CodeRef,
1170             coords => Coords,
1171             iterlim => PositiveInt,
1172             log => Optional [CodeRef],
1173             mask => Optional [Piddle1D_ne],
1174             weight => Optional [Piddle1D_ne],
1175             save_mask => Optional [Bool],
1176             save_weight => Optional [Bool],
1177             );
1178              
1179 20         55584 my $opt = _wrap_hash( $check->( @_ ) );
1180              
1181 20   50     4174 $opt->{log} //= undef;
1182 20   50     142 $opt->{save_mask} //= 0;
1183 20   50     164 $opt->{save_weight} //= 0;
1184 20   100     113 $opt->{mask} //= undef;
1185 20   100     157 $opt->{weight} //= undef;
1186              
1187 20         523 my ( $ndims, $nelem ) = $opt->coords->dims;
1188              
1189             parameter_failure->throw( "<$_> must have $nelem elements" )
1190 20 100       301 for grep { defined $opt->{$_} && $opt->{$_}->nelem != $nelem } qw[ mask weight ];
  40         202  
1191              
1192 20 100       564 $opt->weight(
1193             defined $opt->weight
1194             ? PDL::convert( $opt->weight, PDL::double )
1195             : PDL->ones( PDL::double, $nelem ),
1196             );
1197              
1198 20         4720 my $total_weight;
1199              
1200 20 100       455 if ( defined $opt->mask ) {
1201 2         91 $nelem = $opt->mask->sum;
1202 2         388 $total_weight = ( $opt->mask * $opt->weight )->dsum;
1203             }
1204             else {
1205 18         888 $opt->mask( PDL->ones( PDL::long, $nelem ) );
1206 18         3020 $total_weight = $opt->weight->dsum;
1207             }
1208              
1209 20         2996 my $mask = $opt->mask->copy;
1210 20         8023 my $weight = $opt->weight->copy;
1211              
1212 20 100       5247 $opt->center( $opt->center->( $opt->coords, $mask, $weight, $total_weight ) )
1213             if is_coderef( $opt->center );
1214              
1215 20 50 33     6174 parameter_failure->throw( "
must be a 1D piddle with $ndims elements" )
1216             unless is_Piddle1D( $opt->center ) && $opt->center->nelem == $ndims;
1217              
1218             #############################################################################
1219              
1220             # Iterate until convergence.
1221              
1222 20         1344 my @iteration;
1223              
1224 20         48 my $work = {};
1225              
1226             # Set up initial state
1227              
1228 20         523 push @iteration,
1229             _new_iteration( {
1230             center => $opt->center,
1231             total_weight => $total_weight,
1232             nelem => $nelem,
1233             iter => 0,
1234             } );
1235              
1236 20         724 $mask .= $opt->mask;
1237 20         2425 $weight .= $opt->weight;
1238              
1239 20         2139 my $iteration = 0;
1240 20         60 my $converged;
1241             my $error;
1242              
1243 20 100       48 eval {
1244              
1245 20         560 $opt->initialize->( $opt->coords, $mask, $weight, $iteration[-1], $work, );
1246              
1247 20 50       605 $opt->log && $opt->log->( _new_iteration( $iteration[-1] ) );
1248              
1249 20   66     1413 while ( !$converged && ++$iteration <= $opt->iterlim ) {
1250              
1251 530         28129 my $prev = $iteration[-1];
1252              
1253 530         11742 my $current = _new_iteration( $prev );
1254 530         5420 push @iteration, $current;
1255              
1256 530         1440 ++$current->{iter};
1257              
1258 530         11668 $current->total_weight( $total_weight );
1259 530         17345 $current->nelem( $nelem );
1260              
1261 530         17083 $mask .= $opt->mask;
1262 530         110112 $weight .= $opt->weight;
1263              
1264 530         143030 $opt->calc_wmask->( $opt->coords, $mask, $weight, $current, $work );
1265              
1266 525 50       12320 $current->total_weight( ( $mask * $weight )->dsum )
1267             unless defined $current->total_weight;
1268 525 50       15311 $current->nelem( $mask->sum )
1269             unless defined $current->nelem;
1270              
1271 525 50       14961 iteration_empty_failure->throw( 'no elements left after clip' )
1272             if $current->nelem == 0;
1273              
1274 525         72575 $current->center( $opt->calc_center->( $opt->coords, $mask, $weight, $current, $work, ) );
1275              
1276 525         844540 $converged = $opt->is_converged->( $opt->coords, $mask, $weight, $prev, $current, $work, );
1277              
1278 525 50       15793 $opt->log && $opt->log->( _new_iteration( $current ) );
1279             }
1280 15         284 1;
1281             } or $error = $@;
1282              
1283 20 50       1571 $error
1284 0         0 = iteration_limit_reached_failure->new( msg => "iteration limit (@{[ $opt->iterlim ]}) reached" )
1285             if $iteration > $opt->iterlim;
1286              
1287             _return_iterate_results( {
1288 20 50       311 %{ $iteration[-1] },
  20 50       598  
1289             ( $opt->save_mask ? ( mask => $mask ) : () ),
1290             ( $opt->save_weight ? ( weight => $weight ) : () ),
1291             iterations => \@iteration,
1292             success => !$error,
1293             error => $error,
1294             } );
1295             }
1296              
1297             1;
1298              
1299             #
1300             # This file is part of PDL-Algorithm-Center
1301             #
1302             # This software is Copyright (c) 2017 by Smithsonian Astrophysical Observatory.
1303             #
1304             # This is free software, licensed under:
1305             #
1306             # The GNU General Public License, Version 3, June 2007
1307             #
1308              
1309             __END__