libIMP.pl
changeset 39 56bdfe65a697
parent 36 04e8cb4f8073
child 40 c1803ae2540f
equal deleted inserted replaced
38:15c603bc4f70 39:56bdfe65a697
     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()
   530 }
   555 }
   531 
   556 
   532 #----------------------------------------------------------------------
   557 #----------------------------------------------------------------------
   533 # create_merge_plots()
   558 # create_merge_plots()
   534 #   - tilt time series (*_time_lag.ps)
   559 #   - tilt time series (*_time_lag.ps)
       
   560 #	- heading errors (*_hdg_err.ps)
   535 #----------------------------------------------------------------------
   561 #----------------------------------------------------------------------
   536 
   562 
   537 sub create_merge_plots($$$)
   563 sub create_merge_plots($$$)
   538 {
   564 {
   539     my($basename,$plotsize,$verbose) = @_;
   565     my($basename,$plotsize,$verbose) = @_;
   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;