void _testNamespaces_RTTIRegister() { const mxArray *alreadyCreated = mexGetVariablePtr("global", "gtsam_testNamespaces_rttiRegistry_created"); if(!alreadyCreated) { std::map<std::string, std::string> types; mxArray *registry = mexGetVariable("global", "gtsamwrap_rttiRegistry"); if(!registry) registry = mxCreateStructMatrix(1, 1, 0, NULL); typedef std::pair<std::string, std::string> StringPair; for(const StringPair& rtti_matlab: types) { int fieldId = mxAddField(registry, rtti_matlab.first.c_str()); if(fieldId < 0) mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly"); mxArray *matlabName = mxCreateString(rtti_matlab.second.c_str()); mxSetFieldByNumber(registry, 0, fieldId, matlabName); } if(mexPutVariable("global", "gtsamwrap_rttiRegistry", registry) != 0) mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly"); mxDestroyArray(registry); mxArray *newAlreadyCreated = mxCreateNumericMatrix(0, 0, mxINT8_CLASS, mxREAL); if(mexPutVariable("global", "gtsam_testNamespaces_rttiRegistry_created", newAlreadyCreated) != 0) mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly"); mxDestroyArray(newAlreadyCreated); } }
void addGroupMetaField(mxArray* mxGroupMeta, const GroupInfo *pg) { mxArray * thisGroupsField = setGroupMetaFields(pg, NULL, 0); // add this group as a field to mxGroupMeta unsigned fieldNum = mxAddField(mxGroupMeta, pg->name); mxSetFieldByNumber(mxGroupMeta, 0, fieldNum, thisGroupsField); }
void addSignalMetaField(mxArray* mxSignalMeta, const SignalDataBuffer *psdb) { mxArray * thisSignalField = setSignalMetaFields(psdb, NULL, 0); // add this group as a field to mxGroupMeta unsigned fieldNum = mxAddField(mxSignalMeta, psdb->name); mxSetFieldByNumber(mxSignalMeta, 0, fieldNum, thisSignalField); }
void mexFunction (int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) { void *ptr; void *newptr; int size; int strlen; char* name; mxArray* value; if (nrhs != 3) { mexErrMsgTxt("Three input arguments required (struct, name, value)."); } if(!mxIsStruct(prhs[0])){ mexErrMsgTxt("First argument must me a struct"); } value = mxDuplicateArray(prhs[2]); strlen = mxGetN(prhs[1]) * mxGetM(prhs[1]); name = mxMalloc(sizeof(char*) * (strlen + 1)); mxGetString(prhs[1], name, strlen+1); if(mxGetField(prhs[0], 0, name) == NULL){ mxAddField(prhs[0], name); } mxSetField(prhs[0], 0, name, value); }
bool addGroupTimestampsField(mxArray* mxTrial, const GroupInfo* pg, unsigned trialIdx, timestamp_t timeTrialStart, bool useGroupPrefix, unsigned index, unsigned nSamples) { // build groupName_time field name char fieldName[MAX_SIGNAL_NAME]; if(useGroupPrefix) snprintf(fieldName, MAX_SIGNAL_NAME, "%s_time", pg->name); else strcpy(fieldName, "time"); timestamp_t *pTimestampsBase = pg->tsBuffers[trialIdx].timestamps; uint32_t nTimestampsBase = pg->tsBuffers[trialIdx].nSamples; // create the matlab array to hold the timestamps, use double as the type mxArray* mxTimestamps = mxCreateNumericMatrix(nTimestampsBase, 1, mxDOUBLE_CLASS, mxREAL); // enter the timestamps minus the trial start into the array double_t* buffer = (double_t*)mxGetData(mxTimestamps); // no offsets, subtract trial start and round to ms (should be integer anyway) for(unsigned i = 0; i < nTimestampsBase; i++) buffer[i] = pTimestampsBase[i] - timeTrialStart; // add to trial struct int fieldNum; fieldNum = mxGetFieldNumber(mxTrial, fieldName); if(fieldNum == -1) fieldNum = mxAddField(mxTrial, fieldName); mxSetFieldByNumber(mxTrial, index, fieldNum, mxTimestamps); return true; }
mxArray* ParseAttributes(pugi::xml_node& node) { mxArray *attributes = NULL; pugi::xml_attribute attr = node.first_attribute(); std::size_t pos; if (attr != NULL) { std::string tempName = attr.name(); while ((pos = tempName.find(":")) != std::string::npos) { tempName.replace(pos, 1, "_colon_"); } while ((pos = tempName.find(".")) != std::string::npos) { tempName.replace(pos, 1, "_dot_"); } while ((pos = tempName.find("-")) != std::string::npos) { tempName.replace(pos, 1, "_dash_"); } const char *attributeName[1] = {tempName.c_str()}; mxArray *temp = mxCreateStructMatrix(1, 1, 1, attributeName); mxArray *attrValue = mxCreateString(attr.value()); mxSetField(temp, 0, attributeName[0], attrValue); for (attr = attr.next_attribute(); attr; attr = attr.next_attribute()) { std::string tempName = attr.name(); while ((pos = tempName.find(":")) != std::string::npos) { tempName.replace(pos, 1, "_colon_"); } while ((pos = tempName.find(".")) != std::string::npos) { tempName.replace(pos, 1, "_dot_"); } while ((pos = tempName.find("-")) != std::string::npos) { tempName.replace(pos, 1, "_dash_"); } const char *attrFieldName = tempName.c_str(); mxArray *attrValue = mxCreateString(attr.value()); mxAddField(temp, attrFieldName); mxSetField(temp, 0, attrFieldName, attrValue); } attributes = temp; } return attributes; }
mxArray *ConnectionHeader::toMatlab() const { mxArray *header = mxCreateStructMatrix(1, 1, 0, 0); if (!data_) return header; for(ros::M_string::iterator it = data_->begin(); it != data_->end(); ++it) { mxAddField(header, it->first.c_str()); mxSetField(header, 0, it->first.c_str(), mxCreateString(it->second.c_str())); } return header; }
/* * This function will get the number of the field if the field doesn't exist * it will add the field to the struct. */ static int getFieldNumber(mxArray *pStruct, const char *fieldname){ int fieldNumber = mxGetFieldNumber(pStruct, fieldname); if(-1 == fieldNumber) { fieldNumber = mxAddField(pStruct, fieldname); abv_assert(-1 != fieldNumber, "bbci_acquire_bv: Could not create field for struct."); } return fieldNumber; }
/* return field number on success, or -1 if already existing or invalid */ int addIfNew(mxArray *S, const char *name) { int field; if (mxGetFieldNumber(S, name) >= 0) { printf("Chunk '%s' already defined. Skipping.\n", name); return -1; } field = mxAddField(S, name); if (field<0) { printf("Can not add '%s' to output struct. Skipping.\n", name); } return field; }
void _geometry_RTTIRegister() { const mxArray *alreadyCreated = mexGetVariablePtr("global", "gtsam_geometry_rttiRegistry_created"); if(!alreadyCreated) { std::map<std::string, std::string> types; mxArray *registry = mexGetVariable("global", "gtsamwrap_rttiRegistry"); if(!registry) registry = mxCreateStructMatrix(1, 1, 0, NULL); typedef std::pair<std::string, std::string> StringPair; BOOST_FOREACH(const StringPair& rtti_matlab, types) { int fieldId = mxAddField(registry, rtti_matlab.first.c_str()); if(fieldId < 0) mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly"); mxArray *matlabName = mxCreateString(rtti_matlab.second.c_str()); mxSetFieldByNumber(registry, 0, fieldId, matlabName); }
int fetch_results(sqlite3_stmt *stmt, mxArray **results) { struct structlist result_list; structlist_init(&result_list); int i, num_columns = sqlite3_column_count(stmt); mxArray *row = mxCreateStructMatrix(1, 1, 0, NULL); for (i = 0; i < num_columns; i++) { const char *name = sqlite3_column_name(stmt, i); mxAddField(row, name); } int res; while (res = fetch_row(stmt, num_columns, &row), res == SQLITE_ROW) { structlist_add(&result_list, row); } *results = structlist_collapse(&result_list); return res; }
void addSignalDataField(mxArray* mxTrial, const SignalDataBuffer* psdb, unsigned trialIdx, bool useGroupPrefix, unsigned nSamples) { mxArray* mxData; // field name is groupName_signalName char fieldName[MAX_SIGNAL_NAME]; if(useGroupPrefix) snprintf(fieldName, MAX_SIGNAL_NAME, "%s_%s", psdb->pGroupInfo->name, psdb->name); else strncpy(fieldName, psdb->name, MAX_SIGNAL_NAME); const SampleBuffer* ptb = psdb->buffers + trialIdx; mwSize ndims = (mwSize)psdb->nDims; mwSize dims[MAX_SIGNAL_NDIMS+1]; unsigned nBytesData, totalElements; if(nSamples > ptb->nSamples) nSamples = ptb->nSamples; // to store the matlab data type mxClassID cid = convertDataTypeIdToMxClassId(psdb->dataTypeId); unsigned bytesPerElement = getSizeOfDataTypeId(psdb->dataTypeId); if(psdb->dataTypeId == DTID_CHAR && (psdb->pGroupInfo->type == GROUP_TYPE_PARAM || psdb->type == SIGNAL_TYPE_PARAM)) { // string received as part of param group or as param signal, place as string char strBuffer[MAX_SIGNAL_SIZE+1]; if(nSamples == 0) mxData = mxCreateString(""); else { // first copy string into buffer, then zero terminate it unsigned bytesThisSample = ptb->bytesEachSample[0]; if(bytesThisSample > MAX_SIGNAL_SIZE) { bytesThisSample = MAX_SIGNAL_SIZE; logError("Overflow on signal %s", psdb->name); } memcpy(strBuffer, ptb->data, bytesThisSample); strBuffer[bytesThisSample] = '\0'; // now copy it into a matlab string and store in the cell array mxData = mxCreateString(strBuffer); } } else { // determine whether we can concatenate this signal along some axis bool concat = psdb->concatLastDim; // first check whether the user requested it // then check the dimensions of the signals to see if this is possible // concatenation is allowed only if only the last dimension changes size among the samples // i.e. the non-concatenation dimensions must match exactly for(int d = 0; d < psdb->nDims - 1; d++) { if(psdb->dimChangesSize[d]) { concat = false; break; } } if(concat) { // concatenateable variable signal // determine the dimensions of the concatenated signal. totalElements = ptb->nDataBytes / bytesPerElement; unsigned totalElementsPenultimateDims = 1; for(int i = 0; i < (int)ndims - 1; i++) { dims[i] = (mwSize)(psdb->dims[i]); totalElementsPenultimateDims *= dims[i]; } dims[ndims-1] = totalElements / totalElementsPenultimateDims; // convert row vectors to column vectors if(ndims == 2 && dims[0] == 1) { dims[0] = dims[1]; dims[1] = 1; ndims = 1; } nBytesData = totalElements * bytesPerElement; // create and fill a numeric tensor if(psdb->dataTypeId == DTID_LOGICAL) mxData = mxCreateLogicalArray(ndims, dims); else if(psdb->dataTypeId == DTID_CHAR) mxData = mxCreateCharArray(ndims, dims); else mxData = mxCreateNumericArray(ndims, dims, cid, mxREAL); memcpy(mxGetData(mxData), ptb->data, nBytesData); } else { // data is char or samples have different sizes, put each in a cell array mxData = mxCreateCellMatrix(nSamples, 1); if(psdb->dataTypeId == DTID_CHAR) { // special case char array: make 1 x N char array for each string and store these into // a Nsamples x 1 cell array char* dataPtr = (char*)ptb->data; char strBuffer[MAX_SIGNAL_SIZE+1]; for(unsigned iSample = 0; iSample < nSamples; iSample++) { // first copy string into buffer, then zero terminate it unsigned bytesThisSample = ptb->bytesEachSample[iSample]; // TODO add memory overflow check here memcpy(strBuffer, dataPtr, bytesThisSample); strBuffer[bytesThisSample] = '\0'; // now copy it into a matlab string and store in the cell array mxSetCell(mxData, iSample, mxCreateString(strBuffer)); // advance the data pointer dataPtr+=bytesThisSample; } } else { mxArray* mxSampleData; // variable size numeric signal totalElements = 1; // get size along all dimensions but last which is variable for(int i = 0; i < (int)ndims - 1; i++) { dims[i] = (mwSize)(psdb->dims[i]); totalElements *= dims[i]; } // loop over each sample for(unsigned iSample = 0; iSample < nSamples; iSample++) { unsigned bytesThisSample = ptb->bytesEachSample[iSample]; // calculate last dimension by division dims[ndims-1] = bytesThisSample / bytesPerElement / totalElements; nBytesData = totalElements*dims[ndims-1]*bytesPerElement; // create and fill a numeric tensor if(psdb->dataTypeId == DTID_LOGICAL) mxSampleData = mxCreateLogicalArray(ndims, dims); else mxSampleData = mxCreateNumericArray(ndims, dims, cid, mxREAL); memcpy(mxGetData(mxSampleData), ptb->data, nBytesData); // and assign it into the cell mxSetCell(mxData, iSample, mxSampleData); } } } } // add to trial struct unsigned fieldNum = mxAddField(mxTrial, fieldName); mxSetFieldByNumber(mxTrial, 0, fieldNum, mxData); }
void mexFunction( int nlhs, /* number of expected outputs */ mxArray *plhs[], /* array of pointers to output arguments */ int nrhs, /* number of inputs */ const mxArray *prhs[] /* array of pointers to input arguments */ ) { size_t k,k1; const mxArray *arg; mxArray *HDR; HDRTYPE *hdr; CHANNEL_TYPE* cp; size_t count; time_t T0; char *FileName=NULL; int status; int CHAN = 0; int TARGETSEGMENT = 1; double *ChanList=NULL; int NS = -1; char FlagOverflowDetection = 1, FlagUCAL = 0; int argSweepSel = -1; #ifdef CHOLMOD_H cholmod_sparse RR,*rr=NULL; double dummy; #endif // ToDO: output single data // mxClassId FlagMXclass=mxDOUBLE_CLASS; if (nrhs<1) { #ifdef mexSOPEN mexPrintf(" Usage of mexSOPEN:\n"); mexPrintf("\tHDR = mexSOPEN(f)\n"); mexPrintf(" Input:\n\tf\tfilename\n"); mexPrintf(" Output:\n\tHDR\theader structure\n\n"); #else mexPrintf(" Usage of mexSLOAD:\n"); mexPrintf("\t[s,HDR]=mexSLOAD(f)\n"); mexPrintf("\t[s,HDR]=mexSLOAD(f,chan)\n\t\tchan must be sorted in ascending order\n"); mexPrintf("\t[s,HDR]=mexSLOAD(f,ReRef)\n\t\treref is a (sparse) matrix for rerefencing\n"); mexPrintf("\t[s,HDR]=mexSLOAD(f,chan,'...')\n"); mexPrintf("\t[s,HDR]=mexSLOAD(f,chan,'OVERFLOWDETECTION:ON')\n"); mexPrintf("\t[s,HDR]=mexSLOAD(f,chan,'OVERFLOWDETECTION:OFF')\n"); mexPrintf("\t[s,HDR]=mexSLOAD(f,chan,'UCAL:ON')\n"); mexPrintf("\t[s,HDR]=mexSLOAD(f,chan,'UCAL:OFF')\n"); mexPrintf("\t[s,HDR]=mexSLOAD(f,chan,'OUTPUT:SINGLE')\n"); mexPrintf("\t[s,HDR]=mexSLOAD(f,chan,'TARGETSEGMENT:<N>')\n"); mexPrintf("\t[s,HDR]=mexSLOAD(f,chan,'SWEEP',[NE, NG, NS])\n"); mexPrintf(" Input:\n\tf\tfilename\n"); mexPrintf("\tchan\tlist of selected channels; 0=all channels [default]\n"); mexPrintf("\tUCAL\tON: do not calibrate data; default=OFF\n"); // mexPrintf("\tOUTPUT\tSINGLE: single precision; default='double'\n"); mexPrintf("\tOVERFLOWDETECTION\tdefault = ON\n\t\tON: values outside dynamic range are not-a-number (NaN)\n"); mexPrintf("\tTARGETSEGMENT:<N>\n\t\tselect segment <N> in multisegment files (like Nihon-Khoden), default=1\n\t\tIt has no effect for other data formats.\n"); mexPrintf("\t[NE, NG, NS] are the number of the experiment, the series and the sweep, resp. for sweep selection in HEKA/PatchMaster files. (0 indicates all)\n"); mexPrintf("\t\t examples: [1,2,3] the 3rd sweep from the 2nd series of experiment 1; [1,3,0] selects all sweeps from experiment=1, series=3. \n\n"); mexPrintf(" Output:\n\ts\tsignal data, each column is one channel\n"); mexPrintf("\tHDR\theader structure\n\n"); #endif return; } /* improve checks for input arguments */ /* process input arguments */ for (k = 0; k < nrhs; k++) { arg = prhs[k]; if (mxIsEmpty(arg) && (k>0)) { #ifdef DEBUG mexPrintf("arg[%i] Empty\n",k); #endif } else if ((k==0) && mxIsCell(arg) && mxGetNumberOfElements(arg)==1 && mxGetCell(arg,0) && mxIsChar(mxGetCell(arg,0))) { FileName = mxArrayToString(mxGetCell(arg,0)); #ifdef DEBUG mexPrintf("arg[%i] IsCell\n",k); #endif } else if ((k==0) && mxIsStruct(arg)) { FileName = mxArrayToString(mxGetField(prhs[k],0,"FileName")); #ifdef DEBUG mexPrintf("arg[%i] IsStruct\n",k); #endif } #ifdef CHOLMOD_H else if ((k==1) && mxIsSparse(arg)) { rr = sputil_get_sparse(arg,&RR,&dummy,0); } #endif else if ((k==1) && mxIsNumeric(arg)) { #ifdef DEBUG mexPrintf("arg[%i] IsNumeric\n",k); #endif ChanList = (double*)mxGetData(prhs[k]); NS = mxGetNumberOfElements(prhs[k]); } else if (mxIsChar(arg)) { #ifdef DEBUG mexPrintf("arg[%i]=%s \n",k,mxArrayToString(prhs[k])); #endif if (k==0) FileName = mxArrayToString(prhs[k]); else if (!strcmp(mxArrayToString(prhs[k]), "CNT32")) ; // obsolete - supported for backwards compatibility else if (!strcmp(mxArrayToString(prhs[k]), "OVERFLOWDETECTION:ON")) FlagOverflowDetection = 1; else if (!strcmp(mxArrayToString(prhs[k]), "OVERFLOWDETECTION:OFF")) FlagOverflowDetection = 0; else if (!strcmp(mxArrayToString(prhs[k]), "UCAL:ON")) FlagUCAL = 1; else if (!strcmp(mxArrayToString(prhs[k]), "UCAL:OFF")) FlagUCAL = 0; // else if (!strcmp(mxArrayToString(prhs[k]),"OUTPUT:SINGLE")) // FlagMXclass = mxSINGLE_CLASS; else if (!strncmp(mxArrayToString(prhs[k]),"TARGETSEGMENT:",14)) TARGETSEGMENT = atoi(mxArrayToString(prhs[k])+14); else if (!strcasecmp(mxArrayToString(prhs[k]), "SWEEP") && (prhs[k+1] != NULL) && mxIsNumeric(prhs[k+1])) argSweepSel = ++k; } else { #ifndef mexSOPEN mexPrintf("mexSLOAD: argument #%i is invalid.",k+1); mexErrMsgTxt("mexSLOAD failes because of unknown parameter\n"); #else mexPrintf("mexSOPEN: argument #%i is invalid.",k+1); mexErrMsgTxt("mexSOPEN fails because of unknown parameter\n"); #endif } } if (VERBOSE_LEVEL>7) mexPrintf("110: input arguments checked\n"); hdr = constructHDR(0,0); #ifdef __LIBBIOSIG2_H__ unsigned flags = (!!FlagOverflowDetection)*BIOSIG_FLAG_OVERFLOWDETECTION + (!!FlagUCAL)*BIOSIG_FLAG_UCAL; #ifdef CHOLMOD_H flags += (rr!=NULL)*BIOSIG_FLAG_ROW_BASED_CHANNELS; #else biosig_reset_flag(hdr, BIOSIG_FLAG_ROW_BASED_CHANNELS); #endif biosig_set_flag(hdr, flags); biosig_set_targetsegment(hdr, TARGETSEGMENT); // sweep selection for Heka format if (argSweepSel>0) { double *SZ = (double*) mxGetData(prhs[argSweepSel]); k = 0; while (k < mxGetNumberOfElements(prhs[argSweepSel]) && k < 5) { biosig_set_segment_selection(hdr, k+1, (uint32_t)SZ[k]); k++; } } #else //__LIBBIOSIG2_H__ hdr->FLAG.OVERFLOWDETECTION = FlagOverflowDetection; hdr->FLAG.UCAL = FlagUCAL; #ifdef CHOLMOD_H hdr->FLAG.ROW_BASED_CHANNELS = (rr!=NULL); #else hdr->FLAG.ROW_BASED_CHANNELS = 0; #endif hdr->FLAG.TARGETSEGMENT = TARGETSEGMENT; // sweep selection for Heka format if (argSweepSel>0) { double *SZ = (double*) mxGetData(prhs[argSweepSel]); k = 0; while (k < mxGetNumberOfElements(prhs[argSweepSel]) && k < 5) { hdr->AS.SegSel[k] = (uint32_t)SZ[k]; k++; } } #endif // __LIBBIOSIG2_H__ : TODO: below, nothing is converted to level-2 interface, yet if (VERBOSE_LEVEL>7) mexPrintf("120: going to sopen\n"); hdr = sopen(FileName, "r", hdr); /* #ifdef WITH_PDP if (hdr->AS.B4C_ERRNUM) { hdr->AS.B4C_ERRNUM = 0; sopen_pdp_read(hdr); } #endif */ if (VERBOSE_LEVEL>7) mexPrintf("121: sopen done\n"); if ((status=serror2(hdr))) { const char* fields[]={"TYPE","VERSION","FileName","FLAG","ErrNum","ErrMsg"}; HDR = mxCreateStructMatrix(1, 1, 6, fields); #ifdef __LIBBIOSIG2_H__ mxSetField(HDR,0,"FileName",mxCreateString(biosig_get_filename(hdr))); const char *FileTypeString = GetFileTypeString(biosig_get_filetype(hdr)); mxSetField(HDR,0,"VERSION",mxCreateDoubleScalar(biosig_get_version(hdr))); #else mxSetField(HDR,0,"FileName",mxCreateString(hdr->FileName)); const char *FileTypeString = GetFileTypeString(hdr->TYPE); mxSetField(HDR,0,"VERSION",mxCreateDoubleScalar(hdr->VERSION)); #endif mxArray *errnum = mxCreateNumericMatrix(1,1,mxUINT8_CLASS,mxREAL); *(uint8_t*)mxGetData(errnum) = (uint8_t)status; mxSetField(HDR,0,"ErrNum",errnum); #ifdef HAVE_OCTAVE // handle bug in octave: mxCreateString(NULL) causes segmentation fault // Octave 3.2.3 causes a seg-fault in mxCreateString(NULL) if (FileTypeString) FileTypeString="\0"; #endif mxSetField(HDR,0,"TYPE",mxCreateString(FileTypeString)); char *msg = (char*)malloc(72+23+strlen(FileName)); // 72: max length of constant text, 23: max length of GetFileTypeString() if (msg == NULL) mxSetField(HDR,0,"ErrMsg",mxCreateString("Error mexSLOAD: Cannot open file\n")); else { if (status==B4C_CANNOT_OPEN_FILE) sprintf(msg,"Error mexSLOAD: file %s not found.\n",FileName); /* Flawfinder: ignore *** sufficient memory is allocated above */ else if (status==B4C_FORMAT_UNKNOWN) sprintf(msg,"Error mexSLOAD: Cannot open file %s - format %s not known.\n",FileName,FileTypeString); /* Flawfinder: ignore *** sufficient memory is allocated above */ else if (status==B4C_FORMAT_UNSUPPORTED) sprintf(msg,"Error mexSLOAD: Cannot open file %s - format %s not supported [%s].\n", FileName, FileTypeString, hdr->AS.B4C_ERRMSG); /* Flawfinder: ignore *** sufficient memory is allocated above */ else sprintf(msg,"Error %i mexSLOAD: Cannot open file %s - format %s not supported [%s].\n", status, FileName, FileTypeString, hdr->AS.B4C_ERRMSG); /* Flawfinder: ignore *** sufficient memory is allocated above */ mxSetField(HDR,0,"ErrMsg",mxCreateString(msg)); free(msg); } if (VERBOSE_LEVEL>7) mexPrintf("737: abort mexSLOAD - sopen failed\n"); destructHDR(hdr); if (VERBOSE_LEVEL>7) mexPrintf("757: abort mexSLOAD - sopen failed\n"); #ifdef mexSOPEN plhs[0] = HDR; #else plhs[0] = mxCreateDoubleMatrix(0,0, mxREAL); plhs[1] = HDR; #endif if (VERBOSE_LEVEL>7) mexPrintf("777: abort mexSLOAD - sopen failed\n"); return; } #ifdef CHOLMOD_H RerefCHANNEL(hdr,rr,2); #endif if (hdr->FLAG.OVERFLOWDETECTION != FlagOverflowDetection) mexPrintf("Warning mexSLOAD: Overflowdetection not supported in file %s\n",hdr->FileName); if (hdr->FLAG.UCAL != FlagUCAL) mexPrintf("Warning mexSLOAD: Flag UCAL is %i instead of %i (%s)\n",hdr->FLAG.UCAL,FlagUCAL,hdr->FileName); if (VERBOSE_LEVEL>7) fprintf(stderr,"[112] SOPEN-R finished NS=%i %i\n",hdr->NS,NS); // convert2to4_eventtable(hdr); #ifdef CHOLMOD_H if (hdr->Calib != NULL) { NS = hdr->Calib->ncol; } else #endif if ((NS<0) || ((NS==1) && (ChanList[0] == 0.0))) { // all channels for (k=0, NS=0; k<hdr->NS; ++k) { if (hdr->CHANNEL[k].OnOff) NS++; } } else { for (k=0; k<hdr->NS; ++k) hdr->CHANNEL[k].OnOff = 0; // reset for (k=0; k<NS; ++k) { int ch = (int)ChanList[k]; if ((ch < 1) || (ch > hdr->NS)) mexPrintf("Invalid channel number CHAN(%i) = %i!\n",k+1,ch); else hdr->CHANNEL[ch-1].OnOff = 1; // set } } if (VERBOSE_LEVEL>7) fprintf(stderr,"[113] NS=%i %i\n",hdr->NS,NS); #ifndef mexSOPEN if (hdr->FLAG.ROW_BASED_CHANNELS) plhs[0] = mxCreateDoubleMatrix(NS, hdr->NRec*hdr->SPR, mxREAL); else plhs[0] = mxCreateDoubleMatrix(hdr->NRec*hdr->SPR, NS, mxREAL); count = sread(mxGetPr(plhs[0]), 0, hdr->NRec, hdr); hdr->NRec = count; #endif sclose(hdr); #ifdef CHOLMOD_H if (hdr->Calib && hdr->rerefCHANNEL) { hdr->NS = hdr->Calib->ncol; free(hdr->CHANNEL); hdr->CHANNEL = hdr->rerefCHANNEL; hdr->rerefCHANNEL = NULL; hdr->Calib = NULL; } #endif if ((status=serror2(hdr))) return; if (VERBOSE_LEVEL>7) fprintf(stderr,"\n[129] SREAD/SCLOSE on %s successful [%i,%i] [%i,%i] %i.\n",hdr->FileName,(int)hdr->data.size[0],(int)hdr->data.size[1],(int)hdr->NRec,(int)count,(int)NS); // hdr2ascii(hdr,stderr,4); #ifndef mexSOPEN if (nlhs>1) { #endif char* mexFileName = (char*)mxMalloc(strlen(hdr->FileName)+1); mxArray *tmp, *tmp2, *Patient, *Manufacturer, *ID, *EVENT, *Filter, *Flag, *FileType; uint16_t numfields; const char *fnames[] = {"TYPE","VERSION","FileName","T0","tzmin","FILE","Patient",\ "HeadLen","NS","SPR","NRec","SampleRate", "FLAG", \ "EVENT","Label","LeadIdCode","PhysDimCode","PhysDim","Filter",\ "PhysMax","PhysMin","DigMax","DigMin","Transducer","Cal","Off","GDFTYP","TOffset",\ "LowPass","HighPass","Notch","ELEC","Impedance","fZ","AS","Dur","REC","Manufacturer",NULL}; for (numfields=0; fnames[numfields++] != NULL; ); HDR = mxCreateStructMatrix(1, 1, --numfields, fnames); mxSetField(HDR,0,"TYPE",mxCreateString(GetFileTypeString(hdr->TYPE))); mxSetField(HDR,0,"HeadLen",mxCreateDoubleScalar(hdr->HeadLen)); mxSetField(HDR,0,"VERSION",mxCreateDoubleScalar(hdr->VERSION)); mxSetField(HDR,0,"NS",mxCreateDoubleScalar(NS)); mxSetField(HDR,0,"SPR",mxCreateDoubleScalar(hdr->SPR)); mxSetField(HDR,0,"NRec",mxCreateDoubleScalar(hdr->NRec)); mxSetField(HDR,0,"SampleRate",mxCreateDoubleScalar(hdr->SampleRate)); mxSetField(HDR,0,"Dur",mxCreateDoubleScalar(hdr->SPR/hdr->SampleRate)); mxSetField(HDR,0,"FileName",mxCreateString(hdr->FileName)); mxSetField(HDR,0,"T0",mxCreateDoubleScalar(ldexp(hdr->T0,-32))); mxSetField(HDR,0,"tzmin",mxCreateDoubleScalar(hdr->tzmin)); /* Channel information */ #ifdef CHOLMOD_H /* if (hdr->Calib == NULL) { // is refering to &RR, do not destroy mxArray *Calib = mxCreateDoubleMatrix(hdr->Calib->nrow, hdr->Calib->ncol, mxREAL); } */ #endif mxArray *LeadIdCode = mxCreateDoubleMatrix(1,NS, mxREAL); mxArray *PhysDimCode = mxCreateDoubleMatrix(1,NS, mxREAL); mxArray *GDFTYP = mxCreateDoubleMatrix(1,NS, mxREAL); mxArray *PhysMax = mxCreateDoubleMatrix(1,NS, mxREAL); mxArray *PhysMin = mxCreateDoubleMatrix(1,NS, mxREAL); mxArray *DigMax = mxCreateDoubleMatrix(1,NS, mxREAL); mxArray *DigMin = mxCreateDoubleMatrix(1,NS, mxREAL); mxArray *Cal = mxCreateDoubleMatrix(1,NS, mxREAL); mxArray *Off = mxCreateDoubleMatrix(1,NS, mxREAL); mxArray *Toffset = mxCreateDoubleMatrix(1,NS, mxREAL); mxArray *ELEC_POS = mxCreateDoubleMatrix(NS,3, mxREAL); /* mxArray *ELEC_Orient = mxCreateDoubleMatrix(NS,3, mxREAL); mxArray *ELEC_Area = mxCreateDoubleMatrix(NS,1, mxREAL); */ mxArray *LowPass = mxCreateDoubleMatrix(1,NS, mxREAL); mxArray *HighPass = mxCreateDoubleMatrix(1,NS, mxREAL); mxArray *Notch = mxCreateDoubleMatrix(1,NS, mxREAL); mxArray *Impedance = mxCreateDoubleMatrix(1,NS, mxREAL); mxArray *fZ = mxCreateDoubleMatrix(1,NS, mxREAL); mxArray *SPR = mxCreateDoubleMatrix(1,NS, mxREAL); mxArray *Label = mxCreateCellMatrix(NS,1); mxArray *Transducer = mxCreateCellMatrix(NS,1); mxArray *PhysDim1 = mxCreateCellMatrix(NS,1); for (k=0,k1=0; k1<NS; ++k) if (hdr->CHANNEL[k].OnOff) { *(mxGetPr(LeadIdCode)+k1) = (double)hdr->CHANNEL[k].LeadIdCode; *(mxGetPr(PhysDimCode)+k1) = (double)hdr->CHANNEL[k].PhysDimCode; *(mxGetPr(GDFTYP)+k1) = (double)hdr->CHANNEL[k].GDFTYP; *(mxGetPr(PhysMax)+k1) = (double)hdr->CHANNEL[k].PhysMax; *(mxGetPr(PhysMin)+k1) = (double)hdr->CHANNEL[k].PhysMin; *(mxGetPr(DigMax)+k1) = (double)hdr->CHANNEL[k].DigMax; *(mxGetPr(DigMin)+k1) = (double)hdr->CHANNEL[k].DigMin; *(mxGetPr(Toffset)+k1) = (double)hdr->CHANNEL[k].TOffset; *(mxGetPr(Cal)+k1) = (double)hdr->CHANNEL[k].Cal; *(mxGetPr(Off)+k1) = (double)hdr->CHANNEL[k].Off; *(mxGetPr(SPR)+k1) = (double)hdr->CHANNEL[k].SPR; *(mxGetPr(LowPass)+k1) = (double)hdr->CHANNEL[k].LowPass; *(mxGetPr(HighPass)+k1) = (double)hdr->CHANNEL[k].HighPass; *(mxGetPr(Notch)+k1) = (double)hdr->CHANNEL[k].Notch; *(mxGetPr(Impedance)+k1) = (double)hdr->CHANNEL[k].Impedance; *(mxGetPr(fZ)+k1) = (double)hdr->CHANNEL[k].fZ; *(mxGetPr(ELEC_POS)+k1) = (double)hdr->CHANNEL[k].XYZ[0]; *(mxGetPr(ELEC_POS)+k1+NS) = (double)hdr->CHANNEL[k].XYZ[1]; *(mxGetPr(ELEC_POS)+k1+NS*2) = (double)hdr->CHANNEL[k].XYZ[2]; /* *(mxGetPr(ELEC_Orient)+k1) = (double)hdr->CHANNEL[k].Orientation[0]; *(mxGetPr(ELEC_Orient)+k1+NS) = (double)hdr->CHANNEL[k].Orientation[1]; *(mxGetPr(ELEC_Orient)+k1+NS*2) = (double)hdr->CHANNEL[k].Orientation[2]; *(mxGetPr(ELEC_Area)+k1) = (double)hdr->CHANNEL[k].Area; */ mxSetCell(Label,k1,mxCreateString(hdr->CHANNEL[k].Label)); mxSetCell(Transducer,k1,mxCreateString(hdr->CHANNEL[k].Transducer)); mxSetCell(PhysDim1,k1,mxCreateString(PhysDim3(hdr->CHANNEL[k].PhysDimCode))); k1++; } mxSetField(HDR,0,"LeadIdCode",LeadIdCode); mxSetField(HDR,0,"PhysDimCode",PhysDimCode); mxSetField(HDR,0,"GDFTYP",GDFTYP); mxSetField(HDR,0,"PhysMax",PhysMax); mxSetField(HDR,0,"PhysMin",PhysMin); mxSetField(HDR,0,"DigMax",DigMax); mxSetField(HDR,0,"DigMin",DigMin); mxSetField(HDR,0,"TOffset",Toffset); mxSetField(HDR,0,"Cal",Cal); mxSetField(HDR,0,"Off",Off); mxSetField(HDR,0,"Impedance",Impedance); mxSetField(HDR,0,"fZ",fZ); mxSetField(HDR,0,"Off",Off); mxSetField(HDR,0,"PhysDim",PhysDim1); mxSetField(HDR,0,"Transducer",Transducer); mxSetField(HDR,0,"Label",Label); const char* field[] = {"XYZ","Orientation","Area","GND","REF",NULL}; for (numfields=0; field[numfields++] != 0; ); tmp = mxCreateStructMatrix(1, 1, --numfields, field); mxSetField(tmp,0,"XYZ",ELEC_POS); /* mxSetField(tmp,0,"Orientation",ELEC_Orient); mxSetField(tmp,0,"Area",ELEC_Area); */ mxSetField(HDR,0,"ELEC",tmp); const char* field2[] = {"SPR",NULL}; for (numfields=0; field2[numfields++] != 0; ); tmp2 = mxCreateStructMatrix(1, 1, --numfields, field2); mxSetField(tmp2,0,"SPR",SPR); if (hdr->AS.bci2000!=NULL) { mxAddField(tmp2, "BCI2000"); mxSetField(tmp2,0,"BCI2000",mxCreateString(hdr->AS.bci2000)); } if (hdr->TYPE==Sigma) { mxAddField(tmp2, "H1"); mxSetField(tmp2,0,"H1",mxCreateString((char*)hdr->AS.Header)); } mxSetField(HDR,0,"AS",tmp2); /* FLAG */ const char* field3[] = {"UCAL","OVERFLOWDETECTION","ROW_BASED_CHANNELS",NULL}; for (numfields=0; field3[numfields++] != 0; ); Flag = mxCreateStructMatrix(1, 1, --numfields, field3); #ifdef MX_API_VER //#if 1 // Matlab, Octave 3.6.1 mxSetField(Flag,0,"UCAL",mxCreateLogicalScalar(hdr->FLAG.UCAL)); mxSetField(Flag,0,"OVERFLOWDETECTION",mxCreateLogicalScalar(hdr->FLAG.OVERFLOWDETECTION)); mxSetField(Flag,0,"ROW_BASED_CHANNELS",mxCreateLogicalScalar(hdr->FLAG.ROW_BASED_CHANNELS)); #else // mxCreateLogicalScalar are not included in Octave 3.0 mxSetField(Flag,0,"UCAL",mxCreateDoubleScalar(hdr->FLAG.UCAL)); mxSetField(Flag,0,"OVERFLOWDETECTION",mxCreateDoubleScalar(hdr->FLAG.OVERFLOWDETECTION)); mxSetField(Flag,0,"ROW_BASED_CHANNELS",mxCreateDoubleScalar(hdr->FLAG.ROW_BASED_CHANNELS)); #endif mxSetField(HDR,0,"FLAG",Flag); /* Filter */ const char *filter_fields[] = {"HighPass","LowPass","Notch",NULL}; for (numfields=0; filter_fields[numfields++] != 0; ); Filter = mxCreateStructMatrix(1, 1, --numfields, filter_fields); mxSetField(Filter,0,"LowPass",LowPass); mxSetField(Filter,0,"HighPass",HighPass); mxSetField(Filter,0,"Notch",Notch); mxSetField(HDR,0,"Filter",Filter); /* annotation, marker, event table */ const char *event_fields[] = {"SampleRate","TYP","POS","DUR","CHN","Desc",NULL}; if (hdr->EVENT.DUR == NULL) EVENT = mxCreateStructMatrix(1, 1, 3, event_fields); else { EVENT = mxCreateStructMatrix(1, 1, 5, event_fields); mxArray *DUR = mxCreateDoubleMatrix(hdr->EVENT.N,1, mxREAL); mxArray *CHN = mxCreateDoubleMatrix(hdr->EVENT.N,1, mxREAL); for (k=0; k<hdr->EVENT.N; ++k) { *(mxGetPr(DUR)+k) = (double)hdr->EVENT.DUR[k]; *(mxGetPr(CHN)+k) = (double)hdr->EVENT.CHN[k]; // channels use a 1-based index, 0 indicates all channels } mxSetField(EVENT,0,"DUR",DUR); mxSetField(EVENT,0,"CHN",CHN); } if (hdr->EVENT.CodeDesc != NULL) { mxAddField(EVENT, "CodeDesc"); mxArray *CodeDesc = mxCreateCellMatrix(hdr->EVENT.LenCodeDesc-1,1); for (k=1; k < hdr->EVENT.LenCodeDesc; ++k) { mxSetCell(CodeDesc,k-1,mxCreateString(hdr->EVENT.CodeDesc[k])); } mxSetField(EVENT,0,"CodeDesc",CodeDesc); } mxArray *TYP = mxCreateDoubleMatrix(hdr->EVENT.N,1, mxREAL); mxArray *POS = mxCreateDoubleMatrix(hdr->EVENT.N,1, mxREAL); for (k=0; k<hdr->EVENT.N; ++k) { *(mxGetPr(TYP)+k) = (double)hdr->EVENT.TYP[k]; *(mxGetPr(POS)+k) = (double)hdr->EVENT.POS[k]+1; // conversion from 0-based to 1-based indexing } mxSetField(EVENT,0,"TYP",TYP); mxSetField(EVENT,0,"POS",POS); #if (BIOSIG_VERSION >= 10500) if (hdr->EVENT.TimeStamp) { mxArray *TimeStamp = mxCreateDoubleMatrix(hdr->EVENT.N,1, mxREAL); for (k=0; k<hdr->EVENT.N; ++k) { *(mxGetPr(TimeStamp)+k) = ldexp(hdr->EVENT.TimeStamp[k],-32); } mxAddField(EVENT, "TimeStamp"); mxSetField(EVENT,0,"TimeStamp",TimeStamp); } #endif mxSetField(EVENT,0,"SampleRate",mxCreateDoubleScalar(hdr->EVENT.SampleRate)); mxSetField(HDR,0,"EVENT",EVENT); /* Record identification */ const char *ID_fields[] = {"Recording","Technician","Hospital","Equipment","IPaddr",NULL}; for (numfields=0; ID_fields[numfields++] != 0; ); ID = mxCreateStructMatrix(1, 1, --numfields, ID_fields); mxSetField(ID,0,"Recording",mxCreateString(hdr->ID.Recording)); mxSetField(ID,0,"Technician",mxCreateString(hdr->ID.Technician)); mxSetField(ID,0,"Hospital",mxCreateString(hdr->ID.Hospital)); mxSetField(ID,0,"Equipment",mxCreateString((char*)&hdr->ID.Equipment)); int len = 4; uint8_t IPv6=0; for (k=4; k<16; k++) IPv6 |= hdr->IPaddr[k]; if (IPv6) len=16; mxArray *IPaddr = mxCreateNumericMatrix(1,len,mxUINT8_CLASS,mxREAL); memcpy(mxGetData(IPaddr),hdr->IPaddr,len); mxSetField(ID,0,"IPaddr",IPaddr); mxSetField(HDR,0,"REC",ID); /* Patient Information */ const char *patient_fields[] = {"Sex","Handedness","Id","Name","Weight","Height","Birthday",NULL}; for (numfields=0; patient_fields[numfields++] != 0; ); Patient = mxCreateStructMatrix(1, 1, --numfields, patient_fields); const char *strarray[1]; #ifdef __LIBBIOSIG2_H__ strarray[0] = biosig_get_patient_name(hdr); if (strarray[0]) { mxSetField(Patient,0,"Name",mxCreateCharMatrixFromStrings(1,strarray)); } strarray[0] = biosig_get_patient_id(hdr); if (strarray[0]) { mxSetField(Patient,0,"Id",mxCreateCharMatrixFromStrings(1,strarray)); } #else strarray[0] = hdr->Patient.Name; if (strarray[0]) { mxSetField(Patient,0,"Name",mxCreateCharMatrixFromStrings(1,strarray)); } strarray[0] = hdr->Patient.Id; if (strarray[0]) { mxSetField(Patient,0,"Id",mxCreateCharMatrixFromStrings(1,strarray)); } #endif mxSetField(Patient,0,"Handedness",mxCreateDoubleScalar(hdr->Patient.Handedness)); mxSetField(Patient,0,"Sex",mxCreateDoubleScalar(hdr->Patient.Sex)); mxSetField(Patient,0,"Weight",mxCreateDoubleScalar((double)hdr->Patient.Weight)); mxSetField(Patient,0,"Height",mxCreateDoubleScalar((double)hdr->Patient.Height)); mxSetField(Patient,0,"Birthday",mxCreateDoubleScalar(ldexp(hdr->Patient.Birthday,-32))); double d; if (hdr->Patient.Weight==0) d = NAN; // not-a-number else if (hdr->Patient.Weight==255) d = INFINITY; // Overflow else d = (double)hdr->Patient.Weight; mxSetField(Patient,0,"Weight",mxCreateDoubleScalar(d)); if (hdr->Patient.Height==0) d = NAN; // not-a-number else if (hdr->Patient.Height==255) d = INFINITY; // Overflow else d = (double)hdr->Patient.Height; mxSetField(Patient,0,"Height",mxCreateDoubleScalar(d)); /* Manufacturer Information */ const char *manufacturer_fields[] = {"Name","Model","Version","SerialNumber",NULL}; for (numfields=0; manufacturer_fields[numfields++] != 0; ); Manufacturer = mxCreateStructMatrix(1, 1, --numfields, manufacturer_fields); #ifdef __LIBBIOSIG2_H__ strarray[0] = biosig_get_manufacturer_name(hdr); if (strarray[0]) { mxSetField(Manufacturer,0,"Name",mxCreateCharMatrixFromStrings(1,strarray)); } strarray[0] = biosig_get_manufacturer_model(hdr); if (strarray[0]) { biosig_get_manufacturer_model(hdr); mxSetField(Manufacturer,0,"Model",mxCreateCharMatrixFromStrings(1,strarray)); } strarray[0] = biosig_get_manufacturer_version(hdr); if (strarray[0]) { biosig_get_manufacturer_version(hdr); mxSetField(Manufacturer,0,"Version",mxCreateCharMatrixFromStrings(1,strarray)); } strarray[0] = biosig_get_manufacturer_serial_number(hdr); if (strarray[0]) { mxSetField(Manufacturer,0,"SerialNumber",mxCreateCharMatrixFromStrings(1,strarray)); } #else strarray[0] = hdr->ID.Manufacturer.Name; if (strarray[0]) { mxSetField(Manufacturer,0,"Name",mxCreateCharMatrixFromStrings(1,strarray)); } strarray[0] = hdr->ID.Manufacturer.Model; if (strarray[0]) { mxSetField(Manufacturer,0,"Model",mxCreateCharMatrixFromStrings(1,strarray)); } strarray[0] = hdr->ID.Manufacturer.Version; if (strarray[0]) { mxSetField(Manufacturer,0,"Version",mxCreateCharMatrixFromStrings(1,strarray)); } strarray[0] = hdr->ID.Manufacturer.SerialNumber; if (strarray[0]) { mxSetField(Manufacturer,0,"SerialNumber",mxCreateCharMatrixFromStrings(1,strarray)); } #endif mxSetField(HDR,0,"Manufacturer",Manufacturer); if (VERBOSE_LEVEL>7) fprintf(stdout,"[148] going for SCLOSE\n"); mxSetField(HDR,0,"Patient",Patient); #ifndef mexSOPEN plhs[1] = HDR; } #else plhs[0] = HDR; #endif if (VERBOSE_LEVEL>7) fprintf(stdout,"[151] going for SCLOSE\n"); #ifdef CHOLMOD_H hdr->Calib = NULL; // is refering to &RR, do not destroy #endif if (VERBOSE_LEVEL>7) fprintf(stdout,"[156] SCLOSE finished\n"); destructHDR(hdr); hdr = NULL; if (VERBOSE_LEVEL>7) fprintf(stdout,"[157] SCLOSE finished\n"); };
void mxAddAndSetField(mxArray *in,int n,const char *field_name,mxArray *value) { if(mxGetField(in,n,field_name)==NULL) mxAddField(in,field_name); mxSetField(in,n,field_name,value); }
void mexFunction(int nlhs , mxArray *plhs[], int nrhs, mxArray const *prhs[]) { // clock_t begin, end; // begin = clock(); //Check amount of inputs if (nrhs<3 || nrhs>4) { mexErrMsgIdAndTxt("CBCT:MEX:Ax:InvalidInput", "Invalid number of inputs to MEX file."); } //////////////////////////// //4rd argument is interpolated or ray-voxel bool interpolated=false; if (nrhs==4){ if ( mxIsChar(prhs[3]) != 1) mexErrMsgIdAndTxt( "CBCT:MEX:Ax:InvalidInput","4rd input shoudl be a string"); /* copy the string data from prhs[0] into a C string input_ buf. */ char *krylov = mxArrayToString(prhs[3]); if (strcmp(krylov,"interpolated") && strcmp(krylov,"ray-voxel")) mexErrMsgIdAndTxt( "CBCT:MEX:Ax:InvalidInput","4rd input shoudl be either 'interpolated' or 'ray-voxel'"); else // If its not ray-voxel, its "interpolated" if (~strcmp(krylov,"ray-voxel")) interpolated=true; } ///////////////////////// 3rd argument: angle of projection. size_t mrows = mxGetM(prhs[2]); size_t nalpha = mxGetN(prhs[2]); if( !mxIsDouble(prhs[2]) || mxIsComplex(prhs[2]) || !(mrows==1) ) { mexErrMsgIdAndTxt("CBCT:MEX:Ax:InvalidInput", "Input alpha must be a noncomplex array."); } mxArray const * const ptralphas=prhs[2]; double const * const alphasM= static_cast<double const *>(mxGetData(ptralphas)); // just copy paste the data to a float array float * alphas= (float*)malloc(nalpha*sizeof(float)); for (int i=0;i<nalpha;i++) alphas[i]=(float)alphasM[i]; ////////////////////////// First input. // First input should be x from (Ax=b), or the image. mxArray const * const image = prhs[0]; mwSize const numDims = mxGetNumberOfDimensions(image); // Image should be dim 3 if (numDims!=3){ mexErrMsgIdAndTxt( "CBCT:MEX:Ax:InvalidInput", "Invalid dimension size of image (x) to MEX file."); } if( !mxIsSingle(prhs[0])) { mexErrMsgIdAndTxt("CBCT:MEX:Ax:InvalidInput", "Input image must be a single noncomplex array."); } // Now that input is ok, parse it to C data types. float const * const imgaux = static_cast<float const *>(mxGetData(image)); // We need a float image, and, unfortunatedly, the only way of casting it is by value const mwSize *size_img= mxGetDimensions(image); //get size of image float * img = (float*)malloc(size_img[0] *size_img[1] *size_img[2]* sizeof(float)); for (int i=0;i<size_img[0] *size_img[1] *size_img[2];i++) img[i]=(float)imgaux[i]; ///////////////////// Second input argument, // Geometry structure that has all the needed geometric data. mxArray * geometryMex=(mxArray*)prhs[1]; // IMPORTANT-> Make sure Matlab creates the struct in this order. const char *fieldnames[13]; fieldnames[0] = "nVoxel"; fieldnames[1] = "sVoxel"; fieldnames[2] = "dVoxel"; fieldnames[3] = "nDetector"; fieldnames[4] = "sDetector"; fieldnames[5] = "dDetector"; fieldnames[6] = "DSD"; fieldnames[7] = "DSO"; fieldnames[8] = "offOrigin"; fieldnames[9] = "offDetector"; fieldnames[10]= "accuracy"; fieldnames[11]= "mode"; fieldnames[12]= "COR"; if(!mxIsStruct(geometryMex)) mexErrMsgIdAndTxt( "CBCT:MEX:Ax:InvalidInput", "Second input must be a structure."); int nfields = mxGetNumberOfFields(geometryMex); if (nfields < 10 || nfields >13 ){ mexErrMsgIdAndTxt("CBCT:MEX:Ax:InvalidInput","there are missing or extra fields in the geometry"); } // Check that all names are good mxArray *tmp; size_t ncols; bool offsetAllOrig=false; bool offsetAllDetec=false; for(int ifield=0; ifield<nfields; ifield++) { tmp=mxGetField(geometryMex,0,fieldnames[ifield]); if(tmp==NULL){ // Special cases first: if(ifield==11){ mxAddField(geometryMex,fieldnames[ifield]); mxSetField(geometryMex,ifield,fieldnames[ifield],mxCreateString("cone")); }else if(ifield==12){ mxAddField(geometryMex,fieldnames[ifield]); mxSetField(geometryMex,ifield,fieldnames[ifield],mxCreateNumericMatrix(1,1,mxINT32_CLASS,mxREAL )); }else{ mexPrintf("%s number: %d %s \n", "FIELD",ifield+1, fieldnames[ifield]); mexErrMsgIdAndTxt( "CBCT:MEX:Ax:InvalidInput", "Above field is missing. Check spelling. "); } } switch(ifield){ // cases where we want 3 input arrays. case 0:case 1:case 2: mrows = mxGetM(tmp); ncols = mxGetN(tmp); if (mrows!=3 || ncols!=1){ mexPrintf("%s %s \n", "FIELD: ", fieldnames[ifield]); mexPrintf("%d x %d \n", "FIELD: ", (int)mrows,(int)ncols); mexErrMsgIdAndTxt( "CBCT:MEX:Ax:inputsize", "Above field has wrong size! Should be 3x1!"); } break; //this one can be either 3x1 or 3xNangles case 8: mrows = mxGetM(tmp); ncols = mxGetN(tmp); if (mrows!=3 || ( ncols!=1&& ncols!=nalpha) ){ mexPrintf("%s %s \n", "FIELD: ", fieldnames[ifield]); mexPrintf("%ld x %ld \n", "FIELD: ", (long int)mrows,(long int)ncols); mexErrMsgIdAndTxt( "CBCT:MEX:Ax:inputsize", "Above field has wrong size! Should be 3x1 or 3xlength(angles)!"); } if (ncols==nalpha) offsetAllOrig=true; break; case 9: mrows = mxGetM(tmp); ncols = mxGetN(tmp); if (mrows!=2 || ( ncols!=1&& ncols!=nalpha)){ mexPrintf("%s %s \n", "FIELD: ", fieldnames[ifield]); mexErrMsgIdAndTxt( "CBCT:MEX:Ax:inputsize", "Above field has wrong size! Should be 2x1 or 2xlength(angles)!"); } if (ncols==nalpha) offsetAllDetec=true; break; // this ones should be 2x1 case 3:case 4:case 5: mrows = mxGetM(tmp); ncols = mxGetN(tmp); if (mrows!=2 || ncols!=1){ mexPrintf("%s %s \n", "FIELD: ", fieldnames[ifield]); mexErrMsgIdAndTxt( "CBCT:MEX:Ax:inputsize", "Above field has wrong size! Should be 2x1!"); } break; // this ones should be 1x1 case 6:case 7:case 10:case 12: mrows = mxGetM(tmp); ncols = mxGetN(tmp); if (mrows!=1 || ncols!=1){ mexPrintf("%s %s \n", "FIELD: ", fieldnames[ifield]); mexErrMsgIdAndTxt( "CBCT:MEX:Ax:inputsize", "Above field has wrong size! Should be 1x1!"); } break; case 11: if (!mxIsChar(tmp)){ mexPrintf("%s %s \n", "FIELD: ", fieldnames[ifield]); mexErrMsgIdAndTxt( "CBCT:MEX:Ax:inputsize", "Above field is not string!"); } break; default: mexErrMsgIdAndTxt( "CBCT:MEX:Ax:input", "something wrong happened. Ensure Geometric struct has correct amount of inputs."); } } // Now we know that all the input struct is good! Parse it from mxArrays to // C structures that MEX can understand. double * nVoxel, *nDetec; //we need to cast these to int double * sVoxel, *dVoxel,*sDetec,*dDetec, *DSO, *DSD; double *offOrig,*offDetec; double * acc, *COR; const char* mode; int c; Geometry geo; geo.unitX=1;geo.unitY=1;geo.unitZ=1; bool coneBeam=true; // mexPrintf("%d \n",nfields); for(int ifield=0; ifield<nfields; ifield++) { tmp=mxGetField(geometryMex,0,fieldnames[ifield]); switch(ifield){ case 0: nVoxel=(double *)mxGetData(tmp); // copy data to MEX memory geo.nVoxelX=(int)nVoxel[0]; geo.nVoxelY=(int)nVoxel[1]; geo.nVoxelZ=(int)nVoxel[2]; break; case 1: sVoxel=(double *)mxGetData(tmp); geo.sVoxelX=(float)sVoxel[0]; geo.sVoxelY=(float)sVoxel[1]; geo.sVoxelZ=(float)sVoxel[2]; break; case 2: dVoxel=(double *)mxGetData(tmp); geo.dVoxelX=(float)dVoxel[0]; geo.dVoxelY=(float)dVoxel[1]; geo.dVoxelZ=(float)dVoxel[2]; break; case 3: nDetec=(double *)mxGetData(tmp); geo.nDetecU=(int)nDetec[0]; geo.nDetecV=(int)nDetec[1]; break; case 4: sDetec=(double *)mxGetData(tmp); geo.sDetecU=(float)sDetec[0]; geo.sDetecV=(float)sDetec[1]; break; case 5: dDetec=(double *)mxGetData(tmp); geo.dDetecU=(float)dDetec[0]; geo.dDetecV=(float)dDetec[1]; break; case 6: DSD=(double *)mxGetData(tmp); geo.DSD=(float)DSD[0]; break; case 7: DSO=(double *)mxGetData(tmp); geo.DSO=(float)DSO[0]; break; case 8: geo.offOrigX=(float*)malloc(nalpha * sizeof(float)); geo.offOrigY=(float*)malloc(nalpha * sizeof(float)); geo.offOrigZ=(float*)malloc(nalpha * sizeof(float)); offOrig=(double *)mxGetData(tmp); for (int i=0;i<nalpha;i++){ if (offsetAllOrig) c=i; else c=0; geo.offOrigX[i]=(float)offOrig[0+3*c]; geo.offOrigY[i]=(float)offOrig[1+3*c]; geo.offOrigZ[i]=(float)offOrig[2+3*c]; } break; case 9: geo.offDetecU=(float*)malloc(nalpha * sizeof(float)); geo.offDetecV=(float*)malloc(nalpha * sizeof(float)); offDetec=(double *)mxGetData(tmp); for (int i=0;i<nalpha;i++){ if (offsetAllDetec) c=i; else c=0; geo.offDetecU[i]=(float)offDetec[0+2*c]; geo.offDetecV[i]=(float)offDetec[1+2*c]; } break; case 10: acc=(double*)mxGetData(tmp); if (acc[0]<0.001) mexErrMsgIdAndTxt( "CBCT:MEX:Ax:Accuracy","Accuracy should be bigger than 0"); geo.accuracy=(float)acc[0]; break; case 11: mode=""; mode=mxArrayToString(tmp); if (!strcmp(mode,"parallel")) coneBeam=false; else if (strcmp(mode,"cone")) mexErrMsgIdAndTxt( "CBCT:MEX:Ax:Mode","Unkown mode. Should be parallel or cone"); break; case 12: COR=(double*)mxGetData(tmp); geo.COR=(float)COR[0]; break; default: mexErrMsgIdAndTxt( "CBCT:MEX:Ax:unknown","This shoudl not happen. Weird"); break; } } tmp=mxGetField(geometryMex,0,fieldnames[10]); if (tmp==NULL) geo.accuracy=0.5; // Geometry tmp=mxGetField(geometryMex,0,fieldnames[11]); if (tmp==NULL) coneBeam=true; // COR tmp=mxGetField(geometryMex,0,fieldnames[12]); if (tmp==NULL) geo.COR=0.0; // Additional test if( (size_img[0]!=geo.nVoxelX)|(size_img[1]!=geo.nVoxelY)|(size_img[2]!=geo.nVoxelZ)) mexErrMsgIdAndTxt( "CBCT:MEX:Ax:input", "Image size and nVoxel are not same size."); size_t num_bytes = geo.nDetecU*geo.nDetecV * sizeof(float); float** result = (float**)malloc(nalpha * sizeof(float*)); for (int i=0; i<nalpha ;i++) result[i]=(float*)malloc(geo.nDetecU*geo.nDetecV *sizeof(float)); // call the real function if (coneBeam){ if (interpolated){ siddon_ray_projection(img,geo,result,alphas,nalpha); }else{ interpolation_projection(img,geo,result,alphas,nalpha); } }else{ if (interpolated){ // mexErrMsgIdAndTxt( "CBCT:MEX:Ax:debug", // "ray-voxel intersection is still unavailable for parallel beam, as there are some bugs on it."); siddon_ray_projection_parallel(img,geo,result,alphas,nalpha); }else{ interpolation_projection_parallel(img,geo,result,alphas,nalpha); } } // Set outputs and exit mwSize outsize[3]; outsize[0]=geo.nDetecV; outsize[1]=geo.nDetecU; outsize[2]= nalpha; plhs[0] = mxCreateNumericArray(3,outsize,mxSINGLE_CLASS,mxREAL); float *outProjections = (float*)mxGetPr(plhs[0]); for (int i=0; i<nalpha ;i++) for (int j=0; j<geo.nDetecU*geo.nDetecV;j++) outProjections[geo.nDetecU*geo.nDetecV*i+j]=(float)result[i][j]; for (int i=0; i<nalpha ;i++) free (result[i]); free(result); // Free image data free(img); return; }
void addTrialMetaFields(mxArray* mxTrial, const DataLoggerStatus* dlStatus, unsigned trialIdx) { // add subject field unsigned fieldNum; mxArray* mxTemp; const DataLoggerStatusByTrial* trialStatus = dlStatus->byTrial + trialIdx; timestamp_t timestampStart = trialStatus->timestampStart; timestamp_t timestampEnd = trialStatus->timestampEnd; struct tm timeInfo; unsigned msec; datenum_t wallclockStart = convertWallclockToMatlabDateNum(trialStatus->wallclockStart); convertWallclockToLocalTime(trialStatus->wallclockStart, &timeInfo, &msec); fieldNum = mxAddField(mxTrial, "subject"); mxSetFieldByNumber(mxTrial, 0, fieldNum, mxCreateString(dlStatus->subject)); fieldNum = mxAddField(mxTrial, "protocol"); mxSetFieldByNumber(mxTrial, 0, fieldNum, mxCreateString(dlStatus->protocol)); fieldNum = mxAddField(mxTrial, "protocolVersion"); mxTemp = mxCreateNumericMatrix(1, 1, mxUINT32_CLASS, mxREAL); memcpy(mxGetData(mxTemp), &dlStatus->protocolVersion, sizeof(uint32_t)); mxSetFieldByNumber(mxTrial, 0, fieldNum, mxTemp); fieldNum = mxAddField(mxTrial, "dataStore"); mxSetFieldByNumber(mxTrial, 0, fieldNum, mxCreateString(dlStatus->dataStore)); // add date as "YYYYMMDD" number fieldNum = mxAddField(mxTrial, "date"); unsigned date = (timeInfo.tm_year+1900) * 10000 + (timeInfo.tm_mon+1) * 100 + timeInfo.tm_mday; mxTemp = mxCreateNumericMatrix(1, 1, mxUINT32_CLASS, mxREAL); memcpy(mxGetData(mxTemp), &date, sizeof(uint32_t)); mxSetFieldByNumber(mxTrial, 0, fieldNum, mxTemp); fieldNum = mxAddField(mxTrial, "saveTag"); mxTemp = mxCreateNumericMatrix(1, 1, mxUINT32_CLASS, mxREAL); ((uint32_t*)mxGetData(mxTemp))[0] = dlStatus->saveTag; mxSetFieldByNumber(mxTrial, 0, fieldNum, mxTemp); fieldNum = mxAddField(mxTrial, "trialId"); mxTemp = mxCreateNumericMatrix(1, 1, mxUINT32_CLASS, mxREAL); ((uint32_t*)mxGetData(mxTemp))[0] = trialStatus->trialId; mxSetFieldByNumber(mxTrial, 0, fieldNum, mxTemp); // generate unique trialId string using Subject_Date_Protocol_SaveTag_trialId char trialIdStr[MAX_STRING]; char dateStr[MAX_STRING]; strftime(dateStr, MAX_STRING, "%Y%m%d", &timeInfo); snprintf(trialIdStr, MAX_STRING, "%s_%s_%s_saveTag%03u_trial%04u", dlStatus->subject, dateStr, dlStatus->protocol, dlStatus->saveTag, trialStatus->trialId); fieldNum = mxAddField(mxTrial, "trialIdStr"); mxSetFieldByNumber(mxTrial, 0, fieldNum, mxCreateString(trialIdStr)); // save wallclock matlab datenums for time and stop timestamps fieldNum = mxAddField(mxTrial, "wallclockStart"); mxTemp = mxCreateNumericMatrix(1, 1, mxDOUBLE_CLASS, mxREAL); ((double*)mxGetData(mxTemp))[0] = wallclockStart; mxSetFieldByNumber(mxTrial, 0, fieldNum, mxTemp); fieldNum = mxAddField(mxTrial, "tsStart"); mxTemp = mxCreateNumericMatrix(1, 1, mxDOUBLE_CLASS, mxREAL); ((double*)mxGetData(mxTemp))[0] = timestampStart; mxSetFieldByNumber(mxTrial, 0, fieldNum, mxTemp); fieldNum = mxAddField(mxTrial, "tsStop"); mxTemp = mxCreateNumericMatrix(1, 1, mxDOUBLE_CLASS, mxREAL); ((double*)mxGetData(mxTemp))[0] = timestampEnd; mxSetFieldByNumber(mxTrial, 0, fieldNum, mxTemp); // compute duration in ms, add one to match timestamps 0...N double duration = round((trialStatus->timestampEnd - trialStatus->timestampStart)) + 1; fieldNum = mxAddField(mxTrial, "duration"); mxTemp = mxCreateNumericMatrix(1, 1, mxDOUBLE_CLASS, mxREAL); ((double*)mxGetData(mxTemp))[0] = duration; mxSetFieldByNumber(mxTrial, 0, fieldNum, mxTemp); fieldNum = mxAddField(mxTrial, "format"); mxSetFieldByNumber(mxTrial, 0, fieldNum, mxCreateString("tds3")); fieldNum = mxAddField(mxTrial, "timeUnits"); mxSetFieldByNumber(mxTrial, 0, fieldNum, mxCreateString("ms")); }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { /* Check for proper number of arguments. */ if (nrhs < 1 || nrhs > 3) error(SCRIPT_NAME ": Improper usage!"); if( !mxIsChar(prhs[0]) && !is_mex_fid( prhs[0] ) ) { error( SCRIPT_NAME ": expected file name or file descriptor as the first argument!"); } int width, height; bool writeMode = false; if( nrhs == 3 ) { if( !is_mex_scalar( prhs[1]) || !is_mex_scalar( prhs[2] ) ) { error( SCRIPT_NAME ": expected frame dimmensions as argument 2 and 3"); } height = (int)*mxGetPr( prhs[1] ); width = (int)*mxGetPr( prhs[2] ); writeMode = true; } if( nrhs == 2 ) { if( !mxIsNumeric( prhs[1] ) || mxGetM( prhs[1] ) != 1 || mxGetN( prhs[1] ) != 2) { error( SCRIPT_NAME ": expected 2-column matrix as argument 2"); } double *dim = mxGetPr( prhs[1] ); height = (int)dim[0]; width = (int)dim[1]; writeMode = true; } if( writeMode && (width < 1 || height < 1 || width > 65535 || height > 65535 ) ) { error( SCRIPT_NAME ": Illegal frame size"); } // Open file for reading or writing int fid; if( mxIsChar( prhs[0] ) ) { // File name given char *fileName = get_mex_string( prhs[0] ); if( writeMode ) { if( !strcmp( "stdout", fileName ) ) fid = 1; else { fid = open( fileName, O_CREAT | O_TRUNC | O_RDWR | O_BINARY, S_IREAD | S_IWRITE ); if( fid == -1 ) { error( SCRIPT_NAME ": cannot open file for writing!"); } } } else { if( !strcmp( "stdin", fileName ) ) fid = 0; else { fid = open( fileName, O_RDONLY | O_BINARY ); if( fid == -1 ) { error( SCRIPT_NAME ": cannot open file for reading!"); } } } mxFree( fileName ); } else { // File descriptor given double *p_fid = mxGetPr( prhs[0] ); fid = dup( (int)p_fid[0] ); } mxArray *pfs_stream = mxCreateStructMatrix( 1, 1, 0, NULL ); plhs[0] = pfs_stream; int fnum; fnum = mxAddField( pfs_stream, "FID" ); mxSetFieldByNumber( pfs_stream, 0, fnum, create_mex_double( fid ) ); fnum = mxAddField( pfs_stream, "MODE" ); if( writeMode ) mxSetFieldByNumber( pfs_stream, 0, fnum, create_mex_string("W") ); else mxSetFieldByNumber( pfs_stream, 0, fnum, create_mex_string("R") ); fnum = mxAddField( pfs_stream, "EOF" ); mxSetFieldByNumber( pfs_stream, 0, fnum, mxCreateLogicalScalar( false ) ); if( writeMode ) { fnum = mxAddField( pfs_stream, "columns" ); mxSetFieldByNumber( pfs_stream, 0, fnum, create_mex_double( width ) ); fnum = mxAddField( pfs_stream, "rows" ); mxSetFieldByNumber( pfs_stream, 0, fnum, create_mex_double( height ) ); fnum = mxAddField( pfs_stream, "channels" ); mxArray *channels = mxCreateStructMatrix( 1, 1, 0, NULL ); mxSetFieldByNumber( pfs_stream, 0, fnum, channels ); } }
void addEventGroupFields(mxArray* mxTrial, mxArray* mxGroupMeta, const GroupInfo* pg, unsigned trialIdx, timestamp_t timeTrialStart, bool useGroupPrefix, unsigned groupMetaIndex) { // field names will be groupName_<eventName> // but the signal always comes in as .eventName and the contents are the name // of the event // // so: build up a trie where the eventName is the key and a TimestampBuffer is the value Trie* eventTrie = trie_create(); Trie* trieNode; // get timestamp buffer from group buffer const TimestampBuffer* groupTimestamps = pg->tsBuffers + trialIdx; const char* groupName = pg->name; // for now check that the event group has only 1 signal and it's type is EventName bool printError = false; if(pg->nSignals != 1) printError = true; else if(pg->signals[0]->type != SIGNAL_TYPE_EVENTNAME) printError = true; if(printError) { logError("Event groups must have 1 signal of type event name"); return; } const SignalDataBuffer*psdb = pg->signals[0]; const SampleBuffer* ptb = psdb->buffers + trialIdx; char eventName[MAX_SIGNAL_NAME]; char* dataPtr = (char*)ptb->data; for(unsigned iSample = 0; iSample < ptb->nSamples; iSample++) { // first copy string into buffer, then zero terminate it unsigned bytesThisSample = ptb->bytesEachSample[iSample]; // TODO add overflow detection memcpy(eventName, dataPtr, bytesThisSample); dataPtr += bytesThisSample; eventName[bytesThisSample] = '\0'; //logError("Event %s\n", eventName); // search for this eventName in the trie EventTrieInfo* info = (EventTrieInfo*)trie_lookup(eventTrie, eventName); if(info == NULL) { // doesn't exist, give it a TimestampBuffer info = (EventTrieInfo*)CALLOC(sizeof(EventTrieInfo), 1); strncpy(info->eventName, eventName, MAX_SIGNAL_NAME); trie_add(eventTrie, eventName, info); } // push this timestamp to the buffer bool success = pushTimestampToTimestampBuffer(&info->tsBuffer, groupTimestamps->timestamps[iSample]); if(!success) { logError("Issue building event fields\n"); return; } } // now iterate over the eventName trie and add each field unsigned nEventNames = trie_count(eventTrie); mxArray* mxSignalNames = mxCreateCellMatrix(nEventNames, 1); unsigned iEvent = 0; unsigned fieldNum = 0; trieNode = trie_get_first(eventTrie); char fieldName[MAX_SIGNAL_NAME]; while(trieNode != NULL) { EventTrieInfo* info = (EventTrieInfo*)trieNode->value; // build the groupName_eventName field name if(useGroupPrefix) snprintf(fieldName, MAX_SIGNAL_NAME, "%s_%s", groupName, info->eventName); else strncpy(fieldName, info->eventName, MAX_SIGNAL_NAME); // store the name of the field in the cell array mxSetCell(mxSignalNames, iEvent, mxCreateString(fieldName)); // copy timestamps from buffer to double vector mxArray* mxTimestamps = mxCreateNumericMatrix(info->tsBuffer.nSamples, 1, mxDOUBLE_CLASS, mxREAL); // subtract off trial start time and convert to ms, rounding at ms double_t* buffer = (double_t*)mxGetData(mxTimestamps); for(unsigned i = 0; i < info->tsBuffer.nSamples; i++) buffer[i] = round((info->tsBuffer.timestamps[i] - timeTrialStart)); // add event time list field to trial struct fieldNum = mxAddField(mxTrial, fieldName); mxSetFieldByNumber(mxTrial, 0, fieldNum, mxTimestamps); // get the next event in the trie trieNode = trie_get_next(trieNode); iEvent++; } // free the event Trie resources trie_flush(eventTrie, FREE); // add signal names to the meta array fieldNum = mxGetFieldNumber(mxGroupMeta, "signalNames"); if(fieldNum == -1) fieldNum = mxAddField(mxGroupMeta, "signalNames"); mxSetFieldByNumber(mxGroupMeta, groupMetaIndex, fieldNum, mxSignalNames); }
EXPORT bool glx_init(glxlink *mod) { gl_verbose("initializing matlab link"); gl_verbose("PATH=%s", getenv("PATH")); // initialize matlab engine MATLABLINK *matlab = (MATLABLINK*)mod->get_data(); matlab->status = 0; #ifdef WIN32 if ( matlab->command ) matlab->engine = engOpen(matlab->command); else matlab->engine = engOpenSingleUse(NULL,NULL,&matlab->status); if ( matlab->engine==NULL ) { gl_error("matlab engine start failed, status code is '%d'", matlab->status); return false; } #else matlab->engine = engOpen(matlab->command); if ( matlab->engine==NULL ) { gl_error("matlab engine start failed"); return false; } #endif // set the output buffer if ( matlab->output_buffer!=NULL ) engOutputBuffer(matlab->engine,matlab->output_buffer,(int)matlab->output_size); // setup matlab engine engSetVisible(matlab->engine,window_show(matlab)); gl_debug("matlab link is open"); // special values needed by matlab mxArray *ts_never = mxCreateDoubleScalar((double)(TIMESTAMP)TS_NEVER); engPutVariable(matlab->engine,"TS_NEVER",ts_never); mxArray *ts_error = mxCreateDoubleScalar((double)(TIMESTAMP)TS_INVALID); engPutVariable(matlab->engine,"TS_ERROR",ts_error); mxArray *gld_ok = mxCreateDoubleScalar((double)(bool)true); engPutVariable(matlab->engine,"GLD_OK",gld_ok); mxArray *gld_err = mxCreateDoubleScalar((double)(bool)false); engPutVariable(matlab->engine,"GLD_ERROR",gld_err); // set the workdir if ( strcmp(matlab->workdir,"")!=0 ) { #ifdef WIN32 _mkdir(matlab->workdir); #else mkdir(matlab->workdir,0750); #endif if ( matlab->workdir[0]=='/' ) matlab_exec(matlab,"cd '%s'", matlab->workdir); else matlab_exec(matlab,"cd '%s/%s'", getcwd(NULL,0),matlab->workdir); } // run the initialization command(s) if ( matlab->init ) { mxArray *ans = matlab_exec(matlab,"%s",matlab->init); if ( ans && mxIsDouble(ans) && (bool)*mxGetPr(ans)==false ) { gl_error("matlab init failed"); return false; } else if ( ans && mxIsChar(ans) ) { int buflen = (mxGetM(ans) * mxGetN(ans)) + 1; char *string =(char*)malloc(buflen); int status_error = mxGetString(ans, string, buflen); if (status_error == 0) { gl_error("'%s'",string); return false; } else { gl_error("Did not catch Matlab error"); return false; } } } if ( matlab->rootname!=NULL ) { // build gridlabd data mwSize dims[] = {1,1}; mxArray *gridlabd_struct = mxCreateStructArray(2,dims,0,NULL); /////////////////////////////////////////////////////////////////////////// // build global data LINKLIST *item; mxArray *global_struct = mxCreateStructArray(2,dims,0,NULL); for ( item=mod->get_globals() ; item!=NULL ; item=mod->get_next(item) ) { char *name = mod->get_name(item); GLOBALVAR *var = mod->get_globalvar(item); mxArray *var_struct = NULL; mwIndex var_index; if ( var==NULL ) continue; // do not map module or structured globals if ( strchr(var->prop->name,':')!=NULL ) { // ignore module globals here } else if ( strchr(var->prop->name,'.')!=NULL ) { char struct_name[256]; if ( sscanf(var->prop->name,"%[^.]",struct_name)==0 ) { gld_property prop(var); var_index = mxAddField(global_struct,prop.get_name()); var_struct = matlab_create_value(&prop); if ( var_struct!=NULL ) { //mod->add_copyto(var->prop->addr,mxGetData(var_struct)); mxSetFieldByNumber(global_struct,0,var_index,var_struct); } } } else // simple data { gld_property prop(var); var_index = mxAddField(global_struct,prop.get_name()); var_struct = matlab_create_value(&prop); if ( var_struct!=NULL ) { //mod->add_copyto(var->prop->addr,mxGetData(var_struct)); mxSetFieldByNumber(global_struct,0,var_index,var_struct); } } // update export list if ( var_struct!=NULL ) { mod->set_addr(item,(void*)var_struct); mod->set_index(item,(size_t)var_index); } } // add globals structure to gridlabd structure mwIndex gridlabd_index = mxAddField(gridlabd_struct,"global"); mxSetFieldByNumber(gridlabd_struct,0,gridlabd_index,global_struct); /////////////////////////////////////////////////////////////////////////// // build module data dims[0] = dims[1] = 1; mxArray *module_struct = mxCreateStructArray(2,dims,0,NULL); // add modules for ( MODULE *module = callback->module.getfirst() ; module!=NULL ; module=module->next ) { // create module info struct mwIndex dims[] = {1,1}; mxArray *module_data = mxCreateStructArray(2,dims,0,NULL); mwIndex module_index = mxAddField(module_struct,module->name); mxSetFieldByNumber(module_struct,0,module_index,module_data); // create version info struct const char *version_fields[] = {"major","minor"}; mxArray *version_data = mxCreateStructArray(2,dims,sizeof(version_fields)/sizeof(version_fields[0]),version_fields); mxArray *major_data = mxCreateDoubleScalar((double)module->major); mxArray *minor_data = mxCreateDoubleScalar((double)module->minor); mxSetFieldByNumber(version_data,0,0,major_data); mxSetFieldByNumber(version_data,0,1,minor_data); // attach version info to module info mwIndex version_index = mxAddField(module_data,"version"); mxSetFieldByNumber(module_data,0,version_index,version_data); } gridlabd_index = mxAddField(gridlabd_struct,"module"); mxSetFieldByNumber(gridlabd_struct,0,gridlabd_index,module_struct); /////////////////////////////////////////////////////////////////////////// // build class data dims[0] = dims[1] = 1; mxArray *class_struct = mxCreateStructArray(2,dims,0,NULL); gridlabd_index = mxAddField(gridlabd_struct,"class"); mxSetFieldByNumber(gridlabd_struct,0,gridlabd_index,class_struct); mwIndex class_id[1024]; // index into class struct memset(class_id,0,sizeof(class_id)); // add classes for ( CLASS *oclass = callback->class_getfirst() ; oclass!=NULL ; oclass=oclass->next ) { // count objects in this class mwIndex dims[] = {0,1}; for ( item=mod->get_objects() ; item!=NULL ; item=mod->get_next(item) ) { OBJECT *obj = mod->get_object(item); if ( obj==NULL || obj->oclass!=oclass ) continue; dims[0]++; } if ( dims[0]==0 ) continue; mxArray *runtime_struct = mxCreateStructArray(2,dims,0,NULL); // add class mwIndex class_index = mxAddField(class_struct,oclass->name); mxSetFieldByNumber(class_struct,0,class_index,runtime_struct); // add properties to class for ( PROPERTY *prop=oclass->pmap ; prop!=NULL && prop->oclass==oclass ; prop=prop->next ) { mwIndex dims[] = {1,1}; mxArray *property_struct = mxCreateStructArray(2,dims,0,NULL); mwIndex runtime_index = mxAddField(runtime_struct,prop->name); mxSetFieldByNumber(runtime_struct,0,runtime_index,property_struct); } // add objects to class for ( item=mod->get_objects() ; item!=NULL ; item=mod->get_next(item) ) { OBJECT *obj = mod->get_object(item); if ( obj==NULL || obj->oclass!=oclass ) continue; mwIndex index = class_id[obj->oclass->id]++; // add properties to class for ( PROPERTY *prop=oclass->pmap ; prop!=NULL && prop->oclass==oclass ; prop=prop->next ) { gld_property p(obj,prop); mxArray *data = matlab_create_value(&p); mxSetField(runtime_struct,index,prop->name,data); } // update export list mod->set_addr(item,(void*)runtime_struct); mod->set_index(item,(size_t)index); } } /////////////////////////////////////////////////////////////////////////// // build the object data dims[0] = 0; for ( item=mod->get_objects() ; item!=NULL ; item=mod->get_next(item) ) { if ( mod->get_object(item)!=NULL ) dims[0]++; } dims[1] = 1; memset(class_id,0,sizeof(class_id)); const char *objfields[] = {"name","class","id","parent","rank","clock","valid_to","schedule_skew", "latitude","longitude","in","out","rng_state","heartbeat","lock","flags"}; mxArray *object_struct = mxCreateStructArray(2,dims,sizeof(objfields)/sizeof(objfields[0]),objfields); mwIndex n=0; for ( item=mod->get_objects() ; item!=NULL ; item=mod->get_next(item) ) { OBJECT *obj = mod->get_object(item); if ( obj==NULL ) continue; class_id[obj->oclass->id]++; // index into class struct const char *objname[] = {obj->name&&isdigit(obj->name[0])?NULL:obj->name}; const char *oclassname[] = {obj->oclass->name}; if (obj->name) mxSetFieldByNumber(object_struct,n,0,mxCreateCharMatrixFromStrings(mwSize(1),objname)); mxSetFieldByNumber(object_struct,n,1,mxCreateCharMatrixFromStrings(mwSize(1),oclassname)); mxSetFieldByNumber(object_struct,n,2,mxCreateDoubleScalar((double)class_id[obj->oclass->id])); if (obj->parent) mxSetFieldByNumber(object_struct,n,3,mxCreateDoubleScalar((double)obj->parent->id+1)); mxSetFieldByNumber(object_struct,n,4,mxCreateDoubleScalar((double)obj->rank)); mxSetFieldByNumber(object_struct,n,5,mxCreateDoubleScalar((double)obj->clock)); mxSetFieldByNumber(object_struct,n,6,mxCreateDoubleScalar((double)obj->valid_to)); mxSetFieldByNumber(object_struct,n,7,mxCreateDoubleScalar((double)obj->schedule_skew)); if ( isfinite(obj->latitude) ) mxSetFieldByNumber(object_struct,n,8,mxCreateDoubleScalar((double)obj->latitude)); if ( isfinite(obj->longitude) ) mxSetFieldByNumber(object_struct,n,9,mxCreateDoubleScalar((double)obj->longitude)); mxSetFieldByNumber(object_struct,n,10,mxCreateDoubleScalar((double)obj->in_svc)); mxSetFieldByNumber(object_struct,n,11,mxCreateDoubleScalar((double)obj->out_svc)); mxSetFieldByNumber(object_struct,n,12,mxCreateDoubleScalar((double)obj->rng_state)); mxSetFieldByNumber(object_struct,n,13,mxCreateDoubleScalar((double)obj->heartbeat)); mxSetFieldByNumber(object_struct,n,14,mxCreateDoubleScalar((double)obj->lock)); mxSetFieldByNumber(object_struct,n,15,mxCreateDoubleScalar((double)obj->flags)); n++; } gridlabd_index = mxAddField(gridlabd_struct,"object"); mxSetFieldByNumber(gridlabd_struct,0,gridlabd_index,object_struct); /////////////////////////////////////////////////////////////////////////// // post the gridlabd structure matlab->root = gridlabd_struct; engPutVariable(matlab->engine,matlab->rootname,matlab->root); } /////////////////////////////////////////////////////////////////////////// // build the import/export data for ( LINKLIST *item=mod->get_exports() ; item!=NULL ; item=mod->get_next(item) ) { OBJECTPROPERTY *objprop = mod->get_export(item); if ( objprop==NULL ) continue; // add to published items gld_property prop(objprop->obj,objprop->prop); item->addr = (mxArray*)matlab_create_value(&prop); engPutVariable(matlab->engine,item->name,(mxArray*)item->addr); } for ( LINKLIST *item=mod->get_imports() ; item!=NULL ; item=mod->get_next(item) ) { OBJECTPROPERTY *objprop = mod->get_import(item); if ( objprop==NULL ) continue; // check that not already in export list LINKLIST *export_item; bool found=false; for ( export_item=mod->get_exports() ; export_item!=NULL ; export_item=mod->get_next(export_item) ) { OBJECTPROPERTY *other = mod->get_export(item); if ( memcmp(objprop,other,sizeof(OBJECTPROPERTY)) ) found=true; } if ( !found ) { gld_property prop(objprop->obj,objprop->prop); item->addr = (mxArray*)matlab_create_value(&prop); engPutVariable(matlab->engine,item->name,(mxArray*)item->addr); } } static int32 matlab_flag = 1; gl_global_create("MATLAB",PT_int32,&matlab_flag,PT_ACCESS,PA_REFERENCE,PT_DESCRIPTION,"indicates that MATLAB is available",NULL); mod->last_t = gl_globalclock; return true; }
mxArray * mp_create_mxDict_from_dict(MP_Dict_c *dict) { const char *func = "mp_create_mxDict_from_dict"; map<string,string,mp_ltstring> *paramMap; mxArray *mxBlockCell; mxArray *mxBlock; mxArray *mxDict; mxArray *mxTable; MP_Block_c *block; int numDictFieldNames; int iFieldNumber; const char *dictFieldNames[] = {"block"}; // Case of a NULL input if(NULL==dict) { mp_error_msg(func,"the input is NULL\n"); return(NULL); } // Create the block cell mxBlockCell = mxCreateCellMatrix((mwSize)dict->numBlocks,(mwSize)1); if(mxBlockCell == NULL) { mp_error_msg(func,"could not create block cell\n"); return(NULL); } // Loop to create each block for (unsigned int i=0; i < dict->numBlocks; i++) { block = dict->block[i]; if(block == NULL) { mp_error_msg(func,"block 0<=i=%d<%d is NULL\n",i,dict->numBlocks); mxDestroyArray(mxBlockCell); return(NULL); } paramMap = block->get_block_parameters_map(); if (NULL==paramMap) { mp_error_msg(func,"empty paramMap for block 0<=i=%d<%d\n", i,dict->numBlocks); mxDestroyArray(mxBlockCell); return(NULL); } // Create mxBlock mxBlock = mxCreateStructMatrix((mwSize)1,(mwSize)1,0,NULL); if(mxBlock == NULL) { mp_error_msg(func,"could not create block 0<=i=%d<%d\n",i,dict->numBlocks); mxDestroyArray(mxBlockCell); return(NULL); } // Add all fields map<string, string, mp_ltstring>::const_iterator iter; for ( iter = (*paramMap).begin(); iter != (*paramMap).end(); iter++ ) { // TODO: we shouldn't need to know what fields are possible in the first place if(!strcmp(iter->first.c_str(),"data")) { // Adding the table Field mxAddField(mxBlock,"data"); if((mxTable = anywaveTableRead(paramMap, NULL)) == NULL) { mp_error_msg(func,"could not load the anywaveTable %s\n",iter->second.c_str()); mxDestroyArray(mxBlockCell); return(NULL); } iFieldNumber = mxGetFieldNumber(mxBlock, "data"); mxSetCell(mxBlock,iFieldNumber,mxTable); } else { // Add the field mxAddField(mxBlock,iter->first.c_str()); // TODO: Here should query the type of the field to set it appropriately! // Set the field value mxArray *mxTmp = mxCreateString(iter->second.c_str()); if(NULL==mxTmp) { mp_error_msg(func,"could not create field %s in block 0<=i=%d<%d\n",iter->second.c_str(),i,dict->numBlocks); mxDestroyArray(mxBlockCell); return(NULL); } mxSetField(mxBlock,0,iter->first.c_str(),mxTmp); // If the paramMap contains a file link to xml, then go search it ! // TODO: we shouldn't need to know what fields are possible in the first place if(!strcmp(iter->first.c_str(),"tableFileName")) { // Adding the table Field mxAddField(mxBlock,"data"); if((mxTable = anywaveTableRead(paramMap, (char *)iter->second.c_str())) == NULL) { mp_error_msg(func,"could not load the anywaveTable %s\n",iter->second.c_str()); mxDestroyArray(mxBlockCell); return(NULL); } iFieldNumber = mxGetFieldNumber(mxBlock, "data"); mxSetCell(mxBlock,iFieldNumber,mxTable); } } } // Put the mxBlock in the mxBlockCell mxSetCell(mxBlockCell,i,mxBlock); // Delete tmp variables delete paramMap; } // Create the output information structure // dict.block{numBlocks} numDictFieldNames = 1; mxDict = mxCreateStructMatrix((mwSize)1,(mwSize)1,numDictFieldNames,dictFieldNames); if(NULL==mxDict) { mp_error_msg(func,"could not create dict\n"); mxDestroyArray(mxBlockCell); return(NULL); } mxSetField(mxDict,0,"block",mxBlockCell); return(mxDict); }
void mexFunction( int nlhs, mxArray *plhs[],int nrhs, const mxArray *prhs[] ) { double nrecords, record_offset; mxArray *output_array; mxArray *itemArray, *frameArray, *timestampArray; unsigned char *pitem, *pframe; uint32_t *ptimestamp; int32_t i; char strFileName[MAXSTRING]; FILE *fid=NULL; mxArray *posstruct, *xArray, *yArray; int16_t *px, *py; int j; unsigned char y; unsigned char fieldmask=0; char nfields=0; /*create empty outputs*/ for (i=0; i<nlhs; i++) { plhs[i] = mxCreateDoubleMatrix(0,0,mxREAL); } if (nrhs<3) mexErrMsgTxt("Incorrect number of input arguments."); if (!mxIsChar(prhs[0])) mexErrMsgTxt("First argument should be a string"); if (!mxIsDouble(prhs[1])) mexErrMsgTxt("Second argument should be a double"); if (!mxIsDouble(prhs[2])) mexErrMsgTxt("Third argument should be a double"); if (nrhs>3) { if (!mxIsDouble(prhs[3])) mexErrMsgTxt("Fourth argument should be a double"); fieldmask = (unsigned char) mxGetScalar(prhs[3]); } else { fieldmask = 15; } if (fieldmask<1 || fieldmask>15) mexErrMsgTxt("Invalid fieldmask"); mxGetString(prhs[0], strFileName, MAXSTRING); if ( (fid = fopen(strFileName, "rb")) == NULL ) mexErrMsgTxt("Unable to open file"); nrecords = mxGetScalar(prhs[2]); record_offset = mxGetScalar(prhs[1]); fseek(fid, record_offset, 0); posstruct = mxCreateStructMatrix(nrecords,1,2,field_names_pos); itemArray = mxCreateNumericMatrix(nrecords, 1, mxUINT8_CLASS, mxREAL); pitem = (unsigned char*) mxGetPr(itemArray); frameArray = mxCreateNumericMatrix(nrecords, 1, mxUINT8_CLASS, mxREAL); pframe = (unsigned char*)mxGetPr(frameArray); timestampArray = mxCreateNumericMatrix(nrecords, 1, mxUINT32_CLASS, mxREAL); ptimestamp = (uint32_t*)mxGetPr(timestampArray); for (i=0; i<nrecords; i++) { fread(&(pitem[i]), sizeof(char), 1, fid); fread(&(pframe[i]), sizeof(char), 1, fid); fread(&(ptimestamp[i]), sizeof(uint32_t), 1, fid); /* only when we want position data...*/ if (fieldmask & 8) { xArray = mxCreateNumericMatrix(pitem[i], 1, mxINT16_CLASS, mxREAL); yArray = mxCreateNumericMatrix(pitem[i], 1, mxINT16_CLASS, mxREAL); px = (int16_t*)mxGetPr(xArray); py = (int16_t*)mxGetPr(yArray); for (j=0; j<pitem[i]; j++) { fread(&(px[j]), sizeof(short), 1, fid); fread(&y, sizeof(char), 1, fid); py[j] = (int16_t) y; } mxSetFieldByNumber(posstruct, i, 0, xArray); mxSetFieldByNumber(posstruct, i, 1, yArray); } else fseek(fid, pitem[i] * 3, SEEK_CUR); } /*create output structure*/ output_array = mxCreateStructMatrix(1,1,0,NULL); if (fieldmask & 1) { mxAddField(output_array, "nitems"); mxSetFieldByNumber(output_array, 0, 0, itemArray); nfields++; } if (fieldmask & 2) { mxAddField(output_array, "frame"); mxSetFieldByNumber(output_array, 0, nfields, frameArray); nfields++; } if (fieldmask & 4) { mxAddField(output_array, "timestamp"); mxSetFieldByNumber(output_array, 0, nfields, timestampArray); nfields++; } if (fieldmask & 8) { mxAddField(output_array, "pos"); mxSetFieldByNumber(output_array, 0, nfields, posstruct); } plhs[0] = output_array; }
/* * a l l o c a t e O u t p u t s */ returnValue allocateOutputs( int nlhs, mxArray* plhs[], int_t nV, int_t nC = 0, int_t nP = 1, int_t handle = -1 ) { /* Create output vectors and assign pointers to them. */ int_t curIdx = 0; /* handle */ if ( handle >= 0 ) plhs[curIdx++] = mxCreateDoubleMatrix( 1, 1, mxREAL ); /* x */ plhs[curIdx++] = mxCreateDoubleMatrix( nV, nP, mxREAL ); if ( nlhs > curIdx ) { /* fval */ plhs[curIdx++] = mxCreateDoubleMatrix( 1, nP, mxREAL ); if ( nlhs > curIdx ) { /* exitflag */ plhs[curIdx++] = mxCreateDoubleMatrix( 1, nP, mxREAL ); if ( nlhs > curIdx ) { /* iter */ plhs[curIdx++] = mxCreateDoubleMatrix( 1, nP, mxREAL ); if ( nlhs > curIdx ) { /* lambda */ plhs[curIdx++] = mxCreateDoubleMatrix( nV+nC, nP, mxREAL ); if ( nlhs > curIdx ) { /* setup auxiliary output struct */ mxArray* auxOutput = mxCreateStructMatrix( 1,1,0,0 ); int_t curFieldNum; /* working set */ curFieldNum = mxAddField( auxOutput,"workingSetB" ); if ( curFieldNum >= 0 ) mxSetFieldByNumber( auxOutput,0,curFieldNum,mxCreateDoubleMatrix( nV, nP, mxREAL ) ); curFieldNum = mxAddField( auxOutput,"workingSetC" ); if ( curFieldNum >= 0 ) mxSetFieldByNumber( auxOutput,0,curFieldNum,mxCreateDoubleMatrix( nC, nP, mxREAL ) ); curFieldNum = mxAddField( auxOutput,"cpuTime" ); if ( curFieldNum >= 0 ) mxSetFieldByNumber( auxOutput,0,curFieldNum,mxCreateDoubleMatrix( 1, nP, mxREAL ) ); plhs[curIdx] = auxOutput; } } } } } return SUCCESSFUL_RETURN; }
mxArray* ParseChildNodes(pugi::xml_node& node) { mxArray *children = NULL; pugi::xml_attribute tempAttr = node.first_attribute(); if (HasChildNodes(node) || tempAttr != NULL) { mxArray *attributes = ParseAttributes(node); std::vector<std::string> distinctNames; std::vector<std::string> allChildNodeNames; std::vector<pugi::xml_node> childNodes; std::size_t numChildNodes; childNodes = GetChildNodes(node); numChildNodes = childNodes.size(); for (int i = 0; i < numChildNodes; i++) { allChildNodeNames.push_back(childNodes.at(i).name()); } distinctNames = GetDistinctNodeNames(allChildNodeNames); /* Patch for bypassing the variable-length arrays problems of modern C++ compilers */ std::vector<const char*> distinctChildNodeNames; std::transform(distinctNames.begin(), distinctNames.end(), std::back_inserter(distinctChildNodeNames), [](const std::string & str) { // initialize empty char array char *output = new char[str.size()+1]; std::strcpy(output, str.c_str()); return output; }); std::vector<std::string> processedNames; children = mxCreateStructMatrix(1, 1, (int)distinctNames.size(), &distinctChildNodeNames[0]); for (int idx = 0; idx < childNodes.size(); idx++) { pugi::xml_node theChild = childNodes.at(idx); std::string type = node_types[theChild.type()]; std::string temp = theChild.name(); std::string val = theChild.value(); const char *namey[1] = {}; namey[0] = temp.c_str(); mxArray *glhf = mxGetField(children, 0, namey[0]); int indexOfMatchingItem = mxGetFieldNumber(children, namey[0]); if (!(strcmp(type.c_str(), "pcdata") == 0) && !(strcmp(type.c_str(), "comment") == 0) && !(strcmp(type.c_str(), "cdata") == 0)) { //XML allows the same elements to be defined multiple times, put each in a different cell if (std::find(processedNames.begin(), processedNames.end(), temp) != processedNames.end()) { if ( glhf != NULL ) { if (!mxIsCell(glhf)) { mxArray *temp = glhf; glhf = mxCreateCellMatrix(1, 2); mxSetCell(glhf, 0, temp); mxSetCell(glhf, 1, ParseChildNodes(theChild)); mxSetCell(children, indexOfMatchingItem, glhf); } else { std::size_t numberItemsInCell = mxGetN(glhf); mxArray *temp = glhf; glhf = mxCreateCellMatrix(1, numberItemsInCell + 1); for (int i = 0; i < numberItemsInCell; i++) { mxSetCell(glhf, i, mxGetCell(temp, i)); } mxSetCell(glhf, numberItemsInCell, ParseChildNodes(theChild)); mxSetCell(children, indexOfMatchingItem, glhf); } } } //add previously unknown (new) element to the structure else { mxSetCell(children, indexOfMatchingItem, ParseChildNodes(theChild)); } processedNames.push_back(temp); } else { const char *typeFieldNames[1] = {"Text"}; std::string value = theChild.value(); mxArray *matValue = mxCreateString(value.c_str()); if (strcmp(type.c_str(), "cdata") == 0) { typeFieldNames[0] = "CDATA"; } else if (strcmp(type.c_str(), "comment") == 0) { typeFieldNames[0] = "Comment"; } children = mxCreateStructMatrix(1, 1, 1, typeFieldNames); mxSetFieldByNumber(children, 0, 0, matValue); processedNames.push_back(temp); } } if (attributes != NULL) { const char *attrFieldName = "Attributes"; mxAddField(children, attrFieldName); mxSetField(children, 0, attrFieldName, attributes); } } return children; }