Specific example of a way to break out of a while loop using non-blocking I/O

Hi,

I currently have a macro that allows me to draw 4 2d histograms and make cuts out of them. The neat thing is that once a cut is made on the first histogram, the second histogram is updated with the first cut applied, which I then make a cut out of, and these two cuts are then applied to the third histogram, and so on. Once I have all 4 cuts, I then make a 1d histogram. Like follows:

    for (int i = 0; i < numOfCuts; i++) {
        pad1->cd();
        tree->Draw("a:b", "", "colz");
        gPad->Modified();
        gPad->Update();
        gPad->WaitPrimitive();
        TCutG* Cut1 = (TCutG*)gROOT->GetListOfSpecials()->FindObject("CUTG");
        TString cutName1 = "abcut";
        Cut1->SetName(cutName1);
        for (int j = 0; j < numOfCuts; j++) {
            if (j == i) continue;
            pad2->cd();
            tree->Draw("e:b", cutName1, "colz");
            gPad->Modified();
            gPad->Update();
            gPad->WaitPrimitive();
            TCutG* Cut2 = (TCutG*)gROOT->GetListOfSpecials()->FindObject("CUTG");
            TString cutName2 = "ebcut";
            Cut2->SetName(cutName2);
            for (int k = 0; k < numOfCuts; k++) {
                if (k == j || k == i) continue;
                pad3->cd();
                tree->Draw("e:a", cutName1 + " && " + cutName2, "colz");
                gPad->Modified();
                gPad->Update();
                gPad->WaitPrimitive();
                TCutG* Cut3 = (TCutG*)gROOT->GetListOfSpecials()->FindObject("CUTG");
                TString cutName3 = "eacut";
                Cut3->SetName(cutName3);
                for (int l = 0; l < numOfCuts; l++) {
                    if (l == k || l == j || l == i) continue;
                    pad4->cd();
                    tree->Draw("c:d", cutName1 + " && " + cutName2 + " && " + cutName3, "colz");
                    gPad->Modified();
                    gPad->Update();
                    gPad->WaitPrimitive();
                    TCutG* Cut4 = (TCutG*)gROOT->GetListOfSpecials()->FindObject("CUTG");
                    TString cutName4 = "cdcut";
                    Cut4->SetName(cutName4);
                    make1dHist(tree, Cut1, Cut2, Cut3, Cut4);
                    pad4->cd(); pad4->Clear();
                }
                pad3->cd(); pad3->Clear();
            }
            pad2->cd(); pad2->Clear();
        }
        pad1->cd(); pad1->Clear();
    }

This is currently working but can be better. At this point, I can only make a cut once, i.e. if a bad cut is made, I cannot adjust it. So, instead of using gPad->Modified(); gPad->Update(); gPad->WaitPrimitive();, is there another way where I can send some sort of signal to the macro letting it know that it’s time to move on?

I have tried using a while loop in place of those three gPad commands and asking for an user input using std::cin, but that doesn’t seem to work as it is a blocking I/O. I have also read some other posts in the past regarding non-blocking I/O ( ROOT Forum → Search → non-blocking), but they don’t seem to have an example of a specific way to break out of a while loop.

I am not sure to fully understand what you are looking for, but I found in my collection of examples something which might give you some ideas:

void wait_tcutg()
{
   TH2F* h1 =new TH2F("h1", "h1", 100, -2, 2, 100, -2, 2);
   for (Int_t i=0; i<1000; i++) {
      Double_t x = gRandom->Gaus();
      Double_t y = gRandom->Gaus();
      h1->Fill(x,y);
   }
   Double_t xmin = h1->GetXaxis()->GetXmin();
   h1->Draw("colz");
   gPad->Modified();      // make sure
   gPad->Update();      // hist is drawn
   Double_t *x;
   Int_t cont = 1;
   Int_t sernr = 0;
   TString new_name;
   do {
      cout << "Please make a TCutG" << endl
      << "Terminate if a point is below xmin: " << xmin << endl;
      TCutG* cutg=(TCutG*)gPad->WaitPrimitive("CUTG","CutG");
      cont = 1;
      if (cutg) {
         cutg->Print();
         x = cutg->GetX();
         for ( Int_t i=0; i< cutg->GetN(); i++ ) {
            if (x[i] < xmin) {
               cont = 0;
               break;
            }
         }
         // make names unique
         if ( cont ) {
            new_name = "mycut_";
            new_name += sernr++;
            cutg->SetName(new_name);
         } else {
            // end
            delete cutg;
         }
      } else {
         cout << "No cut " << endl;
      }
   } while (cont);
   cout << "End" << endl;
}

Thank you for the example, and sorry for the confusion about what I’m trying to do. Essentially, I’m trying to find an alternative for WaitPrimitive(). Right now, WaitPrimitive() only allows me to make a cut and not adjust it, i.e. once I close the cut polygon, the code goes to the next line. I want to be able to make the cut and adjust it afterward if need to. So, is it possible for WaitPrimitive() to wait for some other signal instead? Like can I make a TButton and make WaitPrimitive() responds to only that?

I see, you need to enter a “cut editor” . Surely that is not something you can do with WaitPrimitive(). As you noticed WaitPrimitive is just waiting for some user interaction and when this interaction fulfills some criteria it goes on.
When you have a TGraph on a pad you can move its point interactively. TCutg is a TGraph, so you can move the cut points the same way, but that will be outside of your loop. I do not see any way to interrupt your loop, let you modify the cut, and then go back into your loop. Sorry.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.