FV3 Bundle
CRTM_SensorData_Define.f90
Go to the documentation of this file.
1 !
2 ! CRTM_SensorData_Define
3 !
4 ! Module defining the CRTM SensorData structure and containing
5 ! routines to manipulate it.
6 !
7 !
8 ! CREATION HISTORY:
9 ! Written by: Paul van Delst, 23-Jul-2004
10 ! paul.vandelst@noaa.gov
11 !
12 
14 
15  ! -----------------
16  ! Environment setup
17  ! -----------------
18  ! Intrinsic modules
19  USE iso_fortran_env , ONLY: output_unit
20  ! Module use
21  USE type_kinds , ONLY: fp
24  OPERATOR(.equalto.), &
30  USE crtm_parameters , ONLY: strlen, &
33  ! Disable implicit typing
34  IMPLICIT NONE
35 
36 
37  ! ------------
38  ! Visibilities
39  ! ------------
40  ! Everything private by default
41  PRIVATE
42  ! Parameters
43  PUBLIC :: invalid_wmo_satellite_id
44  PUBLIC :: invalid_wmo_sensor_id
45  ! Datatypes
46  PUBLIC :: crtm_sensordata_type
47  ! Operators
48  PUBLIC :: OPERATOR(==)
49  PUBLIC :: OPERATOR(+)
50  PUBLIC :: OPERATOR(-)
51  ! Procedures
53  PUBLIC :: crtm_sensordata_destroy
54  PUBLIC :: crtm_sensordata_create
55  PUBLIC :: crtm_sensordata_zero
56  PUBLIC :: crtm_sensordata_isvalid
57  PUBLIC :: crtm_sensordata_inspect
59  PUBLIC :: crtm_sensordata_compare
61  PUBLIC :: crtm_sensordata_readfile
63 
64 
65  ! ---------------------
66  ! Procedure overloading
67  ! ---------------------
68  INTERFACE OPERATOR(==)
69  MODULE PROCEDURE crtm_sensordata_equal
70  END INTERFACE OPERATOR(==)
71 
72  INTERFACE OPERATOR(+)
73  MODULE PROCEDURE crtm_sensordata_add
74  END INTERFACE OPERATOR(+)
75 
76  INTERFACE OPERATOR(-)
77  MODULE PROCEDURE crtm_sensordata_subtract
78  END INTERFACE OPERATOR(-)
79 
80 
81  ! -----------------
82  ! Module parameters
83  ! -----------------
84  CHARACTER(*), PARAMETER :: module_version_id = &
85  '$Id: CRTM_SensorData_Define.f90 60152 2015-08-13 19:19:13Z paul.vandelst@noaa.gov $'
86  ! Literal constants
87  REAL(fp), PARAMETER :: zero = 0.0_fp
88  REAL(fp), PARAMETER :: one = 1.0_fp
89  ! Message string length
90  INTEGER, PARAMETER :: ml = 256
91  ! File status on close after write error
92  CHARACTER(*), PARAMETER :: write_error_status = 'DELETE'
93 
94 
95  ! -------------------------------
96  ! SensorData structure definition
97  ! -------------------------------
98  !:tdoc+:
100  ! Allocation indicator
101  LOGICAL :: is_allocated = .false.
102  ! Dimension values
103  INTEGER :: n_channels = 0 ! L
104  ! The data sensor IDs
105  CHARACTER(STRLEN) :: sensor_id = ' '
106  INTEGER :: wmo_satellite_id = invalid_wmo_satellite_id
107  INTEGER :: wmo_sensor_id = invalid_wmo_sensor_id
108  ! The sensor channels and brightness temperatures
109  INTEGER , ALLOCATABLE :: sensor_channel(:) ! L
110  REAL(fp), ALLOCATABLE :: tb(:) ! L
111  END TYPE crtm_sensordata_type
112  !:tdoc-:
113 
114 
115 CONTAINS
116 
117 
118 !################################################################################
119 !################################################################################
120 !## ##
121 !## ## PUBLIC MODULE ROUTINES ## ##
122 !## ##
123 !################################################################################
124 !################################################################################
125 
126 !--------------------------------------------------------------------------------
127 !:sdoc+:
128 !
129 ! NAME:
130 ! CRTM_SensorData_Associated
131 !
132 ! PURPOSE:
133 ! Elemental function to test the status of the allocatable components
134 ! of a CRTM SensorData object.
135 !
136 ! CALLING SEQUENCE:
137 ! Status = CRTM_SensorData_Associated( SensorData )
138 !
139 ! OBJECTS:
140 ! SensorData: SensorData structure which is to have its member's
141 ! status tested.
142 ! UNITS: N/A
143 ! TYPE: CRTM_SensorData_type
144 ! DIMENSION: Scalar or any rank
145 ! ATTRIBUTES: INTENT(IN)
146 !
147 ! FUNCTION RESULT:
148 ! Status: The return value is a logical value indicating the
149 ! status of the SensorData members.
150 ! .TRUE. - if the array components are allocated.
151 ! .FALSE. - if the array components are not allocated.
152 ! UNITS: N/A
153 ! TYPE: LOGICAL
154 ! DIMENSION: Same as input SensorData argument
155 !
156 !:sdoc-:
157 !--------------------------------------------------------------------------------
158 
159  ELEMENTAL FUNCTION crtm_sensordata_associated( SensorData ) RESULT( Status )
160  TYPE(crtm_sensordata_type), INTENT(IN) :: sensordata
161  LOGICAL :: status
162  status = sensordata%Is_Allocated
163  END FUNCTION crtm_sensordata_associated
164 
165 
166 !--------------------------------------------------------------------------------
167 !:sdoc+:
168 !
169 ! NAME:
170 ! CRTM_SensorData_Destroy
171 !
172 ! PURPOSE:
173 ! Elemental subroutine to re-initialize CRTM SensorData objects.
174 !
175 ! CALLING SEQUENCE:
176 ! CALL CRTM_SensorData_Destroy( SensorData )
177 !
178 ! OBJECTS:
179 ! SensorData: Re-initialized SensorData structure.
180 ! UNITS: N/A
181 ! TYPE: CRTM_SensorData_type
182 ! DIMENSION: Scalar OR any rank
183 ! ATTRIBUTES: INTENT(OUT)
184 !
185 !:sdoc-:
186 !--------------------------------------------------------------------------------
187 
188  ELEMENTAL SUBROUTINE crtm_sensordata_destroy( SensorData )
189  TYPE(crtm_sensordata_type), INTENT(OUT) :: sensordata
190  sensordata%Is_Allocated = .false.
191  END SUBROUTINE crtm_sensordata_destroy
192 
193 
194 !--------------------------------------------------------------------------------
195 !:sdoc+:
196 !
197 ! NAME:
198 ! CRTM_SensorData_Create
199 !
200 ! PURPOSE:
201 ! Elemental subroutine to create an instance of the CRTM SensorData object.
202 !
203 ! CALLING SEQUENCE:
204 ! CALL CRTM_SensorData_Create( SensorData, n_Channels )
205 !
206 ! OBJECTS:
207 ! SensorData: SensorData structure.
208 ! UNITS: N/A
209 ! TYPE: CRTM_SensorData_type
210 ! DIMENSION: Scalar or any rank
211 ! ATTRIBUTES: INTENT(OUT)
212 !
213 ! INPUTS:
214 ! n_Channels: Number of sensor channels.
215 ! Must be > 0.
216 ! UNITS: N/A
217 ! TYPE: INTEGER
218 ! DIMENSION: Same as SensorData object
219 ! ATTRIBUTES: INTENT(IN)
220 !
221 !:sdoc-:
222 !--------------------------------------------------------------------------------
223 
224  ELEMENTAL SUBROUTINE crtm_sensordata_create( SensorData, n_Channels )
225  ! Arguments
226  TYPE(crtm_sensordata_type), INTENT(OUT) :: sensordata
227  INTEGER, INTENT(IN) :: n_channels
228  ! Local variables
229  INTEGER :: alloc_stat
230 
231  ! Check input
232  IF ( n_channels < 1 ) RETURN
233 
234  ! Perform the allocation
235  ALLOCATE( sensordata%Sensor_Channel( n_channels ), &
236  sensordata%Tb( n_channels ), &
237  stat = alloc_stat )
238  IF ( alloc_stat /= 0 ) RETURN
239 
240  ! Initialise
241  ! ...Dimensions
242  sensordata%n_Channels = n_channels
243  ! ...Arrays
244  sensordata%Sensor_Channel = 0
245  sensordata%Tb = zero
246 
247  ! Set allocation indicator
248  sensordata%Is_Allocated = .true.
249 
250  END SUBROUTINE crtm_sensordata_create
251 
252 
253 !--------------------------------------------------------------------------------
254 !:sdoc+:
255 !
256 ! NAME:
257 ! CRTM_SensorData_Zero
258 !
259 ! PURPOSE:
260 ! Elemental subroutine to zero out the data arrays in a
261 ! CRTM SensorData object.
262 !
263 ! CALLING SEQUENCE:
264 ! CALL CRTM_SensorData_Zero( SensorData )
265 !
266 ! OBJECTS:
267 ! SensorData: CRTM SensorData structure in which the data arrays are
268 ! to be zeroed out.
269 ! UNITS: N/A
270 ! TYPE: CRTM_SensorData_type
271 ! DIMENSION: Scalar or any rank
272 ! ATTRIBUTES: INTENT(IN OUT)
273 !
274 ! COMMENTS:
275 ! - The dimension components of the structure are *NOT* set to zero.
276 ! - The SensorData sensor id and channel components are *NOT* reset.
277 !
278 !:sdoc-:
279 !--------------------------------------------------------------------------------
280 
281  ELEMENTAL SUBROUTINE crtm_sensordata_zero( SensorData )
282  TYPE(crtm_sensordata_type), INTENT(IN OUT) :: sensordata
283  ! Do nothing if structure is unused
284  IF ( .NOT. crtm_sensordata_associated(sensordata) ) RETURN
285  ! Only zero out the data arrays
286  sensordata%Tb = zero
287  END SUBROUTINE crtm_sensordata_zero
288 
289 
290 !--------------------------------------------------------------------------------
291 !:sdoc+:
292 !
293 ! NAME:
294 ! CRTM_SensorData_IsValid
295 !
296 ! PURPOSE:
297 ! Non-pure function to perform some simple validity checks on a
298 ! CRTM SensorData object.
299 !
300 ! If invalid data is found, a message is printed to stdout.
301 !
302 ! CALLING SEQUENCE:
303 ! result = CRTM_SensorData_IsValid( SensorData )
304 !
305 ! or
306 !
307 ! IF ( CRTM_SensorData_IsValid( SensorData ) ) THEN....
308 !
309 ! OBJECTS:
310 ! SensorData: CRTM SensorData object which is to have its
311 ! contents checked.
312 ! UNITS: N/A
313 ! TYPE: CRTM_SensorData_type
314 ! DIMENSION: Scalar
315 ! ATTRIBUTES: INTENT(IN)
316 !
317 ! FUNCTION RESULT:
318 ! result: Logical variable indicating whether or not the input
319 ! passed the check.
320 ! If == .FALSE., SensorData object is unused or contains
321 ! invalid data.
322 ! == .TRUE., SensorData object can be used in CRTM.
323 ! UNITS: N/A
324 ! TYPE: LOGICAL
325 ! DIMENSION: Scalar
326 !
327 !:sdoc-:
328 !--------------------------------------------------------------------------------
329 
330  FUNCTION crtm_sensordata_isvalid( SensorData ) RESULT( IsValid )
331  TYPE(crtm_sensordata_type), INTENT(IN) :: sensordata
332  LOGICAL :: isvalid
333  CHARACTER(*), PARAMETER :: routine_name = 'CRTM_SensorData_IsValid'
334  CHARACTER(ML) :: msg
335 
336  ! Setup
337  isvalid = .false.
338  ! ...Check if structure is used
339  IF ( .NOT. crtm_sensordata_associated(sensordata) ) THEN
340  msg = 'SensorData structure not allocated'
341  CALL display_message( routine_name, msg, information )
342  RETURN
343  ENDIF
344  IF ( sensordata%n_channels < 1 ) THEN
345  msg = 'SensorData structure dimension invalid'
346  CALL display_message( routine_name, msg, information )
347  RETURN
348  ENDIF
349 
350  ! Check data
351  ! ...Change default so all entries can be checked
352  isvalid = .true.
353  ! ...Data sensor ids
354  IF ( len_trim(sensordata%Sensor_Id) == 0 ) THEN
355  msg = 'Invalid Sensor Id found'
356  CALL display_message( routine_name, msg, information )
357  isvalid = .false.
358  ENDIF
359  IF ( sensordata%WMO_Satellite_Id == invalid_wmo_satellite_id ) THEN
360  msg = 'Invalid WMO Satellite Id found. Continuing...'
361  CALL display_message( routine_name, msg, warning )
362  ENDIF
363  IF ( sensordata%WMO_Sensor_Id == invalid_wmo_sensor_id ) THEN
364  msg = 'Invalid WMO Sensor Id Continuing...'
365  CALL display_message( routine_name, msg, warning )
366  ENDIF
367  ! ...Listed sensor channels
368  IF ( any(sensordata%Sensor_Channel < 1) ) THEN
369  msg = 'Invalid Sensor Channel found'
370  CALL display_message( routine_name, msg, information )
371  isvalid = .false.
372  ENDIF
373  ! ...Data
374  IF ( all(sensordata%Tb < zero ) ) THEN
375  msg = 'All input SensorData brightness temperatures are negative'
376  CALL display_message( routine_name, msg, information )
377  isvalid = .false.
378  ENDIF
379 
380  END FUNCTION crtm_sensordata_isvalid
381 
382 
383 !--------------------------------------------------------------------------------
384 !:sdoc+:
385 !
386 ! NAME:
387 ! CRTM_SensorData_Inspect
388 !
389 ! PURPOSE:
390 ! Subroutine to print the contents of a CRTM SensorData object to stdout.
391 !
392 ! CALLING SEQUENCE:
393 ! CALL CRTM_SensorData_Inspect( SensorData, Unit=unit )
394 !
395 ! INPUTS:
396 ! SensorData: CRTM SensorData object to display.
397 ! UNITS: N/A
398 ! TYPE: CRTM_SensorData_type
399 ! DIMENSION: Scalar
400 ! ATTRIBUTES: INTENT(IN)
401 !
402 ! OPTIONAL INPUTS:
403 ! Unit: Unit number for an already open file to which the output
404 ! will be written.
405 ! If the argument is specified and the file unit is not
406 ! connected, the output goes to stdout.
407 ! UNITS: N/A
408 ! TYPE: INTEGER
409 ! DIMENSION: Scalar
410 ! ATTRIBUTES: INTENT(IN), OPTIONAL
411 !
412 !:sdoc-:
413 !--------------------------------------------------------------------------------
414 
415  SUBROUTINE crtm_sensordata_inspect( SensorData, Unit )
416  ! Arguments
417  TYPE(crtm_sensordata_type), INTENT(IN) :: sensordata
418  INTEGER, OPTIONAL, INTENT(IN) :: unit
419  ! Local variables
420  INTEGER :: fid
421 
422  ! Setup
423  fid = output_unit
424  IF ( PRESENT(unit) ) THEN
425  IF ( file_open(unit) ) fid = unit
426  END IF
427 
428 
429  WRITE(fid,'(1x,"SENSORDATA OBJECT")')
430  ! Dimensions
431  WRITE(fid,'(3x,"n_Channels:",1x,i0)') sensordata%n_Channels
432  ! Scalar components
433  WRITE(fid,'(3x,"Sensor Id :",1x,a)') sensordata%Sensor_Id
434  WRITE(fid,'(3x,"WMO Satellite Id:",1x,i0)') sensordata%WMO_Satellite_Id
435  WRITE(fid,'(3x,"WMO Sensor Id :",1x,i0)') sensordata%WMO_Sensor_Id
436  IF ( .NOT. crtm_sensordata_associated(sensordata) ) RETURN
437  ! Array components
438  WRITE(fid,'(3x,"Sensor channels:")')
439  WRITE(fid,'(10(1x,i5))') sensordata%Sensor_Channel
440  WRITE(fid,'(3x,"Brightness temperatures:")')
441  WRITE(fid,'(10(1x,es13.6))') sensordata%Tb
442  END SUBROUTINE crtm_sensordata_inspect
443 
444 
445 !--------------------------------------------------------------------------------
446 !:sdoc+:
447 !
448 ! NAME:
449 ! CRTM_SensorData_DefineVersion
450 !
451 ! PURPOSE:
452 ! Subroutine to return the module version information.
453 !
454 ! CALLING SEQUENCE:
455 ! CALL CRTM_SensorData_DefineVersion( Id )
456 !
457 ! OUTPUT ARGUMENTS:
458 ! Id: Character string containing the version Id information
459 ! for the module.
460 ! UNITS: N/A
461 ! TYPE: CHARACTER(*)
462 ! DIMENSION: Scalar
463 ! ATTRIBUTES: INTENT(OUT)
464 !
465 !:sdoc-:
466 !--------------------------------------------------------------------------------
467 
468  SUBROUTINE crtm_sensordata_defineversion( Id )
469  CHARACTER(*), INTENT(OUT) :: id
470  id = module_version_id
471  END SUBROUTINE crtm_sensordata_defineversion
472 
473 
474 !------------------------------------------------------------------------------
475 !:sdoc+:
476 ! NAME:
477 ! CRTM_SensorData_Compare
478 !
479 ! PURPOSE:
480 ! Elemental function to compare two CRTM_SensorData objects to within
481 ! a user specified number of significant figures.
482 !
483 ! CALLING SEQUENCE:
484 ! is_comparable = CRTM_SensorData_Compare( x, y, n_SigFig=n_SigFig )
485 !
486 ! OBJECTS:
487 ! x, y: Two CRTM SensorData objects to be compared.
488 ! UNITS: N/A
489 ! TYPE: CRTM_SensorData_type
490 ! DIMENSION: Scalar or any rank
491 ! ATTRIBUTES: INTENT(IN)
492 !
493 ! OPTIONAL INPUTS:
494 ! n_SigFig: Number of significant figure to compare floating point
495 ! components.
496 ! UNITS: N/A
497 ! TYPE: INTEGER
498 ! DIMENSION: Scalar or same as input
499 ! ATTRIBUTES: INTENT(IN), OPTIONAL
500 !
501 ! FUNCTION RESULT:
502 ! is_equal: Logical value indicating whether the inputs are equal.
503 ! UNITS: N/A
504 ! TYPE: LOGICAL
505 ! DIMENSION: Same as inputs.
506 !:sdoc-:
507 !------------------------------------------------------------------------------
508 
509  ELEMENTAL FUNCTION crtm_sensordata_compare( &
510  x, &
511  y, &
512  n_SigFig ) &
513  result( is_comparable )
514  TYPE(crtm_sensordata_type), INTENT(IN) :: x, y
515  INTEGER, OPTIONAL, INTENT(IN) :: n_sigfig
516  LOGICAL :: is_comparable
517  ! Variables
518  INTEGER :: l, n
519 
520  ! Set up
521  is_comparable = .false.
522  IF ( PRESENT(n_sigfig) ) THEN
523  n = abs(n_sigfig)
524  ELSE
525  n = default_n_sigfig
526  END IF
527 
528  ! Check the structure association status
529  IF ( (.NOT. crtm_sensordata_associated(x)) .OR. &
530  (.NOT. crtm_sensordata_associated(y)) ) RETURN
531 
532  ! Check scalars
533  IF ( (x%n_Channels /= y%n_Channels ) .OR. &
534  (x%Sensor_Id /= y%Sensor_Id ) .OR. &
535  (x%WMO_Satellite_ID /= y%WMO_Satellite_ID) .OR. &
536  (x%WMO_Sensor_ID /= y%WMO_Sensor_ID ) ) RETURN
537 
538  ! Check arrays
539  l = x%n_Channels
540  IF ( any(x%Sensor_Channel(1:l) /= y%Sensor_Channel(1:l)) .OR. &
541  (.NOT. all(compares_within_tolerance(x%Tb(1:l),y%Tb(1:l),n))) ) RETURN
542 
543  ! If we get here, the structures are comparable
544  is_comparable = .true.
545 
546  END FUNCTION crtm_sensordata_compare
547 
548 
549 !------------------------------------------------------------------------------
550 !:sdoc+:
551 !
552 ! NAME:
553 ! CRTM_SensorData_InquireFile
554 !
555 ! PURPOSE:
556 ! Function to inquire CRTM SensorData object files.
557 !
558 ! CALLING SEQUENCE:
559 ! Error_Status = CRTM_SensorData_InquireFile( Filename , &
560 ! n_DataSets = n_DataSets )
561 !
562 ! INPUTS:
563 ! Filename: Character string specifying the name of a
564 ! CRTM SensorData data file to read.
565 ! UNITS: N/A
566 ! TYPE: CHARACTER(*)
567 ! DIMENSION: Scalar
568 ! ATTRIBUTES: INTENT(IN)
569 !
570 ! OPTIONAL OUTPUTS:
571 ! n_DataSets: The number of datasets in the file.
572 ! UNITS: N/A
573 ! TYPE: INTEGER
574 ! DIMENSION: Scalar
575 ! ATTRIBUTES: OPTIONAL, INTENT(OUT)
576 !
577 ! FUNCTION RESULT:
578 ! Error_Status: The return value is an integer defining the error status.
579 ! The error codes are defined in the Message_Handler module.
580 ! If == SUCCESS, the file inquire was successful
581 ! == FAILURE, an unrecoverable error occurred.
582 ! UNITS: N/A
583 ! TYPE: INTEGER
584 ! DIMENSION: Scalar
585 !
586 !:sdoc-:
587 !------------------------------------------------------------------------------
588 
589  FUNCTION crtm_sensordata_inquirefile( &
590  Filename , & ! Input
591  n_DataSets) & ! Optional output
592  result( err_stat )
593  ! Arguments
594  CHARACTER(*), INTENT(IN) :: filename
595  INTEGER, OPTIONAL, INTENT(OUT) :: n_datasets
596  ! Function result
597  INTEGER :: err_stat
598  ! Function parameters
599  CHARACTER(*), PARAMETER :: routine_name = 'CRTM_SensorData_InquireFile'
600  ! Function variables
601  CHARACTER(ML) :: msg
602  INTEGER :: io_stat
603  INTEGER :: fid
604  INTEGER :: n
605 
606  ! Setup
607  err_stat = success
608  ! Check that the file exists
609  IF ( .NOT. file_exists( trim(filename) ) ) THEN
610  msg = 'File '//trim(filename)//' not found.'
611  CALL inquire_cleanup(); RETURN
612  END IF
613 
614  ! Open the SensorData data file
615  err_stat = open_binary_file( filename, fid )
616  IF ( err_stat /= success ) THEN
617  msg = 'Error opening '//trim(filename)
618  CALL inquire_cleanup(); RETURN
619  END IF
620 
621  ! Read the dimensions
622  READ( fid,iostat=io_stat ) n
623  IF ( io_stat /= 0 ) THEN
624  WRITE( msg,'("Error reading dataset dimensions from ",a,". IOSTAT = ",i0)' ) &
625  trim(filename), io_stat
626  CALL inquire_cleanup(close_file=.true.); RETURN
627  END IF
628 
629  ! Close the file
630  CLOSE( fid, iostat=io_stat )
631  IF ( io_stat /= 0 ) THEN
632  WRITE( msg,'("Error closing ",a,". IOSTAT = ",i0)' ) trim(filename), io_stat
633  CALL inquire_cleanup(); RETURN
634  END IF
635 
636  ! Set the return arguments
637  IF ( PRESENT(n_datasets) ) n_datasets = n
638 
639  CONTAINS
640 
641  SUBROUTINE inquire_cleanup( Close_File )
642  LOGICAL, OPTIONAL, INTENT(IN) :: Close_File
643  ! Close file if necessary
644  IF ( PRESENT(close_file) ) THEN
645  IF ( close_file ) THEN
646  CLOSE( fid,iostat=io_stat )
647  IF ( io_stat /= success ) &
648  msg = trim(msg)//'; Error closing input file during error cleanup'
649  END IF
650  END IF
651  ! Set error status and print error message
652  err_stat = failure
653  CALL display_message( routine_name, trim(msg), err_stat )
654  END SUBROUTINE inquire_cleanup
655 
656  END FUNCTION crtm_sensordata_inquirefile
657 
658 
659 !------------------------------------------------------------------------------
660 !:sdoc+:
661 !
662 ! NAME:
663 ! CRTM_SensorData_ReadFile
664 !
665 ! PURPOSE:
666 ! Function to read CRTM SensorData object files.
667 !
668 ! CALLING SEQUENCE:
669 ! Error_Status = CRTM_SensorData_ReadFile( Filename , &
670 ! SensorData , &
671 ! Quiet = Quiet , &
672 ! No_Close = No_Close , &
673 ! n_DataSets = n_DataSets )
674 !
675 ! INPUTS:
676 ! Filename: Character string specifying the name of a
677 ! SensorData format data file to read.
678 ! UNITS: N/A
679 ! TYPE: CHARACTER(*)
680 ! DIMENSION: Scalar
681 ! ATTRIBUTES: INTENT(IN)
682 !
683 ! OUTPUTS:
684 ! SensorData: CRTM SensorData object array containing the sensor data.
685 ! UNITS: N/A
686 ! TYPE: CRTM_SensorData_type
687 ! DIMENSION: Rank-1
688 ! ATTRIBUTES: INTENT(OUT)
689 !
690 ! OPTIONAL INPUTS:
691 ! Quiet: Set this logical argument to suppress INFORMATION
692 ! messages being printed to stdout
693 ! If == .FALSE., INFORMATION messages are OUTPUT [DEFAULT].
694 ! == .TRUE., INFORMATION messages are SUPPRESSED.
695 ! If not specified, default is .FALSE.
696 ! UNITS: N/A
697 ! TYPE: LOGICAL
698 ! DIMENSION: Scalar
699 ! ATTRIBUTES: INTENT(IN), OPTIONAL
700 !
701 ! No_Close: Set this logical argument to NOT close the file upon exit.
702 ! If == .FALSE., the input file is closed upon exit [DEFAULT]
703 ! == .TRUE., the input file is NOT closed upon exit.
704 ! If not specified, default is .FALSE.
705 ! UNITS: N/A
706 ! TYPE: LOGICAL
707 ! DIMENSION: Scalar
708 ! ATTRIBUTES: INTENT(IN), OPTIONAL
709 !
710 ! OPTIONAL OUTPUTS:
711 ! n_DataSets: The actual number of datasets read in.
712 ! UNITS: N/A
713 ! TYPE: INTEGER
714 ! DIMENSION: Scalar
715 ! ATTRIBUTES: OPTIONAL, INTENT(OUT)
716 !
717 ! FUNCTION RESULT:
718 ! Error_Status: The return value is an integer defining the error status.
719 ! The error codes are defined in the Message_Handler module.
720 ! If == SUCCESS, the file read was successful
721 ! == FAILURE, an unrecoverable error occurred.
722 ! UNITS: N/A
723 ! TYPE: INTEGER
724 ! DIMENSION: Scalar
725 !
726 !:sdoc-:
727 !------------------------------------------------------------------------------
728 
729  FUNCTION crtm_sensordata_readfile( &
730  Filename , & ! Input
731  SensorData, & ! Output
732  Quiet , & ! Optional input
733  No_Close , & ! Optional input
734  n_DataSets, & ! Optional output
735  Debug ) & ! Optional input (Debug output control)
736  result( err_stat )
737  ! Arguments
738  CHARACTER(*), INTENT(IN) :: filename
739  TYPE(crtm_sensordata_type), INTENT(OUT) :: sensordata(:)
740  LOGICAL, OPTIONAL, INTENT(IN) :: quiet
741  LOGICAL, OPTIONAL, INTENT(IN) :: no_close
742  INTEGER, OPTIONAL, INTENT(OUT) :: n_datasets
743  LOGICAL, OPTIONAL, INTENT(IN) :: debug
744  ! Function result
745  INTEGER :: err_stat
746  ! Function parameters
747  CHARACTER(*), PARAMETER :: routine_name = 'CRTM_SensorData_ReadFile'
748  ! Function variables
749  CHARACTER(ML) :: msg
750  LOGICAL :: noisy
751  LOGICAL :: yes_close
752  INTEGER :: io_stat
753  INTEGER :: fid
754  INTEGER :: i, n
755 
756  ! Setup
757  err_stat = success
758  ! ...Check Quiet argument
759  noisy = .true.
760  IF ( PRESENT(quiet) ) noisy = .NOT. quiet
761  ! ...Check file close argument
762  yes_close = .true.
763  IF ( PRESENT(no_close) ) yes_close = .NOT. no_close
764  ! ...Override Quiet settings if debug set.
765  IF ( PRESENT(debug) ) THEN
766  IF ( debug ) noisy = .true.
767  END IF
768 
769 
770  ! Check if the file is open
771  IF ( file_open( filename ) ) THEN
772  ! Yes, the file is already open
773  ! ...Get the file id
774  INQUIRE( file=filename,number=fid )
775  IF ( fid == -1 ) THEN
776  msg = 'Error inquiring '//trim(filename)//' for its fid'
777  CALL read_cleanup(); RETURN
778  END IF
779  ELSE
780  ! No, the file is not open
781  ! ...Check that the file exists
782  IF ( .NOT. file_exists( filename ) ) THEN
783  msg = 'File '//trim(filename)//' not found.'
784  CALL read_cleanup(); RETURN
785  END IF
786  ! ...Open the file
787  err_stat = open_binary_file( filename, fid )
788  IF ( err_stat /= success ) THEN
789  msg = 'Error opening '//trim(filename)
790  CALL read_cleanup(); RETURN
791  END IF
792  END IF
793 
794 
795  ! Read the dimensions
796  READ( fid,iostat=io_stat ) n
797  IF ( io_stat /= 0 ) THEN
798  WRITE( msg,'("Error reading dataset dimensions from ",a,". IOSTAT = ",i0)' ) &
799  trim(filename), io_stat
800  CALL read_cleanup(close_file=.true.); RETURN
801  END IF
802  ! ...Check if output array large enough
803  IF ( n > SIZE(sensordata) ) THEN
804  WRITE( msg,'("Number of SensorData sets, ",i0," > size of the output ",&
805  &"SensorData object array, ",i0,".")' ) &
806  n, SIZE(sensordata)
807  CALL read_cleanup(close_file=.true.); RETURN
808  END IF
809 
810 
811  ! Read the SensorData data
812  sensordata_loop: DO i = 1, n
813  err_stat = read_record( fid, sensordata(i) )
814  IF ( err_stat /= success ) THEN
815  WRITE( msg,'("Error reading SensorData element #",i0," from ",a)' ) &
816  i, trim(filename)
817  CALL read_cleanup(close_file=.true.); RETURN
818  END IF
819  END DO sensordata_loop
820 
821 
822  ! Close the file
823  IF ( yes_close ) THEN
824  CLOSE( fid,iostat=io_stat )
825  IF ( io_stat /= 0 ) THEN
826  WRITE( msg,'("Error closing ",a,". IOSTAT = ",i0)' ) trim(filename), io_stat
827  CALL read_cleanup(); RETURN
828  END IF
829  END IF
830 
831 
832  ! Set the optional return values
833  IF ( PRESENT(n_datasets) ) n_datasets = n
834 
835 
836  ! Output an info message
837  IF ( noisy ) THEN
838  WRITE( msg,'("Number of datasets read from ",a,": ",i0)' ) trim(filename), n
839  CALL display_message( routine_name, trim(msg), information )
840  END IF
841 
842  CONTAINS
843 
844  SUBROUTINE read_cleanup( Close_File )
845  LOGICAL, OPTIONAL, INTENT(IN) :: Close_File
846  ! Close file if necessary
847  IF ( PRESENT(close_file) ) THEN
848  IF ( close_file ) THEN
849  CLOSE( fid,iostat=io_stat )
850  IF ( io_stat /= 0 ) &
851  msg = trim(msg)//'; Error closing input file during error cleanup.'
852  END IF
853  END IF
854  ! Destroy the structure
855  CALL crtm_sensordata_destroy( sensordata )
856  ! Set error status and print error message
857  err_stat = failure
858  CALL display_message( routine_name, trim(msg), err_stat )
859  END SUBROUTINE read_cleanup
860 
861  END FUNCTION crtm_sensordata_readfile
862 
863 
864 !------------------------------------------------------------------------------
865 !:sdoc+:
866 !
867 ! NAME:
868 ! CRTM_SensorData_WriteFile
869 !
870 ! PURPOSE:
871 ! Function to write CRTM SensorData object files.
872 !
873 ! CALLING SEQUENCE:
874 ! Error_Status = CRTM_SensorData_WriteFile( Filename , &
875 ! SensorData , &
876 ! Quiet = Quiet , &
877 ! No_Close = No_Close )
878 !
879 ! INPUTS:
880 ! Filename: Character string specifying the name of the
881 ! SensorData format data file to write.
882 ! UNITS: N/A
883 ! TYPE: CHARACTER(*)
884 ! DIMENSION: Scalar
885 ! ATTRIBUTES: INTENT(IN)
886 !
887 ! SensorData: CRTM SensorData object array containing the datasets.
888 ! UNITS: N/A
889 ! TYPE: CRTM_SensorData_type
890 ! DIMENSION: Rank-1
891 ! ATTRIBUTES: INTENT(IN)
892 !
893 ! OPTIONAL INPUTS:
894 ! Quiet: Set this logical argument to suppress INFORMATION
895 ! messages being printed to stdout
896 ! If == .FALSE., INFORMATION messages are OUTPUT [DEFAULT].
897 ! == .TRUE., INFORMATION messages are SUPPRESSED.
898 ! If not specified, default is .FALSE.
899 ! UNITS: N/A
900 ! TYPE: LOGICAL
901 ! DIMENSION: Scalar
902 ! ATTRIBUTES: INTENT(IN), OPTIONAL
903 !
904 ! No_Close: Set this logical argument to NOT close the file upon exit.
905 ! If == .FALSE., the input file is closed upon exit [DEFAULT]
906 ! == .TRUE., the input file is NOT closed upon exit.
907 ! If not specified, default is .FALSE.
908 ! UNITS: N/A
909 ! TYPE: LOGICAL
910 ! DIMENSION: Scalar
911 ! ATTRIBUTES: INTENT(IN), OPTIONAL
912 !
913 ! FUNCTION RESULT:
914 ! Error_Status: The return value is an integer defining the error status.
915 ! The error codes are defined in the Message_Handler module.
916 ! If == SUCCESS, the file write was successful
917 ! == FAILURE, an unrecoverable error occurred.
918 ! UNITS: N/A
919 ! TYPE: INTEGER
920 ! DIMENSION: Scalar
921 !
922 ! SIDE EFFECTS:
923 ! - If the output file already exists, it is overwritten.
924 ! - If an error occurs during *writing*, the output file is deleted before
925 ! returning to the calling routine.
926 !
927 !:sdoc-:
928 !------------------------------------------------------------------------------
929 
930  FUNCTION crtm_sensordata_writefile( &
931  Filename , & ! Input
932  SensorData, & ! Input
933  Quiet , & ! Optional input
934  No_Close , & ! Optional input
935  Debug ) & ! Optional input (Debug output control)
936  result( err_stat )
937  ! Arguments
938  CHARACTER(*), INTENT(IN) :: filename
939  TYPE(crtm_sensordata_type), INTENT(IN) :: sensordata(:)
940  LOGICAL, OPTIONAL, INTENT(IN) :: quiet
941  LOGICAL, OPTIONAL, INTENT(IN) :: no_close
942  LOGICAL, OPTIONAL, INTENT(IN) :: debug
943  ! Function result
944  INTEGER :: err_stat
945  ! Function parameters
946  CHARACTER(*), PARAMETER :: routine_name = 'CRTM_SensorData_WriteFile'
947  CHARACTER(*), PARAMETER :: file_status_on_error = 'DELETE'
948  ! Function variables
949  CHARACTER(ML) :: msg
950  LOGICAL :: noisy
951  LOGICAL :: yes_close
952  INTEGER :: io_stat
953  INTEGER :: fid
954  INTEGER :: i, n
955 
956  ! Setup
957  err_stat = success
958  ! ...Check Quiet argument
959  noisy = .true.
960  IF ( PRESENT(quiet) ) noisy = .NOT. quiet
961  ! ...Check file close argument
962  yes_close = .true.
963  IF ( PRESENT(no_close) ) yes_close = .NOT. no_close
964  ! ...Override Quiet settings if debug set.
965  IF ( PRESENT(debug) ) THEN
966  IF ( debug ) noisy = .true.
967  END IF
968 
969  ! Check the SensorData structure dimensions
970  IF ( any(sensordata%n_Channels < 1) ) THEN
971  msg = 'Dimensions of SensorData structures are < or = 0.'
972  CALL write_cleanup(); RETURN
973  END IF
974 
975 
976  ! Check if the file is open
977  IF ( file_open( filename ) ) THEN
978  ! Yes, the file is already open
979  INQUIRE( file=filename,number=fid )
980  IF ( fid == -1 ) THEN
981  msg = 'Error inquiring '//trim(filename)//' for its fid'
982  CALL write_cleanup(); RETURN
983  END IF
984  ELSE
985  ! No, the file is not open
986  err_stat = open_binary_file( filename, fid, for_output = .true. )
987  IF ( err_stat /= success ) THEN
988  msg = 'Error opening '//trim(filename)
989  CALL write_cleanup(); RETURN
990  END IF
991  END IF
992 
993 
994  ! Write the number of SensorDatas dimension
995  n = SIZE(sensordata)
996  WRITE( fid,iostat=io_stat) n
997  IF ( io_stat /= 0 ) THEN
998  WRITE( msg,'("Error writing dataset dimensions to ",a,". IOSTAT = ",i0)' ) &
999  trim(filename), io_stat
1000  CALL write_cleanup(close_file=.true.); RETURN
1001  END IF
1002 
1003 
1004  ! Write the SensorData data
1005  sensordata_loop: DO i = 1, n
1006  err_stat = write_record( fid, sensordata(i) )
1007  IF ( err_stat /= success ) THEN
1008  WRITE( msg,'("Error writing SensorData element #",i0," to ",a)' ) &
1009  i, trim(filename)
1010  CALL write_cleanup(close_file=.true.); RETURN
1011  END IF
1012  END DO sensordata_loop
1013 
1014 
1015  ! Close the file (if error, no delete)
1016  IF ( yes_close ) THEN
1017  CLOSE( fid,status='KEEP',iostat=io_stat )
1018  IF ( io_stat /= 0 ) THEN
1019  WRITE( msg,'("Error closing ",a,". IOSTAT = ",i0)' ) trim(filename), io_stat
1020  CALL write_cleanup(); RETURN
1021  END IF
1022  END IF
1023 
1024 
1025  ! Output an info message
1026  IF ( noisy ) THEN
1027  WRITE( msg,'("Number of datasets written to ",a,": ",i0)' ) trim(filename), n
1028  CALL display_message( routine_name, trim(msg), information )
1029  END IF
1030 
1031  CONTAINS
1032 
1033  SUBROUTINE write_cleanup( Close_File )
1034  LOGICAL, OPTIONAL, INTENT(IN) :: Close_File
1035  ! Close file if necessary
1036  IF ( PRESENT(close_file) ) THEN
1037  IF ( close_file ) THEN
1038  CLOSE( fid,status=write_error_status,iostat=io_stat )
1039  IF ( io_stat /= 0 ) &
1040  msg = trim(msg)//'; Error deleting output file during error cleanup.'
1041  END IF
1042  END IF
1043  ! Set error status and print error message
1044  err_stat = failure
1045  CALL display_message( routine_name, trim(msg), err_stat )
1046  END SUBROUTINE write_cleanup
1047 
1048  END FUNCTION crtm_sensordata_writefile
1049 
1050 
1051 !##################################################################################
1052 !##################################################################################
1053 !## ##
1054 !## ## PRIVATE MODULE ROUTINES ## ##
1055 !## ##
1056 !##################################################################################
1057 !##################################################################################
1058 
1059 !------------------------------------------------------------------------------
1060 !
1061 ! NAME:
1062 ! CRTM_SensorData_Equal
1063 !
1064 ! PURPOSE:
1065 ! Elemental function to test the equality of two CRTM_SensorData objects.
1066 ! Used in OPERATOR(==) interface block.
1067 !
1068 ! CALLING SEQUENCE:
1069 ! is_equal = CRTM_SensorData_Equal( x, y )
1070 !
1071 ! or
1072 !
1073 ! IF ( x == y ) THEN
1074 ! ...
1075 ! END IF
1076 !
1077 ! OBJECTS:
1078 ! x, y: Two CRTM SensorData objects to be compared.
1079 ! UNITS: N/A
1080 ! TYPE: CRTM_SensorData_type
1081 ! DIMENSION: Scalar or any rank
1082 ! ATTRIBUTES: INTENT(IN)
1083 !
1084 ! FUNCTION RESULT:
1085 ! is_equal: Logical value indicating whether the inputs are equal.
1086 ! UNITS: N/A
1087 ! TYPE: LOGICAL
1088 ! DIMENSION: Same as inputs.
1089 !
1090 !------------------------------------------------------------------------------
1091 
1092  ELEMENTAL FUNCTION crtm_sensordata_equal( x, y ) RESULT( is_equal )
1093  TYPE(crtm_sensordata_type) , INTENT(IN) :: x, y
1094  LOGICAL :: is_equal
1095  ! Variables
1096  INTEGER :: n
1097 
1098  ! Set up
1099  is_equal = .false.
1100 
1101  ! Check the structure association status
1102  IF ( (.NOT. crtm_sensordata_associated(x)) .OR. &
1103  (.NOT. crtm_sensordata_associated(y)) ) RETURN
1104 
1105  ! Check contents
1106  ! ...Scalars
1107  IF ( (x%n_Channels /= y%n_Channels ) .OR. &
1108  (x%Sensor_Id /= y%Sensor_Id ) .OR. &
1109  (x%WMO_Satellite_ID /= y%WMO_Satellite_ID) .OR. &
1110  (x%WMO_Sensor_ID /= y%WMO_Sensor_ID ) ) RETURN
1111  ! ...Arrays
1112  n = x%n_Channels
1113  IF ( all(x%Sensor_Channel(1:n) == y%Sensor_Channel(1:n) ) .AND. &
1114  all(x%Tb(1:n) .equalto. y%Tb(1:n)) ) &
1115  is_equal = .true.
1116 
1117  END FUNCTION crtm_sensordata_equal
1118 
1119 
1120 !--------------------------------------------------------------------------------
1121 !
1122 ! NAME:
1123 ! CRTM_SensorData_Add
1124 !
1125 ! PURPOSE:
1126 ! Pure function to add two CRTM SensorData objects.
1127 ! Used in OPERATOR(+) interface block.
1128 !
1129 ! CALLING SEQUENCE:
1130 ! sDatasum = CRTM_SensorData_Add( sData1, sData2 )
1131 !
1132 ! or
1133 !
1134 ! sDatasum = sData1 + sData2
1135 !
1136 !
1137 ! INPUTS:
1138 ! sData1, sData2: The SensorData objects to add.
1139 ! UNITS: N/A
1140 ! TYPE: CRTM_SensorData_type
1141 ! DIMENSION: Scalar or any rank
1142 ! ATTRIBUTES: INTENT(IN OUT)
1143 !
1144 ! RESULT:
1145 ! sDatasum: SensorData structure containing the added components.
1146 ! UNITS: N/A
1147 ! TYPE: CRTM_SensorData_type
1148 ! DIMENSION: Same as input
1149 !
1150 !--------------------------------------------------------------------------------
1151 
1152  ELEMENTAL FUNCTION crtm_sensordata_add( sData1, sData2 ) RESULT( sDatasum )
1153  TYPE(crtm_sensordata_type), INTENT(IN) :: sdata1, sdata2
1154  TYPE(crtm_sensordata_type) :: sdatasum
1155  ! Variables
1156  INTEGER :: n
1157 
1158  ! Check input
1159  ! ...If input structures not used, do nothing
1160  IF ( .NOT. crtm_sensordata_associated( sdata1 ) .OR. &
1161  .NOT. crtm_sensordata_associated( sdata2 ) ) RETURN
1162  ! ...If input structure for different sensors, or sizes, do nothing
1163  IF ( sdata1%n_Channels /= sdata2%n_Channels .OR. &
1164  sdata1%Sensor_Id /= sdata2%Sensor_Id .OR. &
1165  sdata1%WMO_Satellite_ID /= sdata2%WMO_Satellite_ID .OR. &
1166  sdata1%WMO_Sensor_ID /= sdata2%WMO_Sensor_ID .OR. &
1167  any(sdata1%Sensor_Channel /= sdata2%Sensor_Channel) ) RETURN
1168 
1169  ! Copy the first structure
1170  sdatasum = sdata1
1171 
1172  ! And add its components to the second one
1173  n = sdata1%n_Channels
1174  sdatasum%Tb(1:n) = sdatasum%Tb(1:n) + sdata2%Tb(1:n)
1175 
1176  END FUNCTION crtm_sensordata_add
1177 
1178 !--------------------------------------------------------------------------------
1179 !
1180 ! NAME:
1181 ! CRTM_SensorData_Subtract
1182 !
1183 ! PURPOSE:
1184 ! Pure function to subtract two CRTM SensorData objects.
1185 ! Used in OPERATOR(-) interface block.
1186 !
1187 ! CALLING SEQUENCE:
1188 ! sDatadiff = CRTM_SensorData_Subtract( sData1, sData2 )
1189 !
1190 ! or
1191 !
1192 ! sDatadiff = sData1 - sData2
1193 !
1194 !
1195 ! INPUTS:
1196 ! sData1, sData2: The SensorData objects to difference.
1197 ! UNITS: N/A
1198 ! TYPE: CRTM_SensorData_type
1199 ! DIMENSION: Scalar or any rank
1200 ! ATTRIBUTES: INTENT(IN OUT)
1201 !
1202 ! RESULT:
1203 ! sDatadiff: SensorData structure containing the differenced components.
1204 ! UNITS: N/A
1205 ! TYPE: CRTM_SensorData_type
1206 ! DIMENSION: Same as input
1207 !
1208 !--------------------------------------------------------------------------------
1209 
1210  ELEMENTAL FUNCTION crtm_sensordata_subtract( sData1, sData2 ) RESULT( sDatadiff )
1211  TYPE(crtm_sensordata_type), INTENT(IN) :: sdata1, sdata2
1212  TYPE(crtm_sensordata_type) :: sdatadiff
1213  ! Variables
1214  INTEGER :: n
1215 
1216  ! Check input
1217  ! ...If input structures not used, do nothing
1218  IF ( .NOT. crtm_sensordata_associated( sdata1 ) .OR. &
1219  .NOT. crtm_sensordata_associated( sdata2 ) ) RETURN
1220  ! ...If input structure for different sensors, or sizes, do nothing
1221  IF ( sdata1%n_Channels /= sdata2%n_Channels .OR. &
1222  sdata1%Sensor_Id /= sdata2%Sensor_Id .OR. &
1223  sdata1%WMO_Satellite_ID /= sdata2%WMO_Satellite_ID .OR. &
1224  sdata1%WMO_Sensor_ID /= sdata2%WMO_Sensor_ID .OR. &
1225  any(sdata1%Sensor_Channel /= sdata2%Sensor_Channel) ) RETURN
1226 
1227  ! Copy the first structure
1228  sdatadiff = sdata1
1229 
1230  ! And subtract the second one's components from it
1231  n = sdata1%n_Channels
1232  sdatadiff%Tb(1:n) = sdatadiff%Tb(1:n) - sdata2%Tb(1:n)
1233 
1234  END FUNCTION crtm_sensordata_subtract
1235 
1236 
1237 !----------------------------------------------------------------------------------
1238 !
1239 ! NAME:
1240 ! Read_Record
1241 !
1242 ! PURPOSE:
1243 ! Utility function to read a single CRTM SensorData object
1244 !
1245 ! CALLING SEQUENCE:
1246 ! Error_Status = Read_Record( FileID, SensorData )
1247 !
1248 ! INPUTS:
1249 ! FileID: Logical unit number from which to read data.
1250 ! UNITS: N/A
1251 ! TYPE: INTEGER
1252 ! DIMENSION: Scalar
1253 ! ATTRIBUTES: INTENT(IN)
1254 !
1255 ! OUTPUTS:
1256 ! SensorData: CRTM SensorData object containing the data read in.
1257 ! UNITS: N/A
1258 ! TYPE: CRTM_SensorData_type
1259 ! DIMENSION: Scalar
1260 ! ATTRIBUTES: INTENT(OUT)
1261 !
1262 ! FUNCTION RESULT:
1263 ! Error_Status: The return value is an integer defining the error status.
1264 ! The error codes are defined in the Message_Handler module.
1265 ! If == SUCCESS, the record read was successful
1266 ! == FAILURE, an unrecoverable error occurred.
1267 ! UNITS: N/A
1268 ! TYPE: INTEGER
1269 ! DIMENSION: Scalar
1270 !
1271 !----------------------------------------------------------------------------------
1272 
1273  FUNCTION read_record( &
1274  fid , & ! Input
1275  SensorData) & ! Output
1276  result( err_stat )
1277  ! Arguments
1278  INTEGER , INTENT(IN) :: fid
1279  TYPE(crtm_sensordata_type), INTENT(OUT) :: sensordata
1280  ! Function result
1281  INTEGER :: err_stat
1282  ! Function parameters
1283  CHARACTER(*), PARAMETER :: routine_name = 'CRTM_SensorData_ReadFile(Record)'
1284  ! Function variables
1285  CHARACTER(ML) :: msg
1286  INTEGER :: io_stat
1287  INTEGER :: n_channels
1288 
1289  ! Set up
1290  err_stat = success
1291 
1292 
1293  ! Read the dimensions
1294  READ( fid,iostat=io_stat ) n_channels
1295  IF ( io_stat /= 0 ) THEN
1296  WRITE( msg,'("Error reading data dimensions. IOSTAT = ",i0)' ) io_stat
1297  CALL read_record_cleanup(); RETURN
1298  END IF
1299 
1300 
1301  ! Allocate the structure
1302  CALL crtm_sensordata_create( sensordata, n_channels )
1303  IF ( .NOT. crtm_sensordata_associated( sensordata ) ) THEN
1304  msg = 'SensorData object allocation failed.'
1305  CALL read_record_cleanup(); RETURN
1306  END IF
1307 
1308 
1309  ! Read the SensorData data
1310  READ( fid,iostat=io_stat ) sensordata%Sensor_Id , &
1311  sensordata%WMO_Satellite_ID, &
1312  sensordata%WMO_Sensor_ID , &
1313  sensordata%Sensor_Channel , &
1314  sensordata%Tb
1315  IF ( io_stat /= 0 ) THEN
1316  WRITE( msg,'("Error reading SensorData data. IOSTAT = ",i0)' ) io_stat
1317  CALL read_record_cleanup(); RETURN
1318  END IF
1319 
1320  CONTAINS
1321 
1322  SUBROUTINE read_record_cleanup()
1323  ! Deallocate SensorData structure if necessary
1324  CALL crtm_sensordata_destroy( sensordata )
1325  ! Close input file
1326  CLOSE( fid,iostat=io_stat )
1327  IF ( io_stat /= success ) &
1328  msg = trim(msg)//'; Error closing file during error cleanup'
1329  ! Report error(s)
1330  err_stat = failure
1331  CALL display_message( routine_name, trim(msg), err_stat )
1332  END SUBROUTINE read_record_cleanup
1333 
1334  END FUNCTION read_record
1335 
1336 
1337 !----------------------------------------------------------------------------------
1338 !
1339 ! NAME:
1340 ! Write_Record
1341 !
1342 ! PURPOSE:
1343 ! Function to write a single CRTM SensorData object
1344 !
1345 ! CALLING SEQUENCE:
1346 ! Error_Status = Write_Record( FileID, SensorData )
1347 !
1348 ! INPUT ARGUMENTS:
1349 ! FileID: Logical unit number to which data is written
1350 ! UNITS: N/A
1351 ! TYPE: INTEGER
1352 ! DIMENSION: Scalar
1353 ! ATTRIBUTES: INTENT(IN)
1354 !
1355 ! SensorData: CRTM SensorData object containing the data to write.
1356 ! UNITS: N/A
1357 ! TYPE: CRTM_SensorData_type
1358 ! DIMENSION: Scalar
1359 ! ATTRIBUTES: INTENT(IN)
1360 !
1361 ! FUNCTION RESULT:
1362 ! Error_Status: The return value is an integer defining the error status.
1363 ! The error codes are defined in the Message_Handler module.
1364 ! If == SUCCESS, the write was successful
1365 ! == FAILURE, an unrecoverable error occurred.
1366 ! UNITS: N/A
1367 ! TYPE: INTEGER
1368 ! DIMENSION: Scalar
1369 !
1370 !----------------------------------------------------------------------------------
1371 
1372  FUNCTION write_record( &
1373  fid , & ! Input
1374  SensorData) & ! Input
1375  result( err_stat )
1376  ! Arguments
1377  INTEGER , INTENT(IN) :: fid
1378  TYPE(crtm_sensordata_type), INTENT(IN) :: sensordata
1379  ! Function result
1380  INTEGER :: err_stat
1381  ! Function parameters
1382  CHARACTER(*), PARAMETER :: routine_name = 'CRTM_SensorData_WriteFile(Record)'
1383  ! Function variables
1384  CHARACTER(ML) :: msg
1385  INTEGER :: io_stat
1386 
1387  ! Setup
1388  err_stat = success
1389  IF ( .NOT. crtm_sensordata_associated( sensordata ) ) THEN
1390  msg = 'Input SensorData object is not used.'
1391  CALL write_record_cleanup(); RETURN
1392  END IF
1393 
1394 
1395  ! Write the dimensions
1396  WRITE( fid,iostat=io_stat ) sensordata%n_Channels
1397  IF ( io_stat /= 0 ) THEN
1398  WRITE( msg,'("Error writing dimensions. IOSTAT = ",i0)' ) io_stat
1399  CALL write_record_cleanup(); RETURN
1400  END IF
1401 
1402 
1403  ! Write the data
1404  WRITE( fid,iostat=io_stat ) sensordata%Sensor_Id , &
1405  sensordata%WMO_Satellite_ID, &
1406  sensordata%WMO_Sensor_ID , &
1407  sensordata%Sensor_Channel , &
1408  sensordata%Tb
1409  IF ( io_stat /= 0 ) THEN
1410  WRITE( msg,'("Error writing SensorData data. IOSTAT = ",i0)' ) io_stat
1411  CALL write_record_cleanup(); RETURN
1412  END IF
1413 
1414  CONTAINS
1415 
1416  SUBROUTINE write_record_cleanup()
1417  ! Close and delete output file
1418  CLOSE( fid,status=write_error_status,iostat=io_stat )
1419  IF ( io_stat /= success ) &
1420  msg = trim(msg)//'; Error closing file during error cleanup'
1421  ! Report error(s)
1422  err_stat = failure
1423  CALL display_message( routine_name, trim(msg), err_stat )
1424  END SUBROUTINE write_record_cleanup
1425 
1426  END FUNCTION write_record
1427 
1428 END MODULE crtm_sensordata_define
elemental subroutine, public crtm_sensordata_create(SensorData, n_Channels)
integer, parameter, public failure
integer, parameter, public invalid_wmo_sensor_id
subroutine, public crtm_sensordata_inspect(SensorData, Unit)
integer, parameter, public strlen
integer, parameter, public warning
integer, parameter, public fp
Definition: Type_Kinds.f90:124
elemental logical function, public crtm_sensordata_associated(SensorData)
integer function, public readgatts_binary_file(fid, Write_Module, Created_On, Title, History, Comment)
elemental logical function, public crtm_sensordata_compare(x, y, n_SigFig)
integer function, public crtm_sensordata_writefile(Filename, SensorData, Quiet, No_Close, Debug)
character(*), parameter write_error_status
integer function, public crtm_sensordata_inquirefile(Filename, n_DataSets)
subroutine inquire_cleanup()
integer, parameter, public invalid_wmo_satellite_id
logical function, public crtm_sensordata_isvalid(SensorData)
subroutine read_cleanup()
elemental subroutine, public crtm_sensordata_destroy(SensorData)
subroutine write_cleanup()
elemental subroutine, public crtm_sensordata_zero(SensorData)
subroutine read_record_cleanup()
integer function, public open_binary_file(Filename, FileID, For_Output, No_Check)
recursive subroutine, public display_message(Routine_Name, Message, Error_State, Message_Log)
elemental type(crtm_sensordata_type) function crtm_sensordata_subtract(sData1, sData2)
integer, parameter, public default_n_sigfig
integer function, public writegatts_binary_file(fid, Write_Module, Created_On, Title, History, Comment)
subroutine, public crtm_sensordata_defineversion(Id)
subroutine write_record_cleanup()
integer function read_record(fid, SensorData)
character(*), parameter module_version_id
integer function, public crtm_sensordata_readfile(Filename, SensorData, Quiet, No_Close, n_DataSets, Debug)
elemental type(crtm_sensordata_type) function crtm_sensordata_add(sData1, sData2)
elemental logical function crtm_sensordata_equal(x, y)
integer, parameter, public success
integer, parameter, public information