Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gvolume design #5

Open
maureeungaro opened this issue Aug 16, 2017 · 13 comments
Open

gvolume design #5

maureeungaro opened this issue Aug 16, 2017 · 13 comments
Labels

Comments

@maureeungaro
Copy link
Contributor

Hello Mauri,

Good to get started on this right away.

OK to start with the GVolume class, since that is needed for everything else. I think this is actually not quite a trivial class. This class is actually very important, because this is where you will have most of your interaction when defining your geometry. It thus needs to have all the “bells and whistles” to make such an interaction as flexible as possible.

Here is my philosophy on such an object:

Since the object is essentially a “container” for information (in this case the geometry information), it should behave like one, i.e. the following constructs should work.
gvolume[‘pos’] should return the 3 vector for position and the associated dimensions in 2 lists (or tuples).
gvolume.get(‘pos’) does the same.
gvolume.set(‘pos’,’1mm 2.cm 1.3inch’) # This means we DO need string/unit parsing and conversion.
gvolume.set([1.,2.,1.3],([“mm”,”cm”,”inch”]) # this should do the same, so we use overloading.
gvolume[‘pos’] = ([1.,2.,1.3],([“mm”,”cm”,”inch”]) # This we may need to look at. I don’t know if = can be overloaded.
It also needs to be possible to create the object from a simple string, or from a set of arguments:
gvolume(“name | mother | description | '’1
mm 2.cm 1.3inch’ | …..)
gvolume(name=“name”,mother=“mother”,description=“This is a volume”,pos = ’1*mm 2.cm 1.3inch’, ….)
Again, items like “pos”, and “dims” need to be flexible in how you define them, so it can also be pos=[1.,2.,1.3],pos_units=[“mm”,”cm”,”inch”]
The object must know how to present itself for inspection.
Define the str() method, so you can print the object and see what it contains. The output of this string can either be the GEMC txt format, or something more verbose.
The class uses the correct formatting so that Python help(gvolume) gives very useful and meaningful output.
More pedantic documentation is written in a Python notebook, which GitHub is happy to render for you to pdf if you don’t have Jupyter installed.

My current implementation has some, but not all of this. I also had the class itself know how to translate to different formats (i.e. it had a write_sql() to put out an SQL string), which I think in our rewrite we could leave to a separate library, i.e. a MySQL input/output class.

As you can see, I think this class does need to ability to convert units. You would want to store the data in consistent units (whatever is the Gemc standard), but you may want to input an object using inches. Translations between the standard length units and angle units are not complicated, and I have already implemented something we can adapt.

I don’t see how you want incorporate CLHEP into this project. Do you mean to use Geant4Py? (http://geant4.web.cern.ch/geant4/UserDocumentation/UsersGuides/ForApplicationDeveloper/BackupVersions/V9.3/html/apas08.html)
I have not used this, but it could be useful for this project. Using this we can replace all of Gemc with Python :-)

I would prefer to keep the core library as free of non standard Python as possible. For instance, the ROOT code should only be in the ROOT module, so that if ROOT is not installed, everything else is still fully functional. We can argue whether Numpy or Scipy are sufficiently standard, but I would hesitate having a CLHEP or G4 Python binding as a pre-requirement for all this to work.

Note: How do we move this discussion to GitHub so it is archived? Is the current correct location for this project gemc/api/python?

Best,
Maurik

@maureeungaro
Copy link
Contributor Author

maureeungaro commented Aug 16, 2017

Hi Maurik,

The text file has a string for position. It can be:

"1*mm 2.*cm 1.3*inch "

With an arbitrary number of spaces between the numbers. This is passed directly to clhep, no need for a standard.

Also, why not have just ONE call to set the position? This way is simpler, standard, and we do not need to write or maintain alternatives.

I thiink that

gvolume.setPosition("1*mm 2.*cm 1.3*inch ")

is intuitive enough to be "the way".

I like the idea that the object must know how to present itself for inspection. We should definitely do that.

@mholtrop
Copy link
Collaborator

mholtrop commented Aug 16, 2017 via email

@maureeungaro
Copy link
Contributor Author

Hi Maurik,

I see your point. No plan to incorporate CLHEP, my argument assumed that we only need to pass strings. I do see the advantage in using numbers as well.

However I do not like much:

gvolume.set([1.,2.,1.3],([“mm”,”cm”,”inch”])   

But it may be unavoidable? Let's think about this a bit more. I would prefer using your unit scheme and perhaps having the functions handle it, very similar to what you were doing.

So

x,y,z = function_calculates_xyz()

already contains units and one could do something like:

gvolume.setPosition(x,y,z)

where x,y,z already have the units in them.

@mholtrop
Copy link
Collaborator

mholtrop commented Aug 16, 2017 via email

@jsgeorge68
Copy link
Contributor

Hi!
I'm at the airport so was replying to the email but realized I can actually see this thread on my phone. What do you know. For what it's worth, here's what I sent by email. I think it's actually what you guys just said.

Jeff

Hi everyone,

I'm probably misunderstanding so feel free to straighten me out :)

I am wondering why the API needs to understand the geometry representation at all. It seems to me that the purpose of the API is to accept some kind of geometry definition from the user through some python statements and then present that definition to gemc in one ic several convenient formats. The API doesn't have to know what a cm is as long as it can tell gemc (or ROOT or whatever) what it needs to know so IT understands what the user intended.

All the API needs to do is to check that it has a valid input. For position, there need to be three valid numbers and three valid units stored in the gVolume container. Maurik's dictionary would do fine to ensure the unit string is something we've heard of. Beyond that I think we leave it to the output generator to present the geometry in the way that its consumer wants. If we start translating everything to a common system within the API then we get to where a user can't recognize their own geometry files because the API has cleverly translated everything to some other system.

Also, the container in the API never interacts with anything outside the class directly. So the input can be a single string format for simplicity as Mauri suggested but we can easily add cases to parse variations (like giving one unit for the whole vector) if we decide they are useful. Likewise the format for storing in the container is purely a matter of convenience as no outside consumer will ever see it except through the class output methods that can present it however is needed. Storing numerical values and unit strings makes sense to me but it hardly matters.

I guess I'm just trying to say that the container isn't storing a geometry representation. It's storing a set of labels that tell something else how to represent the geometry by way of the output methods.

Ok, tell me if I went off the rails. :) this is fun to think about, especially with all of you who actually know what you're talking about.

@maureeungaro
Copy link
Contributor Author

Hi Jeff, Maurik,

Writing email until Seamus and Jeff join the team on github (will copy this there to save it).

My original idea was too much "perl-like", i.e. "just fill tables of string". Although that is working well in perl, it is a bit shortsighted in that it cannot take advantage of the power of python.

In clas12 sometimes we had to use ROOT to make calculations and "prepare" some variables, then use them in the perl scripts. This could be done within python directly. For example, "pos" could be a 3-vector object and it could be passed to setPosition. Within the script functions could be used to handle pos and rotations instead of having to parse the infos from string, make calculations, then parse it back into a string to be accepted by gvolume.

Example:

A detector has a "rot". We want to make a copy of it around phi. One would just have to do rot.rotateZ(deltaPhi) instead of parsing rot, getting the number, and produce a new "rot" string.

As Jeff suggested, perhaps the "gvolume" class shouldn't know about this. It is not a geometry representation and in the end it just writes strings. It could still handle the various setPosition(string), setPosition(vector) etc. And the units mechanism could be done outside of gvolume.

Mauri

@maureeungaro
Copy link
Contributor Author

Hi all,

Sorry, but I think I fundamentally disagree. If you want to “just store a bunch of strings”, then you don’t need any of this and you just use a list or dict. I do think that we are storing a geometry object in gvolume. If not, what are we storing there?

Mauri has a good example with the rotation, which is why I started using Python instead of the Perl interface. I needed complicated rotations to optimally pack a collection of trapezoids with a fixed, very small, amount of space in between. This sounds like a simple problem, but actually it is not and the rotations required quickly drove me nuts. I needed rotation classes to get this done, and wanted everything is a single script. Perl just could not do this.

If the gvolume class knows what it is that it stores, then you can verify that the data makes sense. Otherwise you will be depending on something else to decide if the data is correct, but why spit these two?

Also, if you want to output to something other than text tables, say you want to render the results using Blender (has a full Python API, so, yes, we should consider that!), you will need to do all sorts of conversions. So then, why would you write the code so that these conversions are done in the Blender output, and again in the ROOT output, and again in the GDML output, and …. Makes no sense to me. The object itself “knows" it is a geometry and “knows" to present its data in a sensible way to either the user or whatever we use as an output. We can argue what a “sensible way” is, but I am not so convinced that the string format is a universal sensible way to represent a geometry object. That is why I suggest we have other input and output representations. I think I am arguing for a fairly standard OOP design, where you do not care (as Jeff points out) how the data is stored internally in the object, but you have all the convenient tools at hand to put the data there and extract it again, in formats that are appropriate for what you are trying to do.

If all you are interested in doing is store strings and then extract strings, I don’t think this project makes sense, at least not for me. To me this project is more about the transformations of geometry representations than the storing of a single geometry representation.

Best,
Maurik

@maureeungaro
Copy link
Contributor Author

Everyone is on the team so we can continue the discussion on github.

Maurik brings up two issues:

  1. gvolume itself “knows" it is a geometry
    2 gvolume to present its data in a sensible way

My thoughts:

  1. other than some internal validation, this means for example to have "position" not to be a string, but a vector, and "rotation" as well. I agree. In fact this could be extended to other descriptor, like "color".

  2. not sure about this. I was thinking of a separate class "gfactory" that knows what a gvolume is, and have an abstract method "write()" that is derived by various factories (ROOT, Json, mysql, etc). The class would have with a vector or a map of gvolumes. This would allow the gvolume and gfactory to be simple and specialized.

Maurik, any particular reason why you prefer gvolume to know how to write a specific object? The output objects do not have much to do with gvolume itself.

@mholtrop
Copy link
Collaborator

mholtrop commented Aug 16, 2017 via email

@maureeungaro
Copy link
Contributor Author

maureeungaro commented Aug 17, 2017

Hi Maurik,

Yes we agree on the introspection.

Here's a general idea I propose for the gfactory. I will use c++ language cause I do not know python enough, but looks like python can do all this (this won't compile, it is just for illustration).

class gfactory {

private:
 vector<gvolume>  gvolumes
 
 map<string, writer> write

public:

 constructor:  gfactory(string outputType) {
 initializeWriters() < fills map, e.g. write["ROOT"], write["JSON"] etc 
 loadGVolumes()
 write[outputType]->write() < will write the whole gvolumes in the appropriate format
}

addGVolume(gvolume thisV) {gvolumes.push_back(thisV)}

 virtual loadGVolumes() < derived and filled by users, see below   
}

All that may be behind the scenes, in a "main" hidden from the user, where the gfactory is instantiated. Users will write the loadGVolumes(), which may look like:

loadGVolumes() {
 gvolume thisVolume1(name1, mother1) < lets make a nice constructor
 thisVolume1.setPosition(x,y,z)
 addGVolume(thisVolume1)

 gvolume thisVolume2(name2, mother2) 
 thisVolume2.setPosition(x',y',z')
 addGVolume(thisVolume2) 

 moreComplicatedRoutine1()
 moreComplicatedRoutine2()

}

the outputType can be passed by command line.
materials, mirrors, optical properties would be members of gfactory as well in the same fashion. If a user is not interested in the mirrors for example, it can skip that implementation and the virtual base class method will be used instead.

Of course a lot of details may have to be ironed out ;-)

@mholtrop
Copy link
Collaborator

mholtrop commented Aug 17, 2017 via email

@maureeungaro
Copy link
Contributor Author

Hi Maurik,

A small example should answer most of these questions, let me try set it up on a new branch, it may take some time as another project will now require my immediate attention in the next couple of weeks.

Regarding the name, the api is mostly but not all about "geometry". There are materials, information relative to hit definition and sensitivity, optical properties and mirror. In the gemc code all this is called "gSystem", but that name seems not enough descriptive for a python module.

Other ideas (I don't particularly like any of these)

gemcDetector
gemcSystem
pyGemcDetector
pyGSystem

Best,

Mauri

@mholtrop
Copy link
Collaborator

mholtrop commented Aug 17, 2017 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants