void LoadDNSSCD::updateProperties(API::Run &run, std::map<std::string, T> &metadata, std::string time) { typename std::map<std::string, T>::iterator it = metadata.begin(); while (it != metadata.end()) { TimeSeriesProperty<T> *timeSeries(nullptr); std::string name(it->first); std::string units; // std::regex does not work for rhel7, thus boost boost::regex reg("([-_a-zA-Z]+)\\[(.*)]"); boost::smatch match; if (boost::regex_search(name, match, reg) && match.size() > 2) { std::string new_name(match.str(1)); units.assign(match.str(2)); name = new_name; } if (run.hasProperty(name)) { timeSeries = dynamic_cast<TimeSeriesProperty<T> *>(run.getLogData(name)); if (!timeSeries) throw std::invalid_argument( "Log '" + name + "' already exists but the values are a different type."); } else { timeSeries = new TimeSeriesProperty<T>(name); if (!units.empty()) timeSeries->setUnits(units); run.addProperty(timeSeries); } timeSeries->addValue(time, it->second); ++it; } }
/** * Recursively add properties from a nexus file to * the workspace run. * * @param nxfileID :: Nexus file handle to be parsed, just after an NXopengroup * @param runDetails :: where to add properties * @param parent_name :: nexus caller name * @param parent_class :: nexus caller class * @param level :: current level in nexus tree * */ void LoadHelper::recurseAndAddNexusFieldsToWsRun(NXhandle nxfileID, API::Run& runDetails, std::string& parent_name, std::string& parent_class, int level) { std::string indent_str(level * 2, ' '); // Two space by indent level // Link ? // Attributes ? // Classes NXstatus getnextentry_status; ///< return status int datatype; ///< NX data type if a dataset, e.g. NX_CHAR, NX_FLOAT32, see napi.h char nxname[NX_MAXNAMELEN], nxclass[NX_MAXNAMELEN]; nxname[0] = '0'; nxclass[0] = '0'; bool has_entry = true; // follows getnextentry_status while (has_entry) { getnextentry_status = NXgetnextentry(nxfileID, nxname, nxclass, &datatype); if (getnextentry_status == NX_OK) { g_log.debug() << indent_str << parent_name << "." << nxname << " ; " << nxclass << std::endl; NXstatus opengroup_status; NXstatus opendata_status; if ((opengroup_status = NXopengroup(nxfileID, nxname, nxclass)) == NX_OK) { // Go down to one level std::string p_nxname(nxname); //current names can be useful for next level std::string p_nxclass(nxclass); recurseAndAddNexusFieldsToWsRun(nxfileID, runDetails, p_nxname, p_nxclass, level + 1); NXclosegroup(nxfileID); } // if(NXopengroup else if ((opendata_status = NXopendata(nxfileID, nxname)) == NX_OK) { //dump_attributes(nxfileID, indent_str); g_log.debug() << indent_str << nxname << " opened." << std::endl; if (parent_class == "NXData" || parent_class == "NXMonitor" || std::string(nxname) == "data") { g_log.debug() << indent_str << "skipping " << parent_class << " (" << nxname << ")" << std::endl; /* nothing */ } else { // create a property int rank; int dims[4]; int type; dims[0] = dims[1] = dims[2] = dims[3] = 0; std::string property_name = (parent_name.empty() ? nxname : parent_name + "." + nxname); g_log.debug() << indent_str << "considering property " << property_name << std::endl; // Get the value NXgetinfo(nxfileID, &rank, dims, &type); // Note, we choose to only build properties on small float arrays // filter logic is below bool build_small_float_array = false; // default if ((type == NX_FLOAT32) || (type == NX_FLOAT64)) { if ((rank == 1) && (dims[0] <= 9)) { build_small_float_array = true; } else { g_log.debug() << indent_str << "ignored multi dimension float data on " << property_name << std::endl; } } else if (type != NX_CHAR) { if ((rank != 1) || (dims[0] != 1) || (dims[1] != 1) || (dims[2] != 1) || (dims[3] != 1)) { g_log.debug() << indent_str << "ignored multi dimension data on " << property_name << std::endl; } } void *dataBuffer; NXmalloc(&dataBuffer, rank, dims, type); if (NXgetdata(nxfileID, dataBuffer) != NX_OK) { NXfree(&dataBuffer); throw std::runtime_error("Cannot read data from NeXus file"); } if (type == NX_CHAR) { std::string property_value((const char *) dataBuffer); if (boost::algorithm::ends_with(property_name, "_time")) { // That's a time value! Convert to Mantid standard property_value = dateTimeInIsoFormat(property_value); } runDetails.addProperty(property_name, property_value); } else if ((type == NX_FLOAT32) || (type == NX_FLOAT64) || (type == NX_INT16) || (type == NX_INT32) || (type == NX_UINT16)) { // Look for "units" NXstatus units_status; char units_sbuf[NX_MAXNAMELEN]; int units_len = NX_MAXNAMELEN; int units_type = NX_CHAR; units_status = NXgetattr(nxfileID, const_cast<char*>("units"), (void *) units_sbuf, &units_len, &units_type); if (units_status != NX_ERROR) { g_log.debug() << indent_str << "[ " << property_name << " has unit " << units_sbuf << " ]" << std::endl; } if ((type == NX_FLOAT32) || (type == NX_FLOAT64)) { // Mantid numerical properties are double only. double property_double_value = 0.0; // Simple case, one value if (dims[0] == 1) { if (type == NX_FLOAT32) { property_double_value = *((float*) dataBuffer); } else if (type == NX_FLOAT64) { property_double_value = *((double*) dataBuffer); } if (units_status != NX_ERROR) runDetails.addProperty(property_name, property_double_value, std::string(units_sbuf)); else runDetails.addProperty(property_name, property_double_value); } else if (build_small_float_array) { // An array, converted to "name_index", with index < 10 (see test above) for (int dim_index = 0; dim_index < dims[0]; dim_index++) { if (type == NX_FLOAT32) { property_double_value = ((float*) dataBuffer)[dim_index]; } else if (type == NX_FLOAT64) { property_double_value = ((double*) dataBuffer)[dim_index]; } std::string indexed_property_name = property_name + std::string("_") + boost::lexical_cast<std::string>(dim_index); if (units_status != NX_ERROR) runDetails.addProperty(indexed_property_name, property_double_value, std::string(units_sbuf)); else runDetails.addProperty(indexed_property_name, property_double_value); } } } else { // int case int property_int_value = 0; if (type == NX_INT16) { property_int_value = *((short int*) dataBuffer); } else if (type == NX_INT32) { property_int_value = *((int*) dataBuffer); } else if (type == NX_UINT16) { property_int_value = *((short unsigned int*) dataBuffer); } if (units_status != NX_ERROR) runDetails.addProperty(property_name, property_int_value, std::string(units_sbuf)); else runDetails.addProperty(property_name, property_int_value); } // if (type==... } else { g_log.debug() << indent_str << "unexpected data on " << property_name << std::endl; } // test on nxdata type NXfree(&dataBuffer); dataBuffer = NULL; } // if (parent_class == "NXData" || parent_class == "NXMonitor") else NXclosedata(nxfileID); } else { g_log.debug() << indent_str << "unexpected status (" << opendata_status << ") on " << nxname << std::endl; } } else if (getnextentry_status == NX_EOD) { g_log.debug() << indent_str << "End of Dir" << std::endl; has_entry = false; // end of loop } else { g_log.debug() << indent_str << "unexpected status (" << getnextentry_status << ")" << std::endl; has_entry = false; // end of loop } } // while } // recurseAndAddNexusFieldsToWsRun