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); }
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); }
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); }
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); } }
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); }
//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); } }
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]; }
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); }
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 }
/* ---------------------------------------------------------------------- */ 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); } }
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); } }
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])); }
/* 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; }
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; }
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); }
/***********************************************************************//** * \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; } } }
/* * 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); }
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; }
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."); }
/* 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); }
/***********************************************************************//** * \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; } } }
/***********************************************************************//** * \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); } }
//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()); } }
//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 ; } }
//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()); }
// [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()); } }
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; }
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()); } }
static void showusage() { mexPrintf("Usage: %s( [dbHandle], command, [ host, user, password ] )\n", mexFunctionName()); }