3 from .cycommon
import get_mn_y
, tlm2uvswfi
5 'INVERSE' : QPMS_NORMALISATION_INVERSE
,
6 'REVERSE_AZIMUTHAL_PHASE' : QPMS_NORMALISATION_REVERSE_AZIMUTHAL_PHASE
,
7 'SPHARM_REAL' : QPMS_NORMALISATION_SPHARM_REAL
,
8 'M_I' : QPMS_NORMALISATION_M_I
,
9 'M_MINUS' : QPMS_NORMALISATION_M_MINUS
,
10 'N_I' : QPMS_NORMALISATION_N_I
,
11 'N_MINUS' : QPMS_NORMALISATION_N_MINUS
,
12 'L_I' : QPMS_NORMALISATION_L_I
,
13 'L_MINUS' : QPMS_NORMALISATION_L_MINUS
,
14 'CSPHASE' : QPMS_NORMALISATION_CSPHASE
,
15 'UNNORM' : QPMS_NORMALISATION_NORM_NONE
,
16 'UNNORM_CS' : QPMS_NORMALISATION_NORM_NONE | QPMS_NORMALISATION_CSPHASE
,
17 'POWERNORM' : QPMS_NORMALISATION_NORM_POWER
,
18 'POWERNORM_CS' : QPMS_NORMALISATION_NORM_POWER | QPMS_NORMALISATION_CSPHASE
,
19 'SPHARMNORM' : QPMS_NORMALISATION_NORM_SPHARM
,
20 'SPHARMNORM_CS' : QPMS_NORMALISATION_NORM_SPHARM | QPMS_NORMALISATION_CSPHASE
,
21 'UNDEF' : QPMS_NORMALISATION_UNDEF
,
22 'DEFAULT' : QPMS_NORMALISATION_DEFAULT
,
26 VSWFNorm
= enum
.IntFlag
('VSWFNorm', names
=__VSWF_norm_dict
, module
=__name__
)
27 except AttributeError: # For older Python versions, use IntEnum instead
28 VSWFNorm
= enum
.IntEnum
('VSWFNorm', names
=__VSWF_norm_dict
, module
=__name__
)
32 '''Cython wrapper over qpms_vswf_set_spec_t.
34 It should be kept immutable. The memory is managed by numpy/cython, not directly by the C functions, therefore
35 whenever used in other wrapper classes that need the pointer
36 to qpms_vswf_set_spec_t, remember to set a (private, probably immutable) reference to qpms.basespec to ensure
37 correct reference counting and garbage collection.
39 #cdef qpms_vswf_set_spec_t s # in pxd
40 #cdef np.ndarray __ilist # in pxd
41 #cdef const qpms_uvswfi_t[:] __ilist
44 cdef BaseSpec from_cpointer
(const qpms_vswf_set_spec_t
*orig
):
45 '''Makes an instance of BaseSpec from an existing
46 C pointer, copying the contents
48 cdef const qpms_uvswfi_t
[::1] ilist_orig
= <qpms_uvswfi_t
[:orig
[0].n
]> orig
[0].ilist
49 cdef BaseSpec bs
= BaseSpec
(ilist_orig
)
50 bs
.s
.norm
= orig
[0].norm
53 def __cinit__
(self, *args
, **kwargs
):
54 cdef const qpms_uvswfi_t
[:] ilist_memview
56 if 'lMax' in kwargs
.keys
(): # if only lMax is specified, create the 'usual' definition in ('E','M') order
58 my
, ny
= get_mn_y
(lMax
)
60 tlist
= nelem
* (QPMS_VSWF_ELECTRIC
,) + nelem
* (QPMS_VSWF_MAGNETIC
,)
63 ilist
= tlm2uvswfi
(tlist
,llist
,mlist
)
66 else: # len(args) > 0:
68 #self.__ilist = np.array(args[0], dtype=qpms_uvswfi_t, order='C', copy=True) # FIXME define the dtypes at qpms_cdef.pxd level
69 self.__ilist
= np
.array
(ilist
, dtype
=np
.ulonglong
, order
='C', copy
=True
)
70 self.__ilist
.setflags
(write
=False
)
71 ilist_memview
= self.__ilist
72 self.s
.ilist
= &ilist_memview
[0]
73 self.s
.n
= len(self.__ilist
)
74 self.s
.capacity
= 0 # is this the best way?
75 if 'norm' in kwargs
.keys
():
76 self.s
.norm
= kwargs
['norm']
78 self.s
.norm
= <qpms_normalisation_t
>(QPMS_NORMALISATION_DEFAULT
)
79 # set the other metadata
83 cdef qpms_vswf_type_t t
84 for i
in range(self.s
.n
):
85 if(qpms_uvswfi2tmn
(ilist_memview
[i
], &t
, &m
, &l
) != QPMS_SUCCESS
):
86 raise ValueError("Invalid uvswf index")
87 if (t
== QPMS_VSWF_ELECTRIC
):
88 self.s
.lMax_N
= max(self.s
.lMax_N
, l
)
89 elif (t
== QPMS_VSWF_MAGNETIC
):
90 self.s
.lMax_M
= max(self.s
.lMax_M
, l
)
91 elif (t
== QPMS_VSWF_LONGITUDINAL
):
92 self.s
.lMax_L
= max(self.s
.lMax_L
, l
)
94 raise ValueError # If this happens, it's probably a bug, as it should have failed already at qpms_uvswfi2tmn
95 self.s
.lMax
= max(self.s
.lMax
, l
)
97 def __eq__
(self, BaseSpec other
):
98 return bool
(qpms_vswf_set_spec_isidentical
(&self.s
, &other
.s
))
100 def __hash__
(self): # Very inefficient implementation, but this is not to be used very often
101 return hash((self.s
.norm
, self.s
.n
, tuple(self.__ilist
[:self.s
.n
])))
104 cdef const qpms_uvswfi_t
[:] ilist_memview
= <qpms_uvswfi_t
[:self.s
.n
]> self.s
.ilist
105 #cdef qpms_vswf_type_t[:] t = np.empty(shape=(self.s.n,), dtype=qpms_vswf_type_t) # does not work, workaround:
107 cdef np
.ndarray ta
= np
.empty
(shape
=(self.s
.n
,), dtype
=np
.intc
)
109 #cdef qpms_l_t[:] l = np.empty(shape=(self.s.n,), dtype=qpms_l_t) # FIXME explicit dtype again
110 cdef np
.ndarray la
= np
.empty
(shape
=(self.s
.n
,), dtype
=np
.intc
)
111 cdef qpms_l_t
[:] l
= la
112 #cdef qpms_m_t[:] m = np.empty(shape=(self.s.n,), dtype=qpms_m_t) # FIXME explicit dtype again
113 cdef np
.ndarray ma
= np
.empty
(shape
=(self.s
.n
,), dtype
=np
.intc
)
114 cdef qpms_m_t
[:] m
= ma
115 for i
in range(self.s
.n
):
116 qpms_uvswfi2tmn
(self.s
.ilist
[i
], <qpms_vswf_type_t
*>&t
[i
], &m
[i
], &l
[i
])
131 def __getitem__
(self, key
):
132 # TODO raise correct errors (TypeError on bad type of key, IndexError on exceeding index)
133 return self.__ilist
[key
]
139 cdef qpms_vswf_set_spec_t
*rawpointer
(BaseSpec
self):
140 '''Pointer to the qpms_vswf_set_spec_t structure.
141 Don't forget to reference the BaseSpec object itself when storing the pointer anywhere!!!
147 return <uintptr_t
> &(self.s
)
151 return VSWFNorm
(self.s
.norm
)
153 default_bspec
= BaseSpec
(lMax
=2)