@@ -711,6 +711,30 @@ def __init__(
711711 mode , quality , swap , missing_value_mode
712712 )
713713
714+ @classmethod
715+ def from_filter_options (cls , filter_options : tuple [int , ...]) -> Sperr :
716+ if len (filter_options ) < 2 :
717+ raise ValueError (f"Expected at least 2 values, got { len (filter_options )} " )
718+
719+ mode , quality , swap , missing_value_mode = cls .__unpack_options (
720+ meta = filter_options [0 ], ret = filter_options [1 ]
721+ )
722+
723+ if mode == 2 :
724+ return cls (
725+ peak_signal_to_noise_ratio = quality ,
726+ swap = swap ,
727+ missing_value_mode = missing_value_mode ,
728+ )
729+ if mode == 3 :
730+ return cls (
731+ absolute = quality , swap = swap , missing_value_mode = missing_value_mode
732+ )
733+ if mode == 1 :
734+ return cls (rate = quality , swap = swap , missing_value_mode = missing_value_mode )
735+
736+ raise ValueError (f"Mode must be in [1, 3], got { mode } " )
737+
714738 @classmethod
715739 def __pack_options (
716740 cls , mode : int , quality : float , swap : bool , missing_value_mode : int
@@ -746,6 +770,40 @@ def __pack_options(
746770
747771 return ret , missing_value_mode
748772
773+ @classmethod
774+ def __unpack_options (cls , meta : int , ret : int ) -> tuple [int , float , bool , int ]:
775+ # Unpack missing value mode from packed_info bits 6-9
776+ # See h5zsperr_unpack_extra_info
777+ missing_value_mode = (meta >> 6 ) & 0b1111
778+
779+ # Unpack other fields from ret
780+ # See H5Z_SPERR_decode_cd_values
781+ swap = bool (ret >> (cls ._INTEGER_BITS + cls ._FRACTIONAL_BITS + 3 ))
782+
783+ bit1 = (ret >> (cls ._INTEGER_BITS + cls ._FRACTIONAL_BITS )) & 1
784+ bit2 = (ret >> (cls ._INTEGER_BITS + cls ._FRACTIONAL_BITS + 1 )) & 1
785+ if bit1 and not bit2 :
786+ mode = 1
787+ elif not bit1 and bit2 :
788+ mode = 2
789+ elif bit1 and bit2 :
790+ mode = 3
791+ else :
792+ raise ValueError ("Mode must be in [1, 3], got 0" )
793+
794+ negative = bool ((ret >> (cls ._INTEGER_BITS + cls ._FRACTIONAL_BITS - 1 )) & 1 )
795+
796+ mask = 1 << (cls ._INTEGER_BITS + cls ._FRACTIONAL_BITS - 1 )
797+ masked_ret = ret & (mask - 1 )
798+
799+ quality = float (masked_ret ) / float (1 << cls ._FRACTIONAL_BITS )
800+ if negative :
801+ quality *= - 1.0
802+ if mode == 3 :
803+ quality = math .exp2 (quality )
804+
805+ return mode , quality , swap , missing_value_mode
806+
749807
750808class SZ (FilterBase ):
751809 """``h5py.Group.create_dataset``'s compression arguments for using SZ2 filter.
0 commit comments