1 #====================================================================== |
1 #====================================================================== |
2 # L I B I M P . P L |
2 # L I B I M P . P L |
3 # doc: Tue Nov 26 21:59:40 2013 |
3 # doc: Tue Nov 26 21:59:40 2013 |
4 # dlm: Sat Jun 9 12:07:15 2018 |
4 # dlm: Mon Jul 1 15:47:57 2019 |
5 # (c) 2017 A.M. Thurnherr |
5 # (c) 2017 A.M. Thurnherr |
6 # uE-Info: 52 109 NIL 0 0 70 2 2 4 NIL ofnI |
6 # uE-Info: 689 0 NIL 0 0 70 2 2 4 NIL ofnI |
7 #====================================================================== |
7 #====================================================================== |
8 |
8 |
9 # HISTORY: |
9 # HISTORY: |
10 # Nov 26, 2013: - created |
10 # Nov 26, 2013: - created |
11 # Dec 1, 2013: - removed HDG_ROT |
11 # Dec 1, 2013: - removed HDG_ROT |
47 # May 25, 2018: - continued working |
47 # May 25, 2018: - continued working |
48 # May 30, 2018: - BUG: trimming did not re-calculate elapsed time |
48 # May 30, 2018: - BUG: trimming did not re-calculate elapsed time |
49 # Jun 5, 2018: - BUG: on -c main magnetometer and accelerometer vectors were |
49 # Jun 5, 2018: - BUG: on -c main magnetometer and accelerometer vectors were |
50 # modified twice |
50 # modified twice |
51 # Jun 7, 2018: - relaxed definition of -e |
51 # Jun 7, 2018: - relaxed definition of -e |
52 # Jun 9, 2018: - BUG: some "edge" data (beyond the valid profile) were bogus (does not matter in practice) |
52 # Jun 9, 2018: - BUG: some "edge" data (beyond the valid profile) were bogus (does |
|
53 # not matter in practice) |
|
54 # Jun 30, 2019: - renamed -s in IMP+LADCP to -o (option not used in KVH+LADCP) |
|
55 # - changed semantics so that offset histogram is plotted even on -o |
|
56 # - made create_merge_plots return errors |
|
57 # Jul 1, 2019: - BUG: pre-deployment output cleared IMU pitch/roll fields (1 record |
|
58 # affected) |
|
59 # - modified output of pre-/post-cast records to include all LADCP |
|
60 # but no IMU data |
|
61 # - BUG: GIMBAL_PITCH had not only been defined for in-water records |
53 |
62 |
54 #---------------------------------------------------------------------- |
63 #---------------------------------------------------------------------- |
55 # gRef() library |
64 # gRef() library |
56 #---------------------------------------------------------------------- |
65 #---------------------------------------------------------------------- |
57 |
66 |
347 sub prep_piro_LADCP($) |
356 sub prep_piro_LADCP($) |
348 { |
357 { |
349 my($verbose) = @_; |
358 my($verbose) = @_; |
350 |
359 |
351 my($LADCP_pitch_mean,$LADCP_roll_mean) = (0,0); |
360 my($LADCP_pitch_mean,$LADCP_roll_mean) = (0,0); |
|
361 for (my($ens)=0; $ens<=$#{$LADCP{ENSEMBLE}}; $ens++) { |
|
362 $LADCP{ENSEMBLE}[$ens]->{GIMBAL_PITCH} = |
|
363 gimbal_pitch($LADCP{ENSEMBLE}[$ens]->{PITCH},$LADCP{ENSEMBLE}[$ens]->{ROLL}); |
|
364 } |
352 for (my($ens)=$LADCP_begin; $ens<=$LADCP_end; $ens++) { |
365 for (my($ens)=$LADCP_begin; $ens<=$LADCP_end; $ens++) { |
353 $LADCP{ENSEMBLE}[$ens]->{GIMBAL_PITCH} = |
366 $LADCP{ENSEMBLE}[$ens]->{GIMBAL_PITCH} = |
354 gimbal_pitch($LADCP{ENSEMBLE}[$ens]->{PITCH},$LADCP{ENSEMBLE}[$ens]->{ROLL}); |
367 gimbal_pitch($LADCP{ENSEMBLE}[$ens]->{PITCH},$LADCP{ENSEMBLE}[$ens]->{ROLL}); |
355 $LADCP_pitch_mean += $LADCP{ENSEMBLE}[$ens]->{GIMBAL_PITCH}; |
368 $LADCP_pitch_mean += $LADCP{ENSEMBLE}[$ens]->{GIMBAL_PITCH}; |
356 $LADCP_roll_mean += $LADCP{ENSEMBLE}[$ens]->{ROLL}; |
369 $LADCP_roll_mean += $LADCP{ENSEMBLE}[$ens]->{ROLL}; |
396 printf(GMT "%f $dhist[$i]\n",$i*$dhist_binsize>180 ? $i*$dhist_binsize-360 : $i*$dhist_binsize); |
409 printf(GMT "%f $dhist[$i]\n",$i*$dhist_binsize>180 ? $i*$dhist_binsize-360 : $i*$dhist_binsize); |
397 } |
410 } |
398 GMT_psbasemap('-Bg45a90f15:"IMU Heading Offset [\260]":/ga100f10:"Frequency":WeSn'); |
411 GMT_psbasemap('-Bg45a90f15:"IMU Heading Offset [\260]":/ga100f10:"Frequency":WeSn'); |
399 GMT_unitcoords(); |
412 GMT_unitcoords(); |
400 GMT_pstext('-F+f14,Helvetica,CornFlowerBlue+jTR -N'); |
413 GMT_pstext('-F+f14,Helvetica,CornFlowerBlue+jTR -N'); |
401 printf(GMT "0.99 1.06 %g \260 offset (%d%% agreement)\n",angle($HDG_offset),100*$modefrac); |
414 if (defined($opt_o)) { |
|
415 printf(GMT "0.99 1.06 -o %g \260 offset (%d%% agreement)\n",angle($HDG_offset),100*$modefrac); |
|
416 } else { |
|
417 printf(GMT "0.99 1.06 %g \260 offset (%d%% agreement)\n",angle($HDG_offset),100*$modefrac); |
|
418 } |
402 GMT_pstext('-F+f14,Helvetica,blue+jTL -N'); |
419 GMT_pstext('-F+f14,Helvetica,blue+jTL -N'); |
403 printf(GMT "0.01 1.06 $P{profile_id} $opt_a\n"); |
420 printf(GMT "0.01 1.06 $P{profile_id} $opt_a\n"); |
404 GMT_end(); |
421 GMT_end(); |
405 } |
422 } |
406 |
423 |
447 } |
464 } |
448 |
465 |
449 printf(STDERR "\n\t\tIMU mean pitch/roll: %.1f/%.1f deg",$IMP_pitch_mean,$IMP_roll_mean) |
466 printf(STDERR "\n\t\tIMU mean pitch/roll: %.1f/%.1f deg",$IMP_pitch_mean,$IMP_roll_mean) |
450 if $verbose; |
467 if $verbose; |
451 |
468 |
452 if (defined($opt_s)) { |
469 my($dhist_binsize,$dhist_min_pirom,$dhist_min_mfrac) = split(/,/,$opt_e); |
453 $HDG_offset = $opt_s; |
470 croak("$0: cannot decode -e $opt_e\n") |
454 printf(STDERR "\n\tHEADING_OFFSET = %.1f (set by -s)\n",$HDG_offset) if $verbose; |
471 unless ($dhist_binsize > 0 && $dhist_min_pirom > 0 && $dhist_min_mfrac >= 0); |
455 } else { |
472 |
456 my($dhist_binsize,$dhist_min_pirom,$dhist_min_mfrac) = split(/,/,$opt_e); |
473 my(@dhist); my($nhist) = my($modeFreq) = 0; |
457 croak("$0: cannot decode -e $opt_e\n") |
474 for (my($ens)=$LADCP_begin; $ens<=$LADCP_end; $ens++) { |
458 unless ($dhist_binsize > 0 && $dhist_min_pirom > 0 && $dhist_min_mfrac >= 0); |
475 my($r) = int(($LADCP{ENSEMBLE}[$ens]->{ELAPSED_TIME} + $IMP{TIME_LAG} - $ants_[0][$elapsedF]) / $IMP{DT}); |
459 |
476 next unless numberp($IMP{TILT_AZIMUTH}[$r]); |
460 my(@dhist); my($nhist) = my($modeFreq) = 0; |
477 next unless (abs($ants_[$r][$pitchF]-$IMP_pitch_mean) >= $dhist_min_pirom && |
461 for (my($ens)=$LADCP_begin; $ens<=$LADCP_end; $ens++) { |
478 abs($ants_[$r][$rollF] -$IMP_roll_mean) >= $dhist_min_pirom); |
462 my($r) = int(($LADCP{ENSEMBLE}[$ens]->{ELAPSED_TIME} + $IMP{TIME_LAG} - $ants_[0][$elapsedF]) / $IMP{DT}); |
479 $dhist[int(angle_pos($LADCP{ENSEMBLE}[$ens]->{TILT_AZIMUTH}-$IMP{TILT_AZIMUTH}[$r])/$dhist_binsize+0.5)]++; |
463 next unless numberp($IMP{TILT_AZIMUTH}[$r]); |
480 $nhist++; |
464 next unless (abs($ants_[$r][$pitchF]-$IMP_pitch_mean) >= $dhist_min_pirom && |
481 } |
465 abs($ants_[$r][$rollF] -$IMP_roll_mean) >= $dhist_min_pirom); |
482 croak("$0: empty histogram\n") |
466 $dhist[int(angle_pos($LADCP{ENSEMBLE}[$ens]->{TILT_AZIMUTH}-$IMP{TILT_AZIMUTH}[$r])/$dhist_binsize+0.5)]++; |
483 unless ($nhist); |
467 $nhist++; |
484 |
468 } |
485 if (defined($opt_o)) { # set heading offset, either with -o |
469 croak("$0: empty histogram\n") |
486 $HDG_offset = $opt_o; |
470 unless ($nhist); |
487 } else { # or from the data |
471 |
|
472 $HDG_offset = 0; |
488 $HDG_offset = 0; |
473 for (my($i)=1; $i<@dhist-1; $i++) { # make sure mode is not on edge |
489 for (my($i)=1; $i<@dhist-1; $i++) { # make sure mode is not on edge |
474 $HDG_offset = $i if ($dhist[$i] >= $dhist[$HDG_offset]); |
490 $HDG_offset = $i if ($dhist[$i] >= $dhist[$HDG_offset]); |
475 } |
491 } |
476 my($modefrac) = ($dhist[$HDG_offset]+$dhist[$HDG_offset-1]+$dhist[$HDG_offset+1]) / $nhist; |
|
477 |
|
478 $HDG_offset *= $dhist_binsize; |
492 $HDG_offset *= $dhist_binsize; |
479 pl_hdg_offset($dhist_binsize,$modefrac,@dhist); |
493 } |
480 |
494 |
|
495 my($modefrac) = ($dhist[$HDG_offset]+$dhist[$HDG_offset-1]+$dhist[$HDG_offset+1]) / $nhist; |
|
496 pl_hdg_offset($dhist_binsize,$modefrac,@dhist); |
|
497 |
|
498 unless (defined($opt_o)) { # make sure data are consistent (unless -o is used) |
481 if ($opt_f) { |
499 if ($opt_f) { |
482 printf(STDERR "\n\nIGNORED WARNING (-f): Cannot determine reliable heading offset; $HDG_offset+/-$dhist_binsize deg accounts for only %f%% of total\n",$modefrac*100) |
500 printf(STDERR "\n\nIGNORED WARNING (-f): Cannot determine reliable heading offset; $HDG_offset+/-$dhist_binsize deg accounts for only %f%% of total\n",$modefrac*100) |
483 if ($modefrac < $dhist_min_mfrac); |
501 if ($modefrac < $dhist_min_mfrac); |
484 } else { |
502 } else { |
485 croak(sprintf("\n$0: Cannot determine reliable heading offset; $HDG_offset+/-$dhist_binsize deg accounts for only %f%% of total\n",$modefrac*100)) |
503 croak(sprintf("\n$0: Cannot determine reliable heading offset; $HDG_offset+/-$dhist_binsize deg accounts for only %f%% of total\n",$modefrac*100)) |
486 if ($modefrac < $dhist_min_mfrac); |
504 if ($modefrac < $dhist_min_mfrac); |
487 } |
505 } |
488 |
506 } |
489 printf(STDERR "\n\t") if $verbose; |
507 |
490 printf(STDERR "IMU heading offset = %g deg (%d%% agreement)\n",angle($HDG_offset),100*$modefrac) if $verbose; |
508 printf(STDERR "\n\t") if $verbose; |
491 } |
509 if ($opt_o) { |
|
510 printf(STDERR "IMU heading offset = -o %g deg (%d%% agreement)\n",angle($HDG_offset),100*$modefrac) |
|
511 if $verbose; |
|
512 } else { |
|
513 printf(STDERR "IMU heading offset = %g deg (%d%% agreement)\n",angle($HDG_offset),100*$modefrac) |
|
514 if $verbose; |
|
515 } |
|
516 |
492 return ($HDG_offset,$IMP_pitch_mean,$IMP_roll_mean); |
517 return ($HDG_offset,$IMP_pitch_mean,$IMP_roll_mean); |
493 } |
518 } |
494 |
519 |
495 #----------------------------------------------------------- |
520 #----------------------------------------------------------- |
496 # rot_IMP() |
521 # rot_IMP() |
652 GMT_pstext('-F+f14,Helvetica,blue+jTL -N'); |
678 GMT_pstext('-F+f14,Helvetica,blue+jTL -N'); |
653 printf(GMT "0.01 1.06 $P{profile_id} $opt_a\n"); |
679 printf(GMT "0.01 1.06 $P{profile_id} $opt_a\n"); |
654 GMT_end(); |
680 GMT_end(); |
655 |
681 |
656 print(STDERR "\n") if $verbose; |
682 print(STDERR "\n") if $verbose; |
|
683 return (sqrt($sumSq/$nSq),$sumErr/$nErr,$sumBe/$nBe); |
657 } |
684 } |
658 |
685 |
659 #---------------------------------------------------------------------- |
686 #---------------------------------------------------------------------- |
660 # output_merged() |
687 # output_merged() |
661 # - output merged data |
688 # - output merged data |
|
689 # - there must be exactly one record for each PD0 ensemble |
662 #---------------------------------------------------------------------- |
690 #---------------------------------------------------------------------- |
663 |
691 |
664 sub output_merged($) |
692 sub output_merged($) |
665 { |
693 { |
666 my($verbose) = @_; |
694 my($verbose) = @_; |
688 } |
716 } |
689 $out[$L_ensF] = $LADCP{ENSEMBLE}[$ens]->{NUMBER}; |
717 $out[$L_ensF] = $LADCP{ENSEMBLE}[$ens]->{NUMBER}; |
690 $out[$dcF] = ($ens <= $LADCP_bottom); |
718 $out[$dcF] = ($ens <= $LADCP_bottom); |
691 &antsOut(@out); |
719 &antsOut(@out); |
692 } elsif ($ens < $LADCP_begin || $ens > $LADCP_end) { # pre deplyment or post recovery |
720 } elsif ($ens < $LADCP_begin || $ens > $LADCP_end) { # pre deplyment or post recovery |
693 $ants_[$r][$L_elapsedF] = undef; |
721 my(@out); # correct IMP record NOT known |
694 $ants_[$r][$L_ensF] = $LADCP{ENSEMBLE}[$ens]->{NUMBER}; |
722 $out[$L_elapsedF] = undef; |
695 $ants_[$r][$L_pitchF] = undef; |
723 $out[$L_ensF] = $LADCP{ENSEMBLE}[$ens]->{NUMBER}; |
696 $ants_[$r][$L_rollF] = undef; |
724 $out[$L_pitchF] = $LADCP{ENSEMBLE}[$ens]->{GIMBAL_PITCH} - $LADCP_pitch_mean; |
697 $ants_[$r][$L_hdgF] = undef; |
725 $out[$L_rollF] = $LADCP{ENSEMBLE}[$ens]->{ROLL} - $LADCP_roll_mean; |
698 $ants_[$r][$pitchF] = undef; |
726 $out[$L_hdgF] = $LADCP{ENSEMBLE}[$ens]->{HEADING}; |
699 $ants_[$r][$rollF] = undef; |
727 &antsOut(@out); |
700 $ants_[$r][$hdgF] = undef; |
|
701 $ants_[$r][$dcF] = ($ens <= $LADCP_bottom); |
|
702 &antsOut(@{$ants_[$r]}); |
|
703 } else { |
728 } else { |
704 $ants_[$r][$tazimF] = angle($LADCP{ENSEMBLE}[$ens]->{IMP_TILT_AZIMUTH} + $HDG_offset); |
729 $ants_[$r][$tazimF] = angle($LADCP{ENSEMBLE}[$ens]->{IMP_TILT_AZIMUTH} + $HDG_offset); |
705 $ants_[$r][$tanomF] = $LADCP{ENSEMBLE}[$ens]->{IMP_TILT_ANOM}; |
730 $ants_[$r][$tanomF] = $LADCP{ENSEMBLE}[$ens]->{IMP_TILT_ANOM}; |
706 $ants_[$r][$L_tazimF] = $LADCP{ENSEMBLE}[$ens]->{TILT_AZIMUTH}; |
731 $ants_[$r][$L_tazimF] = $LADCP{ENSEMBLE}[$ens]->{TILT_AZIMUTH}; |
707 $ants_[$r][$L_tanomF] = $LADCP{ENSEMBLE}[$ens]->{TILT_ANOM}; |
732 $ants_[$r][$L_tanomF] = $LADCP{ENSEMBLE}[$ens]->{TILT_ANOM}; |
708 $ants_[$r][$L_elapsedF] = $LADCP{ENSEMBLE}[$ens]->{ELAPSED_TIME}; |
733 $ants_[$r][$L_elapsedF] = $LADCP{ENSEMBLE}[$ens]->{ELAPSED_TIME}; |
709 $ants_[$r][$L_ensF] = $LADCP{ENSEMBLE}[$ens]->{NUMBER}; |
734 $ants_[$r][$L_ensF] = $LADCP{ENSEMBLE}[$ens]->{NUMBER}; |
710 $ants_[$r][$L_depthF] = $LADCP{ENSEMBLE}[$ens]->{DEPTH}; |
735 $ants_[$r][$L_depthF] = $LADCP{ENSEMBLE}[$ens]->{DEPTH}; |
711 $ants_[$r][$L_pitchF] = $LADCP{ENSEMBLE}[$ens]->{GIMBAL_PITCH} - $LADCP_pitch_mean; |
736 $ants_[$r][$L_pitchF] = $LADCP{ENSEMBLE}[$ens]->{GIMBAL_PITCH} - $LADCP_pitch_mean; |
712 $ants_[$r][$L_rollF] = $LADCP{ENSEMBLE}[$ens]->{ROLL} - $LADCP_roll_mean; |
737 $ants_[$r][$L_rollF] = $LADCP{ENSEMBLE}[$ens]->{ROLL} - $LADCP_roll_mean; |
713 $ants_[$r][$L_hdgF] = $LADCP{ENSEMBLE}[$ens]->{HEADING}; |
738 $ants_[$r][$L_hdgF] = $LADCP{ENSEMBLE}[$ens]->{HEADING}; |
714 $ants_[$r][$dcF] = ($ens <= $LADCP_bottom); |
739 $ants_[$r][$dcF] = ($ens <= $LADCP_bottom) ? 1 : 0; |
715 &antsOut(@{$ants_[$r]}); |
740 &antsOut(@{$ants_[$r]}); |
716 } |
741 } |
717 } |
742 } |
718 |
743 |
719 print(STDERR "\n") if $verbose; |
744 print(STDERR "\n") if $verbose; |