void ProgXrayImport::readGeoInfo(const FileName &fn, MDRow &rowGeo) const { double tiltAngle; switch (dSource) { case MISTRAL: tiltAngle = dMi(anglesArray, fn.getPrefixNumber()-1); break; case BESSY: case GENERIC: { FileName fnBase = fn.withoutExtension(); std::ifstream fhPosition; fhPosition.open((fnBase+"-positions.txt").c_str()); if (!fhPosition) REPORT_ERROR(ERR_IO_NOTEXIST,fnBase+"-positions.txt"); int itemsFound=0; std::string line; std::vector<std::string> tokens; while (!fhPosition.eof()) { getline(fhPosition,line); splitString(line," ",tokens); if (tokens[0]=="xm:sample:rx") { tiltAngle=textToFloat(tokens[1]); itemsFound++; } if (itemsFound==1) break; } fhPosition.close(); if (itemsFound!=1) REPORT_ERROR(ERR_VALUE_EMPTY,(std::string)"Cannot find tilt angle in "+ fnBase+"-positions.txt"); } break; } rowGeo.setValue(MDL_ANGLE_TILT, tiltAngle); }
void ProgXrayImport::getFlatfield(const FileName &fnFFinput, Image<double> &Iavg) { // Process the flatfield images MultidimArray<double> &mdaIavg = Iavg(); Matrix1D<double> expTimeArray, cBeamArray, slitWidthArray; // Local vectors DataSource ldSource = dSource; // Checking if fnFFinput is a single file to obtain the flatfield avg from if (extFlat && isImage(fnFFinput)) { fMD.read(fnFFinput); ldSource = NONE; } else { switch (ldSource) { case MISTRAL: if (!H5File.checkDataset(fnFFinput.getBlockName().c_str())) break; { fMD.read(fnFFinput); H5File.getDataset("NXtomo/instrument/bright_field/ExpTimes", expTimeArray, false); H5File.getDataset("NXtomo/instrument/bright_field/current", cBeamArray, false); // If expTime is empty or only one single value in nexus file then we fill with 1 if (expTimeArray.size() < 2) { reportWarning("Input file does not contains flatfields' exposition time information."); expTimeArray.initConstant(fMD.size(), 1.); } // If current is empty or only one single value in nexus file then we fill with 1 if (cBeamArray.size() < 2) { reportWarning("Input file does not contains flatfields' current beam information."); cBeamArray.initConstant(fMD.size(), 1.); } } // Since Alba does not provide slit width, we set to ones slitWidthArray.initConstant(fMD.size(), 1.); break; case BESSY: { size_t objId; for (size_t i = fIni; i <= fEnd; ++i) { objId = fMD.addObject(); fMD.setValue(MDL_IMAGE, fnFFinput + formatString("/img%d.spe", i), objId); } break; } case GENERIC: { // Get Darkfield std::cout << "Getting darkfield from "+fnFFinput << " ..." << std::endl; getDarkfield(fnFFinput, IavgDark); if (darkFix) IavgDark.write(fnRoot+"_"+fnFFinput.removeDirectories()+"_darkfield.xmp"); std::vector<FileName> listDir; fnFFinput.getFiles(listDir); size_t objId; for (size_t i = 0; i < listDir.size(); ++i) { if (!listDir[i].hasImageExtension()) continue; objId = fMD.addObject(); fMD.setValue(MDL_IMAGE, fnFFinput+"/"+listDir[i], objId); } } break; } } if ( fMD.size() == 0 ) { reportWarning("XrayImport::getFlatfield: No images to process"); return; } ImageInfo imFFInfo; getImageInfo(fMD, imFFInfo); if ( (imFFInfo.adim.xdim != imgInfo.adim.xdim) || (imFFInfo.adim.ydim != imgInfo.adim.ydim) ) { reportWarning(formatString("XrayImport:: Flatfield images size %dx%d different from Tomogram images size %dx%d", imFFInfo.adim.xdim,imFFInfo.adim.ydim,imgInfo.adim.xdim,imgInfo.adim.ydim)); std::cout << "Setting crop values to fit the smallest dimensions." <<std::endl; // This shift in the crop sizes is exclusive of Mistral data cropSizeXi = (imgInfo.adim.xdim - std::min(imgInfo.adim.xdim-cropSizeX*2, imFFInfo.adim.xdim))/2 + 1; cropSizeYi = (imgInfo.adim.ydim - std::min(imgInfo.adim.ydim-cropSizeY*2, imFFInfo.adim.ydim))/2 + 1; cropSizeXe = cropSizeXi - 2; cropSizeYe = cropSizeYi - 2; } int cropX = (imFFInfo.adim.xdim - (imgInfo.adim.xdim-cropSizeXi-cropSizeXe))/2;// - 1; int cropY = (imFFInfo.adim.ydim - (imgInfo.adim.ydim-cropSizeYi-cropSizeYe))/2;// - 1; int N = 0; Image<double> Iaux; FileName fnImg; FOR_ALL_OBJECTS_IN_METADATA(fMD) { fMD.getValue(MDL_IMAGE, fnImg, __iter.objId); readAndCrop(fnImg, Iaux, cropX, cropY); if ( darkFix ) { Iaux() -= IavgDark(); forcePositive(Iaux()); } double currentBeam = 1; double expTime = 1; double slitWidth = 1; switch (ldSource) { case MISTRAL: { size_t idx = fnImg.getPrefixNumber(); currentBeam = dMi(cBeamArray, idx-1); expTime = dMi(expTimeArray, idx-1); slitWidth = dMi(slitWidthArray, idx-1); } break; case BESSY: case GENERIC: readCorrectionInfo(fnImg, currentBeam, expTime, slitWidth); break; default: break; } Iaux() *= 1.0/(currentBeam*expTime*slitWidth); if ( N == 0 ) mdaIavg = Iaux(); else mdaIavg += Iaux(); N++; } darkFix = false; // We reset just in case there is no dark field for tomo images mdaIavg*=1.0/N; /* Create a mask with zero valued pixels to apply boundaries median filter * to avoid dividing by zero when normalizing */ MultidimArray<char> &mdaMask = MULTIDIM_ARRAY(bpMask); if ( !fnBPMask.empty() && !mdaIavg.sameShape(mdaMask) ) REPORT_ERROR(ERR_MULTIDIM_SIZE, "XrayImport: Mask size does not match flat fields size."); if (BPFactor > 0) { double avg, std; mdaIavg.computeAvgStdev(avg, std); mdaMask.resize(mdaIavg, false); double th = avg - std*BPFactor; FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(mdaMask) dAi(mdaMask, n) = dAi(mdaIavg, n) < th; } else if (fnBPMask.empty()) mdaIavg.equal(0,mdaMask); MultidimArray<char> mask = mdaMask; boundMedianFilter(mdaIavg,mask); }