Skip to content

Improve geo classes#1527

Merged
karabowi merged 5 commits intoFairRootGroup:devfrom
fuhlig1:improve_geo_classes
May 6, 2024
Merged

Improve geo classes#1527
karabowi merged 5 commits intoFairRootGroup:devfrom
fuhlig1:improve_geo_classes

Conversation

@fuhlig1
Copy link
Member

@fuhlig1 fuhlig1 commented Apr 25, 2024

Improve the Geo classes in the example directory.
Move duplicate code into the base class FairGeoSet.
In the constructors use setter functions instead to access data members of the base classes directly.
Use fmt library for name generation and parsing to get rid of sprintf.
Add and improve unit tests for these classes,


Checklist:

Summary by CodeRabbit

  • New Features

    • Introduced enhanced naming and module setting mechanisms across various geometry classes, improving clarity and consistency.
    • Added new testing capabilities for Rutherford geometry settings.
  • Bug Fixes

    • Removed redundant and obsolete methods and variables from multiple classes, streamlining geometry handling.
  • Documentation

    • Updated copyright years and removed outdated comments across several files.
  • Refactor

    • Consolidated functionality of methods into constructors for better initialization in geometry classes.
    • Updated and streamlined geometry handling by replacing direct assignments with method calls.
  • Chores

    • Cleaned up CMake files to better manage dependencies and conditions for building examples.

@coderabbitai
Copy link

coderabbitai bot commented Apr 25, 2024

Walkthrough

Walkthrough

This update streamlines geometry management in various simulation classes by standardizing the setting of names and module counts through dedicated methods. It removes outdated methods and variables, enhancing code clarity and maintainability. The changes also include updates to the build system to accommodate these modifications and introduce new tests to ensure consistency in geometry naming conventions.

Changes

Files Changes
CMakeLists.txt, tests/examples/CMakeLists.txt, tests/examples/simulation/rutherford/CMakeLists.txt Updated build configurations and added new test suites.
.../src/PixelGeo.cxx, .../src/FairTestDetectorGeo.cxx, .../src/FairTutPropGeo.cxx, .../src/FairTutorialDet1Geo.cxx, .../src/FairTutorialDet2Geo.cxx, .../src/FairTutorialDet4Geo.cxx, .../src/FairRutherfordGeo.cxx Constructors modified to use SetName and setMaxModules. Removed getModuleName and getEleName.
.../src/PixelGeo.h, .../src/FairTestDetectorGeo.h, .../src/FairTutPropGeo.h, .../src/FairTutorialDet1Geo.h, .../src/FairTutorialDet2Geo.h, .../src/FairTutorialDet4Geo.h, .../src/FairRutherfordGeo.h Removed obsolete declarations and methods. Updated copyright years.
fairroot/geobase/FairGeoSet.cxx, fairroot/geobase/FairGeoSet.h Introduced new methods and member variables for improved module management and string formatting.
examples/common/geometry/target_rutherford.geo Renamed geometry entity from "targ" to "target1".
tests/geobase/checks_FairGeoSet.h Modified test generation logic for improved test coverage.

This table summarizes the key files affected by the update, highlighting the nature of the changes and their impact on the project structure and functionality.


Recent Review Details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits Files that changed from the base of the PR and between d0891a5 and 85f4ec3.
Files selected for processing (22)
  • CMakeLists.txt (2 hunks)
  • examples/MQ/pixelDetector/src/PixelGeo.cxx (1 hunks)
  • examples/MQ/pixelDetector/src/PixelGeo.h (2 hunks)
  • examples/advanced/Tutorial3/simulation/FairTestDetectorGeo.cxx (1 hunks)
  • examples/advanced/Tutorial3/simulation/FairTestDetectorGeo.h (2 hunks)
  • examples/advanced/propagator/src/FairTutPropGeo.cxx (1 hunks)
  • examples/advanced/propagator/src/FairTutPropGeo.h (2 hunks)
  • examples/common/geometry/target_rutherford.geo (1 hunks)
  • examples/simulation/Tutorial1/src/FairTutorialDet1Geo.cxx (1 hunks)
  • examples/simulation/Tutorial1/src/FairTutorialDet1Geo.h (2 hunks)
  • examples/simulation/Tutorial2/src/FairTutorialDet2Geo.cxx (1 hunks)
  • examples/simulation/Tutorial2/src/FairTutorialDet2Geo.h (2 hunks)
  • examples/simulation/Tutorial4/src/mc/FairTutorialDet4Geo.cxx (1 hunks)
  • examples/simulation/Tutorial4/src/mc/FairTutorialDet4Geo.h (2 hunks)
  • examples/simulation/rutherford/src/FairRutherfordGeo.cxx (1 hunks)
  • examples/simulation/rutherford/src/FairRutherfordGeo.h (2 hunks)
  • fairroot/geobase/FairGeoSet.cxx (3 hunks)
  • fairroot/geobase/FairGeoSet.h (4 hunks)
  • tests/examples/CMakeLists.txt (1 hunks)
  • tests/examples/simulation/rutherford/CMakeLists.txt (1 hunks)
  • tests/examples/simulation/rutherford/test_FairRutherfordGeo.cxx (1 hunks)
  • tests/geobase/checks_FairGeoSet.h (3 hunks)
Files skipped from review due to trivial changes (1)
  • examples/common/geometry/target_rutherford.geo
Files skipped from review as they are similar to previous changes (21)
  • CMakeLists.txt
  • examples/MQ/pixelDetector/src/PixelGeo.cxx
  • examples/MQ/pixelDetector/src/PixelGeo.h
  • examples/advanced/Tutorial3/simulation/FairTestDetectorGeo.cxx
  • examples/advanced/Tutorial3/simulation/FairTestDetectorGeo.h
  • examples/advanced/propagator/src/FairTutPropGeo.cxx
  • examples/advanced/propagator/src/FairTutPropGeo.h
  • examples/simulation/Tutorial1/src/FairTutorialDet1Geo.cxx
  • examples/simulation/Tutorial1/src/FairTutorialDet1Geo.h
  • examples/simulation/Tutorial2/src/FairTutorialDet2Geo.cxx
  • examples/simulation/Tutorial2/src/FairTutorialDet2Geo.h
  • examples/simulation/Tutorial4/src/mc/FairTutorialDet4Geo.cxx
  • examples/simulation/Tutorial4/src/mc/FairTutorialDet4Geo.h
  • examples/simulation/rutherford/src/FairRutherfordGeo.cxx
  • examples/simulation/rutherford/src/FairRutherfordGeo.h
  • fairroot/geobase/FairGeoSet.cxx
  • fairroot/geobase/FairGeoSet.h
  • tests/examples/CMakeLists.txt
  • tests/examples/simulation/rutherford/CMakeLists.txt
  • tests/examples/simulation/rutherford/test_FairRutherfordGeo.cxx
  • tests/geobase/checks_FairGeoSet.h

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Out of diff range and nitpick comments (1)
fairroot/geobase/FairGeoSet.cxx (1)

2-2: Update the copyright year to reflect the current year.

Consider updating the copyright year to reflect the current year if this file has been modified during the current year.

@fuhlig1 fuhlig1 force-pushed the improve_geo_classes branch from b3d639c to 37b74ed Compare April 25, 2024 11:32
@fuhlig1
Copy link
Member Author

fuhlig1 commented Apr 25, 2024

@coderabbitai generate unit testing code for examples/MQ/pixelDetector/src/PixelGeo.cxx and examples/MQ/pixelDetector/src/PixelGeo.h

@coderabbitai
Copy link

coderabbitai bot commented Apr 25, 2024

Tip

For best results, initiate chat on the files or code changes.

@fuhlig1, here is the unit testing code for PixelGeo.cxx and PixelGeo.h using Google Test. This test suite checks the correct initialization of the PixelGeo object, ensuring that the name and maximum modules are set as expected in the constructor.

#include <gtest/gtest.h>
#include "PixelGeo.h"

class PixelGeoTest : public ::testing::Test {
protected:
    PixelGeo* pixelGeo;

    void SetUp() override {
        pixelGeo = new PixelGeo();
    }

    void TearDown() override {
        delete pixelGeo;
    }
};

TEST_F(PixelGeoTest, ConstructorTest) {
    EXPECT_EQ(pixelGeo->GetName(), "Pixel");
    EXPECT_EQ(pixelGeo->GetMaxModules(), 10);
}

This test suite includes:

  • A test fixture class PixelGeoTest that creates an instance of PixelGeo before each test and cleans up afterward.
  • A test ConstructorTest that checks if the PixelGeo object is initialized with the correct name and maximum modules.

Make sure to include Google Test in your project to compile and run this test. If you need further assistance or additional tests, feel free to ask!

Analysis chain
Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Fetch the contents of PixelGeo.cxx and PixelGeo.h
cat examples/MQ/pixelDetector/src/PixelGeo.cxx
cat examples/MQ/pixelDetector/src/PixelGeo.h

Length of output: 1811

@fuhlig1
Copy link
Member Author

fuhlig1 commented Apr 25, 2024

@coderabbitai, generate unit testing code for examples/MQ/pixelDetector/src/PixelGeo.cxx and examples/MQ/pixelDetector/src/PixelGeo.h. Take also the base class fairroot/geobase/FairGeoSet.cxx and fairroot/geobase/FairGeoSet.h into account

@coderabbitai
Copy link

coderabbitai bot commented Apr 25, 2024

Tip

For best results, initiate chat on the files or code changes.

@fuhlig1, based on the provided source code for PixelGeo and FairGeoSet, I have generated a more comprehensive unit testing code that includes tests for both the derived class PixelGeo and the base class FairGeoSet. This will help ensure that the integration and inheritance aspects are correctly handled.

Here's the unit testing code using Google Test:

#include <gtest/gtest.h>
#include "PixelGeo.h"
#include "FairGeoSet.h"

class PixelGeoTest : public ::testing::Test {
protected:
    PixelGeo* pixelGeo;
    FairGeoSet* fairGeoSet;

    void SetUp() override {
        pixelGeo = new PixelGeo();
        fairGeoSet = pixelGeo;  // Upcast to base class to test base class functionality
    }

    void TearDown() override {
        delete pixelGeo;
    }
};

TEST_F(PixelGeoTest, ConstructorTest) {
    // Test the constructor of PixelGeo
    EXPECT_EQ(pixelGeo->GetName(), "Pixel");
    EXPECT_EQ(pixelGeo->GetMaxModules(), 10);
}

TEST_F(PixelGeoTest, BaseClassConstructorTest) {
    // Test the constructor of the base class FairGeoSet via PixelGeo
    EXPECT_EQ(fairGeoSet->GetMaxModules(), 10);  // Assuming GetMaxModules is a public method in FairGeoSet
}

TEST_F(PixelGeoTest, ModuleManagement) {
    // Test module management functions if applicable
    int modules[10] = {1, 0, 1, 0, 1, 0, 1, 0, 1, 0};
    fairGeoSet->setModules(-1, modules);
    int* retrievedModules = fairGeoSet->getModules();
    for (int i = 0; i < 10; ++i) {
        EXPECT_EQ(retrievedModules[i], modules[i]);
    }
}

// Additional tests can be added here to cover more functionalities

This test suite includes:

  • A test fixture class PixelGeoTest that creates an instance of PixelGeo and uses it to test both the derived and base class functionalities.
  • A constructor test for PixelGeo to ensure it initializes with the correct name and maximum modules.
  • A base class constructor test to verify that the base class part of PixelGeo is initialized correctly.
  • A module management test to check the functionality of setting and getting module configurations, assuming such methods are publicly accessible and part of the FairGeoSet interface.

Make sure to include Google Test in your project to compile and run these tests. If you need further assistance or additional tests, feel free to ask!

Analysis chain
Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Fetch the contents of PixelGeo.cxx, PixelGeo.h, FairGeoSet.cxx, and FairGeoSet.h
cat examples/MQ/pixelDetector/src/PixelGeo.cxx
cat examples/MQ/pixelDetector/src/PixelGeo.h
cat fairroot/geobase/FairGeoSet.cxx
cat fairroot/geobase/FairGeoSet.h

Length of output: 23325

Copy link
Member

@dennisklein dennisklein left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general 👍, I put a few comments inline.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something went wrong with the whitespace in this file?

{
// construct TString starting after the end of the detector name
// which contains the detector number
TString modNumber(name(fName.Length(), (name.Length() - fName.Length())));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
TString modNumber(name(fName.Length(), (name.Length() - fName.Length())));
assert(name.Length() > fName.Length());
TString modNumber(name(fName.Length(), (name.Length() - fName.Length())));

Makes it a bit more readable IMHO, as this is really the assumption you are making, right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

// construct TString starting after the end of the detector name
// which contains the detector number
TString modNumber(name(fName.Length(), (name.Length() - fName.Length())));
return (modNumber.Atoi() - 1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this always work? e.g. if fName == "blubb" and name == "blubbXXX" or name == "asdf15", let's add test coverage?

Perhaps this function should also check that the prefixes are equal? Otherwise, if fName == "blubb", getModNumInMod("asdfg42") will work, but should it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ASCII files defining the detector geometry need to implement it the way that all elements in the file start with fName followed by a number. I will add code to check this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added two checks which confirm the consistency of the input.

Comment on lines +93 to +95
virtual const char* getModuleName(Int_t);
virtual const char* getEleName(Int_t);
Copy link
Member

@dennisklein dennisklein Apr 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, thinking more about those functions: I think we should go one step further and change the return type and return a string (by-value). Returning a const char * is really dangerous, because those functions look like ordinary getters (edit: Perhaps not getters, what I mean is, they don't make me expect to depend on each other): all results of a previous call become dangling pointers as soon as the next call happens.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about the same but unfortunately these functions are public and definitely used in user code so we can't change it without breaking the user code.
Is it possible to implement a second function which only has a different return type? If so we can deprecate the old function and internally use the new one.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that would be the better approach for a smoother transition.

Copy link
Member

@ChristianTackeGSI ChristianTackeGSI Apr 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably should start by seperating the interfaces that should be called and that should be overriden (there's some cool "pattern" name for this, I have forgotten it).

We should deprecate getModuleName so that people stop calling it.

And here's an idea for the "to be called" method.

std::string CallGetModuleName(Int_t x)
{
    // getModuleName usually is not thread safe!
    static std::mutex mtx;
    std::lock_guard lock{mtx};

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
    return {getModuleName(x)};
#pragma GCC diagnostic pop
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea but we should try to get this PR merged and create issues with the still open problems/suggestions.
We should now focus on getting the warnings fixed such that we can create the new FairRoot release.

@fuhlig1 fuhlig1 force-pushed the improve_geo_classes branch from 37b74ed to 9e8d932 Compare April 26, 2024 11:46
Comment on lines +116 to +117
std::string modNameSet{""}; //! name of module
std::string eleNameSet{""}; //! substring for elements in module
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can these be renamed fModNameSet and fEleNameSet?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@fuhlig1 fuhlig1 force-pushed the improve_geo_classes branch from 9e8d932 to 41dc0cd Compare April 26, 2024 13:04
karabowi
karabowi previously approved these changes Apr 26, 2024
const char* getGeomFile() { return geoFile.Data(); }
Int_t getMaxSectors(void) { return maxSectors; }
Int_t getMaxModules(void) { return maxModules; }
void setMaxModules(Int_t _maxMods) { maxModules = _maxMods; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, the general naming convention was about CamelCase, right?

Please let's at least use it for new APIs?

Suggested change
void setMaxModules(Int_t _maxMods) { maxModules = _maxMods; }
void SetMaxModules(Int_t _maxMods) { maxModules = _maxMods; }

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. I kept the old convention for the geobase area since this was inherited from Hades. I agree that we should change this but I would like to do it in a second step. There are many more issues with this class which I would like to fix.
The main intention of this PR was to get rid of the sprintf usage. I would like to limit the scope of this PR to this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fully understand this!

I just think, it will be more work in the future, if you introduce more names with the wrong naming convention (we have to deprecate it in the renaming phase, etc.)

Anyway: Your decision. This is not super important to me.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I "unresolve" this for another point:

Some of the inner workings of FairGeoSet (especially the usage of the modules member variable) depend on maxModules not changing during operation. Providing a simple setter like this suggests that changing maxModules at any time is allowed.

Either this method should check that modules is not already allocated.

Or (preferred) this method should not exist at all and the maxmodules parameter should be part of the ctor.

If you don't want to go the ctor route in this PR, then maybe leave out the complete maxModules part at all and move it to another PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW: The same is probably true for maxSectors?

SECTION("name generation")
{
const Int_t index = GENERATE(0, 1, 99);
auto index = GENERATE(take(100, random(1, 1000)));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const auto does not work?

fuhlig1 added 5 commits May 3, 2024 16:58
Remove usage of char* with std::string. Since the API requests to return a
char* this information is extracted from the string.
Add checks to confirm the correctness of the input.
Add a accessor to set the maximum number of modules.
The generation and parsing of the names uses the fmt library such that this
dependency has to be added to the build system.
Instead of 3 hardcoded values use 100 random values in the range from 1 to
10000 to thest name generation and extraction in FairGeoSet and derived
classes.
Currently the tests of the example code fails since the code has an error with
numbers which have mor than one digit. The correct code is already in the base
class but currently shadowed by code in the example classes.
The functionality to generate and parse names is now available from the base
class FairGeoSet. Use the base class implementation.
Use functions in the constructor to initilaize data members instead of
accessing the data members of the parent class directly. This will allow to
make these data private in future.
The volume name violates the naming conventions. The problem only was found
due to the newly added unit tests.
@fuhlig1 fuhlig1 force-pushed the improve_geo_classes branch from bedee49 to 85f4ec3 Compare May 3, 2024 15:08
@karabowi karabowi merged commit c230328 into FairRootGroup:dev May 6, 2024
@karabowi
Copy link
Collaborator

karabowi commented May 6, 2024

We will address the requested changes for v19.2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants