void ProgXrayImport::getDarkfield(const FileName &fnDir, Image<double> &IavgDark) { IavgDark.clear(); std::vector<FileName> listDir; fnDir.getFiles(listDir); for (size_t i=0; i<listDir.size(); i++) if (listDir[i]=="darkfields") { std::cout << formatString("Getting darkfield from %s/darkfields",fnDir.c_str()) << " ..." << std::endl; darkFix = true; std::vector<FileName> listDirDark; FileName(fnDir+"/darkfields").getFiles(listDirDark); int N = 0; for (size_t j=0; j<listDirDark.size(); j++) { if (!listDirDark[j].hasImageExtension()) continue; Image<double> Iaux; readAndCrop(fnDir+"/darkfields/"+listDirDark[j],Iaux, cropSizeX, cropSizeY); if (N==0) IavgDark()=Iaux(); else IavgDark()+=Iaux(); N++; } if (N==0) REPORT_ERROR(ERR_IO_NOTEXIST,"darkfields directory is empty"); IavgDark()*=1.0/N; break; } }
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); }