void StimulusDisplay::getDisplayBounds(const Datum &display_info, GLdouble &left, GLdouble &right, GLdouble &bottom, GLdouble &top) { if(display_info.getDataType() == M_DICTIONARY && display_info.hasKey(M_DISPLAY_WIDTH_KEY) && display_info.hasKey(M_DISPLAY_HEIGHT_KEY) && display_info.hasKey(M_DISPLAY_DISTANCE_KEY)){ GLdouble width_unknown_units = display_info.getElement(M_DISPLAY_WIDTH_KEY); GLdouble height_unknown_units = display_info.getElement(M_DISPLAY_HEIGHT_KEY); GLdouble distance_unknown_units = display_info.getElement(M_DISPLAY_DISTANCE_KEY); GLdouble half_width_deg = (180. / M_PI) * atan((width_unknown_units/2.)/distance_unknown_units); GLdouble half_height_deg = half_width_deg * height_unknown_units / width_unknown_units; //GLdouble half_height_deg = (180. / M_PI) * atan((height_unknown_units/2.)/distance_unknown_units); left = -half_width_deg; right = half_width_deg; top = half_height_deg; bottom = -half_height_deg; } else { left = M_STIMULUS_DISPLAY_LEFT_EDGE; right = M_STIMULUS_DISPLAY_RIGHT_EDGE; top = M_STIMULUS_DISPLAY_TOP_EDGE; bottom = M_STIMULUS_DISPLAY_BOTTOM_EDGE; } }
int DataFileManager::openFile(const Datum &oeDatum) { std::string dFile(oeDatum.getElement(DATA_FILE_FILENAME).getString()); DatumFileOptions opt = (DatumFileOptions)oeDatum.getElement(DATA_FILE_OPTIONS).getInteger(); if(dFile.size() == 0) { merror(M_FILE_MESSAGE_DOMAIN, "Attempt to open data file with an empty name"); return -1; } return openFile(dFile, opt); }
// overridable base class method // assumes data have already been checked for proper dictionary, name. CalibratorRequestedAction Calibrator::getRequestedAction(Datum dictionaryData) { // check what action is requested (e.g. update parameters) if (!(dictionaryData.hasKey(R_CALIBRATOR_ACTION))) { mwarning(M_SYSTEM_MESSAGE_DOMAIN, "Request sent to calibrator %s that did not contain an action field was ignored.", uniqueCalibratorName.c_str()); return(CALIBRATOR_NO_ACTION); } Datum actionData = dictionaryData.getElement(R_CALIBRATOR_ACTION); if (!(actionData.getDataType() == M_STRING)) { // check if name field is a string mwarning(M_SYSTEM_MESSAGE_DOMAIN, "Request sent to calibrator %s that did not contain a string in the action field was ignored.", uniqueCalibratorName.c_str()); return(CALIBRATOR_NO_ACTION); } if (actionData.getString() == R_CALIBRATOR_ACTION_SET_PARAMETERS) { // check is name field matches the name of this calibrator if (VERBOSE_EYE_CALIBRATORS>1) mprintf( "Calibrator %s successfully received request for to update its parameters to contained values.", uniqueCalibratorName.c_str()); return CALIBRATOR_ACTION_SET_PARAMS_TO_CONTAINED; } else if (actionData.getString() == R_CALIBRATOR_ACTION_SET_PARAMETERS_TO_DEFAULTS) { if (VERBOSE_EYE_CALIBRATORS>1) mprintf("Calibrator %s successfully received request for to update its parameters to defaults.", uniqueCalibratorName.c_str()); return CALIBRATOR_ACTION_SET_PARAMS_TO_DEFAULTS; } else { mwarning(M_SYSTEM_MESSAGE_DOMAIN, "Calibrator %s received a request, but action was unknown. Request ignored", uniqueCalibratorName.c_str()); return CALIBRATOR_NO_ACTION; } return (CALIBRATOR_NO_ACTION); }
int DataFileManager::openFile(const Datum &oeDatum) { std::string dFile(oeDatum.getElement(DATA_FILE_FILENAME).getString()); DatumFileOptions opt = (DatumFileOptions)oeDatum.getElement(DATA_FILE_OPTIONS).getInteger(); if(dFile.size() == 0) { merror(M_FILE_MESSAGE_DOMAIN, "Attempt to open an empty data file"); return -1; } if(GlobalDataFileManager->isFileOpen()) { mwarning(M_FILE_MESSAGE_DOMAIN, "Data file already open at %s", (GlobalDataFileManager->getFilename()).c_str()); return -1; } return openFile(dFile, opt); }
// compute the function value(s) with the current parameters //bool LinearFitableFunction::applyTheFunction(Datum *pInputData, Datum *outputData){ // DDC fix bool LinearFitableFunction::applyTheFunction(const Datum& pInputData, Datum *outputData){ lock(); if (Parameters == NULL) { mwarning(M_SYSTEM_MESSAGE_DOMAIN, "WARNING: Prompted for calibrated value but parameters not yet set."); unlock(); return false; } //if (pInputData->getNElements() != numInputs) { // DDC fix if (pInputData.getNElements() != numInputs) { // //int xxx0 = pInputData->getNElements(); // DDC fix // int xxx0 = pInputData.getNElements(); // //double xxx1 = (double)(pInputData->getElement(0)); // DDC fix // //double xxx2 = (double)(pInputData->getElement(1)); // double xxx1 = (double)(pInputData.getElement(0)); // DDC fix // double xxx2 = (double)(pInputData.getElement(1)); mwarning(M_SYSTEM_MESSAGE_DOMAIN, "WARNING: Prompted for calibrated value but not all input data exists."); unlock(); return false; } double *inputDataDouble = new double [numInputs]; for (int i=0;i<numInputs;i++) { //inputDataDouble[i] = (double)(pInputData->getElement(i)); // copy data here // DDC fix inputDataDouble[i] = (double)(pInputData.getElement(i)); // copy data here // DDC fix //xxx = inputDataDouble[i]; //TODO -- remove } double temp = 0; for (int p=0; p< (basisSet->getNElements()); p++) { temp = temp + ((Parameters[p])*((basisSet->getElement(p))->applyBasis(inputDataDouble))); //ppp = Parameters[p]; //TODO -- remove } *outputData = Datum(temp);//DDC edit //*outputData = (Datum)temp; delete [] inputDataDouble; // DDC added unlock(); return true; }
static shared_ptr<mw::Component> createRealtimeComponent(const shared_ptr<ComponentRegistry> &componentRegistry, const Datum &realtimeComponentsValue, const std::string &componentType, const std::string &defaultPluginName) { std::string pluginName(defaultPluginName); if (realtimeComponentsValue.isDictionary()) { Datum componentValue = realtimeComponentsValue.getElement(componentType); if (componentValue.isString()) { pluginName = componentValue.getString(); } } mprintf(M_SYSTEM_MESSAGE_DOMAIN, " %s:\t%s", componentType.c_str(), pluginName.c_str()); return componentRegistry->createNewObject(pluginName, map<string, string>()); }
// this routine checks that the request is a dictionary and that it contains a name that matches the calibrator bool Calibrator::checkRequest(Datum dictionaryData) { Datum data; // to hold field data for checking // check if this is a dictionary if (!(dictionaryData.getDataType() == M_DICTIONARY)) { mwarning(M_SYSTEM_MESSAGE_DOMAIN, "Request sent to calibrator %s that was not expected dictionary type was ignored.", uniqueCalibratorName.c_str()); return(false); } // check if there is a name field and if this calibrator should respond (i.e. if it has the correct name) if (!(dictionaryData.hasKey(R_CALIBRATOR_NAME))) { mwarning(M_SYSTEM_MESSAGE_DOMAIN, "Request sent to calibrator %s that did not contain name field was ignored.", uniqueCalibratorName.c_str()); return(false); } Datum nameData = dictionaryData.getElement(R_CALIBRATOR_NAME); if (!(nameData.getDataType() == M_STRING)) { // check if name field is a string mwarning(M_SYSTEM_MESSAGE_DOMAIN, "Request sent to calibrator %s that did not contain a string in the name field was ignored.", uniqueCalibratorName.c_str()); return(false); } if (uniqueCalibratorName == nameData.getString()) { // check is name field matches the name of this calibrator if (VERBOSE_EYE_CALIBRATORS) mprintf("Calibrator %s successfully received a properly named request.", uniqueCalibratorName.c_str()); } else { if (VERBOSE_EYE_CALIBRATORS) mprintf("Calibrator %s received a request, but name did not match.", uniqueCalibratorName.c_str()); return(false); // request not meant for this calibrator (can be normal behavior -- no warnings) } return true; }
// this routine handles both "requests" and loading of private data (stored params) // if a request, then priuvate values are probably in need of update // if a load of private, then private values are OK, but I can check this. void EyeCalibrator::tryToUseDataToSetParameters(Datum dictionaryData) { // check if this is a dictionary if (!(dictionaryData.getDataType() == M_DICTIONARY)) { mwarning(M_SYSTEM_MESSAGE_DOMAIN, "Data processed by calibrator %s that was not expected dictionary type was ignored.", uniqueCalibratorName.c_str()); return; } // try to perform the requested action bool paramsChanged = false; Datum paramData; // if appropriate param fields are present and have expected length, then use the data // to try to update the parameters // H params ================================================ if (!(dictionaryData.hasKey(R_CALIBRATOR_PARAMS_H))) { mwarning(M_SYSTEM_MESSAGE_DOMAIN, "Data processed to update params of calibrator %s without proper params filed was ignored.", uniqueCalibratorName.c_str()); return; } paramData = dictionaryData.getElement(R_CALIBRATOR_PARAMS_H); // check if vector and correct length if (paramData.getDataType() != M_LIST) { mwarning(M_SYSTEM_MESSAGE_DOMAIN, "Data processed to update params of calibrator %s that did not contain vector in params field was ignored.", uniqueCalibratorName.c_str()); return; } Datum paramsH = paramData; if (paramsH.getNElements() != (fitableFunctions->getElement(HfunctionIndex))->getNumParameters() ) { mwarning(M_SYSTEM_MESSAGE_DOMAIN, "Data processed to update params of calibrator %s that did not contain expected number of params was ignored.", uniqueCalibratorName.c_str()); return; } bool noErr = (fitableFunctions->getElement(HfunctionIndex))->setParameters(paramsH); if (noErr) paramsChanged = true; // params have been updated // V params ================================================ if (!(dictionaryData.hasKey(R_CALIBRATOR_PARAMS_V))) { mwarning(M_SYSTEM_MESSAGE_DOMAIN, "Data processed to update params of calibrator %s without proper params filed was ignored.", uniqueCalibratorName.c_str()); return; } paramData = dictionaryData.getElement(R_CALIBRATOR_PARAMS_V); // check if vector and correct length if (paramData.getDataType() != M_LIST) { mwarning(M_SYSTEM_MESSAGE_DOMAIN, "Data processed to update params of calibrator %s that did not contain vector in params field was ignored.", uniqueCalibratorName.c_str()); return; } Datum paramsV = paramData; if (paramsV.getNElements() != (fitableFunctions->getElement(VfunctionIndex))->getNumParameters() ) { mwarning(M_SYSTEM_MESSAGE_DOMAIN, "Data processed to update params of calibrator %s that did not contain expected number of params was ignored.", uniqueCalibratorName.c_str()); return; } noErr = (fitableFunctions->getElement(VfunctionIndex))->setParameters(paramsV); if (noErr) paramsChanged = true; // params have been updated // if any params were updated, announce the full set of current parameters // if this change was triggered by an external change to the private variable, then we do not need to update that private variable (and we cannot anyway -- it is locked) if (paramsChanged) reportParameterUpdate(); }
bool ExperimentUnpackager::unpackageExperiment(Datum payload) { namespace bf = boost::filesystem; if(payload.getDataType() != M_DICTIONARY) { merror(M_NETWORK_MESSAGE_DOMAIN, "Invalid payload type for experiment package"); return false; } Datum experimentFilePackage = payload.getElement(M_PACKAGER_EXPERIMENT_STRING); if(experimentFilePackage.getNElements() != M_EXPERIMENT_PACKAGE_NUMBER_ELEMENTS_PER_UNIT || experimentFilePackage.getDataType() != M_DICTIONARY) return false; Datum experimentFileName = experimentFilePackage.getElement(M_PACKAGER_FILENAME_STRING); if(experimentFileName.getDataType() != M_STRING || experimentFileName.getString().empty()) return false; bf::path experimentName(experimentFileName.getString()); loadedExperimentFilename = prependExperimentInstallPath(removeFileExtension(experimentName.string()), experimentName.string()); bf::path experimentPath = loadedExperimentFilename.branch_path(); createExperimentInstallDirectoryStructure(experimentName.string()); // create the XML file Datum experimentFileBuffer = experimentFilePackage.getElement(M_PACKAGER_CONTENTS_STRING); if(experimentFileBuffer.getDataType() != M_STRING || experimentFileBuffer.getString().empty()) return false; if(!(createFile(Datum(loadedExperimentFilename.string().c_str()), experimentFileBuffer))) { // failed to create experiment file merror(M_FILE_MESSAGE_DOMAIN, "Failed to create server side experiment file %s", loadedExperimentFilename.string().c_str()); return false; } // create all of the other media files Datum mediaFileList = payload.getElement(M_PACKAGER_MEDIA_BUFFERS_STRING); if(mediaFileList.isList()) { for(int i=0; i<mediaFileList.getNElements(); ++i) { Datum mediaFilePackage = mediaFileList.getElement(i); if(mediaFilePackage.getDataType() != M_DICTIONARY | mediaFilePackage.getNElements() != 2) { merror(M_FILE_MESSAGE_DOMAIN, "incorrectly packaged media files"); return false; } Datum mediaFileName = mediaFilePackage.getElement(M_PACKAGER_FILENAME_STRING); Datum mediaFileBuffer = mediaFilePackage.getElement(M_PACKAGER_CONTENTS_STRING); if(mediaFileName.getDataType() != M_STRING || mediaFileName.getString().empty() || mediaFileBuffer.getDataType() != M_STRING) return false; std::string filename(mediaFileName.getString()); std::string filenameWPath = experimentPath.string() + "/" + filename; if(!(createFile(Datum(filenameWPath.c_str()), mediaFileBuffer))) { // failed to create experiment file merror(M_FILE_MESSAGE_DOMAIN, "Failed to create server side experiment file %s", filenameWPath.c_str()); return false; } } } expandRangeReplicatorItems(loadedExperimentFilename); modifyExperimentMediaPaths(loadedExperimentFilename); return true; }
bool LinearFitableFunction::fitTheFunction() { if (basisSet == NULL) return false; lock(); int numParams = basisSet->getNElements(); int numData = allSamplesToFit->getNElements(); if (numData < numParams) { mwarning(M_SYSTEM_MESSAGE_DOMAIN, "WARNING: Attempted fit without enough data."); unlock(); return false; } if (VERBOSE_FITABLE_FUNCTION) { mprintf("Fitable function: n data=%d n params=%d", numData, numParams); } float *B = new float [numParams]; float *Y = new float [numData]; // 2D array creation float **X = new2DfloatArray(numData,numParams); // create space to hold all Parameters if (Parameters != NULL) delete [] Parameters; Parameters = new float [numParams]; // get data back in correct format double *temp = new double [numInputs]; // unfold the data into the prescribed basis. // the format here is Y = Xb // we start with the most recent data, but order does not matter shared_ptr<FitableSample> sampleToFit = allSamplesToFit->getFrontmost(); for (int n=0; n<numData;n++) { Datum *inputVector = sampleToFit->getInputVector(); if (VERBOSE_FITABLE_FUNCTION>1) { MWTime timeUS = sampleToFit->getTime(); // testing only mprintf("Fitable function: datum %d timeUS = %ld",n, (long)timeUS); } for (int i=0;i<numInputs;i++) { temp[i] = inputVector->getElement(i); } for (int p=0; p<numParams;p++) { X[n][p] = (basisSet->getElement(p))->applyBasis(temp); } Y[n] = (float)(sampleToFit->getOutputData()); sampleToFit = sampleToFit->getNext(); // go to next sample on the list } // linear regression to find Parameters (SVD pseudo-inverse) // B = inv(XtX) XtY int tempNumParams; float chisq; SVDfit svdfitter(X,Y,NULL,numData,numParams); // no weighting for now svdfitter.doFit(B, &tempNumParams, &chisq); if (tempNumParams != numParams) merror(M_SYSTEM_MESSAGE_DOMAIN, "Unexpected number of parameters"); // save for later application for (int p=0; p<numParams;p++) { Parameters[p] = B[p]; if (VERBOSE_FITABLE_FUNCTION) { mprintf("Fitable function: final fit param %d = %f5", p, Parameters[p]); } } delete [] B; delete2DfloatArray(X, numData); delete [] Y; delete [] temp; unlock(); return true; }
bool LinearFitableFunction::fitTheFunction() { if (basisSet == NULL) return false; Locker lock(*this); int numParams = basisSet->getNElements(); int numData = allSamplesToFit->getNElements(); if (numData < numParams) { mwarning(M_SYSTEM_MESSAGE_DOMAIN, "WARNING: Attempted fit without enough data."); return false; } if (VERBOSE_FITABLE_FUNCTION) { mprintf("Fitable function: n data=%d n params=%d", numData, numParams); } std::vector<float> B(numParams); std::vector<float> Y(numData); std::vector<float> X(numData * numParams); // create space to hold all Parameters if (Parameters != NULL) delete [] Parameters; Parameters = new float [numParams]; // get data back in correct format std::vector<double> temp(numInputs); // unfold the data into the prescribed basis. // the format here is Y = Xb // we start with the most recent data, but order does not matter shared_ptr<FitableSample> sampleToFit = allSamplesToFit->getFrontmost(); for (int n=0; n<numData;n++) { Datum *inputVector = sampleToFit->getInputVector(); if (VERBOSE_FITABLE_FUNCTION>1) { MWTime timeUS = sampleToFit->getTime(); // testing only mprintf("Fitable function: datum %d timeUS = %ld",n, (long)timeUS); } for (int i=0;i<numInputs;i++) { temp[i] = inputVector->getElement(i); } for (int p=0; p<numParams;p++) { // Need to use Fortran-style (i.e. column-major) ordering X[n + p*numData] = (basisSet->getElement(p))->applyBasis(temp.data()); } Y[n] = (float)(sampleToFit->getOutputData()); sampleToFit = sampleToFit->getNext(); // go to next sample on the list } // linear regression to find Parameters (SVD pseudo-inverse) // B = inv(XtX) XtY // using SGELSD from LAPACK { __CLPK_integer m = numData; __CLPK_integer n = numParams; __CLPK_integer nrhs = 1; __CLPK_real *a = X.data(); __CLPK_integer lda = m; __CLPK_real *b = Y.data(); __CLPK_integer ldb = m; std::vector<__CLPK_real> s(n); // The choice of N*epsilon for rcond comes from _Numerical Recipes in C_, Section 15.4, // "Solution by Use of Singular Value Decomposition" __CLPK_real rcond = n * std::numeric_limits<__CLPK_real>::epsilon(); __CLPK_integer rank; std::vector<__CLPK_real> work(1); __CLPK_integer lwork = -1; std::vector<__CLPK_integer> iwork(1); __CLPK_integer info; // We call SGELSD two times: once to determine appropriate sizes for work and iwork, and once to // perform the actual fit for (int numReps = 0; numReps < 2; numReps++) { sgelsd_(&m, &n, &nrhs, a, &lda, b, &ldb, s.data(), &rcond, &rank, work.data(), &lwork, iwork.data(), &info); if (info != 0) { merror(M_GENERIC_MESSAGE_DOMAIN, "Fitable function: SGELSD returned %d", int(info)); return false; } if (-1 == lwork) { // Set sizes of work and iwork for next pass work.resize(work.at(0)); lwork = work.size(); iwork.resize(iwork.at(0)); } else { // Store solution for (int p = 0; p < numParams; p++) { B[p] = b[p]; } } } } // save for later application for (int p=0; p<numParams;p++) { Parameters[p] = B[p]; if (VERBOSE_FITABLE_FUNCTION) { mprintf("Fitable function: final fit param %d = %f5", p, Parameters[p]); } } return true; }