649class TdlpackRecord(object):
650 """
651 Defines a TDLPACK data record object. Once data are unpacked (TdlpackRecord.unpack(data=True)),
652 values are accessible using "fancy indexing".
653
654 For gridded records, use grid index values and/or ranges (e.g. rec[0,0]).
655
656 For station records, use the station ID string: (e.g. rec['KPHL']).
657
658 Attributes
659 ----------
660
661 **`data : array_like`**
662
663 Data values.
664
665 **`grid_length : float`**
666
667 Distance between grid points in units of meters.
668
669 **`id : array_like`**
670
671 ID of the TDLPACK data record. This is a NumPy 1D array of dtype=np.int32.
672
673 **`ioctet : int`**
674
675 Size of the packed TDLPACK data record in bytes.
676
677 **`ipack : array_like`**
678
679 Packed TDLPACK data record. This is a NumPy 1D array of dtype=np.int32.
680
681 **`is0 : array_like`**
682
683 TDLPACK Section 0 (Indicator Section).
684
685 **`is1 : array_like`**
686
687 TDLPACK Section 1 (Product Definition Section).
688
689 **`is2 : array_like`**
690
691 TDLPACK Section 2 (Grid Definition Section)
692
693 **`is4 : array_like`**
694
695 TDLPACK Section 4 (Data Section).
696
697 **`lead_time : int`**
698
699 Forecast lead time in units of hours.
700
701 **`lower_left_latitude : float`**
702
703 Latitude of lower left grid point
704
705 **`lower_left_longitude : float`**
706
707 Longitude of lower left grid point
708
709 **`number_of_values : int`**
710
711 Number of data values.
712
713 **`nx : int`**
714
715 Number of points in the x-direction (West-East).
716
717 **`ny : int`**
718
719 Number of points in the y-direction (West-East).
720
721 **`origin_longitude : float`**
722
723 Originating longitude of projected grid.
724
725 **`plain : str`**
726
727 Plain language description of TDLPACK record.
728
729 **`primary_missing_value : float`**
730
731 Primary missing value.
732
733 **`reference_date : int`**
734
735 Reference date from the TDLPACK data record in YYYYMMDDHH format.
736
737 **`secondary_missing_value : float`**
738
739 Secondary missing value.
740
741 **`standard_latitude : float`**
742
743 Latitude at which the grid length applies.
744
745 **`type : {'grid', 'station'}`**
746
747 Identifies the type of data. This implies that data are 1D for type = 'station'
748 and data are 2D for type = 'grid'.
749
750 """
751 counter = 0
752 def __init__(self,date=None,id=None,lead=None,plain=None,grid=None,data=None,
753 missing_value=None,**kwargs):
754 """
755 Constructor
756
757 Parameters
758 ----------
759
760 **`date : int, optional`**
761
762 Forecast initialization or observation date in YYYYMMDDHH format.
763
764 **`id : list or 1-D array, optional`**
765
766 List or 1-D array of length 4 containing the 4-word (integer) MOS-2000 ID of the data
767 to be put into TdlpackRecord
768
769 **`lead : int, optional`**
770
771 Lead time (i.e. forecast projection) in hours of the data. NOTE: This can be omitted
772
773 **`plain : str, optional`**
774
775 Plain language descriptor. This is limited to 32 characters, though here
776 the input can be longer (will be cut off when packing).
777
778 **`grid : dict , optional`**
779
780 A dictionary containing grid definition attributes. See
781 Dictionary of grid specs (created from create_grid_def_dict)
782
783 **`data : array_like, optional`**
784
785 Data values.
786
787 **`missing_value : float or list of floats, optional`**
788
789 Provide either a primary missing value or primary and secondary as list.
790
791 **`**kwargs : dict, optional`**
792
793 Dictionary of class attributes (keys) and class attributes (values).
794 """
795 type(self).counter += 1
796 self._metadata_unpacked = False
797 self._data_unpacked = False
798 self.plain = ''
799 if len(kwargs) == 0:
800 # Means we are creating TdlpackRecord instance from the other function
801 # input, NOT the kwargs Dict.
802 self.id = id
803 self.reference_date = date
804 self.type = 'station'
805 self.is0 = np.zeros(ND7,dtype=np.int32)
806 self.is1 = np.zeros(ND7,dtype=np.int32)
807 self.is2 = np.zeros(ND7,dtype=np.int32)
808 self.is4 = np.zeros(ND7,dtype=np.int32)
809
810 self.is1[2] = np.int32(date/1000000)
811 self.is1[3] = np.int32((date/10000)-(self.is1[2]*100))
812 self.is1[4] = np.int32((date/100)-(self.is1[2]*10000)-(self.is1[3]*100))
813 self.is1[5] = np.int32(date-((date/100)*100))
814 self.is1[6] = np.int32(0)
815 self.is1[7] = np.int32(date)
816 self.is1[8] = np.int32(id[0])
817 self.is1[9] = np.int32(id[1])
818 self.is1[10] = np.int32(id[2])
819 self.is1[11] = np.int32(id[3])
820 if lead is None:
821 self.is1[12] = np.int32(self.is1[10]-((self.is1[10]/1000)*1000))
822 else:
823 self.is1[12] = np.int32(lead)
824 self.is1[13] = np.int32(0)
825 self.is1[14] = np.int32(self.is1[8]-((self.is1[8]/100)*100))
826 self.is1[15] = np.int32(0)
827 self.is1[16] = np.int32(0)
828 self.is1[17] = np.int32(0)
829 self.is1[18] = np.int32(0)
830 self.is1[19] = np.int32(0)
831 self.is1[20] = np.int32(0)
832 self.is1[21] = NCHAR_PLAIN
833 if plain is None:
834 self.plain = ' '*NCHAR_PLAIN
835 else:
836 self.plain = plain
837 for n,p in enumerate(plain):
838 self.is1[22+n] = np.int32(ord(p))
839
840 if grid is not None and type(grid) is dict or data.shape == 2:
841 # Gridded Data
842 self.type = 'grid'
843 self.is1[1] = np.int32(1) # Set IS1[1] = 1
844 self.is2[1] = np.int32(grid['proj'])
845 self.is2[2] = np.int32(grid['nx'])
846 self.is2[3] = np.int32(grid['ny'])
847 self.is2[4] = np.int32(grid['latll']*10000)
848 self.is2[5] = np.int32(grid['lonll']*10000)
849 self.is2[6] = np.int32(grid['orientlon']*10000)
850 self.is2[7] = np.int32(grid['meshlength']*1000) # Value in dict is in units of meters.
851 self.is2[8] = np.int32(grid['stdlat']*10000)
852 self.nx = np.int32(grid['nx'])
853 self.ny = np.int32(grid['ny'])
854 if len(data) > 0:
855 self.data = np.array(data,dtype=np.float32)
856 self.number_of_values = len(data)
857 self._data_unpacked = True
858 else:
859 raise ValueError
860
861 if missing_value is None:
862 self.primary_missing_value = np.int32(0)
863 self.secondary_missing_value = np.int32(0)
864 else:
865 if type(missing_value) is list:
866 if len(missing_value) == 1:
867 self.primary_missing_value = np.int32(missing_value[0])
868 elif len(missing_value) == 2:
869 self.primary_missing_value = np.int32(missing_value[0])
870 self.secondary_missing_value = np.int32(missing_value[1])
871 else:
872 self.primary_missing_value = np.int32(missing_value)
873 self.secondary_missing_value = np.int32(0)
874
875 else:
876 # Instantiate via **kwargs
877 for k,v in kwargs.items():
878 setattr(self,k,v)
879
880 def __getitem__(self,indices):
881 """
882 """
883 if self.type == 'grid':
884 if not isinstance(indices,tuple):
885 indices = tuple(indices)
886 elif self.type == 'station':
887 if isinstance(indices,str):
888 indices = tuple([_starecdict[self._filelun][self._starecindex].index(indices)])
889
890 try:
891 return self.data[indices]
892 except(AttributeError):
893 return None
894
895 def __setitem__(self,indices,values):
896 """
897 """
898 if self.type == 'grid':
899 if not isinstance(indices,tuple):
900 indices = tuple(indices)
901 elif self.type == 'station':
902 if isinstance(indices,str):
903 indices = tuple([_starecdict[self._filelun][self._starecindex].index(indices)])
904
905 self.data[indices] = values
906
907 def __repr__(self):
908 strings = []
909 keys = self.__dict__.keys()
910 for k in keys:
911 if not k.startswith('_'):
912 strings.append('%s = %s\n'%(k,self.__dict__[k]))
913 return ''.join(strings)
914
915 def pack(self,dec_scale=None,bin_scale=None):
916 """
917 Pack a TDLPACK record.
918
919 Parameters
920 ----------
921
922 **`dec_scale : int, optional, default = 1`**
923
924 Decimal Scale Factor used to when packing TdlpackRecord data [DEFAULT is 1].
925
926 **`bin_scale : int, optional, default = 0`**
927
928 Binary Scale Factor used to when packing TdlpackRecord data [DEFAULT is 0]. NOTE:
929 binary scale factor is currently NOT SUPPORTED in MOS-2000 software. It is added
930 here for completeness.
931 """
932
933 # Make sure data are unpacked
934 if not self._data_unpacked:
935 self.unpack(data=True)
936
937 _ier = np.int32(0)
938 self.ipack = np.zeros((ND5),dtype=np.int32)
939
940 if dec_scale is not None:
941 self.is1[16] = np.int32(dec_scale)
942
943 if bin_scale is not None:
944 self.is1[17] = np.int32(bin_scale)
945
946 # Pack plain langauge into IS1 array.
947 self.plain = self.plain.ljust(NCHAR_PLAIN)
948 for n,p in enumerate(self.plain):
949 self.is1[22+n] = np.int32(ord(p))
950
951 # Handle potential NaN values
952 if self.primary_missing_value == 0:
953 self.primary_missing_value == DEFAULT_MISSING_VALUE
954 self.data = np.where(np.isnan(self.data),np.float32(self.primary_missing_value),
955 self.data)
956
957 if self.type == 'grid':
958 _a = np.zeros((self.is2[2],self.is2[3]),dtype=np.float32,order='F')
959 _ia = np.zeros((self.is2[2],self.is2[3]),dtype=np.int32,order='F')
960 _ic = np.zeros((self.is2[2]*self.is2[3]),dtype=np.int32)
961
962 self.ioctet,_ier = tdlpack.pack2d(FORTRAN_STDOUT_LUN,self.data,_ia,_ic,self.is0,
963 self.is1,self.is2,self.is4,self.primary_missing_value,
964 self.secondary_missing_value,self.ipack,MINPK,_lx,L3264B)
965 elif self.type == 'station':
966 _ic = np.zeros((self.number_of_values),dtype=np.int32)
967 self.ioctet,_ier = tdlpack.pack1d(FORTRAN_STDOUT_LUN,self.data,_ic,self.is0,
968 self.is1,self.is2,self.is4,self.primary_missing_value,
969 self.secondary_missing_value,self.ipack,MINPK,
970 _lx,L3264B)
971
972 def unpack(self,data=False,missing_value=None):
973 """
974 Unpacks the TDLPACK identification sections and data (optional).
975
976 Parameters
977 ----------
978
979 **`data : bool, optional`**
980
981 If True, unpack data values. The default is False.
982
983 **`missing_value : float, optional`**
984
985 Set a missing value. If a missing value exists for the TDLPACK data record,
986 it will be replaced with this value.
987 """
988 _ier = np.int32(0)
989 if not self._metadata_unpacked:
990 if self.ipack.shape[0] < ND5_META_MAX:
991 _nd5_local = self.ipack.shape[0]
992 else:
993 _nd5_local = ND5_META_MAX
994 _data_meta = np.zeros((_nd5_local),dtype=np.int32)
995 _iwork_meta = np.zeros((_nd5_local),dtype=np.int32)
996 _data_meta,_ier = tdlpack.unpack(FORTRAN_STDOUT_LUN,self.ipack[0:_nd5_local],
997 _iwork_meta,_is0,_is1,_is2,_is4,_misspx,
998 _misssx,np.int32(1),L3264B)
999 if _ier == 0:
1000 self._metadata_unpacked = True
1001 self.is0 = deepcopy(_is0)
1002 self.is1 = deepcopy(_is1)
1003 self.is2 = deepcopy(_is2)
1004 self.is4 = deepcopy(_is4)
1005 self.id = self.is1[8:12]
1006
1007 # Set attributes from is1[].
1008 self.lead_time = np.int32(str(self.is1[10])[-3:])
1009 if not self.plain:
1010 if self.is1[21] > 0:
1011 for n in np.nditer(self.is1[22:(22+self.is1[21])]):
1012 self.plain += chr(n)
1013 else:
1014 self.plain = ' '*NCHAR_PLAIN
1015
1016 # Set attributes from is2[].
1017 if self.is1[1] == 0:
1018 self.type = 'station'
1019 self.map_proj = None
1020 self.nx = None
1021 self.ny = None
1022 self.lower_left_latitude = None
1023 self.lower_left_longitude = None
1024 self.origin_longitude = None
1025 self.grid_length = None
1026 self.standard_latitude = None
1027 if np.sum(self.is2) > 0: self.is2 = np.zeros((ND7),dtype=np.int32)
1028 elif self.is1[1] == 1:
1029 self.type = 'grid'
1030 self.map_proj = self.is2[1]
1031 self.nx = self.is2[2]
1032 self.ny = self.is2[3]
1033 self.lower_left_latitude = self.is2[4]/10000.
1034 self.lower_left_longitude = self.is2[5]/10000.
1035 self.origin_longitude = self.is2[6]/10000.
1036 self.grid_length = self.is2[7]/1000.
1037 self.standard_latitude = self.is2[8]/10000.
1038 self.grid_def = create_grid_definition(proj=self.map_proj,nx=self.nx,ny=self.ny,
1039 latll=self.lower_left_latitude,lonll=self.lower_left_longitude,
1040 orientlon=self.origin_longitude,stdlat=self.standard_latitude,
1041 meshlength=self.grid_length)
1042 self.proj_string = _create_proj_string(self.grid_def)
1043
1044 # Set attributes from is4[].
1045 self.number_of_values = self.is4[2]
1046 self.primary_missing_value = deepcopy(np.float32(self.is4[3]))
1047 self.secondary_missing_value = deepcopy(np.float32(self.is4[4]))
1048
1049 if data:
1050 self._data_unpacked = True
1051 _nd5_local = max(self.is4[2],int(self.ioctet/NBYPWD))
1052 _iwork = np.zeros((_nd5_local),dtype=np.int32)
1053 _data = np.zeros((_nd5_local),dtype=np.float32)
1054 # Check to make sure the size of self.ipack is long enough. If not, then
1055 # we will "append" to self.ipack.
1056 if self.ipack.shape[0] < _nd5_local:
1057 pad = np.zeros((_nd5_local-self.ipack.shape[0]),dtype=np.int32)
1058 self.ipack = np.append(self.ipack,pad)
1059 _data,_ier = tdlpack.unpack(FORTRAN_STDOUT_LUN,self.ipack[0:_nd5_local],
1060 _iwork,self.is0,self.is1,self.is2,self.is4,
1061 _misspx,_misssx,np.int32(2),L3264B)
1062 if _ier == 0:
1063 _data = deepcopy(_data[0:self.number_of_values+1])
1064 else:
1065 _data = np.zeros((self.number_of_values),dtype=np.float32)+DEFAULT_MISSING_VALUE
1066 self.data = deepcopy(_data[0:self.number_of_values])
1067 if missing_value is not None:
1068 self.data = np.where(self.data==self.primary_missing_value,np.float32(missing_value),self.data)
1069 self.primary_missing_value = np.float32(missing_value)
1070 if self.type == 'grid':
1071 self.data = np.reshape(self.data[0:self.number_of_values],(self.nx,self.ny),order='F')
1072
1073 def latlons(self):
1074 """
1075 Returns a tuple of latitudes and lontiude numpy.float32 arrays for the TDLPACK record.
1076 If the record is station, then return is None.
1077
1078 Returns
1079 -------
1080
1081 **`lats,lons : array_like`**
1082
1083 Numpy.float32 arrays of grid latitudes and longitudes. If `self.grid = 'station'`, then None are returned.
1084 """
1085 lats = None
1086 lons = None
1087 if self.type == 'grid':
1088 _ier = np.int32(0)
1089 lats = np.zeros((self.nx,self.ny),dtype=np.float32,order='F')
1090 lons = np.zeros((self.nx,self.ny),dtype=np.float32,order='F')
1091 lats,lons,_ier = tdlpack.gridij_to_latlon(FORTRAN_STDOUT_LUN,self.nx,self.ny,
1092 self.map_proj,self.grid_length,self.origin_longitude,
1093 self.standard_latitude,self.lower_left_latitude,
1094 self.lower_left_longitude)
1095 return (lats,lons)
Defines a TDLPACK data record object. Once data are unpacked (TdlpackRecord.unpack(data=True)),
values are accessible using "fancy indexing".
For gridded records, use grid index values and/or ranges (e.g. rec[0,0]).
For station records, use the station ID string: (e.g. rec['KPHL']).
Attributes
data : array_like
Data values.
grid_length : float
Distance between grid points in units of meters.
id : array_like
ID of the TDLPACK data record. This is a NumPy 1D array of dtype=np.int32.
ioctet : int
Size of the packed TDLPACK data record in bytes.
ipack : array_like
Packed TDLPACK data record. This is a NumPy 1D array of dtype=np.int32.
is0 : array_like
TDLPACK Section 0 (Indicator Section).
is1 : array_like
TDLPACK Section 1 (Product Definition Section).
is2 : array_like
TDLPACK Section 2 (Grid Definition Section)
is4 : array_like
TDLPACK Section 4 (Data Section).
lead_time : int
Forecast lead time in units of hours.
lower_left_latitude : float
Latitude of lower left grid point
lower_left_longitude : float
Longitude of lower left grid point
number_of_values : int
Number of data values.
nx : int
Number of points in the x-direction (West-East).
ny : int
Number of points in the y-direction (West-East).
origin_longitude : float
Originating longitude of projected grid.
plain : str
Plain language description of TDLPACK record.
primary_missing_value : float
Primary missing value.
reference_date : int
Reference date from the TDLPACK data record in YYYYMMDDHH format.
secondary_missing_value : float
Secondary missing value.
standard_latitude : float
Latitude at which the grid length applies.
type : {'grid', 'station'}
Identifies the type of data. This implies that data are 1D for type = 'station'
and data are 2D for type = 'grid'.
TdlpackRecord( date=None, id=None, lead=None, plain=None, grid=None, data=None, missing_value=None, **kwargs)
752 def __init__(self,date=None,id=None,lead=None,plain=None,grid=None,data=None,
753 missing_value=None,**kwargs):
754 """
755 Constructor
756
757 Parameters
758 ----------
759
760 **`date : int, optional`**
761
762 Forecast initialization or observation date in YYYYMMDDHH format.
763
764 **`id : list or 1-D array, optional`**
765
766 List or 1-D array of length 4 containing the 4-word (integer) MOS-2000 ID of the data
767 to be put into TdlpackRecord
768
769 **`lead : int, optional`**
770
771 Lead time (i.e. forecast projection) in hours of the data. NOTE: This can be omitted
772
773 **`plain : str, optional`**
774
775 Plain language descriptor. This is limited to 32 characters, though here
776 the input can be longer (will be cut off when packing).
777
778 **`grid : dict , optional`**
779
780 A dictionary containing grid definition attributes. See
781 Dictionary of grid specs (created from create_grid_def_dict)
782
783 **`data : array_like, optional`**
784
785 Data values.
786
787 **`missing_value : float or list of floats, optional`**
788
789 Provide either a primary missing value or primary and secondary as list.
790
791 **`**kwargs : dict, optional`**
792
793 Dictionary of class attributes (keys) and class attributes (values).
794 """
795 type(self).counter += 1
796 self._metadata_unpacked = False
797 self._data_unpacked = False
798 self.plain = ''
799 if len(kwargs) == 0:
800 # Means we are creating TdlpackRecord instance from the other function
801 # input, NOT the kwargs Dict.
802 self.id = id
803 self.reference_date = date
804 self.type = 'station'
805 self.is0 = np.zeros(ND7,dtype=np.int32)
806 self.is1 = np.zeros(ND7,dtype=np.int32)
807 self.is2 = np.zeros(ND7,dtype=np.int32)
808 self.is4 = np.zeros(ND7,dtype=np.int32)
809
810 self.is1[2] = np.int32(date/1000000)
811 self.is1[3] = np.int32((date/10000)-(self.is1[2]*100))
812 self.is1[4] = np.int32((date/100)-(self.is1[2]*10000)-(self.is1[3]*100))
813 self.is1[5] = np.int32(date-((date/100)*100))
814 self.is1[6] = np.int32(0)
815 self.is1[7] = np.int32(date)
816 self.is1[8] = np.int32(id[0])
817 self.is1[9] = np.int32(id[1])
818 self.is1[10] = np.int32(id[2])
819 self.is1[11] = np.int32(id[3])
820 if lead is None:
821 self.is1[12] = np.int32(self.is1[10]-((self.is1[10]/1000)*1000))
822 else:
823 self.is1[12] = np.int32(lead)
824 self.is1[13] = np.int32(0)
825 self.is1[14] = np.int32(self.is1[8]-((self.is1[8]/100)*100))
826 self.is1[15] = np.int32(0)
827 self.is1[16] = np.int32(0)
828 self.is1[17] = np.int32(0)
829 self.is1[18] = np.int32(0)
830 self.is1[19] = np.int32(0)
831 self.is1[20] = np.int32(0)
832 self.is1[21] = NCHAR_PLAIN
833 if plain is None:
834 self.plain = ' '*NCHAR_PLAIN
835 else:
836 self.plain = plain
837 for n,p in enumerate(plain):
838 self.is1[22+n] = np.int32(ord(p))
839
840 if grid is not None and type(grid) is dict or data.shape == 2:
841 # Gridded Data
842 self.type = 'grid'
843 self.is1[1] = np.int32(1) # Set IS1[1] = 1
844 self.is2[1] = np.int32(grid['proj'])
845 self.is2[2] = np.int32(grid['nx'])
846 self.is2[3] = np.int32(grid['ny'])
847 self.is2[4] = np.int32(grid['latll']*10000)
848 self.is2[5] = np.int32(grid['lonll']*10000)
849 self.is2[6] = np.int32(grid['orientlon']*10000)
850 self.is2[7] = np.int32(grid['meshlength']*1000) # Value in dict is in units of meters.
851 self.is2[8] = np.int32(grid['stdlat']*10000)
852 self.nx = np.int32(grid['nx'])
853 self.ny = np.int32(grid['ny'])
854 if len(data) > 0:
855 self.data = np.array(data,dtype=np.float32)
856 self.number_of_values = len(data)
857 self._data_unpacked = True
858 else:
859 raise ValueError
860
861 if missing_value is None:
862 self.primary_missing_value = np.int32(0)
863 self.secondary_missing_value = np.int32(0)
864 else:
865 if type(missing_value) is list:
866 if len(missing_value) == 1:
867 self.primary_missing_value = np.int32(missing_value[0])
868 elif len(missing_value) == 2:
869 self.primary_missing_value = np.int32(missing_value[0])
870 self.secondary_missing_value = np.int32(missing_value[1])
871 else:
872 self.primary_missing_value = np.int32(missing_value)
873 self.secondary_missing_value = np.int32(0)
874
875 else:
876 # Instantiate via **kwargs
877 for k,v in kwargs.items():
878 setattr(self,k,v)
Constructor
Parameters
date : int, optional
Forecast initialization or observation date in YYYYMMDDHH format.
id : list or 1-D array, optional
List or 1-D array of length 4 containing the 4-word (integer) MOS-2000 ID of the data
to be put into TdlpackRecord
lead : int, optional
Lead time (i.e. forecast projection) in hours of the data. NOTE: This can be omitted
plain : str, optional
Plain language descriptor. This is limited to 32 characters, though here
the input can be longer (will be cut off when packing).
grid : dict , optional
A dictionary containing grid definition attributes. See
Dictionary of grid specs (created from create_grid_def_dict)
data : array_like, optional
Data values.
missing_value : float or list of floats, optional
Provide either a primary missing value or primary and secondary as list.
**kwargs : dict, optional
Dictionary of class attributes (keys) and class attributes (values).
def
pack(self, dec_scale=None, bin_scale=None):
915 def pack(self,dec_scale=None,bin_scale=None):
916 """
917 Pack a TDLPACK record.
918
919 Parameters
920 ----------
921
922 **`dec_scale : int, optional, default = 1`**
923
924 Decimal Scale Factor used to when packing TdlpackRecord data [DEFAULT is 1].
925
926 **`bin_scale : int, optional, default = 0`**
927
928 Binary Scale Factor used to when packing TdlpackRecord data [DEFAULT is 0]. NOTE:
929 binary scale factor is currently NOT SUPPORTED in MOS-2000 software. It is added
930 here for completeness.
931 """
932
933 # Make sure data are unpacked
934 if not self._data_unpacked:
935 self.unpack(data=True)
936
937 _ier = np.int32(0)
938 self.ipack = np.zeros((ND5),dtype=np.int32)
939
940 if dec_scale is not None:
941 self.is1[16] = np.int32(dec_scale)
942
943 if bin_scale is not None:
944 self.is1[17] = np.int32(bin_scale)
945
946 # Pack plain langauge into IS1 array.
947 self.plain = self.plain.ljust(NCHAR_PLAIN)
948 for n,p in enumerate(self.plain):
949 self.is1[22+n] = np.int32(ord(p))
950
951 # Handle potential NaN values
952 if self.primary_missing_value == 0:
953 self.primary_missing_value == DEFAULT_MISSING_VALUE
954 self.data = np.where(np.isnan(self.data),np.float32(self.primary_missing_value),
955 self.data)
956
957 if self.type == 'grid':
958 _a = np.zeros((self.is2[2],self.is2[3]),dtype=np.float32,order='F')
959 _ia = np.zeros((self.is2[2],self.is2[3]),dtype=np.int32,order='F')
960 _ic = np.zeros((self.is2[2]*self.is2[3]),dtype=np.int32)
961
962 self.ioctet,_ier = tdlpack.pack2d(FORTRAN_STDOUT_LUN,self.data,_ia,_ic,self.is0,
963 self.is1,self.is2,self.is4,self.primary_missing_value,
964 self.secondary_missing_value,self.ipack,MINPK,_lx,L3264B)
965 elif self.type == 'station':
966 _ic = np.zeros((self.number_of_values),dtype=np.int32)
967 self.ioctet,_ier = tdlpack.pack1d(FORTRAN_STDOUT_LUN,self.data,_ic,self.is0,
968 self.is1,self.is2,self.is4,self.primary_missing_value,
969 self.secondary_missing_value,self.ipack,MINPK,
970 _lx,L3264B)
Pack a TDLPACK record.
Parameters
dec_scale : int, optional, default = 1
Decimal Scale Factor used to when packing TdlpackRecord data [DEFAULT is 1].
bin_scale : int, optional, default = 0
Binary Scale Factor used to when packing TdlpackRecord data [DEFAULT is 0]. NOTE:
binary scale factor is currently NOT SUPPORTED in MOS-2000 software. It is added
here for completeness.
def
unpack(self, data=False, missing_value=None):
972 def unpack(self,data=False,missing_value=None):
973 """
974 Unpacks the TDLPACK identification sections and data (optional).
975
976 Parameters
977 ----------
978
979 **`data : bool, optional`**
980
981 If True, unpack data values. The default is False.
982
983 **`missing_value : float, optional`**
984
985 Set a missing value. If a missing value exists for the TDLPACK data record,
986 it will be replaced with this value.
987 """
988 _ier = np.int32(0)
989 if not self._metadata_unpacked:
990 if self.ipack.shape[0] < ND5_META_MAX:
991 _nd5_local = self.ipack.shape[0]
992 else:
993 _nd5_local = ND5_META_MAX
994 _data_meta = np.zeros((_nd5_local),dtype=np.int32)
995 _iwork_meta = np.zeros((_nd5_local),dtype=np.int32)
996 _data_meta,_ier = tdlpack.unpack(FORTRAN_STDOUT_LUN,self.ipack[0:_nd5_local],
997 _iwork_meta,_is0,_is1,_is2,_is4,_misspx,
998 _misssx,np.int32(1),L3264B)
999 if _ier == 0:
1000 self._metadata_unpacked = True
1001 self.is0 = deepcopy(_is0)
1002 self.is1 = deepcopy(_is1)
1003 self.is2 = deepcopy(_is2)
1004 self.is4 = deepcopy(_is4)
1005 self.id = self.is1[8:12]
1006
1007 # Set attributes from is1[].
1008 self.lead_time = np.int32(str(self.is1[10])[-3:])
1009 if not self.plain:
1010 if self.is1[21] > 0:
1011 for n in np.nditer(self.is1[22:(22+self.is1[21])]):
1012 self.plain += chr(n)
1013 else:
1014 self.plain = ' '*NCHAR_PLAIN
1015
1016 # Set attributes from is2[].
1017 if self.is1[1] == 0:
1018 self.type = 'station'
1019 self.map_proj = None
1020 self.nx = None
1021 self.ny = None
1022 self.lower_left_latitude = None
1023 self.lower_left_longitude = None
1024 self.origin_longitude = None
1025 self.grid_length = None
1026 self.standard_latitude = None
1027 if np.sum(self.is2) > 0: self.is2 = np.zeros((ND7),dtype=np.int32)
1028 elif self.is1[1] == 1:
1029 self.type = 'grid'
1030 self.map_proj = self.is2[1]
1031 self.nx = self.is2[2]
1032 self.ny = self.is2[3]
1033 self.lower_left_latitude = self.is2[4]/10000.
1034 self.lower_left_longitude = self.is2[5]/10000.
1035 self.origin_longitude = self.is2[6]/10000.
1036 self.grid_length = self.is2[7]/1000.
1037 self.standard_latitude = self.is2[8]/10000.
1038 self.grid_def = create_grid_definition(proj=self.map_proj,nx=self.nx,ny=self.ny,
1039 latll=self.lower_left_latitude,lonll=self.lower_left_longitude,
1040 orientlon=self.origin_longitude,stdlat=self.standard_latitude,
1041 meshlength=self.grid_length)
1042 self.proj_string = _create_proj_string(self.grid_def)
1043
1044 # Set attributes from is4[].
1045 self.number_of_values = self.is4[2]
1046 self.primary_missing_value = deepcopy(np.float32(self.is4[3]))
1047 self.secondary_missing_value = deepcopy(np.float32(self.is4[4]))
1048
1049 if data:
1050 self._data_unpacked = True
1051 _nd5_local = max(self.is4[2],int(self.ioctet/NBYPWD))
1052 _iwork = np.zeros((_nd5_local),dtype=np.int32)
1053 _data = np.zeros((_nd5_local),dtype=np.float32)
1054 # Check to make sure the size of self.ipack is long enough. If not, then
1055 # we will "append" to self.ipack.
1056 if self.ipack.shape[0] < _nd5_local:
1057 pad = np.zeros((_nd5_local-self.ipack.shape[0]),dtype=np.int32)
1058 self.ipack = np.append(self.ipack,pad)
1059 _data,_ier = tdlpack.unpack(FORTRAN_STDOUT_LUN,self.ipack[0:_nd5_local],
1060 _iwork,self.is0,self.is1,self.is2,self.is4,
1061 _misspx,_misssx,np.int32(2),L3264B)
1062 if _ier == 0:
1063 _data = deepcopy(_data[0:self.number_of_values+1])
1064 else:
1065 _data = np.zeros((self.number_of_values),dtype=np.float32)+DEFAULT_MISSING_VALUE
1066 self.data = deepcopy(_data[0:self.number_of_values])
1067 if missing_value is not None:
1068 self.data = np.where(self.data==self.primary_missing_value,np.float32(missing_value),self.data)
1069 self.primary_missing_value = np.float32(missing_value)
1070 if self.type == 'grid':
1071 self.data = np.reshape(self.data[0:self.number_of_values],(self.nx,self.ny),order='F')
Unpacks the TDLPACK identification sections and data (optional).
Parameters
data : bool, optional
If True, unpack data values. The default is False.
missing_value : float, optional
Set a missing value. If a missing value exists for the TDLPACK data record,
it will be replaced with this value.