Пример #1
0
void mexFunction(
	int nlhs,	mxArray *plhs[],
	int nrhs, const mxArray *prhs[])
{
	double *pitch, *outPitch, *temp;
	int pitchLen, outPitchLen;
	char message[200];

	/* Check for proper number of arguments */
	if (nrhs!=1) {
		strcpy(message, mexFunctionName());
		strcat(message, " requires 1 input arguments.\n");
		strcat(message, "Usage: ");
		strcat(message, mexFunctionName());
		strcat(message, " pitch");
		mexErrMsgTxt(message);
	}

	/* Assign pointers to the various parameters */
	pitch = mxGetPr(PITCH);
	pitchLen = mxGetM(PITCH)*mxGetN(PITCH);

	temp = cutZero(pitch, pitchLen, &outPitchLen);

	/* Create a matrix for the return argument */
	OUTPITCH = mxCreateDoubleMatrix(1, outPitchLen, mxREAL);
	outPitch = mxGetPr(OUTPITCH);
	memcpy(outPitch, temp, outPitchLen*sizeof(double)); 
	free(temp);
}
Пример #2
0
void mexFunction(
	int nlhs,	mxArray *plhs[],
	int nrhs, const mxArray *prhs[])
{
	double *frameMat, *magSpec;
	int i, frameSize, frameNum, useHammingWin;
	cAudio myAudio;

	/* Check for proper number of arguments */
	if (nrhs<2){
		char message[200];
		strcpy(message, mexFunctionName());
		strcat(message, " requires 2 input arguments.\n");
		strcat(message, "Usage: magSpec = ");
		strcat(message, mexFunctionName());
		strcat(message, "(frameMat, useHammingWin)\n");
		strcat(message, "\tThe length of a frame must be equal to 2^n.\n");
		mexErrMsgTxt(message);
	}
	
	/* Assign pointers to the various parameters */
	frameMat = mxGetPr(FRAMEMAT);
	useHammingWin = (int)mxGetScalar(USEHAMMINGWIN);
	frameSize = mxGetM(FRAMEMAT);
	frameNum = mxGetN(FRAMEMAT);

	/* Create a matrix for the return argument */
	MAGSPEC = mxCreateDoubleMatrix(frameSize, frameNum, mxREAL);
	magSpec = mxGetPr(MAGSPEC);
	/* Do the actual computation */
	myAudio.absFft4frameMat(frameMat, frameSize, frameNum, useHammingWin, magSpec);
}
Пример #3
0
void mexFunction(
	int nlhs,	mxArray *plhs[],
	int nrhs, const mxArray *prhs[])
{
	double	*wave, *out;
	int waveLen;
	
	/* Check for proper number of arguments */
	if (nrhs!=1) {
		char message[200];
		strcpy(message, mexFunctionName());
		strcat(message, " requires 1 input arguments.\n");
		strcat(message, "Usage: output = ");
		strcat(message, mexFunctionName());
		strcat(message, "(wave)");
		mexErrMsgTxt(message);
	}

	/* Dimensions of the input matrix */
	waveLen = mxGetM(WAVE)*mxGetN(WAVE);

	/* Create a matrix for the return argument */
	OUT = mxCreateDoubleMatrix(1, 1, mxREAL);

	/* Assign pointers to the various parameters */
	wave = mxGetPr(WAVE);
	out = mxGetPr(OUT);
	out[0]=vecZcr(wave, waveLen);
}
Пример #4
0
void handle_error() {
    int err;
    char identifier[255]; /* I think it's large enough */
    const char* message;
    const char* caller;
    const error_desc_t* errDesc;

    err = errno;
    /* Windows users can have problems with errno, see http://api.zeromq.org/master:zmq-errno */
    if (err == 0)
        err = zmq_errno();
    //mexPrintf("ZMQ Error number: %d\n",err);
    
    if (err) {
        message = (const char*) zmq_strerror(err);
        caller  = mexFunctionName();
        errDesc = find_error_by_id(err);

        if (message == NULL)
            message = "Error: Something has gone very, very wrong. Unknown error.";

        if (caller == NULL) {
            sprintf(identifier, "zmq:%s", errDesc->name);
        } else {
            sprintf(identifier, "zmq:core:%s:%s", caller, errDesc->name);
        }

        mexErrMsgIdAndTxt(identifier, message);
    }
}
Пример #5
0
void mexFunction(
	int nlhs,	mxArray *plhs[],
	int nrhs, const mxArray *prhs[])
{
	/* Check for proper number of arguments */
	if (nrhs!=2){
		char message[200];
		sprintf(message, "Format error!\nUsage: y = %s(x, prm)\n", mexFunctionName());
		mexErrMsgTxt(message);
	}

	int xLen=mxGetM(X)*mxGetN(X);
	double *x=mxGetPr(X);

	UNICOMB_PRM prm;
	mxArray *fieldValue;
	fieldValue=mxGetField(PRM, 0, "delay");	prm.delay=(int)*mxGetPr(fieldValue);
	fieldValue=mxGetField(PRM, 0, "bl");	prm.bl=*mxGetPr(fieldValue);
	fieldValue=mxGetField(PRM, 0, "fb");	prm.fb=*mxGetPr(fieldValue);
	fieldValue=mxGetField(PRM, 0, "ff");	prm.ff=*mxGetPr(fieldValue);

//	mexPrintf("prm.delay=%d\n", prm.delay);
//	mexPrintf("prm.bl=%f\n", prm.bl);
//	mexPrintf("prm.fb=%f\n", prm.fb);
//	mexPrintf("prm.ff=%f\n", prm.ff);

	// Output matrix for pfMat
	Y = mxCreateDoubleMatrix(mxGetM(X), mxGetN(X), mxREAL);
	double *y=mxGetPr(Y);
	
	uniComb(x, xLen, y, prm);
}
Пример #6
0
//Gateway routine
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
	TaskHandle task;
	int32 numSampsPerChan;
	float64 timeout;

	uInt32 numChannels;
	int32 totalNumSamples;
	uInt32 arraySizeInSamples;
	uInt32 arraySizeInBytes;	
	int32 sampsRead;
	int32 numBytesPerSamp;
	int16 *dataBuffer;
	int32 status;
	int32 errorStringSize;
	char *errorString;

	double *sampsReadOutput;

	//Parse input arguments
	task = (TaskHandle)mxGetScalar(prhs[0]);
	numSampsPerChan = (int32)mxGetScalar(prhs[1]);
	timeout = (float64)mxGetScalar(prhs[2]);
	arraySizeInSamples = (uInt32)mxGetScalar(prhs[3]);
	
	//Determine # of channels and amt. of memory to allocate
	DAQmxGetTaskNumChans(task, &numChannels);
	totalNumSamples = arraySizeInSamples * numChannels;
	arraySizeInBytes = totalNumSamples * sizeof(int16);

	//Create memory for output arguments
	plhs[0] = mxCreateNumericMatrix(totalNumSamples, 1, mxINT16_CLASS, mxREAL); 
	plhs[1] = mxCreateDoubleScalar(0);
	dataBuffer = (int16*)mxGetPr(plhs[0]);
	sampsReadOutput = mxGetPr(plhs[1]);
	
	//Call DAQmx function
	status = (int32) DAQmxReadRaw(task, numSampsPerChan, timeout, dataBuffer, arraySizeInBytes, &sampsRead, &numBytesPerSamp, NULL);

	//Return output buffer
	if (!status)
	{
		mexPrintf("Successfully read %d samples of data\n", sampsRead);		
		*sampsReadOutput = (double)sampsRead;
	}
	else
	{
		//Display error string
		errorStringSize = DAQmxGetErrorString(status,NULL,0); //Gets size of buffer
		errorString = (char *)mxCalloc(errorStringSize,sizeof(char));
		DAQmxGetErrorString(status,errorString,errorStringSize);
		mexPrintf("ERROR in %s: %s\n", mexFunctionName(), errorString);
		mxFree(errorString);

		//Return an empty array insead
		mxDestroyArray(plhs[0]); //I think this is kosher
		plhs[0] = mxCreateNumericMatrix(0, 0, mxINT16_CLASS, mxREAL);
	}

}
Пример #7
0
void mexFunction(
	int nlhs,	mxArray *plhs[],
	int nrhs, const mxArray *prhs[])
{
	double *inputWave, *mfcc;
	int i, frameNum, feaDim;
	char message[200], cfgFile[200];
	
	if (nrhs<4){	
		sprintf(message, "Usage: mfcc = %s(y, fs, nbits, cfgFile)", mexFunctionName());
		mexErrMsgTxt(message);
	}
	
	/* Assign pointers to the various parameters */
	inputWave = mxGetPr(INPUTWAVE);
	int waveLen= mxGetM(INPUTWAVE)*mxGetN(INPUTWAVE);
	int fs=(int)mxGetScalar(FS);
	int nbits=(int)mxGetScalar(NBITS);
	
	int status = mxGetString(CFGFILE, cfgFile, 200);
	if(status != 0) 
		mexWarnMsgTxt("Not enough space. String is truncated.");

	if (vecMax(inputWave, waveLen)<=1)
		mexPrintf("Input wave signals are not likely to be integers since all are within the range [-1 1]! Perhaps you should use wavReadInt.m instead?\n");
	
	fstream file;
	file.open(cfgFile, ios::in);
	if (!file){
		file.close();
		sprintf(message, "Cannot open config file %s!", cfgFile);
		mexErrMsgTxt(message);
	}

	int *wave = new int[waveLen];
	for (i=0; i<waveLen; i++)
		wave[i]=inputWave[i];

	CMel myMel;
	myMel.wave2mfcc(wave, fs, nbits, waveLen, cfgFile, &frameNum, &feaDim);
	float *feature=new float[frameNum*feaDim];
	memcpy(feature, myMel.m_feature, frameNum*feaDim*sizeof(float));
	
	delete [] wave;
	
//	mexPrintf("fs=%d\n", fs);
//	mexPrintf("nbits=%d\n", nbits);
//	mexPrintf("waveLen=%d\n", waveLen);
//	mexPrintf("cfgFile=%s\n", cfgFile);
//	mexPrintf("frameNum=%d\n", frameNum);
//	mexPrintf("feaDim=%d\n", feaDim);
	
	// Create output
	MFCC = mxCreateDoubleMatrix(feaDim, frameNum, mxREAL);
	mfcc = mxGetPr(MFCC);
	for (i=0; i<feaDim*frameNum; i++)
		mfcc[i]=feature[i];
}
Пример #8
0
void mexFunction(
	int nlhs,	mxArray *plhs[],
	int nrhs, const mxArray *prhs[])
{
	double *y1, *y2;
	int *intY1, *intY2;
	int fs1, fs2, len1, len2, i;
	cAudio myAudio;

	/* Check for proper number of arguments */
	if (nrhs!=3) {
		char message[200];
		strcpy(message, mexFunctionName());
		strcat(message, " requires 3 input arguments.\n");
		strcat(message, "Usage: y2 = ");
		strcat(message, mexFunctionName());
		strcat(message, "(y1, fs1, fs2)");
		mexErrMsgTxt(message);
	}

	/* Assign pointers to the various parameters */
	
	fs1 = (int)mxGetPr(FS1)[0];
	fs2 = (int)mxGetPr(FS2)[0];
	y1 = mxGetPr(Y1);
	len1 = mxGetM(Y1)*mxGetN(Y1);
	intY1 = (int *)malloc(len1*sizeof(int));
	double2intVec(y1, len1, intY1);
	
	len2 = (len1-1)*fs2/fs1+1;
	intY2 = (int *)malloc(len2*sizeof(int));

	/* Do the actual computation */
	myAudio.waveResample(intY1, len1, fs1, fs2, intY2, len2);

	/* Create a matrix for the return argument */
	Y2 = mxCreateDoubleMatrix(1, len2, mxREAL);
	y2 = mxGetPr(Y2);
	int2doubleVec(intY2, len2, y2);

	free(intY1);
	free(intY2);
}
Пример #9
0
void mexFunction(
	int nlhs,	mxArray *plhs[],
	int nrhs, const mxArray *prhs[])
{
	double *wave, *ep;
	int m, n, i, j, fs, waveLen, index1, index2;
	char message[200];

	/* Check for proper number of arguments */
	if (nrhs!=2) {
		strcpy(message, mexFunctionName());
		strcat(message, " requires 2 input arguments.\n");
		strcat(message, "Usage: ep = ");
		strcat(message, mexFunctionName());
		strcat(message, "(wave, fs)");
		mexErrMsgTxt(message);
	}

	/* Dimensions of the input matrix */
	waveLen = mxGetM(WAVE)*mxGetN(WAVE);

	/* Create a matrix for the return argument */
	EP = mxCreateDoubleMatrix(1, 2, mxREAL);

	/* Assign pointers to the various parameters */
	wave = mxGetPr(WAVE);
	fs = (int) mxGetScalar(FS);
	ep = mxGetPr(EP);
	
	if (vecMax(wave, waveLen)<=1)
		mexErrMsgTxt("Input wave signals are not likely to be integers since all are within the range [-1 1]! Perhaps you should use wavReadInt.m instead?");

	int *waveInt = (int *)malloc(waveLen*sizeof(int));
	double2intVec(wave, waveLen, waveInt);
	epdByVolHod(waveInt, waveLen, fs, &index1, &index2);
	free(waveInt);
	
	ep[0]=index1+1;	// MATLAB index
	ep[1]=index2+1;	// MATLAB index
}
Пример #10
0
/* ---------------------------------------------------------------------- */
void
mexFunction(int nlhs,       mxArray *plhs[],
            int nrhs, const mxArray *prhs[])
/* ---------------------------------------------------------------------- */
{
    double                tolerance;
    char                  errmsg[1023 + 1];
    struct grdecl         grdecl;
    struct processed_grid g;

    if (args_ok(nlhs, nrhs, prhs)) {
        mx_init_grdecl(&grdecl, prhs[0]);
        tolerance = define_tolerance(nrhs, prhs);

        process_grdecl(&grdecl, tolerance, &g);

        plhs[0] = allocate_grid(&g, mexFunctionName());

        if (plhs[0] != NULL) {
            fill_grid(plhs[0], &g);
        } else {
            /* Failed to create grid structure.  Return empty. */
            plhs[0] = mxCreateDoubleMatrix(0, 0, mxREAL);
        }

        free_processed_grid(&g);
    } else {
        sprintf(errmsg,
                "Calling sequence is\n\t"
                "G = %s(grdecl)\t%%or\n\t"
                "G = %s(grdecl, tolerance)\n"
                "The 'grdecl' must be a valid structure with fields\n"
                "\t'cartDims', 'COORD', 'ZCORN'",
                mexFunctionName(), mexFunctionName());
        mexErrMsgTxt(errmsg);
    }
}
Пример #11
0
void doCudaUnmap(int i)
{
  /* Unmap if it is actually mapped */
  if (resourceCache[i].resource && resourceCache[i].ismapped) {
    /* Mark as unmapped */
    resourceCache[i].ismapped = 0;
    
	  cudastatus = cudaGraphicsUnmapResources(1, &(resourceCache[i].resource), 0);
	  if (cudastatus != cudaSuccess) {
	    mexPrintf("\nmemcpyCudaOpenGL: ERROR in cudaGraphicsUnmapResources(): %s\n", cudaGetErrorString(cudastatus));
	  }
	  
    if (verbose) mexPrintf("\n%s: doCudaUnmap(%i).\n", mexFunctionName(), i);	  
  }
}
Пример #12
0
void doCudaUnregister(int i)
{
  /* Unmap if it is mappped: */
  doCudaUnmap(i);
  
  /* Unregister if it is registered: */
  if (resourceCache[i].resource) {
    cudastatus = cudaGraphicsUnregisterResource(resourceCache[i].resource);
    if (cudastatus != cudaSuccess) {
      mexPrintf("\nmemcpyCudaOpenGL: ERROR in cudaGraphicsUnregisterResource(): %s\n", cudaGetErrorString(cudastatus));
    }
    
    if (verbose) mexPrintf("\n%s: doCudaUnregister(%i).\n", mexFunctionName(), i);    
  }
  
  /* Clear out and thereby free the cache slot: */
  memset(&(resourceCache[i]), 0, sizeof(resourceCache[i]));
}
Пример #13
0
/* Flush the resourceCache - Unmap and unregister all cached resources: */
void cacheFlush(void)
{
  int i;

  if (verbose) mexPrintf("\n%s: cacheFlush.\n", mexFunctionName());

  /* Iterate over all cache slots and unmap/unregister their resources: */
  for (i = 1; i < cachesize; i++) {
    /* In use? */
    if (resourceCache[i].glhandle) {
      doCudaUnregister(i);
    }
  }

  /* Nothing valid in cache anymore. Clear and reset it. */
  cacheclock = 0;
  memset(resourceCache, 0, sizeof(resourceCache[0]) * MAX_CACHE_SLOTS);

  /* Cache is in a pristine "as good as new" condition. */
  return;
}
Пример #14
0
void mexFunction(
	int nlhs,	mxArray *plhs[],
	int nrhs, const mxArray *prhs[])
{
	double *frame, ashod;
	int frameSize, diffOrder;
	if (nrhs<2){
		char message[200];
		sprintf(message, "Usage: ashod = %s(vec, diffOrder)", mexFunctionName());
		mexErrMsgTxt(message);
	}
	
	/* Assign pointers to the various parameters */
	frame=mxGetPr(FRAME);
	frameSize=mxGetM(FRAME)*mxGetN(FRAME);
	diffOrder=mxGetScalar(DIFFORDER);
	ashod=frame2ashod(frame, frameSize, diffOrder);

	/* Create a matrix for the return argument */
	ASHOD = mxCreateDoubleMatrix(1, 1, mxREAL);
	mxGetPr(ASHOD)[0]=ashod;
}
Пример #15
0
void mexFunction(
	int nlhs,	mxArray *plhs[],
	int nrhs, const mxArray *prhs[])
{
	double	*pitch, *wave, pitchRate;
	int fs, pitchLen, waveLen;
	cAudio myAudio;

	/* Check for proper number of arguments */
	if (nrhs!=3){
		char message[200];
		strcpy(message, mexFunctionName());
		strcat(message, " requires 3 input arguments: pitch, pitchRate, fs.");
		mexErrMsgTxt(message);
	}

	/* Dimensions of the input matrix */
	pitchLen = mxGetM(PITCH)*mxGetN(PITCH);
	
	/* Assign pointers to the various parameters */
	pitch = mxGetPr(PITCH);
	pitchRate = mxGetScalar(PITCHRATE);
	fs = (int)mxGetScalar(FS);
	
	/* If some of the elements are nan/inf, change them to 0 */
	double *pitch2=(double *)malloc(pitchLen*sizeof(double));
	memcpy(pitch2, pitch, pitchLen*sizeof(double));
	for (int i=0; i<pitchLen; i++)
		if (mxIsNaN(pitch[i])||mxIsInf(pitch[i]))
			pitch2[i]=0.0;
	
	/* Create a matrix for the return argument */
	waveLen=(int)floor(fs*pitchLen/pitchRate+0.5);
	WAVE = mxCreateDoubleMatrix(waveLen, 1, mxREAL);
	wave = mxGetPr(WAVE);

	myAudio.pitch2wave(pitch2, pitchLen, pitchRate, fs, wave, waveLen);
	free(pitch2);
}
Пример #16
0
/***********************************************************************//**
 * \brief mexFunction to append a stack to an existing em-file.
 **************************************************************************/
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray*prhs[]) {


    size_t filename_length = 0;
#define __MAX_FILENAME_LENGTH__ ((int)2048)
    char filename[__MAX_FILENAME_LENGTH__+1];
#define __MAX_S__LENGTH__ (__MAX_FILENAME_LENGTH__+1024)
    char s[__MAX_S__LENGTH__+1];

    tom_io_em_header header;
#define __BUFFERLENGTH_SYNOPSIS__ 1024
    char synopsis[__BUFFERLENGTH_SYNOPSIS__];
    void *data;

    mxArray *mxData;
    size_t sizex, sizey, sizez;
    mxClassID mxType;
    mxComplexity mxIsComplexVolume;

    size_t i;
    int res;
    int header_read;
    int allow_conversion = 1;

    mxArray *plhs_tmp[5] = { NULL, NULL, NULL, NULL, NULL };





    snprintf(synopsis, __BUFFERLENGTH_SYNOPSIS__, "[size, magic, comment, emdata, userdata] = %s(filename, volume, [allow_conversion])", mexFunctionName());

    if (nrhs==0 && nlhs==0) {
        /* Print help */
        mexPrintf("SYNOPSIS: %s\n", synopsis);
        mexPrintf("mex-file compiled from file \"" __FILE__ "\" at " __DATE__ ", " __TIME__ ".\n");
        return;
    }

    if (nrhs < 2 || nrhs > 3) {
        snprintf(s, __MAX_S__LENGTH__, "%s: call function with up to 3 parameters: %s.", mexFunctionName(), synopsis);
        mexErrMsgTxt(s);
    }
    if (nlhs>5) {
        snprintf(s, __MAX_S__LENGTH__, "%s: Too many output parameters: %s.", mexFunctionName(), synopsis);
        mexErrMsgTxt(s);
    }


    {
        const mxArray *PRHS_FILENAME = prhs[0];
        const mxArray *PRHS_VOLUME = prhs[1];
        const mwSize *size;


        /* Check input parameters! */
        if (!mxIsChar(PRHS_FILENAME) || mxGetNumberOfDimensions(PRHS_FILENAME)!=2 || mxGetM(PRHS_FILENAME)!=1 || (filename_length=mxGetN(PRHS_FILENAME))<1) {
            snprintf(s, __MAX_S__LENGTH__, "%s: needs the file name as first parameter: %s.", mexFunctionName(), synopsis);
            mexErrMsgTxt(s);
        }
        if (filename_length >= __MAX_FILENAME_LENGTH__) {
            snprintf(s, __MAX_S__LENGTH__, "%s: Maximal length of file name exceeded. (Recompile with larger buffer :)", mexFunctionName());
            mexErrMsgTxt(s);
        }
        mxGetString(PRHS_FILENAME, filename, __MAX_FILENAME_LENGTH__);

        if (!mxIsNumeric(PRHS_VOLUME) || mxGetNumberOfDimensions(PRHS_VOLUME)>3) {
            snprintf(s, __MAX_S__LENGTH__, "%s: needs a numerical volume as second parameter: %s", mexFunctionName(), synopsis);
            mexErrMsgTxt(s);
        }
        data = mxGetData(PRHS_VOLUME);
        size = mxGetDimensions(PRHS_VOLUME);
        mxType = mxGetClassID(PRHS_VOLUME);
        mxIsComplexVolume = mxIsComplex(PRHS_VOLUME);
        sizex = size[0];
        sizey = size[1];
        sizez = mxGetNumberOfDimensions(PRHS_VOLUME)==3 ? size[2] : 1;

        if (mxIsComplexVolume) {
            if (mxType==mxSINGLE_CLASS || mxType==mxDOUBLE_CLASS) {
                mwSize size[3];
                size_t x, y, z;

                size[0] = sizex*2;
                size[1] = sizey;
                size[2] = sizez;
                if (!(mxData = mxCreateNumericArray(sizez==1 ? 2 : 3, size, mxType, mxREAL))) {
                    mexErrMsgTxt("%s: Error allocating temporary buffer for complex data.");
                }
                data = mxGetData(mxData);
                if (mxType == mxSINGLE_CLASS) {
                    float *data_as_real = (float *)data;
                    const float *data_real = (const float *)mxGetData(PRHS_VOLUME);
                    const float *data_complex = (const float *)mxGetImagData(PRHS_VOLUME);
                    for (z=0; z<sizez; z++) {
                        for (y=0; y<sizey; y++) {
                            for (x=0; x<sizex; x++) {
                                *data_as_real++ = *data_real++;
                                *data_as_real++ = *data_complex++;
                            }
                        }
                    }
                } else {
                    double *data_as_real = (double *)data;
                    const double *data_real = (const double *)mxGetData(PRHS_VOLUME);
                    const double *data_complex = (const double *)mxGetImagData(PRHS_VOLUME);
                    for (z=0; z<sizez; z++) {
                        for (y=0; y<sizey; y++) {
                            for (x=0; x<sizex; x++) {
                                *data_as_real++ = *data_real++;
                                *data_as_real++ = *data_complex++;
                            }
                        }
                    }
                }
            } else {
                snprintf(s, __MAX_S__LENGTH__, "%s: Complex data for this type not supported (currently only for single and double).", mexFunctionName());
                mexErrMsgTxt(s);
            }
        }

        if (nrhs >= 3) {
            mwSize numel;
            numel = mxGetM(prhs[2]) * mxGetN(prhs[2]);
            if (!(mxIsNumeric(prhs[2]) || mxIsLogical(prhs[2])) || numel>1) {
                snprintf(s, __MAX_S__LENGTH__, "%s: allow_conversion must be one of true, false or [].", mexFunctionName(), synopsis);
                mexErrMsgTxt(s);
            }
            if (numel == 1) {
                allow_conversion = mxGetScalar(prhs[2]) != 0.;
            }
        }
    }


    {
        /* Allocate the memory for the ouput, so that in case of successfully writing, no
           error can happen afterwards in the mexfunction. */
        switch (nlhs) {
        case 5:
            if (!(plhs_tmp[4] = mxCreateNumericMatrix(1, 256, mxINT8_CLASS, mxREAL))) {
                mexErrMsgTxt("Error allocating memory");
            }
        case 4:
            if (!(plhs_tmp[3] = mxCreateNumericMatrix(1, 40, mxINT32_CLASS, mxREAL))) {
                mexErrMsgTxt("Error allocating memory");
            }
        case 3:
            if (!(plhs_tmp[2] = mxCreateNumericMatrix(1, 80, mxINT8_CLASS, mxREAL))) {
                mexErrMsgTxt("Error allocating memory");
            }
        case 2:
            if (!(plhs_tmp[1] = mxCreateNumericMatrix(1, 4, mxINT8_CLASS, mxREAL))) {
                mexErrMsgTxt("Error allocating memory");
            }
        case 1:
            if (!(plhs_tmp[0] = mxCreateNumericMatrix(3, 1, mxUINT32_CLASS, mxREAL))) {
                mexErrMsgTxt("Error allocating memory");
            }
        }
    }


    res = tom_io_em_write_append_stack(filename, data, getIOTypeFromMxClassID(mxType, mxIsComplexVolume), sizex, sizey, sizez, 0, 0, 0, &header, &header_read, allow_conversion);

    if (res != TOM_ERR_OK) {
        if (res ==TOM_ERR_WRITE_FILE) {
            snprintf(s, __MAX_S__LENGTH__, "%s: IO-error occured. The em-file may now be damaged :(", mexFunctionName());
            mexErrMsgTxt(s);
        } else if (res==TOM_ERR_OPEN_FILE) {
            snprintf(s, __MAX_S__LENGTH__, "%s: Error opening the file \"%s\" for writing.", mexFunctionName(), filename);
            mexErrMsgTxt(s);
        } else if (header_read && res==TOM_ERR_WRONG_IOTYPE_CONVERSION) {
            snprintf(s, __MAX_S__LENGTH__, "%s: Wrong typeconversion: can not convert volume of type %d to type %d as in the em-file.", mexFunctionName(), getIOTypeFromMxClassID(mxType, mxIsComplexVolume), tom_io_em_get_iotype_header(&header));
            mexErrMsgTxt(s);
        } else if (res == TOM_ERR_IOTYPE_NOT_SUPPORTED) {
            snprintf(s, __MAX_S__LENGTH__, "%s: Saving data of type %d to em-file is (currently) not supported.", mexFunctionName(), getIOTypeFromMxClassID(mxType, mxIsComplexVolume));
            mexErrMsgTxt(s);
        } else if (header_read && TOM_ERR_WRONG_DATA_SIZE && (sizex!=header.dims[0] || sizey!=header.dims[1])) {
            snprintf(s, __MAX_S__LENGTH__, "%s: Size mismatch: The volume has dimension %dx%dx%d, but the em-file has size %dx%dx%d.", mexFunctionName(), sizex, sizey, sizez, header.dims[0], header.dims[1], header.dims[2]);
            mexErrMsgTxt(s);
        } else {
            snprintf(s, __MAX_S__LENGTH__, "%s: Unexpected error. Is the \"%s\" a valid em-file? (%d)", mexFunctionName(), filename, res);
            mexErrMsgTxt(s);
        }
    }


    {
        /* Construct the output. */
        void *pdata;
        switch (nlhs) {
        case 5:
            pdata = mxGetData(plhs[4] = plhs_tmp[4]);
            for (i=0; i<256; i++) {
                ((int8_t *)pdata)[i] = header.userdata[i];
            }
        case 4:
            pdata = mxGetData(plhs[3] = plhs_tmp[3]);
            for (i=0; i<40; i++) {
                ((int32_t *)pdata)[i] = header.emdata[i];
            }
        case 3:
            pdata = mxGetData(plhs[2] = plhs_tmp[2]);
            for (i=0; i<80; i++) {
                ((int8_t *)pdata)[i] = header.comment[i];
            }
        case 2:
            pdata = mxGetData(plhs[1] = plhs_tmp[1]);
            ((int8_t *)pdata)[0] = header.machine;
            ((int8_t *)pdata)[1] = header.byte2;
            ((int8_t *)pdata)[2] = header.byte3;
            ((int8_t *)pdata)[3] = header.type;
        case 1:
            pdata = mxGetData(plhs[0] = plhs_tmp[0]);
            ((uint32_t *)pdata)[0] = header.dims[0];
            ((uint32_t *)pdata)[1] = header.dims[1];
            ((uint32_t *)pdata)[2] = header.dims[2];
            break;
        case 0:
        default:
            break;
        }
    }
}
Пример #17
0
/*
 * This ist the Entry Function of this Mex-DLL
 */
void mexFunction(int nlhs, mxArray*plhs[], int nrhs, const mxArray*prhs[])
{
    mexAtExit(CloseDBs);
    
    /*
     * Get the current Language
     */
    if (Language == -1)
    {
#ifdef _WIN32        
        switch(PRIMARYLANGID(GetUserDefaultLangID()))
        {
            case LANG_GERMAN:
                Language = 1;
                break;
                
            default:
                Language = 0;
        }
#else
        Language = 0;
#endif
    }
    
	/*
	 * Print Version Information
	 */
	if (! FirstStart)
    {
    	FirstStart = true;

        mexPrintf (MSG_HELLO, sqlite3_libversion());
    }
    
    /*
     * Check if the first argument is a number, then we have to use
	 * this number as an database id.
     */
    int db_id = 0;
    int FirstArg = 0;
    int NumArgs = nrhs;
    
    if (nrhs >= 1 && mxIsNumeric(prhs[0]))
    {
        db_id = (int) *mxGetPr(prhs[0]);
        if (db_id < 0 || db_id > MaxNumOfDbs)
        {
            mexPrintf(MSG_INVALIDDBHANDLE);
            mexErrMsgTxt(MSG_IMPOSSIBLE);
        }
        db_id --;
        FirstArg ++;
        NumArgs --;
    }

	/*
	 * All remaining arguments have to be strings
	 */
    bool isNotOK = false;
    int  i;
    
    for (i = FirstArg; i < nrhs; i++)
    {
        if (! mxIsChar(prhs[i]))
        {
            isNotOK = true;
            break;
        }
    }
    if (NumArgs < 1 || isNotOK)
    {
        mexPrintf(MSG_USAGE);
        mexErrMsgTxt(MSG_INVALIDARG);
    }

	/*
	 * Get the first string argument, this is the command string
	 */
    char *command = getstring(prhs[FirstArg]);
    
    if (! strcmp(command, "open"))
    {
		/*
		 * open a database. There have to be two string arguments.
		 * The command 'open' and the database filename
		 */
        if (NumArgs != 2)
        {
            mexPrintf(MSG_NOOPENARG, mexFunctionName());
			mxFree(command);
            mexErrMsgTxt(MSG_INVALIDARG);
        }
        
		// TODO: Memoryleak 'command not freed' when getstring fails
        char* dbname = getstring(prhs[FirstArg +1]);

		/*
		 * Is there an database ID? The close the database with the same id 
		 */
        if (db_id > 0 && g_dbs[db_id])
        {
            sqlite3_close(g_dbs[db_id]);
            g_dbs[db_id] = 0;
        }

		/*
		 * If there isn't an database id, then try to get one
		 */
        if (db_id < 0)
        {
            for (i = 0; i < MaxNumOfDbs; i++)
            {
                if (g_dbs[i] == 0)
                {
                    db_id = i;
                    break;
                }
            }
        }
		/*
		 * no database id? sorry, database id table full
		 */
        if (db_id < 0)
        {
            plhs[0] = mxCreateScalarDouble((double) 0);
            mexPrintf(MSG_NOFREESLOT);
			mxFree(command);
        	mxFree(dbname);
            mexErrMsgTxt(MSG_IMPOSSIBLE);
        }
       
		/*
		 * Open the database
		 */
        int rc = sqlite3_open(dbname, &g_dbs[db_id]);
        
        if (rc)
        {
			/*
			 * Anything wrong? free the database id and inform the user
			 */
            mexPrintf(MSG_CANTOPEN, sqlite3_errmsg(g_dbs[db_id]));
            sqlite3_close(g_dbs[db_id]);

            g_dbs[db_id] = 0;
            plhs[0] = mxCreateScalarDouble((double) 0);
            
			mxFree(command);
	        mxFree(dbname);
            mexErrMsgTxt(MSG_IMPOSSIBLE);
        }
        
		/*
		 * return value will be the used database id
		 */
        plhs[0] = mxCreateScalarDouble((double) db_id +1);
        mxFree(dbname);
    }
    else if (! strcmp(command, "close"))
    {
		/*
		 * close a database
		 */

		/*
		 * if the database id is < 0 than close all open databases
		 */
        if (db_id < 0)
        {
            for (i = 0; i < MaxNumOfDbs; i++)
            {
                if (g_dbs[i])
                {
                    sqlite3_close(g_dbs[i]);
                    g_dbs[i] = 0;
                }
            }
        }
        else
        {
			/*
			 * If the database is open, then close it. Otherwise
			 * inform the user
			 */
            if (! g_dbs[db_id])
            {
				mxFree(command);
                mexErrMsgTxt(MSG_DBNOTOPEN);
            }
            else
            {
                sqlite3_close(g_dbs[db_id]);
                g_dbs[db_id] = 0;
            }
        }
    }
    else if (! strcmp(command, "status"))
    {
    	for (i = 0; i < MaxNumOfDbs; i++)
        {
            mexPrintf("DB Handle %d: %s\n", i, g_dbs[i] ? "OPEN" : "CLOSED");
        }
    }
    else
    {
		/*
		 * Every unknown command is treated as an sql query string
		 */

		/*
		 * database id < 0? Thats an error...
		 */
        if (db_id < 0)
        {
            mexPrintf(MSG_INVALIDDBHANDLE);
			mxFree(command);
            mexErrMsgTxt(MSG_IMPOSSIBLE);
        }
        
		/*
		 * database not open? -> error
		 */
        if (!g_dbs[db_id])
        {
			mxFree(command);
            mexErrMsgTxt(MSG_DBNOTOPEN);
        }

		const char* query = command;

		/*
		 * emulate the "show tables" sql query
		 */
        if (! strcmpi(query, "show tables"))
        {
            query = "SELECT name as tablename FROM sqlite_master "
                    "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%' "
                    "UNION ALL "
                    "SELECT name as tablename FROM sqlite_temp_master "
                    "WHERE type IN ('table','view') "
                    "ORDER BY 1";
        }

		/*
		 * complete the query
		 */
        if (sqlite3_complete(query))
        {
			mxFree(command);
            mexErrMsgTxt(MSG_INVQUERY);
        }
        
        sqlite3_stmt *st;
        
		/*
		 * and prepare it
		 * if anything is wrong with the query, than complain about it.
		 */
        if (sqlite3_prepare_v2(g_dbs[db_id], query, -1, &st, 0))
        {
            if (st)
                sqlite3_finalize(st);
            
			mxFree(command);
            mexErrMsgIdAndTxt(TransErrToIdent(g_dbs[db_id]), sqlite3_errmsg(g_dbs[db_id]));
        }

		/*
		 * Any results?
		 */
        int ncol = sqlite3_column_count(st);
        if (ncol > 0)
        {
            char **fieldnames = new char *[ncol];   /* Column names */
            Values* allrows = 0;                    /* All query results */
            Values* lastrow = 0;					/* pointer to the last result row */
            int rowcount = 0;						/* number of result rows */
            
			/*
			 * Get the column names of the result set
			 */
            for(i=0; i<ncol; i++)
            {
                const char *cname = sqlite3_column_name(st, i);
                
                fieldnames[i] = new char [strlen(cname) +1];
                strcpy (fieldnames[i], cname);
				/*
				 * replace invalid chars by '_', so we can build
				 * valid MATLAB structs
				 */
                char *mk_c = fieldnames[i];
                while (*mk_c)
                {
                	if ((*mk_c == ' ') || (*mk_c == '*') || (*mk_c == '?'))
                    	*mk_c = '_';
                    mk_c++;
                }
            }
            
            /*
			 * get the result rows from the engine
			 *
			 * We cannot get the number of result lines, so we must
			 * read them in a loop and save them into an temporary list.
			 * Later, we can transfer this List into an MATLAB array of structs.
			 * This way, we must allocate enough memory for two result sets,
			 * but we save time by allocating the MATLAB Array at once.
			 */
            for(;;)
            {
				/*
				 * Advance to teh next row
				 */
                int step_res = sqlite3_step(st);

				/*
				 * no row left? break out of the loop
				 */
                if (step_res != SQLITE_ROW)
                    break;

				/*
				 * get new memory for the result
				 */
                Values* RecordValues = new Values(ncol);
                
                Value *v = RecordValues->m_Values;
                for (int j = 0; j < ncol; j++, v++)
                {
                     int fieldtype = sqlite3_column_type(st,j);

                     v->m_Type = fieldtype;
                        
                     switch (fieldtype)
                     {
                         case SQLITE_NULL:      v->m_NumericValue = g_NaN;                                   break;
                         case SQLITE_INTEGER:	v->m_NumericValue = (double) sqlite3_column_int(st, j);      break;
                         case SQLITE_FLOAT:     v->m_NumericValue = (double) sqlite3_column_double(st, j);	 break;
                         case SQLITE_TEXT:      v->m_StringValue  = strnewdup((const char*) sqlite3_column_text(st, j));   break;
                                
                         default:	
							mxFree(command);
							mexErrMsgTxt(MSG_UNKNWNDBTYPE);
                     }
                }
				/*
				 * and add this row to the list of all result rows
				 */
                if (! lastrow)
                {
                    allrows = lastrow = RecordValues;
                }
                else
                {
                    lastrow->m_NextValues = RecordValues;
                    lastrow = lastrow->m_NextValues;
                }
				/*
				 * we have one more...
				 */
                rowcount ++;
            }
            
			/*
			 * end the sql engine
			 */
            sqlite3_finalize(st);

			/*
			 * got nothing? return an empty result to MATLAB
			 */
            if (rowcount == 0 || ! allrows)
            {
                if (!( plhs[0] = mxCreateDoubleMatrix(0,0,mxREAL) ))
				{
					mxFree(command);
                    mexErrMsgTxt(MSG_CANTCREATEOUTPUT);
				}
            }
            else
            {
				/*
				 * Allocate an array of MATLAB structs to return as result
				 */
                int ndims[2];
                
                ndims[0] = rowcount;
                ndims[1] = 1;
                
                if (( plhs[0] = mxCreateStructArray (2, ndims, ncol, (const char**)fieldnames)) == 0)
                {
					mxFree(command);
                    mexErrMsgTxt(MSG_CANTCREATEOUTPUT);
                }
                
				/*
				 * transfer the result rows from the temporary list into the result array
				 */
                lastrow = allrows;
                i = 0;
                while(lastrow)
                {
                    Value* recordvalue = lastrow->m_Values;
                    
                    for (int j = 0; j < ncol; j++, recordvalue++)
                    {
                        if (recordvalue -> m_Type == SQLITE_TEXT)
                        {
                            mxArray* c = mxCreateString(recordvalue->m_StringValue);
                            mxSetFieldByNumber(plhs[0], i, j, c);
                        }
                        else if (recordvalue -> m_Type == SQLITE_NULL && !NULLasNaN)
                        {
                            mxArray* out_double = mxCreateDoubleMatrix(0,0,mxREAL);
                            mxSetFieldByNumber(plhs[0], i, j, out_double);
                        }
                        else
                        {
                            mxArray* out_double = mxCreateDoubleScalar(recordvalue->m_NumericValue);
                            mxSetFieldByNumber(plhs[0], i, j, out_double);
                        }
                    }
                    allrows = lastrow;
                    lastrow = lastrow->m_NextValues;
                    delete allrows;
                    i++;
                }
            }
            for(int i=0; i<ncol; i++)
                delete [] fieldnames[i];
            delete [] fieldnames;
        }
        else
        {
			/*
			 * no result, cleanup the sqlite engine
			 */
            int res = sqlite3_step(st);
            sqlite3_finalize(st);

            if (res != SQLITE_DONE)
            {
				mxFree(command);
                mexErrMsgIdAndTxt(TransErrToIdent(g_dbs[db_id]), sqlite3_errmsg(g_dbs[db_id]));
            }            
        }
    }
	mxFree(command);
}
Пример #18
0
void usageExit(int errorAbort)
{
  mexPrintf("\nUsage:\n");
  mexPrintf("======\n\n");
  mexPrintf("%s(0); - Unmap and unregister all resources. Automatically called at shutdown.\n\n", mexFunctionName());
  mexPrintf("%s(1, glObject, glTarget); - Unmap resource glObject of type glTarget\n\n", mexFunctionName());
  mexPrintf("%s(2, glObject, glTarget); - Unregister (and unmap if mapped) resource glObject of type glTarget\n\n", mexFunctionName());
  mexPrintf("%s(3, glObject, glTarget, gpuptr, nrbytes, direction, keepmapped, mapflags);\n", mexFunctionName());
  mexPrintf("- Copy data in VRAM between a CUDA memory buffer and a OpenGL resource. The resource gets\n");
  mexPrintf("  registered for use with CUDA if it isn't registered already, and mapped for use if it\n");
  mexPrintf("  isn't mapped already. 'glObject' and 'glTarget' are OpenGL object and target type handles\n");
  mexPrintf("  of the OpenGL resource. 'gpuptr' is a CUDA memory pointer into the CUDA memory buffer.\n");
  mexPrintf("  'nrbytes' = Number of bytes to copy. 'direction' 0 = OpenGL->CUDA, 1 = CUDA->OpenGL.\n");
  mexPrintf("  'keepmapped' 0 = Unmap immediately after copy [default], 1 = Keep mapped for future use.\n");
  mexPrintf("  Mapping and unmapping comes at some overhead, so should be avoided if possible. However,\n");
  mexPrintf("  OpenGL can't operate on mapped buffers, so one must unmap before OpenGL object is used again\n");
  mexPrintf("  by OpenGL. For a processing flow where a specific object is used as input and output for a\n");
  mexPrintf("  CUDA computation and not used by OpenGL during the CUDA computation, it can make sense to\n");
  mexPrintf("  keep the object mapped inbetween, avoiding one extra map/unmap cycle.\n");
  mexPrintf("  'mapflags': Optional, auto-selected. If set to a >= 0 value, use them as flags for CUDA resource registration.\n\n");
  mexPrintf("%s(4, glObject, glTarget, gpuptr, nrbytes, direction, keepmapped, mapflags);\n\n", mexFunctionName());
  mexPrintf("- Like 3, but avoid data copy. Instead return a uint64 64-Bit memory pointer to the actual mapped resource.\n");
  mexPrintf("  This implies 'keepmapped' == 1, regardless of what you specify.\n");
  mexPrintf("  This allows C-Level plugins to access the mapped resource directly via CUDA pointers.\n\n");
  mexPrintf("%s(5, newlimit); - Increase soft-limit of LRU cache to 'newlimit'.\n\n", mexFunctionName());
  mexPrintf("%s(6, verbose); - Set 'verbose' flag. Defaults to zero. 1 = Verbose status output.\n\n", mexFunctionName());

  /* mexPrintf("%s(5) \n", mexFunctionName()); */

  if (errorAbort) mexErrMsgTxt("Wrong number of arguments. See usage help above.");

  return;
}
Пример #19
0
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {

  unsigned int cmd, glhandle, gltarget, direction, flags, keepmapped, ispbo;
  unsigned long nrbytes;
  void *gpuptr;
  int slot = 0;
  cudaGraphicsResource_t resource = NULL;
  struct cudaArray *mappedArray = NULL;
  void* mappedPtr = NULL;
  size_t mappedSize = 0;

  /* Be optimistic, assume success unless told otherwise: */
  cudastatus = cudaSuccess;
  
  if (firsttime) {
      firsttime = 0;

      mexPrintf("\n%s: A simple CUDA <=> OpenGL interoperation interface.\n", mexFunctionName());
      mexPrintf("(c) 2013 by Mario Kleiner. Licensed to you under the MIT license.\n\n");

      /* Reset cache clock to zero and clear the cache: */
      cacheclock = 0;
      memset(resourceCache, 0, sizeof(resourceCache[0]) * MAX_CACHE_SLOTS);

      /* Start off with an effective cache capacity of 8 slots (1 slot is blocked from use): */
      cachesize = 8 + 1;
      firstLRUCycle = 1;

      /* Make sure the cache is flushed at mex file shutdown time: */
      mexAtExit(mexExit);
  }
  
  /* Retrieve command code: Give usage info if none given. */
  if (nrhs < 1) { usageExit(0); return; }

  cmd = (unsigned int) mxGetScalar(prhs[0]);

  /* Change of verbosity? */
  if (cmd == 6) {
    if (nrhs < 2) usageExit(1);  
    verbose = (unsigned int) mxGetScalar(prhs[1]);
    if (verbose) mexPrintf("\n%s: Verbose tracing of operations enabled.\n", mexFunctionName());
    return;
  }

  /* Resizing the LRU cache requested? */
  if (cmd == 5) {
    if (nrhs < 2) usageExit(1);

    /* Reset LRU cache full warning: */
    firstLRUCycle = 1;
    
    slot = (unsigned int) mxGetScalar(prhs[1]);
    
    /* Increment request by 1 to compensate for the "lost" slot 0: */
    slot = slot + 1;
    
    /* Child protections: */
    if (slot > MAX_CACHE_SLOTS) {
      mexPrintf("%s: Requested new softlimit %i for cache exceeds compiled in maximum %i. Will clamp to maximum.\n", mexFunctionName(), slot - 1, MAX_CACHE_SLOTS - 1);
      cachesize = MAX_CACHE_SLOTS;
      return;
    }
    
    if (slot < cachesize) {
      /* Shrinking the cache requested. This implies a full cache flush: */
      mexPrintf("%s: Requested new softlimit %i for cache is smaller than old softlimit %i. Will flush the cache before shrinking it.\n", mexFunctionName(), slot - 1, cachesize - 1);
      cacheFlush();
    }
    
    /* Set new softlimit: */
    cachesize = slot;
    mexPrintf("%s: New softlimit for LRU cache set to %i slots.\n", mexFunctionName(), cachesize - 1);
    
    return;
  }

  if (cmd == 0) {
    /* Cache flush requested: */
    cacheFlush();
    return;
  }

  /* Following ops require at least object handle and target type: */
  if (nrhs < 3) usageExit(1);

  /* Time to increment the age of our cached items by a clock tick: */
  ageCache();

  /* Retrieve OpenGL object handle to our image buffer: */
  glhandle = (unsigned int) mxGetScalar(prhs[1]);

  /* Get GLEnum target: */
  gltarget = (unsigned int) mxGetScalar(prhs[2]);
  
  if (cmd == 1) {
    /* Unmap resource if it is mapped: */
    unmapResource(glhandle, gltarget);
    return;
  }

  if (cmd == 2) {
    /* Unmap and unregister resource if it is mapped and/or registered: */
    unregisterResource(glhandle, gltarget);
    return;
  }

  if (nrhs < 6) usageExit(1);

  /* Retrieve CUDA memory pointer to source/destination CUDA memory buffer: */
  gpuptr = (void*) (unsigned long) mxGetScalar(prhs[3]);
  
  /* Retrieve number of bytes to copy: */
  nrbytes = (unsigned long) mxGetScalar(prhs[4]);
  
  /* Retrieve direction: 0 = OpenGL -> CUDA, 1 = CUDA -> OpenGL : */
  direction = (unsigned int) mxGetScalar(prhs[5]);

  /* Retrieve optional 'keepmapped' flag. */
  keepmapped = 0;
  if (nrhs >= 7) keepmapped = (unsigned int) mxGetScalar(prhs[6]);

  /* Define CUDA optimization flags, depending if this is a OpenGL->CUDA or
   * CUDA->OpenGL copy operation.
   */
  if ((nrhs >= 8) && (mxGetScalar(prhs[7]) >= 0)) {
    /* Override map flags provided. Use them: */
    flags = (unsigned int) mxGetScalar(prhs[7]);
  }
  else {
    /* Use auto-selected map flags: */
    flags = (direction) ? cudaGraphicsRegisterFlagsWriteDiscard : cudaGraphicsRegisterFlagsReadOnly;
  }

  /* Is gltarget a OpenGL pixelbuffer object? Check for gltarget == GL_PACK_BUFFER or GL_UNPACK_BUFFER. */
  ispbo = (gltarget == 35051 || gltarget == 35052) ? 1 : 0;

  /* Copy of data or mapped resource access pointer requested? */
  if (cmd == 3 || cmd == 4) {
    /* Register OpenGL object with CUDA as 'resource': */
    
    /* Already in cache? This would mean it is registered already with compatible mapping flags: */
    slot = cacheInsert(glhandle, gltarget, flags);
    if (slot < 0) {
      /* Not yet in cache. This means it is not registered at this time, either because it
         wasn't registered at all, or because it was registered with incompatible 'flags',
         so it just got unregistered and expelled from the cache. In any case, we need to
         insert it into the cache and register it. -slot is the free target slot for this
         purpose.
       */
       
      /* Turn slot into something useful: */
      slot = -slot;
    
      if (ispbo) {
        /* OpenGL Pixelbuffer object (GL_PACK_BUFFER or GL_UNPACK_BUFFER): */
        cudastatus = cudaGraphicsGLRegisterBuffer(&(resourceCache[slot].resource), glhandle, flags);
      }
      else {
        /* OpenGL texture or renderbuffer object: */
        cudastatus = cudaGraphicsGLRegisterImage(&(resourceCache[slot].resource), glhandle, gltarget, flags);
      }
      
      if (cudastatus != cudaSuccess) {
        mexPrintf("\nmemcpyCudaOpenGL: ERROR in %s(): %s\n", (ispbo) ? "cudaGraphicsGLRegisterBuffer" : "cudaGraphicsGLRegisterImage", cudaGetErrorString(cudastatus));
        resourceCache[slot].resource = NULL;
        goto err_final;
      }

      if (verbose) mexPrintf("\n%s: cacheInsert(%i): CUDA resource registered (globject %i, gltarget %i, flags %i).\n", mexFunctionName(), slot, glhandle, gltarget, flags);
      
      /* Fill cache slot: */
      resourceCache[slot].glhandle = glhandle;
      resourceCache[slot].gltarget = gltarget;
      resourceCache[slot].mapflags = flags;
      resourceCache[slot].lastaccess = cacheclock;
      resourceCache[slot].ismapped = 0;
    }
      
    /* At this point, the resource is stored in slot 'slot' of the cache and registered in a compatible way: */
    
    /* Map the 'resource', unless it is already mapped: */
    if (!resourceCache[slot].ismapped) {
      /* Map it: */
      cudastatus = cudaGraphicsMapResources(1, &(resourceCache[slot].resource), 0);
      if (cudastatus != cudaSuccess) {
        mexPrintf("\nmemcpyCudaOpenGL: ERROR in cudaGraphicsMapResources(): %s\n", cudaGetErrorString(cudastatus));
        goto err_unregister;
      }

      if (verbose) mexPrintf("\n%s: CUDA resource %i mapped (globject %i, gltarget %i, flags %i).\n", mexFunctionName(), slot, glhandle, gltarget, flags);
      
      /* Successfully mapped: */
      resourceCache[slot].ismapped = 1;
    }
    
    /* Get simpler handle: */
    resource = resourceCache[slot].resource;
    
    /* Get mapped resource image array handle or PBO pointer: */
    if (ispbo) {
      cudastatus = cudaGraphicsResourceGetMappedPointer(&mappedPtr, &mappedSize, resource);
    }
    else {
      cudastatus = cudaGraphicsSubResourceGetMappedArray(&mappedArray, resource, 0, 0);
    }
    
    if (cudastatus != cudaSuccess) {
      mexPrintf("\nmemcpyCudaOpenGL: ERROR in %s(): %s\n", (ispbo) ? "cudaGraphicsResourceGetMappedPointer" : "cudaGraphicsSubResourceGetMappedArray", cudaGetErrorString(cudastatus));
      goto err_unmap;
    }
  }
  
  /* Copy of PBO data between CUDA and OpenGL requested? */
  if (cmd == 3 && ispbo) {
    /* Copy from OpenGL PBO to CUDA buffer? */
    if (direction == 0) {
        /* OpenGL -> CUDA copy: */
        cudastatus = cudaMemcpyAsync(gpuptr, (const void*) mappedPtr, (size_t) nrbytes, cudaMemcpyDeviceToDevice, 0);
        if (cudastatus != cudaSuccess) {
            mexPrintf("\nmemcpyCudaOpenGL: ERROR in cudaMemcpyAsync(): %s\n", cudaGetErrorString(cudastatus));
            goto err_unmap;
        }
    }

    if (direction == 1) {
        /* CUDA -> OpenGL copy: */
        cudastatus = cudaMemcpyAsync(mappedPtr, (const void*) gpuptr, (size_t) nrbytes, cudaMemcpyDeviceToDevice, 0);
        if (cudastatus != cudaSuccess) {
            mexPrintf("\nmemcpyCudaOpenGL: ERROR in cudaMemcpyAsync(): %s\n", cudaGetErrorString(cudastatus));
            goto err_unmap;
        }
    }
  }

  /* Copy of texture or renderbuffer data between CUDA and OpenGL requested? */
  if (cmd == 3 && !ispbo) {
    /* Copy from OpenGL object to CUDA buffer? */
    if (direction == 0) {
        /* OpenGL -> CUDA copy: */
        cudastatus = cudaMemcpyFromArrayAsync(gpuptr, (const struct cudaArray*) mappedArray, 0, 0, (size_t) nrbytes, cudaMemcpyDeviceToDevice, 0);
        if (cudastatus != cudaSuccess) {
            mexPrintf("\nmemcpyCudaOpenGL: ERROR in cudaMemcpyFromArray(): %s\n", cudaGetErrorString(cudastatus));
            goto err_unmap;
        }
    }

    if (direction == 1) {
        /* CUDA -> OpenGL copy: */
        cudastatus = cudaMemcpyToArrayAsync((struct cudaArray*) mappedArray, 0, 0, (const void*) gpuptr, (size_t) nrbytes, cudaMemcpyDeviceToDevice, 0);
        if (cudastatus != cudaSuccess) {
            mexPrintf("\nmemcpyCudaOpenGL: ERROR in cudaMemcpyToArray(): %s\n", cudaGetErrorString(cudastatus));
            goto err_unmap;
        }
    }
  }
  
  /* Return of pointers to mapped resource requested? */
  if (cmd == 4) {
    /* Yes: This implies we must not unmap the resource now, as otherwise the
     * returned pointers would be dead on arrival.
     */
    keepmapped = 1;
    
    /* Cast pointer to void* then store it in a 64-Bit unsigned integer return value: */
    plhs[0] = mxCreateNumericMatrix(1, 1, mxUINT64_CLASS, mxREAL);
    *((unsigned long long*) mxGetData(plhs[0])) = (unsigned long long) (void*) ((ispbo) ? mappedPtr : mappedArray);
  }
  
  /* Keep resource mapped? */
  if (slot && !keepmapped) doCudaUnmap(slot);
  
  /* Successfully completed: */
  return;
  
  /* Error handling -- Unwind in reverse order: */
  
err_unmap:
  
  /* Unmap the 'resource': */
  unmapResource(glhandle, gltarget);

err_unregister:
  
  /* Unregister the 'resource': */
  unregisterResource(glhandle, gltarget);

err_final:      
      
  if (cudastatus != cudaSuccess) mexErrMsgTxt("Error in memcpyCudaOpenGL(), reason see above.");
}
Пример #20
0
/* Enter an item into the cache, unless it is already there, in which case its index is returned: */
int cacheInsert(unsigned int glhhandle, unsigned int gltarget, unsigned int mapflags)
{
  int i, lruvictim;
  unsigned long long curage;
  unsigned long long maxage = 0;

  /* Iterate over all cache slots and search for (glhandle,gltarget) key:
     We omit slot 0 as it is reserved. Otherwise we couldn't signal caching state
     to caller via the sign of the return value, as zero is ambiguous.
   */
  for (i = 1; i < cachesize; i++) {
    /* Found? */
    if ((resourceCache[i].glhandle == glhhandle) && (resourceCache[i].gltarget == gltarget)) {
      /* Cache hit: Update access timestamp and return slot. */
      resourceCache[i].lastaccess = cacheclock;
      
      /* Well, almost. We need to make sure that this resource is also registered
         with compatible 'mapflags', or bad things would happen.
       */
      if (mapflags != resourceCache[i].mapflags) {
        /* Incompatible flags. Need to unregister the resource and then return
         * its former host slot 'i' as "free" slot, so calling code thinks the
         * resource is not in cache and reregisters it with proper mapflags.
         */
         if (verbose) mexPrintf("\n%s: cacheInsert(%i): Incompatible cached map flags [%i vs. %i]. Triggering reregister.\n", mexFunctionName(), i, mapflags, resourceCache[i].mapflags);
         doCudaUnregister(i);
         return(-i);
      }
     
      /* Registered in a directly useable way: */ 
      return(i);
    }

    /* Nope. Keep track of first free slot, or slot which hasn't been accessed for
       the longest time, ie., the victim for lru replacement if neccessary. */
    curage = cacheclock - resourceCache[i].lastaccess;
    if (curage > maxage) {
      maxage = curage;
      lruvictim = i;
    }
  }

  /* If we reach this point, then the object isn't in the cache yet and needs
     to be entered into a free cache slot, if any. lruvictim is our candidate
     slot. If its lastaccess timestamp is zero, then we got a free slot for use.
     Otherwise our cache is full and lruvictim is the slot that wasn't used for
     the longest time which makes it our victim for expelling it from the cache.
   */
  if (resourceCache[lruvictim].lastaccess > 0) {
    /* Occupied slot. Free it up by unmapping and unregistering the cached
       OpenGL resource.
     */
    doCudaUnregister(lruvictim);
    if (firstLRUCycle) {
      firstLRUCycle = 0;
      mexPrintf("%s: Warning: CUDA<->OpenGL interop cache soft-limit of %i slots reached. Cache full!\n", mexFunctionName(), cachesize - 1);
      mexPrintf("%s: Warning: Will switch to LRU cache replacement mode now. Performance may be degraded!\n", mexFunctionName());
      mexPrintf("%s: Warning: Increase the cache soft-limit, or check your code for unintended resource leaks.\n", mexFunctionName());
    }

    if (verbose) mexPrintf("\n%s: cacheInsert(%i): LRU-Replacement done (Victims age %i).\n", mexFunctionName(), lruvictim, maxage);
  }
  else if (verbose) mexPrintf("\n%s: cacheInsert(%i): Inserted into free slot.\n", mexFunctionName(), lruvictim);

  /* Cache miss: Return the (now) free cache slot 'lruvictim' to be filled. Return
     a negative index to indicate this was a cache-miss and the cache needs to be filled.
   */
  return(-lruvictim);
}
Пример #21
0
/***********************************************************************//**
 * \brief mexFunction to append a stack to an existing em-file.
 **************************************************************************/
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray*prhs[]) {


    size_t filename_length = 0;
    #define __MAX_FILENAME_LENGTH__ ((int)2048)
    char filename[__MAX_FILENAME_LENGTH__+1];

    #define __MAX_S__LENGTH__ (4096)
    char s[__MAX_S__LENGTH__+1];

    #define __BUFFERLENGTH_SYNOPSIS__ 1024
    char synopsis[__BUFFERLENGTH_SYNOPSIS__];

    size_t i, j, k;

    const void *w_data;
    int w_iotype;

    uint32_t subregion_start[3] = { 0,0,0 };
    uint32_t reverse_sampling[3] = { 0,0,0 };
    tom_io_em_header header;
    int allow_conversion = 1;
    mxArray *plhs_tmp[5] = { NULL, NULL, NULL, NULL, NULL };
    void *complexCopy = NULL;

    uint32_t w_sizex, w_sizey, w_sizez;
    size_t w_stridex=0, w_stridey=0, w_stridez=0;




    snprintf(synopsis, __BUFFERLENGTH_SYNOPSIS__, "[size, magic, comment, emdata, userdata] = %s(filename, volume, [subregion_start, reverse_sampling, allow_conversion])", mexFunctionName());
    if (nrhs==0 && nlhs==0) {
        /* Print help */
        mexPrintf("SYNOPSIS: %s\n", synopsis);
        mexPrintf("mex-file compiled from file \"" __FILE__ "\" at " __DATE__ ", " __TIME__ ".\n");
        return;
    }

    if (nlhs>5 || nrhs<2 || nrhs>5) {
        snprintf(s, __MAX_S__LENGTH__, "%s: Wrong number of in/output arguments: %s.", mexFunctionName(), synopsis);
        mexErrMsgTxt(s);
    }

    {
        #define __MAX_UINT32_T__ 0xFFFFFFFF
        const mxArray *arg;
        mxArray *tmpArray = NULL;
        const mwSize *size;
        double *pdouble;
        mxClassID type;

        /* filename */
        arg = prhs[0];
        if (!mxIsChar(arg) || mxGetNumberOfDimensions(arg)!=2 || mxGetM(arg)!=1 || (filename_length=mxGetN(arg))<1 || filename_length>=__MAX_FILENAME_LENGTH__) {
            snprintf(s, __MAX_S__LENGTH__, "%s: needs file name as first parameter: %s.", mexFunctionName(), synopsis);
            mexErrMsgTxt(s);
        }
        mxGetString(arg, filename, __MAX_FILENAME_LENGTH__);


        /* subregion_start */
        if (nrhs >= 3) {
            arg = prhs[2];
            i = mxGetM(arg); j = mxGetN(arg);
            if (!mxIsNumeric(arg) || mxIsComplex(arg) || mxGetNumberOfDimensions(arg)!=2 || !((i==0&&j==0) || (i==1&&j==3) || (i==3&&j==1))) {
                snprintf(s, __MAX_S__LENGTH__, "%s: The subregion_start must be either [] or a 1x3 vector: %s", mexFunctionName(), synopsis);
                mexErrMsgTxt(s);
            }
            if (i!=0) {
                if (!(tmpArray=getDoubleArray(arg))) {
                    snprintf(s, __MAX_S__LENGTH__, "%s: Error creating a copy of the subregion_start. Maybe out of memory.", mexFunctionName());
                    mexErrMsgTxt(s);
                }
                pdouble = mxGetPr(tmpArray);
                for (k=0; k<3; k++) {
                    subregion_start[k] = (uint32_t)pdouble[k];
                    if (pdouble[k] != subregion_start[k]) {
                        snprintf(s, __MAX_S__LENGTH__, "%s: subregion_start must contain integer values: %s", mexFunctionName(), synopsis);
                        mexErrMsgTxt(s);
                    }
                }
                mxDestroyArray(tmpArray);
            }
        }

        /* reverse_sampling */
        if (nrhs >= 4) {
            arg = prhs[3];
            i = mxGetM(arg); j = mxGetN(arg);
            if (!mxIsNumeric(arg) || mxIsComplex(arg) || mxGetNumberOfDimensions(arg)!=2 || !((i==0&&j==0) || (i==1&&j==3) || (i==3&&j==1))) {
                snprintf(s, __MAX_S__LENGTH__, "%s: The reverse_sampling must be either [] or a 1x3 vector: %s", mexFunctionName(), synopsis);
                mexErrMsgTxt(s);
            }
            if (i!=0) {
                if (!(tmpArray=getDoubleArray(arg))) {
                    snprintf(s, __MAX_S__LENGTH__, "%s: Error creating a copy of the reverse_sampling. Maybe out of memory.", mexFunctionName());
                    mexErrMsgTxt(s);
                }
                pdouble = mxGetPr(tmpArray);
                for (k=0; k<3; k++) {
                    reverse_sampling[k] = (uint32_t)pdouble[k];
                    if (pdouble[k] != reverse_sampling[k]) {
                        snprintf(s, __MAX_S__LENGTH__, "%s: reverse_sampling must contain integer values: %s", mexFunctionName(), synopsis);
                        mexErrMsgTxt(s);
                    }
                }
                mxDestroyArray(tmpArray);
            }
        }
        if (reverse_sampling[0] < 1) { reverse_sampling[0] = 1; }
        if (reverse_sampling[1] < 1) { reverse_sampling[1] = 1; }
        if (reverse_sampling[2] < 1) { reverse_sampling[2] = 1; }


        /* allow_conversion */
        if (nrhs >= 5) {
            const mwSize numel = mxGetNumberOfElements(arg = prhs[4]);
            if (!(mxIsNumeric(arg) || mxIsLogical(arg)) || numel>1) {
                snprintf(s, __MAX_S__LENGTH__, "%s: allow_conversion must be one of true, false or [].", mexFunctionName(), synopsis);
                mexErrMsgTxt(s);
            }
            if (numel == 1) {
                allow_conversion = mxGetScalar(arg) != 0;
            }
        }


        {
            /* Allocate the memory for the ouput, so that in case of successfully writing, no
            error can happen afterwards in the mexfunction. */
            switch (nlhs) {
                case 5:
                    if (!(plhs_tmp[4] = mxCreateNumericMatrix(1, 256, mxINT8_CLASS, mxREAL))) { mexErrMsgTxt("Error allocating memory"); }
                case 4:
                    if (!(plhs_tmp[3] = mxCreateNumericMatrix(1, 40, mxINT32_CLASS, mxREAL))) { mexErrMsgTxt("Error allocating memory"); }
                case 3:
                    if (!(plhs_tmp[2] = mxCreateNumericMatrix(1, 80, mxINT8_CLASS, mxREAL))) { mexErrMsgTxt("Error allocating memory"); }
                case 2:
                    if (!(plhs_tmp[1] = mxCreateNumericMatrix(1, 4, mxINT8_CLASS, mxREAL))) { mexErrMsgTxt("Error allocating memory"); }
                case 1:
                    if (!(plhs_tmp[0] = mxCreateNumericMatrix(3, 1, mxUINT32_CLASS, mxREAL))) { mexErrMsgTxt("Error allocating memory"); }
            }
        }


        /* data */
        arg = prhs[1];
        if (!mxIsNumeric(arg) || mxGetNumberOfDimensions(arg)>3) {
            snprintf(s, __MAX_S__LENGTH__, "%s: needs a numerical volume as second parameter: %s", mexFunctionName(), synopsis);
            mexErrMsgTxt(s);
        }
        type = mxGetClassID(arg);
        size = mxGetDimensions(arg);
        w_sizex = size[0];
        w_sizey = size[1];
        w_sizez = mxGetNumberOfDimensions(arg)==3 ? size[2] : 1;
        if (w_sizex!=size[0] || w_sizey!=size[1] || w_sizez!=(mxGetNumberOfDimensions(arg)==3?size[2]:1)) {
            snprintf(s, __MAX_S__LENGTH__, "%s: The volume is too large to save it as EM.", mexFunctionName(), synopsis);
            mexErrMsgTxt(s);
        }

        if (mxIsComplex(arg)) {
            const size_t numel = w_sizex * w_sizey * w_sizez;
            float *pdst;
            if (!allow_conversion && type!=mxSINGLE_CLASS) {
                snprintf(s, __MAX_S__LENGTH__, "%s: Can not convert complex volume to single (not allow_conversion).", mexFunctionName());
                mexErrMsgTxt(s);
            }
            if (!(complexCopy = malloc(numel*2*sizeof(float)))) {
                snprintf(s, __MAX_S__LENGTH__, "%s: Error allocating memory for temporary copy of complex data.", mexFunctionName());
                mexErrMsgTxt(s);
            }
            pdst = complexCopy;
            if (type == mxSINGLE_CLASS) {
                const float *psrc_re;
                const float *psrc_im;
                psrc_re = (float *)mxGetData(arg);
                psrc_im = (float *)mxGetData(arg);
                for (i=0; i<numel; i++) {
                    *pdst++ = psrc_re[i];
                    *pdst++ = psrc_im[i];
                }
            } else if (type == mxDOUBLE_CLASS) {
                const double *psrc_re, *psrc_im;
                psrc_re = mxGetPr(arg);
                psrc_im = mxGetPi(arg);
                for (i=0; i<numel; i++) {
                    *pdst++ = psrc_re[i];
                    *pdst++ = psrc_im[i];
                }
            } else {
                free(complexCopy); complexCopy = NULL;
                snprintf(s, __MAX_S__LENGTH__, "%s: EM supports only floating point complex data (single).", mexFunctionName(), type);
                mexErrMsgTxt(s);
            }
            w_data = complexCopy;
            w_iotype = TOM_IO_TYPE_COMPLEX4;
        } else {
            w_data = mxGetData(arg);
            w_iotype = getIOTypeFromMxClassID(type, false);
        }
    }

    {
        int header_read;
        int fcn_res = tom_io_em_write_paste(filename, w_data, w_iotype, w_sizex, w_sizey, w_sizez, w_stridex, w_stridey, w_stridez, &header, &header_read, allow_conversion, subregion_start, reverse_sampling);
        if (fcn_res != TOM_ERR_OK) {
            if (complexCopy) { free(complexCopy); complexCopy = NULL; }
            switch (fcn_res) {
                case TOM_ERR_VOLUME_TOO_LARGE:
                    snprintf(s, __MAX_S__LENGTH__, "%s: The %lux%lux%lu-volume is to large to paste it into the %lux%lux%lu-EM-file (start at %lux%lux%lu, sample %lux%lux%lu).", mexFunctionName(), (unsigned long)w_sizex, (unsigned long)w_sizey, (unsigned long)w_sizez, (unsigned long)header.dims[0], (unsigned long)header.dims[1], (unsigned long)header.dims[2], (unsigned long)subregion_start[0], (unsigned long)subregion_start[1], (unsigned long)subregion_start[2], (unsigned long)reverse_sampling[0], (unsigned long)reverse_sampling[1], (unsigned long)reverse_sampling[2]);
                    break;
                case TOM_ERR_WRONG_IOTYPE_CONVERSION:
                    snprintf(s, __MAX_S__LENGTH__, "%s: Error converting the volume from type %d to type %d (allow conversion = %s).", mexFunctionName(), (int)w_iotype, (int)tom_io_em_get_iotype(&header), allow_conversion ? "yes" : "no");
                    break;
                default:
                    snprintf(s, __MAX_S__LENGTH__, "%s: Unspecified error pasting the volume to file (%d).", mexFunctionName(), fcn_res);
                    break;
            }
            mexErrMsgTxt(s);
        }
        if (complexCopy) { free(complexCopy); complexCopy = NULL;}
    }


    {
        /* Construct the output. */
        void *pdata;
        switch (nlhs) {
            case 5:
                pdata = mxGetData(plhs[4] = plhs_tmp[4]);
                for (i=0; i<256; i++) { ((int8_t *)pdata)[i] = header.userdata[i]; }
            case 4:
                pdata = mxGetData(plhs[3] = plhs_tmp[3]);
                for (i=0; i<40; i++) { ((int32_t *)pdata)[i] = header.emdata[i]; }
            case 3:
                pdata = mxGetData(plhs[2] = plhs_tmp[2]);
                for (i=0; i<80; i++) { ((int8_t *)pdata)[i] = header.comment[i]; }
            case 2:
                pdata = mxGetData(plhs[1] = plhs_tmp[1]);
                ((int8_t *)pdata)[0] = header.machine;
                ((int8_t *)pdata)[1] = header.byte2;
                ((int8_t *)pdata)[2] = header.byte3;
                ((int8_t *)pdata)[3] = header.type;
            case 1:
                pdata = mxGetData(plhs[0] = plhs_tmp[0]);
                ((uint32_t *)pdata)[0] = header.dims[0];
                ((uint32_t *)pdata)[1] = header.dims[1];
                ((uint32_t *)pdata)[2] = header.dims[2];
                break;
            case 0:
            default:
                break;
        }
    }


}
Пример #22
0
/***********************************************************************//**
 * \brief mexFunction to append a stack to an existing em-file.
 **************************************************************************/
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray*prhs[]) {


    size_t filename_length = 0;
#define __MAX_FILENAME_LENGTH__ ((int)2048)
    char filename[__MAX_FILENAME_LENGTH__+1];

#define __MAX_S__LENGTH__ (4096)
    char s[__MAX_S__LENGTH__+1];

#define __BUFFERLENGTH_SYNOPSIS__ 1024
    char synopsis[__BUFFERLENGTH_SYNOPSIS__];

    size_t i, j, k;

    const void *w_data;
    int w_iotype;

    size_t dims[3];
    uint32_t *subregion = NULL;
    uint32_t subregion_field[6];
    tom_io_em_header header;

    float *complexCopy = 0;
    char autoval_magic = 1;
    size_t stridey=0, stridez=0;

    memset(&header, 0, sizeof(header));

    snprintf(synopsis, __BUFFERLENGTH_SYNOPSIS__, "%s(filename, data, [subregion_in, magic, comment, emdata, userdata])", mexFunctionName());
    if (nrhs==0 && nlhs==0) {
        /* Print help */
        mexPrintf("SYNOPSIS: %s\n", synopsis);
        mexPrintf("mex-file compiled from file \"" __FILE__ "\" at " __DATE__ ", " __TIME__ ".\n");
        return;
    }

    if (nlhs>0 || nrhs<2 || nrhs>7) {
        snprintf(s, __MAX_S__LENGTH__, "%s: Wrong number of in/output arguments: %s.", mexFunctionName(), synopsis);
        mexErrMsgTxt(s);
    }

    {
#define __MAX_UINT32_T__ 0xFFFFFFFF
        const mxArray *arg;
        mxArray *tmpArray = NULL;
        const mwSize *size;
        double *pdouble;
        int8_t *pint8;
        int32_t *pint32;
        mxClassID type;

        /* filename */
        arg = prhs[0];
        if (!mxIsChar(arg) || mxGetNumberOfDimensions(arg)!=2 || mxGetM(arg)!=1 || (filename_length=mxGetN(arg))<1 || filename_length>=__MAX_FILENAME_LENGTH__) {
            snprintf(s, __MAX_S__LENGTH__, "%s: needs file name as first parameter: %s.", mexFunctionName(), synopsis);
            mexErrMsgTxt(s);
        }
        mxGetString(arg, filename, __MAX_FILENAME_LENGTH__);


        /* subregion */
        if (nrhs >= 3) {
            arg = prhs[2];
            i = mxGetM(arg);
            j = mxGetN(arg);
            if (!mxIsNumeric(arg) || mxIsComplex(arg) || mxGetNumberOfDimensions(arg)!=2 || !((i==0&&j==0) || (i==1&&j==6) || (i==6&&j==1))) {
                snprintf(s, __MAX_S__LENGTH__, "%s: The subregion must be either [] or a 1x6 vector: %s", mexFunctionName(), synopsis);
                mexErrMsgTxt(s);
            }
            if (i!=0) {
                if (!(tmpArray=getDoubleArray(arg))) {
                    snprintf(s, __MAX_S__LENGTH__, "%s: Error creating a copy of the subregion. Maybe out of memory.", mexFunctionName());
                    mexErrMsgTxt(s);
                }
                pdouble = mxGetPr(tmpArray);
                for (k=0; k<6; k++) {
                    if (pdouble[k] != floor(pdouble[k]) || pdouble[k]<0 || (k>=3&&pdouble[k]<=0) || pdouble[k]>__MAX_UINT32_T__) {
                        snprintf(s, __MAX_S__LENGTH__, "%s: The subregion must contain positive integer values: %s", mexFunctionName(), synopsis);
                        mexErrMsgTxt(s);
                    }
                    subregion_field[k] = (uint32_t)pdouble[k];
                }
                subregion = subregion_field;
                mxDestroyArray(tmpArray);
            }
        }



        /* magic */
        if (nrhs >= 4) {
            arg = prhs[3];
            if (!mxIsNumeric(arg) || mxIsComplex(arg) || mxGetNumberOfDimensions(arg)!=2) {
                snprintf(s, __MAX_S__LENGTH__, "%s: magic must be a 4-vector of int8 or [].", mexFunctionName());
                mexErrMsgTxt(s);
            }
            if (mxGetNumberOfElements(arg) > 0) {
                if (mxGetClassID(arg)!=mxINT8_CLASS || mxGetNumberOfElements(arg)!=4 || (mxGetN(arg)!=1&&mxGetM(arg)!=1)) {
                    snprintf(s, __MAX_S__LENGTH__, "%s: magic must be a 4-vector of int8 or [].", mexFunctionName());
                    mexErrMsgTxt(s);
                }
                pint8 = (int8_t *)mxGetData(arg);
                header.machine = pint8[0];
                header.byte2 = pint8[1];
                header.byte3 = pint8[2];
                header.type = pint8[3];
                autoval_magic = 0;
            }
        }

        /* comment */
        if (nrhs >= 5) {
            arg = prhs[4];
            if (!mxIsNumeric(arg) || mxIsComplex(arg) || mxGetNumberOfDimensions(arg)!=2) {
                snprintf(s, __MAX_S__LENGTH__, "%s: comment must be a 80-vector of int8 or [].", mexFunctionName());
                mexErrMsgTxt(s);
            }
            if (mxGetNumberOfElements(arg) > 0) {
                if (mxGetClassID(arg)!=mxINT8_CLASS || mxGetNumberOfElements(arg)!=80 || (mxGetN(arg)!=1&&mxGetM(arg)!=1)) {
                    snprintf(s, __MAX_S__LENGTH__, "%s: comment must be a 80-vector of int8 or [].", mexFunctionName());
                    mexErrMsgTxt(s);
                }
                pint8 = (int8_t *)mxGetData(arg);
                for (i=0; i<80; i++) {
                    header.comment[i] = pint8[i];
                }
            }
        }

        /* emdata */
        if (nrhs >= 6) {
            arg = prhs[5];
            if (!mxIsNumeric(arg) || mxIsComplex(arg) || mxGetNumberOfDimensions(arg)!=2) {
                snprintf(s, __MAX_S__LENGTH__, "%s: emdata must be a 40-vector of int32 or [].", mexFunctionName());
                mexErrMsgTxt(s);
            }
            if (mxGetNumberOfElements(arg) > 0) {
                if (mxGetClassID(arg)!=mxINT32_CLASS || mxGetNumberOfElements(arg)!=40 || (mxGetN(arg)!=1&&mxGetM(arg)!=1)) {
                    snprintf(s, __MAX_S__LENGTH__, "%s: comment must be a 40-vector of int32 or [].", mexFunctionName());
                    mexErrMsgTxt(s);
                }
                pint32 = (int32_t *)mxGetData(arg);
                for (i=0; i<40; i++) {
                    header.emdata[i] = pint32[i];
                }
            }
        }


        /* userdata */
        if (nrhs >= 7) {
            arg = prhs[6];
            if (!mxIsNumeric(arg) || mxIsComplex(arg) || mxGetNumberOfDimensions(arg)!=2) {
                snprintf(s, __MAX_S__LENGTH__, "%s: userdata must be a 256-vector of int8 or [].", mexFunctionName());
                mexErrMsgTxt(s);
            }
            if (mxGetNumberOfElements(arg) > 0) {
                if (mxGetClassID(arg)!=mxINT8_CLASS || mxGetNumberOfElements(arg)!=256 || (mxGetN(arg)!=1&&mxGetM(arg)!=1)) {
                    snprintf(s, __MAX_S__LENGTH__, "%s: userdata must be a 256-vector of int8 or [].", mexFunctionName());
                    mexErrMsgTxt(s);
                }
                pint8 = (int8_t *)mxGetData(arg);
                for (i=0; i<256; i++) {
                    header.userdata[i] = pint8[i];
                }
            }
        }

        arg = prhs[1];
        if (!mxIsNumeric(arg) || mxGetNumberOfDimensions(arg)>3 || mxGetNumberOfElements(arg)<1) {
            snprintf(s, __MAX_S__LENGTH__, "%s: The volume must be a non-empty numeric array.", mexFunctionName());
            mexErrMsgTxt(s);
        }
        size = mxGetDimensions(arg);
        dims[0] = size[0];
        dims[1] = size[1];
        dims[2] = mxGetNumberOfDimensions(arg)==3 ? size[2] : 1;

        type = mxGetClassID(arg);
        if (mxIsComplex(arg)) {
            const size_t numel = dims[0]*dims[1]*dims[2];
            float *pdst;
            if (!autoval_magic && tom_io_em_get_iotype(&header)!=TOM_IO_TYPE_COMPLEX4) {
                snprintf(s, __MAX_S__LENGTH__, "%s: Saving complex data is only possible as complex (single) floating point.", mexFunctionName());
                mexErrMsgTxt(s);
            }
            if (!(complexCopy = malloc(numel*2*sizeof(float)))) {
                snprintf(s, __MAX_S__LENGTH__, "%s: Error allocating memory for temporary copy of complex data.", mexFunctionName());
                mexErrMsgTxt(s);
            }
            pdst = complexCopy;
            if (type == mxSINGLE_CLASS) {
                const float *psrc_re, *psrc_im;
                psrc_re = (float *)mxGetData(arg);
                psrc_im = (float *)mxGetImagData(arg);
                for (i=0; i<numel; i++) {
                    *pdst++ = psrc_re[i];
                    *pdst++ = psrc_im[i];
                }
            } else if (type == mxDOUBLE_CLASS) {
                const double *psrc_re, *psrc_im;
                psrc_re = mxGetPr(arg);
                psrc_im = mxGetPr(arg);
                for (i=0; i<numel; i++) {
                    *pdst++ = psrc_re[i];
                    *pdst++ = psrc_im[i];
                }
            } else {
                free(complexCopy);
                snprintf(s, __MAX_S__LENGTH__, "%s: EM supports only floating point complex data (single).", mexFunctionName(), type);
                mexErrMsgTxt(s);
            }
            w_iotype = TOM_IO_TYPE_COMPLEX4;
            w_data = complexCopy;
        } else {
            switch (type) {
            case mxINT8_CLASS:
                w_iotype = TOM_IO_TYPE_INT8;
                break;
            case mxINT16_CLASS:
                w_iotype = TOM_IO_TYPE_INT16;
                break;
            case mxINT32_CLASS:
                w_iotype = TOM_IO_TYPE_INT32;
                break;
            case mxSINGLE_CLASS:
                w_iotype = TOM_IO_TYPE_FLOAT;
                break;
            case mxDOUBLE_CLASS:
                w_iotype = TOM_IO_TYPE_DOUBLE;
                break;
            default:
                snprintf(s, __MAX_S__LENGTH__, "%s: The volume has type %s: This can not be saved to EM without conversion.", mexFunctionName(), type);
                mexErrMsgTxt(s);
            }
            w_data = mxGetData(arg);
        }
        if (subregion) {
            if (subregion[0]+subregion[3]>dims[0] || subregion[1]+subregion[4]>dims[1] || subregion[2]+subregion[5]>dims[2]) {
                snprintf(s, __MAX_S__LENGTH__, "%s: The subregion is out of the volume.", mexFunctionName());
                mexErrMsgTxt(s);
            }
            header.dims[0] = subregion[3];
            header.dims[1] = subregion[4];
            header.dims[2] = subregion[5];
            w_data = (const char *)w_data + ((((subregion[2]*dims[1] + subregion[1]))*dims[0] + subregion[0])*tom_io_iotype_datasize(w_iotype));
            stridey = dims[0] * tom_io_iotype_datasize(w_iotype);
            stridez = dims[1] * stridey;
        } else {
            if (dims[0]>=__MAX_UINT32_T__ || dims[1]>=__MAX_UINT32_T__ || dims[2]>=__MAX_UINT32_T__) {
                snprintf(s, __MAX_S__LENGTH__, "%s: The volume is too large to save it to EM.", mexFunctionName());
                mexErrMsgTxt(s);
            }
            header.dims[0] = dims[0];
            header.dims[1] = dims[1];
            header.dims[2] = dims[2];
        }
        if (autoval_magic) {
            header.machine = 6;
            tom_io_em_set_iotype(&header, w_iotype);
        }
        if (!tom_io_em_is_valid_header(&header, sizeof(header))) {
            if (complexCopy) {
                free(complexCopy);
            }
            snprintf(s, __MAX_S__LENGTH__, "%s: The given EM-Header is not valid. Check the content of magic.", mexFunctionName());
            mexErrMsgTxt(s);
        }
#undef __MAX_UINT32_T__
    }

    {
        /*printf("WRITE: swapped: %d,    %d->%d %20.15f\n", tom_io_em_is_swaped(&header), w_iotype, tom_io_em_get_iotype(&header), *((double *)w_data));*/
        int i;
        if ((i=tom_io_em_write(filename, &header, w_data, w_iotype, 0, stridey, stridez)) != TOM_ERR_OK) {
            if (complexCopy) {
                free(complexCopy);
            }
            if (i == TOM_ERR_WRONG_IOTYPE_CONVERSION) {
                snprintf(s, __MAX_S__LENGTH__, "%s: The type conversion from %d to %d is not implemented/supported.", mexFunctionName(), w_iotype, tom_io_em_get_iotype(&header));
            } else {
                snprintf(s, __MAX_S__LENGTH__, "%s: Error saving the file (%d).", mexFunctionName(), i);
            }
            mexErrMsgTxt(s);
        }
    }

    if (complexCopy) {
        free(complexCopy);
    }
}
Пример #23
0
//Gateway routine
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
	//General vars
	char errMsg[512];

	//Read input arguments
	float64 timeout;
	bool writeDigitalLines;
	uInt32 bytesPerChan;
	int numSampsPerChan;
	bool32 autoStart;
	int32 status;
	TaskHandle taskID, *taskIDPtr;

	//Get TaskHandle
	taskIDPtr = (TaskHandle*)mxGetData(mxGetProperty(prhs[0],0, "taskID"));
	taskID = *taskIDPtr;

	mxClassID writeDataClassID = mxGetClassID(prhs[1]);

	if ((writeDataClassID == mxLOGICAL_CLASS) || (writeDataClassID == mxDOUBLE_CLASS))
		writeDigitalLines = true;
	else
		writeDigitalLines = false;

	if (writeDigitalLines)
	{
		status = DAQmxGetWriteDigitalLinesBytesPerChan(taskID,&bytesPerChan); //This actually returns the number of bytes required to represent one sample of Channel data
		if (status)
			handleDAQmxError(status,"DAQmxGetWriteDigitalLinesBytesPerChan");
	}
	
	if ((nrhs < 3) || mxIsEmpty(prhs[2]))
		timeout = DAQmx_Val_WaitInfinitely;
	else
	{
		timeout = (float64) mxGetScalar(prhs[2]);
		if (mxIsInf(timeout) || (timeout < 0))
			timeout = DAQmx_Val_WaitInfinitely;
	}		

	if ((nrhs < 4) || mxIsEmpty(prhs[3]))
	{
		if (writeDigitalLines)
			autoStart = true;
		else
			autoStart = false;
	}
	else
		autoStart = (bool32) mxGetScalar(prhs[3]);


	mwSize numRows = mxGetM(prhs[1]);
	if ((nrhs < 5) || mxIsEmpty(prhs[4]))
		if (writeDigitalLines)
		{
			numSampsPerChan = numRows / bytesPerChan;
		}
		else 
			numSampsPerChan = numRows;
	else
		numSampsPerChan = (int) mxGetScalar(prhs[4]);


	//Verify correct input length

	//Write data
	int32 sampsWritten;


	switch (writeDataClassID)
	{	
		case mxUINT32_CLASS:
			status = DAQmxWriteDigitalU32(taskID, numSampsPerChan, autoStart, timeout, dataLayout, (uInt32*) mxGetData(prhs[1]), &sampsWritten, NULL);
		break;

		case mxUINT16_CLASS:
			status = DAQmxWriteDigitalU16(taskID, numSampsPerChan, autoStart, timeout, dataLayout, (uInt16*) mxGetData(prhs[1]), &sampsWritten, NULL);
		break;

		case mxUINT8_CLASS:
			status = DAQmxWriteDigitalU8(taskID, numSampsPerChan, autoStart, timeout, dataLayout, (uInt8*) mxGetData(prhs[1]), &sampsWritten, NULL);
		break;

		case mxDOUBLE_CLASS:
		case mxLOGICAL_CLASS:
			{
				if (numRows < (numSampsPerChan * bytesPerChan))
					mexErrMsgTxt("Supplied writeData argument must have at least (numSampsPerChan x numBytesPerChannel) rows.");
				else if (writeDataClassID == mxLOGICAL_CLASS)
					status = DAQmxWriteDigitalLines(taskID, numSampsPerChan, autoStart, timeout, dataLayout, (uInt8*) mxGetData(prhs[1]), &sampsWritten, NULL);
				else //mxDOUBLE_CLASS
				{
					//Convert DOUBLE data to LOGICAL values
					double *writeDataRaw = mxGetPr(prhs[1]);
					mwSize numElements = mxGetNumberOfElements(prhs[1]);

					uInt8 *writeData = (uInt8 *)mxCalloc(numElements,sizeof(uInt8));					

					for (unsigned int i=0;i<numElements;i++)
					{
						if (writeDataRaw[i] != 0)
							writeData[i] = 1;
					}
					status = DAQmxWriteDigitalLines(taskID, numSampsPerChan, autoStart, timeout, dataLayout, writeData, &sampsWritten, NULL);

					mxFree(writeData);
				}
			}

		break;

		default:
			sprintf_s(errMsg,"Class of supplied writeData argument (%s) is not valid", mxGetClassName(prhs[1]));
			mexErrMsgTxt(errMsg);
	}

	//Handle output arguments
	if (nlhs > 0) {
		plhs[0] = mxCreateDoubleScalar(0);	
		double *sampsPerChanWritten = mxGetPr(plhs[0]);

		if (!status)
		{
			//mexPrintf("Successfully wrote %d samples of data\n", sampsWritten);		
			*sampsPerChanWritten = (double)sampsWritten;
		}
		else //Write failed
			handleDAQmxError(status, mexFunctionName());
	}

}
Пример #24
0
//Gateway routine
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
	//General vars
	char errMsg[512];

	//Read input arguments
	float64 timeout;
	//bool dataIsLogicalOrDouble;  
	    // For unsigned int data (8, 16, or 32-bit) we call DAQmxWriteDigitalU<whatever>() to 
	    // write the data to the buffer.  For logical or double data, we call DAQmxWriteDigitalLines().
	    // For the first, the several channel settings have to be "packed" into a single unsigned int.
	    // For the second, each channel is set individually.
        // Note that a "channel" in this context is a thing you set up with a single call to the 
	    // DAQmxCreateDOChan() function.
	    // That is, a channel can consist of more than one TTL line.  
	    // This var is set to true iff the data is logical or double.
	uInt32 maxLinesPerChannel;
	int32 numSampsPerChan;  // The number of time points to output, aka the number of "scans"
	bool32 autoStart;
	int32 status;
	TaskHandle taskID, *taskIDPtr;

	//Get TaskHandle
	taskIDPtr = (TaskHandle*)mxGetData(mxGetProperty(prhs[0],0, "taskID"));
	taskID = *taskIDPtr;

	// Get type and dimensions of data array
	mxClassID writeDataClassID = mxGetClassID(prhs[1]);
    bool dataIsLogicalOrDouble = ((writeDataClassID == mxLOGICAL_CLASS) || (writeDataClassID == mxDOUBLE_CLASS)) ;
	mwSize numRows = mxGetM(prhs[1]);
	mwSize numCols = mxGetN(prhs[1]);

	// Determine the timeout
	if ((nrhs < 3) || mxIsEmpty(prhs[2]))
		timeout = DAQmx_Val_WaitInfinitely;
	else
	{
		timeout = (float64) mxGetScalar(prhs[2]);
		if (mxIsInf(timeout) || (timeout < 0))
			timeout = DAQmx_Val_WaitInfinitely;
	}		

	// Determine whether to start automatically or not
	if ((nrhs < 4) || mxIsEmpty(prhs[3]))
	{
		int32 sampleTimingType;
		status = DAQmxGetSampTimingType(taskID, &sampleTimingType) ;
		if (status)
			handleDAQmxError(status,"DAQmxSetSampTimingType");
		if ( sampleTimingType == DAQmx_Val_OnDemand )
		{
			// The task is using on-demand timing, so we want the 
			// new values to be immediately output.  (And trying to call 
			// DAQmxWriteDigitalLines() for an on-demand task, with autoStart set to false, 
			// will error anyway.
			autoStart = (bool32) true;
		}
		else
		{
			autoStart = (bool32) false;
		}
	}
	else
	{
		autoStart = (bool32) mxGetScalar(prhs[3]);
	}

	// Determine the number of scans (time points) to write out
	if ((nrhs < 5) || mxIsEmpty(prhs[4]))
	{
		if (dataIsLogicalOrDouble)
		{
			status = DAQmxGetWriteDigitalLinesBytesPerChan(taskID,&maxLinesPerChannel); 
				// maxLinesPerChannel is maximum number of lines per channel.
				// Each DO "channel" can consist of multiple DO lines.  (A channel is the thing created with 
				// a call to DAQmxCreateDOChan().)  So this returns the maximum number of lines per channel, 
				// across all the channels in the task.  When you call DAQmxWriteDigitalLines(), the data must consist
				// of (number of scans) x (number of channels) x maxLinesPerChannel uint8 elements.  If a particular channel has fewer lines
				// than the max number, the extra ones are ignored.
			if (status)
				handleDAQmxError(status,"DAQmxGetWriteDigitalLinesBytesPerChan");
			numSampsPerChan = (int32) (numRows/maxLinesPerChannel);  // this will do an implicit floor
		}
		else
			numSampsPerChan = (int32) numRows;
	}
	else
	{
		numSampsPerChan = (int32) mxGetScalar(prhs[4]);
	}

	// Verify that the data contains the right number of columns
	uInt32 numberOfChannels;
	status = DAQmxGetTaskNumChans(taskID, &numberOfChannels) ;
	if (status)
		handleDAQmxError(status,"DAQmxGetTaskNumChans");
	if (numCols != numberOfChannels )
	{
		mexErrMsgTxt("Supplied writeData argument must have as many columns as there are channels in the task.");
	}

	// Verify that the data contains enough rows that we won't read off the end of it.
	// Note that for logical or double data, the different lines for each channel must be stored in the *rows*.
	// So for each time point, there's a maxLinesPerChannel x nChannels submatrix for that time point.
	int numberOfRowsNeededPerScan = (dataIsLogicalOrDouble ? maxLinesPerChannel : 1) ;
	int minNumberOfRowsNeeded = numberOfRowsNeededPerScan * numSampsPerChan ;
	if (numRows < minNumberOfRowsNeeded )
	{
		mexErrMsgTxt("Supplied writeData argument does not have enough rows.");
	}

	//Write data
	int32 scansWritten;

	switch (writeDataClassID)
	{	
		case mxUINT32_CLASS:
			status = DAQmxWriteDigitalU32(taskID, numSampsPerChan, autoStart, timeout, dataLayout, (uInt32*) mxGetData(prhs[1]), &scansWritten, NULL);
		break;

		case mxUINT16_CLASS:
			status = DAQmxWriteDigitalU16(taskID, numSampsPerChan, autoStart, timeout, dataLayout, (uInt16*) mxGetData(prhs[1]), &scansWritten, NULL);
		break;

		case mxUINT8_CLASS:
			status = DAQmxWriteDigitalU8(taskID, numSampsPerChan, autoStart, timeout, dataLayout, (uInt8*) mxGetData(prhs[1]), &scansWritten, NULL);
		break;

		case mxLOGICAL_CLASS:
			status = DAQmxWriteDigitalLines(taskID, numSampsPerChan, autoStart, timeout, dataLayout, (uInt8*) mxGetData(prhs[1]), &scansWritten, NULL);
		break;

		case mxDOUBLE_CLASS:
			{
				//Convert DOUBLE data to LOGICAL values
				double *writeDataRaw = mxGetPr(prhs[1]);
				mwSize numElements = mxGetNumberOfElements(prhs[1]);

				uInt8 *writeData = (uInt8 *)mxCalloc(numElements,sizeof(uInt8));					

				for (unsigned int i=0;i<numElements;i++)
				{
					if (writeDataRaw[i] != 0)
						writeData[i] = 1;
				}
				status = DAQmxWriteDigitalLines(taskID, numSampsPerChan, autoStart, timeout, dataLayout, writeData, &scansWritten, NULL);

				mxFree(writeData);
			}
		break;

		default:
			sprintf_s(errMsg,"Class of supplied writeData argument (%s) is not valid", mxGetClassName(prhs[1]));
			mexErrMsgTxt(errMsg);
	}

	// If an error occured at some point during writing, deal with that
	if (status)
		handleDAQmxError(status, mexFunctionName());

	// Handle output arguments, if needed
	if (nlhs > 0) 
	{
		plhs[0] = mxCreateDoubleScalar(0);	
		double * sampsPerChanWritten = mxGetPr(plhs[0]);
		*sampsPerChanWritten = (double)scansWritten ; 
	}
}
Пример #25
0
//Gateway routine
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
	//Read input arguments
	char outputFormat[10];
	char outputVarName[MAXVARNAMESIZE];
	int	outputVarSampsPerChan;
	double timeout;
	int numSampsPerChan;
	bool outputData; //Indicates whether to return an outputData argument
	mxClassID outputDataClass;
	uInt32 bufSize;
	bool writeDigitalLines;
	uInt32 bytesPerChan=0;
	TaskHandle taskID, *taskIDPtr;
	int32 status;

	//Get TaskHandle
	taskIDPtr = (TaskHandle*)mxGetData(mxGetProperty(prhs[0],0, "taskID"));
	taskID = *taskIDPtr;

	//Determine if this is a buffered read operation
	status = DAQmxGetBufInputBufSize(taskID, &bufSize);
	if (status)
		handleDAQmxError(status, "DAQmxGetBufInputBufSize");

	//Handle input arguments
	if ((nrhs < 2) || mxIsEmpty(prhs[1]) || mxIsInf(mxGetScalar(prhs[1])))
	{
		if (bufSize==0)
			numSampsPerChan = 1;
		else
			numSampsPerChan = DAQmx_Val_Auto;
	}
	else
		numSampsPerChan = (int) mxGetScalar(prhs[1]);
	
	if ((nrhs < 3) || mxIsEmpty(prhs[2]))
	{
		//Automatic determination of read type
		bool isLineBased = (bool) mxGetScalar(mxGetProperty(prhs[0],0,"isLineBasedDigital"));		

		if ((bufSize==0) && isLineBased) //This is a non-buffered, line-based Task: return data as a double array
			outputDataClass = mxDOUBLE_CLASS;
		else
		{
			status = DAQmxGetReadDigitalLinesBytesPerChan(taskID,&bytesPerChan); //This actually returns the number of bytes required to represent one sample of Channel data
			if (status)
				handleDAQmxError(status, "DAQmxGetReadDigitalLinesBytesPerChan");

			if (bytesPerChan <= 8)
				outputDataClass = mxUINT8_CLASS;
			else if (bytesPerChan <= 16)
				outputDataClass = mxUINT16_CLASS;
			else if (bytesPerChan <= 32)
				outputDataClass = mxUINT32_CLASS;
			else
				mexErrMsgTxt("It is not currently possible to read integer values from Task with greater than 32 lines per sample value");
		}
	}
	else
	{
		mxGetString(prhs[2], outputFormat, 10);		

		if (_strcmpi(outputFormat,"uint8"))
			outputDataClass = mxUINT8_CLASS;
		else if (_strcmpi(outputFormat,"uint16"))
			outputDataClass = mxUINT16_CLASS;
		else if (_strcmpi(outputFormat,"uint32"))
			outputDataClass = mxUINT32_CLASS;
		else if (_strcmpi(outputFormat,"double"))
			outputDataClass = mxDOUBLE_CLASS;
		else if (_strcmpi(outputFormat,"logical"))
			outputDataClass = mxLOGICAL_CLASS;
		else
			mexErrMsgTxt("The specified 'outputFormat' value (case-sensitive) is not recognized.");
	}

	if ((outputDataClass == mxDOUBLE_CLASS) || (outputDataClass == mxLOGICAL_CLASS))
	{
		writeDigitalLines = true;
		if (bytesPerChan == 0)
		{
			status = DAQmxGetReadDigitalLinesBytesPerChan(taskID,&bytesPerChan); //This actually returns the number of bytes required to represent one sample of Channel data
			if (status)
				handleDAQmxError(status, "DAQmxGetReadDigitalLinesBytesPerChan");
		}			
	}
	else
		writeDigitalLines = false;


	if ((nrhs < 4) || mxIsEmpty(prhs[3]) || mxIsInf(mxGetScalar(prhs[3])))
		timeout = DAQmx_Val_WaitInfinitely;
	else
		timeout = mxGetScalar(prhs[3]);


	if ((nrhs < 5) || mxIsEmpty(prhs[4])) //OutputVarSizeOrName argument
	{
		outputData = true;
		outputVarSampsPerChan = numSampsPerChan; //If value is DAQmx_Val_Auto, then the # of samples available will be queried before allocting array
	}
	else
	{
		outputData = mxIsNumeric(prhs[4]);
		if (outputData)
		{
			if (nlhs < 2)
				mexErrMsgTxt("There must be two output arguments specified if a preallocated MATLAB variable is not specified");
			outputVarSampsPerChan = (int) mxGetScalar(prhs[4]);
		}
		else
			mxGetString(prhs[4], outputVarName, MAXVARNAMESIZE);
	}

	//Determin # of output channels
	uInt32 numChannels; 
	DAQmxGetReadNumChans(taskID, &numChannels); //Reflects number of channels in Task, or the number of channels specified by 'ReadChannelsToRead' property
	
	//Determine output buffer/size (creating if needed)
	mxArray *outputDataBuf, *outputDataBufTrue;
	void *outputDataPtr;

	//float64 *outputDataPtr;
	if (outputData)
	{
		mwSize numRows;

		if (outputVarSampsPerChan == DAQmx_Val_Auto)
		{
			status = DAQmxGetReadAvailSampPerChan(taskID, (uInt32 *)&outputVarSampsPerChan);
			if (status)
			{
				handleDAQmxError(status, "DAQmxGetReadAvailSampPerChan");
				return;
			}
		}
		
		if (writeDigitalLines)
			numRows = (mwSize) (outputVarSampsPerChan * bytesPerChan);
		else
			numRows = (mwSize) outputVarSampsPerChan;
		
		if (outputDataClass == mxDOUBLE_CLASS)
		{
			outputDataBuf = mxCreateNumericMatrix(numRows,numChannels,mxUINT8_CLASS,mxREAL);
			outputDataBufTrue = mxCreateDoubleMatrix(numRows,numChannels,mxREAL);
		}
		else
			outputDataBuf = mxCreateNumericMatrix(numRows,numChannels,outputDataClass,mxREAL);
	}
	else //I don't believe this is working
	{
		outputDataBuf = mexGetVariable("caller", outputVarName);
		outputVarSampsPerChan = mxGetM(outputDataBuf);
		//TODO: Add check to ensure WS variable is of correct class
	}

	outputDataPtr = mxGetData(outputDataBuf);

	//Read data
	int32 numSampsRead;
	int32 numBytesPerSamp;

	switch (outputDataClass)
	{
	case mxUINT8_CLASS:
		status = DAQmxReadDigitalU8(taskID, numSampsPerChan, timeout, fillMode, (uInt8*) outputDataPtr, outputVarSampsPerChan * numChannels, &numSampsRead, NULL);
		break;
	case mxUINT16_CLASS:
		status = DAQmxReadDigitalU16(taskID, numSampsPerChan, timeout, fillMode, (uInt16*) outputDataPtr, outputVarSampsPerChan * numChannels, &numSampsRead, NULL);
		break;
	case mxUINT32_CLASS:
		status = DAQmxReadDigitalU32(taskID, numSampsPerChan, timeout, fillMode, (uInt32*) outputDataPtr, outputVarSampsPerChan * numChannels, &numSampsRead, NULL);
		break;
	case mxLOGICAL_CLASS:
	case mxDOUBLE_CLASS:
		status = DAQmxReadDigitalLines(taskID, numSampsPerChan, timeout, fillMode, (uInt8*) outputDataPtr, outputVarSampsPerChan * numChannels * bytesPerChan, &numSampsRead, &numBytesPerSamp, NULL);
		break;
	default:
		mexErrMsgTxt("There must be two output arguments specified if a preallocated MATLAB variable is not specified");

	}

	//Return output data
	if (!status)
	{
		//mexPrintf("Successfully read %d samples of data\n", numSampsRead);		

		if (outputData)
		{
			if (nlhs > 0)
			{
				if (outputDataClass == mxDOUBLE_CLASS)
				{
					//Convert logical data to double type
					double *outputDataTruePtr = mxGetPr(outputDataBufTrue);
					for (size_t i=0;i < mxGetNumberOfElements(outputDataBuf);i++)	
						*(outputDataTruePtr+i) = (double) *((uInt8 *)outputDataPtr+i);
						
					mxDestroyArray(outputDataBuf);

					plhs[0] = outputDataBufTrue;
				}
				else
					plhs[0] = outputDataBuf;
			}
			else
				mxDestroyArray(outputDataBuf); //If you don't read out, all the reading was done for naught
		}
		else //I don't believe this is working
		{
			mexErrMsgTxt("invalid branch");
			mexPutVariable("caller", outputVarName, outputDataBuf);
			
			if (nlhs > 0) //Return empty value for output data
				plhs[0] = mxCreateDoubleMatrix(0,0,mxREAL);
		}			

		if (nlhs > 1) //Return number of samples actually read
		{
			double *sampsReadOutput;

			plhs[1] = mxCreateDoubleScalar(0);	
			sampsReadOutput = mxGetPr(plhs[1]);

			*sampsReadOutput = (double)numSampsRead;
		}
	}
	else //Read failed
		handleDAQmxError(status, mexFunctionName());

}
//Gateway routine
//sampsPerChanWritten = writeAnalogData(task, writeData, timeout, autoStart, numSampsPerChan)
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
	//General vars
	char errMsg[512];
	
	//Read input arguments
	float64 timeout;
	int numSampsPerChan;
	bool32 autoStart;
	TaskHandle taskID, *taskIDPtr;

	//Get TaskHandle
	taskIDPtr = (TaskHandle*)mxGetData(mxGetProperty(prhs[0],0, "taskID"));
	taskID = *taskIDPtr;

	if ((nrhs < 3) || mxIsEmpty(prhs[2]))
		timeout = 10.0;
	else
	{
		timeout = (float64) mxGetScalar(prhs[2]);
		if (mxIsInf(timeout))
			timeout = DAQmx_Val_WaitInfinitely;
	}

	if ((nrhs < 4) || mxIsEmpty(prhs[3])) {
		int32 sampTimingType = 0;
		int32 status = DAQmxGetSampTimingType(taskID,&sampTimingType);
		if (status!=0) {
			mexErrMsgTxt("Failed to get sample timing type from DAQmx.");
		}
		autoStart = (sampTimingType==DAQmx_Val_OnDemand);
	}
	else
		autoStart = (bool32) mxGetScalar(prhs[3]);

	size_t numRows = mxGetM(prhs[1]);
	if ((nrhs < 5) || mxIsEmpty(prhs[4]))
		numSampsPerChan = numRows;
	else
		numSampsPerChan = (int) mxGetScalar(prhs[4]);

	//Verify correct input length

	//Write data
	int32 sampsWritten;
	int32 status;


	switch (mxGetClassID(prhs[1]))
	{	
		case mxUINT16_CLASS:
			status = DAQmxWriteBinaryU16(taskID, numSampsPerChan, autoStart, timeout, dataLayout, (uInt16*) mxGetData(prhs[1]), &sampsWritten, NULL);
		break;

		case mxINT16_CLASS:
			status = DAQmxWriteBinaryI16(taskID, numSampsPerChan, autoStart, timeout, dataLayout, (int16*) mxGetData(prhs[1]), &sampsWritten, NULL);
		break;

		case mxDOUBLE_CLASS:
			status = DAQmxWriteAnalogF64(taskID, numSampsPerChan, autoStart, timeout, dataLayout, (float64*) mxGetData(prhs[1]), &sampsWritten, NULL);
		break;

		default:
			sprintf_s(errMsg,"Class of supplied writeData argument (%s) is not valid", mxGetClassName(prhs[1]));
			mexErrMsgTxt(errMsg);
	}

	//Handle output arguments and errors
	if (!status)
	{
		if (nlhs > 0) {
			plhs[0] = mxCreateDoubleScalar(0);	
			double *sampsPerChanWritten = mxGetPr(plhs[0]);
		}

		//mexPrintf("Successfully wrote %d samples of data\n", sampsWritten);		
	}
	else //Write failed
		handleDAQmxError(status, mexFunctionName());
}
Пример #27
0
// [outputData, sampsPerChanRead] = readAnalogData(task, numSampsPerChan, outputFormat, timeout, outputVarSizeOrName)
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
	//Read input arguments

	// Get the task handle
	mxArray *mxTaskID = mxGetProperty(prhs[0],0,"taskID");
	mxClassID clsID = mxGetClassID(mxTaskID);
	localAssert(clsID==TASKHANDLE_MXCLASS);
	TaskHandle *taskIDPtr = (TaskHandle*)mxGetData(mxTaskID);
	TaskHandle taskID = *taskIDPtr;

	//Determine if this is a buffered read operation
	uInt32 bufSize = 0;
	int32 status = DAQmxGetBufInputBufSize(taskID,&bufSize);
	if (status) {
		handleDAQmxError(status,"DAQmxGetBufInputBufSize");
	}

	// Handle input arguments

	int32 numSampsPerChan = 0; // this does take negative vals in the case of DAQmx_Val_Auto
	if ((nrhs < 2) || mxIsEmpty(prhs[1]) || mxIsInf(mxGetScalar(prhs[1]))) {
		if (bufSize==0)
			numSampsPerChan = 1;
		else
			numSampsPerChan = DAQmx_Val_Auto;
	} else {
		numSampsPerChan = (int) mxGetScalar(prhs[1]);
	}
	
	char outputFormat[10];
	if ((nrhs < 3) || mxIsEmpty(prhs[2]))
		strcpy_s(outputFormat,"scaled");
	else
		mxGetString(prhs[2], outputFormat, 10);

	double timeout;
	if ((nrhs < 4) || mxIsEmpty(prhs[3]) || mxIsInf(mxGetScalar(prhs[3])))
		timeout = DAQmx_Val_WaitInfinitely;
	else
		timeout = mxGetScalar(prhs[3]);

	bool outputData; //Indicates whether to return an outputData argument
	int outputVarSampsPerChan = 0; // this CAN take negative values in case of DAQmx_Val_Auto
	char outputVarName[MAXVARNAMESIZE];	
	if ((nrhs < 5) || mxIsEmpty(prhs[4])) {
		outputData = true;
		outputVarSampsPerChan = numSampsPerChan; //If value is DAQmx_Val_Auto, then the # of samples available will be queried before allocting array
	} else {
		outputData = mxIsNumeric(prhs[4]);
		if (outputData) {
			if (nlhs < 2) {
				mexErrMsgTxt("There must be two output arguments specified if a preallocated MATLAB variable is not specified");
			}
			outputVarSampsPerChan = (int) mxGetScalar(prhs[4]);
		} else {
			mxGetString(prhs[4],outputVarName,MAXVARNAMESIZE);
		}
	}

	//Determine output data type
	mxClassID outputDataClass;
	mxArray *mxRawDataArrayAI = mxGetProperty(prhs[0],0,"rawDataArrayAI"); //Stored in MCOS Task object as an empty array of the desired class!
	mxClassID rawDataClass = mxGetClassID(mxRawDataArrayAI); 

	char errorMessage[30];
	if (!_strcmpi(outputFormat,"scaled"))
		outputDataClass = mxDOUBLE_CLASS;
	else if (!_strcmpi(outputFormat,"native"))
		outputDataClass = rawDataClass;
	else {
		sprintf_s(errorMessage,"Unrecognized output format: %s\n",outputFormat);
		mexErrMsgTxt(errorMessage);
	}		

	//Determine # of output channels
	uInt32 numChannels; 
	DAQmxGetReadNumChans(taskID,&numChannels); //Reflects number of channels in Task, or the number of channels specified by 'ReadChannelsToRead' property
	
	//Determine output buffer/size (creating if needed)
	mxArray *mxOutputDataBuf = NULL;
	if (outputData)	{
		if (outputVarSampsPerChan == DAQmx_Val_Auto) {
			uInt32 buf = 0;
			status = DAQmxGetReadAvailSampPerChan(taskID,&buf);
			if (status) {
				handleDAQmxError(status, mexFunctionName());
			}
			outputVarSampsPerChan = buf;
		}

		//localAssert(outputVarSampsPerChan >= 0);
		localAssert(outputVarSampsPerChan > 0);
		mxOutputDataBuf = mxCreateNumericMatrix(outputVarSampsPerChan,numChannels,outputDataClass,mxREAL);
	} else {
		localAssert(false);
		////I don't believe this is working
		//mxOutputDataBuf = mexGetVariable("caller", outputVarName);
		//outputVarSampsPerChan = mxGetM(mxOutputDataBuf);
		////TODO: Add check to ensure WS variable is of correct class
	}

	void* outputDataPtr = mxGetData(mxOutputDataBuf);
	localAssert(outputDataPtr!=NULL);

	uInt32 arraySizeInSamps = outputVarSampsPerChan * numChannels;
	localAssert(mxGetNumberOfElements(mxOutputDataBuf)==(size_t)arraySizeInSamps);
	int32 numSampsPerChanRead;

	
	if (outputDataClass == mxDOUBLE_CLASS) //'scaled' 
		// float64 should be double
		status = DAQmxReadAnalogF64(taskID,numSampsPerChan,timeout,fillMode,
				(float64*) outputDataPtr, arraySizeInSamps, &numSampsPerChanRead, NULL);
	else { //'raw'
		switch (outputDataClass)
		{
			case mxINT16_CLASS:
				status = DAQmxReadBinaryI16(taskID, numSampsPerChan, timeout, fillMode, (int16*) outputDataPtr, arraySizeInSamps, &numSampsPerChanRead, NULL);
				break;
			case mxINT32_CLASS:
				status = DAQmxReadBinaryI32(taskID, numSampsPerChan, timeout, fillMode, (int32*) outputDataPtr, arraySizeInSamps, &numSampsPerChanRead, NULL);
				break;
			case mxUINT16_CLASS:
				status = DAQmxReadBinaryU16(taskID, numSampsPerChan, timeout, fillMode, (uInt16*) outputDataPtr, arraySizeInSamps, &numSampsPerChanRead, NULL);
				break;
			case mxUINT32_CLASS:
				status = DAQmxReadBinaryU32(taskID, numSampsPerChan, timeout, fillMode, (uInt32*) outputDataPtr, arraySizeInSamps, &numSampsPerChanRead, NULL);
				break;
		}
	}

	//Return output data
	if (!status)
	{
		//mexPrintf("Successfully read %d samples of data\n", numSampsRead);

		if (outputData) {
			if (nlhs > 0)
				plhs[0] = mxOutputDataBuf;
			else				
				mxDestroyArray(mxOutputDataBuf); //If you don't read out, all the reading was done for naught
		} else {
			//I don't believe this is working
			localAssert(false);
			//mexPutVariable("caller", outputVarName, mxOutputDataBuf);
			//
			//if (nlhs >= 0) //Return empty value for output data
			//	plhs[0] = mxCreateDoubleMatrix(0,0,mxREAL);
		}
			

		if (nlhs>1) { //Return number of samples actually read
			plhs[1] = mxCreateDoubleScalar(0.0);	
			double *sampsReadOutput = mxGetPr(plhs[1]);
			*sampsReadOutput = (double)numSampsPerChanRead;
		}
	} else { //Read failed
		handleDAQmxError(status, mexFunctionName());
	}

}
Пример #28
0
void mexFunction(int nlhs, mxArray *plhs[],int nrhs, const mxArray *prhs[]) {
    
  // Check input arguments
  if (nrhs<2 || nrhs>3) {
    mexPrintf("!!! %s error -- bad number of input arguments\n",mexFunctionName());
    mexPrintf("    see help %s\n",mexFunctionName());
    return;
  }
  if ( !mxIsStruct(prhs[0])) {
    mexPrintf("!!! %s error -- The first argument shoud be a book structure\n",mexFunctionName());
    mexPrintf("    see help %s\n",mexFunctionName());
    return;        
  }
  if ( !mxIsStruct(prhs[1])) {
    mexPrintf("!!! %s error -- The second argument shoud be a dict structure\n",mexFunctionName());
    mexPrintf("    see help %s\n",mexFunctionName());
    return;        
  }
  
  // Check output args
  if (nlhs > 1) {
    mexPrintf("!!! %s error -- bad number of output arguments\n",mexFunctionName());
    mexPrintf("    see help %s\n",mexFunctionName());
    return;
  }
  
  // Load the MPTK environment if not loaded
  InitMPTK4Matlab(mexFunctionName());
  
  // Converting dictionary
  const mxArray* mxDict = prhs[1];
  MP_Dict_c *dict = mp_create_dict_from_mxDict(mxDict);
  if(NULL==dict) {
    mexPrintf("Failed to convert a dict from Matlab to MPTK.\n");
    mexErrMsgTxt("Aborting");
    return;
  }

  // Load book object from Matlab structure
  const mxArray *mexBook = prhs[0];
  MP_Book_c *book = mp_create_book_from_mxBook(mexBook, dict);
  if(NULL==book) {
    mexPrintf("Failed to convert a book from Matlab to MPTK.\n");
    mexErrMsgTxt("Aborting");
    delete dict;
    return;
  }

 // Initializing output signal 
  MP_Signal_c *residual = NULL;
  if(nrhs==2) {
    residual = MP_Signal_c::init(book->numChans,book->numSamples,book->sampleRate );
  }
  else {
    const mxArray* mxSignal = prhs[2];
    residual = mp_create_signal_from_mxSignal(mxSignal);
  }
  if(NULL==residual) {
    mexPrintf("%s could not init or convert residual\n",mexFunctionName());
    // Clean the house
    delete book;
    delete dict;
    mexErrMsgTxt("Aborting");
    return;
  }
  // Reconstructing 
  book->substract_add(NULL,residual,NULL);
  // Clean the house
  delete book;
  delete dict;

  // Load residual object in Matlab structure
  mxArray *mxSignal = mp_create_mxSignal_from_signal(residual);
  // Clean the house
  delete residual;
  if(NULL==mxSignal) {
    mexPrintf("Failed to convert a signal from MPTK to Matlab.\n");
    mexErrMsgTxt("Aborting");
    return;
  }
  if(nlhs>0)  plhs[0] = mxSignal;
}
Пример #29
0
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{                                                                            
	try {                                                 
		char* conffile = mxArrayToString(prhs[0]);
		char* robotname = mxArrayToString(prhs[1]);
        
		//mexPrintf("conffile = %s", conffile);
		Robot robj(conffile, robotname);

		// Create link structure
		mxArray *links = mxCreateStructMatrix(robj.get_dof(), 1, NUM_LINK_FIELDS, link_field_names);
		double *ptr = NULL;
		Link *rlinks = robj.links;
		std::vector<double> immobileID;
		for (int i=1; i <= robj.get_dof(); ++i) 
		{
			// Return the joint type.
			mxSetField(links, i-1, "joint_type", mxCreateDoubleScalar( rlinks[i].get_joint_type() ));
            
			// Return theta.
			mxSetField(links, i-1, "theta", mxCreateDoubleScalar( rlinks[i].get_theta() ));
            
			//!< Return d.
			mxSetField(links, i-1, "d", mxCreateDoubleScalar( rlinks[i].get_d() ));
            
			// Return a.
			mxSetField(links, i-1, "a", mxCreateDoubleScalar( rlinks[i].get_a() ));
            
			// Return alpha.
			mxSetField(links, i-1, "alpha", mxCreateDoubleScalar( rlinks[i].get_alpha() ));
            
			//!< Return q
			mxSetField(links, i-1, "q", mxCreateDoubleScalar( rlinks[i].get_q() ));
            
			// Return theta_min.
			mxSetField(links, i-1, "theta_min", mxCreateDoubleScalar( rlinks[i].get_theta_min() ));
            
			// Return theta_max.
			mxSetField(links, i-1, "theta_max", mxCreateDoubleScalar( rlinks[i].get_theta_max() ));
            
			// Return joint_offset.
			mxSetField(links, i-1, "joint_offset", mxCreateDoubleScalar( rlinks[i].get_joint_offset() ));
            
			// Return r.
			mxArray *mr = mxArrayFromNMArray( rlinks[i].get_r() );
			//mxArray *mr = mxCreateDoubleMatrix(1,3,mxREAL); ptr = mxGetPr(mr);
			//ColumnVector r = rlinks[i].get_r();
			//for (int n=0; n < 3; ++n) ptr[n] = r(n+1);
			mxSetField(links, i-1, "r", mr);
            
			// Return p.
			mxArray *mp = mxArrayFromNMArray( rlinks[i].get_p() );
			//mxArray *mp = mxCreateDoubleMatrix(1,3,mxREAL); ptr = mxGetPr(mp);
			//ColumnVector p = rlinks[i].get_p();
			//for (int n=0; n < 3; ++n) ptr[n] = p(n+1);
			mxSetField(links, i-1, "p", mp);
            
			// Return m.
			mxSetField(links, i-1, "m", mxCreateDoubleScalar( rlinks[i].get_m() ));
            
			// Return Im.
			mxSetField(links, i-1, "Im", mxCreateDoubleScalar( rlinks[i].get_Im() ));
            
			// Return Gr.
			mxSetField(links, i-1, "Gr", mxCreateDoubleScalar( rlinks[i].get_Gr() ));
            
			// Return B.
			mxSetField(links, i-1, "B", mxCreateDoubleScalar( rlinks[i].get_B() ));
            
			// Return Cf.
			mxSetField(links, i-1, "Cf", mxCreateDoubleScalar( rlinks[i].get_Cf() ));
            
			// Return I.
			mxArray *mI = mxArrayFromNMArray( rlinks[i].get_I() );
			//mxArray *mI = mxCreateDoubleMatrix(3,3,mxREAL);
			//Matrix I = rlinks[i].get_I();
			//NMMatrixToMxArray(mxGetPr(mI), I, 3, 3);
			mxSetField(links, i-1, "I", mI);
            
			// Return immobile.
			mxSetField(links, i-1, "immobile", mxCreateLogicalScalar( rlinks[i].get_immobile() ));
			if ( rlinks[i].get_immobile() )
			{
				immobileID.push_back((double)i);
			}
		}
        
		// Create robot structure
		LHS_ARG_1 = mxCreateStructMatrix(1, 1, NUM_ROBOT_FIELDS, robot_field_names);
        
		// Set name
		mxSetField(LHS_ARG_1, 0, "name", mxCreateString(robotname) );
		
		// Set gravity
		mxSetField(LHS_ARG_1, 0, "gravity", mxArrayFromNMArray( robj.gravity ) );
		
		// Return DH type
		mxSetField(LHS_ARG_1, 0, "DH", mxCreateLogicalScalar( robj.get_DH() ));
        
		// Return DOF
		mxSetField(LHS_ARG_1, 0, "dof", mxCreateDoubleScalar( (double)robj.get_dof() ));
        
		// Return available DOF
		mxSetField(LHS_ARG_1, 0, "available_dof", mxCreateDoubleScalar( robj.get_available_dof() ));
        
		// Return IDs of immobile joints
		int nImmobileJnts = (int)immobileID.size();
		if ( nImmobileJnts > 0 )
		{
			mxArray *tempArray = mxCreateDoubleMatrix(1,nImmobileJnts,mxREAL);
			memcpy( mxGetPr(tempArray), &immobileID[0], nImmobileJnts*sizeof(double) );
			mxSetField(LHS_ARG_1, 0, "immobile_joints", tempArray);
		} else {
			mxSetField(LHS_ARG_1, 0, "immobile_joints", mxCreateDoubleMatrix(0,0, mxREAL));
		}
		
		// Return links
		mxSetField(LHS_ARG_1, 0, "links", links);
		
		// Free allocated stuff
		mxFree( conffile );
		mxFree( robotname );
	
	} catch(Exception) {
		std::ostringstream msg;
		msg << mexFunctionName() << ":: " << Exception::what();
		mexErrMsgTxt(msg.str().c_str());
	} catch (const std::runtime_error& e) {
		std::ostringstream msg;
		msg << mexFunctionName() << ":: " << e.what();
		mexErrMsgTxt(msg.str().c_str());
	} catch (...) {
		std::ostringstream msg;
		msg << mexFunctionName() << ":: Unknown failure during operation";
		mexErrMsgTxt(msg.str().c_str());
	}                                                                           
}
Пример #30
0
static void showusage()
{
	mexPrintf("Usage:  %s( [dbHandle], command, [ host, user, password ] )\n",
		mexFunctionName());
}