Ejemplo n.º 1
0
def startvalfunc(Ne_init, loc, locsp, time, inputs, ambinfo=[0]):
    """ This is a method to determine the start values for the fitter.
    Inputs
        Ne_init - A nloc x nt numpy array of the initial estimate of electron density. Basically
        the zeroth lag of the ACF.
        loc - A nloc x 3 numpy array of cartisian coordinates.
        time - A nt x 2 numpy array of times in seconds
        exinputs - A list of extra inputs allowed for by the fitter class. It only
            has one element and its the name of the ionocontainer file holding the
            rest of the start parameters.
    Outputs
        xarray - This is a numpy array of starting values for the fitter parameters."""
    if isinstance(inputs, str):
        if os.path.splitext(inputs)[-1] == '.h5':
            ionoin = IonoContainer.readh5(inputs)
        elif os.path.splitext(inputs)[-1] == '.mat':
            ionoin = IonoContainer.readmat(inputs)
        elif os.path.splitext(inputs)[-1] == '':
            ionoin = makeionocombined(inputs)
    elif isinstance(inputs, list):
        ionoin = makeionocombined(inputs)
    else:
        ionoin = inputs

    numel = sp.prod(ionoin.Param_List.shape[-2:]) + 1

    xarray = sp.zeros((loc.shape[0], len(time), numel))
    for ilocn, iloc in enumerate(loc):
        #for iamb in ambinfo:
        newlocsp = locsp[ilocn]
        #newlocsp[0] += iamb
        (datast, vel) = ionoin.getclosestsphere(newlocsp, time)[:2]
        datast[:, -1, 0] = Ne_init[ilocn, :]
        # get the ion densities
        ionoden = datast[:, :-1, 0]
        # find the right normalization for the ion species
        ionodensum = sp.repeat(sp.sum(ionoden, axis=-1)[:, sp.newaxis],
                               ionoden.shape[-1],
                               axis=-1)
        # renormalized to the right level
        ionoden = sp.repeat(Ne_init[ilocn, :, sp.newaxis],
                            ionoden.shape[-1],
                            axis=-1) * ionoden / ionodensum
        datast[:, :-1, 0] = ionoden
        xarray[ilocn, :, :-1] = sp.reshape(
            datast, (len(time), numel - 1))  #/float(len(ambinfo))
        locmag = sp.sqrt(sp.sum(iloc * iloc))
        ilocmat = sp.repeat(iloc[sp.newaxis, :], len(time), axis=0)
        xarray[ilocn, :,
               -1] = sp.sum(vel * ilocmat) / locmag  #/float(len(ambinfo))
    return xarray
Ejemplo n.º 2
0
    def __init__(self,ionoin,configfile,timein=None,mattype='matrix'):
        """ This will create the RadarSpaceTimeOperator object.
            Inputs
                ionoin - The input ionocontainer. This can be either an string that is a ionocontainer file,
                    a list of ionocontainer objects or a list a strings to ionocontainer files.
                config  - The ini file that used to set up the simulation.
                timein - A Ntx2 numpy array of times.
                RSTOPinv - The inverse operator object.
                invmat - The inverse matrix to the original operator.
        """
        mattype=mattype.lower()
        accepttypes=['matrix','sim','real']
        if not mattype in accepttypes:
            raise ValueError('Matrix type can only be {0}'.format(', '.join(accepttypes)))
        d2r = np.pi/180.0
        (sensdict,simparams) = readconfigfile(configfile)
        # determine if the input ionocontainer is a string, a list of strings or a list of ionocontainers.
        ionoin=makeionocombined(ionoin)
        #Input location
        self.Cart_Coords_In = ionoin.Cart_Coords
        self.Sphere_Coords_In = ionoin.Sphere_Coords

        # Set the input times
        if timein is None:
            self.Time_In = ionoin.Time_Vector
        else:
            self.Time_In = timein

        #Create an array of output location based off of the inputs
        rng_vec2 = simparams['Rangegatesfinal']
        nrgout = len(rng_vec2)

        angles = simparams['angles']
        nang =len(angles)

        ang_data = np.array([[iout[0],iout[1]] for iout in angles])
        rng_all = np.repeat(rng_vec2,(nang),axis=0)
        ang_all = np.tile(ang_data,(nrgout,1))
        self.Sphere_Coords_Out = np.column_stack((rng_all,ang_all))
        (R_vec,Az_vec,El_vec) = (self.Sphere_Coords_Out[:,0],self.Sphere_Coords_Out[:,1],
            self.Sphere_Coords_Out[:,2])
        xvecmult = np.sin(Az_vec*d2r)*np.cos(El_vec*d2r)
        yvecmult = np.cos(Az_vec*d2r)*np.cos(El_vec*d2r)
        zvecmult = np.sin(El_vec*d2r)
        X_vec = R_vec*xvecmult
        Y_vec = R_vec*yvecmult
        Z_vec = R_vec*zvecmult

        self.Cart_Coords_Out = np.column_stack((X_vec,Y_vec,Z_vec))
        self.Time_Out = np.column_stack((simparams['Timevec'],simparams['Timevec']+simparams['Tint']))+self.Time_In[0,0]
        self.simparams=simparams
        self.sensdict=sensdict
        self.lagmat = self.simparams['amb_dict']['WttMatrix']
        self.mattype=mattype
        # create the matrix
        (self.RSTMat,self.overlaps,self.blocklocs) = makematPA(ionoin.Sphere_Coords,ionoin.Cart_Coords,ionoin.Time_Vector,configfile,ionoin.Velocity,mattype)
Ejemplo n.º 3
0
    def mult_iono(self,ionoin_list):
        """
            This will apply the forward model to the contents of an ionocontainer object. It is assuming that
            this is an ionocontainer holding the spectra.
        """

        ntout = self.Time_Out.shape[0]
        nlout = self.Cart_Coords_Out.shape[0]
        blist_in,blist_out = self.blocklocs
        amb_dict = self.simparams['amb_dict']
        ambmat = amb_dict['WttMatrix']
        overlaps = self.overlaps

        t_s = self.sensdict['t_s']

        if isinstance(ionoin_list,list)or isinstance(ionoin_list,str):

            Iono_in = makeionocombined(ionoin_list)
        else:
            Iono_in=ionoin_list


        ionocart = Iono_in.Cart_Coords

        if self.simparams['numpoints']==Iono_in.Param_List.shape[-1]:
            tau,acf=spect2acf(Iono_in.Param_Names,Iono_in.Param_List)
            np = ambmat.shape[0]
        else:
            acf=Iono_in.Param_List
            np = acf.shape[-1]
        np_in =acf.shape[-1]
        tau_out = t_s*np.arange(np)
        outdata = np.zeros((nlout,ntout,np),dtype=acf.dtype)
        assert np.allclose(ionocart,self.Cart_Coords_In), "Spatial Coordinates need to be the same"

        for it_out in range(ntout):

            overlists = overlaps[it_out]
            irows = blist_out[it_out]
            curintimes = [i[0] for i in overlists]
            curintratio=[i[1] for i in overlists]
            if self.mattype.lower()=='sim':
                curintimes=[curintimes[0]]
                curintratio=[1.]

            cur_outmat = self.RSTMat[irows[0]:irows[1],:]
            icols=    blist_in[it_out]
            cur_mat = cur_outmat[:,icols[0]:icols[1]]

            for i_it,it_in in enumerate(curintimes):
                tempdata=np.zeros((np_in,nlout),dtype=acf.dtype)
                for iparam in range(np_in):
                   tempdata[iparam]=cur_mat.dot(acf[:,it_in,iparam])
                if self.simparams['numpoints']==Iono_in.Param_List.shape[-1]:
                    tempdata=np.dot(ambmat,tempdata)

                outdata[:,it_out] = np.transpose(tempdata)*curintratio[i_it] + outdata[:,it_out]

        outiono = IonoContainer(self.Sphere_Coords_Out,outdata,times=self.Time_Out,sensor_loc=Iono_in.Sensor_loc,
                               ver=1,coordvecs = ['r','theta','phi'],paramnames=tau_out)
        return outiono
Ejemplo n.º 4
0
def phantest(inputfile,outdir,configfile,timevec):
    
    
    ne_red=1e-10
    nemin,nemax=[0.*ne_red,3e11*ne_red]
    xlim = [-200.,360.]
    xticks = [-150.,0.,150.,300.]
    defmap = 'viridis'# color map
    fs=18# fontsize
    fscb=12
    figsize = (10,7)
    ylim = [100.,500.]
    
#    iono1=makesimpledata(inputfile,timevec= None,begx=0.,begz=300.,vx=500.)
    iono1=makeionocombined(os.path.split(inputfile)[0])
    iono2=iono1.deepcopy()
    iono2.Param_List[:,1:]=0.
#    sum1=sp.sum(iono1.Param_List,axis=1)
#    iono1.Param_List[:,:,:]=0.
#    iono1.Param_List[:,0]=sum1
    RSTO1 = RadarSpaceTimeOperator(iono1,configfile,timevec,mattype='matrix')
    RSTO2 = RadarSpaceTimeOperator(iono2,configfile,timevec,mattype='sim')
    iono1new=RSTO1.mult_iono(iono1)
    iono2new=RSTO2.mult_iono(iono2)
    
    rngrdr =iono1new.Sphere_Coords[:,0].astype('float32')
    sign1 = sp.sign(iono1new.Sphere_Coords[:,1])
    el = iono1new.Sphere_Coords[:,2].astype('float32')
    elvec,elinv = sp.unique(el,return_inverse=True)
    nbeams = len(elvec)
    nrg = len(rngrdr)/nbeams
    
    Rngrdrmat = sp.reshape(rngrdr,(nrg,nbeams))
    Signmat = sp.reshape(sign1,(nrg,nbeams))
    Elmat = sp.reshape(el,(nrg,nbeams))

    Xmat = Rngrdrmat*Signmat*sp.cos(Elmat*sp.pi/180.)
    Zmat = Rngrdrmat*sp.sin(Elmat*sp.pi/180.)
    Ne1 = iono1new.Param_List[:,:,0].reshape(nrg,nbeams,1).real*ne_red
    Nemat1 = Ne1[:,:,0]
    Ne2 = iono2new.Param_List[:,:,0].reshape(nrg,nbeams,1).real*ne_red
    Nemat2 = Ne2[:,:,0]    
    fig ,axmat= plt.subplots(nrows=1,ncols=2,facecolor='w',figsize=figsize,sharey=True)

    avec=axmat.flatten()

    plt.sca(avec[0])
    avec[0].set_xlabel('X Plane in km',fontsize=fs)
    avec[0].set_ylabel('Alt in km',fontsize=fs)
    pc1 = avec[0].pcolor(Xmat,Zmat,Nemat1,cmap = defmap,vmin=nemin,vmax=nemax)
    plt.tick_params(labelsize=16)
    plt.xticks(xticks)
    avec[0].set_xlim(xlim)
    avec[0].set_ylim(ylim)
    avec[0].set_title('Operator No motion',fontsize=fs)
    tick_locator = ticker.MaxNLocator(nbins=5)
        
    cb1 = plt.colorbar(pc1, ax=avec[0])
    cb1.ax.xaxis.set_label_position('top')
    cb1.ax.set_xlabel('')
    cb1.locator = tick_locator
    cb1.update_ticks()
    
    plt.sca(avec[1])
    avec[1].set_xlabel('X Plane in km',fontsize=fs)
    avec[1].set_ylabel('Alt in km',fontsize=fs)
    pc1 = avec[1].pcolor(Xmat,Zmat,Nemat2,cmap = defmap,vmin=nemin,vmax=nemax)
    plt.tick_params(labelsize=fs)
    plt.xticks(xticks)
    avec[1].set_xlim(xlim)
    avec[1].set_ylim(ylim)
    avec[1].set_title('Operator for Motion',fontsize=fs)
    tick_locator = ticker.MaxNLocator(nbins=5)
        
    cb2 = plt.colorbar(pc1, ax=avec[1])
    cb2.ax.xaxis.set_label_position('top')
    cb2.ax.set_xlabel('')
    cb2.locator = tick_locator
    cb2.update_ticks()
    plt.tight_layout()
    return fig,avec,Nemat1,Nemat2
Ejemplo n.º 5
0
def parametersweep(basedir,configfile,acfdir='ACF',invtype='tik'):
    """ 
        This function will run the inversion numerious times with different constraint
        parameters. This will create a directory called cost and place.
        Input
        basedir - The directory that holds all of the data for the simulator.
        configfile - The ini file for the simulation.
        acfdir - The directory within basedir that hold the acfs to be inverted.
        invtype - The inversion method that will be tested. Can be tik, tikd, and tv.
    """

    alpha_sweep=sp.logspace(-3.5,sp.log10(7),25)
    costdir = os.path.join(basedir,'Cost')
    ionoinfname=os.path.join(basedir,acfdir,'00lags.h5')
    ionoin=IonoContainer.readh5(ionoinfname)
    
    dirio = ('Spectrums','Mat','ACFMat')
    inputdir = os.path.join(basedir,dirio[0])
    
    dirlist = glob.glob(os.path.join(inputdir,'*.h5'))
    (listorder,timevector,filenumbering,timebeg,time_s) = IonoContainer.gettimes(dirlist)
    Ionolist = [dirlist[ikey] for ikey in listorder]
    
    RSTO = RadarSpaceTimeOperator(Ionolist,configfile,timevector,mattype='Sim')
    
    npts=RSTO.simparams['numpoints']
    
    ionospec=makeionocombined(dirlist)
    if npts==ionospec.Param_List.shape[-1]:
        tau,acfin=spect2acf(ionospec.Param_Names,ionospec.Param_List)
        nloc,ntimes=acfin.shape[:2]
        ambmat=RSTO.simparams['amb_dict']['WttMatrix']
        np=ambmat.shape[0]
        acfin_amb=sp.zeros((nloc,ntimes,np),dtype=acfin.dtype)
    # get the original acf
    
    
        ambmat=RSTO.simparams['amb_dict']['WttMatrix']
        np=ambmat.shape[0]
            
        for iloc,locarr in enumerate(acfin):
            for itime,acfarr in enumerate(locarr):
                acfin_amb[iloc,itime]=sp.dot(ambmat,acfarr)
        acfin_amb=acfin_amb[:,0]
    else:
        acfin_amb=ionospec.Param_List[:,0]
        
    if not os.path.isdir(costdir):
        os.mkdir(costdir)
    # pickle file stuff 
    pname=os.path.join(costdir,'cost{0}-{1}.pickle'.format(acfdir,invtype))

    alpha_list=[]
    errorlist=[]
    errorlaglist=[]
    datadiflist=[]
    constlist=[]
    if 'perryplane' in basedir.lower() or 'SimpData':
        rbounds=[-500,500]
    else:
        rbounds=[0,500]

    alpha_list_new=alpha_sweep.tolist()
    for i in alpha_list:
        if i in alpha_list_new:
            alpha_list_new.remove(i)
    
    for i in alpha_list_new:
        ionoout,datadif,constdif=invertRSTO(RSTO,ionoin,alpha_list=i,invtype=invtype,rbounds=rbounds,Nlin=1)
        
        datadiflist.append(datadif)
        constlist.append(constdif)
        acfout=ionoout.Param_List[:,0]
        alpha_list.append(i)
        outdata=sp.power(sp.absolute(acfout-acfin_amb),2)
        aveerror=sp.sqrt(sp.nanmean(outdata,axis=0))
        errorlaglist.append(aveerror)
        errorlist.append(sp.nansum(aveerror))
        
    pickleFile = open(pname, 'wb')
    pickle.dump([alpha_list,errorlist,datadiflist,constlist,errorlaglist],pickleFile)
    pickleFile.close()
    mkalphalist(pname)
    alphaarr=sp.array(alpha_list)
    errorarr=sp.array(errorlist)
    errorlagarr=sp.array(errorlaglist)
    datadif=sp.array(datadiflist)
    constdif=sp.array(constlist)
    fig,axlist,axmain=plotalphaerror(alphaarr,errorarr,errorlagarr)
    fig.savefig(os.path.join(costdir,'cost{0}-{1}.png'.format(acfdir,invtype)))
    
    fig,axlist=plotLcurve(alphaarr,datadif,constdif)
    fig.savefig(os.path.join(costdir,'lcurve{0}-{1}.png'.format(acfdir,invtype)))
Ejemplo n.º 6
0
def plotgradlines(inputlist,fitiono,alt,times,paramlist=['Ne','Te','Ti']):
    """
    Plots the values along a specific alittude. 
    """
    inputiono = makeionocombined(inputlist)
    Iono1 = GeoData(readIono,[inputiono])
    fitiono = IonoContainer.readh5(fitiono)
    fitGeo = GeoData(readIono,[fitiono])
    
    paramlist = ['Ne','Te','Ti']
    (x,y,z) = inputiono.Cart_Coords.transpose()
    r = sp.sqrt(x**2+y**2)*sp.sign(y)
    incoords = sp.column_stack((r,z,sp.ones_like(z)))
    ru,zu =[ sp.unique(r),sp.unique(z)]
    Rmat,Zmat = sp.meshgrid(ru,zu)
    zinput = sp.argmin(sp.absolute(zu-alt))
    
    (xf,yf,zf) = fitiono.Cart_Coords.transpose()
    rf = sp.sqrt(xf**2+yf**2)*sp.sign(yf)
    outcoords = sp.column_stack((rf,zf,sp.ones_like(zf)))
    rfu,zfu =[ sp.unique(rf),sp.unique(zf)]
    Rfmat,Zfmat = sp.meshgrid(rfu,zfu)
    zoutput = sp.argmin(sp.absolute(zfu-alt))
    
    fitGeo.interpolate(incoords,Iono1.coordnames,method='linear',fill_value=sp.nan,twodinterp = True,oldcoords=outcoords)

    uz = sp.unique(z)
    ur = sp.unique(r)
    (rmat,zmat) = sp.meshgrid(ur,uz)
    
    inputdata = {}
    for iparm in paramlist:
        if iparm =='Nepow':
            iparm='Ne'
        curdata = Iono1.data[iparm][:,times[0]]
        
        inputdata[iparm] = sp.reshape(curdata,Rmat.shape)[zinput]

    outputdata = {}
    for iparm in paramlist:
        curdata = fitGeo.data[iparm][:, times[1]]
        outputdata[iparm] = sp.reshape(curdata,Rmat.shape)[zinput]
    
    fig, axvec = plt.subplots(len(paramlist),1,sharey=False,figsize=(12,5*len(paramlist)))
    
    for ipn,iparam in enumerate(paramlist):
        ax = axvec[ipn]
        ax2 = ax.twinx()
        p1, = ax.plot(ru,inputdata[iparam],'b-',label='In',linewidth=3)
        p2, = ax.plot(ru,outputdata[iparam],'b--',label='Out',linewidth=3)
        ax.set_title(iparam)
        ax.set_xlabel('X Plane in km')
        gi = sp.gradient(inputdata[iparam])/sp.gradient(ru)
        go = sp.gradient(outputdata[iparam])/sp.gradient(ru)
        p3, = ax2.plot(ru,gi,'g-',label='Grad In',linewidth=3)
        p4, = ax2.plot(ru,go,'g--',label='Grad Out',linewidth=3)
        ax.yaxis.label.set_color(p1.get_color())
        ax2.yaxis.label.set_color(p3.get_color())
        lines = [p1,p2,p3,p4]
        ax.legend(lines,[l.get_label() for l in lines])
    
    plt.tight_layout()    
    return(fig)
Ejemplo n.º 7
0
    def mult_iono(self, ionoin_list):
        """
            This will apply the forward model to the contents of an ionocontainer object. It is assuming that
            this is an ionocontainer holding the spectra.
        """

        ntout = self.Time_Out.shape[0]
        nlout = self.Cart_Coords_Out.shape[0]
        blist_in, blist_out = self.blocklocs
        amb_dict = self.simparams['amb_dict']
        ambmat = amb_dict['WttMatrix']
        overlaps = self.overlaps

        t_s = self.sensdict['t_s']

        if isinstance(ionoin_list, list) or isinstance(ionoin_list, str):

            Iono_in = makeionocombined(ionoin_list)
        else:
            Iono_in = ionoin_list

        ionocart = Iono_in.Cart_Coords

        if self.simparams['numpoints'] == Iono_in.Param_List.shape[-1]:
            tau, acf = spect2acf(Iono_in.Param_Names, Iono_in.Param_List)
            np = ambmat.shape[0]
        else:
            acf = Iono_in.Param_List
            np = acf.shape[-1]
        np_in = acf.shape[-1]
        tau_out = t_s * np.arange(np)
        outdata = np.zeros((nlout, ntout, np), dtype=acf.dtype)
        assert np.allclose(
            ionocart,
            self.Cart_Coords_In), "Spatial Coordinates need to be the same"

        for it_out in range(ntout):

            overlists = overlaps[it_out]
            irows = blist_out[it_out]
            curintimes = [i[0] for i in overlists]
            curintratio = [i[1] for i in overlists]
            if self.mattype.lower() == 'sim':
                curintimes = [curintimes[0]]
                curintratio = [1.]

            cur_outmat = self.RSTMat[irows[0]:irows[1], :]
            icols = blist_in[it_out]
            cur_mat = cur_outmat[:, icols[0]:icols[1]]

            for i_it, it_in in enumerate(curintimes):
                tempdata = np.zeros((np_in, nlout), dtype=acf.dtype)
                for iparam in range(np_in):
                    tempdata[iparam] = cur_mat.dot(acf[:, it_in, iparam])
                if self.simparams['numpoints'] == Iono_in.Param_List.shape[-1]:
                    tempdata = np.dot(ambmat, tempdata)

                outdata[:, it_out] = np.transpose(
                    tempdata) * curintratio[i_it] + outdata[:, it_out]

        outiono = IonoContainer(self.Sphere_Coords_Out,
                                outdata,
                                times=self.Time_Out,
                                sensor_loc=Iono_in.Sensor_loc,
                                ver=1,
                                coordvecs=['r', 'theta', 'phi'],
                                paramnames=tau_out)
        return outiono
Ejemplo n.º 8
0
    def __init__(self, ionoin, configfile, timein=None, mattype='matrix'):
        """ This will create the RadarSpaceTimeOperator object.
            Inputs
                ionoin - The input ionocontainer. This can be either an string that is a ionocontainer file,
                    a list of ionocontainer objects or a list a strings to ionocontainer files.
                config  - The ini file that used to set up the simulation.
                timein - A Ntx2 numpy array of times.
                RSTOPinv - The inverse operator object.
                invmat - The inverse matrix to the original operator.
        """
        mattype = mattype.lower()
        accepttypes = ['matrix', 'sim', 'real']
        if not mattype in accepttypes:
            raise ValueError('Matrix type can only be {0}'.format(
                ', '.join(accepttypes)))
        d2r = np.pi / 180.0
        (sensdict, simparams) = readconfigfile(configfile)
        # determine if the input ionocontainer is a string, a list of strings or a list of ionocontainers.
        ionoin = makeionocombined(ionoin)
        #Input location
        self.Cart_Coords_In = ionoin.Cart_Coords
        self.Sphere_Coords_In = ionoin.Sphere_Coords

        # Set the input times
        if timein is None:
            self.Time_In = ionoin.Time_Vector
        else:
            self.Time_In = timein

        #Create an array of output location based off of the inputs
        rng_vec2 = simparams['Rangegatesfinal']
        nrgout = len(rng_vec2)

        angles = simparams['angles']
        nang = len(angles)

        ang_data = np.array([[iout[0], iout[1]] for iout in angles])
        rng_all = np.repeat(rng_vec2, (nang), axis=0)
        ang_all = np.tile(ang_data, (nrgout, 1))
        self.Sphere_Coords_Out = np.column_stack((rng_all, ang_all))
        (R_vec, Az_vec,
         El_vec) = (self.Sphere_Coords_Out[:, 0], self.Sphere_Coords_Out[:, 1],
                    self.Sphere_Coords_Out[:, 2])
        xvecmult = np.sin(Az_vec * d2r) * np.cos(El_vec * d2r)
        yvecmult = np.cos(Az_vec * d2r) * np.cos(El_vec * d2r)
        zvecmult = np.sin(El_vec * d2r)
        X_vec = R_vec * xvecmult
        Y_vec = R_vec * yvecmult
        Z_vec = R_vec * zvecmult

        self.Cart_Coords_Out = np.column_stack((X_vec, Y_vec, Z_vec))
        self.Time_Out = np.column_stack(
            (simparams['Timevec'],
             simparams['Timevec'] + simparams['Tint'])) + self.Time_In[0, 0]
        self.simparams = simparams
        self.sensdict = sensdict
        self.lagmat = self.simparams['amb_dict']['WttMatrix']
        self.mattype = mattype
        # create the matrix
        (self.RSTMat, self.overlaps,
         self.blocklocs) = makematPA(ionoin.Sphere_Coords, ionoin.Cart_Coords,
                                     ionoin.Time_Vector, configfile,
                                     ionoin.Velocity, mattype)