def select(self, key=None, val=None, touch=None, log='any', out=int):
        """ Return the indices of the rays matching selection criteria

        The criterion can be of two types:
            - a key found in self.dchans, with a matching value
            - a touch tuple (indicating which element in self.config is touched
                by the desired rays)

        Parameters
        ----------
        key :    None / str
            A key to be found in self.dchans
        val :   int / str / float / list of such
            The value to be matched
            If a list of values is provided, the behaviour depends on log
        log :   str
            A flag indicating which behaviour to use when val is a list
                - any : Returns indices of rays matching any value in val
                - all : Returns indices of rays matching all values in val
                - not : Returns indices of rays matching None of the val
        touch:  None / str / int / tuple
            Used if key is None
            Tuple that can be of len()=1, 2 or 3
            Tuple indicating you want the rays that are touching some specific elements of self.config:
                - touch[0] : str / int or list of such
                    str : a 'Cls_Name' string indicating the element
                    int : the index of the element in self.lStruct_computeInOut
                - touch[1] : int / list of int
                    Indices of the desired segments on the polygon
                    (i.e.: of the cross-section polygon of the above element)
                - touch[2] : int / list of int
                    Indices, if relevant, of the toroidal / linear unit
                    Only relevant when the element has noccur>1
            In this case only log='not' has an effect
        out :   str
            Flag indicating whether to return:
                - bool : a (nRays,) boolean array of indices
                - int :  a (N,) array of int indices (N=number of matching rays)

        Returns
        -------
        ind :   np.ndarray
            The array of matching rays

        """
        assert out in [int,bool]
        assert log in ['any','all','not']
        C = [key is None,touch is None]
        assert np.sum(C)>=1
        if np.sum(C)==2:
            ind = np.ones((self.nRays,),dtype=bool)
        else:
            if key is not None:
                assert type(key) is str and key in self._dchans.keys()
                ltypes = [str,int,float,np.int64,np.float64]
                C0 = type(val) in ltypes
                C1 = type(val) in [list,tuple,np.ndarray]
                assert C0 or C1
                if C0:
                    val = [val]
                else:
                    assert all([type(vv) in ltypes for vv in val])
                ind = np.vstack([self._dchans[key]==ii for ii in val])
                if log=='any':
                    ind = np.any(ind,axis=0)
                elif log=='all':
                    ind = np.all(ind,axis=0)
                else:
                    ind = ~np.any(ind,axis=0)

            elif touch is not None:
                lint = [int,np.int64]
                larr = [list,tuple,np.ndarray]
                touch = [touch] if not type(touch) is list else touch
                assert len(touch) in [1,2,3]

                def _check_touch(tt):
                    cS = type(tt) is str and len(tt.split('_'))==2
                    c0 = type(tt) in lint
                    c1 = type(tt) in larr and len(tt)>=0
                    c1 = c1 and all([type(t) in lint for t in tt])
                    return cS, c0, c1
                for ii in range(0,3-len(touch)):
                    touch.append([])

                ntouch = len(touch)
                assert ntouch == 3

                for ii in range(0,ntouch):
                    cS, c0, c1 = _check_touch(touch[ii])

                    if not (cS or c0 or c1):
                        msg = "Provided touch is not valid:\n"%touch
                        msg += "    - Provided: %s\n"%str(touch)
                        msg += "Please provide either:\n"
                        msg += "    - str in the form 'Cls_Name'\n"
                        msg += "    - int (index)\n"
                        msg += "    - array of int indices"
                        raise Exception(msg)

                    if cS:
                        lS = self.lStruct_computeInOut
                        k0, k1 = touch[ii].split('_')
                        ind = [jj for jj in range(0,len(lS))
                               if lS[jj].Id.Cls==k0 and lS[jj].Id.Name==k1]
                        assert len(ind)==1
                        touch[ii] = [ind[0]]
                    elif c0:
                        touch[ii] = [touch[ii]]

                # Common part
                ind = np.zeros((ntouch,self.nRays),dtype=bool)
                for i in range(0,ntouch):
                    if len(touch[i])==0:
                        ind[i,:] = True
                    else:
                        for n in range(0,len(touch[i])):
                            ind[i,:] = np.logical_or(ind[i,:],
                                                     self._dgeom['indout'][i,:]==touch[i][n])
                ind = np.all(ind,axis=0)
                if log=='not':
                    ind[:] = ~ind
        if out is int:
            ind = ind.nonzero()[0]
        return ind
def select ( self , key = None , val = None , touch = None , log = 'any' , out = int ) : assert out in [ int , bool ] assert log in [ 'any' , 'all' , 'not' ] C = [ key is None , touch is None ] assert np . sum ( C ) >= 1 if np . sum ( C ) == 2 : ind = np . ones ( ( self . nRays , ) , dtype = bool ) else : if key is not None : assert type ( key ) is str and key in self . _dchans . keys ( ) ltypes = [ str , int , float , np . int64 , np . float64 ] C0 = type ( val ) in ltypes C1 = type ( val ) in [ list , tuple , np . ndarray ] assert C0 or C1 if C0 : val = [ val ] else : assert all ( [ type ( vv ) in ltypes for vv in val ] ) ind = np . vstack ( [ self . _dchans [ key ] == ii for ii in val ] ) if log == 'any' : ind = np . any ( ind , axis = 0 ) elif log == 'all' : ind = np . all ( ind , axis = 0 ) else : ind = ~ np . any ( ind , axis = 0 ) elif touch is not None : lint = [ int , np . int64 ] larr = [ list , tuple , np . ndarray ] touch = [ touch ] if not type ( touch ) is list else touch assert len ( touch ) in [ 1 , 2 , 3 ] def _check_touch ( tt ) : cS = type ( tt ) is str and len ( tt . split ( '_' ) ) == 2 c0 = type ( tt ) in lint c1 = type ( tt ) in larr and len ( tt ) >= 0 c1 = c1 and all ( [ type ( t ) in lint for t in tt ] ) return cS , c0 , c1 for ii in range ( 0 , 3 - len ( touch ) ) : touch . append ( [ ] ) ntouch = len ( touch ) assert ntouch == 3 for ii in range ( 0 , ntouch ) : cS , c0 , c1 = _check_touch ( touch [ ii ] ) if not ( cS or c0 or c1 ) : msg = "Provided touch is not valid:\n" % touch msg += "    - Provided: %s\n" % str ( touch ) msg += "Please provide either:\n" msg += "    - str in the form 'Cls_Name'\n" msg += "    - int (index)\n" msg += "    - array of int indices" raise Exception ( msg ) if cS : lS = self . lStruct_computeInOut k0 , k1 = touch [ ii ] . split ( '_' ) ind = [ jj for jj in range ( 0 , len ( lS ) ) if lS [ jj ] . Id . Cls == k0 and lS [ jj ] . Id . Name == k1 ] assert len ( ind ) == 1 touch [ ii ] = [ ind [ 0 ] ] elif c0 : touch [ ii ] = [ touch [ ii ] ] ind = np . zeros ( ( ntouch , self . nRays ) , dtype = bool ) for i in range ( 0 , ntouch ) : if len ( touch [ i ] ) == 0 : ind [ i , : ] = True else : for n in range ( 0 , len ( touch [ i ] ) ) : ind [ i , : ] = np . logical_or ( ind [ i , : ] , self . _dgeom [ 'indout' ] [ i , : ] == touch [ i ] [ n ] ) ind = np . all ( ind , axis = 0 ) if log == 'not' : ind [ : ] = ~ ind if out is int : ind = ind . nonzero ( ) [ 0 ] return ind
Return the indices of the rays matching selection criteria

        The criterion can be of two types:
            - a key found in self.dchans, with a matching value
            - a touch tuple (indicating which element in self.config is touched
                by the desired rays)

        Parameters
        ----------
        key :    None / str
            A key to be found in self.dchans
        val :   int / str / float / list of such
            The value to be matched
            If a list of values is provided, the behaviour depends on log
        log :   str
            A flag indicating which behaviour to use when val is a list
                - any : Returns indices of rays matching any value in val
                - all : Returns indices of rays matching all values in val
                - not : Returns indices of rays matching None of the val
        touch:  None / str / int / tuple
            Used if key is None
            Tuple that can be of len()=1, 2 or 3
            Tuple indicating you want the rays that are touching some specific elements of self.config:
                - touch[0] : str / int or list of such
                    str : a 'Cls_Name' string indicating the element
                    int : the index of the element in self.lStruct_computeInOut
                - touch[1] : int / list of int
                    Indices of the desired segments on the polygon
                    (i.e.: of the cross-section polygon of the above element)
                - touch[2] : int / list of int
                    Indices, if relevant, of the toroidal / linear unit
                    Only relevant when the element has noccur>1
            In this case only log='not' has an effect
        out :   str
            Flag indicating whether to return:
                - bool : a (nRays,) boolean array of indices
                - int :  a (N,) array of int indices (N=number of matching rays)

        Returns
        -------
        ind :   np.ndarray
            The array of matching rays