-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlf2mpr_nrt.pdl
More file actions
executable file
·145 lines (138 loc) · 5.69 KB
/
Copy pathlf2mpr_nrt.pdl
File metadata and controls
executable file
·145 lines (138 loc) · 5.69 KB
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
#!/homef/nabil/perl5/perlbrew/perls/perl-5.42.0/bin/perl
use v5.38;
use FindBin qw($RealBin);
use lib "$RealBin/lib";
use AIALimbfit::DrmsRuntime qw(configure_drms_environment validate_drms_runtime show_info_lines);
use AIALimbfit::Inventory qw(limb_path);
use AIALimbfit::LimbfitCommand qw(validate_limbfit_args);
use AIALimbfit::Reducer qw(kwd_lines masterpoint_filename reduce_limb_points);
use AIALimbfit::Slot qw(tstr2ts);
use Getopt::Long;
use File::Path qw(make_path);
use PDL::IO::Misc;
use Scalar::Util qw(looks_like_number);
my $config_file = $ENV{AIA_LIMBFIT_CONFIG} // "$RealBin/config.pl";
my $cfg = do $config_file or die "Cannot load $config_file: " . ( $@ || $! );
my ( $yr, $mo, $da, $hr );
my $inpdir = $cfg->{fits_root};
my $outdir = $cfg->{pointing_dir};
my ( $previous, $next );
my @requested_wavelengths;
GetOptions(
'year=i' => \$yr,
'month=i' => \$mo,
'day=i' => \$da,
'hour=i' => \$hr,
'inpdir=s' => \$inpdir,
'outdir=s' => \$outdir,
'wavel=i@' => \@requested_wavelengths,
'interpolate-previous=s' => \$previous,
'interpolate-next=s' => \$next,
) or die "Invalid options\n";
die "--year, --month, --day, and --hour are required\n"
unless defined $yr && defined $mo && defined $da && defined $hr;
validate_limbfit_args( year => $yr, month => $mo, day => $da, hour => $hr );
validate_limbfit_args(
year => $yr,
month => $mo,
day => $da,
hour => $hr,
wavelength => $_,
wavelengths => $cfg->{wl}
) for @requested_wavelengths;
die "Hour must be on the $cfg->{cadence_h}-hour cadence\n" if $hr % $cfg->{cadence_h};
die "Input and output directories must not be empty\n"
unless defined $inpdir && length($inpdir) && defined $outdir && length($outdir);
die "Interpolation requires both --interpolate-previous and --interpolate-next\n"
if defined($previous) != defined($next);
umask 0002;
my %seen;
my @wl = @requested_wavelengths ? grep { !$seen{$_}++ } @requested_wavelengths : @{ $cfg->{wl} };
my $outbase = masterpoint_filename( $yr, $mo, $da, $hr, $cfg->{cadence_h} );
my $outnam = "$outdir/$outbase";
my $slot = sprintf '%04d-%02d-%02dT%02d:00:00Z', $yr, $mo, $da, $hr;
unlink $outnam or die "Cannot remove stale '$outnam': $!\n" if -e $outnam;
my @kwd;
if ( defined $previous ) {
configure_drms_environment($cfg);
validate_drms_runtime( $cfg->{show_info} );
my ( $target_epoch, $previous_epoch, $next_epoch ) =
( tstr2ts($slot), tstr2ts($previous), tstr2ts($next) );
die "Invalid interpolation timestamp\n"
unless defined $target_epoch && defined $previous_epoch && defined $next_epoch;
die "Interpolation target must be strictly between its sources\n"
if $previous_epoch >= $target_epoch || $target_epoch >= $next_epoch;
my @keys = map { ( sprintf( 'A_%.3d_X0', $_ ), sprintf( 'A_%.3d_Y0', $_ ) ) } @wl;
my @source;
for my $time ( $previous, $next ) {
my @lines = show_info_lines(
$cfg->{show_info}, '-q',
'key=' . join( q{,}, @keys ),
sprintf( '%s[%s]', $cfg->{mpt_series}, $time )
);
chomp @lines;
@lines = grep { /\S/ } @lines;
die "Expected one pointing record at $time, found " . scalar(@lines) . "\n" unless @lines == 1;
my @values = split /\s+/, $lines[0];
die "Incomplete pointing record at $time\n" unless @values == @keys;
for my $i ( 0 .. $#values ) {
die "Cannot interpolate $keys[$i]: invalid value '$values[$i]' at $time\n"
if !looks_like_number( $values[$i] )
|| $values[$i] =~ /(?:nan|inf)/i
|| ( defined $cfg->{nan_sentinel} && $values[$i] == $cfg->{nan_sentinel} );
}
push @source, \@values;
}
my $fraction = ( $target_epoch - $previous_epoch ) / ( $next_epoch - $previous_epoch );
for my $i ( 0 .. $#wl ) {
push @kwd,
kwd_lines(
$wl[$i],
$source[0][ $i * 2 ] + $fraction * ( $source[1][ $i * 2 ] - $source[0][ $i * 2 ] ),
$source[0][ $i * 2 + 1 ] + $fraction * ( $source[1][ $i * 2 + 1 ] - $source[0][ $i * 2 + 1 ] )
);
}
warn "INTERPOLATION OK slot=$slot previous=$previous next=$next fraction=$fraction\n";
}
else {
my @missing = grep { !-s limb_path( $inpdir, $yr, $mo, $da, $hr, $_ ) } @wl;
die "Missing or empty limb files: " . join( ', ', map { "${_}A" } @missing ) . "\n" if @missing;
my @failed;
for my $w (@wl) {
my $path = limb_path( $inpdir, $yr, $mo, $da, $hr, $w );
my ( $xavg, $yavg );
my $reduced = eval {
my ( $x0, $y0 ) = rcols $path, 0, 1;
( undef, undef, $xavg, $yavg ) = reduce_limb_points( $x0, $y0, $w, $cfg );
1;
};
my $failure = $@;
$failure = "non-finite reducer result\n"
if $reduced && ( "$xavg" =~ /(?:nan|inf)/i || "$yavg" =~ /(?:nan|inf)/i );
if ( !$reduced || $failure ) {
chomp $failure;
warn "REDUCER FAIL slot=$slot wavelength=${w}A reason=$failure\n";
push @failed, "${w}A: $failure";
next;
}
push @kwd, kwd_lines( $w, $xavg, $yavg );
}
die "Reducer failed for $slot: " . join( '; ', @failed ) . "\n" if @failed;
}
make_path( $outdir, { chmod => oct('755') } ) unless -d $outdir;
my $temporary = "$outnam.$$";
my $written = eval {
open my $fh, '>', $temporary or die "Can't open '$temporary' for writing: $!\n";
print {$fh} @kwd;
close $fh or die "Can't close '$temporary': $!\n";
rename $temporary, $outnam or die "Can't replace '$outnam': $!\n";
1;
};
if ( !$written ) {
my $error = $@ || "Unknown write failure\n";
unlink $temporary if -e $temporary;
die $error;
}
my $partial_note =
@requested_wavelengths ? q{ partial=} . join( q{,}, map { $_ . q{A} } @wl ) : q{};
warn q{MASTERPOINT OK slot=} . $slot . q{ output=} . $outnam . $partial_note . "\n";