const Char_t *KVINDRAIDTelescope::GetArrayName() { // Name of telescope given in the form Det1_Det2_Ring-numberTelescope-number //where ring and telescope numbers are those of the smallest (in angular terms) //detector of the telescope (if both are the same size, either one will do). // The detectors are signified by their TYPE names i.e. KVDetector::GetType //in order to access angular dimensions of detectors, we need their KVTelescopes KVINDRATelescope *de_det = dynamic_cast<KVINDRADetector*>(GetDetector(1))->GetTelescope(); KVINDRATelescope *e_det = 0; if (GetSize() > 1) e_det = dynamic_cast<KVINDRADetector*>(GetDetector(2))->GetTelescope(); UInt_t ring, mod; if (!e_det || de_det->IsSmallerThan(e_det)) { ring = de_det->GetRingNumber(); mod = de_det->GetNumber(); } else { ring = e_det->GetRingNumber(); mod = e_det->GetNumber(); } SetName(GetDetector(1)->GetType()); if (e_det) { fName.Append("_"); fName.Append(GetDetector(2)->GetType()); } SetType(fName.Data()); fName.Append("_"); TString num; num.Form("%02d%02d", ring, mod); fName += num; return fName.Data(); }
//___________________________________________________________________________ Double_t KVChannelVolt::Invert(Double_t volts) { //Given the calibrated (or simulated) signal amplitude in volts, //calculate the corresponding channel number according to the //calibration parameters (useful for filtering simulations). Double_t gain = 1.; KVDetector* det = GetDetector(); if (det) gain = det->GetGain(); Int_t channel = 0; if (fReady) { if (fPar[2]) { // quadratic transfer function Double_t c; c = fPar[1] * fPar[1] - 4. * fPar[2] * (fPar[0] - gain / gain_ref * volts); if (c < 0.0) return -1; c = (-fPar[1] + TMath::Sqrt(c)) / (2.0 * fPar[2]); if (c < 0.0 && ((-fPar[1] - TMath::Sqrt(c)) / (2.0 * fPar[2])) > 0.0) { c = (-fPar[1] - TMath::Sqrt(c)) / (2.0 * fPar[2]); } channel = (Int_t)(c + 0.5); } else { // linear transfer function channel = (Int_t)(0.5 + (gain / gain_ref * volts - fPar[0]) / fPar[1]); } } else { Warning("Compute", "Parameters not correctly initialized"); } return (Double_t) channel; }
//___________________________________________________________________________ Double_t KVChannelVolt::InvertDouble(Double_t volts) { Double_t gain = 1.; KVDetector* det = GetDetector(); if (det) gain = det->GetGain(); Double_t channel = 0; if (fReady) { if (fPar[2]) { // quadratic transfer function Double_t c; c = fPar[1] * fPar[1] - 4. * fPar[2] * (fPar[0] - gain / gain_ref * volts); if (c < 0.0) return -1; c = (-fPar[1] + TMath::Sqrt(c)) / (2.0 * fPar[2]); if (c < 0.0 && ((-fPar[1] - TMath::Sqrt(c)) / (2.0 * fPar[2])) > 0.0) { c = (-fPar[1] - TMath::Sqrt(c)) / (2.0 * fPar[2]); } channel = c; } else { // linear transfer function channel = (gain / gain_ref * volts - fPar[0]) / fPar[1]; } } else { Warning("Compute", "Parameters not correctly initialized"); } return (Double_t) channel; }
const Char_t *KVIDCsI::GetArrayName() { // Name of telescope given in the form CSI_R_L_Ring-numberTelescope-number //where ring and telescope numbers are those of the smallest (in angular terms) //detector of the telescope (if both are the same size, either one will do). // The detectors are signified by their TYPE names i.e. KVDetector::GetType //in order to access angular dimensions of detectors, we need their KVTelescopes KVINDRATelescope *de_det = dynamic_cast<KVINDRADetector*>(GetDetector(1))->GetTelescope(); UInt_t ring, mod; ring = de_det->GetRingNumber(); mod = de_det->GetNumber(); TString dummy; dummy.Form("%s_R_L", GetDetector(1)->GetType()); SetType(dummy.Data()); dummy.Form("%s_%02d%02d", GetType(), ring, mod); SetName(dummy.Data()); return fName.Data(); }
TF1* KVRecombination::GetParlogPHDFunction(Int_t Z, Int_t A){ // Create TF1* fParlog if not already done if(!fParlog) { fParlog = new TF1(Form("ParlogPHD:%s", GetDetector()->GetName()), this, &KVRecombination::PHDParlog, 0., 1.e+04, 1, "KVRecombination", "PHDParlog"); fParlog->SetNpx(500); } fParlog->SetParameter(0,Z); fParlog->SetParameter(1,A); return fParlog; }
TF1* KVPulseHeightDefect::GetMoultonPHDFunction(Int_t Z) { // Create TF1* fMoulton if not already done if(!fMoulton) { fMoulton = new TF1(Form("MoultonPHD:%s", GetDetector()->GetName()), this, &KVPulseHeightDefect::PHDMoulton, 0., 1.e+04, 1, "KVPulseHeightDefect", "PHDMoulton"); fMoulton->SetNpx(500); } fMoulton->SetParameter(0,Z); return fMoulton; }
void KVIDChIoCorrCsI::Initialize() { // Initialize telescope for current run. fChIo = 0; fChIo = (KVChIo *) GetDetector(1); fCsI = 0; fCsI = (KVCsI *) GetDetector(2); fGrid = 0; fGrid = (KVIDZAGrid*) GetIDGrid(); if (fChIo && fCsI && fGrid) { fGrid->Initialize(); fGrid->SetOnlyZId(kTRUE); SetBit(kReadyForID); } else ResetBit(kReadyForID); }
void KVFAZIA::Build(Int_t) { // Build the combined INDRA & FAZIA arrays GetGeometryParameters(); GenerateCorrespondanceFile(); if (!gGeoManager) { new TGeoManager("FAZIA", Form("FAZIA geometry for dataset %s", gDataSet->GetName())); TGeoMaterial* matVacuum = gGeoManager->GetMaterial("Vacuum"); if (!matVacuum) { matVacuum = new TGeoMaterial("Vacuum", 0, 0, 0); matVacuum->SetTitle("Vacuum"); } TGeoMedium* Vacuum = gGeoManager->GetMedium("Vacuum"); if (!Vacuum) Vacuum = new TGeoMedium("Vacuum", 1, matVacuum); TGeoVolume* top = gGeoManager->MakeBox("WORLD", Vacuum, 500, 500, 500); gGeoManager->SetTopVolume(top); } BuildFAZIA(); if (fBuildTarget) BuildTarget(); KVGeoImport imp(gGeoManager, KVMaterial::GetRangeTable(), this, kTRUE); imp.SetDetectorPlugin(ClassName()); imp.SetNameCorrespondanceList(fCorrespondanceFile.Data()); // any additional structure name formatting definitions DefineStructureFormats(imp); // the following parameters are optimized for a 12-block compact // geometry placed at 80cm with rings 1-5 of INDRA removed. // make sure that the expected number of detectors get imported! imp.ImportGeometry(fImport_dTheta, fImport_dPhi, fImport_ThetaMin, fImport_PhiMin, fImport_ThetaMax, fImport_PhiMax); /* KVFAZIADetector* det=0; TIter next_d(GetDetectors()); while ( det = (KVFAZIADetector* )next_d() ){ printf("%s %s %d %d %d\n",det->GetName(),det->GetFAZIAType(),det->GetBlockNumber(),det->GetQuartetNumber(),det->GetTelescopeNumber()); } */ SetIdentifications(); SortIDTelescopes(); KVDetector* det = GetDetector("SI2-T1-Q1-B001"); det->GetIDTelescopes()->ls(); SetDetectorThicknesses(); SetBit(kIsBuilt); }
//___________________________________________________________________________ Double_t KVChannelVolt::Compute(Double_t chan) const { Double_t gain = 1.; KVDetector* det = GetDetector(); if (det) gain = det->GetGain(); //Calculate the calibrated signal strength in volts for a given channel number. if (fReady) { return (fPar[0] + fPar[1] * chan + fPar[2] * chan * chan) * gain_ref / gain; } else { return 0.; } }
void KVIDSiLiCsI_camp5::Initialize() { // Initialize telescope for current run. // Pointers to grids for run are set, and if there is at least 1 (GG) grid, // we set IsReadyForID = kTRUE fSiLi = GetDetector(1); fCsI = GetDetector(2); fGGgrid = fPGgrid = 0; TIter next(fIDGrids); KVIDGrid* grid = 0; while ((grid = (KVIDGrid*)next())) { if (!strcmp(grid->GetVarY(), "SILI_GG")) fGGgrid = (KVIDZAGrid*)grid; else if (!strcmp(grid->GetVarY(), "SILI_PG")) fPGgrid = (KVIDZAGrid*)grid; } if (fGGgrid) { SetBit(kReadyForID); fGGgrid->Initialize(); if (fPGgrid) fPGgrid->Initialize(); } else ResetBit(kReadyForID); }
TF1* KVRecombination::GetELossFunction(Int_t Z, Int_t A, Bool_t Wrong){ // Return pointer to TF1 giving energy loss in active layer of detector minus // the pulse height defect for a given nucleus (Z,A). // // If Wrong=kTRUE (default:kFALSE) this will be calculated incorrectly // (if the particle does not stop in the detector) by using the Parlog formula // with the incident energy of the particle instead of the calculated energy // loss of the particle. wrong=Wrong; if(!fDeltaEphd){ fDeltaEphd = new TF1(Form("KVRecombination:%s:ELossActive", GetDetector()->GetName()), this, &KVRecombination::ELossActive, 0., 1.e+04, 2, "KVRecombination", "ELossActive"); fDeltaEphd->SetNpx( gEnv->GetValue("KVPulseHeightDefect.EnergyLoss.Npx", 20) ); } fDeltaEphd->SetParameters((Double_t)Z, (Double_t)A); fDeltaEphd->SetRange(0., GetDetector()->GetSmallestEmaxValid(Z,A)); fDeltaEphd->SetTitle(Form("PHD dependent energy loss [MeV] in detector %s for Z=%d A=%d", GetDetector()->GetName(), Z, A)); GetParlogPHDFunction(Z,A); return fDeltaEphd; }
Double_t KVRecombination::ELossActive(Double_t *x, Double_t *par){ // Calculate energy lost in active layer of detector minus the Parlog PHD // x[0] = incident energy // par[0] = Z // par[1] = A Double_t e = x[0]; TIter next(GetDetector()->GetListOfAbsorbers()); KVMaterial* mat; while( (mat = (KVMaterial*)next()) != GetDetector()->GetActiveLayer() ){ // calculate energy losses in absorbers before active layer e = mat->GetERes(par[0], par[1], e); //residual energy after layer if (e <= 0.) return 0.; // return 0 if particle stops in layers before active layer } // calculate energy loss in active layer Double_t dE = mat->GetDeltaE(par[0], par[1], e); // calculate Parlog PHD corresponding to energy lost in active layer Double_t phd; if(wrong) phd = PHDParlog(&e, par);//incorrect calculation using incident energy else phd = PHDParlog(&dE, par); return dE - phd; }
float ThermometerFa::Read() { float val = GetDetector()->Read(); std::vector<float> &histData = GetHistData(); if(histData.size() < 3) histData.push_back(val); histData[0] = histData[1]; histData[1] = histData[2]; histData[2] = val; return val; }
void KVIDChIoCsI_camp5::Initialize() { // Initialize telescope for current run. // If there is at least 1 grid, we set fCanIdentify = kTRUE // "Natural" line widths are calculated for KVIDZAGrids. fChIo = (KVChIo*) GetDetector(1); fCsI = (KVCsI*) GetDetector(2); fCsIRPedestal = fCsI->GetPedestal("R"); fCsILPedestal = fCsI->GetPedestal("L"); fGGgrid = fPGgrid = 0; TIter next(GetListOfIDGrids()); KVIDGraph* grid; while ((grid = (KVIDGraph*)next())) { if (!strcmp(grid->GetVarY(), "CHIO-GG")) fGGgrid = (KVIDZAGrid*)grid; else if (!strcmp(grid->GetVarY(), "CHIO-PG")) fPGgrid = (KVIDZAGrid*)grid; } if (fGGgrid) { SetBit(kReadyForID); fGGgrid->Initialize(); if (fPGgrid) fPGgrid->Initialize(); } else ResetBit(kReadyForID); }
void KVIDCsI::Initialize() { // Override default initialization method // If telescope has 1 CsI detector and at least 1 grid // then it is ready to identify particles, after we initialise // the grid if (GetDetectors()->GetEntries() == 1 && GetDetector(1)->IsType("CsI") && GetIDGrid()) { GetIDGrid()->Initialize(); SetBit(kReadyForID); } else ResetBit(kReadyForID); }
void KVIDCsI::Initialize() { // Initialisation of telescope before identification. // This method MUST be called once before any identification is attempted. // Initialisation of grid is performed here. // IsReadyForID() will return kTRUE if a grid is associated to this telescope for the current run. CsIGrid = (KVIDGCsI *) GetIDGrid(); fCsI = GetDetector(1); if( CsIGrid ) { CsIGrid->Initialize(); SetBit(kReadyForID); } else ResetBit(kReadyForID); }
int main(int argc, char *argv[]) { int minX=0, minY=0, binX=1, binY=1, sizeX, sizeY; char model[256]; float temperature; int status; checkStatus(Initialize("/usr/local/etc/andor")); printf("Intialize(/usr/local/etc/andor) OK\n"); checkStatus(GetDetector(&sizeX, &sizeY)); printf("GetDetector() OK, sizeX=%d, sizeY=%d\n", sizeX, sizeY); checkStatus(GetHeadModel(model)); printf("GetHeadModel() OK, model=%s\n", model); checkStatus(SetReadMode(4)); printf("SetReadMode(4) OK\n"); checkStatus(SetImage(binX, binY, minX+1, minX+sizeX, minY+1, minY+sizeY)); printf("SetImage OK\n"); status = GetTemperatureF(&temperature); printf("GetTemperature OK, temperature=%f, status=%d\n", temperature, status); return 0; }
void KVFAZIA::GetDetectorEvent(KVDetectorEvent* detev, TSeqCollection* signals) { // First step in event reconstruction based on current status of detectors in array. // Fills the given KVDetectorEvent with the list of all groups which have fired. // i.e. loop over all groups of the array and test whether KVGroup::Fired() returns true or false. // // If the list of fired acquisition parameters 'signals' is given, KVMultiDetArray::GetDetectorEvent // is called // if (signals) { // list of fired acquisition parameters given TIter next_par(signals); KVSignal* par = 0; KVDetector* det = 0; KVGroup* grp = 0; while ((par = (KVSignal*)next_par())) { if (!(par->GetN() > 0)) Info("GetDetectorEvent", "%s empty", par->GetName()); par->DeduceFromName(); if ((det = GetDetector(par->GetDetectorName()))) { ((KVFAZIADetector*)det)->SetSignal(par, par->GetType()); if ((!(((KVFAZIADetector*)det)->GetSignal(par->GetType())->GetN() > 0))) Warning("Error", "%s %s empty signal is returned", det->GetName(), par->GetType()); if ((grp = det->GetGroup()) && !detev->GetGroups()->FindObject(grp)) { detev->AddGroup(grp); } } else { Error("GetDetectedEvent", "Unknown detector %s !!!", par->GetDetectorName()); } } } else { KVMultiDetArray::GetDetectorEvent(detev, 0); } }
void Features::Detect(const Mat& image, vector<cv::KeyPoint>& keys) const { cv::FeatureDetector* detector = GetDetector(this->flag); detector->detect(image, keys); }
/* Detection is for single scale detection Input: 1. im: A grayscale image in height x width. 2. ext: The pre-defined HOG extractor. 3. threshold: The constant threshold to control the prediction. Output: 1. bbox: The predicted bounding boxes in this format (n x 5 matrix): x11 y11 x12 y12 s1 ... ... ... ... ... xi1 yi1 xi2 yi2 si ... ... ... ... ... xn1 yn1 xn2 yn2 sn where n is the number of bounding boxes. For the ith bounding box, (xi1,yi1) and (xi2, yi2) correspond to its top-left and bottom-right coordinates, and si is the score of convolution. Please note that these coordinates are in the input image im. */ Mat Detector::Detection(const Mat& im, HOGExtractor& ext, const float threshold) { /* TODO 4: Obtain the HOG descriptor of the input im. And then convolute the linear detector on the HOG descriptor. You may put the score of convolution in the structure "convolutionScore". */ Mat HOGDes = ext.ExtractHOG(im); Mat convolutionScore(HOGDes.size[0], HOGDes.size[1], CV_32FC1, Scalar(0)); // Begin TODO 4 Mat detector = GetDetector(); vector<cv::Mat> channels_HOGDes(36); vector<cv::Mat> channels_detector(36); split(HOGDes, channels_HOGDes); split(detector, channels_detector); vector<cv::Mat>::iterator iter1; vector<cv::Mat>::iterator iter2; for (iter1 = channels_HOGDes.begin(), iter2 = channels_detector.begin(); iter1 != channels_HOGDes.end(),iter2!=channels_detector.end(); iter1++, iter2++) { Mat t_res(HOGDes.size[0], HOGDes.size[1], CV_32FC1, Scalar(0)); filter2D( (*iter1), t_res, (*iter1).depth(), (*iter2) ); convolutionScore += t_res; } // cout << "HoGsize= " << HOGDes.size[0] << ", " << HOGDes.size[1] << endl; // cout << "Detectorsize= " << detector.size[0] << ", " << detector.size[1] << endl; /* for (int i; i < HOGDes.size[0]; i++) { for (int j; j < HOGDes.size[0]; j++) { cout << convolutionScore.at<float>(i,j) << ", "; } cout << endl; } cout << endl;*/ // End TODO 4 /* TODO 5: Select out those positions where the score is above the threshold. Here, the positions are in ConvolutionScore. To output the coordinates of the bounding boxes, please remember to recover the positions to those in the input image. Please put the predicted bounding boxes and their scores in the below structure "bbox". */ Mat bbox; // Begin TODO 5 float cells = ext.GetCells(); float blocks = ext.GetBlocks(); float maxScore = -5.0; for ( int i = 0; i < convolutionScore.size[0]; i++ ) { for ( int j = 0; j < convolutionScore.size[1]; j++ ) { if (convolutionScore.at<float>(i, j)>maxScore) { maxScore = convolutionScore.at<float>(i, j); } if (convolutionScore.at<float>(i, j) > threshold) { float x1, y1, x2, y2, score; score = convolutionScore.at<float>(i, j); x1 = (int)((float)i - ((float)detector.size[0] / 2)+0.5) * cells; y1 = (int)((float)j - ((float)detector.size[1] / 2) + 0.5) * cells; x2 = (int)((float)i + ((float)detector.size[0] / 2) + 0.5) * cells; y2 = (int)((float)j + ((float)detector.size[1] / 2) + 0.5) * cells; Mat t_bbox = (Mat_<float>(1, 5) << x1, y1, x2, y2, score); if (bbox.size[0]!=0) { vconcat(bbox, t_bbox, bbox); } else { bbox = t_bbox; //bbox = Mat(t_bbox); } } } } cout << "Max Score = " << maxScore << endl; // End TODO 5 // cout << "Here bbox = " <<bbox.rows<<", "<<bbox.cols<< endl; return bbox; }
Double_t KVIDChIoSi_e475s::GetIDMapY(Option_t *) { //Y coordinate for ChIo-Si identification is chio pedestal-corrected 'PG' channel //return GetDetector(1)->GetACQData("PG") - GetDetector(1)->GetPedestal("PG"); return GetDetector(1)->GetEnergy(); }
void AngularCorrelationSelector::FillHistograms() { //without addback for(auto g1 = 0; g1 < fGrif->GetMultiplicity(); ++g1) { auto grif1 = fGrif->GetGriffinHit(g1); //check for coincident betas bool coincBeta = false; for(auto s = 0; s < fScep->GetMultiplicity(); ++s) { auto scep = fScep->GetSceptarHit(s); if(!coincBeta && gbLow <= grif1->GetTime()-scep->GetTime() && grif1->GetTime()-scep->GetTime() <= gbHigh) coincBeta = true; fH1["betaGammaTiming"]->Fill(scep->GetTime()-grif1->GetTime()); fH2["betaGammaHP"]->Fill(scep->GetDetector(), grif1->GetArrayNumber()); } fH1["gammaEnergy"]->Fill(grif1->GetEnergy()); if(coincBeta) fH1["gammaEnergyBeta"]->Fill(grif1->GetEnergy()); for(auto g2 = 0; g2 < fGrif->GetMultiplicity(); ++g2) { if(g1 == g2) continue; auto grif2 = fGrif->GetGriffinHit(g2); double angle = grif1->GetPosition().Angle(grif2->GetPosition())*180./TMath::Pi(); if(angle < 0.0001) continue; auto angleIndex = fAngleMap.lower_bound(angle-0.0005); double ggTime = TMath::Abs(grif1->GetTime()-grif2->GetTime()); fH1["gammaGammaTiming"]->Fill(ggTime); fH2["gammaGammaHP"]->Fill(grif1->GetArrayNumber(), grif2->GetArrayNumber()); if(ggTime < ggHigh) { fH2["gammaGamma"]->Fill(grif1->GetEnergy(), grif2->GetEnergy()); fH2[Form("gammaGamma%d", angleIndex->second)]->Fill(grif1->GetEnergy(), grif2->GetEnergy()); if(coincBeta) { fH2["gammaGammaBeta"]->Fill(grif1->GetEnergy(), grif2->GetEnergy()); fH2[Form("gammaGammaBeta%d", angleIndex->second)]->Fill(grif1->GetEnergy(), grif2->GetEnergy()); } } else if(bgLow < ggTime && ggTime < bgHigh) { fH2["gammaGammaBG"]->Fill(grif1->GetEnergy(), grif2->GetEnergy()); fH2[Form("gammaGammaBG%d", angleIndex->second)]->Fill(grif1->GetEnergy(), grif2->GetEnergy()); if(coincBeta) { fH2["gammaGammaBetaBG"]->Fill(grif1->GetEnergy(), grif2->GetEnergy()); fH2[Form("gammaGammaBetaBG%d", angleIndex->second)]->Fill(grif1->GetEnergy(), grif2->GetEnergy()); } } } //event mixing, we use the last event as second griffin for(auto g2 = 0; g2 < fLastGrif.GetMultiplicity(); ++g2) { if(g1 == g2) continue; auto grif2 = fLastGrif.GetGriffinHit(g2); double angle = grif1->GetPosition().Angle(grif2->GetPosition())*180./TMath::Pi(); if(angle < 0.0001) continue; auto angleIndex = fAngleMap.lower_bound(angle-0.0005); double ggTime = TMath::Abs(grif1->GetTime()-grif2->GetTime()); fH2["gammaGammaHPMixed"]->Fill(grif1->GetArrayNumber(), grif2->GetArrayNumber()); fH2["gammaGammaMixed"]->Fill(grif1->GetEnergy(), grif2->GetEnergy()); fH2[Form("gammaGammaMixed%d", angleIndex->second)]->Fill(grif1->GetEnergy(), grif2->GetEnergy()); if(coincBeta) { fH2["gammaGammaBetaMixed"]->Fill(grif1->GetEnergy(), grif2->GetEnergy()); fH2[Form("gammaGammaBetaMixed%d", angleIndex->second)]->Fill(grif1->GetEnergy(), grif2->GetEnergy()); } } } //with addback for(auto g1 = 0; g1 < fGrif->GetAddbackMultiplicity(); ++g1) { auto grif1 = fGrif->GetAddbackHit(g1); //check for coincident betas bool coincBeta = false; for(auto s = 0; s < fScep->GetMultiplicity(); ++s) { auto scep = fScep->GetSceptarHit(s); if(!coincBeta && gbLow <= grif1->GetTime()-scep->GetTime() && grif1->GetTime()-scep->GetTime() <= gbHigh) coincBeta = true; fH1["betaAddbackTiming"]->Fill(scep->GetTime()-grif1->GetTime()); fH2["betaAddbackHP"]->Fill(scep->GetDetector(), grif1->GetArrayNumber()); } fH1["addbackEnergy"]->Fill(grif1->GetEnergy()); if(coincBeta) fH1["addbackEnergyBeta"]->Fill(grif1->GetEnergy()); for(auto g2 = 0; g2 < fGrif->GetAddbackMultiplicity(); ++g2) { if(g1 == g2) continue; auto grif2 = fGrif->GetAddbackHit(g2); double angle = grif1->GetPosition().Angle(grif2->GetPosition())*180./TMath::Pi(); if(angle < 0.0001) continue; auto angleIndex = fAngleMapAddback.lower_bound(angle-0.0005); double ggTime = TMath::Abs(grif1->GetTime()-grif2->GetTime()); fH1["addbackAddbackTiming"]->Fill(ggTime); fH2["addbackAddbackHP"]->Fill(grif1->GetArrayNumber(), grif2->GetArrayNumber()); if(ggTime < ggHigh) { fH2["addbackAddback"]->Fill(grif1->GetEnergy(), grif2->GetEnergy()); fH2[Form("addbackAddback%d", angleIndex->second)]->Fill(grif1->GetEnergy(), grif2->GetEnergy()); if(coincBeta) { fH2["addbackAddbackBeta"]->Fill(grif1->GetEnergy(), grif2->GetEnergy()); fH2[Form("addbackAddbackBeta%d", angleIndex->second)]->Fill(grif1->GetEnergy(), grif2->GetEnergy()); } } else if(bgLow < ggTime && ggTime < bgHigh) { fH2["addbackAddbackBG"]->Fill(grif1->GetEnergy(), grif2->GetEnergy()); fH2[Form("addbackAddbackBG%d", angleIndex->second)]->Fill(grif1->GetEnergy(), grif2->GetEnergy()); if(coincBeta) { fH2["addbackAddbackBetaBG"]->Fill(grif1->GetEnergy(), grif2->GetEnergy()); fH2[Form("addbackAddbackBetaBG%d", angleIndex->second)]->Fill(grif1->GetEnergy(), grif2->GetEnergy()); } } } //event mixing, we use the last event as second griffin for(auto g2 = 0; g2 < fLastGrif.GetAddbackMultiplicity(); ++g2) { if(g1 == g2) continue; auto grif2 = fLastGrif.GetAddbackHit(g2); double angle = grif1->GetPosition().Angle(grif2->GetPosition())*180./TMath::Pi(); if(angle < 0.0001) continue; auto angleIndex = fAngleMapAddback.lower_bound(angle-0.0005); double ggTime = TMath::Abs(grif1->GetTime()-grif2->GetTime()); fH2["addbackAddbackHPMixed"]->Fill(grif1->GetArrayNumber(), grif2->GetArrayNumber()); fH2["addbackAddbackMixed"]->Fill(grif1->GetEnergy(), grif2->GetEnergy()); fH2[Form("addbackAddbackMixed%d", angleIndex->second)]->Fill(grif1->GetEnergy(), grif2->GetEnergy()); if(coincBeta) { fH2["addbackAddbackBetaMixed"]->Fill(grif1->GetEnergy(), grif2->GetEnergy()); fH2[Form("addbackAddbackBetaMixed%d", angleIndex->second)]->Fill(grif1->GetEnergy(), grif2->GetEnergy()); } } } //update "last" event fLastGrif = *fGrif; fLastScep = *fScep; }
int main(int argc, char **argv) { int status; int bitdepth; int width, height; int min, max; int i, j, numgains; float gain; int num_ad; int num_vspeeds; int num_hspeeds; float speed; AndorCapabilities caps; at_32 lNumCameras; at_32 lCameraHandle; int start_n, stop_n; int npix; /* Check command line */ npix = 90; if (argc > 1) sscanf(argv[1], "%d", &npix); /* FIRST, FIND OUT WHAT WE NEED TO KNOW ABOUT THIS CAMERA. */ printf("Initializing Andor Camera.\n"); /* How many cameras are connected */ printf("GetAvailableCameras = %d\n", GetAvailableCameras(&lNumCameras)); if (lNumCameras == 1) printf("There is %d camera connected.\n", lNumCameras); else printf("There are %d cameras connected.\n", lNumCameras); if (lNumCameras <= 0) exit(0); /* Get the camera we are working with. */ printf("GetCameraHandle = %d\n", GetCameraHandle(0, &lCameraHandle)); printf("SetCurrentCamera = %d\n", SetCurrentCamera(lCameraHandle)); /* Initialize the CCD */ printf("Initialize = %d\n", Initialize("/usr/local/etc/andor")); /* Wait for this to happen */ sleep(2); /* What Capabilities do we have? */ caps.ulSize = sizeof(caps); printf("GetCapabilities = %d\n", GetCapabilities(&caps)); if (caps.ulCameraType & AC_CAMERATYPE_IXON) printf("Camera is an iXon.\n"); else printf("Camera is not an iXon.\n"); if (caps.ulAcqModes & AC_ACQMODE_FRAMETRANSFER) printf("Frame transfer is available.\n"); else printf("Frame transfer is not available.\n"); if (caps.ulSetFunctions & AC_SETFUNCTION_CROPMODE) printf("Crop mode is available.\n"); else printf("Crop mode is not available.\n"); /* Find out what the width and height are */ printf("GetDetector = %d\n", GetDetector(&width, &height)); printf("Andor full size %dx%d.\n", width, height); /* What is the allowable temperature range? */ printf("GetTemperatureRange = %d\n", GetTemperatureRange(&min, &max)); printf("Andor temperature range is %d to %d C.\n", min, max); /* How many preamp gains do we have? */ printf("GetNumberPreAmpGains = %d\n", GetNumberPreAmpGains(&numgains)); printf("Andor number of preamp gains is %d.\n", numgains); /* Let's find out what these gains are */ for (i=0; i<numgains; i++) { printf("GetPreAmpGain = %d\n", GetPreAmpGain(i, &gain)); printf("Andor Preamp Gain %d is %f.\n", i, gain); } /* How many vertical speeds do we have? */ printf("GetNumberVSSpeeds = %d\n", GetNumberVSSpeeds(&num_vspeeds)); printf("Andor number of Vertical Speeds is %d.\n", num_vspeeds); /* Let's find out what these VSpeeds are */ for (i=0; i<num_vspeeds; i++) { printf("GetVSSpeed = %d\n", GetVSSpeed(i, &speed)); printf("Andor Vertical Speed %d is %.2f uS.\n", i, speed); } for(j = 0; j < 1; j++) { if (j == 0) printf("For EMCCD output:\n"); else printf("For CCD output:\n"); /* How many horizontal speeds do we have? */ printf("GetNumberHSSpeeds = %d\n", GetNumberHSSpeeds(0, j, &num_hspeeds)); printf("Andor number of Horizontal Speeds is %d.\n", num_hspeeds); /* Let's find out what these speeds are */ for (i=0; i<num_hspeeds; i++) { printf("GetHSSpeed = %d\n", GetHSSpeed(0, j, i, &speed)); printf("Andor Horizontal Speed %d is %.2f MHz.\n", i, speed); } } /* What is the range of gain settings - This is always wrong */ printf("GetEMGainRange = %d\n", GetEMGainRange(&min, &max)); printf("Andor EM Gain range is %d to %d.\n", min, max); /* How many AD channels are there? */ printf("GetNumberADChannels = %d\n", GetNumberADChannels(&num_ad)); printf("Number of AD channels = %d\n", num_ad); /* What are the bit depths? */ for(i=0; i < num_ad; i++) { printf("GetBitDepth = %d\n", GetBitDepth(i, &bitdepth)); printf("AD channel %d has bit depth %d\n", i, bitdepth); } /* NOW WE START TO SET THINGS UP THE WAY WE WANT THEM */ /* Turn on Cameralink mode */ printf("SetCameraLinkMode = %d\n", SetCameraLinkMode(1)); /* Put us in Frame Transfer Mode */ printf( "Turning on Frame Transfer Mode.\n"); printf("SetFrameTransferMode = %d\n", SetFrameTransferMode(1)); /* Set output amplifier to EMCCD */ printf("SetOutputAmplifier = %d\n", SetOutputAmplifier(0)); /* Turn on advanced EM settings */ printf("SetEMAdvanced = %d\n", SetEMAdvanced(1)); /* Let's see if that worked... we should get 1000 as maximum */ printf("GetEMGainRange = %d\n", GetEMGainRange(&min, &max)); printf("Andor EM Gain range is %d to %d.\n", min, max); /* Set EM gain */ printf("SetEMCCDGain = %d\n", SetEMCCDGain(300)); /* Set our horizontal speed to the desired one. */ printf("SetHSSpeed = %d\n", SetHSSpeed(0, 0)); /* Set our vertical speed to the desired one. */ printf("SetVSSpeed = %d\n", SetVSSpeed(0)); /* Set our gain to the desired one. */ printf("SetPreAmpGain = %d\n", SetPreAmpGain(2)); /* Setup the read mode. I suspect this is the problem */ printf("SetReadMode = %d\n", SetReadMode(4)); /* Try to get frames like this */ printf("SetAcquisitionMode = %d\n", SetAcquisitionMode(5)); printf("PrepareAcquisition = %d\n", PrepareAcquisition()); printf("StartAcquisition %d\n", StartAcquisition()); sleep(1); printf("AbortAcquisition %d\n", AbortAcquisition()); /* This sequence seemed to work with the server */ //printf("SetHSSpeed = %d\n", SetHSSpeed(0, 1)); /* DO we get the right gain range now? */ printf("GetEMGainRange = %d\n", GetEMGainRange(&min, &max)); printf("Andor EM Gain range is %d to %d.\n", min, max); /* We wish to use Cropped mode */ printf("SetIsolatedCropMode = %d\n", SetIsolatedCropMode(1,npix,npix,1,1)); /* Set the image to read the full area of cropped region */ printf("SetImage = %d\n", SetImage(1, 1, 1, npix, 1, npix)); /* Set exposure time to 1mS */ printf("SetExposureTime = %d\n", SetExposureTime(0.001)); /* Set Kinetic Cycle time to the smallest possible value */ printf("SetKineticCycleTime = %d\n",SetKineticCycleTime(0.0)); /* OK, let's see what the frame rate is */ printf("SetAcquisitionMode = %d\n", SetAcquisitionMode(5)); printf("StartAcquisition %d\n", StartAcquisition()); sleep(1); printf("GetTotalNumberImagesAcquired = %d\n", GetTotalNumberImagesAcquired(&start_n)); sleep(5); printf("GetTotalNumberImagesAcquired = %d\n", GetTotalNumberImagesAcquired(&stop_n)); printf("Frame rate seems to be %.2f Hz\n", (double)(stop_n - start_n)/5.0); printf("AbortAcquisition = %d\n",AbortAcquisition()); /* Get one frame... it seems things work better after this */ GetStatus(&status); while(status==DRV_ACQUIRING) GetStatus(&status); printf("SaveAsFITS %d\n", SaveAsFITS("./image.fit", 4)); /* That is all */ printf("ShutDown = %d\n", ShutDown()); exit(0); }
//------------------------------------------------------------------------------ // FUNCTION NAME: InitializeCamera() // // RETURNS: If the function terminates before entering the message loop, // return FALSE. // Otherwise, return the WPARAM value sent by the WM_QUIT // message. // // LAST MODIFIED: PMcK 11/11/98 // // DESCRIPTION: calls initialization function, processes message loop // // Windows recognizes this function by name as the initial // entry point for the program. This function calls the // application initialization routine, if no other instance of // the program is running, and always calls the instance // initialization routine. It then executes a message // retrieval and dispatch loop that is the top-level control // structure for the remainder of execution. The loop is // terminated when a WM_QUIT message is received, at which // time this function exits the application instance by // returning the value passed by PostQuitMessage(). // // If the function must abort before entering the message loop, // it returns the conventional value NULL. // // // ARGUMENTS: hInstance - The handle to the instance of this application // that is currently being executed. // // hPrevInstance - The handle to the instance of this // application that was last executed. If this is the only // instance of this application executing, hPrevInstance is // NULL. In Win32 applications, this parameter is always NULL. // // lpCmdLine - A pointer to a null terminated string specifying // the command line of the application. // // nCmdShow - Specifies how the main window is to be diplayed. //------------------------------------------------------------------------------ bool ANDOR885_Camera::InitializeCamera() { AndorCapabilities caps; char aBuffer[256]; int errorValue; bool errorFlag = false; // int test,test2; //need to pause while camera initializes float speed, STemp, gain; int iSpeed, nAD, nAmp, nPreAmp, index, IsPreAmpAvailable; int i; caps.ulSize = sizeof(AndorCapabilities); long numCameras; GetAvailableCameras(&numCameras); GetCurrentDirectoryA(256,aBuffer);// Look in current working directory // for driver files. Note: had to override usual mapping of GetCurrentDirectory to // GetCurrentDirectoryW because of mismatch of argument types. errorValue=Initialize(aBuffer); // Initialize driver in current directory printError(errorValue, "Initialize error", &errorFlag, ANDOR_ERROR); if (errorFlag) return true; // Get camera capabilities errorValue=GetCapabilities(&caps); printError(errorValue, "Get Andor Capabilities information Error", &errorFlag, ANDOR_ERROR); // Get Head Model errorValue=GetHeadModel(model); printError(errorValue, "Get Head Model information Error", &errorFlag, ANDOR_ERROR); // Get detector information errorValue=GetDetector(&imageWidth,&imageHeight); printError(errorValue, "Get Detector information Error", &errorFlag, ANDOR_ERROR); // Set frame transfer mode errorValue=SetFrameTransferMode((frameTransfer == ANDOR_ON) ? 1 : 0); printError(errorValue, "Set Frame Transfer Mode Error", &errorFlag, ANDOR_ERROR); // Set acquisition mode to required setting specified in xxxxWndw.c errorValue=SetAcquisitionMode(acquisitionMode); printError(errorValue, "Set Acquisition Mode Error", &errorFlag, ANDOR_ERROR); if(caps.ulGetFunctions > 32) { GetEMCCDGain(&EMCCDGain); } if(readMode == READMODE_IMAGE) { // This function only needs to be called when acquiring an image. It sets // the horizontal and vertical binning and the area of the image to be // captured. In this example it is set to 1x1 binning and is acquiring the // whole image SetImage(1,1,1,imageWidth,1,imageHeight); } // Set read mode to required setting specified in xxxxWndw.c errorValue=SetReadMode(readMode); printError(errorValue, "Set Read Mode Error", &errorFlag, ANDOR_ERROR); // Set Vertical speed to max /* STemp = 0; VSnumber = 0; GetNumberVSSpeeds(&index); for(iSpeed=0; iSpeed<index; iSpeed++){ GetVSSpeed(iSpeed, &speed); if(speed > STemp){ STemp = speed; VSnumber = iSpeed; } } errorValue=SetVSSpeed(VSnumber); printError(errorValue, "Set Vertical Speed Error", &errorFlag, ANDOR_ERROR); */ if (!notDestructed){ STemp = 0; GetNumberVSSpeeds(&index); for(iSpeed=0; iSpeed < index; iSpeed++){ GetVSSpeed(iSpeed, &speed); verticalShiftSpeed_t.choices[iSpeed] = STI::Utils::valueToString(speed); if(speed > STemp){ STemp = speed; verticalShiftSpeed = iSpeed; } } verticalShiftSpeed_t.initial = (--verticalShiftSpeed_t.choices.end())->second; } errorValue = SetVSSpeed(verticalShiftSpeed); printError(errorValue, "Set Vertical Speed Error", &errorFlag, ANDOR_ERROR); /* Set Vertical Clock Voltage; note: only the fastest vertical shift speeds will benefit from the higher clock voltage; increasing clock voltage adds noise. */ if (!notDestructed) { index = 0; errorValue = GetNumberVSAmplitudes(&index); if (errorValue == DRV_SUCCESS) { for (i = 0; i < index; i++){ if (i == 0){ verticalClockVoltage_t.choices[i] = "Normal"; } else { verticalClockVoltage_t.choices[i] = STI::Utils::valueToString(i); } } verticalClockVoltage_t.initial = (verticalClockVoltage_t.choices.begin())->second; } } errorValue = SetVSAmplitude(0); printError(errorValue, "Set Vertical Clock Voltage Error", &errorFlag, ANDOR_ERROR); // Set Horizontal Speed to max and check bit depth //(scan over all possible AD channels; although, the 885 has only one 14-bit channel) STemp = 0; // HSnumber = 0; ADnumber = 0; if (!notDestructed) { errorValue = GetNumberADChannels(&nAD); if (errorValue != DRV_SUCCESS){ std::cerr << "Get number AD Channel Error\n"; errorFlag = true; } else if (nAD != 1) { std::cerr << "Expect 1 AD channel for this camera. The following code will miss channels\n"; errorFlag = true; } else { errorValue = GetNumberHSSpeeds(0, 0, &index); if(errorValue == DRV_SUCCESS){ for (iSpeed = 0; iSpeed < index; iSpeed++) { GetHSSpeed(0, 0, iSpeed, &speed); horizontalShiftSpeed_t.choices[iSpeed] = STI::Utils::valueToString(speed); if(speed < STemp){ STemp = speed; horizontalShiftSpeed = iSpeed; } } horizontalShiftSpeed_t.initial = horizontalShiftSpeed_t.choices.find(horizontalShiftSpeed)->second; } //getBitDepth if (DRV_SUCCESS != GetBitDepth(0, &bitDepth)) return true; } errorValue = GetNumberAmp(&nAmp); printError(errorValue, "Get Number Amplifiers Error", &errorFlag, ANDOR_ERROR); errorValue = GetNumberPreAmpGains(&nPreAmp); printError(errorValue, "Get Number Preamplifiers Error", &errorFlag, ANDOR_ERROR); if (nAmp == 1 && nAD == 1) { for (i = 0; i < nPreAmp; i++) { errorValue = GetPreAmpGain(i, &gain); errorValue = IsPreAmpGainAvailable(0,0,horizontalShiftSpeed,i,&IsPreAmpAvailable); if (IsPreAmpAvailable == 1) { preAmpGain_t.choices[i] = STI::Utils::valueToString(gain); } } if (!preAmpGain_t.choices.empty()) { preAmpGain = preAmpGain_t.choices.begin()->first; //preAmpGainPos = 0; preAmpGain_t.initial = (preAmpGain_t.choices.begin())->second; // set the initial condition for the preamplifier gain errorValue = SetPreAmpGain(preAmpGain); printError(errorValue, "Set AD Channel Error", &errorFlag, ANDOR_ERROR); } else { std::cerr << "No gains available at this speed. Weird."; errorFlag = true; } } else { std::cerr << "Unexpected number of A/D's or output amps" << std::endl; std::cerr << "Expected A/D's: 1 \t Measured: " << nAD << std::endl; std::cerr << "Expected output Amps: 1 \t Measured: " << nAmp << std::endl; errorFlag = true; } } else { errorValue = SetPreAmpGain(preAmpGain); printError(errorValue, "Set AD Channel Error", &errorFlag, ANDOR_ERROR); } errorValue=SetADChannel(ADnumber); printError(errorValue, "Set AD Channel Error", &errorFlag, ANDOR_ERROR); errorValue=SetHSSpeed(0,horizontalShiftSpeed); printError(errorValue, "Set Horizontal Speed Error", &errorFlag, ANDOR_ERROR); if(errorFlag) //MessageBox(GetActiveWindow(),aBuffer,"Error!",MB_OK); SMD std::cerr<<aBuffer<<std::endl; // Wait for 2 seconds to allow MCD to calibrate fully before allowing an // acquisition to begin // test=GetTickCount(); // do{ // test2=GetTickCount()-test; // }while(test2<2000); Sleep(2000); errorValue = SetExposureTime(exposureTime); printError(errorValue, "Exposure time error", &errorFlag, ANDOR_ERROR); // It is necessary to get the actual times as the system will calculate the // nearest possible time. eg if you set exposure time to be 0, the system // will use the closest value (around 0.01s) GetAcquisitionTimings(&exposureTime,&accumulateTime,&kineticTime); std::cerr << "Actual Exposure Time is " << exposureTime << " s.\n"; // Set Shutter is made up of ttl level, shutter and open close time //Check Get open close time if(openTime==0) openTime=1; if(closeTime==0) closeTime=1; // Set shutter errorValue=SetShutter(ttl,shutterMode,closeTime,openTime); if(errorValue!=DRV_SUCCESS){ std::cerr << "Shutter error\n"; errorFlag = true; } else std::cerr << "Shutter set to specifications\n"; /*// Determine availability of trigger option and set trigger selection std::map<int,std::string>::iterator it; std::vector<int> triggerKeys; for (it = triggerMode_t.choices.begin(); it != triggerMode_t.choices.end(); it++) { errorValue = SetTriggerMode(it->first); if (errorValue != DRV_SUCCESS) triggerKeys.push_back(it->first); } for (int i = 0; i < triggerKeys.size(); i++) triggerMode_t.choices.erase(triggerKeys.at(i)); if (triggerMode_t.choices.empty()) { std::cerr << "No triggerModes found" << std::endl; return true; } else if (triggerMode_t.choices.find(TRIGGERMODE_EXTERNAL_EXPOSURE) != triggerMode_t.choices.end()) triggerMode = TRIGGERMODE_EXTERNAL_EXPOSURE; else if (triggerMode_t.choices.find(TRIGGERMODE_EXTERNAL) != triggerMode_t.choices.end()) triggerMode = TRIGGERMODE_EXTERNAL; else triggerMode = triggerMode_t.choices.begin()->first; errorValue=SetTriggerMode(triggerMode); printError(errorValue, "Set Trigger Mode Error", &errorFlag, ANDOR_ERROR); triggerMode_t.initial = triggerMode_t.choices.find(triggerMode)->second; */ // Determine availability of trigger option and set trigger selection std::map<int,std::string>::iterator it; std::vector<int> triggerKeys; for (it = triggerMode_t.choices.begin(); it != triggerMode_t.choices.end(); it++) { errorValue = SetTriggerMode(it->first); if (errorValue != DRV_SUCCESS) triggerKeys.push_back(it->first); } for (int i = 0; i < triggerKeys.size(); i++) triggerMode_t.choices.erase(triggerKeys.at(i)); if (triggerMode_t.choices.empty()) { std::cerr << "No triggerModes found" << std::endl; return true; } else if (triggerMode_t.choices.find(TRIGGERMODE_EXTERNAL_EXPOSURE) != triggerMode_t.choices.end()) triggerMode = TRIGGERMODE_EXTERNAL_EXPOSURE; else if (triggerMode_t.choices.find(TRIGGERMODE_EXTERNAL) != triggerMode_t.choices.end()) triggerMode = TRIGGERMODE_EXTERNAL; else triggerMode = triggerMode_t.choices.begin()->first; errorValue=SetTriggerMode(triggerMode); printError(errorValue, "Set Trigger Mode Error", &errorFlag, ANDOR_ERROR); triggerMode_t.initial = triggerMode_t.choices.find(triggerMode)->second; errorValue = GetTemperatureRange(&minTemp, &maxTemp); if (errorValue != DRV_SUCCESS){ std::cerr << "Error finding temperature range or camera is not on" << std::endl; errorFlag = true; } else { std::cerr << "Temperature must be between " << minTemp << " and " << maxTemp << std::endl; std::cerr << "Warning: Water cooling is required for temperatures < -58 deg C" << std::endl; //Set temperature if (coolerSetpt > maxTemp || coolerSetpt < minTemp) { std::cerr << "Chosen temperature out of range." << std::endl; if (coolerSetpt > maxTemp) coolerSetpt = maxTemp; else coolerSetpt = minTemp; std::cerr << "Resetting temp to nearest acceptable value " << std::endl; } errorValue = SetTemperature(coolerSetpt); printError(errorValue, "Error setting cooler temperature", &errorFlag, ANDOR_ERROR); int i; errorValue = IsCoolerOn(&i); if (i == 0) { // if it's off and it's supposed to be on, turn it on if (coolerStat == ANDOR_ON) { std::cerr << "Turning on cooler." << std::endl; errorValue = CoolerON(); printError(errorValue, "Error turning on cooler", &errorFlag, ANDOR_ERROR); } } else if (i == 1) { std::cerr << "Cooler is on." << std::endl; //if it's on and it's supposed to be off, turn it off if (coolerStat == ANDOR_OFF) { errorValue = CoolerOFF(); printError(errorValue, "Error turning off cooler", &errorFlag, ANDOR_ERROR); } else { errorValue = GetTemperature(&i); switch(errorValue){ case DRV_TEMP_STABILIZED: std::cerr << "Cooler temp has stabilized at " << i << " deg C" << std::endl; break; case DRV_TEMP_NOT_REACHED: std::cerr << "Cooler temp is " << i << " deg C" << std::endl; std::cerr << "Cooler setpoint has not been reached." << std::endl; std::cerr << "This may be because water cooling is required for setpoints < -58 deg C" << std::endl; std::cerr << "Either wait or try resetting cooler setpoint" << std::endl; break; case DRV_TEMP_DRIFT: std::cerr << "Cooler temp is " << i << " deg C" << std::endl; std::cerr << "Cooler temperature has drifted. Try resetting setpoint" << std::endl; break; case DRV_TEMP_NOT_STABILIZED: std::cerr << "Cooler temp is " << i << " deg C" << std::endl; std::cerr << "Temperature has been reached, but cooler has not stabilized" << std::endl; std::cerr << "Either wait or try resetting cooler setpoint" << std::endl; break; default: std::cerr << "Unrecognized error sequence. Camera may be off or acquiring" << std::endl; break; } } } if(!errorFlag){ std::cerr << "Cooler temperature set to: " << coolerSetpt << std::endl; } } errorValue = SetSpool(0,0,NULL,10); //Disable spooling printError(errorValue, "Spool mode error", &errorFlag, ANDOR_ERROR); // Returns the value from PostQuitMessage return errorFlag; }