#define rcmaker_cxx // This is a standalone root macro that reads in a sequence of tif images // from the CHESS FLIcam ccd camera corresponding to a single rocking curve // measurement. It outputs a root tree containing a sequence of TH1D // histogram objects, one for each pixel, containing the image intensity // versus step sequence number. The order of the histogram objects in the // tree is left-to-right row-wise storage, then top to bottom, as seen in a // standard tif viewer. As a cross-check, the pixel coordinates (tif x,y) // are encoded in the titles of the histograms. // // To use this macro, try the following session from within the directory // containing your tif images, entitled "pristine_007_NNN.tif" in this example, // where NNN varies from 15 to 155. This macro is located in the parent dir. // // Root > .L /usr/lib64/libtiff.so // Root > .L ../rcmaker.C+O // Root > rcmaker("pristine",7,141,15); // Root > .ls // // Update by RTJ on 11/21/2012: // I have overhauled this macro to make it work properly with the newer image // files generated by the ANDOR camera at CHESS. The files are now quite a // bit larger (10MB typical) and end with the extension ".tiff" instead of // ".tif". There are no changes the usage instructions. The script should // be able to recognize automatically which of the image types are being // analyzed. // // Update by RTJ on 8/24/2016: // I have overhauled this macro to make it work with the different style of // image files and scan summary files that we collected at the Canadian Light // Source. The image files themselves have the extension ".tif" and have the // scan number and scan step number encoded into the filename. The camera is // the Hammamatsu AA-60 and the scintillator C9300-124. #include #include #include #include #include #include #include #include #include #include #include #include #include #include void rcmaker(const char *prefix, Int_t seq, Int_t count, Int_t start=0) { bool oldFliCam = true; bool AndorCam = false; bool HamaCam = false; bool is16bit = false; bool is8bit = false; // read the dimensions of the topographs from the first image file std::stringstream ssn; ssn << TString(prefix) << "_" << std::setfill('0') << std::setw(3) << seq << "_" << std::setfill('0') << std::setw(3) << start << ".tif"; TIFF* refimg = TIFFOpen(ssn.str().c_str(),"r"); // the new Andor camera uses a different filename convention if (!refimg) { ssn.str(""); ssn << TString(prefix) << "_scan" << std::setfill('0') << std::setw(3) << seq << "_" << std::setfill('0') << std::setw(3) << start << ".tiff"; refimg = TIFFOpen(ssn.str().c_str(),"r"); oldFliCam = false; AndorCam = true; } // the Hamamatsu camera uses yet another filename convention if (!refimg) { ssn.str(""); ssn << TString(prefix) << "-" << seq << "_" << std::setfill('0') << std::setw(5) << start << ".tif"; refimg = TIFFOpen(ssn.str().c_str(),"r"); AndorCam = false; HamaCam = true; } // if none of the above sections succeeded, this image file is not supported if (!refimg) { std::cerr << "rcmaker error - unable to read from first image file " << ssn.str() << ", unable to continue." << std::endl; return; } UShort_t config; TIFFGetField(refimg, TIFFTAG_PLANARCONFIG, &config); if (config != 1) { std::cerr << "rcmaker error - tiff image has an unfamiliar " << "PlanarConfiguration value of " << config << ", unable to continue." << std::endl; return; } UInt_t height,width; TIFFGetField(refimg, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(refimg, TIFFTAG_IMAGELENGTH, &height); // if image file was not found, give up if (!(width > 0 && height > 0)) { std::cerr << "rcmaker error - zero image dimensions found in " << "image file " << ssn.str() << ", unable to continue." << std::endl; return; } TIFFClose(refimg); // open a tree file to receive the rocking curve histograms ssn.str(""); ssn << TString(prefix) << "_" << std::setfill('0') << std::setw(3) << seq << "_" << "rocking_curves.root"; std::stringstream title; title << "rocking curves for sample " << TString(prefix) << " scan " << std::setfill('0') << std::setw(3) << seq; TFile rootfile(ssn.str().c_str(),"RECREATE",title.str().c_str()); // create a rocking curve histogram and a tree to receive it TTree roottree("rctree","Rocking Curves"); ssn.str(""); ssn << "rc_" << TString(prefix) << "_" << std::setfill('0') << std::setw(3) << seq; TH1D rchist(ssn.str().c_str(),title.str().c_str(),count,start,start+count); roottree.Branch("rchist",&rchist,128000,0); // loop over the image in horizontal swaths of SwathHeight rows const Int_t SwathHeight = 128; # define HINDEX(IU, IV0, INDEX) ((((IV0)*width)+(IU))*count)+(INDEX) Double_t *harray = new Double_t[width*SwathHeight*count]; UShort_t *buf = (UShort_t*)_TIFFmalloc(width*sizeof(UShort_t)); unsigned char *buf8 = (unsigned char*)buf; for (Int_t swath=0; swath*SwathHeight < (int)height; ++swath) { Int_t startHeight = swath*SwathHeight; Int_t stopHeight = (swath+1)*SwathHeight; stopHeight = (stopHeight < (int)height)? stopHeight : height; // loop over the input image files, filling the rocking curve histograms for (Int_t index=0; index < count; index++) { ssn.str(""); if (oldFliCam) { ssn << TString(prefix) << "_" << std::setfill('0') << std::setw(3) << seq << "_" << std::setfill('0') << std::setw(3) << index+start << ".tif"; } else if (AndorCam) { ssn << TString(prefix) << "_scan" << std::setfill('0') << std::setw(3) << seq << "_" << std::setfill('0') << std::setw(3) << index+start << ".tiff"; } else if (HamaCam) { ssn << TString(prefix) << "-" << seq << "_" << std::setfill('0') << std::setw(5) << index+start << ".tif"; } TIFF *img = TIFFOpen(ssn.str().c_str(),"r"); if (!img) { std::cerr << "rcmaker warning - scan image file " << ssn.str() << " could not be opened, " << "moving on..." << std::endl; continue; } UInt_t linewidth = TIFFScanlineSize(img); if (linewidth == width*sizeof(UShort_t)) { is16bit = true; } else if (linewidth == width*sizeof(char)) { is8bit = true; } else { std::cerr << "rcmaker error - expecting 16-bit samples " << "but found " << linewidth*8./width << " bits/sample, cannot continue." << std::endl; return; } for (Int_t iv=startHeight,iv0=0; iv < stopHeight; ++iv,++iv0) { TIFFReadScanline(img, buf, iv); for (Int_t iu=0; iu<(int)width; ++iu) { if (is16bit) harray[HINDEX(iu,iv0,index)] = buf[iu]; else if (is8bit) harray[HINDEX(iu,iv0,index)] = buf8[iu]; else harray[HINDEX(iu,iv0,index)] = 999; } } TIFFClose(img); } // save the rocking curves as histograms to the tree for (Int_t iv=startHeight,iv0=0; iv < stopHeight; ++iv,++iv0) { for (Int_t iu=0; iu<(int)width; ++iu) { ssn.str(""); ssn << "pixel_" << std::setfill('0') << std::setw(3) << iu << "_" << std::setfill('0') << std::setw(3) << iv; title.str(""); title << "rocking curve for sample " << TString(prefix) << " scan " << std::setfill('0') << std::setw(3) << seq << " pixel " << std::setfill('0') << std::setw(3) << iu << "," << std::setfill('0') << std::setw(3) << iv; rchist.SetNameTitle(ssn.str().c_str(),title.str().c_str()); rchist.SetContent(&harray[HINDEX(iu,iv0,0)]); roottree.Fill(); } } } _TIFFfree(buf); // save the tree to the file and close rootfile.Write(); rootfile.Close(); }