Page MenuHomeHEPForge

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
This document is not UTF8. It was detected as ISO-8859-1 (Latin 1) and converted to UTF8 for display.
Index: branches/spherical/ChangeLog
===================================================================
--- branches/spherical/ChangeLog (revision 241)
+++ branches/spherical/ChangeLog (revision 242)
@@ -1,919 +1,947 @@
+2008-07-02 Gregory Soyez <gsoyez@quark.phy.bnl.gov>
+
+ * started the process of merging the spherical version of SISCone
+ into the main trunk. The new version will be inserted in the
+ "siscone/spherical" directory. We shall put it under the
+ 'siscone_spherical' namespace and rename the relevant classes
+ using a 'CSph' prefic instead of the 'C' prefix used in the main
+ trunk.
+ Steps to be done: (. = todo, - = done)
+ - move the relevant files in a 'siscone/spherical' directory
+ . change the namespace
+ . rename the classes and update the names in the code
+ . in the examples, move the main example into a 'spherical' one
+ . add a siscone/Makefile.am in the branch
+ . test on the branch
+ . copy (serical + example) into the main trunk
+ . update the makefiles
+ . test
+
+ Questions:
+ - do we also copy the unchanged files? (It will mess a bit the
+ filenames but they concerns material hidden to the end-user,
+ so I'd keep them in the trunk
+ It concerns circulator, reference, ranlux and siscone_error.
+ - do we remove the quadtree? (I'd say 'yes')
+ - keep the "unused" files in the branch? (area, quadtree, ...)
+
+
2008-06-16 Gregory Soyez <gsoyez@quark.phy.bnl.gov>
- * siscone/vicinity.cpp (siscone): revised the normalisation
- of the cocirsumar range.
+ * siscone/vicinity.cpp (siscone): revised the normalisation of the
+ cocircular range.
* siscone/split_merge.cpp (siscone): recomputed the norm of
the result of a collinear merging. This is required as
the norm is used in stable-cone search and not recomputed
automatically.
* siscone/protocones.cpp (siscone): normalised directions
used to determine the angles. This might well be the reason
of the co-circular problem.
* siscone/geom_2d.cpp (siscone): removed an unused variable
2008-06-14 Gregory Soyez <gsoyez@quark.phy.bnl.gov>
* Note: this version passed 10000 basic safety tests.
* siscone/vicinity.cpp (siscone): added cocirc-tests
WARNING: this is a naive adaptation from the cylindrical case.
* siscone/momentum.h (siscone): reverted most of the last
modification: since the simple computation using a cos()
requires the computation of the norm (not its squared because
the sign of the cos matters) it is most complicated than the one
with the tangent. Note that we're free of the problem mentionned
below as the only place where it can happen is in the
computation of the vicinity and there we compute distances
internally rather than calling is_closer.
Finally, we've added a is_closer_safe with the computation
using te cosine.
2008-06-13 Gregory Soyez <gsoyez@quark.phy.bnl.gov>
* siscone/vicinity.cpp (siscone):
pre-added co-circularity management
* siscone/momentum.h (siscone):
replaced the tangent used in distances comparison by
a cosine (the tangent is more precise at small R but
we'll probably never get down to that small values of R).
The reason for the replacement is that it gives wrong
results for vicinity computation for 2R>pi/2.
This present computation is also faster (no x-product).
All calls to that function have been updated too.
2008-06-12 Gregory Soyez <gsoyez@quark.phy.bnl.gov>
* Description: this is the first complete adaptation to the
SISCone jet-search using spherical coordinatee.
This branch is motivated by potential applications to
cosmic-rays and follows a request by Yvonne Küssel
<Yvonne.Kuessel@gmx.de>
* Summary of modifications:
- use the distance on a sphere instead of the eta-phi one This
is the most important change and comes with
modifications... well... ... everywhere. Most of the infos
about the distance are in the momentum.{h,cpp} files. There
are other important pieces when computing the candidate
centres (in vicinity.cpp). And the theta_phi range (previously
eta_phi!) in geom2d.cpp has also been relooked.
- The spit--merge(SM) uses the energy instead of pttilde by
default for the ordering
- The final jets ae ordered in E instead of pt.
- we don't remove particles with infinite rapidity (both in SC
search and SM)
- for the cone consistency tests, we use |px|+|py|+|pz| instead
of |px|+|py|
- we have removed the cut on soft particles in
Csplit_merge::merge_collinear_and_remove_soft() since it was
mainly used for area speed up.
- Csplit_merge::use_pt_weighted_splitting is replaced by
Csplit_merge::use_E_weighted_splitting when it is defined, the
weight is of course 1/E^2 instead of 1/pt^2
- To emphasise the fact that this is not the main SISCone trunk,
we've added one sentence in the header of every file and a
WARNING in the SISCone banner.
* Still to be done
- implement co-circularity (currently the range is set to 0)
- in the split--merge, check the precision of the collinearity
test?
* Other points to think about
- for the split of 2 protojets, we're currently making many
calls to a full distance computation. This can surely be
improved when no weighting is asked...
- completely remove the quadtree?
- remove the area support?
- remove the Ctheta_phi range?
or improve it (the cell initialisation assume a square shape,
not a circle, but already with a square, the geometry is
rather involved)
* Final word: still need a whole bunch of tests (noticeably IRC
safety, speed). Note that the stable-cone search has been
checked "graphically".
2008-05-20 Gregory Soyez <gsoyez@quark.phy.bnl.gov>
* siscone/hash.cpp (siscone):
Adapted the size of the hash to scale like Nn(=N^2R^2) instead
of N^2. This allows to save a fair amount of memory.
2008-05-16 Gregory Soyez <gsoyez@quark.phy.bnl.gov>
* siscone/defines.h
siscone/hash.{h,cpp} (siscone)
siscone/protocones.{h,cpp} (siscone):
siscone/siscone.{h,cpp} (siscone):
add some debug information about the occupancy of the hash
when DEBUG_STABLE_CONES is defined
* examples/test.cpp: update the code to use Csiscone directly
instead of separate calls to stable cone search and split--merge
stage. This should be less confusing for end-users.
2008-05-15 Gregory Soyez <gsoyez@quark.phy.bnl.gov>
* configure.ac:
in the last CXXFLAGS fix, the default has been set at a wrong
place (practically, CXXFLAGS was set to the system default value
-O2 -g and thus not replaced with our local default).
This is fixed now.
2008-03-24 Gregory Soyez <g.soyez@ulg.ac.be>
* configure.ac:
fix CXXFLAGS in such a way as to allow the user to set their own
default.
2008-03-17 Gregory Soyez <g.soyez@ulg.ac.be>
* siscone/defines.h:
siscone/siscone.h/cpp
examples/option.cpp
BUGS:
Because of potentil conflicts with other packages, the
tags defined in config.h are no longer included in
defines.h but only in SISCone source files.
As a practical consequence, the program name and version
number are now accessed through siscone_package_name() and
siscone_version() both defined in siscone.h and inside
the siscone namespace. See examples/options.cpp for
an example.
This solves the corresponding bug reported by Seuster.
2008-03-15 Gavin Salam <salam@lpthe.jussieu.fr>
* BUGS:
added entry related to PACKAGE/VERSION/etc reported by Seuster.
2008-03-12 Gregory Soyez <g.soyez@ulg.ac.be>
* siscone/split_merge.h/cpp (siscone):
This is a non-negligible modification: we have added the
possibility to modify the way particles are split during the
split-merge step.
Assume one has to split protojets 1 and 2. The standard split
associates a common particle j to the closest centre
i.e. compares the distances D_{1j} vs. D_{2j}.
Now, by calling Csplit_merge::set_pt_weighted_splitting(true),
it is possible to perform the splitting according to the anti-kt
distance i.e. comparing D_{1j}/k_{t1} vs. D_{2j}/k_{t2}.
This new option should allow to produce more
rigid (soft-resilient) jets.
Note that the default is to use the standard distance comparison
so backward compatibility is not broken.
2008-03-11 Gregory Soyez <g.soyez@ulg.ac.be>
* siscone/area.cpp (siscone):
the jet+area finding now really returns the number of jets
as does the standard clustering
* siscone/area.cpp (siscone):
don't include ghosts in stable-cone search when only the
passive area is requested.
This is a huge speed improvement as the execution time (when
only passive area is requested) is now (with Ntot = N+Nghosts)
O(N^2 log(N) + Ntot^2)
instead of
O(Ntot^2 log(Ntot) + Ntot^2)
* configure.ac:
switched the main trunk to SISCone-1.4.0-devel
2008-03-07 Gavin SALAM <salam@lpthe.jussieu.fr>
* configure.ac:
switched version to 1.3.1
2008-01-17 Gavin Salam <salam@lpthe.jussieu.fr>
* configure.ac:
switched version number over to 1.3.1-devel
2008-01-15 Gregory Soyez <g.soyez@ulg.ac.be>
* siscone/geom_2d.h (M_PI):
added definition of M_PI if needed (VC compilation)
* siscone/protocones.cpp (siscone):
added the algorithm header (VC compilation)
2007-11-12 Gregory Soyez <g.soyez@ulg.ac.be>
* NEWS & configure.ac:
SISCone 1.3.0
2007-11-10 Gavin Salam <salam@lpthe.jussieu.fr>
* configure.ac:
* examples/Makefile.am:
* examples/events/Makefile.am:
made sure some sample events were included in the dist
2007-11-07 Gavin SALAM <salam@lpthe.jussieu.fr>
* configure.ac:
switched +="" to A=A"" to eliminate an error on mac
2007-10-24 Gregory Soyez <g.soyez@ulg.ac.be>
* examples/options.cpp: fix a missing "siscone/" in header include
* examples/Makefile.am: fix a problem with make distcheck
* configure.ac: the --enable-shared cmd-line option is already
handled by libtool. We just need to add AM_DISABLE_SHARED to
disable the shared lib by default (can still be changed by using
--enable-shared)
Also, we set the minimal version of autoconf to 2.57.
* examples/Makefile.am: do not install anything (just build
examples locally)
* examples/main.cpp (main): print a more specific error message
when the event file cannot be opened
2007-10-03 Gregory Soyez <g.soyez@ulg.ac.be>
* siscone/defines.h: read available information from config.h
* In examples, include headers from the 'siscone' folder
* Move the src folder into a new 'siscone' folder
2007-10-02 Gregory Soyez <g.soyez@ulg.ac.be>
* add configure script for the build process. This comes with a
bunch of new files: autogen.sh, configure.ac, and a Makefile.am
in each directory. See the INSTALL files for more details
* replace each Makefile by makefile.static
Makefile-based build is now made through
make -f makefile.static
* examples/area.cpp: add a sample program for SISCone jet area
computation
2007-06-24 Gregory Soyez <g.soyez@ulg.ac.be>
* src/defines.h: SISCone 1.2.0
2007-06-15 Gregory Soyez <g.soyez@ulg.ac.be>
* src/geom_2d.h/cpp: use a 32x32 eta-phi-plane tiling. The range
is then defined by two binary fields. This allows easy overlap
test and merging. For protojets splitting, the new ranges are
built by adding particles one-by-one.
* src/split_merge.cpp (siscone):
- align code with the modifications in geom_2d.h/cpp
- the output of save_contents has slightly been improved
* src/area.h/cpp: add methods to compute only the active or passive
area
* examples/main.cpp: add pass-by-pass statistics in the verbose
output
* examples/options.cpp: fix bug when passing an unknown long
option to getopt_long
2007-06-02 Gregory Soyez <g.soyez@ulg.ac.be>
* examples/sample.cpp: add a few lines to show how one can browse
the output jets of compute_jets.
* examples/times.cpp: only save runtime using the siscone class
instead of a separate determination.
2007-05-09 Gavin Salam <salam@lpthe.jussieu.fr>
* src/split_merge.cpp:
soft_pt2_cutoff -> stable_cone_soft_pt2_cutoff
fixed infinite loop for non-zero stable_cone_soft_pt2_cutoff
2007-05-09 Gregory Soyez <g.soyez@ulg.ac.be>
* src/split_merge.cpp|h:
When building the list of particles to be passed to stable-cone
search, allow to remove particles below a pt2 threshold
soft_pt2_cutoff.
2007-04-27 Gavin SALAM <salam@lpthe.jussieu.fr>
* src/geom_2d.cpp:
corrected bugs in range_union -- now passes test that 1000
events are identical to what we had previously.
2007-04-26 Gregory Soyez <g.soyez@ulg.ac.be>
* src/split_merge.cpp (siscone): add range support to the
split--merge. When computing overlap, we first check that the
two ranges overlap. In splitting, ranges are set to the parent
ranges. In merging, range is set as the union of the parent
ranges.
* src/split_merge.h: add a range variable to the Cjet class
* src/geom_2d.cpp/h (siscone): add the Ceta_phi_range to handle
covering ranges in the ete-phi plane. This goes with a function
to test overlap and another to compute union.
* src/momentum.h: Move geometry tools into geom_2d.h (new file)
2007-04-24 Gavin SALAM <salam@lpthe.jussieu.fr> + Matteo
* src/defines.h (VERSION):
updated version number to 1.1.2-devel
* src/split_merge.cpp (include):
moved test on SM_var2_hardest_cut_off to beginning of loop, to
ensure that we don't get a first jet that's below the cutoff.
2007-04-20 Gregory Soyez <g.soyez@ulg.ac.be>
* src/split_merge.h: remove the "protected" attribute for
'SM_var2_hardest_cut_off' for easier inclusion in fastjet. Note
however that the 'protected' declaration in the previous version
was used to prevent from dangerous usage of the variable. This
is still applicable now!
2007-04-18 Gregory Soyez <g.soyez@ulg.ac.be>
* src/area.cpp: Add a parameter '_hard_only' which allow to
compute only the hard jets area (without the purely ghosted
ones.
* src/split_merge.h/cpp: Add a cut-off on the SM_var of the
hardest protojet. This is useful for computation of the area of
the hard jets without computing the purel ghosted ones. Note
that this cut-off is colinear-unsafe so has to be used with
great care.
2007-04-13 Gregory Soyez <g.soyez@ulg.ac.be>
* src/area.cpp: add Carea, the class to compute jet area
2007-03-16 Gregory Soyez <g.soyez@ulg.ac.be>
* SISCone 1.1.1 (tags/siscone-1.1.1)
2007-03-15 Gregory Soyez <g.soyez@ulg.ac.be>
* doc/html/usage.html: update the html doc for the recent
modifications of the split-merge algorithm.
* src/split_merge.cpp: improve the recomputation method when two
jets are very close in the ordering when SM var is set to SM_Et
2007-03-15 Gavin SALAM <salam@lpthe.jussieu.fr>
* src/split_merge.cpp:
modified fix to multiple-pass bug, in hope of being minimally
sensitive to rounding errors
2007-03-15 Gregory Soyez <g.soyez@ulg.ac.be>
* src/siscone.h: set the default number of passes to 0
* examples/main.cpp: adding two command line parameters to the
siscone application:
- npass controls the number of passes (0 by default)
- sm controls the choice for the split--merge variable
2007-03-14 Gregory Soyez <g.soyez@ulg.ac.be>
* src/momentum.h: add Et (inline) member function
* src/siscone.h: remove backward-compatibility computation members to
make things more clear.
* src/split_merge.cpp:
- fix multiple-pass bug
- add Et SM variable management
2007-03-14 Gavin Salam <salam@lpthe.jussieu.fr>
* src/split_merge.cpp:
put an assert for zero-size jets (common sign of a bug...);
ensured that "recomputed" protocones (with full momentum) also
have their eta-phi recalculated.
2007-03-12 Gavin SALAM <salam@lpthe.jussieu.fr>
* src/split_merge.cpp:
added some more debugging output.
2007-03-10 Gavin Salam <salam@lpthe.jussieu.fr>
* src/split_merge.cpp:
fixed some typos and a bug in the EPSILON_SPLITMERGE case for
pt-tilde.
2007-03-09 Gregory Soyez <g.soyez@ulg.ac.be>
* src/siscone.h: The default value for the SM variable is set to
pttilde
* src/split_merge.h/cpp: Update the split--merge procedure so that
it takes into account the choice for the split--merge
variable. Among the four choices, (pt_tilde, mt, pt and Et),
pt_tilde is the default (mt and pt can lead to IR unsafety). Et
is not yet implemented. We strongly advise to keep default value.
2007-03-09 Gavin Salam <salam@lpthe.jussieu.fr>
* src/siscone.h|cpp:
* src/split_merge.h|cpp:
introduced an enum, Esplit_merge_scale (naming convention in
analogy with the leading "C" for classes), which contains values
SM_pt, SM_Et, SM_mt, SM_pttilde, and put in routines that take
the enum (as well as leaving in old ones)
2007-03-06 Gavin SALAM <salam@lpthe.jussieu.fr>
* src/split_merge.cpp:
added transverse mass to info printed out about protojets with
the debug mode on (helpful in investigating limiting IR cases)
2007-03-02 Gregory Soyez <g.soyez@ulg.ac.be>
* SISCone 1.1.0 (tags/siscone-1.1.0)
2007-03-02 Gavin Salam <salam@lpthe.jussieu.fr>
* src/split_merge.cpp:
transformed a quiet error on illegal f values into a throw.
* src/siscone.cpp:
throw an error on illegal R values.
2007-03-01 Gavin Salam <salam@lpthe.jussieu.fr>
* src/split_merge.cpp|h:
added a new member variable, most_ambiguous_split, which records
the degree of ambiguity of the most ambiguous decision about
attributing a particle to one or other jet during a split step.
Useful for testing purposes.
2007-03-01 Gregory Soyez <g.soyez@ulg.ac.be>
* src/split_merge.cpp: set the full momentum
information on stable cones when we add them
to the protojet list
* src/siscone.h,cpp: add comments concerning the
split_merge_on_transverse_mass parameter
* src/defines.h (VERSION): set to 1.1.0beta
* src/split_merge.cpp (siscone):
- set ptmin as a real pt cut-off (independent on the
choice of variable for the SM)
- code cleaned (involves other files e.g. defines.h
momentum.h/cpp, siscone.h/cpp)
* set the website to the HEPForge one in headers
* replaced 'content' by 'contents' everywhere
WARNING: it implies Cjet::contents and
Csplit_merge::save_contents
* src/quadtree.cpp (siscone): replace 'childs' with 'children'
2007-02-21 Gregory Soyez <g.soyez@ulg.ac.be>
* src/protocones.cpp (siscone):
- remove all functions that are no longer necessary and replace
them by their new version. This includes the computatin of the
cone content, its re-computation, the check for co-circularity
and the test for stable cones in the co-circular situations.
- add a few comments of potentially tricky points.
- remove "cout" statements.
- remove 'largest_cocircular_range' which is no longer used
* src/vicinity.h:
- "largest_cocircular_range" removed.
- quadtree related stuff removed. As a consequence,
'build_from_list' is renamed 'build'. The usage of the
quadtree can now only be used in
'Cstable_cone::proceed_with_stability' hence, the USE_QUADTREE
define has been renamed USE_QUADTREE_FOR_STABILITY_TEST.
- Comments aligned to make the code clearer.
* src/momentum.h: Add mass() and mass2() member functions to
Cmomentum().
Put inline functions in the header rather than in the source
file.
* add C++ mark ("// -*- C++ -*-") in the headers where it was
missing
2007-02-20 Gavin Salam <salam@lpthe.jussieu.fr>
* src/split_merge.cpp:
enhanced check on infinite rapidities to include also
meaningless rapidities.
* src/split_merge.cpp|h:
* src/siscone.cpp:
sorted out an issue on multi-pass runs caused by earlier fix for
transverse mass ordering.
2007-02-20 [am-pm] Gavin Salam <salam@lpthe.jussieu.fr>
* src/split_merge.cpp:
fixed a bug that appeared once split_merge_on_transverse_mass
got moved into the Csplit_merge_ptcomparison class
* src/protocones.cpp|h:
introduced compute_cone_contents_nodist(), which calculates the
initial cone contents by circulating around all in/out
operations and collecting the net result --- this avoids any
distance calculations and so removes a potential source of
rounding error. (Any remaining rounding error is dealt with by
cocircularity tests).
* src/defines.h
added more info about the meaning of the different EPSILON
scales.
2007-02-19 [evening] Gavin Salam <salam@lpthe.jussieu.fr>
* src/defines.h:
introduced const bool split_merge_on_transverse_mass, which
determines whether the split merge occurs on transverse mass
instead of pt -- the latter turns out to be IR unsafe in
mom-conserving events for moderately large values of R (R>1)
* src/split_merge.cpp:
implemented the split-merge ordering on transverse masses,
including the limit of there being small differences.
* src/momentum.h:
introduced perpmass2() which returns the transverse mass,
pt^2+m^2
2007-02-19 [pm] Gavin Salam <salam@lpthe.jussieu.fr>
NB: seg-faults are being seen sporadically when fastjet writes its
description & need to be understood (but very rare and valgrind
gives nothing on small numbers of events...)
* src/defines.h:
added optional #define EPSILON_SPLITMERGE, which if defined,
sets a threshold for pt differences below which the ordering is
determined from the explicit particle content...
* src/split_merge.cpp|h:
trying to introduce more "exact" pt comparison in split merge to
deal with multiple scales -- this involves a new
Csplit_merge_ptcomparison class which allows the set to carry
out comparisons while making use of knowledge about the particle
momenta inside the split_merge class.
* src/circulator.h:
added != and == comparison operators.
* src/protocones.h|cpp:
added Cstable_cones::test_cone_cocircular_p3() for carrying out
a p^3 check of stability -- NB seems a bit slower for small p,
but obviously much better for large p... Tests of 2*10^5
particles show no errors, longer tests to be done later...
2007-02-19 [am, early pm] Gavin Salam <salam@lpthe.jussieu.fr>
* src/vicinity.h|cpp:
introduced the Cvicinity_inclusion class to allow one to carry
out checks both on the inclusion in the cone and in its
"cocircular" border. Made corresponding changes elsewhere.
* src/protocones.h|cpp:
wrote new_cocircular_check() and ran a certain number of tests
on it; currently it is this one that is being called from
update_cone(), but it still uses the original 2^p routine for
actually checking the cone status.
* src/[elsewhere]
added a lot of (now commented) debugging statements to help fix
bugs in the new_cocircular_check().
2007-02-18 [pm - later] Gavin Salam <salam@lpthe.jussieu.fr>
* src/circulator.h: *** ADDED ***
class for a circulator, used below.
* src/protocones.(h|cpp):
wrote prepare_cocircular_lists(), and checked that it's working
sensibly on some simple test events; also added code for
esetablishing the largest cocircular range among the children of
the current parent (should be used later to establish a more
reliable in/out status).
NB: the call to this function has added another 1-2% slowdown,
and we're now about 3-4% slower than before starting this
morning. But this should be the last of the changes that adds
significant extra time use?
* src/vicinity.(h|cpp):
support code for the protocones modification
2007-02-18 [pm] Gavin Salam <salam@lpthe.jussieu.fr>
* src/defines.h:
changed default EPSILON values to reflect what will be needed
with the new approach.
* src/vicinity.cpp:
carried out the calculation of cocircular_range inside the
append_to_vicinity member function; the extra
calculations/storage etc lead to a 2-3% slow-down for the
standard fastjet (354 particle) test event with R=1.
* src/momentum.h:
added a small 2-vector class, needed as a shorthand in
vicinity.cpp, plus various small utility routines.
* src/vicinity.h:
introduced cocircular_range and cocircular (list) as members of
Cvicinity_elm
* src/momentum.h:
introduced phi_in_range, dphi and abs_dphi inline functions.
2007-02-18 [am] Gavin Salam <salam@lpthe.jussieu.fr>
* src/vicinity.cpp (include):
switched to twopi from defines.h instead of the pi2 class member
* src/siscone_error.(cpp|h): *** ADDED ***
this is a simple class for throwing errors.
* src/protocones.cpp:
caused test_cone cocircular to throw errors when it receives
more than 32 points
carried out replacement client -> candidate
* src/defines.h:
introduced definition of twopi, which is used in many place (only
some usage instances have been replaced for now).
2007-02-16 Gregory Soyez <g.soyez@ulg.ac.be>
* src/defines.h: consider the limit on cocircularity and
collinearity as different ones. This introduces the
EPSILON_COCIRCULAR definition.
* src/protocones.cpp (siscone):
1. the list of cocircular situations already encountered is
maintained with a pair of references (the cone contents and
its border) instead of its coordinates.
2. we have improved the recomputation of the cone contents by
dynamically tracking he particles inside of the cone. This
adds a list of included particles in Cvicinity as well as a
pointer to elements of that list in vicinity elements.
2007-02-15 Gregory Soyez <g.soyez@ulg.ac.be>
* src/protocones.cpp: Code has been restructured to clearly
separate the cocircular case
* dealt woth cocircularity and 2\pi periodicity and added
an inline fction
2007-02-14 Gregory Soyez <g.soyez@ulg.ac.be>
* src/reference.cpp (siscone): ensures that the reference is not
zero
* src/protocones.cpp (siscone): Fix a bug with the interference
between the recomputation of jets and the update of cocircular
points
* src/protocones.cpp (siscone): add tests for recomputation of the
cone content for the case of cocircular points
* src/protocones.cpp (siscone): when testing the threshold for
recomputation of te cone content, we add a test putting
automatically the cone to 0 when it is empty.
2007-02-13 Gregory Soyez <g.soyez@ulg.ac.be>
* We add a test of cocircularity: when more the p>2 particles are
found on the same circle, we branch to a different test of cone
stability. This new part of the algorithm tests all possible
inclusions/exclusions of the particles along the circle in a
2^p-type algorithm. Note that findling large values of p is
highly improbable !
2007-02-12 Gregory Soyez <g.soyez@ulg.ac.be>
* when traversing the centre list (in stable cones search), we
start with the centre which is the most separated from its
neighbours. This allows to minimize the possibility that we
miscomputed the computation of the initial cone content due to
possible rounding errors when two centres are too close.
2007-02-12 Gregory Soyez <g.soyez@ulg.ac.be>
* in collinear merging, take care of the periodicity in phi
* put the threshold for collinear merging in defines.h
(EPSILON_COLLINEAR)
2007-02-12 Gregory Soyez <g.soyez@ulg.ac.be>
* undo the previous modification and use another approach to deal
with collinear particles: we keep the p_remain list as it was
before (see revision 84). Instead, after computing p_remain, we
compute p_uncol which is obtained from p_remain by merging
collinear particles. In the siscone main loop, we then use
p_uncol instead of p_remain for the search for stable
cones. Note that with this modification, the 'parent_index'
field of Cmomentum is back to its original definition as a
'int'.
2007-02-12 Gregory Soyez <g.soyez@ulg.ac.be>
* remove initialisation of parent_index in momentum.cpp and
vicinity.cpp This is allowed because of the Npass loop in
siscone. Indeed, parent_index is only used internally in
split_merge and init at the very beginning of the loop by a call
to init_pleft
* replaced "int parent_index" by "vector<int> parent_index" and
align the code in split_merge.cpp
* add a few lines off code in split_merge.cpp to account for
collinear particles.
* Note concerning the previous update: the change has been
validated and is no longer considered as temporary
2007-02-12 Gregory Soyez <g.soyez@ulg.ac.be>
* Changed the test for recomputation of cone content in Cstable_cones
see defines.h for details
(this change may be temporary)
2007-02-10 Gregory Soyez <g.soyez@ulg.ac.be>
* fixed doxygen documentation issues:
- undocumented or renamed parameters
- include various links into a custom html footer
2007-01-25 Gregory Soyez <g.soyez@ulg.ac.be>
* fixed memory leak for Cvicinity::ve_list
in Cvicinity::set_particle_list()
2007-01-23 Gavin SALAM <salam@lpthe.jussieu.fr>
* added _ptmin argument to Csiscone::recompute_jets(...)
2007-01-22 Gregory Soyez <g.soyez@ulg.ac.be>
* add ptmin threshold on protojets during split-merge
* modify example program to allow for the --ptmin option
2007-01-20 Gregory Soyez <g.soyez@ulg.ac.be>
* fix typo mistake in split_merge.cpp
2007-01-18 Gregory Soyez <g.soyez@ulg.ac.be>
* insert a header on top of each source files to give brief information
about its content, the SISCone project and copyright
2007-01-03 Gregory Soyez <g.soyez@ulg.ac.be>
* remove the usage of the quadtree in stable cones detection.
Usage of the quadtree in vicinity list creation and final stability
tests can be switched on buy defining USE_QUADTREE in defines.h.
This step was not fully achieved in the last update.
2006-12-28 Gregory Soyez <g.soyez@ulg.ac.be>
* remove the usage of the quadtree in stable cones detection.
Usage of the quadtree in vicinity list creation and final stability
tests can be switched on by defining USE_QUADTREE in defines.h
2006-12-28 Gavin Salam <salam@lpthe.jussieu.fr>
* commented out various "template std::vector<...>" lines to solve
compilation problem on Macs.
* modified the make depend targets so that they do not include
"standard" include files (which differ from one system to
another).
* fixed log(_Np) bug pointed out by Matteo; fixed program name in
defines.h
2006-12-28 Gregory Soyez <g.soyez@ulg.ac.be>
* replace variables with name being "underscore" followed by
a single letter by longer names since they lead to compilation
problems under Mac. In practice, we renamed _N with _Np in hash.cpp/h
and _R by _radius in protocones.cpp/h and siscone.cpp/h
2006-12-27 Gregory Soyez <g.soyez@ulg.ac.be>
* arranged for "make dist" to create a file with the same version
name in the directory and the tar file; made the tar-file
read-only (to avoid involuntarily overwrite); removed svn file
from the examples/events subdirectory.
2006-12-26 Gregory Soyez <g.soyez@ulg.ac.be>
* updated the 'dist' target in the Makefile: include mem_check
with the correct path and build archive so that it unpacks into
a siscone-1.0-beta directory
* fix typos in INSTALL
2006-12-26 Gavin Salam <salam@lpthe.jussieu.fr>
* Changed banner so that first char is # (to allow the rest of the
line to be considered a comment by things like gnuplot).
* moved scones -> siscone (and sorted out various "ignores")
* Reordered changelog so that later stuff appears first (I think
this is standard? Makes it easier to see what's been happening
recently...)
* Tidying up: moved jets.gri and mem_check into the examples
directory; added -f to "rm" command in make clean to avoid
errors; modified siscones->siscone in a couple of places in
doc.
* Brought the README and INSTALL files up to date
* set some svn:ignore property so as to ignore .dat files (to
reduce "noise" with svn status).
* added #!/bin/bash to head of examples/mem_check
2006-12-22 Gregory Soyez <g.soyez@ulg.ac.be>
* rename scones namespace into siscone
* put ranlux stuff into the namespace (we don't want to
pollute the gobal namespace
* add doc/devel as directory for developer's documentation
(using Doxygen)
* scones.h/cpp is renamed siscone.h/cpp
* creation of an 'examples' directory for various programs
only the library libsiscone.a is left in the src dir
Malefiles are modified accordingly
2006-12-21 Gavin Salam <salam@lpthe.jussieu.fr>
* added the MERGE_IDENTICAL_PROTOCONES_DEFAULT_TRUE define to
allow one to make MERGE_IDENTICAL_PROTOCONES to be set true by
default if need be. (This makes it a bit easier to make a quick
modification to run a test).
* changed some of the related comments
* replaced occurrences of "extensive" with "multipass"
* Added the ChangeLog file!
2006-12-21 START OF CHANGELOG
Index: branches/spherical/siscone/vicinity.cpp
===================================================================
--- branches/spherical/siscone/vicinity.cpp (revision 241)
+++ branches/spherical/siscone/vicinity.cpp (revision 242)
@@ -1,300 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-// File: vicinity.cpp //
-// Description: source file for particle vicinity (Cvicinity class) //
-// This file is part of the SISCone project. //
-// WARNING: this is not the main SISCone trunk but //
-// an adaptation to spherical coordinates //
-// For more details, see http://projects.hepforge.org/siscone //
-// //
-// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
-// //
-// This program is free software; you can redistribute it and/or modify //
-// it under the terms of the GNU General Public License as published by //
-// the Free Software Foundation; either version 2 of the License, or //
-// (at your option) any later version. //
-// //
-// This program is distributed in the hope that it will be useful, //
-// but WITHOUT ANY WARRANTY; without even the implied warranty of //
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
-// GNU General Public License for more details. //
-// //
-// You should have received a copy of the GNU General Public License //
-// along with this program; if not, write to the Free Software //
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
-// //
-// $Revision:: $//
-// $Date:: $//
-///////////////////////////////////////////////////////////////////////////////
-
-#include "vicinity.h"
-#include <math.h>
-#include <algorithm>
-#include <iostream>
-
-namespace siscone{
-
-using namespace std;
-
-/*************************************************************
- * Cvicinity_elm implementation *
- * element in the vicinity of a parent. *
- * class used to manage one points in the vicinity *
- * of a parent point. *
- *************************************************************/
-
-// ordering pointers to Cvicinity_elm
-//------------------------------------
-bool ve_less(Cvicinity_elm *ve1, Cvicinity_elm *ve2){
- return ve1->angle < ve2->angle;
-}
-
-
-/*************************************************************
- * Cvicinity implementation *
- * list of element in the vicinity of a parent. *
- * class used to manage the points which are in the vicinity *
- * of a parent point. The construction of the list can be *
- * made from a list of points or from a quadtree. *
- *************************************************************/
-
-// default constructor
-//---------------------
-Cvicinity::Cvicinity(){
- n_part = 0;
-
- ve_list = NULL;
-#ifdef USE_QUADTREE_FOR_STABILITY_TEST
- quadtree = NULL;
-#endif
-
- parent = NULL;
- VR2 = VR = 0.0;
-
-}
-
-// constructor with initialisation
-//---------------------------------
-Cvicinity::Cvicinity(vector<Cmomentum> &_particle_list){
- parent = NULL;
- ve_list = NULL;
-#ifdef USE_QUADTREE_FOR_STABILITY_TEST
- quadtree = NULL;
-#endif
- cosVR = VR2 = tan2R = VR = 0.0;
-
- set_particle_list(_particle_list);
-}
-
-// default destructor
-//--------------------
-Cvicinity::~Cvicinity(){
- if (ve_list!=NULL)
- delete[] ve_list;
-
-#ifdef USE_QUADTREE_FOR_STABILITY_TEST
- if (quadtree!=NULL)
- delete quadtree;
-#endif
-}
-
-/*
- * set the particle_list
- * - particle_list list of particles (type Cmomentum)
- * - n number of particles in the list
- ************************************************************/
-void Cvicinity::set_particle_list(vector<Cmomentum> &_particle_list){
- int i,j;
-#ifdef USE_QUADTREE_FOR_STABILITY_TEST
- double eta_max=0.0;
-#endif
-
- // if the particle list is not empty, destroy it !
- if (ve_list!=NULL){
- delete[] ve_list;
- }
- vicinity.clear();
-#ifdef USE_QUADTREE_FOR_STABILITY_TEST
- if (quadtree!=NULL)
- delete quadtree;
-#endif
-
- // allocate memory array for particles
- // Note: - we compute max for |eta|
- // - we allocate indices to particles
- n_part = 0;
- plist.clear();
- pincluded.clear();
- for (i=0;i<(int) _particle_list.size();i++){
- // if a particle is colinear with the beam (infinite rapidity)
- // we do not take it into account
- //if (fabs(_particle_list[i].pz)!=_particle_list[i].E){
- plist.push_back(_particle_list[i]);
- pincluded.push_back(Cvicinity_inclusion()); // zero inclusion status
-
- // the parent_index is handled in the split_merge because
- // of our multiple-pass procedure.
- // Hence, it is not required here any longer.
- // plist[n_part].parent_index = i;
- plist[n_part].index = n_part;
-
- // make sure the reference is randomly created
- plist[n_part].ref.randomize();
-
-#ifdef USE_QUADTREE_FOR_STABILITY_TEST
- if (fabs(plist[n_part].eta)>eta_max) eta_max=fabs(plist[n_part].eta);
-#endif
- n_part++;
- //}
- }
-
- // allocate quadtree and vicinity_elm list
- // note: we set phi in [-pi:pi] as it is the natural range for atan2!
- ve_list = new Cvicinity_elm[2*n_part];
-#ifdef USE_QUADTREE_FOR_STABILITY_TEST
- eta_max+=0.1;
- quadtree = new Cquadtree(0.0, 0.0, eta_max, M_PI);
-#endif
-
- // append particle to the vicinity_elm list
- j = 0;
- for (i=0;i<n_part;i++){
-#ifdef USE_QUADTREE_FOR_STABILITY_TEST
- quadtree->add(&plist[i]);
-#endif
- ve_list[j].v = ve_list[j+1].v = &plist[i];
- ve_list[j].is_inside = ve_list[j+1].is_inside = &(pincluded[i]);
- j+=2;
- }
-
-}
-
-
-/*
- * build the vicinity list from a list of points.
- * - _parent reference particle
- * - _VR vicinity radius
- ************************************************************/
-void Cvicinity::build(Cmomentum *_parent, double _VR){
- int i;
-
- // set parent and radius
- parent = _parent;
-
- VR = _VR;
- VR2 = VR*VR;
- cosVR = cos(VR);
- R2 = 0.25*VR2;
- R = 0.5*VR;
- double tmp = tan(R);
- tan2R = tmp*tmp;
-
- D2_R = 2.0*(1-cos(R));
- //tmp = sqrt(D2_R);
- inv_R_EPS_COCIRC = 1.0 / R / EPSILON_COCIRCULAR;
- inv_R_2EPS_COCIRC = 0.5 / R / EPSILON_COCIRCULAR;
-
- // clear vicinity
- vicinity.clear();
-
- // init parent variables
- // we cpte the direction of the centre and two orthogonal ones
- // to measure the angles. Those are taken orthogonal to the
- // axis of smallest components (of the centre) to increase precision
- parent_centre = (*parent)/parent->_norm;
- parent_centre.get_angular_directions(angular_dir1, angular_dir2);
- angular_dir1 /= angular_dir1._norm;
- angular_dir2 /= angular_dir2._norm;
-
- // really browse the particle list
- for (i=0;i<n_part;i++){
- append_to_vicinity(&plist[i]);
- }
-
- // sort the vicinity
- sort(vicinity.begin(), vicinity.end(), ve_less);
-
- vicinity_size = vicinity.size();
-}
-
-
-/// strictly increasing function of the angle
-//TODO//
-inline double sort_angle(double s, double c){
- if (s==0) return (c>0) ? 0.0 : 2.0;
- double t=c/s;
- return (s>0) ? 1-t/(1+fabs(t)) : 3-t/(1+fabs(t));
-}
-
-
-/*
- * append a particle to the 'vicinity' list after
- * having computed the angular-ordering quantities
- * - v vector to test
- **********************************************************/
-void Cvicinity::append_to_vicinity(Cmomentum *v){
- // skip the particle itself)
- if (v==parent)
- return;
-
- int i=2*(v->index);
-
- // compute the distance of the i-th particle with the parent
- double dot = dot_product3(parent_centre,*v);
- C3vector vnormal = *v;
- vnormal/=v->_norm;
- dot/=v->_norm;
-
- // really check if the distance is less than VR
- if (dot>cosVR){
- C3vector cross = cross_product3(parent_centre,vnormal);
-
- // for the centres
- C3vector median = (parent_centre+vnormal);
- double amplT = sqrt((tan2R*(1+dot)+(dot-1))*(1+dot));
- C3vector transverse = amplT*cross/cross._norm;
-
- // first angle (+)
- ve_list[i].centre = median + transverse;
- ve_list[i].centre.build_norm();
- ve_list[i].centre/=ve_list[i].centre._norm;
- C3vector diff = ve_list[i].centre - parent_centre;
- //ve_list[i].angle = atan2(dot_product3(angular_dir2, diff),dot_product3(angular_dir1, diff));
- ve_list[i].angle = sort_angle(dot_product3(angular_dir2, diff),dot_product3(angular_dir1, diff));
- ve_list[i].side = true;
- ve_list[i].cocircular.clear();
- vicinity.push_back(&(ve_list[i]));
-
- // second angle (-)
- ve_list[i+1].centre = median - transverse;
- ve_list[i+1].centre.build_norm();
- ve_list[i+1].centre/=ve_list[i+1].centre._norm;
- diff = ve_list[i+1].centre - parent_centre;
- ve_list[i+1].angle = sort_angle(dot_product3(angular_dir2, diff),dot_product3(angular_dir1, diff));
- ve_list[i+1].side = false;
- ve_list[i+1].cocircular.clear();
- vicinity.push_back(&(ve_list[i+1]));
-
- // now work out the cocircularity range for the two points (range
- // of angle within which the points stay within a distance
- // EPSILON_COCIRCULAR of circule
- // P = parent; C = child; O = Origin (center of circle)
- C3vector OP = parent_centre - ve_list[i+1].centre;
- C3vector OC = vnormal - ve_list[i+1].centre;
-
- // two sources of error are (GPS CCN29-19) epsilon/(R sin theta)
- // and sqrt(2*epsilon/(R (1-cos theta))) and the way things work
- // out, it is the _smaller_ of the two that is relevant [NB have
- // changed definition of theta here relative to that used in
- // CCN29] [NB2: write things so as to avoid zero denominators and
- // to minimize the multiplications, divisions and above all sqrts
- // -- that means that c & s are defined including a factor of VR2]
- double inv_err1 = cross_product3(OP,OC)._norm * inv_R_EPS_COCIRC;
- double inv_err2_sq = (D2_R-dot_product3(OP,OC)) * inv_R_2EPS_COCIRC;
- ve_list[i].cocircular_range = pow2(inv_err1) > inv_err2_sq ?
- 1.0/inv_err1 :
- sqrt(1.0/inv_err2_sq);
- ve_list[i+1].cocircular_range = ve_list[i].cocircular_range;
- }
-}
-
-}
Index: branches/spherical/siscone/protocones.h
===================================================================
--- branches/spherical/siscone/protocones.h (revision 241)
+++ branches/spherical/siscone/protocones.h (revision 242)
@@ -1,262 +0,0 @@
-// -*- C++ -*-
-///////////////////////////////////////////////////////////////////////////////
-// File: protocones.h //
-// Description: header file for stable cones determination (Cstable_cones) //
-// This file is part of the SISCone project. //
-// WARNING: this is not the main SISCone trunk but //
-// an adaptation to spherical coordinates //
-// For more details, see http://projects.hepforge.org/siscone //
-// //
-// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
-// //
-// This program is free software; you can redistribute it and/or modify //
-// it under the terms of the GNU General Public License as published by //
-// the Free Software Foundation; either version 2 of the License, or //
-// (at your option) any later version. //
-// //
-// This program is distributed in the hope that it will be useful, //
-// but WITHOUT ANY WARRANTY; without even the implied warranty of //
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
-// GNU General Public License for more details. //
-// //
-// You should have received a copy of the GNU General Public License //
-// along with this program; if not, write to the Free Software //
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
-// //
-// $Revision:: $//
-// $Date:: $//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef __PROTOCONES_H__
-#define __PROTOCONES_H__
-
-#include "momentum.h"
-#include "vicinity.h"
-#include <stdio.h>
-#include <vector>
-#include <list>
-#include "hash.h"
-
-#include "defines.h"
-
-namespace siscone{
-
-/**
- * \class Cborder_store
- *
- * class for storing a border momentum (in context of co-circularity
- * checks).
-
- * This class essentially calculates angle of border point w.r.t.
- * circle center (eta & phi), and provides a store of information
- * about whether we are currently including this point in the
- * candidate
- */
-class Cborder_store{
-public:
- /// default ctor
- Cborder_store(Cmomentum * momentum, C3vector &centre, C3vector &angl_dir1, C3vector &angl_dir2) :
- mom(momentum), is_in(false) {
- C3vector diff = (*momentum) - centre;
- angle = atan2(dot_product3(diff, angl_dir2), dot_product3(diff, angl_dir1));
-#ifdef DEBUG_STABLE_CONES
- std::cout << " adding point " << momentum->_theta << ", " << momentum->_phi
- << " at an angle of " << angle << std::endl;
-#endif
- }
-
- Cmomentum * mom; ///< particle momentum
- double angle; ///< angle w.r.t. circle centre
- bool is_in; ///< inclusion status of the particle
-};
-
-
-/// allows easy sorting of Cborder_store objects (which need to be
-/// ordered in angle).
-inline bool operator<(const Cborder_store & a, const Cborder_store & b) {
- return a.angle < b.angle;
-}
-
-
-/**
- * \class Cstable_cones
- * \brief Computes the list of stable comes from a particle list.
- *
- * This class does the first fundamental task of te cone algorithm:
- * it is used to compute the list of stable cones given a list
- * of particles.
- */
-class Cstable_cones : public Cvicinity{
- public:
- /// default ctor
- Cstable_cones();
-
- /// ctor with initialisation (sse init for details)
- Cstable_cones(std::vector<Cmomentum> &_particle_list);
-
- /// default dtor
- ~Cstable_cones();
-
- /**
- * initialisation
- * \param _particle_list list of particles
- */
- void init(std::vector<Cmomentum> &_particle_list);
-
- /**
- * compute stable cones.
- * This function really does the job i.e. computes
- * the list of stable cones (in a seedless way)
- * \param _radius radius of the cones
- * \return The number of stable cones found is returned
- */
- int get_stable_cones(double _radius);
-
- /// list of stable cones
- std::vector<Cmomentum> protocones;
-
- /// list of candidates
- hash_cones *hc;
-
- /// total number of tested cones
- int nb_tot;
-#ifdef DEBUG_STABLE_CONES
- int nb_hash_cones, nb_hash_occupied;
-#endif
-
- protected:
- /// cone radius
- double R;
-
- /// cone radius SQUARED
- double R2;
-
- /// squared tangent of the cone radius
- double tan2R;
-
- private:
- /// cone with a given particle as parent
- /// this reduction to a single vector assumes we trust the checksums
- Cmomentum cone;
-
- /// child particle, taken in the 'vicinity' list
- Cmomentum *child;
-
- /// centre of the tested cone
- Cvicinity_elm *centre;
-
- /// index in the particle list;
- unsigned int centre_idx;
-
- /// first cone used in the vicinity list
- unsigned int first_cone;
-
- /**
- * initialise the cone.
- * We take the first particle in the angular ordering to compute this one
- * \return 0 on success, 1 on error
- */
- int init_cone();
-
- /**
- * test cones.
- * We check if the cone(s) build with the present parent and child
- * are stable
- * \return 0 on success 1 on error
- */
- int test_cone();
-
- /**
- * update the cone
- * go to the next child for that parent and update 'cone' appropriately
- * \return 0 if update candidate found, 1 otherwise
- */
- int update_cone();
-
- /*
- * run through the vicinity of the current parent and for each child
- * indicate which members are cocircular...
- */
- void prepare_cocircular_lists();
-
- /**
- * check if we are in a situation of cocircularity.
- * if it is the case, update and test in the corresponding way
- * \return 'false' if no cocircularity detected, 'true' otherwise
- * Note that if cocircularity is detected, we need to
- * recall 'update' from 'update' !!!
- */
- bool cocircular_check();
-
- /**
- * Routine for testing cocircular configurations in p^3 time,
- * rather than 2^p time;
- */
- void test_cone_cocircular(Cmomentum & borderless_cone,
- std::list<Cmomentum *> & border_list);
-
- /**
- * carry out the computations needed for the stability check of the
- * candidate, using the border_vect to indicate which particles
- * should / should not be in the stable cone; if the cone is stable
- * insert it into the hash.
- */
- void test_stability(Cmomentum & candidate,
- const std::vector<Cborder_store> & border_vect);
-
- /**
- * compute the cone contents by going once around the full set of
- * circles and tracking the entry/exit status each time -- this sets
- * up the inclusion information, which can then be directly used to
- * calculate the cone momentum.
- */
- void compute_cone_contents();
-
- /**
- * compute the cone momentum from particle list.
- * in this version, we use the 'pincluded' information
- * from the Cviinity class
- */
- void recompute_cone_contents();
-
- /*
- * if we have gone beyond the acceptable threshold of change, compute
- * the cone momentum from particle list. in this version, we use the
- * 'pincluded' information from the Cvicinity class, but we don't
- * change the member cone, only the locally supplied one
- */
- void recompute_cone_contents_if_needed(Cmomentum & this_cone, double & this_dpt);
-
- /**
- * compute stability of all enumerated candidates.
- * For all candidate cones which are stable w.r.t. their border particles,
- * pass the last test: stability with quadtree intersection
- */
- int proceed_with_stability();
-
- /*
- * circle intersection.
- * computes the intersection with a circle of given centre and radius.
- * The output takes the form of a checkxor of the intersection's particles
- * - cx circle centre x coordinate
- * - cy circle centre y coordinate
- * return the checkxor for the intersection
- ******************************************************************/
- Creference circle_intersect(C3vector &cone_centre);
-
- /// present candidate cone
- Cmomentum cone_candidate;
-
- /// in case of co-circular points, vector for them
- std::vector<Cmomentum*> child_list;
-
- /// list of cocircular enclusures already studied
- /// first element if cone contents, second is cone border
- std::vector< std::pair<Creference,Creference> > multiple_centre_done;
-
- // information for updating cone contents to avoid rounding errors
- double dpt; ///< sums of Delta P_t
-};
-
-}
-#endif
Index: branches/spherical/siscone/momentum.cpp
===================================================================
--- branches/spherical/siscone/momentum.cpp (revision 241)
+++ branches/spherical/siscone/momentum.cpp (revision 242)
@@ -1,294 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-// File: momentum.cpp //
-// Description: source file for 4-momentum class Cmomentum //
-// This file is part of the SISCone project. //
-// WARNING: this is not the main SISCone trunk but //
-// an adaptation to spherical coordinates //
-// For more details, see http://projects.hepforge.org/siscone //
-// //
-// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
-// //
-// This program is free software; you can redistribute it and/or modify //
-// it under the terms of the GNU General Public License as published by //
-// the Free Software Foundation; either version 2 of the License, or //
-// (at your option) any later version. //
-// //
-// This program is distributed in the hope that it will be useful, //
-// but WITHOUT ANY WARRANTY; without even the implied warranty of //
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
-// GNU General Public License for more details. //
-// //
-// You should have received a copy of the GNU General Public License //
-// along with this program; if not, write to the Free Software //
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
-// //
-// $Revision:: $//
-// $Date:: $//
-///////////////////////////////////////////////////////////////////////////////
-
-#include "momentum.h"
-#include <math.h>
-#include <stdlib.h>
-
-namespace siscone{
-
-/*************************************************************************
- * class C3vector *
- * This class contains the information for particle or group of *
- * particles management. *
- *************************************************************************/
-
-// default ctor
-//--------------
-C3vector::C3vector(){
- _theta = _phi = _norm = 0.0;
- px = py = pz = 0.0;
- ref = Creference();
-}
-
-// ctor with initialisation
-//--------------------------
-C3vector::C3vector(double _px, double _py, double _pz){
- px = _px;
- py = _py;
- pz = _pz;
-
- // compute the norm
- build_norm();
-
- ref = Creference();
-}
-
-// default dtor
-//--------------
-C3vector::~C3vector(){
-
-}
-
-
-// assignment of vectors
-//-----------------------
-C3vector& C3vector::operator = (const C3vector &v){
- px = v.px;
- py = v.py;
- pz = v.pz;
-
- _norm = v._norm;
- _theta = v._theta;
- _phi = v._phi;
-
- ref = v.ref;
- return *this;
-}
-
-// addition of vectors
-//------------------------------------------------
-const C3vector C3vector::operator + (const C3vector &v){
- C3vector tmp = *this;
- return tmp+=v;
-}
-
-// subtraction of vectors
-//------------------------------------------------
-const C3vector C3vector::operator - (const C3vector &v){
- C3vector tmp = *this;
- return tmp-=v;
-}
-
-// division by constant
-//------------------------------------------------
-const C3vector C3vector::operator / (const double &r){
- C3vector tmp = *this;
- return tmp/=r;
-}
-
-// incrementation
-//------------------------------------------------
-C3vector& C3vector::operator += (const C3vector &v){
- px+=v.px;
- py+=v.py;
- pz+=v.pz;
-
- return *this;
-}
-
-// decrementation
-//------------------------------------------------
-C3vector& C3vector::operator -= (const C3vector &v){
- px-=v.px;
- py-=v.py;
- pz-=v.pz;
-
- return *this;
-}
-
-// multiplication by a constant
-//------------------------------------------------
-C3vector& C3vector::operator *= (const double &r){
- px*=r;
- py*=r;
- pz*=r;
-
- return *this;
-}
-
-// division by a constant
-//------------------------------------------------
-C3vector& C3vector::operator /= (const double &r){
- px/=r;
- py/=r;
- pz/=r;
-
- _norm/=r;
-
- return *this;
-}
-
-// build norm from 3-momentum info
-void C3vector::build_norm(){
- _norm = norm();
-}
-
-// build norm from 3-momentum info
-void C3vector::build_thetaphi(){
- _theta = theta();
- _phi = phi();
-}
-
-
-// for this direction, compute the two reference directions
-// used to measure angles
-void C3vector::get_angular_directions(C3vector &angular_dir1, C3vector &angular_dir2){
- if (px < py){
- if (pz < px){
- // z smallest
- angular_dir1 = C3vector(-py, px, 0.0);
- } else {
- // x smallest
- angular_dir1 = C3vector(0.0, -pz, py);
- }
- } else {
- if (pz < py){
- // z smallest
- angular_dir1 = C3vector(-py, px, 0.0);
- } else {
- // y smallest
- angular_dir1 = C3vector(-pz, 0.0, px);
- }
- }
- angular_dir2 = cross_product3(*this, angular_dir1);
- // We'll simply take x & y so the reflection symmetry is not broken
- //angular_dir1 = C3vector(0.0, -pz, py);
- //angular_dir2 = C3vector(-pz, 0.0, -px);
-}
-
-/*************************************************************************
- * class Cmomentum *
- * This class contains the information for particle or group of *
- * particles management. *
- * It includes all Lorentz properties as well as tools for summing them. *
- *************************************************************************/
-
-// default ctor
-//--------------
-Cmomentum::Cmomentum(){
- E=0.0;
- index = -1;
-}
-
-// ctor with initialisation
-//--------------------------
-Cmomentum::Cmomentum(double _px, double _py, double _pz, double _E)
- : C3vector(_px, _py, _pz) {
- E = _E;
-
- // compute the angles
- build_thetaphi();
-}
-
-// ctor with initialisation
-//--------------------------
-Cmomentum::Cmomentum(C3vector &_v, double _E)
- : C3vector(_v.px, _v.py, _v.pz) {
- E = _E;
-}
-
-// default dtor
-//--------------
-Cmomentum::~Cmomentum(){
-
-}
-
-// assignment of vectors
-//-----------------------
-Cmomentum& Cmomentum::operator = (const Cmomentum &v){
- px = v.px;
- py = v.py;
- pz = v.pz;
- E = v.E;
-
- _norm = v._norm;
- _theta = v._theta;
- _phi = v._phi;
-
- ref = v.ref;
- return *this;
-}
-
-// addition of vectors
-// !!! WARNING !!! no updating of eta and phi !!!
-//------------------------------------------------
-const Cmomentum Cmomentum::operator + (const Cmomentum &v){
- Cmomentum tmp = *this;
- return tmp+=v;
-}
-
-// incrementation of vectors
-// !!! WARNING !!! no updating of eta and phi !!!
-//------------------------------------------------
-Cmomentum& Cmomentum::operator += (const Cmomentum &v){
- px+=v.px;
- py+=v.py;
- pz+=v.pz;
- E +=v.E;
-
- ref+=v.ref;
-
- return *this;
-}
-
-// decrementation of vectors
-// !!! WARNING !!! no updating of eta and phi !!!
-//------------------------------------------------
-Cmomentum& Cmomentum::operator -= (const Cmomentum &v){
- px-=v.px;
- py-=v.py;
- pz-=v.pz;
- E -=v.E;
-
- ref-=v.ref;
- return *this;
-}
-
-
-// ordering of two vectors
-// the default ordering is w.r.t. their references
-//-------------------------------------------------
-bool operator < (const Cmomentum &v1, const Cmomentum &v2){
- return v1.ref < v2.ref;
-}
-
-// ordering of vectors in eta (e.g. used in collinear tests)
-//-----------------------------------------------------------
-bool momentum_theta_less(const Cmomentum &v1, const Cmomentum &v2){
- return v1._theta < v2._theta;
-}
-
-// ordering of vectors in pt
-//---------------------------
-bool momentum_pt_less(const Cmomentum &v1, const Cmomentum &v2){
- return v1.perp2() < v2.perp2();
-}
-
-}
-
Index: branches/spherical/siscone/vicinity.h
===================================================================
--- branches/spherical/siscone/vicinity.h (revision 241)
+++ branches/spherical/siscone/vicinity.h (revision 242)
@@ -1,161 +0,0 @@
-// -*- C++ -*-
-///////////////////////////////////////////////////////////////////////////////
-// File: vicinity.h //
-// Description: header file for particle vicinity (Cvicinity class) //
-// This file is part of the SISCone project. //
-// WARNING: this is not the main SISCone trunk but //
-// an adaptation to spherical coordinates //
-// For more details, see http://projects.hepforge.org/siscone //
-// //
-// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
-// //
-// This program is free software; you can redistribute it and/or modify //
-// it under the terms of the GNU General Public License as published by //
-// the Free Software Foundation; either version 2 of the License, or //
-// (at your option) any later version. //
-// //
-// This program is distributed in the hope that it will be useful, //
-// but WITHOUT ANY WARRANTY; without even the implied warranty of //
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
-// GNU General Public License for more details. //
-// //
-// You should have received a copy of the GNU General Public License //
-// along with this program; if not, write to the Free Software //
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
-// //
-// $Revision:: $//
-// $Date:: $//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef __VICINITY_H__
-#define __VICINITY_H__
-
-#include <vector>
-#include <list>
-#include "momentum.h"
-#include "defines.h"
-#include "quadtree.h"
-
-namespace siscone{
-
-
-
-/**
- * \class Cvicinity_inclusion
- * \brief a class to keep track of inclusion status in cone and in cocircular region
- * while using minimal resources
- */
-class Cvicinity_inclusion {
-public:
- /// default ctor
- Cvicinity_inclusion() : cone(false), cocirc(false) {}
-
- bool cone; ///< flag for particle inclusion in the cone
- bool cocirc; ///< flag for particle inclusion in the border
-};
-
-
-/**
- * \class Cvicinity_elm
- * \brief element in the vicinity of a parent.
- *
- * class used to manage one points in the vicinity
- * of a parent point.
- */
-class Cvicinity_elm{
- public:
- /// pointer to the second borderline particle
- Cmomentum *v;
-
- /// variable to tell if the particle is inside or outside the cone
- Cvicinity_inclusion *is_inside;
-
- // centre variables
- C3vector centre; ///< direction of the centre
- double angle; ///< angle with parent
- bool side; ///< true if angle on the positive side, false otherwise
- double cocircular_range; ///< amount by which the angle can be varied while
- ///< maintaining this point within co-circularity margin
-
- /// list of elements co-circular with this one
- /// NB: empty list uses less mem than vector
- std::list<Cvicinity_elm * > cocircular;
-};
-
-/// ordering pointers to Cvicinity_elm
-bool ve_less(Cvicinity_elm *ve1, Cvicinity_elm *ve2);
-
-
-/**
- * \class Cvicinity
- * \brief list of element in the vicinity of a parent.
- *
- * class used to manage the points which are in the vicinity
- * of a parent point.
- */
-class Cvicinity{
- public:
- /// default constructor
- Cvicinity();
-
- /// constructor with initialisation (see set_particle_list)
- Cvicinity(std::vector<Cmomentum> &_particle_list);
-
- /// default destructor
- ~Cvicinity();
-
- /**
- * set the particle_list
- * \param _particle_list list of particles (type Cmomentum)
- */
- void set_particle_list(std::vector<Cmomentum> &_particle_list);
-
- /**
- * build the vicinity list from the list of points.
- * \param _parent reference particle
- * \param _VR vicinity radius
- */
- void build(Cmomentum *_parent, double _VR);
-
- // cone kinematical information
- Cmomentum *parent; ///< parent vector
- double VR; ///< radius of the vicinity
- double VR2; ///< squared radius of the vicinity
- double cosVR; ///< cosine of the radius of the vicinity
- double R; ///< normal radius
- double R2; ///< squared normal radius
- double tan2R; ///< squared tangent of the normal radius
- double D2_R; ///< euclidian distance (squared) corresp. to the arc R
- double inv_R_EPS_COCIRC; ///< R / EPSILON_COCIRCULAR
- double inv_R_2EPS_COCIRC; ///< R / (2*EPSILON_COCIRCULAR)
-
- // particle list information
- int n_part; ///< number of particles
- std::vector<Cmomentum> plist; ///< the list of particles
- std::vector<Cvicinity_inclusion> pincluded; ///< the inclusion state of particles
- Cvicinity_elm *ve_list; ///< list of vicinity elements built from particle list (size=2*n)
-#ifdef USE_QUADTREE_FOR_STABILITY_TEST
- Cquadtree *quadtree; ///< quadtree used for final stability tests
-#endif
-
- // vicinity information
- std::vector<Cvicinity_elm*> vicinity; ///< list of points in parent's vicinity
- unsigned int vicinity_size; ///< number of elements in vicinity
-
- protected:
- /**
- * append a particle to the 'vicinity' list after
- * having tested it and computed the angular-ordering quantities
- * \param v vector to test
- */
- void append_to_vicinity(Cmomentum *v);
-
- // internal variables
- C3vector parent_centre; ///< parent centre
- C3vector angular_dir1; ///< main direction to measure angles
- C3vector angular_dir2; ///< second direction to measure angles (sign)
-};
-
-}
-
-#endif
Index: branches/spherical/siscone/siscone.cpp
===================================================================
--- branches/spherical/siscone/siscone.cpp (revision 241)
+++ branches/spherical/siscone/siscone.cpp (revision 242)
@@ -1,223 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-// File: siscone.cpp //
-// Description: source file for the main SISCone class //
-// This file is part of the SISCone project. //
-// WARNING: this is not the main SISCone trunk but //
-// an adaptation to spherical coordinates //
-// For more details, see http://projects.hepforge.org/siscone //
-// //
-// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
-// //
-// This program is free software; you can redistribute it and/or modify //
-// it under the terms of the GNU General Public License as published by //
-// the Free Software Foundation; either version 2 of the License, or //
-// (at your option) any later version. //
-// //
-// This program is distributed in the hope that it will be useful, //
-// but WITHOUT ANY WARRANTY; without even the implied warranty of //
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
-// GNU General Public License for more details. //
-// //
-// You should have received a copy of the GNU General Public License //
-// along with this program; if not, write to the Free Software //
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
-// //
-// $Revision:: $//
-// $Date:: $//
-///////////////////////////////////////////////////////////////////////////////
-
-#include "config.h"
-
-#include "ranlux.h"
-#include "momentum.h"
-#include "defines.h"
-#include "siscone.h"
-#include "siscone_error.h"
-#include <iostream>
-#include <sstream>
-#include <iomanip>
-
-namespace siscone{
-using namespace std;
-
-/***************************************************************
- * Csiscone implementation *
- * final class: gather everything to compute the jet contents. *
- * *
- * This is the class user should use. *
- * It computes the jet contents of a list of particles *
- * given a cone radius and a threshold for splitting/merging. *
- ***************************************************************/
-
-// default ctor
-//--------------
-Csiscone::Csiscone(){
- rerun_allowed = false;
-}
-
-// default dtor
-//--------------
-Csiscone::~Csiscone(){
- rerun_allowed = false;
-}
-
-bool Csiscone::init_done=false;
-
-/*
- * compute the jets from a given particle set doing multiple passes
- * such pass N looks for jets among all particles not put into jets
- * during previous passes.
- * - _particles list of particles
- * - _radius cone radius
- * - _f shared energy threshold for splitting&merging
- * - _n_pass_max maximum number of runs
- * - _Emin minimum energy of the protojets
- * - _split_merge_scale the scale choice for the split-merge procedure
- * NOTE: using pt leads to IR unsafety for some events with momentum
- * conservation. So we strongly advise not to change the default
- * value.
- * return the number of jets found.
- **********************************************************************/
-int Csiscone::compute_jets(vector<Cmomentum> &_particles, double _radius, double _f,
- int _n_pass_max, double _Emin,
- Esplit_merge_scale _split_merge_scale){
- // initialise random number generator
- if (!init_done){
- // initialise random number generator
- ranlux_init();
-
- // print the banner
- cout << "#ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo" << endl;
- cout << "# SISCone version " << setw(28) << left << siscone_version() << "o" << endl;
- cout << "# http://projects.hepforge.org/siscone o" << endl;
- cout << "# o" << endl;
- cout << "# This is SISCone: the Seedless Infrared Safe Cone Jet Algorithm o" << endl;
- cout << "# SISCone was written by Gavin Salam and Gregory Soyez o" << endl;
- cout << "# It is released under the terms of the GNU General Public License o" << endl;
- cout << "# o" << endl;
- cout << "# !!! WARNING !!! o" << endl;
- cout << "# This is the version of SISCone using spherical coordinates o" << endl;
- cout << "# o" << endl;
- cout << "# A description of the algorithm is available in the publication o" << endl;
- cout << "# JHEP 05 (2007) 086 [arXiv:0704.0292 (hep-ph)]. o" << endl;
- cout << "# Please cite it if you use SISCone. o" << endl;
- cout << "#ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo" << endl;
- cout << endl;
- // do not do this again
- init_done=true;
- }
-
- // run some general safety tests (NB: f will be checked in split-merge)
- if (_radius <= 0.0 || _radius >= 0.5*M_PI) {
- ostringstream message;
- message << "Illegal value for cone radius, R = " << _radius
- << " (legal values are 0<R<pi/2)";
- throw Csiscone_error(message.str());
- }
-
-
-
- ptcomparison.split_merge_scale = _split_merge_scale;
- partial_clear(); // make sure some things are initialised properly
-
- // init the split_merge algorithm with the initial list of particles
- // this initialises particle list p_left of remaining particles to deal with
- init_particles(_particles);
-
- bool finished = false;
-
- rerun_allowed = false;
- protocones_list.clear();
-
-#ifdef DEBUG_STABLE_CONES
- nb_hash_cones_total = 0;
- nb_hash_occupied_total = 0;
-#endif
-
- do{
- // initialise stable_cone finder
- // here we use the list of remaining particles
- // AFTER COLLINEAR CLUSTERING !!!!!!
- Cstable_cones::init(p_uncol_hard);
-
- // get stable cones
- if (get_stable_cones(_radius)){
- // we have some new protocones.
- // add them to candidates
- protocones_list.push_back(protocones);
- add_protocones(&protocones, R2, _Emin);
-#ifdef DEBUG_STABLE_CONES
- nb_hash_cones_total += nb_hash_cones;
- nb_hash_occupied_total += nb_hash_occupied;
-#endif
- } else {
- // no new protocone: leave
- finished=true;
- }
-
- _n_pass_max--;
- } while ((!finished) && (n_left>0) && (_n_pass_max!=0));
-
- rerun_allowed = true;
-
- // split & merge
- return perform(_f, _Emin);
-}
-
-/*
- * recompute the jets with a different overlap parameter.
- * we use the same particles and R as in the preceeding call.
- * - _f shared energy threshold for splitting&merging
- * - _Emin minimum Energy of the protojets
- * - _split_merge_scale the scale choice for the split-merge procedure
- * NOTE: using pt leads to IR unsafety for some events with momentum
- * conservation. So we strongly advise not to change the default
- * value.
- * return the number of jets found, -1 if recomputation not allowed.
- ********************************************************************/
-int Csiscone::recompute_jets(double _f, double _Emin,
- Esplit_merge_scale _split_merge_scale){
- if (!rerun_allowed)
- return -1;
-
- ptcomparison.split_merge_scale = _split_merge_scale;
-
- // restore particle list
- partial_clear();
- init_pleft();
-
- // initialise split/merge algorithm
- unsigned int i;
- for (i=0;i<protocones_list.size();i++)
- add_protocones(&(protocones_list[i]), R2, _Emin);
-
- // split & merge
- return perform(_f, _Emin);
-}
-
-
-// finally, a bunch of functions to access to
-// basic information (package name, version)
-//---------------------------------------------
-
-/*
- * return SISCone package name.
- * This is nothing but "SISCone", it is a replacement to the
- * PACKAGE_NAME string defined in config.h and which is not
- * public by default.
- * return the SISCone name as a string
- */
-string siscone_package_name(){
- return VERSION;
-}
-
-/*
- * return SISCone version number.
- * return a string of the form "X.Y.Z" with possible additional tag
- * (alpha, beta, devel) to mention stability status
- */
-string siscone_version(){
- return VERSION;
-}
-
-}
Index: branches/spherical/siscone/momentum.h
===================================================================
--- branches/spherical/siscone/momentum.h (revision 241)
+++ branches/spherical/siscone/momentum.h (revision 242)
@@ -1,312 +0,0 @@
-// -*- C++ -*-
-///////////////////////////////////////////////////////////////////////////////
-// File: momentum.h //
-// Description: header file for 4-momentum class Cmomentum //
-// This file is part of the SISCone project. //
-// WARNING: this is not the main SISCone trunk but //
-// an adaptation to spherical coordinates //
-// For more details, see http://projects.hepforge.org/siscone //
-// //
-// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
-// //
-// This program is free software; you can redistribute it and/or modify //
-// it under the terms of the GNU General Public License as published by //
-// the Free Software Foundation; either version 2 of the License, or //
-// (at your option) any later version. //
-// //
-// This program is distributed in the hope that it will be useful, //
-// but WITHOUT ANY WARRANTY; without even the implied warranty of //
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
-// GNU General Public License for more details. //
-// //
-// You should have received a copy of the GNU General Public License //
-// along with this program; if not, write to the Free Software //
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
-// //
-// $Revision:: $//
-// $Date:: $//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef __VECTOR_H__
-#define __VECTOR_H__
-
-#include <vector>
-#include <math.h>
-#include "reference.h"
-#include "geom_2d.h"
-#include "defines.h"
-
-namespace siscone{
-
-/**
- * \class C3vector
- * \brief base class for managing the spatial part of Cmomentum (defined after)
- *
- * This class contains the information for particle or group of
- * particles management.
- * It is adapted to use spherical geometry, where, for our purposes,
- * the only time-consuming operation we need is the computation of
- * the norm. To compute it once-and-for-all and store it in a local
- * variable, you should call the 'build_norm' method.
- * On top of that, the angle phi is computed from the x-axis
- * and theta from the "north pole".
- */
-class C3vector{
- public:
- /// default ctor
- C3vector();
-
- /// ctor with initialisation
- C3vector(double _px, double _py, double _pz);
-
- /// default dtor
- ~C3vector();
-
- /// assignment of vectors
- C3vector& operator = (const C3vector &v);
-
- /// addition of vectors
- /// WARNING= norm is not updated
- const C3vector operator + (const C3vector &v);
-
- /// subtraction of vectors
- /// WARNING= norm is not updated
- const C3vector operator - (const C3vector &v);
-
- /// division by a constant
- /// WARNING= norm is not updated
- const C3vector operator / (const double &r);
-
- /// incrementation of vectors
- /// WARNING= norm is not updated
- C3vector& operator += (const C3vector &v);
-
- /// decrementation of vectors
- /// WARNING= norm is not updated
- C3vector& operator -= (const C3vector &v);
-
- /// multiplication by a constant
- /// WARNING= norm is not updated
- C3vector& operator *= (const double &r);
-
- /// division by a constant
- /// WARNING= norm is not updated
- C3vector& operator /= (const double &r);
-
- /// computes pT
- inline double perp() const {return sqrt(perp2());}
-
- /// computes pT^2
- inline double perp2() const {return px*px+py*py;}
-
- /// 3-vect norm
- inline double norm() const {return sqrt(px*px+py*py+pz*pz);}
-
- /// 3-vect norm squared
- inline double norm2() const {return px*px+py*py+pz*pz;}
-
- /// 3-vect azimuthal angle
- inline double phi() const {return atan2(py, px);}
-
- /// 3-vect polar angle
- inline double theta() const {return atan2(perp(),pz);}
-
- /// build the spatial normfrom 4-momentum info
- /// !!! WARNING !!!
- /// !!! computing the norm is the only time-consuming !!!
- /// !!! information we need in all computations. !!!
- /// !!! use this whenever you need repeated access !!!
- /// !!! to the norm to store it in the local variable !!!
- void build_norm();
-
- /// just a useful tool to store theta and phi
- /// locally (in _theta and _phi) in case you need
- /// repeated access
- void build_thetaphi();
-
- /// for this direction, compute the two reference directions
- /// used to measure angles
- void get_angular_directions(C3vector &angular_dir1, C3vector &angular_dir2);
-
- double px; ///< x-momentum
- double py; ///< y-momentum
- double pz; ///< z-momentum
-
- double _norm; ///< particle spatial norm (available ONLY after a call to build_norm)
- double _theta; ///< particle theta angle (available ONLY after a call to build_thetaphi)
- double _phi; ///< particle phi angle (available ONLY after a call to build_thetaphi)
-
- //////////////////////////////////////////////
- // the following part is used for checksums //
- //////////////////////////////////////////////
- Creference ref; ///< reference number for the vector
-};
-
-/**
- * \class Cmomentum
- * \brief base class for dynamic coordinates management
- *
- * This class contains the information for particle or group of
- * particles management.
- * It is adapted to use spherical geometry, where, for our purposes,
- * the only time-consuming operation we need is the computation of
- * the norm. To compute it once-and-for-all and store it in a local
- * variable, you should call the 'build_norm' method.
- * On top of that, the angle phi is computed from the x-axis
- * and theta from the "north pole".
- */
-class Cmomentum : public C3vector{
- public:
- /// default ctor
- Cmomentum();
-
- /// init from a 3-vect
- Cmomentum(C3vector &init, double E=0.0);
-
- /// ctor with initialisation
- Cmomentum(double _px, double _py, double _pz, double _E);
-
- /// ctor with detailed initialisation
- //Cmomentum(double _eta, double _phi, Creference _ref);
-
- /// default dtor
- ~Cmomentum();
-
- /// computes m
- inline double mass() const {return sqrt(mass2());}
-
- /// computes m^2
- inline double mass2() const {return perpmass2()-perp2();}
-
- /// transverse mass, mt = sqrt(pt^2+m^2) = sqrt(E^2 - pz^2)
- inline double perpmass() const {return sqrt((E-pz)*(E+pz));}
-
- /// transverse mass squared, mt^2 = pt^2+m^2 = E^2 - pz^2
- inline double perpmass2() const {return (E-pz)*(E+pz);}
-
- /// computes transverse energy
- inline double Et() const {return E/sqrt(1.0+pz*pz/perp2());}
-
- /// computes transverse energy (squared)
- inline double Et2() const {return E*E/(1.0+pz*pz/perp2());}
-
- /// assignment of vectors
- Cmomentum& operator = (const Cmomentum &v);
-
- /// addition of vectors
- /// !!! WARNING !!! no updating of eta and phi !!!
- const Cmomentum operator + (const Cmomentum &v);
-
- /// incrementation of vectors
- /// !!! WARNING !!! no updating of eta and phi !!!
- Cmomentum& operator += (const Cmomentum &v);
-
- /// decrementation of vectors
- /// !!! WARNING !!! no updating of eta and phi !!!
- Cmomentum& operator -= (const Cmomentum &v);
-
- double E; ///< energy
-
- int parent_index; ///< particle number in the parent list
- int index; ///< internal particle number
-};
-
-/// ordering of two vectors
-/// this is by default done w.r.t. their references
-bool operator < (const Cmomentum &v1, const Cmomentum &v2);
-
-/// ordering of vectors in eta (e.g. used in collinear tests)
-bool momentum_theta_less(const Cmomentum &v1, const Cmomentum &v2);
-
-/// ordering of vectors in pt
-bool momentum_pt_less(const Cmomentum &v1, const Cmomentum &v2);
-
-
-//////////////////////////
-// some handy utilities //
-//////////////////////////
-
-/// square
-inline double sqr(double x){return x*x;}
-
-/// dot product for te spatial 3-vect
-/// \param v1 first 4-vect
-/// \param v2 second 4-vect
-inline double dot_product3(const C3vector &v1, const C3vector &v2){
- //double tmp = v1.px*v2.px + v1.py*v2.py + v1.pz*v2.pz;
- //if (!isfinite(tmp)){
- // std::cout << "dot_product inf: " << std::endl;
- // std::cout << " angles: " << v1._theta << " " << v1._phi << " and " << v2._theta << " " << v2._phi << std::endl;
- // std::cout << " moms : " << v1.px << " " << v1.py << " " << v1.pz
- // << " and " << v2.px << " " << v2.py << " " << v2.pz << std::endl;
- //}
- return v1.px*v2.px + v1.py*v2.py + v1.pz*v2.pz;
-}
-
-/// cross product for the spatial 3-vect
-/// \param v1 first 4-vect
-/// \param v2 second 4-vect
-inline C3vector cross_product3(const C3vector &v1, const C3vector &v2){
- //C3vector tmp;
- //tmp.px = v1.py*v2.pz-v1.pz*v2.py;
- //tmp.py = v1.pz*v2.px-v1.px*v2.pz;
- //tmp.pz = v1.px*v2.py-v1.py*v2.px;
- //return tmp;
- return C3vector(v1.py*v2.pz-v1.pz*v2.py,
- v1.pz*v2.px-v1.px*v2.pz,
- v1.px*v2.py-v1.py*v2.px);
-}
-
-/// squared norm of the cross product for the spatial 3-vect (energy is set to 0)
-/// \param v1 first 4-vect
-/// \param v2 second 4-vect
-inline double norm2_cross_product3(const C3vector &v1, const C3vector &v2){
- return sqr(v1.py*v2.pz-v1.pz*v2.py) + sqr(v1.pz*v2.px-v1.px*v2.pz) + sqr(v1.px*v2.py-v1.py*v2.px);
-}
-
-/// get tangent squared of the spherical distance between to vectors
-/// \param v1 vector defining the first point
-/// \param v2 vector defining the second point
-inline double get_tan2_distance(const Cmomentum &v1, const Cmomentum &v2){
- return norm2_cross_product3(v1,v2)/sqr(dot_product3(v1,v2));
-}
-
-/// get spherical distance between to vectors
-/// \param v1 vector defining the first point
-/// \param v2 vector defining the second point
-inline double get_distance(const C3vector *v1, const C3vector *v2){
- return atan2(sqrt(norm2_cross_product3(*v1,*v2)), dot_product3(*v1,*v2));
-}
-
-/// return true if the two points are distant by less than get spherical distance between to vectors
-/// \param v1 vector defining the first point
-/// \param v2 vector defining the second point
-/// \param tan2R tangent squared of the max distance
-/// WARNING: using the tangent here is dangerous for R>pi/2.
-/// this never happens per se for "regular R" but
-/// it may in the vicinity computation as we're using
-/// 2R there.
-inline bool is_closer(const C3vector *v1, const C3vector *v2, const double tan2R){
- double dot = dot_product3(*v1,*v2);
- return (dot>=0) && (norm2_cross_product3(*v1,*v2)<=tan2R*dot*dot);
-}
-
-/// return true if the two points are distant by less than get spherical distance between to vectors
-/// \param v1 vector defining the first point
-/// \param v2 vector defining the second point
-/// \param tan2R tangent squared of the max distance
-/// safer version but computes the norm
-inline bool is_closer_safer(const C3vector *v1, const C3vector *v2, const double cosR){
- return dot_product3(*v1,*v2)>=cosR*sqrt(v1->norm2()*v2->norm2());
- //double dot = dot_product3(*v1,*v2);
- //return (dot>=0) && (norm2_cross_product3(*v1,*v2)<tan2R*dot*dot);
-}
-
-/// multiply a vector by a constant
-/// WARNING: norm not updated
-inline C3vector operator * (const double &r, const C3vector &v){
- C3vector tmp = v;
- return tmp*=r;
-}
-}
-#endif
Index: branches/spherical/siscone/siscone.h
===================================================================
--- branches/spherical/siscone/siscone.h (revision 241)
+++ branches/spherical/siscone/siscone.h (revision 242)
@@ -1,135 +0,0 @@
-// -*- C++ -*-
-///////////////////////////////////////////////////////////////////////////////
-// File: siscone.h //
-// Description: header file for the main SISCone class //
-// This file is part of the SISCone project. //
-// WARNING: this is not the main SISCone trunk but //
-// an adaptation to spherical coordinates //
-// For more details, see http://projects.hepforge.org/siscone //
-// //
-// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
-// //
-// This program is free software; you can redistribute it and/or modify //
-// it under the terms of the GNU General Public License as published by //
-// the Free Software Foundation; either version 2 of the License, or //
-// (at your option) any later version. //
-// //
-// This program is distributed in the hope that it will be useful, //
-// but WITHOUT ANY WARRANTY; without even the implied warranty of //
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
-// GNU General Public License for more details. //
-// //
-// You should have received a copy of the GNU General Public License //
-// along with this program; if not, write to the Free Software //
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
-// //
-// $Revision:: $//
-// $Date:: $//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef __SISCONE_H__
-#define __SISCONE_H__
-
-#include "protocones.h"
-#include "split_merge.h"
-
-namespace siscone{
-
-/**
- * \class Csiscone
- * final class: gather everything to compute the jet contents.
- *
- * This is the class user should use.
- * It computes the jet contents of a list of particles
- * given a cone radius and a threshold for splitting/merging.
- *
- * After the call to 'perform', the vector jets is filled with
- * the jets found. the 'contents' field of each jets contains
- * the indices of the particles included in that jet.
- */
-class Csiscone : public Cstable_cones, public Csplit_merge{
- public:
- /// default ctor
- Csiscone();
-
- /// default dtor
- ~Csiscone();
-
- /**
- * compute the jets from a given particle set.
- * We are doing multiple passes such pass n_pass looks for jets among
- * all particles not put into jets during previous passes.
- * By default the number of passes is infinite (0).
- * \param _particles list of particles
- * \param _radius cone radius
- * \param _f shared energy threshold for splitting&merging
- * \param _n_pass_max maximum number of passes (0=full search)
- * \param _Emin minimum energy of the protojets
- * \param _split_merge_scale the scale choice for the split-merge procedure
- * NOTE: SM_pt leads to IR unsafety for some events with momentum conservation.
- * SM_Et is IR safe but not boost invariant and not implemented(!)
- * SM_mt is IR safe for hadronic events, but not for decays of two
- * back-to-back particles of identical mass
- * SM_pttilde
- * is always IR safe, and also boost invariant
- * SM_E
- * For spherical coords, this is the natural choice (default)
- *
- * \return the number of jets found.
- */
- int compute_jets(std::vector<Cmomentum> &_particles, double _radius, double _f,
- int _n_pass_max=0, double _Emin=0.0,
- Esplit_merge_scale _split_merge_scale=SM_E);
-
- /**
- * recompute the jets with a different overlap parameter.
- * we use the same particles and R as in the preceeding call.
- * \param _f shared energy threshold for splitting&merging
- * \param _Emin minimum energy of the protojets
- * \param _split_merge_scale the scale choice for the split-merge procedure
- * split--merge variable
- * NOTE: using pt leads to IR unsafety for some events with momentum
- * conservation. So we strongly advise not to change the default
- * value.
- * \return the number of jets found, -1 if recomputation not allowed.
- */
- int recompute_jets(double _f, double _Emin = 0.0,
- Esplit_merge_scale _split_merge_scale=SM_E);
-
- /// list of protocones found pass-by-pass
- std::vector<std::vector<Cmomentum> > protocones_list;
-
- // random number initialisation
- static bool init_done; ///< check random generator initialisation
-
-#ifdef DEBUG_STABLE_CONES
- int nb_hash_cones_total, nb_hash_occupied_total;
-#endif
-
- private:
- bool rerun_allowed; ///< is recompute_jets allowed ?
-};
-
-
-// finally, a bunch of functions to access to
-// basic information (package name, version)
-//---------------------------------------------
-
-/**
- * return SISCone package name.
- * This is nothing but "SISCone", it is a replacement to the
- * PACKAGE_NAME string defined in config.h and which is not
- * public by default.
- * \return the SISCone name as a string
- */
-std::string siscone_package_name();
-
-/**
- * return SISCone version number.
- * \return a string of the form "X.Y.Z" with possible additional tag
- * (alpha, beta, devel) to mention stability status
- */
-std::string siscone_version();
-
-}
-#endif
Index: branches/spherical/siscone/split_merge.cpp
===================================================================
--- branches/spherical/siscone/split_merge.cpp (revision 241)
+++ branches/spherical/siscone/split_merge.cpp (revision 242)
@@ -1,1016 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-// File: split_merge.cpp //
-// Description: source file for splitting/merging (contains the CJet class) //
-// This file is part of the SISCone project. //
-// WARNING: this is not the main SISCone trunk but //
-// an adaptation to spherical coordinates //
-// For more details, see http://projects.hepforge.org/siscone //
-// //
-// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
-// //
-// This program is free software; you can redistribute it and/or modify //
-// it under the terms of the GNU General Public License as published by //
-// the Free Software Foundation; either version 2 of the License, or //
-// (at your option) any later version. //
-// //
-// This program is distributed in the hope that it will be useful, //
-// but WITHOUT ANY WARRANTY; without even the implied warranty of //
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
-// GNU General Public License for more details. //
-// //
-// You should have received a copy of the GNU General Public License //
-// along with this program; if not, write to the Free Software //
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
-// //
-// $Revision:: $//
-// $Date:: $//
-///////////////////////////////////////////////////////////////////////////////
-
-#include "split_merge.h"
-#include "siscone_error.h"
-#include "momentum.h"
-#include <math.h>
-#include <limits> // for max
-#include <iostream>
-#include <algorithm>
-#include <sstream>
-#include <cassert>
-
-namespace siscone{
-
-using namespace std;
-
-/********************************************************
- * class Cjet implementation *
- * real Jet information. *
- * This class contains information for one single jet. *
- * That is, first, its momentum carrying information *
- * about its centre and pT, and second, its particle *
- * contents *
- ********************************************************/
-// default ctor
-//--------------
-Cjet::Cjet(){
- n = 0;
- v = Cmomentum();
- pt_tilde = 0.0;
- sm_var2 = 0.0;
-}
-
-// default dtor
-//--------------
-Cjet::~Cjet(){
-
-}
-
-// ordering of jets in pt
-//------------------------
-bool jets_pt_less(const Cjet &j1, const Cjet &j2){
- return j1.v.perp2() > j2.v.perp2();
-}
-
-// ordering of jets in E (e.g. used in final jets ordering)
-//----------------------------------------------------------
-bool jets_E_less(const Cjet &j1, const Cjet &j2){
- return j1.v.E > j2.v.E;
-}
-
-
-/********************************************************
- * Csplit_merge_ptcomparison implementation *
- * This deals with the ordering of the jets candidates *
- ********************************************************/
-
-// odering of two jets
-// The variable of the ordering is pt or mt
-// depending on 'split_merge_scale' choice
-//
-// with EPSILON_SPLITMERGE defined, this attempts to identify
-// delicate cases where two jets have identical momenta except for
-// softish particles -- the difference of pt's may not be correctly
-// identified normally and so lead to problems for the fate of the
-// softish particle.
-//
-// NB: there is a potential issue in momentum-conserving events,
-// whereby the harder of two jets becomes ill-defined when a soft
-// particle is emitted --- this may have a knock-on effect on
-// subsequent split-merge steps in cases with sufficiently large R
-// (but we don't know what the limit is...)
-//------------------------------------------------------------------
-bool Csplit_merge_ptcomparison::operator ()(const Cjet &jet1, const Cjet &jet2) const{
- double q1, q2;
-
- // compute the value for comparison for both jets
- // This depends on the choice of variable (mt is the default)
- q1 = jet1.sm_var2;
- q2 = jet2.sm_var2;
-
- bool res = q1 > q2;
-
- // if we enable the refined version of the comparison (see defines.h),
- // we compute the difference more precisely when the two jets are very
- // close in the ordering variable.
-#ifdef EPSILON_SPLITMERGE
- if ( (fabs(q1-q2) < EPSILON_SPLITMERGE*max(q1,q2)) &&
- (jet1.v.ref != jet2.v.ref) ) {
- // get the momentum of the difference
- Cmomentum difference;
- double pt_tilde_difference;
- get_difference(jet1,jet2,&difference,&pt_tilde_difference);
-
- // use the following relation: pt1^2 - pt2^2 = (pt1+pt2)*(pt1-pt2)
- double qdiff;
- Cmomentum sum = jet1.v ;
- sum += jet2.v;
- double pt_tilde_sum = jet1.pt_tilde + jet2.pt_tilde;
-
- // depending on the choice of ordering variable, set the result
- switch (split_merge_scale){
- case SM_mt:
- qdiff = sum.E*difference.E - sum.pz*difference.pz;
- break;
- case SM_pt:
- qdiff = sum.px*difference.px + sum.py*difference.py;
- break;
- case SM_pttilde:
- qdiff = pt_tilde_sum*pt_tilde_difference;
- break;
- case SM_E:
- qdiff = sum.E*difference.E;
- break;
- case SM_Et:
- // diff = E^2 (dpt^2 pz^2- pt^2 dpz^2)
- // + dE^2 (pt^2+pz^2) pt2^2
- // where, unless explicitely specified the variables
- // refer to the first jet or differences jet1-jet2.
- qdiff = jet1.v.E*jet1.v.E*
- ((sum.px*difference.px + sum.py*difference.py)*jet1.v.pz*jet1.v.pz
- -jet1.v.perp2()*sum.pz*difference.pz)
- +sum.E*difference.E*(jet1.v.perp2()+jet1.v.pz*jet1.v.pz)*jet2.v.perp2();
- break;
- default:
- throw Csiscone_error("Unsupported split-merge scale choice: "
- + SM_scale_name());
- }
- res = qdiff > 0;
- }
-#endif // EPSILON_SPLITMERGE
-
- return res;
-}
-
-
-/// return a name for the sm scale choice
-/// NB: used internally and also by fastjet
-std::string split_merge_scale_name(Esplit_merge_scale sms) {
- switch(sms) {
- case SM_pt:
- return "pt (IR unsafe)";
- case SM_Et:
- return "Et (boost dep.)";
- case SM_E:
- return "E (boost dep.)";
- case SM_mt:
- return "mt (IR safe except for pairs of identical decayed heavy particles)";
- case SM_pttilde:
- return "pttilde (scalar sum of pt's)";
- default:
- return "[SM scale without a name]";
- }
-}
-
-
-// get the difference between 2 jets
-// - j1 first jet
-// - j2 second jet
-// - v jet1-jet2
-// - pt_tilde jet1-jet2 pt_tilde
-// return true if overlapping, false if disjoint
-//-----------------------------------------------
-void Csplit_merge_ptcomparison::get_difference(const Cjet &j1, const Cjet &j2, Cmomentum *v, double *pt_tilde) const {
- int i1,i2;
-
- // initialise
- i1=i2=0;
- *v = Cmomentum();
- *pt_tilde = 0.0;
-
- // compute overlap
- // at the same time, we store union in indices
- do{
- if (j1.contents[i1]==j2.contents[i2]) {
- i1++;
- i2++;
- } else if (j1.contents[i1]<j2.contents[i2]){
- (*v) += (*particles)[j1.contents[i1]];
- (*pt_tilde) += (*pt)[j1.contents[i1]];
- i1++;
- } else if (j1.contents[i1]>j2.contents[i2]){
- (*v) -= (*particles)[j2.contents[i2]];
- (*pt_tilde) -= (*pt)[j2.contents[i2]];
- i2++;
- } else {
- throw Csiscone_error("get_non_overlap reached part it should never have seen...");
- }
- } while ((i1<j1.n) && (i2<j2.n));
-
- // deal with particles at the end of the list...
- while (i1 < j1.n) {
- (*v) += (*particles)[j1.contents[i1]];
- (*pt_tilde) += (*pt)[j1.contents[i1]];
- i1++;
- }
- while (i2 < j2.n) {
- (*v) -= (*particles)[j2.contents[i2]];
- (*pt_tilde) -= (*pt)[j2.contents[i2]];
- i2++;
- }
-}
-
-
-/********************************************************
- * class Csplit_merge implementation *
- * Class used to split and merge jets. *
- ********************************************************/
-// default ctor
-//--------------
-Csplit_merge::Csplit_merge(){
- merge_identical_protocones = false;
-#ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
-#ifdef MERGE_IDENTICAL_PROTOCONES_DEFAULT_TRUE
- merge_identical_protocones = true;
-#endif
-#endif
- indices = NULL;
-
- // ensure that ptcomparison points to our set of particles (though params not correct)
- ptcomparison.particles = &particles;
- ptcomparison.pt = &pt;
- candidates.reset(new multiset<Cjet,Csplit_merge_ptcomparison>(ptcomparison));
-
- // no hardest cut (col-unsafe)
- SM_var2_hardest_cut_off = -1.0;
-
- // no pt cutoff for the particles to put in p_uncol_hard
- stable_cone_soft_pt2_cutoff = -1.0;
-
- // no pt-weighted splitting
- use_E_weighted_splitting = false;
-}
-
-
-// default dtor
-//--------------
-Csplit_merge::~Csplit_merge(){
- full_clear();
-}
-
-
-// initialisation function
-// - _particles list of particles
-// - protocones list of protocones (initial jet candidates)
-// - R2 cone radius (squared)
-// - Emin minimal energy allowed for jets
-//-------------------------------------------------------------
-int Csplit_merge::init(vector<Cmomentum> &_particles, vector<Cmomentum> *protocones, double R2, double Emin){
- // browse protocones
- return add_protocones(protocones, R2, Emin);
-}
-
-
-// initialisation function for particle list
-// - _particles list of particles
-//-------------------------------------------------------------
-int Csplit_merge::init_particles(vector<Cmomentum> &_particles){
- full_clear();
-
- // compute the list of particles
- // here, we do not need to throw away particles
- // with infinite rapidity (colinear with the beam)
- particles = _particles;
- n = particles.size();
-
- // build the vector of particles' pt and determine min,max eta
- pt.resize(n);
- for (int i=0;i<n;i++){
- pt[i] = particles[i].perp();
- }
-
- // ensure that ptcomparison points to our set of particles (though params not correct)
- ptcomparison.particles = &particles;
- ptcomparison.pt = &pt;
-
- // set up the list of particles left.
- init_pleft();
-
- indices = new int[n];
-
- return 0;
-}
-
-
-// build initial list of remaining particles
-//------------------------------------------
-int Csplit_merge::init_pleft(){
- // at this level, we only rule out particles with
- // infinite rapidity
- // in the parent particle list, index contain the run
- // at which particles are puts in jets:
- // - -1 means infinity rapidity
- // - 0 means not included
- // - i mean included at run i
- int i,j;
-
- // copy particles removing the ones with infinite rapidity
- j=0;
- p_remain.clear();
- for (i=0;i<n;i++){
- // set ref for checkxor
- particles[i].ref.randomize();
-
- //REMOVED: check if rapidity is not infinite or ill-defined
- //if (fabs(particles[i].pz) < (particles[i].E)){
- p_remain.push_back(particles[i]);
- // set up parent index for tracability
- p_remain[j].parent_index = i;
- // left particles are marked with a 1
- // IMPORTANT NOTE: the meaning of index in p_remain is
- // somehow different as in the initial particle list.
- // here, within one pass, we use the index to track whether
- // a particle is included in the current pass (index set to 0
- // in add_protocones) or still remain (index still 1)
- p_remain[j].index = 1;
-
- j++;
- // set up parent-particle index
- particles[i].index = 0;
- //} else {
- // particles[i].index = -1;
- //}
- }
- n_left = p_remain.size();
- n_pass = 0;
-
- merge_collinear_and_remove_soft();
-
- return 0;
-}
-
-
-// partial clearance
-// we want to keep particle list and indices
-// for future usage, so do not clear it !
-// this is done in full_clear
-//----------------------------------------
-int Csplit_merge::partial_clear(){
- // release jets
-
- // set up the auto_ptr for the multiset with the _current_ state of
- // ptcomparison (which may have changed since we constructed the
- // class)
- candidates.reset(new multiset<Cjet,Csplit_merge_ptcomparison>(ptcomparison));
-
- // start off with huge number
- most_ambiguous_split = numeric_limits<double>::max();
-
- jets.clear();
-#ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
- if (merge_identical_protocones)
- cand_refs.clear();
-#endif
-
- p_remain.clear();
-
- return 0;
-}
-
-
-// full clearance
-//----------------
-int Csplit_merge::full_clear(){
- partial_clear();
-
- // clear previously allocated memory
- if (indices != NULL){
- delete[] indices;
- }
- particles.clear();
-
- return 0;
-}
-
-
-// build the list 'p_uncol_hard' from p_remain by clustering collinear particles
-// note that thins in only used for stable-cone detection
-// so the parent_index field is unnecessary
-//-------------------------------------------------------------------------
-int Csplit_merge::merge_collinear_and_remove_soft(){
- int i,j;
- vector<Cmomentum> p_sorted;
- bool collinear;
- double dphi;
-
- p_uncol_hard.clear();
-
- // we first sort the particles according to their theta angle
- for (i=0;i<n_left;i++)
- p_sorted.push_back(p_remain[i]);
- sort(p_sorted.begin(), p_sorted.end(), momentum_theta_less);
-
- // then we cluster particles looping over the particles in the following way
- // if (a particle i has same eta-phi a one after (j))
- // then add momentum i to j
- // else add i to the p_uncol_hard list
- i = 0;
- while (i<n_left){
- //REMOVED: // check if the particle passes the stable_cone_soft_pt2_cutoff
- //REMOVED: if (p_sorted[i].perp2()<stable_cone_soft_pt2_cutoff) {
- //REMOVED: i++;
- //REMOVED: continue;
- //REMOVED: }
-
- // check if there is(are) particle(s) with the 'same' theta
- collinear = false;
- j=i+1;
- while ((j<n_left) && (fabs(p_sorted[j]._theta-p_sorted[i]._theta)<EPSILON_COLLINEAR) && (!collinear)){
- dphi = fabs(p_sorted[j]._phi-p_sorted[i]._phi);
- if (dphi>M_PI) dphi = twopi-dphi;
- if (dphi<EPSILON_COLLINEAR){
- // i is collinear with j; add the momentum (i) to the momentum (j)
-#ifdef DEBUG_SPLIT_MERGE
- cout << "# collinear merging at point " << p_sorted[i]._theta << ", " << p_sorted[j]._phi << endl;
-#endif
- p_sorted[j] += p_sorted[i];
- //p_sorted[j].build_thetaphi();
- p_sorted[j].build_norm();
- // set collinearity test to true
- collinear = true;
- }
- j++;
- }
- // if no collinearity detected, add the particle to our list
- if (!collinear)
- p_uncol_hard.push_back(p_sorted[i]);
- i++;
- }
-
- return 0;
-}
-
-
-// add a list of protocones
-// - protocones list of protocones (initial jet candidates)
-// - R2 cone radius (squared)
-// - Emin minimal energy allowed for jets
-//-------------------------------------------------------------
-int Csplit_merge::add_protocones(vector<Cmomentum> *protocones, double R2, double Emin){
- int i;
- Cmomentum *c;
- Cmomentum *v;
- double tan2R;
- Cjet jet;
-
- if (protocones->size()==0)
- return 1;
-
- E_min = Emin;
- double R = sqrt(R2);
- tan2R = tan(R);
- tan2R *= tan2R;
-
-#ifdef DEBUG_SPLIT_MERGE
- cout << "particle list: ";
- for (int i2=0;i2<n_left;i2++)
- cout << p_remain[i2].parent_index << " "
- << p_remain[i2].px << " " << p_remain[i2].py << " "
- << p_remain[i2].pz << " " << p_remain[i2].E << endl;
- cout << endl;
-#endif
-
- // browse protocones
- // for each of them, build the list of particles in them
- for (vector<Cmomentum>::iterator p_it = protocones->begin();p_it != protocones->end();p_it++){
- // initialise variables
- c = &(*p_it);
-
- // browse particles to create cone contents
- // note that jet is always initialised with default values at this level
- jet.v = Cmomentum();
- jet.pt_tilde=0;
- jet.contents.clear();
- for (i=0;i<n_left;i++){
- v = &(p_remain[i]);
- if (is_closer(v, c, tan2R)){
- jet.contents.push_back(v->parent_index);
- jet.v+= *v;
- jet.pt_tilde+= pt[v->parent_index];
- v->index=0;
- }
- }
- jet.n=jet.contents.size();
-
- // set the momentum in protocones
- // (it was only known through its spatial coordinates up to now)
- *c = jet.v;
- c->build_thetaphi();
-
- // set the jet range
- jet.range=Ctheta_phi_range(c->_theta,c->_phi,R);
-
-#ifdef DEBUG_SPLIT_MERGE
- cout << "adding protojet: ";
- for (int i2=0;i2<jet.n;i2++)
- cout << jet.contents[i2] << " ";
- cout << endl;
-#endif
-
- // add it to the list of jets
- insert(jet);
- }
-
- // update list of included particles
- n_pass++;
-
-#ifdef DEBUG_SPLIT_MERGE
- cout << "remaining particles: ";
-#endif
- int j=0;
- for (i=0;i<n_left;i++){
- if (p_remain[i].index){
- // copy particle
- p_remain[j]=p_remain[i];
- p_remain[j].parent_index = p_remain[i].parent_index;
- p_remain[j].index=1;
- // set run in initial list
- particles[p_remain[j].parent_index].index = n_pass;
-#ifdef DEBUG_SPLIT_MERGE
- cout << p_remain[j].parent_index << " ";
-#endif
- j++;
- }
- }
-#ifdef DEBUG_SPLIT_MERGE
- cout << endl;
-#endif
- n_left = j;
- p_remain.resize(j);
-
- merge_collinear_and_remove_soft();
-
- return 0;
-}
-
-
-/*
- * really do the splitting and merging
- * At the end, the vector jets is filled with the jets found.
- * the 'contents' field of each jets contains the indices
- * of the particles included in that jet.
- * - overlap_tshold threshold for splitting/merging transition
- * - Emin minimal energy allowed for jets
- * return the number of jets is returned
- ******************************************************************/
-int Csplit_merge::perform(double overlap_tshold, double Emin){
- // iterators for the 2 jets
- cjet_iterator j1;
- cjet_iterator j2;
-
- E_min = Emin;
-
- if (candidates->size()==0)
- return 0;
-
- if (overlap_tshold>=1.0 || overlap_tshold <= 0) {
- ostringstream message;
- message << "Illegal value for overlap_tshold, f = " << overlap_tshold;
- message << " (legal values are 0<f<1)";
- throw Csiscone_error(message.str());
- }
-
- // overlap (the contents of this variable depends on the choice for
- // the split--merge variable.)
- // Note that the square of the ovelap is used
- double overlap2;
-
- // avoid to compute tshold*tshold at each overlap
- double overlap_tshold2 = overlap_tshold*overlap_tshold;
-
- do{
- if (candidates->size()>0){
- // browse for the first jet
- j1 = candidates->begin();
-
- // if hardest jet does not pass threshold then nothing else will
- // either so one stops the split merge.
- if (j1->sm_var2<SM_var2_hardest_cut_off) {break;}
-
- // browse for the second jet
- j2 = j1;
- j2++;
- int j2_relindex = 1; // used only in ifdef, but costs little so keep it outside
-
- while (j2 != candidates->end()){
-#ifdef DEBUG_SPLIT_MERGE
- show();
-#endif
- // check overlapping
- if (get_overlap(*j1, *j2, &overlap2)){
- // check if overlapping energy passes threshold
- // Note that this depends on the ordering variable
-#ifdef DEBUG_SPLIT_MERGE
- cout << "overlap between cdt 1 and cdt " << j2_relindex+1 << " with overlap "
- << sqrt(overlap2/j2->sm_var2) << endl<<endl;
-#endif
- if (overlap2<overlap_tshold2*j2->sm_var2){
- // split jets
- split(j1, j2);
-
- // update iterators
- j2 = j1 = candidates->begin();
- j2_relindex = 0;
- } else {
- // merge jets
- merge(j1, j2);
-
- // update iterators
- j2 = j1 = candidates->begin();
- j2_relindex = 0;
- }
- }
- // watch out: split/merge might have caused new jets with E <
- // Emin to disappear, so the total number of jets may
- // have changed by more than expected and j2 might already by
- // the end of the candidates list...
- j2_relindex++;
- if (j2 != candidates->end()) j2++;
- } // end of loop on the second jet
-
- if (j1 != candidates->end()) {
- // all "second jet" passed without overlapping
- // (otherwise we won't leave the j2 loop)
- // => store jet 1 as real jet
- jets.push_back(*j1);
- jets[jets.size()-1].v.build_thetaphi();
- jets[jets.size()-1].v.build_norm();
- // a bug where the contents has non-zero size has been cropping
- // up in many contexts -- so catch it!
- assert(j1->contents.size() > 0);
- jets[jets.size()-1].pass = particles[j1->contents[0]].index;
-#ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
- cand_refs.erase(j1->v.ref);
-#endif
- candidates->erase(j1);
- }
- }
- } while (candidates->size()>0);
-
- // sort jets by Energy
- sort(jets.begin(), jets.end(), jets_E_less);
-#ifdef DEBUG_SPLIT_MERGE
- show();
-#endif
-
- return jets.size();
-}
-
-
-
-// save the event on disk
-// - flux stream used to save jet contents
-//--------------------------------------------
-int Csplit_merge::save_contents(FILE *flux){
- jet_iterator it_j;
- Cjet *j1;
- int i1, i2;
-
- fprintf(flux, "# %d jets found\n", (int) jets.size());
- fprintf(flux, "# columns are: px, py, pz, E and number of particles for each jet\n");
- for (it_j = jets.begin(), i1=0 ; it_j != jets.end() ; it_j++, i1++){
- j1 = &(*it_j);
- fprintf(flux, "%le\t%le\t%le\t%le\t%d\n",
- j1->v.px, j1->v.py, j1->v.pz, j1->v.E, j1->n);
- }
-
- fprintf(flux, "# jet contents\n");
- fprintf(flux, "# columns are: px, py, pz, E, particle index and jet number\n");
- for (it_j = jets.begin(), i1=0 ; it_j != jets.end() ; it_j++, i1++){
- j1 = &(*it_j);
- for (i2=0;i2<j1->n;i2++)
- fprintf(flux, "%le\t%le\t%le\t%le\t%d\t%d\n",
- particles[j1->contents[i2]].px, particles[j1->contents[i2]].py,
- particles[j1->contents[i2]].pz, particles[j1->contents[i2]].E,
- j1->contents[i2], i1);
- }
-
- return 0;
-}
-
-
-// show current jets/candidate status
-//------------------------------------
-int Csplit_merge::show(){
- jet_iterator it_j;
- cjet_iterator it_c;
- Cjet *j;
- const Cjet *c;
- int i1, i2;
-
- for (it_j = jets.begin(), i1=0 ; it_j != jets.end() ; it_j++, i1++){
- j = &(*it_j);
- fprintf(stdout, "jet %2d: %le\t%le\t%le\t%le\t", i1+1,
- j->v.px, j->v.py, j->v.pz, j->v.E);
- for (i2=0;i2<j->n;i2++)
- fprintf(stdout, "%d ", j->contents[i2]);
- fprintf(stdout, "\n");
- }
-
- for (it_c = candidates->begin(), i1=0 ; it_c != candidates->end() ; it_c++, i1++){
- c = &(*it_c);
- fprintf(stdout, "cdt %2d: %le\t%le\t%le\t%le\t%le\t", i1+1,
- c->v.px, c->v.py, c->v.pz, c->v.E, sqrt(c->sm_var2));
- for (i2=0;i2<c->n;i2++)
- fprintf(stdout, "%d ", c->contents[i2]);
- fprintf(stdout, "\n");
- }
-
- fprintf(stdout, "\n");
- return 0;
-}
-
-
-// get the overlap between 2 jets
-// - j1 first jet
-// - j2 second jet
-// - overlap2 returned overlap^2 (determined by the choice of SM variable)
-// return true if overlapping, false if disjoint
-//---------------------------------------------------------------------
-bool Csplit_merge::get_overlap(const Cjet &j1, const Cjet &j2, double *overlap2){
- // check if ranges overlap
- if (!is_range_overlap(j1.range,j2.range))
- return false;
-
- int i1,i2;
- bool is_overlap;
-
- // initialise
- i1=i2=idx_size=0;
- is_overlap = false;
- Cmomentum v;
- double pt_tilde=0.0;
-
- // compute overlap
- // at the same time, we store union in indices
- do{
- if (j1.contents[i1]<j2.contents[i2]){
- indices[idx_size] = j1.contents[i1];
- i1++;
- } else if (j1.contents[i1]>j2.contents[i2]){
- indices[idx_size] = j2.contents[i2];
- i2++;
- } else { // (j1.contents[i1]==j2.contents[i2])
- v += particles[j1.contents[i1]];
- pt_tilde += pt[j1.contents[i1]];
- indices[idx_size] = j1.contents[i1];
- i1++;
- i2++;
- is_overlap = true;
- }
- idx_size++;
- } while ((i1<j1.n) && (i2<j2.n));
-
- // finish computing union
- // (only needed if overlap !)
- if (is_overlap){
- while (i1<j1.n){
- indices[idx_size] = j1.contents[i1];
- i1++;
- idx_size++;
- }
- while (i2<j2.n){
- indices[idx_size] = j2.contents[i2];
- i2++;
- idx_size++;
- }
- }
-
- // assign the overlapping var as return variable
- (*overlap2) = get_sm_var2(v, pt_tilde);
-
- return is_overlap;
-}
-
-
-
-// split the two given jet.
-// during this procedure, the jets j1 & j2 are replaced
-// by 2 new jets. Common particles are associted to the
-// closest initial jet.
-// - it_j1 iterator of the first jet in 'candidates'
-// - it_j2 iterator of the second jet in 'candidates'
-// - j1 first jet (Cjet instance)
-// - j2 second jet (Cjet instance)
-// return true on success, false on error
-////////////////////////////////////////////////////////////////
-bool Csplit_merge::split(cjet_iterator &it_j1, cjet_iterator &it_j2){
- int i1, i2;
- Cjet jet1, jet2;
- double E1_weight, E2_weight;
- Cmomentum tmp;
- Cmomentum *v;
-
- // shorthand to avoid having "->" all over the place
- const Cjet & j1 = * it_j1;
- const Cjet & j2 = * it_j2;
-
- i1=i2=0;
- jet2.v = jet1.v = Cmomentum();
- jet2.pt_tilde = jet1.pt_tilde = 0.0;
-
- // compute centroids
- // When use_E_weighted_splitting is activated, the
- // "geometrical" distance is weighted by the inverse
- // of the E of the protojet
- // This is stored in E{1,2}_weight
- E1_weight = (use_E_weighted_splitting) ? 1.0/j1.v.E/j1.v.E : 1.0;
- E2_weight = (use_E_weighted_splitting) ? 1.0/j2.v.E/j2.v.E : 1.0;
-
- jet1.v = jet2.v = Cmomentum();
-
- // compute jet splitting
- do{
- if (j1.contents[i1]<j2.contents[i2]){
- // particle i1 belong only to jet 1
- v = &(particles[j1.contents[i1]]);
- jet1.contents.push_back(j1.contents[i1]);
- jet1.v += *v;
- jet1.pt_tilde += pt[j1.contents[i1]];
- i1++;
- jet1.range.add_particle(v->_theta,v->_phi);
- } else if (j1.contents[i1]>j2.contents[i2]){
- // particle i2 belong only to jet 2
- v = &(particles[j2.contents[i2]]);
- jet2.contents.push_back(j2.contents[i2]);
- jet2.v += *v;
- jet2.pt_tilde += pt[j2.contents[i2]];
- i2++;
- jet2.range.add_particle(v->_theta,v->_phi);
- } else { // (j1.contents[i1]==j2.contents[i2])
- // common particle, decide which is the closest centre
- v = &(particles[j1.contents[i1]]);
-
- //TODO: improve this brutal use of atan2 and sqrt !!!!
-
- //? what when == ?
- // When use_E_weighted_splitting is activated, the
- // "geometrical" distance is weighted by the inverse
- // of the E of the protojet
- double d1 = get_distance(&(j1.v), v)*E1_weight;
- double d2 = get_distance(&(j2.v), v)*E2_weight;
- // do bookkeeping on most ambiguous split
- if (fabs(d1-d2) < most_ambiguous_split)
- most_ambiguous_split = fabs(d1-d2);
-
- if (d1<d2){
- // particle i1 belong only to jet 1
- jet1.contents.push_back(j1.contents[i1]);
- jet1.v += *v;
- jet1.pt_tilde += pt[j1.contents[i1]];
- jet1.range.add_particle(v->_theta,v->_phi);
- } else {
- // particle i2 belong only to jet 2
- jet2.contents.push_back(j2.contents[i2]);
- jet2.v += *v;
- jet2.pt_tilde += pt[j2.contents[i2]];
- jet2.range.add_particle(v->_theta,v->_phi);
- }
-
- i1++;
- i2++;
- }
- } while ((i1<j1.n) && (i2<j2.n));
-
- while (i1<j1.n){
- v = &(particles[j1.contents[i1]]);
- jet1.contents.push_back(j1.contents[i1]);
- jet1.v += *v;
- jet1.pt_tilde += pt[j1.contents[i1]];
- i1++;
- jet1.range.add_particle(v->_theta,v->_phi);
- }
- while (i2<j2.n){
- v = &(particles[j2.contents[i2]]);
- jet2.contents.push_back(j2.contents[i2]);
- jet2.v += *v;
- jet2.pt_tilde += pt[j2.contents[i2]];
- i2++;
- jet2.range.add_particle(v->_theta,v->_phi);
- }
-
- // finalise jets
- jet1.n = jet1.contents.size();
- jet2.n = jet2.contents.size();
-
- // remove previous jets
-#ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
- cand_refs.erase(j1.v.ref);
- cand_refs.erase(j2.v.ref);
-#endif
- candidates->erase(it_j1);
- candidates->erase(it_j2);
-
- // reinsert new ones
- insert(jet1);
- insert(jet2);
-
- return true;
-}
-
-// merge the two given jet.
-// during this procedure, the jets j1 & j2 are replaced
-// by 1 single jets containing both of them.
-// - it_j1 iterator of the first jet in 'candidates'
-// - it_j2 iterator of the second jet in 'candidates'
-// return true on success, false on error
-////////////////////////////////////////////////////////////////
-bool Csplit_merge::merge(cjet_iterator &it_j1, cjet_iterator &it_j2){
- Cjet jet;
- int i;
-
- // build new jet
- // note: particles within j1 & j2 have already been stored in indices
- for (i=0;i<idx_size;i++){
- jet.contents.push_back(indices[i]);
- jet.v += particles[indices[i]];
- jet.pt_tilde += pt[indices[i]];
- }
- jet.n = jet.contents.size();
-
- // deal with ranges
- jet.range = range_union(it_j1->range, it_j2->range);
-
- // remove old candidates
-#ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
- if (merge_identical_protocones){
- cand_refs.erase(it_j1->v.ref);
- cand_refs.erase(it_j2->v.ref);
- }
-#endif
- candidates->erase(it_j1);
- candidates->erase(it_j2);
-
- // reinsert new candidate
- insert(jet);
-
- return true;
-}
-
-/**
- * Check whether or not a jet has to be inserted in the
- * list of protojets. If it has, set its sm_variable and
- * insert it to the list of protojets.
- */
-bool Csplit_merge::insert(Cjet &jet){
-
- // eventually check that no other candidate are present with the
- // same cone contents. We recall that this automatic merging of
- // identical protocones can lead to infrared-unsafe situations.
-#ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
- if ((merge_identical_protocones) && (!cand_refs.insert(jet.v.ref).second))
- return false;
-#endif
-
- // check that the protojet has large enough energy
- if (jet.v.E<E_min)
- return false;
-
- // assign SM variable
- jet.sm_var2 = get_sm_var2(jet.v, jet.pt_tilde);
-
- // insert the jet.
- candidates->insert(jet);
-
- return true;
-}
-
-/**
- * given a 4-momentum and its associated pT, return the
- * variable that has to be used for SM
- * \param v 4 momentum of the protojet
- * \param pt_tilde pt_tilde of the protojet
- */
-double Csplit_merge::get_sm_var2(Cmomentum &v, double &pt_tilde){
- switch(ptcomparison.split_merge_scale) {
- case SM_E: return v.E*v.E;
- case SM_pt: return v.perp2();
- case SM_mt: return v.perpmass2();
- case SM_pttilde: return pt_tilde*pt_tilde;
- case SM_Et: return v.Et2();
- default:
- throw Csiscone_error("Unsupported split-merge scale choice: "
- + ptcomparison.SM_scale_name());
- }
-
- return 0.0;
-}
-
-}
Index: branches/spherical/siscone/geom_2d.cpp
===================================================================
--- branches/spherical/siscone/geom_2d.cpp (revision 241)
+++ branches/spherical/siscone/geom_2d.cpp (revision 242)
@@ -1,167 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-// File: geom_2d.cpp //
-// Description: source file for two-dimensional geometry tools //
-// This file is part of the SISCone project. //
-// WARNING: this is not the main SISCone trunk but //
-// an adaptation to spherical coordinates //
-// For more details, see http://projects.hepforge.org/siscone //
-// //
-// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
-// //
-// This program is free software; you can redistribute it and/or modify //
-// it under the terms of the GNU General Public License as published by //
-// the Free Software Foundation; either version 2 of the License, or //
-// (at your option) any later version. //
-// //
-// This program is distributed in the hope that it will be useful, //
-// but WITHOUT ANY WARRANTY; without even the implied warranty of //
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
-// GNU General Public License for more details. //
-// //
-// You should have received a copy of the GNU General Public License //
-// along with this program; if not, write to the Free Software //
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
-// //
-// $Revision:: $//
-// $Date:: $//
-///////////////////////////////////////////////////////////////////////////////
-
-#include "geom_2d.h"
-#include <algorithm>
-
-namespace siscone{
-
-#define PHI_RANGE_MASK 0xFFFFFFFF
-
-/*********************************************************
- * class Ceta_phi_range implementation *
- * class for holding a covering range in eta-phi *
- * *
- * This class deals with ranges in the eta-phi plane. It *
- * implements methods to test if two ranges overlap and *
- * to take the union of two overlapping intervals. *
- *********************************************************/
-
-using namespace std;
-
-// static member default init
-//----------------------------
-double Ctheta_phi_range::theta_min = 0.0;
-double Ctheta_phi_range::theta_max = M_PI;
-
-// default ctor
-//--------------
-Ctheta_phi_range::Ctheta_phi_range(){
- theta_range = 0;
- phi_range = 0;
-}
-
-// ctor with initialisation
-// we initialise with a centre (in eta,phi) and a radius
-// - c_theta theta coordinate of the centre
-// - c_phi phi coordinate of the centre
-// - R radius
-//-------------------------------------------------------
-Ctheta_phi_range::Ctheta_phi_range(double c_theta, double c_phi, double R){
- // determination of the eta range
- //-------------------------------
- double xmin = max(c_theta-R,theta_min+0.00001);
- double xmax = min(c_theta+R,theta_max-0.00001);
-
- unsigned int cell_min = get_theta_cell(xmin);
- unsigned int cell_max = get_theta_cell(xmax);
-
- // warning: if cell_max==2^31, 2*cell_max==0 hence,
- // even if the next formula is formally (2*cell_max-cell_min),
- // expressing it as (cell_max-cell_min)+cell_max is safe.
- theta_range = (cell_max-cell_min)+cell_max;
-
- // determination of the phi range
- // !! taking care of periodicity !!
- // !! and the theta dependence !!
- //---------------------------------
- double ymin,ymax;
- double extra = asin(R/M_PI);
- if (xmin<=theta_min+extra){
- ymin = -M_PI+0.00001;
- ymax = M_PI-0.00001;
- } else if (xmax>=theta_max-extra){
- ymin = -M_PI+0.00001;
- ymax = M_PI-0.00001;
- } else {
- extra = max(1.0/sin(xmin), 1.0/sin(xmax));
- ymin = (c_phi-R)*extra;
- while (ymin<-M_PI) ymin+=twopi;
- while (ymin> M_PI) ymin-=twopi;
- ymax = (c_phi-R)*extra;
- while (ymax<-M_PI) ymax+=twopi;
- while (ymax> M_PI) ymax-=twopi;
- }
- cell_min = get_phi_cell(ymin);
- cell_max = get_phi_cell(ymax);
-
- // Also, if the interval goes through pi, inversion is needed
- if (ymax>ymin)
- phi_range = (cell_max-cell_min)+cell_max;
- else {
- phi_range = (cell_min==cell_max)
- ? PHI_RANGE_MASK
- : ((PHI_RANGE_MASK^(cell_min-cell_max)) + cell_max);
- }
-}
-
-// assignment of range
-// - r range to assign to current one
-//---------------------------------------
-Ctheta_phi_range& Ctheta_phi_range::operator = (const Ctheta_phi_range &r){
- theta_range = r.theta_range;
- phi_range = r.phi_range;
-
- return *this;
-}
-
-// add a particle to the range
-// - eta eta coordinate of the particle
-// - phi phi coordinate of the particle
-// \return 0 on success, 1 on error
-//----------------------------------------
-int Ctheta_phi_range::add_particle(const double theta, const double phi){
- // deal with the eta coordinate
- theta_range |= get_theta_cell(theta);
-
- // deal with the phi coordinate
- phi_range |= get_phi_cell(phi);
-
- return 0;
-}
-
-
-// test overlap
-// - r1 first range
-// - r2 second range
-// return true if overlap, false otherwise.
-//------------------------------------------
-bool is_range_overlap(const Ctheta_phi_range &r1, const Ctheta_phi_range &r2){
- // check overlap in eta AND phi
- return ((r1.theta_range & r2.theta_range) && (r1.phi_range & r2.phi_range));
-}
-
-// compute union
-// Note: we assume that the two intervals overlap
-// - r1 first range
-// - r2 second range
-// \return union of the two ranges
-//------------------------------------------
-const Ctheta_phi_range range_union (const Ctheta_phi_range &r1, const Ctheta_phi_range &r2){
- Ctheta_phi_range tmp;
-
- // compute union in eta
- tmp.theta_range = r1.theta_range | r2.theta_range;
-
- // compute union in phi
- tmp.phi_range = r1.phi_range | r2.phi_range;
-
- return tmp;
-}
-
-}
Index: branches/spherical/siscone/split_merge.h
===================================================================
--- branches/spherical/siscone/split_merge.h (revision 241)
+++ branches/spherical/siscone/split_merge.h (revision 242)
@@ -1,406 +0,0 @@
-// -*- C++ -*-
-///////////////////////////////////////////////////////////////////////////////
-// File: split_merge.h //
-// Description: header file for splitting/merging (contains the CJet class) //
-// This file is part of the SISCone project. //
-// WARNING: this is not the main SISCone trunk but //
-// an adaptation to spherical coordinates //
-// For more details, see http://projects.hepforge.org/siscone //
-// //
-// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
-// //
-// This program is free software; you can redistribute it and/or modify //
-// it under the terms of the GNU General Public License as published by //
-// the Free Software Foundation; either version 2 of the License, or //
-// (at your option) any later version. //
-// //
-// This program is distributed in the hope that it will be useful, //
-// but WITHOUT ANY WARRANTY; without even the implied warranty of //
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
-// GNU General Public License for more details. //
-// //
-// You should have received a copy of the GNU General Public License //
-// along with this program; if not, write to the Free Software //
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
-// //
-// $Revision:: $//
-// $Date:: $//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef __SPLIT_MERGE_H__
-#define __SPLIT_MERGE_H__
-
-#include "defines.h"
-#include "geom_2d.h"
-#include "momentum.h"
-#include <stdio.h>
-#include <vector>
-#include <set>
-#include <memory>
-#include <string>
-
-namespace siscone{
-
-/**
- * \class Cjet
- * real Jet information.
- *
- * This class contains information for one single jet.
- * That is, first, its momentum carrying information
- * about its centre and pT, and second, its particle
- * contents
- */
-class Cjet{
- public:
- /// default ctor
- Cjet();
-
- /// default dtor
- ~Cjet();
-
- Cmomentum v; ///< jet momentum
- double pt_tilde; ///< p-scheme pt
- int n; ///< number of particles inside
- std::vector<int> contents; ///< particle contents (list of indices)
-
- /// ordering variable used for ordering and overlap in the
- /// split--merge. This variable is automatically set either to
- /// pt_tilde, or to mt or to pt, depending on the siscone
- /// parameter. Note that the default behaviour is pt_tilde and that
- /// other chices may lead to infrared unsafe situations.
- /// Note: we use the square of the varible rather than the variable itself
- double sm_var2;
-
- /// covered range in eta-phi
- Ctheta_phi_range range;
-
- /// pass at which the jet has been found
- /// It starts at 0 (first pass), -1 means infinite rapidity
- int pass;
-};
-
-/// ordering of jets in pt
-bool jets_pt_less(const Cjet &j1, const Cjet &j2);
-
-/// ordering of jets in energy (e.g. used in final jets ordering)
-bool jets_E_less(const Cjet &j1, const Cjet &j2);
-
-
-/// the choices of scale variable that can be used in the split-merge
-/// step, both for ordering the protojets and for measuing their
-/// overlap; pt, Et and mt=sqrt(pt^2+m^2) are all defined in E-scheme
-/// (4-momentum) recombination; pttilde = \sum_{i\in jet} |p_{t,i}|
-///
-/// NB: if one changes the order here, one _MUST_ also change the order
-/// in the SISCone plugin
-enum Esplit_merge_scale {
- SM_pt, ///< transverse momentum (E-scheme), IR unsafe
- SM_Et, ///< transverse energy (E-scheme), not long. boost inv.
- ///< original run-II choice [may not be implemented]
- SM_mt, ///< transverse mass (E-scheme), IR safe except
- ///< in decays of two identical narrow heavy particles
- SM_pttilde, ///< pt-scheme pt = \sum_{i in jet} |p_{ti}|, should
- ///< be IR safe in all cases
- SM_E ///< pt-scheme pt = \sum_{i in jet} |p_{ti}|, should
- ///< be IR safe in all cases
-};
-
-/// return the name of the split-merge scale choice
-std::string split_merge_scale_name(Esplit_merge_scale sms);
-
-/**
- * \class Csplit_merge_comparison
- * a class that allows us to carry out comparisons of pt of jets, using
- * information from exact particle contents where necessary.
- *
- */
-class Csplit_merge_ptcomparison{
-public:
- Csplit_merge_ptcomparison() :
- particles(0), split_merge_scale(SM_E){};
-
- // return the name corresponding to the SM scale variable
- std::string SM_scale_name() const {
- return split_merge_scale_name(split_merge_scale);}
-
- std::vector<Cmomentum> * particles;
- std::vector<double> * pt;
- bool operator()(const Cjet &jet1, const Cjet &jet2) const;
-
- /**
- * get the difference between 2 jets, calculated such that rounding
- * errors will not affect the result even if the two jets have
- * almost the same content (so that the difference is below the
- * rounding errors)
- *
- * \param j1 first jet
- * \param j2 second jet
- * \param v jet1-jet2
- * \param pt_tilde jet1-jet2 pt_tilde
- */
- void get_difference(const Cjet &j1, const Cjet &j2, Cmomentum *v, double *pt_tilde) const;
-
- /// the following parameter controls the variable we're using for
- /// the split-merge process i.e. the variable we use for
- /// 1. ordering jet candidates;
- /// 2. computing te overlap fraction of two candidates.
- /// The default value uses pttile (p-scheme pt). Other alternatives are
- /// pt, mt=sqrt(pt^2+m^2)=sqrt(E^2-pz^2) or Et.
- /// NOTE: Modifying the default choice can have nasty effects:
- /// - using pt leads to some IR unsafety when we have two jets,
- /// e.g. back-to-back, with the same pt. In that case, their ordering
- /// in pt is random and can be affected by the addition of a
- /// soft particle. Hence, we highly recommand to keep this to
- /// the default value i.e. to use pt only for the purpose of
- /// investigating the IR issue
- /// - using Et is safe but do not respect boost invariance
- /// - using mt solves the IR unsafety issues with the pt variable
- /// for QCD jets but the IR unsafety remains for nack-to-back
- /// jets of unstable narrow-width particles (e.g. Higgs).
- /// Therefore, keeping the default value is strongly advised.
- Esplit_merge_scale split_merge_scale;
-};
-
-
-// iterator types
-/// iterator definition for the jet candidates structure
-typedef std::multiset<siscone::Cjet,Csplit_merge_ptcomparison>::iterator cjet_iterator;
-
-/// iterator definition for the jet structure
-typedef std::vector<siscone::Cjet>::iterator jet_iterator;
-
-
-
-/**
- * \class Csplit_merge
- * Class used to split and merge jets.
- */
-class Csplit_merge{
- public:
- /// default ctor
- Csplit_merge();
-
- /// default dtor
- ~Csplit_merge();
-
-
- //////////////////////////////
- // initialisation functions //
- //////////////////////////////
-
- /**
- * initialisation function
- * \param _particles list of particles
- * \param protocones list of protocones (initial jet candidates)
- * \param R2 cone radius (squared)
- * \param Emin minimal energy allowed for jets
- * \return 0 on success, 1 on error
- */
- int init(std::vector<Cmomentum> &_particles, std::vector<Cmomentum> *protocones, double R2, double Emin=0.0);
-
- /**
- * initialisation function for particle list
- * \param _particles list of particles
- * \return 0 on success, 1 on error
- */
- int init_particles(std::vector<Cmomentum> &_particles);
-
- /**
- * build initial list of left particles
- */
- int init_pleft();
-
- /**
- * use an energy-dependent boundary for splitting
- * When called with true, the criterium for splitting two protojets
- * will be to compare D1^2/kt1^2 vs. D2^2/kt2^2, the (anti-)kt-weighted
- * distance instead of the plain distance D1^2 vs. D2^2.
- * This can be set in order to produce more circular hard jets,
- * with the same underlying philosophy as for the anti-kt algorithm.
- * We thus expect a behaviour closer to the IterativeCone one.
- * By default, we use the standard D1^2 vs. D2^2 comparison and this
- * function is not called.
- */
- inline int set_E_weighted_splitting(bool _use_E_weighted_splitting){
- use_E_weighted_splitting = _use_E_weighted_splitting;
- return 0;
- }
-
- ////////////////////////
- // cleaning functions //
- ////////////////////////
-
- /// partial clearance
- int partial_clear();
-
- /// full clearance
- int full_clear();
-
-
- /////////////////////////////////
- // main parts of the algorithm //
- /////////////////////////////////
-
- /**
- * build the list 'p_uncol_hard' from p_remain by clustering
- * collinear particles
- * note that thins in only used for stable-cone detection
- * so the parent_index field is unnecessary
- *
- * Note that soft particles are not removed here
- * This is just a remnant from the trunk version
- */
- int merge_collinear_and_remove_soft();
-
- /**
- * add a list of protocones
- * \param protocones list of protocones (initial jet candidates)
- * \param R2 cone radius (squared)
- * \param Emin minimal emergy allowed for jets
- * \return 0 on success, 1 on error
- */
- int add_protocones(std::vector<Cmomentum> *protocones, double R2, double Emin=0.0);
-
- /**
- * really do the splitting and merging
- * At the end, the vector jets is filled with the jets found.
- * the 'contents' field of each jets contains the indices
- * of the particles included in that jet.
- * \param overlap_tshold threshold for splitting/merging transition
- * \param Emin minimal energy allowed for jets
- * \return the number of jets is returned
- */
- int perform(double overlap_tshold, double Emin=0.0);
-
-
- //////////////////////////////
- // save and debug functions //
- //////////////////////////////
-
- /// save final jets
- /// \param flux stream to save the jet contentss
- int save_contents(FILE *flux);
-
- /// show jets/candidates status
- int show();
-
- // particle information
- int n; ///< number of particles
- std::vector<Cmomentum> particles; ///< list of particles
- std::vector<double> pt; ///< list of particles' pt
- int n_left; ///< numer of particles that does not belong to any jet
- std::vector<Cmomentum> p_remain; ///< list of particles remaining to deal with
- std::vector<Cmomentum> p_uncol_hard; ///< list of particles remaining with collinear clustering
- int n_pass; ///< index of the run
-
- /// minimal difference in squared distance between a particle and
- /// two overlapping protojets when doing a split (useful when
- /// testing approx. collinear safety)
- double most_ambiguous_split;
-
- // jets information
- std::vector<Cjet> jets; ///< list of jets
-
- // working entries
- int *indices; ///< maximal size array for indices works
- int idx_size; ///< number of elements in indices1
-
- /// The following flag indicates that identical protocones
- /// are to be merged automatically each time around the split-merge
- /// loop and before anything else happens.
- ///
- /// This flag is only effective if ALLOW_MERGE_IDENTICAL_PROTOCONES
- /// is set in 'defines.h'
- /// Note that this lead to infrared-unsafety so it is disabled
- /// by default
- bool merge_identical_protocones;
-
- /// member used for detailed comparisons of pt's
- Csplit_merge_ptcomparison ptcomparison;
-
- /// stop split--merge when the SM_var of the hardest protojet
- /// is below this cut-off.
- /// This is not collinear-safe so you should not use this
- /// variable unless you really know what you are doing
- /// Note that the cut-off is set on the variable squared.
- double SM_var2_hardest_cut_off;
-
- /// pt cutoff for the particles to put in p_uncol_hard
- /// this is meant to allow removing soft particles in the
- /// stable-cone search.
- double stable_cone_soft_pt2_cutoff;
-
- private:
- /**
- * get the overlap between 2 jets
- * \param j1 first jet
- * \param j2 second jet
- * \param v returned overlap^2 (determined by the choice of SM variable)
- * \return true if overlapping, false if disjoint
- */
- bool get_overlap(const Cjet &j1, const Cjet &j2, double *v);
-
-
- /**
- * split the two given jets.
- * during this procedure, the jets j1 & j2 are replaced
- * by 2 new jets. Common particles are associted to the
- * closest initial jet.
- * \param it_j1 iterator of the first jet in 'candidates'
- * \param it_j2 iterator of the second jet in 'candidates'
- * \param j1 first jet (Cjet instance)
- * \param j2 second jet (Cjet instance)
- * \return true on success, false on error
- */
- bool split(cjet_iterator &it_j1, cjet_iterator &it_j2);
-
- /**
- * merge the two given jet.
- * during this procedure, the jets j1 & j2 are replaced
- * by 1 single jets containing both of them.
- * \param it_j1 iterator of the first jet in 'candidates'
- * \param it_j2 iterator of the second jet in 'candidates'
- * \return true on success, false on error
- */
- bool merge(cjet_iterator &it_j1, cjet_iterator &it_j2);
-
- /**
- * Check whether or not a jet has to be inserted in the
- * list of protojets. If it has, set its sm_variable and
- * insert it to the list of protojets.
- * \param jet jet to insert
- */
- bool insert(Cjet &jet);
-
- /**
- * given a 4-momentum and its associated pT, return the
- * variable tht has to be used for SM
- * \param v 4 momentum of the protojet
- * \param pt_tilde pt_tilde of the protojet
- */
- double get_sm_var2(Cmomentum &v, double &pt_tilde);
-
- // jet information
- /// list of jet candidates
- std::auto_ptr<std::multiset<Cjet,Csplit_merge_ptcomparison> > candidates;
-
- /// minimal E
- double E_min;
-
- /**
- * do we have or not to use the energy-weighted splitting
- * (see description for set_E_weighted_splitting)
- * This will be false by default
- */
- bool use_E_weighted_splitting;
-
-#ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
- /// checkxor for the candidates (to avoid having twice the same contents)
- std::set<Creference> cand_refs;
-#endif
-};
-
-}
-
-
-#endif
Index: branches/spherical/siscone/geom_2d.h
===================================================================
--- branches/spherical/siscone/geom_2d.h (revision 241)
+++ branches/spherical/siscone/geom_2d.h (revision 242)
@@ -1,181 +0,0 @@
-// -*- C++ -*-
-///////////////////////////////////////////////////////////////////////////////
-// File: geom_2d.h //
-// Description: header file for two-dimensional geometry tools //
-// This file is part of the SISCone project. //
-// WARNING: this is not the main SISCone trunk but //
-// an adaptation to spherical coordinates //
-// For more details, see http://projects.hepforge.org/siscone //
-// //
-// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
-// //
-// This program is free software; you can redistribute it and/or modify //
-// it under the terms of the GNU General Public License as published by //
-// the Free Software Foundation; either version 2 of the License, or //
-// (at your option) any later version. //
-// //
-// This program is distributed in the hope that it will be useful, //
-// but WITHOUT ANY WARRANTY; without even the implied warranty of //
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
-// GNU General Public License for more details. //
-// //
-// You should have received a copy of the GNU General Public License //
-// along with this program; if not, write to the Free Software //
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
-// //
-// $Revision:: $//
-// $Date:: $//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef __GEOM_2D_H__
-#define __GEOM_2D_H__
-
-#include <iostream>
-#include <math.h>
-#include "defines.h"
-
-#ifndef M_PI
-#define M_PI 3.141592653589793238462643383279502884197
-#endif
-
-namespace siscone{
-
-/// return a result that corresponds to phi, but in the
-/// range (-pi..pi]; the result is only correct if -3pi < phi <= 3pi
-inline double phi_in_range(double phi) {
- if (phi <= -M_PI) phi += twopi;
- else if (phi > M_PI) phi -= twopi;
- return phi;
-}
-
-/// return the difference between the two phi values,
-/// placed in the correct range (-pi..pi], , assuming that phi1,phi2
-/// are already in the correct range.
-inline double dphi(double phi1, double phi2) {
- return phi_in_range(phi1-phi2);
-}
-
-
-/// return the absolute difference between the two phi values,
-/// placed in the correct range, assuming that phi1,phi2 are already
-/// in the correct range.
-inline double abs_dphi(double phi1, double phi2) {
- double delta = fabs(phi1-phi2);
- return delta > M_PI ? twopi-delta : delta;
-}
-
-/// return the square of the argument
-inline double pow2(double x) {return x*x;}
-
-
-/**
- * \class Ctwovect
- * \brief class for holding a two-vector
- */
-class Ctwovect {
-public:
- /// default ctor
- Ctwovect() : x(0.0), y(0.0) {}
-
- /// ctor with initialisation
- /// \param _x first coordinate
- /// \param _y second coordinate
- Ctwovect(double _x, double _y) : x(_x), y(_y) {}
-
- /// vector coordinates
- double x, y;
-
- /// norm (modulud square) of the vector
- inline double mod2() const {return pow2(x)+pow2(y);}
-
- /// modulus of the vector
- inline double modulus() const {return sqrt(mod2());}
-};
-
-
-/// dot product of two 2-vectors
-/// \param a first 2-vect
-/// \param b second 2-vect
-/// \return a.b is returned
-inline double dot_product(const Ctwovect & a, const Ctwovect & b) {
- return a.x*b.x + a.y*b.y;
-}
-
-
-/// cross product of two 2-vectors
-/// \param a first 2-vect
-/// \param b second 2-vect
-/// \return a x b is returned
-inline double cross_product(const Ctwovect & a, const Ctwovect & b) {
- return a.x*b.y - a.y*b.x;
-}
-
-
-/**
- * \class Ceta_phi_range
- * \brief class for holding a covering range in eta-phi
- *
- * This class deals with ranges in the eta-phi plane. It
- * implements methods to test if two ranges overlap and
- * to take the union of two overlapping intervals.
- */
-class Ctheta_phi_range{
-public:
- /// default ctor
- Ctheta_phi_range();
-
- /// ctor with initialisation
- /// we initialise with a centre (in theta,phi) and a radius
- /// \param c_theta theta coordinate of the centre
- /// \param c_phi phi coordinate of the centre
- /// \param R radius
- Ctheta_phi_range(double c_theta, double c_phi, double R);
-
- /// assignment of range
- /// \param r range to assign to current one
- Ctheta_phi_range& operator = (const Ctheta_phi_range &r);
-
- /// add a particle to the range
- /// \param theta theta coordinate of the particle
- /// \param phi phi coordinate of the particle
- /// \return 0 on success, 1 on error
- int add_particle(const double theta, const double phi);
-
- /// theta range as a binary coding of covered cells
- unsigned int theta_range;
-
- /// phi range as a binary coding of covered cells
- unsigned int phi_range;
-
- /// maximal value for theta
- static double theta_min;
- static double theta_max;
-
-private:
- /// return the cell index corrsponding to an theta value
- inline unsigned int get_theta_cell(double theta){
- return (unsigned int) (1 << ((int) (32*((theta-theta_min)/(theta_max-theta_min)))));
- }
-
- /// return the cell index corrsponding to a phi value
- inline unsigned int get_phi_cell(double phi){
- return (unsigned int) (1 << ((int) (32*phi/twopi+16)%32));
- }
-};
-
-/// test overlap
-/// \param r1 first range
-/// \param r2 second range
-/// \return true if overlap, false otherwise.
-bool is_range_overlap(const Ctheta_phi_range &r1, const Ctheta_phi_range &r2);
-
-/// compute union
-/// Note: we assume that the two intervals overlap
-/// \param r1 first range
-/// \param r2 second range
-/// \return union of the two ranges
-const Ctheta_phi_range range_union(const Ctheta_phi_range &r1, const Ctheta_phi_range &r2);
-
-}
-
-#endif
Index: branches/spherical/siscone/makefile.static
===================================================================
--- branches/spherical/siscone/makefile.static (revision 241)
+++ branches/spherical/siscone/makefile.static (revision 242)
@@ -1,55 +0,0 @@
-CC = g++
-LIBOUT = libsiscone.a
-CFLAGS = -Wall -g -O3 -ffast-math
-
-LDFLAGS = -lm #-lprofiler -lpthread -ltcmalloc
-ifeq ($(shell whoami),salam)
- # needed for Gavin to include tcmalloc
- LDFLAGS += -L/ada1/lpthe/salam/software/local/lib
-endif
-
-OBJS = ranlux.o reference.o geom_2d.o momentum.o hash.o quadtree.o \
- vicinity.o protocones.o split_merge.o siscone.o siscone_error.o area.o
-
-SRCS = $(patsubst %.o,%.cpp,$(OBJS))
-
-
-%.o: %.cpp %.h
- $(CC) -c $(CFLAGS) $<
-
-%.o: %.cpp
- $(CC) -c $(CFLAGS) $<
-
-all: $(OBJS)
- ar cru $(LIBOUT) $(OBJS)
- ranlib $(LIBOUT)
-
-.PHONY: clean
-
-clean:
- rm -f *.o *~
-
-
-# note the -Y option below avoids including all the standard
-# include directories (which change from one system to another)
-depend:
- makedepend -- -Y -- $(SRCS)
-# DO NOT DELETE
-
-ranlux.o: ranlux.h
-reference.o: reference.h ranlux.h
-geom_2d.o: geom_2d.h defines.h
-momentum.o: momentum.h reference.h geom_2d.h defines.h
-hash.o: hash.h momentum.h reference.h geom_2d.h defines.h
-quadtree.o: quadtree.h momentum.h reference.h geom_2d.h defines.h
-vicinity.o: vicinity.h momentum.h reference.h geom_2d.h defines.h quadtree.h
-protocones.o: protocones.h momentum.h reference.h geom_2d.h defines.h
-protocones.o: vicinity.h quadtree.h hash.h siscone_error.h circulator.h
-split_merge.o: split_merge.h defines.h geom_2d.h momentum.h reference.h
-split_merge.o: siscone_error.h
-siscone.o: ranlux.h momentum.h reference.h geom_2d.h defines.h siscone.h
-siscone.o: protocones.h vicinity.h quadtree.h hash.h split_merge.h
-siscone.o: siscone_error.h
-siscone_error.o: siscone_error.h
-area.o: area.h momentum.h reference.h geom_2d.h defines.h siscone.h
-area.o: protocones.h vicinity.h quadtree.h hash.h split_merge.h
Index: branches/spherical/siscone/defines.h
===================================================================
--- branches/spherical/siscone/defines.h (revision 241)
+++ branches/spherical/siscone/defines.h (revision 242)
@@ -1,130 +0,0 @@
-// -*- C++ -*-
-///////////////////////////////////////////////////////////////////////////////
-// File: defines.h //
-// Description: header file for generic parameters definitions //
-// This file is part of the SISCone project. //
-// WARNING: this is not the main SISCone trunk but //
-// an adaptation to spherical coordinates //
-// For more details, see http://projects.hepforge.org/siscone //
-// //
-// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
-// //
-// This program is free software; you can redistribute it and/or modify //
-// it under the terms of the GNU General Public License as published by //
-// the Free Software Foundation; either version 2 of the License, or //
-// (at your option) any later version. //
-// //
-// This program is distributed in the hope that it will be useful, //
-// but WITHOUT ANY WARRANTY; without even the implied warranty of //
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
-// GNU General Public License for more details. //
-// //
-// You should have received a copy of the GNU General Public License //
-// along with this program; if not, write to the Free Software //
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
-// //
-// $Revision:: $//
-// $Date:: $//
-///////////////////////////////////////////////////////////////////////////////
-
-//! \file defines.h
-#ifndef __DEFINES_H__
-#define __DEFINES_H__
-
-/// program name
-// we get "SISCone" by calling
-// siscone::siscone_package_name
-// defined in siscone.h
-// Otherwise, config.h
-// It is also defined as "PACKAGE_NAME" in config.h but this method
-// might lead to conflicts
-//#define PROGRAM PACKAGE_NAME
-
-// program version
-// we get it from
-// siscone::siscone_version
-// defined in siscone.h
-// It is also defined as "VERSION" in config.h but this method
-// might lead to conflicts
-
-/// perform final stability check using the quadtree
-/// With the following define enabled, the final check for stability
-/// is performed using the quadtree rather than the explicit list of
-/// particles (see Cstable_cone::proceed_with_stability())
-//#define USE_QUADTREE_FOR_STABILITY_TEST
-
-
-/// threshold for recomoutation of the cone (see Cstable_cones::update_cone())
-/// When traversing cone candidates along the angular ordering,
-/// the momentum of the protojet candidate is computed incrementally
-/// from the particles that enter and leave the cone.
-/// When the cumulative change in "|px|+|py|" exceeds the cone "|px|+|py|"
-/// we explicitely recompute the cone contents
-#define PT_TSHOLD 1000.0
-
-
-/// The following parameter controls collinear safety. For the set of
-/// particles used in the search of stable cones, we gather particles
-/// if their distance in eta and phi is smaller than EPSILON_COLLINEAR.
-///
-/// NB: for things to behave sensibly one requires
-/// 1e-15 << EPSILON_COCIRCULAR << EPSILON_COLLINEAR << 1
-///
-/// among the scales that appear in practice (e.g. in deciding to use
-/// special strategies), we have EPSILON_COLLINEAR, EPSILON_COCIRCULAR,
-/// sqrt(EPSILON_COCIRCULAR) and EPSILON_COLLINEAR / EPSILON_COCIRCULAR.
-///
-#define EPSILON_COLLINEAR 1e-8
-
-
-/// The following parameter controls cocircular situations.
-/// When consecutive particles in the ordered vicinity list are separated
-/// (in angle) by less that that limit, we consider that we face a situation
-/// of cocircularity.
-#define EPSILON_COCIRCULAR 1e-12
-
-
-/// The following define enables you to allow for identical protocones
-/// to be merged automatically after each split-merge step before
-/// anything else happens. Whether this happens depends on teh value
-/// of the merge_identical_protocones flag in Csplit_merge.
-///
-/// It we allow such a merging and define allow
-/// MERGE_IDENTICAL_PROTOCONES_DEFAULT_TRUE then the
-/// 'merge_identical_protocones' flag in Csplit_merge to be set to
-/// 'true'. It may be manually reset to false in which case the
-/// merging of identical protocones (protojets) will be turned off.
-///
-/// Note that this merging identical protocones makes the algorithm
-/// infrared-unsafe, so it should be disabled except for testing
-/// purposes.
-//#define ALLOW_MERGE_IDENTICAL_PROTOCONES
-//#define MERGE_IDENTICAL_PROTOCONES_DEFAULT_TRUE
-
-
-/// if EPSILON_SPLITMERGE is defined then, during the split-merge
-/// step, when two jets are found with PTs that are identical to
-/// within a relative difference of EPSILON_SPLITMERGE they are
-/// compared element-by-element to see where the differences are, and
-/// one then uses pt1^2-pt2^2 = (pt1-pt2).(pt1+pt2) as an estimator of
-/// which is harder. NB: in unfortunate cases, this can take the split
-/// merge step up to N n * ln N time, though on normal events there
-/// don't seem to have been any major problems yet.
-#define EPSILON_SPLITMERGE 1e-12
-
-/// definition of 2*M_PI which is useful a bit everyhere!
-const double twopi = 6.283185307179586476925286766559005768394;
-
-/// debugging information
-//#define DEBUG_STABLE_CONES ///< debug messages in stable cones search
-//#define DEBUG_SPLIT_MERGE ///< debug messages in split-merge
-//#define DEBUG ///< all debug messages !
-
-// in case all debug massages allowed, allow them in practice !
-#ifdef DEBUG
-#define DEBUG_STABLE_CONES
-#define DEBUG_SPLIT_MERGE
-#endif
-
-#endif // __DEFINES_H__
-
Index: branches/spherical/siscone/hash.cpp
===================================================================
--- branches/spherical/siscone/hash.cpp (revision 241)
+++ branches/spherical/siscone/hash.cpp (revision 242)
@@ -1,207 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-// File: hash.cpp //
-// Description: source file for classes hash_element and hash_cones //
-// This file is part of the SISCone project. //
-// WARNING: this is not the main SISCone trunk but //
-// an adaptation to spherical coordinates //
-// For more details, see http://projects.hepforge.org/siscone //
-// //
-// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
-// //
-// This program is free software; you can redistribute it and/or modify //
-// it under the terms of the GNU General Public License as published by //
-// the Free Software Foundation; either version 2 of the License, or //
-// (at your option) any later version. //
-// //
-// This program is distributed in the hope that it will be useful, //
-// but WITHOUT ANY WARRANTY; without even the implied warranty of //
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
-// GNU General Public License for more details. //
-// //
-// You should have received a copy of the GNU General Public License //
-// along with this program; if not, write to the Free Software //
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
-// //
-// $Revision:: $//
-// $Date:: $//
-///////////////////////////////////////////////////////////////////////////////
-
-#include <math.h>
-#include <stdio.h>
-#include "hash.h"
-#include <iostream>
-
-namespace siscone{
-
-using namespace std;
-
-/**************************************************************
- * implementation of hash_cones *
- * list of cones candidates. *
- * We store in this class all the hash_elements and give *
- * functions to manipulate them. *
- **************************************************************/
-
-// constructor with initialisation
-// - _Np number of particles
-// - _R2 cone radius (squared)
-//-----------------------------------
-hash_cones::hash_cones(int _Np, double _R){
- int i;
-
- n_cones = 0;
-#ifdef DEBUG_STABLE_CONES
- n_occupied_cells = 0;
-#endif
-
- // determine hash size
- // for a ymax=5 and R=0.7, we observed an occupancy around 1/8 N^2 ~ N2 R2/4
- //mask = 1 << (int) (2*log(double(_Np))/log(2.0));
- //if (mask<=1) mask=2;
- int nbits = (int) (log(_Np*_R*_R*_Np/4.0)/log(2.0));
- if (nbits<1) nbits=1;
- mask = 1 << nbits;
-
- // create hash
- hash_array = new hash_element*[mask];
- mask--;
-
- // set the array to 0
- //? needed ?
- for (i=0;i<mask+1;i++)
- hash_array[i] = NULL;
-
- tan2R = tan(_R);
- tan2R *= tan2R;
-}
-
-// destructor
-//------------
-hash_cones::~hash_cones(){
- int i;
- hash_element *elm;
-
- for (i=0;i<mask+1;i++){
- while (hash_array[i]!=NULL){
- elm = hash_array[i];
- hash_array[i] = hash_array[i]->next;
- delete elm;
- }
- }
-
- delete[] hash_array;
-}
-
-
-/*
- * insert a new candidate into the hash.
- * - v 4-momentum of the cone to add
- * - parent parent particle defining the cone
- * - child child particle defining the cone
- * - p_io whether the parent has to belong to the cone or not
- * - c_io whether the child has to belong to the cone or not
- * return 0 on success, 1 on error
- ***********************************************************************/
-int hash_cones::insert(Cmomentum *v, Cmomentum *parent, Cmomentum *child, bool p_io, bool c_io){
- hash_element *elm;
- int index = (v->ref.ref[0]) & mask;
-
- // check the array cell corresponding to our reference
- elm = hash_array[index];
-
-#ifdef DEBUG_STABLE_CONES
- if (elm==NULL)
- n_occupied_cells++;
-#endif
-
- do{
- // if it is not present, add it
- if (elm==NULL){
- // create element
- elm = new hash_element;
-
- // set its varibles
- // Note: at this level, eta and phi have already been computed
- // through Cmomentum::build_etaphi.
- elm->centre = *v;
-
- // if at least one of the two is_closer tests gives a result != from the expected,
- // the || will be true hence !(...) false as wanted
- elm->is_stable = !((is_closer(v, parent, tan2R)^p_io)||(is_closer(v, child, tan2R)^c_io));
- //cout << "-- new status of " << v->ref[0] << ":" << elm->is_stable << endl;
-
- // update hash
- elm->next = hash_array[index];
- hash_array[index] = elm;
-
- n_cones++;
- return 0;
- }
-
- // if the cone is already there, simply update stability status
- if (v->ref == elm->centre.ref){
- // there is only an update to perform to see if the cone is still stable
- if (elm->is_stable){
- elm->is_stable = !((is_closer(v, parent, tan2R)^p_io)||(is_closer(v, child, tan2R)^c_io));
- //cout << " parent/child: "
- // << parent->ref[0] << ":" << is_closer(v, parent) << ":" << p_io << " "
- // << child->ref[0] << ":" << is_closer(v, child) << ":" << c_io << endl;
- //cout << "-- rep status of " << v->ref[0] << ":" << elm->is_stable << endl;
- //cout << v->eta << " " << v->phi << endl;
- //cout << (child->eta) << " " << child->phi << endl;
- }
- return 0;
- }
-
- elm = elm->next;
- } while (1);
-
- return 1;
-}
-
-/*
- * insert a new candidate into the hash.
- * - v 4-momentum of te cone to add
- * Note, in this case, we assume stability. We also assume
- * that eta and phi are computed for v
- * return 0 on success, 1 on error
- ***********************************************************************/
-int hash_cones::insert(Cmomentum *v){
- hash_element *elm;
- int index = (v->ref.ref[0]) & mask;
- //cout << "-- stable candidate: " << v->ref[0] << ":" << endl;
-
- // check the array cell corresponding to our reference
- elm = hash_array[index];
- do{
- // if it is not present, add it
- if (elm==NULL){
- // create element
- elm = new hash_element;
-
- // set its varibles
- // Note: at this level, eta and phi have already been computed
- // through Cmomentum::build_etaphi.
- elm->centre = *v;
- elm->is_stable = true;
-
- // update hash
- elm->next = hash_array[index];
- hash_array[index] = elm;
-
- n_cones++;
- return 0;
- }
-
- // if the cone is already there, we have nothing to do
- if (v->ref == elm->centre.ref){
- return 0;
- }
-
- elm = elm->next;
- } while (1);
-
- return 1;
-}
-
-}
Index: branches/spherical/siscone/hash.h
===================================================================
--- branches/spherical/siscone/hash.h (revision 241)
+++ branches/spherical/siscone/hash.h (revision 242)
@@ -1,115 +0,0 @@
-// -*- C++ -*-
-///////////////////////////////////////////////////////////////////////////////
-// File: hash.h //
-// Description: header file for classes hash_element and hash_cones //
-// This file is part of the SISCone project. //
-// WARNING: this is not the main SISCone trunk but //
-// an adaptation to spherical coordinates //
-// For more details, see http://projects.hepforge.org/siscone //
-// //
-// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
-// //
-// This program is free software; you can redistribute it and/or modify //
-// it under the terms of the GNU General Public License as published by //
-// the Free Software Foundation; either version 2 of the License, or //
-// (at your option) any later version. //
-// //
-// This program is distributed in the hope that it will be useful, //
-// but WITHOUT ANY WARRANTY; without even the implied warranty of //
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
-// GNU General Public License for more details. //
-// //
-// You should have received a copy of the GNU General Public License //
-// along with this program; if not, write to the Free Software //
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
-// //
-// $Revision:: $//
-// $Date:: $//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef __HASH_H__
-#define __HASH_H__
-
-#include "momentum.h"
-#include "reference.h"
-
-namespace siscone{
-
-/**
- * \class hash_element
- * information on store cones candidates.
- *
- * We store in this class the information used to count all
- * protocones in a first pass. This first pass only count
- * cones with different references and test their stbility
- * with the parent-child particles (border particles).
- */
-class hash_element{
- public:
- C3vector centre; ///< reference
- bool is_stable; ///< true if stable w.r.t. "border particles"
-
- hash_element *next; ///< pointer to the next element
-};
-
-/**
- * \class hash_cones
- * list of cones candidates.
- *
- * We store in this class all the hash_elements and give
- * functions to manipulate them.
- */
-class hash_cones{
- public:
- /// constructor with initialisation
- /// \param _Np number of particles
- /// \param _R2 cone radius (squared)
- hash_cones(int _Np, double _R2);
-
- /// destructor
- ~hash_cones();
-
- /**
- * insert a new candidate into the hash.
- * \param v 4-momentum of te cone to add
- * \param parent parent particle defining the cone
- * \param child child particle defining the cone
- * \param p_io whether the parent has to belong to the cone or not
- * \param c_io whether the child has to belong to the cone or not
- * \return 0 on success, 1 on error
- */
- int insert(Cmomentum *v, Cmomentum *parent, Cmomentum *child, bool p_io, bool c_io);
-
- /**
- * insert a new candidate into the hash.
- * \param v 4-momentum of te cone to add
- * Note, in this case, we assume stability. We also assume
- * that eta and phi are computed for v
- * \return 0 on success, 1 on error
- */
- int insert(Cmomentum *v);
-
- /// the cone data itself
- hash_element **hash_array;
-
- /// number of elements
- int n_cones;
-
- /// number of occupied cells
-#ifdef DEBUG_STABLE_CONES
- int n_occupied_cells;
-#endif
-
- /// number of cells-1
- int mask;
-
- /// circle radius (squared)
- /// NOTE: need to be set before any call to 'insert'
- double R2;
-
- /// its squreed tangent
- double tan2R;
-};
-
-}
-#endif
Index: branches/spherical/siscone/Makefile.am
===================================================================
--- branches/spherical/siscone/Makefile.am (revision 241)
+++ branches/spherical/siscone/Makefile.am (revision 242)
@@ -1,26 +0,0 @@
-# build information for the SISCone library
-# this is built as a libtool lib.
-lib_LTLIBRARIES = libsiscone.la
-libsiscone_la_SOURCES = ranlux.cpp reference.cpp geom_2d.cpp\
- momentum.cpp hash.cpp vicinity.cpp\
- protocones.cpp split_merge.cpp siscone.cpp\
- siscone_error.cpp
-
-EXTRA_DIST = makefile.static quadtree.cpp quadtree.h area.cpp
-
-# install the SISCone headers
-includedir = ${prefix}/include/siscone
-include_HEADERS = area.h\
- circulator.h\
- defines.h\
- geom_2d.h\
- hash.h\
- momentum.h\
- protocones.h\
- ranlux.h\
- reference.h\
- siscone_error.h\
- siscone.h\
- split_merge.h\
- vicinity.h\
- config.h
Index: branches/spherical/siscone/protocones.cpp
===================================================================
--- branches/spherical/siscone/protocones.cpp (revision 241)
+++ branches/spherical/siscone/protocones.cpp (revision 242)
@@ -1,863 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-// File: protocones.cpp //
-// Description: source file for stable cones determination (Cstable_cones) //
-// This file is part of the SISCone project. //
-// WARNING: this is not the main SISCone trunk but //
-// an adaptation to spherical coordinates //
-// For more details, see http://projects.hepforge.org/siscone //
-// //
-// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
-// //
-// This program is free software; you can redistribute it and/or modify //
-// it under the terms of the GNU General Public License as published by //
-// the Free Software Foundation; either version 2 of the License, or //
-// (at your option) any later version. //
-// //
-// This program is distributed in the hope that it will be useful, //
-// but WITHOUT ANY WARRANTY; without even the implied warranty of //
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
-// GNU General Public License for more details. //
-// //
-// You should have received a copy of the GNU General Public License //
-// along with this program; if not, write to the Free Software //
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
-// //
-// $Revision:: $//
-// $Date:: $//
-///////////////////////////////////////////////////////////////////////////////
-
-/*******************************************************
- * Introductory note: *
- * Since this file has many member functions, we have *
- * structured them in categories: *
- * INITIALISATION FUNCTIONS *
- * - ctor() *
- * - ctor(particle_list) *
- * - dtor() *
- * - init(particle_list) *
- * ALGORITHM MAIN ENTRY *
- * - get_stable_cone(radius) *
- * ALGORITHM MAIN STEPS *
- * - init_cone() *
- * - test_cone() *
- * - update_cone() *
- * - proceed_with_stability() *
- * ALGORITHM MAIN STEPS FOR COCIRCULAR SITUATIONS *
- * - cocircular_pt_less(v1, v2) *
- * - prepare_cocircular_list() *
- * - test_cone_cocircular() *
- * - test_stability(candidate, border_list) *
- * - updat_cone_cocircular() *
- * RECOMPUTATION OF CONE CONTENTS *
- * - compute_cone_contents() *
- * - recompute_cone_contents() *
- * - recompute_cone_contents_if_needed() *
- * VARIOUS TOOLS *
- * - circle_intersect() *
- * - is_inside() *
- * - abs_dangle() *
- *******************************************************/
-
-#include "protocones.h"
-#include "siscone_error.h"
-#include "defines.h"
-#include <math.h>
-#include <iostream>
-#include "circulator.h"
-#include <algorithm>
-
-namespace siscone{
-
-using namespace std;
-
-/**********************************************************************
- * Cstable_cones implementation *
- * Computes the list of stable comes from a particle list. *
- * This class does the first fundamental task of te cone algorithm: *
- * it is used to compute the list of stable cones given a list *
- * of particles. *
- **********************************************************************/
-
-////////////////////////////////////////////////////////
-// INITIALISATION FUNCTIONS //
-// - ctor() //
-// - ctor(particle_list) //
-// - dtor() //
-// - init(particle_list) //
-////////////////////////////////////////////////////////
-
-// default ctor
-//--------------
-Cstable_cones::Cstable_cones(){
- nb_tot = 0;
- hc = NULL;
-}
-
-// ctor with initialisation
-//--------------------------
-Cstable_cones::Cstable_cones(vector<Cmomentum> &_particle_list)
- : Cvicinity(_particle_list){
-
- nb_tot = 0;
- hc = NULL;
-}
-
-// default dtor
-//--------------
-Cstable_cones::~Cstable_cones(){
- if (hc!=NULL) delete hc;
-}
-
-/*
- * initialisation
- * - _particle_list list of particles
- * - _n number of particles
- *********************************************************************/
-void Cstable_cones::init(vector<Cmomentum> &_particle_list){
- // check already allocated mem
- if (hc!=NULL){
- delete hc;
- }
- if (protocones.size()!=0)
- protocones.clear();
-
- multiple_centre_done.clear();
-
- // initialisation
- set_particle_list(_particle_list);
-}
-
-
-////////////////////////////////////////////////////////
-// ALGORITHM MAIN ENTRY //
-// - get_stable_cone(radius) //
-////////////////////////////////////////////////////////
-
-/*
- * compute stable cones.
- * This function really does the job i.e. computes
- * the list of stable cones (in a seedless way)
- * - _radius: radius of the cones
- * The number of stable cones found is returned
- *********************************************************************/
-int Cstable_cones::get_stable_cones(double _radius){
- int p_idx;
-
- // check if everything is correctly initialised
- if (n_part==0){
- return 0;
- }
-
- R = _radius;
- R2 = R*R;
- tan2R = tan(R);
- tan2R *= tan2R;
-
- // allow hash for cones candidates
- hc = new hash_cones(n_part, R);
-
- // browse all particles
- for (p_idx=0;p_idx<n_part;p_idx++){
- // step 0: compute the child list CL.
- // Note that this automatically sets the parent P
- build(&plist[p_idx], 2.0*R);
-
- // special case:
- // if the vicinity is empty, the parent particle is a
- // stable cone by itself. Add it to protocones list.
- if (vicinity_size==0){
- protocones.push_back(*parent);
- continue;
- }
-
-#ifdef DEBUG_STABLE_CONES
- cout << endl << endl;
- cout << "plot 'particles.dat' u 2:1 pt 1 ps 3" << endl;
- cout << "set label 1 'x' at " << parent->_phi << ", " << parent->_theta << endl;
-#endif
-
- // step 1: initialise with the first cone candidate
- init_cone();
-
- do{
- // step 2: test cone stability for that pair (P,C)
- test_cone();
-
- // step 3: go to the next cone child candidate C
- } while (!update_cone());
- }
-
- return proceed_with_stability();
-}
-
-
-////////////////////////////////////////////////////////
-// ALGORITHM MAIN STEPS //
-// - init_cone() //
-// - test_cone() //
-// - update_cone() //
-// - proceed_with_stability() //
-////////////////////////////////////////////////////////
-
-/*
- * initialise the cone.
- * We take the first particle in the angular ordering to compute
- * this one
- * return 0 on success, 1 on error
- *********************************************************************/
-int Cstable_cones::init_cone(){
- // The previous version of the algorithm was starting the
- // loop around vicinity elements with the "most isolated" child.
- // given the nodist method to calculate the cone contents, we no
- // longer need to worry about which cone comes first...
- first_cone=0;
-
- // now make sure we have lists of the cocircular particles
- prepare_cocircular_lists();
-
- //TODO? deal with a configuration with only degeneracies ?
- // The only possibility seems a regular hexagon with a parent point
- // in the centre. And this situation is by itself unclear.
- // Hence, we do nothing here !
-
- // init set child C
- centre = vicinity[first_cone];
- child = centre->v;
- centre_idx = first_cone;
-
- // build the initial cone (nodist: avoids calculating distances --
- // just deduces contents by circulating around all in/out operations)
- // this function also sets the list of included particles
- compute_cone_contents();
-
- return 0;
-}
-
-
-/*
- * test cones.
- * We check if the cone(s) built with the present parent and child
- * are stable
- * return 0 on success 1 on error
- *********************************************************************/
-int Cstable_cones::test_cone(){
- Creference weighted_cone_ref;
-
- // depending on the side we are taking the child particle,
- // we test different configuration.
- // Each time, two configurations are tested in such a way that
- // all 4 possible cases (parent or child in or out the cone)
- // are tested when taking the pair of particle parent+child
- // and child+parent.
-
- // here are the tests entering the first series:
- // 1. check if the cone is already inserted
- // 2. check cone stability for the parent and child particles
-
- //UPDATED(see below): if (centre->side){
- //UPDATED(see below): // test when both particles are not in the cone
- //UPDATED(see below): // or when both are in.
- //UPDATED(see below): // Note: for the totally exclusive case, test emptyness before
- //UPDATED(see below): cone_candidate = cone;
- //UPDATED(see below): if (cone.ref.not_empty()){
- //UPDATED(see below): hc->insert(&cone_candidate, parent, child, false, false);
- //UPDATED(see below): }
- //UPDATED(see below):
- //UPDATED(see below): cone_candidate = cone;
- //UPDATED(see below): cone_candidate+= *parent + *child;
- //UPDATED(see below): hc->insert(&cone_candidate, parent, child, true, true);
- //UPDATED(see below): } else {
- //UPDATED(see below): // test when 1! of the particles is in the cone
- //UPDATED(see below): cone_candidate = cone + *parent;
- //UPDATED(see below): hc->insert(&cone_candidate, parent, child, true, false);
- //UPDATED(see below):
- //UPDATED(see below): cone_candidate = cone + *child;
- //UPDATED(see below): hc->insert(&cone_candidate, parent, child, false, true);
- //UPDATED(see below): }
- //UPDATED(see below):
- //UPDATED(see below): nb_tot+=2;
-
- // instead of testing 2 inclusion/exclusion states for every pair, we test the 4 of them
- // when the parent has an energy bigger than the child
- if (parent->E >= child->E){
- // test when both particles are not in the cone
- // Note: for the totally exclusive case, test emptyness before
- cone_candidate = cone;
- if (cone.ref.not_empty()){
- hc->insert(&cone_candidate, parent, child, false, false);
- }
-
- // test when 1! of the particles is in the cone
- cone_candidate += *parent;
- hc->insert(&cone_candidate, parent, child, true, false);
-
- cone_candidate = cone;
- cone_candidate += *child;
- hc->insert(&cone_candidate, parent, child, false, true);
-
- // test when both are in.
- cone_candidate += *parent;
- hc->insert(&cone_candidate, parent, child, true, true);
-
- nb_tot += 4;
- }
-
-
- return 0;
-}
-
-
-/*
- * update the cone
- * go to the next child for that parent and update 'cone' appropriately
- * return 0 if update candidate found, 1 otherwise
- ***********************************************************************/
-int Cstable_cones::update_cone(){
-#ifdef DEBUG_STABLE_CONES
- cout << "call 'circles_plot.gp' '" << centre->centre.px << "' '"
- << centre->centre.py << "' '" << centre->centre.pz << "'" << endl
- << "pause -1 '(" << centre->angle << " " << (centre->side ? '+' : '-') << ")";
-#endif
-
- // get the next child and centre
- centre_idx++;
- if (centre_idx==vicinity_size)
- centre_idx=0;
- if (centre_idx==first_cone)
- return 1;
-
- // update the cone w.r.t. the old child
- // only required if the old child is entering inside in which
- // case we need to add it. We also know that the child is
- // inside iff its side is -.
- if (!centre->side){
-#ifdef DEBUG_STABLE_CONES
- cout << " old_enter";
-#endif
- // update cone
- cone += (*child);
-
- // update info on particles inside
- centre->is_inside->cone = true;
-
- // update stability check quantities
- dpt += fabs(child->px)+fabs(child->py)+fabs(child->pz);
- }
-
- // update centre and child to correspond to the new position
- centre = vicinity[centre_idx];
- child = centre->v;
-
- // check cocircularity
- // note that if cocirculaity is detected (i.e. if we receive 1
- // in the next test), we need to recall 'update_cone' directly
- // since tests and remaining part of te update has been performed
- //if (cocircular_check())
- if (cocircular_check()){
-#ifdef DEBUG_STABLE_CONES
- cout << " Co-circular case detected" << endl;
-#endif
- return update_cone();
- }
-
- // update the cone w.r.t. the new child
- // only required if the new child was already inside in which
- // case we need to remove it. We also know that the child is
- // inside iff its side is +.
- if ((centre->side) && (cone.ref.not_empty())){
-#ifdef DEBUG_STABLE_CONES
- cout << " new exit";
-#endif
-
- // update cone
- cone -= (*child);
-
- // update info on particles inside
- centre->is_inside->cone = false;
-
- // update stability check quantities
- dpt += fabs(child->px)+fabs(child->py)+fabs(child->pz); //child->perp2();
- }
-
- // check that the addition and subtraction of vectors does
- // not lead to too much rounding error
- // for that, we compute the sum of pt modifications and of |pt|
- // since last recomputation and once the ratio overpasses a threshold
- // we recompute vicinity.
- if ((dpt>PT_TSHOLD*(fabs(cone.px)+fabs(cone.py)+fabs(cone.pz))) && (cone.ref.not_empty())){
- recompute_cone_contents();
- }
- if (cone.ref.is_empty()){
- cone = Cmomentum();
- dpt=0.0;
- }
-
-#ifdef DEBUG_STABLE_CONES
- cout << "'" << endl;
-#endif
-
- return 0;
-}
-
-
-/*
- * compute stability of all enumerated candidates.
- * For all candidate cones which are stable w.r.t. their border particles,
- * pass the last test: stability with quadtree intersection
- ************************************************************************/
-int Cstable_cones::proceed_with_stability(){
- int i,n;
- hash_element *elm;
-
- n=0;
- for (i=0;i<=hc->mask;i++){
- // test ith cell of the hash array
- elm = hc->hash_array[i];
-
- // browse elements therein
- while (elm!=NULL){
- // test stability
- if (elm->is_stable){
- // stability is not ensured by all pairs of "edges" already browsed
-#ifdef USE_QUADTREE_FOR_STABILITY_TEST
- // => testing stability with quadtree intersection
- if (quadtree->circle_intersect(elm->eta, elm->phi, R2)==elm->ref)
-#else
- // => testing stability with the particle-list intersection
- if (circle_intersect(elm->centre)==elm->centre.ref)
-#endif
- protocones.push_back(Cmomentum(elm->centre,1.0));
- }
-
- // jump to the next one
- elm = elm->next;
- }
- }
-
- // free hash
- // we do that at this level because hash eats rather a lot of memory
- // we want to free it before running the split/merge algorithm
-#ifdef DEBUG_STABLE_CONES
- nb_hash_cones = hc->n_cones;
- nb_hash_occupied = hc->n_occupied_cells;
-#endif
-
- delete hc;
- hc=NULL;
-
- return protocones.size();
-}
-
-
-////////////////////////////////////////////////////////
-// ALGORITHM MAIN STEPS FOR COCIRCULAR SITUATIONS //
-// - cocircular_pt_less(v1, v2) //
-// - prepare_cocircular_list() //
-// - test_cone_cocircular() //
-// - test_stability(candidate, border_vect) //
-// - updat_cone_cocircular() //
-////////////////////////////////////////////////////////
-
-/// pt-ordering of momenta used for the cocircular case
-//NEVER USED
-//bool cocircular_pt_less(Cmomentum *v1, Cmomentum *v2){
-// return v1->perp2() < v2->perp2();
-//}
-
-/*
- * run through the vicinity of the current parent and for each child
- * establish which other members are cocircular... Note that the list
- * associated with each child contains references to vicinity
- * elements: thus two vicinity elements each associated with one given
- * particle may appear in a list -- this needs to be watched out for
- * later on...
- **********************************************************************/
-void Cstable_cones::prepare_cocircular_lists() {
- circulator<vector<Cvicinity_elm*>::iterator > here(vicinity.begin(),
- vicinity.begin(),
- vicinity.end());
-
- circulator<vector<Cvicinity_elm*>::iterator > search(here);
-
- do {
- Cvicinity_elm* here_pntr = *here();
- search.set_position(here);
-
- // search forwards for things that should have "here" included in
- // their cocircularity list
- while (true) {
- ++search;
- if ( abs_dphi((*search())->angle, here_pntr->angle) <
- here_pntr->cocircular_range
- && search() != here()) {
- (*search())->cocircular.push_back(here_pntr);
- } else {
- break;
- }
- }
-
- // search backwards
- search.set_position(here);
- while (true) {
- --search;
- if ( abs_dphi((*search())->angle, here_pntr->angle) <
- here_pntr->cocircular_range
- && search() != here()) {
- (*search())->cocircular.push_back(here_pntr);
- } else {
- break;
- }
- }
-
- ++here;
- } while (here() != vicinity.begin());
-}
-
-/*
- * Testing cocircular configurations in p^3 time,
- * rather than 2^p time; we will test all contiguous subsets of points
- * on the border --- note that this is till probably overkill, since
- * in principle we only have to test situations where up to a
- * half-circle is filled (but going to a full circle is simpler)
- ******************************************************************/
-void Cstable_cones::test_cone_cocircular(Cmomentum & borderless_cone,
- list<Cmomentum *> & border_list) {
- // in spherical coordinates, we don't have a universal x-y axis system
- // to measure the angles. So we first determine one minimising
- // the uncertainties
- C3vector angl_dir1, angl_dir2;
- centre->centre.get_angular_directions(angl_dir1, angl_dir2);
- angl_dir1/=angl_dir1._norm;
- angl_dir2/=angl_dir2._norm;
-
- // now we have te reference axis, create the Cborder_store structure
- vector<Cborder_store> border_vect;
- border_vect.reserve(border_list.size());
- for (list<Cmomentum *>::iterator it = border_list.begin();
- it != border_list.end(); it++) {
- border_vect.push_back(Cborder_store(*it, centre->centre, angl_dir1, angl_dir2));
- }
-
- // get them into order of angle
- sort(border_vect.begin(), border_vect.end());
-
- // set up some circulators, since these will help us go around the
- // circle easily
- circulator<vector<Cborder_store>::iterator >
- start(border_vect.begin(), border_vect.begin(),border_vect.end());
- circulator<vector<Cborder_store>::iterator > mid(start), end(start);
-
- // test the borderless cone
- Cmomentum candidate = borderless_cone;
- //candidate.build_etaphi();
- if (candidate.ref.not_empty())
- test_stability(candidate, border_vect);
-
- do {
- // reset status wrt inclusion in the cone
- mid = start;
- do {
- mid()->is_in = false;
- } while (++mid != start);
-
- // now run over all inclusion possibilities with this starting point
- candidate = borderless_cone;
- while (++mid != start) {
- // will begin with start+1 and go up to start-1
- mid()->is_in = true;
- candidate += *(mid()->mom);
- test_stability(candidate, border_vect);
- }
-
- } while (++start != end);
-
- // mid corresponds to momentum that we need to include to get the
- // full cone
- mid()->is_in = true;
- candidate += *(mid()->mom);
- test_stability(candidate, border_vect);
-}
-
-
-/**
- * carry out the computations needed for the stability check of the
- * candidate, using the border_vect to indicate which particles
- * should / should not be in the stable cone; if the cone is stable
- * insert it into the hash.
- **********************************************************************/
-void Cstable_cones::test_stability(Cmomentum & candidate, const vector<Cborder_store> & border_vect) {
-
- // this almost certainly has not been done...
- //candidate.build_etaphi();
-
- bool stable = true;
- for (unsigned i = 0; i < border_vect.size(); i++) {
- if (is_closer(&candidate, border_vect[i].mom,tan2R) ^ (border_vect[i].is_in)) {
- stable = false;
- break; // it's unstable so there's no point continuing
- }
- }
-
- if (stable) hc->insert(&candidate);
-}
-
-/*
- * check if we are in a situation of cocircularity.
- * if it is the case, update and test in the corresponding way
- * return 'false' if no cocircularity detected, 'true' otherwise
- * Note that if cocircularity is detected, we need to
- * recall 'update' from 'update' !!!
- ***************************************************************/
-bool Cstable_cones::cocircular_check(){
- // check if many configurations have the same centre.
- // if this is the case, branch on the algorithm for this
- // special case.
- // Note that those situation, being considered separately in
- // test_cone_multiple, must only be considered here if all
- // angles are on the same side (this avoid multiple counting)
-
- if (centre->cocircular.empty()) return false;
-
- // first get cone into status required at end...
- if ((centre->side) && (cone.ref.not_empty())){
- // update cone
- cone -= (*child);
-
- // update info on particles inside
- centre->is_inside->cone = false;
-
- // update stability check quantities
- dpt += fabs(child->px)+fabs(child->py)+fabs(child->pz); //child->perp2();
- }
-
-
- // now establish the list of unique children in the list
- // first make sure parent and child are in!
-
- list<Cvicinity_inclusion *> removed_from_cone;
- list<Cvicinity_inclusion *> put_in_border;
- list<Cmomentum *> border_list;
-
- Cmomentum cone_removal;
- Cmomentum border = *parent;
- border_list.push_back(parent);
-
- // make sure child appears in the border region
- centre->cocircular.push_back(centre);
-
- // now establish the full contents of the cone minus the cocircular
- // region and of the cocircular region itself
- for(list<Cvicinity_elm *>::iterator it = centre->cocircular.begin();
- it != centre->cocircular.end(); it++) {
-
- if ((*it)->is_inside->cone) {
- cone_removal += *((*it)->v);
- (*it)->is_inside->cone = false;
- removed_from_cone.push_back((*it)->is_inside);
- }
-
- // if a point appears twice (i.e. with + and - sign) in the list of
- // points on the border, we take care not to include it twice.
- // Note that this situation may appear when a point is at a distance
- // close to 2R from the parent
- if (!(*it)->is_inside->cocirc) {
- border += *((*it)->v);
- (*it)->is_inside->cocirc = true;
- put_in_border.push_back((*it)->is_inside);
- border_list.push_back((*it)->v);
- //cout << " adding particle " << (*it)->v->_theta << ", " << (*it)->v->_phi << " to the border list" << endl;
- }
- }
-
-
- // figure out whether this pairing has been observed before
- Cmomentum borderless_cone = cone;
- borderless_cone -= cone_removal;
- bool consider = true;
- for (unsigned int i=0;i<multiple_centre_done.size();i++){
- if ((multiple_centre_done[i].first ==borderless_cone.ref) &&
- (multiple_centre_done[i].second==border.ref))
- consider = false;
- }
-
- // now prepare the hard work
- if (consider) {
- // record the fact that we've now seen this combination
- multiple_centre_done.push_back(pair<Creference,Creference>(borderless_cone.ref,
- border.ref));
-
- // first figure out whether our cone momentum is good
- double local_dpt = fabs(cone_removal.px) + fabs(cone_removal.py);
- double total_dpt = dpt + local_dpt;
-
- recompute_cone_contents_if_needed(borderless_cone, total_dpt);
- if (total_dpt == 0) {
- // a recomputation has taken place -- so take advantage of this
- // and update the member cone momentum
- cone = borderless_cone + cone_removal;
- dpt = local_dpt;
- }
-
- test_cone_cocircular(borderless_cone, border_list);
- }
-
-
- // relabel things that were in the cone but got removed
- for(list<Cvicinity_inclusion *>::iterator is_in = removed_from_cone.begin();
- is_in != removed_from_cone.end(); is_in++) {
- (*is_in)->cone = true;
- }
-
- // relabel things that got put into the border
- for(list<Cvicinity_inclusion *>::iterator is_in = put_in_border.begin();
- is_in != put_in_border.end(); is_in++) {
- (*is_in)->cocirc = false;
- }
-
- // we're done with everything -- return true to signal to user that we've
- // been through the co-circularity rigmarole
- return true;
-}
-
-
-////////////////////////////////////////////////////////
-// RECOMPUTATION OF CONE CONTENTS //
-// - compute_cone_contents() //
-// - recompute_cone_contents() //
-// - recompute_cone_contents_if_needed() //
-////////////////////////////////////////////////////////
-
-/**
- * compute the cone contents by going once around the full set of
- * circles and tracking the entry/exit status each time
- * given parent, child and centre compute the momentum
- * of the particle inside the cone
- * This sets up the inclusion information, which can then be directly
- * used to calculate the cone momentum.
- **********************************************************************/
-void Cstable_cones::compute_cone_contents() {
- circulator<vector<Cvicinity_elm*>::iterator >
- start(vicinity.begin()+first_cone, vicinity.begin(), vicinity.end());
-
- circulator<vector<Cvicinity_elm*>::iterator > here(start);
-
- // note that in the following algorithm, the cone contents never includes
- // the child. Indeed, if it has positive sign, then it will be set as
- // outside at the last step in the loop. If it has negative sign, then the
- // loop will at some point go to the corresponding situation with positive
- // sign and set the inclusion status to 0.
-
- do {
- // as we leave this position a particle enters if its side is
- // negative (i.e. the centre is the one at -ve angle wrt to the
- // parent-child line
- if (!(*here())->side) ((*here())->is_inside->cone) = 1;
-
- // move on to the next position
- ++here;
-
- // as we arrive at this position a particle leaves if its side is positive
- if ((*here())->side) ((*here())->is_inside->cone) = 0;
- } while (here != start);
-
- // once we've reached the start the 'is_inside' information should be
- // 100% complete, so we can use it to calculate the cone contents
- // and then exit
- recompute_cone_contents();
- return;
-
-}
-
-
-/*
- * compute the cone momentum from particle list.
- * in this version, we use the 'pincluded' information
- * from the Cvicinity class
- */
-void Cstable_cones::recompute_cone_contents(){
- unsigned int i;
-
- // set momentum to 0
- cone = Cmomentum();
-
- // Important note: we can browse only the particles
- // in vicinity since all particles in the cone are
- // withing a distance 2R w.r.t. parent hence in vicinity.
- // Among those, we only add the particles for which 'is_inside' is true !
- // This methos rather than a direct comparison avoids rounding errors
- for (i=0;i<vicinity_size;i++){
- // to avoid double-counting, only use particles with + angle
- if ((vicinity[i]->side) && (vicinity[i]->is_inside->cone))
- cone += *vicinity[i]->v;
- }
-
- // set check variables back to 0
- dpt = 0.0;
-}
-
-
-/*
- * if we have gone beyond the acceptable threshold of change, compute
- * the cone momentum from particle list. in this version, we use the
- * 'pincluded' information from the Cvicinity class, but we don't
- * change the member cone, only the locally supplied one
- */
-void Cstable_cones::recompute_cone_contents_if_needed(Cmomentum & this_cone,
- double & this_dpt){
-
- if (this_dpt > PT_TSHOLD*(fabs(this_cone.px)+fabs(this_cone.py))) {
- if (cone.ref.is_empty()) {
- this_cone = Cmomentum();
- } else {
- // set momentum to 0
- this_cone = Cmomentum();
-
- // Important note: we can browse only the particles
- // in vicinity since all particles in the this_cone are
- // withing a distance 2R w.r.t. parent hence in vicinity.
- // Among those, we only add the particles for which 'is_inside' is true !
- // This methos rather than a direct comparison avoids rounding errors
- for (unsigned int i=0;i<vicinity_size;i++){
- // to avoid double-counting, only use particles with + angle
- if ((vicinity[i]->side) && (vicinity[i]->is_inside->cone))
- this_cone += *vicinity[i]->v;
- }
-
- }
- // set check variables back to 0
- this_dpt = 0.0;
- }
-
-}
-
-
-////////////////////////////////////////////////////////
-// VARIOUS TOOLS //
-// - circle_intersect() //
-// - is_inside() //
-// - abs_dangle() //
-////////////////////////////////////////////////////////
-
-
-/*
- * circle intersection.
- * computes the intersection with a circle of given centre and radius.
- * The output takes the form of a checkxor of the intersection's particles
- * - cx circle centre x coordinate
- * - cy circle centre y coordinate
- * return the checkxor for the intersection
- ******************************************************************/
-Creference Cstable_cones::circle_intersect(C3vector &cone_centre){
- Creference intersection;
- int i;
-
- for (i=0;i<n_part;i++){
- // really check if the distance is less than R
- if (is_closer(&cone_centre, &(plist[i]), tan2R))
- intersection+=plist[i].ref;
- }
-
- return intersection;
-}
-
-}
Index: branches/spherical/siscone/spherical/protocones.cpp
===================================================================
--- branches/spherical/siscone/spherical/protocones.cpp (revision 0)
+++ branches/spherical/siscone/spherical/protocones.cpp (revision 242)
@@ -0,0 +1,863 @@
+///////////////////////////////////////////////////////////////////////////////
+// File: protocones.cpp //
+// Description: source file for stable cones determination (Cstable_cones) //
+// This file is part of the SISCone project. //
+// WARNING: this is not the main SISCone trunk but //
+// an adaptation to spherical coordinates //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: $//
+// $Date:: $//
+///////////////////////////////////////////////////////////////////////////////
+
+/*******************************************************
+ * Introductory note: *
+ * Since this file has many member functions, we have *
+ * structured them in categories: *
+ * INITIALISATION FUNCTIONS *
+ * - ctor() *
+ * - ctor(particle_list) *
+ * - dtor() *
+ * - init(particle_list) *
+ * ALGORITHM MAIN ENTRY *
+ * - get_stable_cone(radius) *
+ * ALGORITHM MAIN STEPS *
+ * - init_cone() *
+ * - test_cone() *
+ * - update_cone() *
+ * - proceed_with_stability() *
+ * ALGORITHM MAIN STEPS FOR COCIRCULAR SITUATIONS *
+ * - cocircular_pt_less(v1, v2) *
+ * - prepare_cocircular_list() *
+ * - test_cone_cocircular() *
+ * - test_stability(candidate, border_list) *
+ * - updat_cone_cocircular() *
+ * RECOMPUTATION OF CONE CONTENTS *
+ * - compute_cone_contents() *
+ * - recompute_cone_contents() *
+ * - recompute_cone_contents_if_needed() *
+ * VARIOUS TOOLS *
+ * - circle_intersect() *
+ * - is_inside() *
+ * - abs_dangle() *
+ *******************************************************/
+
+#include "protocones.h"
+#include "siscone_error.h"
+#include "defines.h"
+#include <math.h>
+#include <iostream>
+#include "circulator.h"
+#include <algorithm>
+
+namespace siscone{
+
+using namespace std;
+
+/**********************************************************************
+ * Cstable_cones implementation *
+ * Computes the list of stable comes from a particle list. *
+ * This class does the first fundamental task of te cone algorithm: *
+ * it is used to compute the list of stable cones given a list *
+ * of particles. *
+ **********************************************************************/
+
+////////////////////////////////////////////////////////
+// INITIALISATION FUNCTIONS //
+// - ctor() //
+// - ctor(particle_list) //
+// - dtor() //
+// - init(particle_list) //
+////////////////////////////////////////////////////////
+
+// default ctor
+//--------------
+Cstable_cones::Cstable_cones(){
+ nb_tot = 0;
+ hc = NULL;
+}
+
+// ctor with initialisation
+//--------------------------
+Cstable_cones::Cstable_cones(vector<Cmomentum> &_particle_list)
+ : Cvicinity(_particle_list){
+
+ nb_tot = 0;
+ hc = NULL;
+}
+
+// default dtor
+//--------------
+Cstable_cones::~Cstable_cones(){
+ if (hc!=NULL) delete hc;
+}
+
+/*
+ * initialisation
+ * - _particle_list list of particles
+ * - _n number of particles
+ *********************************************************************/
+void Cstable_cones::init(vector<Cmomentum> &_particle_list){
+ // check already allocated mem
+ if (hc!=NULL){
+ delete hc;
+ }
+ if (protocones.size()!=0)
+ protocones.clear();
+
+ multiple_centre_done.clear();
+
+ // initialisation
+ set_particle_list(_particle_list);
+}
+
+
+////////////////////////////////////////////////////////
+// ALGORITHM MAIN ENTRY //
+// - get_stable_cone(radius) //
+////////////////////////////////////////////////////////
+
+/*
+ * compute stable cones.
+ * This function really does the job i.e. computes
+ * the list of stable cones (in a seedless way)
+ * - _radius: radius of the cones
+ * The number of stable cones found is returned
+ *********************************************************************/
+int Cstable_cones::get_stable_cones(double _radius){
+ int p_idx;
+
+ // check if everything is correctly initialised
+ if (n_part==0){
+ return 0;
+ }
+
+ R = _radius;
+ R2 = R*R;
+ tan2R = tan(R);
+ tan2R *= tan2R;
+
+ // allow hash for cones candidates
+ hc = new hash_cones(n_part, R);
+
+ // browse all particles
+ for (p_idx=0;p_idx<n_part;p_idx++){
+ // step 0: compute the child list CL.
+ // Note that this automatically sets the parent P
+ build(&plist[p_idx], 2.0*R);
+
+ // special case:
+ // if the vicinity is empty, the parent particle is a
+ // stable cone by itself. Add it to protocones list.
+ if (vicinity_size==0){
+ protocones.push_back(*parent);
+ continue;
+ }
+
+#ifdef DEBUG_STABLE_CONES
+ cout << endl << endl;
+ cout << "plot 'particles.dat' u 2:1 pt 1 ps 3" << endl;
+ cout << "set label 1 'x' at " << parent->_phi << ", " << parent->_theta << endl;
+#endif
+
+ // step 1: initialise with the first cone candidate
+ init_cone();
+
+ do{
+ // step 2: test cone stability for that pair (P,C)
+ test_cone();
+
+ // step 3: go to the next cone child candidate C
+ } while (!update_cone());
+ }
+
+ return proceed_with_stability();
+}
+
+
+////////////////////////////////////////////////////////
+// ALGORITHM MAIN STEPS //
+// - init_cone() //
+// - test_cone() //
+// - update_cone() //
+// - proceed_with_stability() //
+////////////////////////////////////////////////////////
+
+/*
+ * initialise the cone.
+ * We take the first particle in the angular ordering to compute
+ * this one
+ * return 0 on success, 1 on error
+ *********************************************************************/
+int Cstable_cones::init_cone(){
+ // The previous version of the algorithm was starting the
+ // loop around vicinity elements with the "most isolated" child.
+ // given the nodist method to calculate the cone contents, we no
+ // longer need to worry about which cone comes first...
+ first_cone=0;
+
+ // now make sure we have lists of the cocircular particles
+ prepare_cocircular_lists();
+
+ //TODO? deal with a configuration with only degeneracies ?
+ // The only possibility seems a regular hexagon with a parent point
+ // in the centre. And this situation is by itself unclear.
+ // Hence, we do nothing here !
+
+ // init set child C
+ centre = vicinity[first_cone];
+ child = centre->v;
+ centre_idx = first_cone;
+
+ // build the initial cone (nodist: avoids calculating distances --
+ // just deduces contents by circulating around all in/out operations)
+ // this function also sets the list of included particles
+ compute_cone_contents();
+
+ return 0;
+}
+
+
+/*
+ * test cones.
+ * We check if the cone(s) built with the present parent and child
+ * are stable
+ * return 0 on success 1 on error
+ *********************************************************************/
+int Cstable_cones::test_cone(){
+ Creference weighted_cone_ref;
+
+ // depending on the side we are taking the child particle,
+ // we test different configuration.
+ // Each time, two configurations are tested in such a way that
+ // all 4 possible cases (parent or child in or out the cone)
+ // are tested when taking the pair of particle parent+child
+ // and child+parent.
+
+ // here are the tests entering the first series:
+ // 1. check if the cone is already inserted
+ // 2. check cone stability for the parent and child particles
+
+ //UPDATED(see below): if (centre->side){
+ //UPDATED(see below): // test when both particles are not in the cone
+ //UPDATED(see below): // or when both are in.
+ //UPDATED(see below): // Note: for the totally exclusive case, test emptyness before
+ //UPDATED(see below): cone_candidate = cone;
+ //UPDATED(see below): if (cone.ref.not_empty()){
+ //UPDATED(see below): hc->insert(&cone_candidate, parent, child, false, false);
+ //UPDATED(see below): }
+ //UPDATED(see below):
+ //UPDATED(see below): cone_candidate = cone;
+ //UPDATED(see below): cone_candidate+= *parent + *child;
+ //UPDATED(see below): hc->insert(&cone_candidate, parent, child, true, true);
+ //UPDATED(see below): } else {
+ //UPDATED(see below): // test when 1! of the particles is in the cone
+ //UPDATED(see below): cone_candidate = cone + *parent;
+ //UPDATED(see below): hc->insert(&cone_candidate, parent, child, true, false);
+ //UPDATED(see below):
+ //UPDATED(see below): cone_candidate = cone + *child;
+ //UPDATED(see below): hc->insert(&cone_candidate, parent, child, false, true);
+ //UPDATED(see below): }
+ //UPDATED(see below):
+ //UPDATED(see below): nb_tot+=2;
+
+ // instead of testing 2 inclusion/exclusion states for every pair, we test the 4 of them
+ // when the parent has an energy bigger than the child
+ if (parent->E >= child->E){
+ // test when both particles are not in the cone
+ // Note: for the totally exclusive case, test emptyness before
+ cone_candidate = cone;
+ if (cone.ref.not_empty()){
+ hc->insert(&cone_candidate, parent, child, false, false);
+ }
+
+ // test when 1! of the particles is in the cone
+ cone_candidate += *parent;
+ hc->insert(&cone_candidate, parent, child, true, false);
+
+ cone_candidate = cone;
+ cone_candidate += *child;
+ hc->insert(&cone_candidate, parent, child, false, true);
+
+ // test when both are in.
+ cone_candidate += *parent;
+ hc->insert(&cone_candidate, parent, child, true, true);
+
+ nb_tot += 4;
+ }
+
+
+ return 0;
+}
+
+
+/*
+ * update the cone
+ * go to the next child for that parent and update 'cone' appropriately
+ * return 0 if update candidate found, 1 otherwise
+ ***********************************************************************/
+int Cstable_cones::update_cone(){
+#ifdef DEBUG_STABLE_CONES
+ cout << "call 'circles_plot.gp' '" << centre->centre.px << "' '"
+ << centre->centre.py << "' '" << centre->centre.pz << "'" << endl
+ << "pause -1 '(" << centre->angle << " " << (centre->side ? '+' : '-') << ")";
+#endif
+
+ // get the next child and centre
+ centre_idx++;
+ if (centre_idx==vicinity_size)
+ centre_idx=0;
+ if (centre_idx==first_cone)
+ return 1;
+
+ // update the cone w.r.t. the old child
+ // only required if the old child is entering inside in which
+ // case we need to add it. We also know that the child is
+ // inside iff its side is -.
+ if (!centre->side){
+#ifdef DEBUG_STABLE_CONES
+ cout << " old_enter";
+#endif
+ // update cone
+ cone += (*child);
+
+ // update info on particles inside
+ centre->is_inside->cone = true;
+
+ // update stability check quantities
+ dpt += fabs(child->px)+fabs(child->py)+fabs(child->pz);
+ }
+
+ // update centre and child to correspond to the new position
+ centre = vicinity[centre_idx];
+ child = centre->v;
+
+ // check cocircularity
+ // note that if cocirculaity is detected (i.e. if we receive 1
+ // in the next test), we need to recall 'update_cone' directly
+ // since tests and remaining part of te update has been performed
+ //if (cocircular_check())
+ if (cocircular_check()){
+#ifdef DEBUG_STABLE_CONES
+ cout << " Co-circular case detected" << endl;
+#endif
+ return update_cone();
+ }
+
+ // update the cone w.r.t. the new child
+ // only required if the new child was already inside in which
+ // case we need to remove it. We also know that the child is
+ // inside iff its side is +.
+ if ((centre->side) && (cone.ref.not_empty())){
+#ifdef DEBUG_STABLE_CONES
+ cout << " new exit";
+#endif
+
+ // update cone
+ cone -= (*child);
+
+ // update info on particles inside
+ centre->is_inside->cone = false;
+
+ // update stability check quantities
+ dpt += fabs(child->px)+fabs(child->py)+fabs(child->pz); //child->perp2();
+ }
+
+ // check that the addition and subtraction of vectors does
+ // not lead to too much rounding error
+ // for that, we compute the sum of pt modifications and of |pt|
+ // since last recomputation and once the ratio overpasses a threshold
+ // we recompute vicinity.
+ if ((dpt>PT_TSHOLD*(fabs(cone.px)+fabs(cone.py)+fabs(cone.pz))) && (cone.ref.not_empty())){
+ recompute_cone_contents();
+ }
+ if (cone.ref.is_empty()){
+ cone = Cmomentum();
+ dpt=0.0;
+ }
+
+#ifdef DEBUG_STABLE_CONES
+ cout << "'" << endl;
+#endif
+
+ return 0;
+}
+
+
+/*
+ * compute stability of all enumerated candidates.
+ * For all candidate cones which are stable w.r.t. their border particles,
+ * pass the last test: stability with quadtree intersection
+ ************************************************************************/
+int Cstable_cones::proceed_with_stability(){
+ int i,n;
+ hash_element *elm;
+
+ n=0;
+ for (i=0;i<=hc->mask;i++){
+ // test ith cell of the hash array
+ elm = hc->hash_array[i];
+
+ // browse elements therein
+ while (elm!=NULL){
+ // test stability
+ if (elm->is_stable){
+ // stability is not ensured by all pairs of "edges" already browsed
+#ifdef USE_QUADTREE_FOR_STABILITY_TEST
+ // => testing stability with quadtree intersection
+ if (quadtree->circle_intersect(elm->eta, elm->phi, R2)==elm->ref)
+#else
+ // => testing stability with the particle-list intersection
+ if (circle_intersect(elm->centre)==elm->centre.ref)
+#endif
+ protocones.push_back(Cmomentum(elm->centre,1.0));
+ }
+
+ // jump to the next one
+ elm = elm->next;
+ }
+ }
+
+ // free hash
+ // we do that at this level because hash eats rather a lot of memory
+ // we want to free it before running the split/merge algorithm
+#ifdef DEBUG_STABLE_CONES
+ nb_hash_cones = hc->n_cones;
+ nb_hash_occupied = hc->n_occupied_cells;
+#endif
+
+ delete hc;
+ hc=NULL;
+
+ return protocones.size();
+}
+
+
+////////////////////////////////////////////////////////
+// ALGORITHM MAIN STEPS FOR COCIRCULAR SITUATIONS //
+// - cocircular_pt_less(v1, v2) //
+// - prepare_cocircular_list() //
+// - test_cone_cocircular() //
+// - test_stability(candidate, border_vect) //
+// - updat_cone_cocircular() //
+////////////////////////////////////////////////////////
+
+/// pt-ordering of momenta used for the cocircular case
+//NEVER USED
+//bool cocircular_pt_less(Cmomentum *v1, Cmomentum *v2){
+// return v1->perp2() < v2->perp2();
+//}
+
+/*
+ * run through the vicinity of the current parent and for each child
+ * establish which other members are cocircular... Note that the list
+ * associated with each child contains references to vicinity
+ * elements: thus two vicinity elements each associated with one given
+ * particle may appear in a list -- this needs to be watched out for
+ * later on...
+ **********************************************************************/
+void Cstable_cones::prepare_cocircular_lists() {
+ circulator<vector<Cvicinity_elm*>::iterator > here(vicinity.begin(),
+ vicinity.begin(),
+ vicinity.end());
+
+ circulator<vector<Cvicinity_elm*>::iterator > search(here);
+
+ do {
+ Cvicinity_elm* here_pntr = *here();
+ search.set_position(here);
+
+ // search forwards for things that should have "here" included in
+ // their cocircularity list
+ while (true) {
+ ++search;
+ if ( abs_dphi((*search())->angle, here_pntr->angle) <
+ here_pntr->cocircular_range
+ && search() != here()) {
+ (*search())->cocircular.push_back(here_pntr);
+ } else {
+ break;
+ }
+ }
+
+ // search backwards
+ search.set_position(here);
+ while (true) {
+ --search;
+ if ( abs_dphi((*search())->angle, here_pntr->angle) <
+ here_pntr->cocircular_range
+ && search() != here()) {
+ (*search())->cocircular.push_back(here_pntr);
+ } else {
+ break;
+ }
+ }
+
+ ++here;
+ } while (here() != vicinity.begin());
+}
+
+/*
+ * Testing cocircular configurations in p^3 time,
+ * rather than 2^p time; we will test all contiguous subsets of points
+ * on the border --- note that this is till probably overkill, since
+ * in principle we only have to test situations where up to a
+ * half-circle is filled (but going to a full circle is simpler)
+ ******************************************************************/
+void Cstable_cones::test_cone_cocircular(Cmomentum & borderless_cone,
+ list<Cmomentum *> & border_list) {
+ // in spherical coordinates, we don't have a universal x-y axis system
+ // to measure the angles. So we first determine one minimising
+ // the uncertainties
+ C3vector angl_dir1, angl_dir2;
+ centre->centre.get_angular_directions(angl_dir1, angl_dir2);
+ angl_dir1/=angl_dir1._norm;
+ angl_dir2/=angl_dir2._norm;
+
+ // now we have te reference axis, create the Cborder_store structure
+ vector<Cborder_store> border_vect;
+ border_vect.reserve(border_list.size());
+ for (list<Cmomentum *>::iterator it = border_list.begin();
+ it != border_list.end(); it++) {
+ border_vect.push_back(Cborder_store(*it, centre->centre, angl_dir1, angl_dir2));
+ }
+
+ // get them into order of angle
+ sort(border_vect.begin(), border_vect.end());
+
+ // set up some circulators, since these will help us go around the
+ // circle easily
+ circulator<vector<Cborder_store>::iterator >
+ start(border_vect.begin(), border_vect.begin(),border_vect.end());
+ circulator<vector<Cborder_store>::iterator > mid(start), end(start);
+
+ // test the borderless cone
+ Cmomentum candidate = borderless_cone;
+ //candidate.build_etaphi();
+ if (candidate.ref.not_empty())
+ test_stability(candidate, border_vect);
+
+ do {
+ // reset status wrt inclusion in the cone
+ mid = start;
+ do {
+ mid()->is_in = false;
+ } while (++mid != start);
+
+ // now run over all inclusion possibilities with this starting point
+ candidate = borderless_cone;
+ while (++mid != start) {
+ // will begin with start+1 and go up to start-1
+ mid()->is_in = true;
+ candidate += *(mid()->mom);
+ test_stability(candidate, border_vect);
+ }
+
+ } while (++start != end);
+
+ // mid corresponds to momentum that we need to include to get the
+ // full cone
+ mid()->is_in = true;
+ candidate += *(mid()->mom);
+ test_stability(candidate, border_vect);
+}
+
+
+/**
+ * carry out the computations needed for the stability check of the
+ * candidate, using the border_vect to indicate which particles
+ * should / should not be in the stable cone; if the cone is stable
+ * insert it into the hash.
+ **********************************************************************/
+void Cstable_cones::test_stability(Cmomentum & candidate, const vector<Cborder_store> & border_vect) {
+
+ // this almost certainly has not been done...
+ //candidate.build_etaphi();
+
+ bool stable = true;
+ for (unsigned i = 0; i < border_vect.size(); i++) {
+ if (is_closer(&candidate, border_vect[i].mom,tan2R) ^ (border_vect[i].is_in)) {
+ stable = false;
+ break; // it's unstable so there's no point continuing
+ }
+ }
+
+ if (stable) hc->insert(&candidate);
+}
+
+/*
+ * check if we are in a situation of cocircularity.
+ * if it is the case, update and test in the corresponding way
+ * return 'false' if no cocircularity detected, 'true' otherwise
+ * Note that if cocircularity is detected, we need to
+ * recall 'update' from 'update' !!!
+ ***************************************************************/
+bool Cstable_cones::cocircular_check(){
+ // check if many configurations have the same centre.
+ // if this is the case, branch on the algorithm for this
+ // special case.
+ // Note that those situation, being considered separately in
+ // test_cone_multiple, must only be considered here if all
+ // angles are on the same side (this avoid multiple counting)
+
+ if (centre->cocircular.empty()) return false;
+
+ // first get cone into status required at end...
+ if ((centre->side) && (cone.ref.not_empty())){
+ // update cone
+ cone -= (*child);
+
+ // update info on particles inside
+ centre->is_inside->cone = false;
+
+ // update stability check quantities
+ dpt += fabs(child->px)+fabs(child->py)+fabs(child->pz); //child->perp2();
+ }
+
+
+ // now establish the list of unique children in the list
+ // first make sure parent and child are in!
+
+ list<Cvicinity_inclusion *> removed_from_cone;
+ list<Cvicinity_inclusion *> put_in_border;
+ list<Cmomentum *> border_list;
+
+ Cmomentum cone_removal;
+ Cmomentum border = *parent;
+ border_list.push_back(parent);
+
+ // make sure child appears in the border region
+ centre->cocircular.push_back(centre);
+
+ // now establish the full contents of the cone minus the cocircular
+ // region and of the cocircular region itself
+ for(list<Cvicinity_elm *>::iterator it = centre->cocircular.begin();
+ it != centre->cocircular.end(); it++) {
+
+ if ((*it)->is_inside->cone) {
+ cone_removal += *((*it)->v);
+ (*it)->is_inside->cone = false;
+ removed_from_cone.push_back((*it)->is_inside);
+ }
+
+ // if a point appears twice (i.e. with + and - sign) in the list of
+ // points on the border, we take care not to include it twice.
+ // Note that this situation may appear when a point is at a distance
+ // close to 2R from the parent
+ if (!(*it)->is_inside->cocirc) {
+ border += *((*it)->v);
+ (*it)->is_inside->cocirc = true;
+ put_in_border.push_back((*it)->is_inside);
+ border_list.push_back((*it)->v);
+ //cout << " adding particle " << (*it)->v->_theta << ", " << (*it)->v->_phi << " to the border list" << endl;
+ }
+ }
+
+
+ // figure out whether this pairing has been observed before
+ Cmomentum borderless_cone = cone;
+ borderless_cone -= cone_removal;
+ bool consider = true;
+ for (unsigned int i=0;i<multiple_centre_done.size();i++){
+ if ((multiple_centre_done[i].first ==borderless_cone.ref) &&
+ (multiple_centre_done[i].second==border.ref))
+ consider = false;
+ }
+
+ // now prepare the hard work
+ if (consider) {
+ // record the fact that we've now seen this combination
+ multiple_centre_done.push_back(pair<Creference,Creference>(borderless_cone.ref,
+ border.ref));
+
+ // first figure out whether our cone momentum is good
+ double local_dpt = fabs(cone_removal.px) + fabs(cone_removal.py);
+ double total_dpt = dpt + local_dpt;
+
+ recompute_cone_contents_if_needed(borderless_cone, total_dpt);
+ if (total_dpt == 0) {
+ // a recomputation has taken place -- so take advantage of this
+ // and update the member cone momentum
+ cone = borderless_cone + cone_removal;
+ dpt = local_dpt;
+ }
+
+ test_cone_cocircular(borderless_cone, border_list);
+ }
+
+
+ // relabel things that were in the cone but got removed
+ for(list<Cvicinity_inclusion *>::iterator is_in = removed_from_cone.begin();
+ is_in != removed_from_cone.end(); is_in++) {
+ (*is_in)->cone = true;
+ }
+
+ // relabel things that got put into the border
+ for(list<Cvicinity_inclusion *>::iterator is_in = put_in_border.begin();
+ is_in != put_in_border.end(); is_in++) {
+ (*is_in)->cocirc = false;
+ }
+
+ // we're done with everything -- return true to signal to user that we've
+ // been through the co-circularity rigmarole
+ return true;
+}
+
+
+////////////////////////////////////////////////////////
+// RECOMPUTATION OF CONE CONTENTS //
+// - compute_cone_contents() //
+// - recompute_cone_contents() //
+// - recompute_cone_contents_if_needed() //
+////////////////////////////////////////////////////////
+
+/**
+ * compute the cone contents by going once around the full set of
+ * circles and tracking the entry/exit status each time
+ * given parent, child and centre compute the momentum
+ * of the particle inside the cone
+ * This sets up the inclusion information, which can then be directly
+ * used to calculate the cone momentum.
+ **********************************************************************/
+void Cstable_cones::compute_cone_contents() {
+ circulator<vector<Cvicinity_elm*>::iterator >
+ start(vicinity.begin()+first_cone, vicinity.begin(), vicinity.end());
+
+ circulator<vector<Cvicinity_elm*>::iterator > here(start);
+
+ // note that in the following algorithm, the cone contents never includes
+ // the child. Indeed, if it has positive sign, then it will be set as
+ // outside at the last step in the loop. If it has negative sign, then the
+ // loop will at some point go to the corresponding situation with positive
+ // sign and set the inclusion status to 0.
+
+ do {
+ // as we leave this position a particle enters if its side is
+ // negative (i.e. the centre is the one at -ve angle wrt to the
+ // parent-child line
+ if (!(*here())->side) ((*here())->is_inside->cone) = 1;
+
+ // move on to the next position
+ ++here;
+
+ // as we arrive at this position a particle leaves if its side is positive
+ if ((*here())->side) ((*here())->is_inside->cone) = 0;
+ } while (here != start);
+
+ // once we've reached the start the 'is_inside' information should be
+ // 100% complete, so we can use it to calculate the cone contents
+ // and then exit
+ recompute_cone_contents();
+ return;
+
+}
+
+
+/*
+ * compute the cone momentum from particle list.
+ * in this version, we use the 'pincluded' information
+ * from the Cvicinity class
+ */
+void Cstable_cones::recompute_cone_contents(){
+ unsigned int i;
+
+ // set momentum to 0
+ cone = Cmomentum();
+
+ // Important note: we can browse only the particles
+ // in vicinity since all particles in the cone are
+ // withing a distance 2R w.r.t. parent hence in vicinity.
+ // Among those, we only add the particles for which 'is_inside' is true !
+ // This methos rather than a direct comparison avoids rounding errors
+ for (i=0;i<vicinity_size;i++){
+ // to avoid double-counting, only use particles with + angle
+ if ((vicinity[i]->side) && (vicinity[i]->is_inside->cone))
+ cone += *vicinity[i]->v;
+ }
+
+ // set check variables back to 0
+ dpt = 0.0;
+}
+
+
+/*
+ * if we have gone beyond the acceptable threshold of change, compute
+ * the cone momentum from particle list. in this version, we use the
+ * 'pincluded' information from the Cvicinity class, but we don't
+ * change the member cone, only the locally supplied one
+ */
+void Cstable_cones::recompute_cone_contents_if_needed(Cmomentum & this_cone,
+ double & this_dpt){
+
+ if (this_dpt > PT_TSHOLD*(fabs(this_cone.px)+fabs(this_cone.py))) {
+ if (cone.ref.is_empty()) {
+ this_cone = Cmomentum();
+ } else {
+ // set momentum to 0
+ this_cone = Cmomentum();
+
+ // Important note: we can browse only the particles
+ // in vicinity since all particles in the this_cone are
+ // withing a distance 2R w.r.t. parent hence in vicinity.
+ // Among those, we only add the particles for which 'is_inside' is true !
+ // This methos rather than a direct comparison avoids rounding errors
+ for (unsigned int i=0;i<vicinity_size;i++){
+ // to avoid double-counting, only use particles with + angle
+ if ((vicinity[i]->side) && (vicinity[i]->is_inside->cone))
+ this_cone += *vicinity[i]->v;
+ }
+
+ }
+ // set check variables back to 0
+ this_dpt = 0.0;
+ }
+
+}
+
+
+////////////////////////////////////////////////////////
+// VARIOUS TOOLS //
+// - circle_intersect() //
+// - is_inside() //
+// - abs_dangle() //
+////////////////////////////////////////////////////////
+
+
+/*
+ * circle intersection.
+ * computes the intersection with a circle of given centre and radius.
+ * The output takes the form of a checkxor of the intersection's particles
+ * - cx circle centre x coordinate
+ * - cy circle centre y coordinate
+ * return the checkxor for the intersection
+ ******************************************************************/
+Creference Cstable_cones::circle_intersect(C3vector &cone_centre){
+ Creference intersection;
+ int i;
+
+ for (i=0;i<n_part;i++){
+ // really check if the distance is less than R
+ if (is_closer(&cone_centre, &(plist[i]), tan2R))
+ intersection+=plist[i].ref;
+ }
+
+ return intersection;
+}
+
+}
Property changes on: branches/spherical/siscone/spherical/protocones.cpp
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+Date Rev
\ No newline at end of property
Index: branches/spherical/siscone/spherical/vicinity.cpp
===================================================================
--- branches/spherical/siscone/spherical/vicinity.cpp (revision 0)
+++ branches/spherical/siscone/spherical/vicinity.cpp (revision 242)
@@ -0,0 +1,300 @@
+///////////////////////////////////////////////////////////////////////////////
+// File: vicinity.cpp //
+// Description: source file for particle vicinity (Cvicinity class) //
+// This file is part of the SISCone project. //
+// WARNING: this is not the main SISCone trunk but //
+// an adaptation to spherical coordinates //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: $//
+// $Date:: $//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "vicinity.h"
+#include <math.h>
+#include <algorithm>
+#include <iostream>
+
+namespace siscone{
+
+using namespace std;
+
+/*************************************************************
+ * Cvicinity_elm implementation *
+ * element in the vicinity of a parent. *
+ * class used to manage one points in the vicinity *
+ * of a parent point. *
+ *************************************************************/
+
+// ordering pointers to Cvicinity_elm
+//------------------------------------
+bool ve_less(Cvicinity_elm *ve1, Cvicinity_elm *ve2){
+ return ve1->angle < ve2->angle;
+}
+
+
+/*************************************************************
+ * Cvicinity implementation *
+ * list of element in the vicinity of a parent. *
+ * class used to manage the points which are in the vicinity *
+ * of a parent point. The construction of the list can be *
+ * made from a list of points or from a quadtree. *
+ *************************************************************/
+
+// default constructor
+//---------------------
+Cvicinity::Cvicinity(){
+ n_part = 0;
+
+ ve_list = NULL;
+#ifdef USE_QUADTREE_FOR_STABILITY_TEST
+ quadtree = NULL;
+#endif
+
+ parent = NULL;
+ VR2 = VR = 0.0;
+
+}
+
+// constructor with initialisation
+//---------------------------------
+Cvicinity::Cvicinity(vector<Cmomentum> &_particle_list){
+ parent = NULL;
+ ve_list = NULL;
+#ifdef USE_QUADTREE_FOR_STABILITY_TEST
+ quadtree = NULL;
+#endif
+ cosVR = VR2 = tan2R = VR = 0.0;
+
+ set_particle_list(_particle_list);
+}
+
+// default destructor
+//--------------------
+Cvicinity::~Cvicinity(){
+ if (ve_list!=NULL)
+ delete[] ve_list;
+
+#ifdef USE_QUADTREE_FOR_STABILITY_TEST
+ if (quadtree!=NULL)
+ delete quadtree;
+#endif
+}
+
+/*
+ * set the particle_list
+ * - particle_list list of particles (type Cmomentum)
+ * - n number of particles in the list
+ ************************************************************/
+void Cvicinity::set_particle_list(vector<Cmomentum> &_particle_list){
+ int i,j;
+#ifdef USE_QUADTREE_FOR_STABILITY_TEST
+ double eta_max=0.0;
+#endif
+
+ // if the particle list is not empty, destroy it !
+ if (ve_list!=NULL){
+ delete[] ve_list;
+ }
+ vicinity.clear();
+#ifdef USE_QUADTREE_FOR_STABILITY_TEST
+ if (quadtree!=NULL)
+ delete quadtree;
+#endif
+
+ // allocate memory array for particles
+ // Note: - we compute max for |eta|
+ // - we allocate indices to particles
+ n_part = 0;
+ plist.clear();
+ pincluded.clear();
+ for (i=0;i<(int) _particle_list.size();i++){
+ // if a particle is colinear with the beam (infinite rapidity)
+ // we do not take it into account
+ //if (fabs(_particle_list[i].pz)!=_particle_list[i].E){
+ plist.push_back(_particle_list[i]);
+ pincluded.push_back(Cvicinity_inclusion()); // zero inclusion status
+
+ // the parent_index is handled in the split_merge because
+ // of our multiple-pass procedure.
+ // Hence, it is not required here any longer.
+ // plist[n_part].parent_index = i;
+ plist[n_part].index = n_part;
+
+ // make sure the reference is randomly created
+ plist[n_part].ref.randomize();
+
+#ifdef USE_QUADTREE_FOR_STABILITY_TEST
+ if (fabs(plist[n_part].eta)>eta_max) eta_max=fabs(plist[n_part].eta);
+#endif
+ n_part++;
+ //}
+ }
+
+ // allocate quadtree and vicinity_elm list
+ // note: we set phi in [-pi:pi] as it is the natural range for atan2!
+ ve_list = new Cvicinity_elm[2*n_part];
+#ifdef USE_QUADTREE_FOR_STABILITY_TEST
+ eta_max+=0.1;
+ quadtree = new Cquadtree(0.0, 0.0, eta_max, M_PI);
+#endif
+
+ // append particle to the vicinity_elm list
+ j = 0;
+ for (i=0;i<n_part;i++){
+#ifdef USE_QUADTREE_FOR_STABILITY_TEST
+ quadtree->add(&plist[i]);
+#endif
+ ve_list[j].v = ve_list[j+1].v = &plist[i];
+ ve_list[j].is_inside = ve_list[j+1].is_inside = &(pincluded[i]);
+ j+=2;
+ }
+
+}
+
+
+/*
+ * build the vicinity list from a list of points.
+ * - _parent reference particle
+ * - _VR vicinity radius
+ ************************************************************/
+void Cvicinity::build(Cmomentum *_parent, double _VR){
+ int i;
+
+ // set parent and radius
+ parent = _parent;
+
+ VR = _VR;
+ VR2 = VR*VR;
+ cosVR = cos(VR);
+ R2 = 0.25*VR2;
+ R = 0.5*VR;
+ double tmp = tan(R);
+ tan2R = tmp*tmp;
+
+ D2_R = 2.0*(1-cos(R));
+ //tmp = sqrt(D2_R);
+ inv_R_EPS_COCIRC = 1.0 / R / EPSILON_COCIRCULAR;
+ inv_R_2EPS_COCIRC = 0.5 / R / EPSILON_COCIRCULAR;
+
+ // clear vicinity
+ vicinity.clear();
+
+ // init parent variables
+ // we cpte the direction of the centre and two orthogonal ones
+ // to measure the angles. Those are taken orthogonal to the
+ // axis of smallest components (of the centre) to increase precision
+ parent_centre = (*parent)/parent->_norm;
+ parent_centre.get_angular_directions(angular_dir1, angular_dir2);
+ angular_dir1 /= angular_dir1._norm;
+ angular_dir2 /= angular_dir2._norm;
+
+ // really browse the particle list
+ for (i=0;i<n_part;i++){
+ append_to_vicinity(&plist[i]);
+ }
+
+ // sort the vicinity
+ sort(vicinity.begin(), vicinity.end(), ve_less);
+
+ vicinity_size = vicinity.size();
+}
+
+
+/// strictly increasing function of the angle
+//TODO//
+inline double sort_angle(double s, double c){
+ if (s==0) return (c>0) ? 0.0 : 2.0;
+ double t=c/s;
+ return (s>0) ? 1-t/(1+fabs(t)) : 3-t/(1+fabs(t));
+}
+
+
+/*
+ * append a particle to the 'vicinity' list after
+ * having computed the angular-ordering quantities
+ * - v vector to test
+ **********************************************************/
+void Cvicinity::append_to_vicinity(Cmomentum *v){
+ // skip the particle itself)
+ if (v==parent)
+ return;
+
+ int i=2*(v->index);
+
+ // compute the distance of the i-th particle with the parent
+ double dot = dot_product3(parent_centre,*v);
+ C3vector vnormal = *v;
+ vnormal/=v->_norm;
+ dot/=v->_norm;
+
+ // really check if the distance is less than VR
+ if (dot>cosVR){
+ C3vector cross = cross_product3(parent_centre,vnormal);
+
+ // for the centres
+ C3vector median = (parent_centre+vnormal);
+ double amplT = sqrt((tan2R*(1+dot)+(dot-1))*(1+dot));
+ C3vector transverse = amplT*cross/cross._norm;
+
+ // first angle (+)
+ ve_list[i].centre = median + transverse;
+ ve_list[i].centre.build_norm();
+ ve_list[i].centre/=ve_list[i].centre._norm;
+ C3vector diff = ve_list[i].centre - parent_centre;
+ //ve_list[i].angle = atan2(dot_product3(angular_dir2, diff),dot_product3(angular_dir1, diff));
+ ve_list[i].angle = sort_angle(dot_product3(angular_dir2, diff),dot_product3(angular_dir1, diff));
+ ve_list[i].side = true;
+ ve_list[i].cocircular.clear();
+ vicinity.push_back(&(ve_list[i]));
+
+ // second angle (-)
+ ve_list[i+1].centre = median - transverse;
+ ve_list[i+1].centre.build_norm();
+ ve_list[i+1].centre/=ve_list[i+1].centre._norm;
+ diff = ve_list[i+1].centre - parent_centre;
+ ve_list[i+1].angle = sort_angle(dot_product3(angular_dir2, diff),dot_product3(angular_dir1, diff));
+ ve_list[i+1].side = false;
+ ve_list[i+1].cocircular.clear();
+ vicinity.push_back(&(ve_list[i+1]));
+
+ // now work out the cocircularity range for the two points (range
+ // of angle within which the points stay within a distance
+ // EPSILON_COCIRCULAR of circule
+ // P = parent; C = child; O = Origin (center of circle)
+ C3vector OP = parent_centre - ve_list[i+1].centre;
+ C3vector OC = vnormal - ve_list[i+1].centre;
+
+ // two sources of error are (GPS CCN29-19) epsilon/(R sin theta)
+ // and sqrt(2*epsilon/(R (1-cos theta))) and the way things work
+ // out, it is the _smaller_ of the two that is relevant [NB have
+ // changed definition of theta here relative to that used in
+ // CCN29] [NB2: write things so as to avoid zero denominators and
+ // to minimize the multiplications, divisions and above all sqrts
+ // -- that means that c & s are defined including a factor of VR2]
+ double inv_err1 = cross_product3(OP,OC)._norm * inv_R_EPS_COCIRC;
+ double inv_err2_sq = (D2_R-dot_product3(OP,OC)) * inv_R_2EPS_COCIRC;
+ ve_list[i].cocircular_range = pow2(inv_err1) > inv_err2_sq ?
+ 1.0/inv_err1 :
+ sqrt(1.0/inv_err2_sq);
+ ve_list[i+1].cocircular_range = ve_list[i].cocircular_range;
+ }
+}
+
+}
Property changes on: branches/spherical/siscone/spherical/vicinity.cpp
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+Date Rev
\ No newline at end of property
Index: branches/spherical/siscone/spherical/protocones.h
===================================================================
--- branches/spherical/siscone/spherical/protocones.h (revision 0)
+++ branches/spherical/siscone/spherical/protocones.h (revision 242)
@@ -0,0 +1,262 @@
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: protocones.h //
+// Description: header file for stable cones determination (Cstable_cones) //
+// This file is part of the SISCone project. //
+// WARNING: this is not the main SISCone trunk but //
+// an adaptation to spherical coordinates //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: $//
+// $Date:: $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __PROTOCONES_H__
+#define __PROTOCONES_H__
+
+#include "momentum.h"
+#include "vicinity.h"
+#include <stdio.h>
+#include <vector>
+#include <list>
+#include "hash.h"
+
+#include "defines.h"
+
+namespace siscone{
+
+/**
+ * \class Cborder_store
+ *
+ * class for storing a border momentum (in context of co-circularity
+ * checks).
+
+ * This class essentially calculates angle of border point w.r.t.
+ * circle center (eta & phi), and provides a store of information
+ * about whether we are currently including this point in the
+ * candidate
+ */
+class Cborder_store{
+public:
+ /// default ctor
+ Cborder_store(Cmomentum * momentum, C3vector &centre, C3vector &angl_dir1, C3vector &angl_dir2) :
+ mom(momentum), is_in(false) {
+ C3vector diff = (*momentum) - centre;
+ angle = atan2(dot_product3(diff, angl_dir2), dot_product3(diff, angl_dir1));
+#ifdef DEBUG_STABLE_CONES
+ std::cout << " adding point " << momentum->_theta << ", " << momentum->_phi
+ << " at an angle of " << angle << std::endl;
+#endif
+ }
+
+ Cmomentum * mom; ///< particle momentum
+ double angle; ///< angle w.r.t. circle centre
+ bool is_in; ///< inclusion status of the particle
+};
+
+
+/// allows easy sorting of Cborder_store objects (which need to be
+/// ordered in angle).
+inline bool operator<(const Cborder_store & a, const Cborder_store & b) {
+ return a.angle < b.angle;
+}
+
+
+/**
+ * \class Cstable_cones
+ * \brief Computes the list of stable comes from a particle list.
+ *
+ * This class does the first fundamental task of te cone algorithm:
+ * it is used to compute the list of stable cones given a list
+ * of particles.
+ */
+class Cstable_cones : public Cvicinity{
+ public:
+ /// default ctor
+ Cstable_cones();
+
+ /// ctor with initialisation (sse init for details)
+ Cstable_cones(std::vector<Cmomentum> &_particle_list);
+
+ /// default dtor
+ ~Cstable_cones();
+
+ /**
+ * initialisation
+ * \param _particle_list list of particles
+ */
+ void init(std::vector<Cmomentum> &_particle_list);
+
+ /**
+ * compute stable cones.
+ * This function really does the job i.e. computes
+ * the list of stable cones (in a seedless way)
+ * \param _radius radius of the cones
+ * \return The number of stable cones found is returned
+ */
+ int get_stable_cones(double _radius);
+
+ /// list of stable cones
+ std::vector<Cmomentum> protocones;
+
+ /// list of candidates
+ hash_cones *hc;
+
+ /// total number of tested cones
+ int nb_tot;
+#ifdef DEBUG_STABLE_CONES
+ int nb_hash_cones, nb_hash_occupied;
+#endif
+
+ protected:
+ /// cone radius
+ double R;
+
+ /// cone radius SQUARED
+ double R2;
+
+ /// squared tangent of the cone radius
+ double tan2R;
+
+ private:
+ /// cone with a given particle as parent
+ /// this reduction to a single vector assumes we trust the checksums
+ Cmomentum cone;
+
+ /// child particle, taken in the 'vicinity' list
+ Cmomentum *child;
+
+ /// centre of the tested cone
+ Cvicinity_elm *centre;
+
+ /// index in the particle list;
+ unsigned int centre_idx;
+
+ /// first cone used in the vicinity list
+ unsigned int first_cone;
+
+ /**
+ * initialise the cone.
+ * We take the first particle in the angular ordering to compute this one
+ * \return 0 on success, 1 on error
+ */
+ int init_cone();
+
+ /**
+ * test cones.
+ * We check if the cone(s) build with the present parent and child
+ * are stable
+ * \return 0 on success 1 on error
+ */
+ int test_cone();
+
+ /**
+ * update the cone
+ * go to the next child for that parent and update 'cone' appropriately
+ * \return 0 if update candidate found, 1 otherwise
+ */
+ int update_cone();
+
+ /*
+ * run through the vicinity of the current parent and for each child
+ * indicate which members are cocircular...
+ */
+ void prepare_cocircular_lists();
+
+ /**
+ * check if we are in a situation of cocircularity.
+ * if it is the case, update and test in the corresponding way
+ * \return 'false' if no cocircularity detected, 'true' otherwise
+ * Note that if cocircularity is detected, we need to
+ * recall 'update' from 'update' !!!
+ */
+ bool cocircular_check();
+
+ /**
+ * Routine for testing cocircular configurations in p^3 time,
+ * rather than 2^p time;
+ */
+ void test_cone_cocircular(Cmomentum & borderless_cone,
+ std::list<Cmomentum *> & border_list);
+
+ /**
+ * carry out the computations needed for the stability check of the
+ * candidate, using the border_vect to indicate which particles
+ * should / should not be in the stable cone; if the cone is stable
+ * insert it into the hash.
+ */
+ void test_stability(Cmomentum & candidate,
+ const std::vector<Cborder_store> & border_vect);
+
+ /**
+ * compute the cone contents by going once around the full set of
+ * circles and tracking the entry/exit status each time -- this sets
+ * up the inclusion information, which can then be directly used to
+ * calculate the cone momentum.
+ */
+ void compute_cone_contents();
+
+ /**
+ * compute the cone momentum from particle list.
+ * in this version, we use the 'pincluded' information
+ * from the Cviinity class
+ */
+ void recompute_cone_contents();
+
+ /*
+ * if we have gone beyond the acceptable threshold of change, compute
+ * the cone momentum from particle list. in this version, we use the
+ * 'pincluded' information from the Cvicinity class, but we don't
+ * change the member cone, only the locally supplied one
+ */
+ void recompute_cone_contents_if_needed(Cmomentum & this_cone, double & this_dpt);
+
+ /**
+ * compute stability of all enumerated candidates.
+ * For all candidate cones which are stable w.r.t. their border particles,
+ * pass the last test: stability with quadtree intersection
+ */
+ int proceed_with_stability();
+
+ /*
+ * circle intersection.
+ * computes the intersection with a circle of given centre and radius.
+ * The output takes the form of a checkxor of the intersection's particles
+ * - cx circle centre x coordinate
+ * - cy circle centre y coordinate
+ * return the checkxor for the intersection
+ ******************************************************************/
+ Creference circle_intersect(C3vector &cone_centre);
+
+ /// present candidate cone
+ Cmomentum cone_candidate;
+
+ /// in case of co-circular points, vector for them
+ std::vector<Cmomentum*> child_list;
+
+ /// list of cocircular enclusures already studied
+ /// first element if cone contents, second is cone border
+ std::vector< std::pair<Creference,Creference> > multiple_centre_done;
+
+ // information for updating cone contents to avoid rounding errors
+ double dpt; ///< sums of Delta P_t
+};
+
+}
+#endif
Property changes on: branches/spherical/siscone/spherical/protocones.h
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+Date Rev
\ No newline at end of property
Index: branches/spherical/siscone/spherical/momentum.cpp
===================================================================
--- branches/spherical/siscone/spherical/momentum.cpp (revision 0)
+++ branches/spherical/siscone/spherical/momentum.cpp (revision 242)
@@ -0,0 +1,294 @@
+///////////////////////////////////////////////////////////////////////////////
+// File: momentum.cpp //
+// Description: source file for 4-momentum class Cmomentum //
+// This file is part of the SISCone project. //
+// WARNING: this is not the main SISCone trunk but //
+// an adaptation to spherical coordinates //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: $//
+// $Date:: $//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "momentum.h"
+#include <math.h>
+#include <stdlib.h>
+
+namespace siscone{
+
+/*************************************************************************
+ * class C3vector *
+ * This class contains the information for particle or group of *
+ * particles management. *
+ *************************************************************************/
+
+// default ctor
+//--------------
+C3vector::C3vector(){
+ _theta = _phi = _norm = 0.0;
+ px = py = pz = 0.0;
+ ref = Creference();
+}
+
+// ctor with initialisation
+//--------------------------
+C3vector::C3vector(double _px, double _py, double _pz){
+ px = _px;
+ py = _py;
+ pz = _pz;
+
+ // compute the norm
+ build_norm();
+
+ ref = Creference();
+}
+
+// default dtor
+//--------------
+C3vector::~C3vector(){
+
+}
+
+
+// assignment of vectors
+//-----------------------
+C3vector& C3vector::operator = (const C3vector &v){
+ px = v.px;
+ py = v.py;
+ pz = v.pz;
+
+ _norm = v._norm;
+ _theta = v._theta;
+ _phi = v._phi;
+
+ ref = v.ref;
+ return *this;
+}
+
+// addition of vectors
+//------------------------------------------------
+const C3vector C3vector::operator + (const C3vector &v){
+ C3vector tmp = *this;
+ return tmp+=v;
+}
+
+// subtraction of vectors
+//------------------------------------------------
+const C3vector C3vector::operator - (const C3vector &v){
+ C3vector tmp = *this;
+ return tmp-=v;
+}
+
+// division by constant
+//------------------------------------------------
+const C3vector C3vector::operator / (const double &r){
+ C3vector tmp = *this;
+ return tmp/=r;
+}
+
+// incrementation
+//------------------------------------------------
+C3vector& C3vector::operator += (const C3vector &v){
+ px+=v.px;
+ py+=v.py;
+ pz+=v.pz;
+
+ return *this;
+}
+
+// decrementation
+//------------------------------------------------
+C3vector& C3vector::operator -= (const C3vector &v){
+ px-=v.px;
+ py-=v.py;
+ pz-=v.pz;
+
+ return *this;
+}
+
+// multiplication by a constant
+//------------------------------------------------
+C3vector& C3vector::operator *= (const double &r){
+ px*=r;
+ py*=r;
+ pz*=r;
+
+ return *this;
+}
+
+// division by a constant
+//------------------------------------------------
+C3vector& C3vector::operator /= (const double &r){
+ px/=r;
+ py/=r;
+ pz/=r;
+
+ _norm/=r;
+
+ return *this;
+}
+
+// build norm from 3-momentum info
+void C3vector::build_norm(){
+ _norm = norm();
+}
+
+// build norm from 3-momentum info
+void C3vector::build_thetaphi(){
+ _theta = theta();
+ _phi = phi();
+}
+
+
+// for this direction, compute the two reference directions
+// used to measure angles
+void C3vector::get_angular_directions(C3vector &angular_dir1, C3vector &angular_dir2){
+ if (px < py){
+ if (pz < px){
+ // z smallest
+ angular_dir1 = C3vector(-py, px, 0.0);
+ } else {
+ // x smallest
+ angular_dir1 = C3vector(0.0, -pz, py);
+ }
+ } else {
+ if (pz < py){
+ // z smallest
+ angular_dir1 = C3vector(-py, px, 0.0);
+ } else {
+ // y smallest
+ angular_dir1 = C3vector(-pz, 0.0, px);
+ }
+ }
+ angular_dir2 = cross_product3(*this, angular_dir1);
+ // We'll simply take x & y so the reflection symmetry is not broken
+ //angular_dir1 = C3vector(0.0, -pz, py);
+ //angular_dir2 = C3vector(-pz, 0.0, -px);
+}
+
+/*************************************************************************
+ * class Cmomentum *
+ * This class contains the information for particle or group of *
+ * particles management. *
+ * It includes all Lorentz properties as well as tools for summing them. *
+ *************************************************************************/
+
+// default ctor
+//--------------
+Cmomentum::Cmomentum(){
+ E=0.0;
+ index = -1;
+}
+
+// ctor with initialisation
+//--------------------------
+Cmomentum::Cmomentum(double _px, double _py, double _pz, double _E)
+ : C3vector(_px, _py, _pz) {
+ E = _E;
+
+ // compute the angles
+ build_thetaphi();
+}
+
+// ctor with initialisation
+//--------------------------
+Cmomentum::Cmomentum(C3vector &_v, double _E)
+ : C3vector(_v.px, _v.py, _v.pz) {
+ E = _E;
+}
+
+// default dtor
+//--------------
+Cmomentum::~Cmomentum(){
+
+}
+
+// assignment of vectors
+//-----------------------
+Cmomentum& Cmomentum::operator = (const Cmomentum &v){
+ px = v.px;
+ py = v.py;
+ pz = v.pz;
+ E = v.E;
+
+ _norm = v._norm;
+ _theta = v._theta;
+ _phi = v._phi;
+
+ ref = v.ref;
+ return *this;
+}
+
+// addition of vectors
+// !!! WARNING !!! no updating of eta and phi !!!
+//------------------------------------------------
+const Cmomentum Cmomentum::operator + (const Cmomentum &v){
+ Cmomentum tmp = *this;
+ return tmp+=v;
+}
+
+// incrementation of vectors
+// !!! WARNING !!! no updating of eta and phi !!!
+//------------------------------------------------
+Cmomentum& Cmomentum::operator += (const Cmomentum &v){
+ px+=v.px;
+ py+=v.py;
+ pz+=v.pz;
+ E +=v.E;
+
+ ref+=v.ref;
+
+ return *this;
+}
+
+// decrementation of vectors
+// !!! WARNING !!! no updating of eta and phi !!!
+//------------------------------------------------
+Cmomentum& Cmomentum::operator -= (const Cmomentum &v){
+ px-=v.px;
+ py-=v.py;
+ pz-=v.pz;
+ E -=v.E;
+
+ ref-=v.ref;
+ return *this;
+}
+
+
+// ordering of two vectors
+// the default ordering is w.r.t. their references
+//-------------------------------------------------
+bool operator < (const Cmomentum &v1, const Cmomentum &v2){
+ return v1.ref < v2.ref;
+}
+
+// ordering of vectors in eta (e.g. used in collinear tests)
+//-----------------------------------------------------------
+bool momentum_theta_less(const Cmomentum &v1, const Cmomentum &v2){
+ return v1._theta < v2._theta;
+}
+
+// ordering of vectors in pt
+//---------------------------
+bool momentum_pt_less(const Cmomentum &v1, const Cmomentum &v2){
+ return v1.perp2() < v2.perp2();
+}
+
+}
+
Property changes on: branches/spherical/siscone/spherical/momentum.cpp
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+Date Rev
\ No newline at end of property
Index: branches/spherical/siscone/spherical/vicinity.h
===================================================================
--- branches/spherical/siscone/spherical/vicinity.h (revision 0)
+++ branches/spherical/siscone/spherical/vicinity.h (revision 242)
@@ -0,0 +1,161 @@
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: vicinity.h //
+// Description: header file for particle vicinity (Cvicinity class) //
+// This file is part of the SISCone project. //
+// WARNING: this is not the main SISCone trunk but //
+// an adaptation to spherical coordinates //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: $//
+// $Date:: $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __VICINITY_H__
+#define __VICINITY_H__
+
+#include <vector>
+#include <list>
+#include "momentum.h"
+#include "defines.h"
+#include "quadtree.h"
+
+namespace siscone{
+
+
+
+/**
+ * \class Cvicinity_inclusion
+ * \brief a class to keep track of inclusion status in cone and in cocircular region
+ * while using minimal resources
+ */
+class Cvicinity_inclusion {
+public:
+ /// default ctor
+ Cvicinity_inclusion() : cone(false), cocirc(false) {}
+
+ bool cone; ///< flag for particle inclusion in the cone
+ bool cocirc; ///< flag for particle inclusion in the border
+};
+
+
+/**
+ * \class Cvicinity_elm
+ * \brief element in the vicinity of a parent.
+ *
+ * class used to manage one points in the vicinity
+ * of a parent point.
+ */
+class Cvicinity_elm{
+ public:
+ /// pointer to the second borderline particle
+ Cmomentum *v;
+
+ /// variable to tell if the particle is inside or outside the cone
+ Cvicinity_inclusion *is_inside;
+
+ // centre variables
+ C3vector centre; ///< direction of the centre
+ double angle; ///< angle with parent
+ bool side; ///< true if angle on the positive side, false otherwise
+ double cocircular_range; ///< amount by which the angle can be varied while
+ ///< maintaining this point within co-circularity margin
+
+ /// list of elements co-circular with this one
+ /// NB: empty list uses less mem than vector
+ std::list<Cvicinity_elm * > cocircular;
+};
+
+/// ordering pointers to Cvicinity_elm
+bool ve_less(Cvicinity_elm *ve1, Cvicinity_elm *ve2);
+
+
+/**
+ * \class Cvicinity
+ * \brief list of element in the vicinity of a parent.
+ *
+ * class used to manage the points which are in the vicinity
+ * of a parent point.
+ */
+class Cvicinity{
+ public:
+ /// default constructor
+ Cvicinity();
+
+ /// constructor with initialisation (see set_particle_list)
+ Cvicinity(std::vector<Cmomentum> &_particle_list);
+
+ /// default destructor
+ ~Cvicinity();
+
+ /**
+ * set the particle_list
+ * \param _particle_list list of particles (type Cmomentum)
+ */
+ void set_particle_list(std::vector<Cmomentum> &_particle_list);
+
+ /**
+ * build the vicinity list from the list of points.
+ * \param _parent reference particle
+ * \param _VR vicinity radius
+ */
+ void build(Cmomentum *_parent, double _VR);
+
+ // cone kinematical information
+ Cmomentum *parent; ///< parent vector
+ double VR; ///< radius of the vicinity
+ double VR2; ///< squared radius of the vicinity
+ double cosVR; ///< cosine of the radius of the vicinity
+ double R; ///< normal radius
+ double R2; ///< squared normal radius
+ double tan2R; ///< squared tangent of the normal radius
+ double D2_R; ///< euclidian distance (squared) corresp. to the arc R
+ double inv_R_EPS_COCIRC; ///< R / EPSILON_COCIRCULAR
+ double inv_R_2EPS_COCIRC; ///< R / (2*EPSILON_COCIRCULAR)
+
+ // particle list information
+ int n_part; ///< number of particles
+ std::vector<Cmomentum> plist; ///< the list of particles
+ std::vector<Cvicinity_inclusion> pincluded; ///< the inclusion state of particles
+ Cvicinity_elm *ve_list; ///< list of vicinity elements built from particle list (size=2*n)
+#ifdef USE_QUADTREE_FOR_STABILITY_TEST
+ Cquadtree *quadtree; ///< quadtree used for final stability tests
+#endif
+
+ // vicinity information
+ std::vector<Cvicinity_elm*> vicinity; ///< list of points in parent's vicinity
+ unsigned int vicinity_size; ///< number of elements in vicinity
+
+ protected:
+ /**
+ * append a particle to the 'vicinity' list after
+ * having tested it and computed the angular-ordering quantities
+ * \param v vector to test
+ */
+ void append_to_vicinity(Cmomentum *v);
+
+ // internal variables
+ C3vector parent_centre; ///< parent centre
+ C3vector angular_dir1; ///< main direction to measure angles
+ C3vector angular_dir2; ///< second direction to measure angles (sign)
+};
+
+}
+
+#endif
Property changes on: branches/spherical/siscone/spherical/vicinity.h
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+Date Rev
\ No newline at end of property
Index: branches/spherical/siscone/spherical/siscone.cpp
===================================================================
--- branches/spherical/siscone/spherical/siscone.cpp (revision 0)
+++ branches/spherical/siscone/spherical/siscone.cpp (revision 242)
@@ -0,0 +1,223 @@
+///////////////////////////////////////////////////////////////////////////////
+// File: siscone.cpp //
+// Description: source file for the main SISCone class //
+// This file is part of the SISCone project. //
+// WARNING: this is not the main SISCone trunk but //
+// an adaptation to spherical coordinates //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: $//
+// $Date:: $//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "config.h"
+
+#include "ranlux.h"
+#include "momentum.h"
+#include "defines.h"
+#include "siscone.h"
+#include "siscone_error.h"
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+
+namespace siscone{
+using namespace std;
+
+/***************************************************************
+ * Csiscone implementation *
+ * final class: gather everything to compute the jet contents. *
+ * *
+ * This is the class user should use. *
+ * It computes the jet contents of a list of particles *
+ * given a cone radius and a threshold for splitting/merging. *
+ ***************************************************************/
+
+// default ctor
+//--------------
+Csiscone::Csiscone(){
+ rerun_allowed = false;
+}
+
+// default dtor
+//--------------
+Csiscone::~Csiscone(){
+ rerun_allowed = false;
+}
+
+bool Csiscone::init_done=false;
+
+/*
+ * compute the jets from a given particle set doing multiple passes
+ * such pass N looks for jets among all particles not put into jets
+ * during previous passes.
+ * - _particles list of particles
+ * - _radius cone radius
+ * - _f shared energy threshold for splitting&merging
+ * - _n_pass_max maximum number of runs
+ * - _Emin minimum energy of the protojets
+ * - _split_merge_scale the scale choice for the split-merge procedure
+ * NOTE: using pt leads to IR unsafety for some events with momentum
+ * conservation. So we strongly advise not to change the default
+ * value.
+ * return the number of jets found.
+ **********************************************************************/
+int Csiscone::compute_jets(vector<Cmomentum> &_particles, double _radius, double _f,
+ int _n_pass_max, double _Emin,
+ Esplit_merge_scale _split_merge_scale){
+ // initialise random number generator
+ if (!init_done){
+ // initialise random number generator
+ ranlux_init();
+
+ // print the banner
+ cout << "#ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo" << endl;
+ cout << "# SISCone version " << setw(28) << left << siscone_version() << "o" << endl;
+ cout << "# http://projects.hepforge.org/siscone o" << endl;
+ cout << "# o" << endl;
+ cout << "# This is SISCone: the Seedless Infrared Safe Cone Jet Algorithm o" << endl;
+ cout << "# SISCone was written by Gavin Salam and Gregory Soyez o" << endl;
+ cout << "# It is released under the terms of the GNU General Public License o" << endl;
+ cout << "# o" << endl;
+ cout << "# !!! WARNING !!! o" << endl;
+ cout << "# This is the version of SISCone using spherical coordinates o" << endl;
+ cout << "# o" << endl;
+ cout << "# A description of the algorithm is available in the publication o" << endl;
+ cout << "# JHEP 05 (2007) 086 [arXiv:0704.0292 (hep-ph)]. o" << endl;
+ cout << "# Please cite it if you use SISCone. o" << endl;
+ cout << "#ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo" << endl;
+ cout << endl;
+ // do not do this again
+ init_done=true;
+ }
+
+ // run some general safety tests (NB: f will be checked in split-merge)
+ if (_radius <= 0.0 || _radius >= 0.5*M_PI) {
+ ostringstream message;
+ message << "Illegal value for cone radius, R = " << _radius
+ << " (legal values are 0<R<pi/2)";
+ throw Csiscone_error(message.str());
+ }
+
+
+
+ ptcomparison.split_merge_scale = _split_merge_scale;
+ partial_clear(); // make sure some things are initialised properly
+
+ // init the split_merge algorithm with the initial list of particles
+ // this initialises particle list p_left of remaining particles to deal with
+ init_particles(_particles);
+
+ bool finished = false;
+
+ rerun_allowed = false;
+ protocones_list.clear();
+
+#ifdef DEBUG_STABLE_CONES
+ nb_hash_cones_total = 0;
+ nb_hash_occupied_total = 0;
+#endif
+
+ do{
+ // initialise stable_cone finder
+ // here we use the list of remaining particles
+ // AFTER COLLINEAR CLUSTERING !!!!!!
+ Cstable_cones::init(p_uncol_hard);
+
+ // get stable cones
+ if (get_stable_cones(_radius)){
+ // we have some new protocones.
+ // add them to candidates
+ protocones_list.push_back(protocones);
+ add_protocones(&protocones, R2, _Emin);
+#ifdef DEBUG_STABLE_CONES
+ nb_hash_cones_total += nb_hash_cones;
+ nb_hash_occupied_total += nb_hash_occupied;
+#endif
+ } else {
+ // no new protocone: leave
+ finished=true;
+ }
+
+ _n_pass_max--;
+ } while ((!finished) && (n_left>0) && (_n_pass_max!=0));
+
+ rerun_allowed = true;
+
+ // split & merge
+ return perform(_f, _Emin);
+}
+
+/*
+ * recompute the jets with a different overlap parameter.
+ * we use the same particles and R as in the preceeding call.
+ * - _f shared energy threshold for splitting&merging
+ * - _Emin minimum Energy of the protojets
+ * - _split_merge_scale the scale choice for the split-merge procedure
+ * NOTE: using pt leads to IR unsafety for some events with momentum
+ * conservation. So we strongly advise not to change the default
+ * value.
+ * return the number of jets found, -1 if recomputation not allowed.
+ ********************************************************************/
+int Csiscone::recompute_jets(double _f, double _Emin,
+ Esplit_merge_scale _split_merge_scale){
+ if (!rerun_allowed)
+ return -1;
+
+ ptcomparison.split_merge_scale = _split_merge_scale;
+
+ // restore particle list
+ partial_clear();
+ init_pleft();
+
+ // initialise split/merge algorithm
+ unsigned int i;
+ for (i=0;i<protocones_list.size();i++)
+ add_protocones(&(protocones_list[i]), R2, _Emin);
+
+ // split & merge
+ return perform(_f, _Emin);
+}
+
+
+// finally, a bunch of functions to access to
+// basic information (package name, version)
+//---------------------------------------------
+
+/*
+ * return SISCone package name.
+ * This is nothing but "SISCone", it is a replacement to the
+ * PACKAGE_NAME string defined in config.h and which is not
+ * public by default.
+ * return the SISCone name as a string
+ */
+string siscone_package_name(){
+ return VERSION;
+}
+
+/*
+ * return SISCone version number.
+ * return a string of the form "X.Y.Z" with possible additional tag
+ * (alpha, beta, devel) to mention stability status
+ */
+string siscone_version(){
+ return VERSION;
+}
+
+}
Property changes on: branches/spherical/siscone/spherical/siscone.cpp
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+Date Rev
\ No newline at end of property
Index: branches/spherical/siscone/spherical/momentum.h
===================================================================
--- branches/spherical/siscone/spherical/momentum.h (revision 0)
+++ branches/spherical/siscone/spherical/momentum.h (revision 242)
@@ -0,0 +1,312 @@
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: momentum.h //
+// Description: header file for 4-momentum class Cmomentum //
+// This file is part of the SISCone project. //
+// WARNING: this is not the main SISCone trunk but //
+// an adaptation to spherical coordinates //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: $//
+// $Date:: $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __VECTOR_H__
+#define __VECTOR_H__
+
+#include <vector>
+#include <math.h>
+#include "reference.h"
+#include "geom_2d.h"
+#include "defines.h"
+
+namespace siscone{
+
+/**
+ * \class C3vector
+ * \brief base class for managing the spatial part of Cmomentum (defined after)
+ *
+ * This class contains the information for particle or group of
+ * particles management.
+ * It is adapted to use spherical geometry, where, for our purposes,
+ * the only time-consuming operation we need is the computation of
+ * the norm. To compute it once-and-for-all and store it in a local
+ * variable, you should call the 'build_norm' method.
+ * On top of that, the angle phi is computed from the x-axis
+ * and theta from the "north pole".
+ */
+class C3vector{
+ public:
+ /// default ctor
+ C3vector();
+
+ /// ctor with initialisation
+ C3vector(double _px, double _py, double _pz);
+
+ /// default dtor
+ ~C3vector();
+
+ /// assignment of vectors
+ C3vector& operator = (const C3vector &v);
+
+ /// addition of vectors
+ /// WARNING= norm is not updated
+ const C3vector operator + (const C3vector &v);
+
+ /// subtraction of vectors
+ /// WARNING= norm is not updated
+ const C3vector operator - (const C3vector &v);
+
+ /// division by a constant
+ /// WARNING= norm is not updated
+ const C3vector operator / (const double &r);
+
+ /// incrementation of vectors
+ /// WARNING= norm is not updated
+ C3vector& operator += (const C3vector &v);
+
+ /// decrementation of vectors
+ /// WARNING= norm is not updated
+ C3vector& operator -= (const C3vector &v);
+
+ /// multiplication by a constant
+ /// WARNING= norm is not updated
+ C3vector& operator *= (const double &r);
+
+ /// division by a constant
+ /// WARNING= norm is not updated
+ C3vector& operator /= (const double &r);
+
+ /// computes pT
+ inline double perp() const {return sqrt(perp2());}
+
+ /// computes pT^2
+ inline double perp2() const {return px*px+py*py;}
+
+ /// 3-vect norm
+ inline double norm() const {return sqrt(px*px+py*py+pz*pz);}
+
+ /// 3-vect norm squared
+ inline double norm2() const {return px*px+py*py+pz*pz;}
+
+ /// 3-vect azimuthal angle
+ inline double phi() const {return atan2(py, px);}
+
+ /// 3-vect polar angle
+ inline double theta() const {return atan2(perp(),pz);}
+
+ /// build the spatial normfrom 4-momentum info
+ /// !!! WARNING !!!
+ /// !!! computing the norm is the only time-consuming !!!
+ /// !!! information we need in all computations. !!!
+ /// !!! use this whenever you need repeated access !!!
+ /// !!! to the norm to store it in the local variable !!!
+ void build_norm();
+
+ /// just a useful tool to store theta and phi
+ /// locally (in _theta and _phi) in case you need
+ /// repeated access
+ void build_thetaphi();
+
+ /// for this direction, compute the two reference directions
+ /// used to measure angles
+ void get_angular_directions(C3vector &angular_dir1, C3vector &angular_dir2);
+
+ double px; ///< x-momentum
+ double py; ///< y-momentum
+ double pz; ///< z-momentum
+
+ double _norm; ///< particle spatial norm (available ONLY after a call to build_norm)
+ double _theta; ///< particle theta angle (available ONLY after a call to build_thetaphi)
+ double _phi; ///< particle phi angle (available ONLY after a call to build_thetaphi)
+
+ //////////////////////////////////////////////
+ // the following part is used for checksums //
+ //////////////////////////////////////////////
+ Creference ref; ///< reference number for the vector
+};
+
+/**
+ * \class Cmomentum
+ * \brief base class for dynamic coordinates management
+ *
+ * This class contains the information for particle or group of
+ * particles management.
+ * It is adapted to use spherical geometry, where, for our purposes,
+ * the only time-consuming operation we need is the computation of
+ * the norm. To compute it once-and-for-all and store it in a local
+ * variable, you should call the 'build_norm' method.
+ * On top of that, the angle phi is computed from the x-axis
+ * and theta from the "north pole".
+ */
+class Cmomentum : public C3vector{
+ public:
+ /// default ctor
+ Cmomentum();
+
+ /// init from a 3-vect
+ Cmomentum(C3vector &init, double E=0.0);
+
+ /// ctor with initialisation
+ Cmomentum(double _px, double _py, double _pz, double _E);
+
+ /// ctor with detailed initialisation
+ //Cmomentum(double _eta, double _phi, Creference _ref);
+
+ /// default dtor
+ ~Cmomentum();
+
+ /// computes m
+ inline double mass() const {return sqrt(mass2());}
+
+ /// computes m^2
+ inline double mass2() const {return perpmass2()-perp2();}
+
+ /// transverse mass, mt = sqrt(pt^2+m^2) = sqrt(E^2 - pz^2)
+ inline double perpmass() const {return sqrt((E-pz)*(E+pz));}
+
+ /// transverse mass squared, mt^2 = pt^2+m^2 = E^2 - pz^2
+ inline double perpmass2() const {return (E-pz)*(E+pz);}
+
+ /// computes transverse energy
+ inline double Et() const {return E/sqrt(1.0+pz*pz/perp2());}
+
+ /// computes transverse energy (squared)
+ inline double Et2() const {return E*E/(1.0+pz*pz/perp2());}
+
+ /// assignment of vectors
+ Cmomentum& operator = (const Cmomentum &v);
+
+ /// addition of vectors
+ /// !!! WARNING !!! no updating of eta and phi !!!
+ const Cmomentum operator + (const Cmomentum &v);
+
+ /// incrementation of vectors
+ /// !!! WARNING !!! no updating of eta and phi !!!
+ Cmomentum& operator += (const Cmomentum &v);
+
+ /// decrementation of vectors
+ /// !!! WARNING !!! no updating of eta and phi !!!
+ Cmomentum& operator -= (const Cmomentum &v);
+
+ double E; ///< energy
+
+ int parent_index; ///< particle number in the parent list
+ int index; ///< internal particle number
+};
+
+/// ordering of two vectors
+/// this is by default done w.r.t. their references
+bool operator < (const Cmomentum &v1, const Cmomentum &v2);
+
+/// ordering of vectors in eta (e.g. used in collinear tests)
+bool momentum_theta_less(const Cmomentum &v1, const Cmomentum &v2);
+
+/// ordering of vectors in pt
+bool momentum_pt_less(const Cmomentum &v1, const Cmomentum &v2);
+
+
+//////////////////////////
+// some handy utilities //
+//////////////////////////
+
+/// square
+inline double sqr(double x){return x*x;}
+
+/// dot product for te spatial 3-vect
+/// \param v1 first 4-vect
+/// \param v2 second 4-vect
+inline double dot_product3(const C3vector &v1, const C3vector &v2){
+ //double tmp = v1.px*v2.px + v1.py*v2.py + v1.pz*v2.pz;
+ //if (!isfinite(tmp)){
+ // std::cout << "dot_product inf: " << std::endl;
+ // std::cout << " angles: " << v1._theta << " " << v1._phi << " and " << v2._theta << " " << v2._phi << std::endl;
+ // std::cout << " moms : " << v1.px << " " << v1.py << " " << v1.pz
+ // << " and " << v2.px << " " << v2.py << " " << v2.pz << std::endl;
+ //}
+ return v1.px*v2.px + v1.py*v2.py + v1.pz*v2.pz;
+}
+
+/// cross product for the spatial 3-vect
+/// \param v1 first 4-vect
+/// \param v2 second 4-vect
+inline C3vector cross_product3(const C3vector &v1, const C3vector &v2){
+ //C3vector tmp;
+ //tmp.px = v1.py*v2.pz-v1.pz*v2.py;
+ //tmp.py = v1.pz*v2.px-v1.px*v2.pz;
+ //tmp.pz = v1.px*v2.py-v1.py*v2.px;
+ //return tmp;
+ return C3vector(v1.py*v2.pz-v1.pz*v2.py,
+ v1.pz*v2.px-v1.px*v2.pz,
+ v1.px*v2.py-v1.py*v2.px);
+}
+
+/// squared norm of the cross product for the spatial 3-vect (energy is set to 0)
+/// \param v1 first 4-vect
+/// \param v2 second 4-vect
+inline double norm2_cross_product3(const C3vector &v1, const C3vector &v2){
+ return sqr(v1.py*v2.pz-v1.pz*v2.py) + sqr(v1.pz*v2.px-v1.px*v2.pz) + sqr(v1.px*v2.py-v1.py*v2.px);
+}
+
+/// get tangent squared of the spherical distance between to vectors
+/// \param v1 vector defining the first point
+/// \param v2 vector defining the second point
+inline double get_tan2_distance(const Cmomentum &v1, const Cmomentum &v2){
+ return norm2_cross_product3(v1,v2)/sqr(dot_product3(v1,v2));
+}
+
+/// get spherical distance between to vectors
+/// \param v1 vector defining the first point
+/// \param v2 vector defining the second point
+inline double get_distance(const C3vector *v1, const C3vector *v2){
+ return atan2(sqrt(norm2_cross_product3(*v1,*v2)), dot_product3(*v1,*v2));
+}
+
+/// return true if the two points are distant by less than get spherical distance between to vectors
+/// \param v1 vector defining the first point
+/// \param v2 vector defining the second point
+/// \param tan2R tangent squared of the max distance
+/// WARNING: using the tangent here is dangerous for R>pi/2.
+/// this never happens per se for "regular R" but
+/// it may in the vicinity computation as we're using
+/// 2R there.
+inline bool is_closer(const C3vector *v1, const C3vector *v2, const double tan2R){
+ double dot = dot_product3(*v1,*v2);
+ return (dot>=0) && (norm2_cross_product3(*v1,*v2)<=tan2R*dot*dot);
+}
+
+/// return true if the two points are distant by less than get spherical distance between to vectors
+/// \param v1 vector defining the first point
+/// \param v2 vector defining the second point
+/// \param tan2R tangent squared of the max distance
+/// safer version but computes the norm
+inline bool is_closer_safer(const C3vector *v1, const C3vector *v2, const double cosR){
+ return dot_product3(*v1,*v2)>=cosR*sqrt(v1->norm2()*v2->norm2());
+ //double dot = dot_product3(*v1,*v2);
+ //return (dot>=0) && (norm2_cross_product3(*v1,*v2)<tan2R*dot*dot);
+}
+
+/// multiply a vector by a constant
+/// WARNING: norm not updated
+inline C3vector operator * (const double &r, const C3vector &v){
+ C3vector tmp = v;
+ return tmp*=r;
+}
+}
+#endif
Property changes on: branches/spherical/siscone/spherical/momentum.h
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+Date Rev
\ No newline at end of property
Index: branches/spherical/siscone/spherical/siscone.h
===================================================================
--- branches/spherical/siscone/spherical/siscone.h (revision 0)
+++ branches/spherical/siscone/spherical/siscone.h (revision 242)
@@ -0,0 +1,135 @@
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: siscone.h //
+// Description: header file for the main SISCone class //
+// This file is part of the SISCone project. //
+// WARNING: this is not the main SISCone trunk but //
+// an adaptation to spherical coordinates //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: $//
+// $Date:: $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __SISCONE_H__
+#define __SISCONE_H__
+
+#include "protocones.h"
+#include "split_merge.h"
+
+namespace siscone{
+
+/**
+ * \class Csiscone
+ * final class: gather everything to compute the jet contents.
+ *
+ * This is the class user should use.
+ * It computes the jet contents of a list of particles
+ * given a cone radius and a threshold for splitting/merging.
+ *
+ * After the call to 'perform', the vector jets is filled with
+ * the jets found. the 'contents' field of each jets contains
+ * the indices of the particles included in that jet.
+ */
+class Csiscone : public Cstable_cones, public Csplit_merge{
+ public:
+ /// default ctor
+ Csiscone();
+
+ /// default dtor
+ ~Csiscone();
+
+ /**
+ * compute the jets from a given particle set.
+ * We are doing multiple passes such pass n_pass looks for jets among
+ * all particles not put into jets during previous passes.
+ * By default the number of passes is infinite (0).
+ * \param _particles list of particles
+ * \param _radius cone radius
+ * \param _f shared energy threshold for splitting&merging
+ * \param _n_pass_max maximum number of passes (0=full search)
+ * \param _Emin minimum energy of the protojets
+ * \param _split_merge_scale the scale choice for the split-merge procedure
+ * NOTE: SM_pt leads to IR unsafety for some events with momentum conservation.
+ * SM_Et is IR safe but not boost invariant and not implemented(!)
+ * SM_mt is IR safe for hadronic events, but not for decays of two
+ * back-to-back particles of identical mass
+ * SM_pttilde
+ * is always IR safe, and also boost invariant
+ * SM_E
+ * For spherical coords, this is the natural choice (default)
+ *
+ * \return the number of jets found.
+ */
+ int compute_jets(std::vector<Cmomentum> &_particles, double _radius, double _f,
+ int _n_pass_max=0, double _Emin=0.0,
+ Esplit_merge_scale _split_merge_scale=SM_E);
+
+ /**
+ * recompute the jets with a different overlap parameter.
+ * we use the same particles and R as in the preceeding call.
+ * \param _f shared energy threshold for splitting&merging
+ * \param _Emin minimum energy of the protojets
+ * \param _split_merge_scale the scale choice for the split-merge procedure
+ * split--merge variable
+ * NOTE: using pt leads to IR unsafety for some events with momentum
+ * conservation. So we strongly advise not to change the default
+ * value.
+ * \return the number of jets found, -1 if recomputation not allowed.
+ */
+ int recompute_jets(double _f, double _Emin = 0.0,
+ Esplit_merge_scale _split_merge_scale=SM_E);
+
+ /// list of protocones found pass-by-pass
+ std::vector<std::vector<Cmomentum> > protocones_list;
+
+ // random number initialisation
+ static bool init_done; ///< check random generator initialisation
+
+#ifdef DEBUG_STABLE_CONES
+ int nb_hash_cones_total, nb_hash_occupied_total;
+#endif
+
+ private:
+ bool rerun_allowed; ///< is recompute_jets allowed ?
+};
+
+
+// finally, a bunch of functions to access to
+// basic information (package name, version)
+//---------------------------------------------
+
+/**
+ * return SISCone package name.
+ * This is nothing but "SISCone", it is a replacement to the
+ * PACKAGE_NAME string defined in config.h and which is not
+ * public by default.
+ * \return the SISCone name as a string
+ */
+std::string siscone_package_name();
+
+/**
+ * return SISCone version number.
+ * \return a string of the form "X.Y.Z" with possible additional tag
+ * (alpha, beta, devel) to mention stability status
+ */
+std::string siscone_version();
+
+}
+#endif
Property changes on: branches/spherical/siscone/spherical/siscone.h
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+Date Rev
\ No newline at end of property
Index: branches/spherical/siscone/spherical/split_merge.cpp
===================================================================
--- branches/spherical/siscone/spherical/split_merge.cpp (revision 0)
+++ branches/spherical/siscone/spherical/split_merge.cpp (revision 242)
@@ -0,0 +1,1016 @@
+///////////////////////////////////////////////////////////////////////////////
+// File: split_merge.cpp //
+// Description: source file for splitting/merging (contains the CJet class) //
+// This file is part of the SISCone project. //
+// WARNING: this is not the main SISCone trunk but //
+// an adaptation to spherical coordinates //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: $//
+// $Date:: $//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "split_merge.h"
+#include "siscone_error.h"
+#include "momentum.h"
+#include <math.h>
+#include <limits> // for max
+#include <iostream>
+#include <algorithm>
+#include <sstream>
+#include <cassert>
+
+namespace siscone{
+
+using namespace std;
+
+/********************************************************
+ * class Cjet implementation *
+ * real Jet information. *
+ * This class contains information for one single jet. *
+ * That is, first, its momentum carrying information *
+ * about its centre and pT, and second, its particle *
+ * contents *
+ ********************************************************/
+// default ctor
+//--------------
+Cjet::Cjet(){
+ n = 0;
+ v = Cmomentum();
+ pt_tilde = 0.0;
+ sm_var2 = 0.0;
+}
+
+// default dtor
+//--------------
+Cjet::~Cjet(){
+
+}
+
+// ordering of jets in pt
+//------------------------
+bool jets_pt_less(const Cjet &j1, const Cjet &j2){
+ return j1.v.perp2() > j2.v.perp2();
+}
+
+// ordering of jets in E (e.g. used in final jets ordering)
+//----------------------------------------------------------
+bool jets_E_less(const Cjet &j1, const Cjet &j2){
+ return j1.v.E > j2.v.E;
+}
+
+
+/********************************************************
+ * Csplit_merge_ptcomparison implementation *
+ * This deals with the ordering of the jets candidates *
+ ********************************************************/
+
+// odering of two jets
+// The variable of the ordering is pt or mt
+// depending on 'split_merge_scale' choice
+//
+// with EPSILON_SPLITMERGE defined, this attempts to identify
+// delicate cases where two jets have identical momenta except for
+// softish particles -- the difference of pt's may not be correctly
+// identified normally and so lead to problems for the fate of the
+// softish particle.
+//
+// NB: there is a potential issue in momentum-conserving events,
+// whereby the harder of two jets becomes ill-defined when a soft
+// particle is emitted --- this may have a knock-on effect on
+// subsequent split-merge steps in cases with sufficiently large R
+// (but we don't know what the limit is...)
+//------------------------------------------------------------------
+bool Csplit_merge_ptcomparison::operator ()(const Cjet &jet1, const Cjet &jet2) const{
+ double q1, q2;
+
+ // compute the value for comparison for both jets
+ // This depends on the choice of variable (mt is the default)
+ q1 = jet1.sm_var2;
+ q2 = jet2.sm_var2;
+
+ bool res = q1 > q2;
+
+ // if we enable the refined version of the comparison (see defines.h),
+ // we compute the difference more precisely when the two jets are very
+ // close in the ordering variable.
+#ifdef EPSILON_SPLITMERGE
+ if ( (fabs(q1-q2) < EPSILON_SPLITMERGE*max(q1,q2)) &&
+ (jet1.v.ref != jet2.v.ref) ) {
+ // get the momentum of the difference
+ Cmomentum difference;
+ double pt_tilde_difference;
+ get_difference(jet1,jet2,&difference,&pt_tilde_difference);
+
+ // use the following relation: pt1^2 - pt2^2 = (pt1+pt2)*(pt1-pt2)
+ double qdiff;
+ Cmomentum sum = jet1.v ;
+ sum += jet2.v;
+ double pt_tilde_sum = jet1.pt_tilde + jet2.pt_tilde;
+
+ // depending on the choice of ordering variable, set the result
+ switch (split_merge_scale){
+ case SM_mt:
+ qdiff = sum.E*difference.E - sum.pz*difference.pz;
+ break;
+ case SM_pt:
+ qdiff = sum.px*difference.px + sum.py*difference.py;
+ break;
+ case SM_pttilde:
+ qdiff = pt_tilde_sum*pt_tilde_difference;
+ break;
+ case SM_E:
+ qdiff = sum.E*difference.E;
+ break;
+ case SM_Et:
+ // diff = E^2 (dpt^2 pz^2- pt^2 dpz^2)
+ // + dE^2 (pt^2+pz^2) pt2^2
+ // where, unless explicitely specified the variables
+ // refer to the first jet or differences jet1-jet2.
+ qdiff = jet1.v.E*jet1.v.E*
+ ((sum.px*difference.px + sum.py*difference.py)*jet1.v.pz*jet1.v.pz
+ -jet1.v.perp2()*sum.pz*difference.pz)
+ +sum.E*difference.E*(jet1.v.perp2()+jet1.v.pz*jet1.v.pz)*jet2.v.perp2();
+ break;
+ default:
+ throw Csiscone_error("Unsupported split-merge scale choice: "
+ + SM_scale_name());
+ }
+ res = qdiff > 0;
+ }
+#endif // EPSILON_SPLITMERGE
+
+ return res;
+}
+
+
+/// return a name for the sm scale choice
+/// NB: used internally and also by fastjet
+std::string split_merge_scale_name(Esplit_merge_scale sms) {
+ switch(sms) {
+ case SM_pt:
+ return "pt (IR unsafe)";
+ case SM_Et:
+ return "Et (boost dep.)";
+ case SM_E:
+ return "E (boost dep.)";
+ case SM_mt:
+ return "mt (IR safe except for pairs of identical decayed heavy particles)";
+ case SM_pttilde:
+ return "pttilde (scalar sum of pt's)";
+ default:
+ return "[SM scale without a name]";
+ }
+}
+
+
+// get the difference between 2 jets
+// - j1 first jet
+// - j2 second jet
+// - v jet1-jet2
+// - pt_tilde jet1-jet2 pt_tilde
+// return true if overlapping, false if disjoint
+//-----------------------------------------------
+void Csplit_merge_ptcomparison::get_difference(const Cjet &j1, const Cjet &j2, Cmomentum *v, double *pt_tilde) const {
+ int i1,i2;
+
+ // initialise
+ i1=i2=0;
+ *v = Cmomentum();
+ *pt_tilde = 0.0;
+
+ // compute overlap
+ // at the same time, we store union in indices
+ do{
+ if (j1.contents[i1]==j2.contents[i2]) {
+ i1++;
+ i2++;
+ } else if (j1.contents[i1]<j2.contents[i2]){
+ (*v) += (*particles)[j1.contents[i1]];
+ (*pt_tilde) += (*pt)[j1.contents[i1]];
+ i1++;
+ } else if (j1.contents[i1]>j2.contents[i2]){
+ (*v) -= (*particles)[j2.contents[i2]];
+ (*pt_tilde) -= (*pt)[j2.contents[i2]];
+ i2++;
+ } else {
+ throw Csiscone_error("get_non_overlap reached part it should never have seen...");
+ }
+ } while ((i1<j1.n) && (i2<j2.n));
+
+ // deal with particles at the end of the list...
+ while (i1 < j1.n) {
+ (*v) += (*particles)[j1.contents[i1]];
+ (*pt_tilde) += (*pt)[j1.contents[i1]];
+ i1++;
+ }
+ while (i2 < j2.n) {
+ (*v) -= (*particles)[j2.contents[i2]];
+ (*pt_tilde) -= (*pt)[j2.contents[i2]];
+ i2++;
+ }
+}
+
+
+/********************************************************
+ * class Csplit_merge implementation *
+ * Class used to split and merge jets. *
+ ********************************************************/
+// default ctor
+//--------------
+Csplit_merge::Csplit_merge(){
+ merge_identical_protocones = false;
+#ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
+#ifdef MERGE_IDENTICAL_PROTOCONES_DEFAULT_TRUE
+ merge_identical_protocones = true;
+#endif
+#endif
+ indices = NULL;
+
+ // ensure that ptcomparison points to our set of particles (though params not correct)
+ ptcomparison.particles = &particles;
+ ptcomparison.pt = &pt;
+ candidates.reset(new multiset<Cjet,Csplit_merge_ptcomparison>(ptcomparison));
+
+ // no hardest cut (col-unsafe)
+ SM_var2_hardest_cut_off = -1.0;
+
+ // no pt cutoff for the particles to put in p_uncol_hard
+ stable_cone_soft_pt2_cutoff = -1.0;
+
+ // no pt-weighted splitting
+ use_E_weighted_splitting = false;
+}
+
+
+// default dtor
+//--------------
+Csplit_merge::~Csplit_merge(){
+ full_clear();
+}
+
+
+// initialisation function
+// - _particles list of particles
+// - protocones list of protocones (initial jet candidates)
+// - R2 cone radius (squared)
+// - Emin minimal energy allowed for jets
+//-------------------------------------------------------------
+int Csplit_merge::init(vector<Cmomentum> &_particles, vector<Cmomentum> *protocones, double R2, double Emin){
+ // browse protocones
+ return add_protocones(protocones, R2, Emin);
+}
+
+
+// initialisation function for particle list
+// - _particles list of particles
+//-------------------------------------------------------------
+int Csplit_merge::init_particles(vector<Cmomentum> &_particles){
+ full_clear();
+
+ // compute the list of particles
+ // here, we do not need to throw away particles
+ // with infinite rapidity (colinear with the beam)
+ particles = _particles;
+ n = particles.size();
+
+ // build the vector of particles' pt and determine min,max eta
+ pt.resize(n);
+ for (int i=0;i<n;i++){
+ pt[i] = particles[i].perp();
+ }
+
+ // ensure that ptcomparison points to our set of particles (though params not correct)
+ ptcomparison.particles = &particles;
+ ptcomparison.pt = &pt;
+
+ // set up the list of particles left.
+ init_pleft();
+
+ indices = new int[n];
+
+ return 0;
+}
+
+
+// build initial list of remaining particles
+//------------------------------------------
+int Csplit_merge::init_pleft(){
+ // at this level, we only rule out particles with
+ // infinite rapidity
+ // in the parent particle list, index contain the run
+ // at which particles are puts in jets:
+ // - -1 means infinity rapidity
+ // - 0 means not included
+ // - i mean included at run i
+ int i,j;
+
+ // copy particles removing the ones with infinite rapidity
+ j=0;
+ p_remain.clear();
+ for (i=0;i<n;i++){
+ // set ref for checkxor
+ particles[i].ref.randomize();
+
+ //REMOVED: check if rapidity is not infinite or ill-defined
+ //if (fabs(particles[i].pz) < (particles[i].E)){
+ p_remain.push_back(particles[i]);
+ // set up parent index for tracability
+ p_remain[j].parent_index = i;
+ // left particles are marked with a 1
+ // IMPORTANT NOTE: the meaning of index in p_remain is
+ // somehow different as in the initial particle list.
+ // here, within one pass, we use the index to track whether
+ // a particle is included in the current pass (index set to 0
+ // in add_protocones) or still remain (index still 1)
+ p_remain[j].index = 1;
+
+ j++;
+ // set up parent-particle index
+ particles[i].index = 0;
+ //} else {
+ // particles[i].index = -1;
+ //}
+ }
+ n_left = p_remain.size();
+ n_pass = 0;
+
+ merge_collinear_and_remove_soft();
+
+ return 0;
+}
+
+
+// partial clearance
+// we want to keep particle list and indices
+// for future usage, so do not clear it !
+// this is done in full_clear
+//----------------------------------------
+int Csplit_merge::partial_clear(){
+ // release jets
+
+ // set up the auto_ptr for the multiset with the _current_ state of
+ // ptcomparison (which may have changed since we constructed the
+ // class)
+ candidates.reset(new multiset<Cjet,Csplit_merge_ptcomparison>(ptcomparison));
+
+ // start off with huge number
+ most_ambiguous_split = numeric_limits<double>::max();
+
+ jets.clear();
+#ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
+ if (merge_identical_protocones)
+ cand_refs.clear();
+#endif
+
+ p_remain.clear();
+
+ return 0;
+}
+
+
+// full clearance
+//----------------
+int Csplit_merge::full_clear(){
+ partial_clear();
+
+ // clear previously allocated memory
+ if (indices != NULL){
+ delete[] indices;
+ }
+ particles.clear();
+
+ return 0;
+}
+
+
+// build the list 'p_uncol_hard' from p_remain by clustering collinear particles
+// note that thins in only used for stable-cone detection
+// so the parent_index field is unnecessary
+//-------------------------------------------------------------------------
+int Csplit_merge::merge_collinear_and_remove_soft(){
+ int i,j;
+ vector<Cmomentum> p_sorted;
+ bool collinear;
+ double dphi;
+
+ p_uncol_hard.clear();
+
+ // we first sort the particles according to their theta angle
+ for (i=0;i<n_left;i++)
+ p_sorted.push_back(p_remain[i]);
+ sort(p_sorted.begin(), p_sorted.end(), momentum_theta_less);
+
+ // then we cluster particles looping over the particles in the following way
+ // if (a particle i has same eta-phi a one after (j))
+ // then add momentum i to j
+ // else add i to the p_uncol_hard list
+ i = 0;
+ while (i<n_left){
+ //REMOVED: // check if the particle passes the stable_cone_soft_pt2_cutoff
+ //REMOVED: if (p_sorted[i].perp2()<stable_cone_soft_pt2_cutoff) {
+ //REMOVED: i++;
+ //REMOVED: continue;
+ //REMOVED: }
+
+ // check if there is(are) particle(s) with the 'same' theta
+ collinear = false;
+ j=i+1;
+ while ((j<n_left) && (fabs(p_sorted[j]._theta-p_sorted[i]._theta)<EPSILON_COLLINEAR) && (!collinear)){
+ dphi = fabs(p_sorted[j]._phi-p_sorted[i]._phi);
+ if (dphi>M_PI) dphi = twopi-dphi;
+ if (dphi<EPSILON_COLLINEAR){
+ // i is collinear with j; add the momentum (i) to the momentum (j)
+#ifdef DEBUG_SPLIT_MERGE
+ cout << "# collinear merging at point " << p_sorted[i]._theta << ", " << p_sorted[j]._phi << endl;
+#endif
+ p_sorted[j] += p_sorted[i];
+ //p_sorted[j].build_thetaphi();
+ p_sorted[j].build_norm();
+ // set collinearity test to true
+ collinear = true;
+ }
+ j++;
+ }
+ // if no collinearity detected, add the particle to our list
+ if (!collinear)
+ p_uncol_hard.push_back(p_sorted[i]);
+ i++;
+ }
+
+ return 0;
+}
+
+
+// add a list of protocones
+// - protocones list of protocones (initial jet candidates)
+// - R2 cone radius (squared)
+// - Emin minimal energy allowed for jets
+//-------------------------------------------------------------
+int Csplit_merge::add_protocones(vector<Cmomentum> *protocones, double R2, double Emin){
+ int i;
+ Cmomentum *c;
+ Cmomentum *v;
+ double tan2R;
+ Cjet jet;
+
+ if (protocones->size()==0)
+ return 1;
+
+ E_min = Emin;
+ double R = sqrt(R2);
+ tan2R = tan(R);
+ tan2R *= tan2R;
+
+#ifdef DEBUG_SPLIT_MERGE
+ cout << "particle list: ";
+ for (int i2=0;i2<n_left;i2++)
+ cout << p_remain[i2].parent_index << " "
+ << p_remain[i2].px << " " << p_remain[i2].py << " "
+ << p_remain[i2].pz << " " << p_remain[i2].E << endl;
+ cout << endl;
+#endif
+
+ // browse protocones
+ // for each of them, build the list of particles in them
+ for (vector<Cmomentum>::iterator p_it = protocones->begin();p_it != protocones->end();p_it++){
+ // initialise variables
+ c = &(*p_it);
+
+ // browse particles to create cone contents
+ // note that jet is always initialised with default values at this level
+ jet.v = Cmomentum();
+ jet.pt_tilde=0;
+ jet.contents.clear();
+ for (i=0;i<n_left;i++){
+ v = &(p_remain[i]);
+ if (is_closer(v, c, tan2R)){
+ jet.contents.push_back(v->parent_index);
+ jet.v+= *v;
+ jet.pt_tilde+= pt[v->parent_index];
+ v->index=0;
+ }
+ }
+ jet.n=jet.contents.size();
+
+ // set the momentum in protocones
+ // (it was only known through its spatial coordinates up to now)
+ *c = jet.v;
+ c->build_thetaphi();
+
+ // set the jet range
+ jet.range=Ctheta_phi_range(c->_theta,c->_phi,R);
+
+#ifdef DEBUG_SPLIT_MERGE
+ cout << "adding protojet: ";
+ for (int i2=0;i2<jet.n;i2++)
+ cout << jet.contents[i2] << " ";
+ cout << endl;
+#endif
+
+ // add it to the list of jets
+ insert(jet);
+ }
+
+ // update list of included particles
+ n_pass++;
+
+#ifdef DEBUG_SPLIT_MERGE
+ cout << "remaining particles: ";
+#endif
+ int j=0;
+ for (i=0;i<n_left;i++){
+ if (p_remain[i].index){
+ // copy particle
+ p_remain[j]=p_remain[i];
+ p_remain[j].parent_index = p_remain[i].parent_index;
+ p_remain[j].index=1;
+ // set run in initial list
+ particles[p_remain[j].parent_index].index = n_pass;
+#ifdef DEBUG_SPLIT_MERGE
+ cout << p_remain[j].parent_index << " ";
+#endif
+ j++;
+ }
+ }
+#ifdef DEBUG_SPLIT_MERGE
+ cout << endl;
+#endif
+ n_left = j;
+ p_remain.resize(j);
+
+ merge_collinear_and_remove_soft();
+
+ return 0;
+}
+
+
+/*
+ * really do the splitting and merging
+ * At the end, the vector jets is filled with the jets found.
+ * the 'contents' field of each jets contains the indices
+ * of the particles included in that jet.
+ * - overlap_tshold threshold for splitting/merging transition
+ * - Emin minimal energy allowed for jets
+ * return the number of jets is returned
+ ******************************************************************/
+int Csplit_merge::perform(double overlap_tshold, double Emin){
+ // iterators for the 2 jets
+ cjet_iterator j1;
+ cjet_iterator j2;
+
+ E_min = Emin;
+
+ if (candidates->size()==0)
+ return 0;
+
+ if (overlap_tshold>=1.0 || overlap_tshold <= 0) {
+ ostringstream message;
+ message << "Illegal value for overlap_tshold, f = " << overlap_tshold;
+ message << " (legal values are 0<f<1)";
+ throw Csiscone_error(message.str());
+ }
+
+ // overlap (the contents of this variable depends on the choice for
+ // the split--merge variable.)
+ // Note that the square of the ovelap is used
+ double overlap2;
+
+ // avoid to compute tshold*tshold at each overlap
+ double overlap_tshold2 = overlap_tshold*overlap_tshold;
+
+ do{
+ if (candidates->size()>0){
+ // browse for the first jet
+ j1 = candidates->begin();
+
+ // if hardest jet does not pass threshold then nothing else will
+ // either so one stops the split merge.
+ if (j1->sm_var2<SM_var2_hardest_cut_off) {break;}
+
+ // browse for the second jet
+ j2 = j1;
+ j2++;
+ int j2_relindex = 1; // used only in ifdef, but costs little so keep it outside
+
+ while (j2 != candidates->end()){
+#ifdef DEBUG_SPLIT_MERGE
+ show();
+#endif
+ // check overlapping
+ if (get_overlap(*j1, *j2, &overlap2)){
+ // check if overlapping energy passes threshold
+ // Note that this depends on the ordering variable
+#ifdef DEBUG_SPLIT_MERGE
+ cout << "overlap between cdt 1 and cdt " << j2_relindex+1 << " with overlap "
+ << sqrt(overlap2/j2->sm_var2) << endl<<endl;
+#endif
+ if (overlap2<overlap_tshold2*j2->sm_var2){
+ // split jets
+ split(j1, j2);
+
+ // update iterators
+ j2 = j1 = candidates->begin();
+ j2_relindex = 0;
+ } else {
+ // merge jets
+ merge(j1, j2);
+
+ // update iterators
+ j2 = j1 = candidates->begin();
+ j2_relindex = 0;
+ }
+ }
+ // watch out: split/merge might have caused new jets with E <
+ // Emin to disappear, so the total number of jets may
+ // have changed by more than expected and j2 might already by
+ // the end of the candidates list...
+ j2_relindex++;
+ if (j2 != candidates->end()) j2++;
+ } // end of loop on the second jet
+
+ if (j1 != candidates->end()) {
+ // all "second jet" passed without overlapping
+ // (otherwise we won't leave the j2 loop)
+ // => store jet 1 as real jet
+ jets.push_back(*j1);
+ jets[jets.size()-1].v.build_thetaphi();
+ jets[jets.size()-1].v.build_norm();
+ // a bug where the contents has non-zero size has been cropping
+ // up in many contexts -- so catch it!
+ assert(j1->contents.size() > 0);
+ jets[jets.size()-1].pass = particles[j1->contents[0]].index;
+#ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
+ cand_refs.erase(j1->v.ref);
+#endif
+ candidates->erase(j1);
+ }
+ }
+ } while (candidates->size()>0);
+
+ // sort jets by Energy
+ sort(jets.begin(), jets.end(), jets_E_less);
+#ifdef DEBUG_SPLIT_MERGE
+ show();
+#endif
+
+ return jets.size();
+}
+
+
+
+// save the event on disk
+// - flux stream used to save jet contents
+//--------------------------------------------
+int Csplit_merge::save_contents(FILE *flux){
+ jet_iterator it_j;
+ Cjet *j1;
+ int i1, i2;
+
+ fprintf(flux, "# %d jets found\n", (int) jets.size());
+ fprintf(flux, "# columns are: px, py, pz, E and number of particles for each jet\n");
+ for (it_j = jets.begin(), i1=0 ; it_j != jets.end() ; it_j++, i1++){
+ j1 = &(*it_j);
+ fprintf(flux, "%le\t%le\t%le\t%le\t%d\n",
+ j1->v.px, j1->v.py, j1->v.pz, j1->v.E, j1->n);
+ }
+
+ fprintf(flux, "# jet contents\n");
+ fprintf(flux, "# columns are: px, py, pz, E, particle index and jet number\n");
+ for (it_j = jets.begin(), i1=0 ; it_j != jets.end() ; it_j++, i1++){
+ j1 = &(*it_j);
+ for (i2=0;i2<j1->n;i2++)
+ fprintf(flux, "%le\t%le\t%le\t%le\t%d\t%d\n",
+ particles[j1->contents[i2]].px, particles[j1->contents[i2]].py,
+ particles[j1->contents[i2]].pz, particles[j1->contents[i2]].E,
+ j1->contents[i2], i1);
+ }
+
+ return 0;
+}
+
+
+// show current jets/candidate status
+//------------------------------------
+int Csplit_merge::show(){
+ jet_iterator it_j;
+ cjet_iterator it_c;
+ Cjet *j;
+ const Cjet *c;
+ int i1, i2;
+
+ for (it_j = jets.begin(), i1=0 ; it_j != jets.end() ; it_j++, i1++){
+ j = &(*it_j);
+ fprintf(stdout, "jet %2d: %le\t%le\t%le\t%le\t", i1+1,
+ j->v.px, j->v.py, j->v.pz, j->v.E);
+ for (i2=0;i2<j->n;i2++)
+ fprintf(stdout, "%d ", j->contents[i2]);
+ fprintf(stdout, "\n");
+ }
+
+ for (it_c = candidates->begin(), i1=0 ; it_c != candidates->end() ; it_c++, i1++){
+ c = &(*it_c);
+ fprintf(stdout, "cdt %2d: %le\t%le\t%le\t%le\t%le\t", i1+1,
+ c->v.px, c->v.py, c->v.pz, c->v.E, sqrt(c->sm_var2));
+ for (i2=0;i2<c->n;i2++)
+ fprintf(stdout, "%d ", c->contents[i2]);
+ fprintf(stdout, "\n");
+ }
+
+ fprintf(stdout, "\n");
+ return 0;
+}
+
+
+// get the overlap between 2 jets
+// - j1 first jet
+// - j2 second jet
+// - overlap2 returned overlap^2 (determined by the choice of SM variable)
+// return true if overlapping, false if disjoint
+//---------------------------------------------------------------------
+bool Csplit_merge::get_overlap(const Cjet &j1, const Cjet &j2, double *overlap2){
+ // check if ranges overlap
+ if (!is_range_overlap(j1.range,j2.range))
+ return false;
+
+ int i1,i2;
+ bool is_overlap;
+
+ // initialise
+ i1=i2=idx_size=0;
+ is_overlap = false;
+ Cmomentum v;
+ double pt_tilde=0.0;
+
+ // compute overlap
+ // at the same time, we store union in indices
+ do{
+ if (j1.contents[i1]<j2.contents[i2]){
+ indices[idx_size] = j1.contents[i1];
+ i1++;
+ } else if (j1.contents[i1]>j2.contents[i2]){
+ indices[idx_size] = j2.contents[i2];
+ i2++;
+ } else { // (j1.contents[i1]==j2.contents[i2])
+ v += particles[j1.contents[i1]];
+ pt_tilde += pt[j1.contents[i1]];
+ indices[idx_size] = j1.contents[i1];
+ i1++;
+ i2++;
+ is_overlap = true;
+ }
+ idx_size++;
+ } while ((i1<j1.n) && (i2<j2.n));
+
+ // finish computing union
+ // (only needed if overlap !)
+ if (is_overlap){
+ while (i1<j1.n){
+ indices[idx_size] = j1.contents[i1];
+ i1++;
+ idx_size++;
+ }
+ while (i2<j2.n){
+ indices[idx_size] = j2.contents[i2];
+ i2++;
+ idx_size++;
+ }
+ }
+
+ // assign the overlapping var as return variable
+ (*overlap2) = get_sm_var2(v, pt_tilde);
+
+ return is_overlap;
+}
+
+
+
+// split the two given jet.
+// during this procedure, the jets j1 & j2 are replaced
+// by 2 new jets. Common particles are associted to the
+// closest initial jet.
+// - it_j1 iterator of the first jet in 'candidates'
+// - it_j2 iterator of the second jet in 'candidates'
+// - j1 first jet (Cjet instance)
+// - j2 second jet (Cjet instance)
+// return true on success, false on error
+////////////////////////////////////////////////////////////////
+bool Csplit_merge::split(cjet_iterator &it_j1, cjet_iterator &it_j2){
+ int i1, i2;
+ Cjet jet1, jet2;
+ double E1_weight, E2_weight;
+ Cmomentum tmp;
+ Cmomentum *v;
+
+ // shorthand to avoid having "->" all over the place
+ const Cjet & j1 = * it_j1;
+ const Cjet & j2 = * it_j2;
+
+ i1=i2=0;
+ jet2.v = jet1.v = Cmomentum();
+ jet2.pt_tilde = jet1.pt_tilde = 0.0;
+
+ // compute centroids
+ // When use_E_weighted_splitting is activated, the
+ // "geometrical" distance is weighted by the inverse
+ // of the E of the protojet
+ // This is stored in E{1,2}_weight
+ E1_weight = (use_E_weighted_splitting) ? 1.0/j1.v.E/j1.v.E : 1.0;
+ E2_weight = (use_E_weighted_splitting) ? 1.0/j2.v.E/j2.v.E : 1.0;
+
+ jet1.v = jet2.v = Cmomentum();
+
+ // compute jet splitting
+ do{
+ if (j1.contents[i1]<j2.contents[i2]){
+ // particle i1 belong only to jet 1
+ v = &(particles[j1.contents[i1]]);
+ jet1.contents.push_back(j1.contents[i1]);
+ jet1.v += *v;
+ jet1.pt_tilde += pt[j1.contents[i1]];
+ i1++;
+ jet1.range.add_particle(v->_theta,v->_phi);
+ } else if (j1.contents[i1]>j2.contents[i2]){
+ // particle i2 belong only to jet 2
+ v = &(particles[j2.contents[i2]]);
+ jet2.contents.push_back(j2.contents[i2]);
+ jet2.v += *v;
+ jet2.pt_tilde += pt[j2.contents[i2]];
+ i2++;
+ jet2.range.add_particle(v->_theta,v->_phi);
+ } else { // (j1.contents[i1]==j2.contents[i2])
+ // common particle, decide which is the closest centre
+ v = &(particles[j1.contents[i1]]);
+
+ //TODO: improve this brutal use of atan2 and sqrt !!!!
+
+ //? what when == ?
+ // When use_E_weighted_splitting is activated, the
+ // "geometrical" distance is weighted by the inverse
+ // of the E of the protojet
+ double d1 = get_distance(&(j1.v), v)*E1_weight;
+ double d2 = get_distance(&(j2.v), v)*E2_weight;
+ // do bookkeeping on most ambiguous split
+ if (fabs(d1-d2) < most_ambiguous_split)
+ most_ambiguous_split = fabs(d1-d2);
+
+ if (d1<d2){
+ // particle i1 belong only to jet 1
+ jet1.contents.push_back(j1.contents[i1]);
+ jet1.v += *v;
+ jet1.pt_tilde += pt[j1.contents[i1]];
+ jet1.range.add_particle(v->_theta,v->_phi);
+ } else {
+ // particle i2 belong only to jet 2
+ jet2.contents.push_back(j2.contents[i2]);
+ jet2.v += *v;
+ jet2.pt_tilde += pt[j2.contents[i2]];
+ jet2.range.add_particle(v->_theta,v->_phi);
+ }
+
+ i1++;
+ i2++;
+ }
+ } while ((i1<j1.n) && (i2<j2.n));
+
+ while (i1<j1.n){
+ v = &(particles[j1.contents[i1]]);
+ jet1.contents.push_back(j1.contents[i1]);
+ jet1.v += *v;
+ jet1.pt_tilde += pt[j1.contents[i1]];
+ i1++;
+ jet1.range.add_particle(v->_theta,v->_phi);
+ }
+ while (i2<j2.n){
+ v = &(particles[j2.contents[i2]]);
+ jet2.contents.push_back(j2.contents[i2]);
+ jet2.v += *v;
+ jet2.pt_tilde += pt[j2.contents[i2]];
+ i2++;
+ jet2.range.add_particle(v->_theta,v->_phi);
+ }
+
+ // finalise jets
+ jet1.n = jet1.contents.size();
+ jet2.n = jet2.contents.size();
+
+ // remove previous jets
+#ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
+ cand_refs.erase(j1.v.ref);
+ cand_refs.erase(j2.v.ref);
+#endif
+ candidates->erase(it_j1);
+ candidates->erase(it_j2);
+
+ // reinsert new ones
+ insert(jet1);
+ insert(jet2);
+
+ return true;
+}
+
+// merge the two given jet.
+// during this procedure, the jets j1 & j2 are replaced
+// by 1 single jets containing both of them.
+// - it_j1 iterator of the first jet in 'candidates'
+// - it_j2 iterator of the second jet in 'candidates'
+// return true on success, false on error
+////////////////////////////////////////////////////////////////
+bool Csplit_merge::merge(cjet_iterator &it_j1, cjet_iterator &it_j2){
+ Cjet jet;
+ int i;
+
+ // build new jet
+ // note: particles within j1 & j2 have already been stored in indices
+ for (i=0;i<idx_size;i++){
+ jet.contents.push_back(indices[i]);
+ jet.v += particles[indices[i]];
+ jet.pt_tilde += pt[indices[i]];
+ }
+ jet.n = jet.contents.size();
+
+ // deal with ranges
+ jet.range = range_union(it_j1->range, it_j2->range);
+
+ // remove old candidates
+#ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
+ if (merge_identical_protocones){
+ cand_refs.erase(it_j1->v.ref);
+ cand_refs.erase(it_j2->v.ref);
+ }
+#endif
+ candidates->erase(it_j1);
+ candidates->erase(it_j2);
+
+ // reinsert new candidate
+ insert(jet);
+
+ return true;
+}
+
+/**
+ * Check whether or not a jet has to be inserted in the
+ * list of protojets. If it has, set its sm_variable and
+ * insert it to the list of protojets.
+ */
+bool Csplit_merge::insert(Cjet &jet){
+
+ // eventually check that no other candidate are present with the
+ // same cone contents. We recall that this automatic merging of
+ // identical protocones can lead to infrared-unsafe situations.
+#ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
+ if ((merge_identical_protocones) && (!cand_refs.insert(jet.v.ref).second))
+ return false;
+#endif
+
+ // check that the protojet has large enough energy
+ if (jet.v.E<E_min)
+ return false;
+
+ // assign SM variable
+ jet.sm_var2 = get_sm_var2(jet.v, jet.pt_tilde);
+
+ // insert the jet.
+ candidates->insert(jet);
+
+ return true;
+}
+
+/**
+ * given a 4-momentum and its associated pT, return the
+ * variable that has to be used for SM
+ * \param v 4 momentum of the protojet
+ * \param pt_tilde pt_tilde of the protojet
+ */
+double Csplit_merge::get_sm_var2(Cmomentum &v, double &pt_tilde){
+ switch(ptcomparison.split_merge_scale) {
+ case SM_E: return v.E*v.E;
+ case SM_pt: return v.perp2();
+ case SM_mt: return v.perpmass2();
+ case SM_pttilde: return pt_tilde*pt_tilde;
+ case SM_Et: return v.Et2();
+ default:
+ throw Csiscone_error("Unsupported split-merge scale choice: "
+ + ptcomparison.SM_scale_name());
+ }
+
+ return 0.0;
+}
+
+}
Property changes on: branches/spherical/siscone/spherical/split_merge.cpp
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+Date Rev
\ No newline at end of property
Index: branches/spherical/siscone/spherical/geom_2d.cpp
===================================================================
--- branches/spherical/siscone/spherical/geom_2d.cpp (revision 0)
+++ branches/spherical/siscone/spherical/geom_2d.cpp (revision 242)
@@ -0,0 +1,167 @@
+///////////////////////////////////////////////////////////////////////////////
+// File: geom_2d.cpp //
+// Description: source file for two-dimensional geometry tools //
+// This file is part of the SISCone project. //
+// WARNING: this is not the main SISCone trunk but //
+// an adaptation to spherical coordinates //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: $//
+// $Date:: $//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "geom_2d.h"
+#include <algorithm>
+
+namespace siscone{
+
+#define PHI_RANGE_MASK 0xFFFFFFFF
+
+/*********************************************************
+ * class Ceta_phi_range implementation *
+ * class for holding a covering range in eta-phi *
+ * *
+ * This class deals with ranges in the eta-phi plane. It *
+ * implements methods to test if two ranges overlap and *
+ * to take the union of two overlapping intervals. *
+ *********************************************************/
+
+using namespace std;
+
+// static member default init
+//----------------------------
+double Ctheta_phi_range::theta_min = 0.0;
+double Ctheta_phi_range::theta_max = M_PI;
+
+// default ctor
+//--------------
+Ctheta_phi_range::Ctheta_phi_range(){
+ theta_range = 0;
+ phi_range = 0;
+}
+
+// ctor with initialisation
+// we initialise with a centre (in eta,phi) and a radius
+// - c_theta theta coordinate of the centre
+// - c_phi phi coordinate of the centre
+// - R radius
+//-------------------------------------------------------
+Ctheta_phi_range::Ctheta_phi_range(double c_theta, double c_phi, double R){
+ // determination of the eta range
+ //-------------------------------
+ double xmin = max(c_theta-R,theta_min+0.00001);
+ double xmax = min(c_theta+R,theta_max-0.00001);
+
+ unsigned int cell_min = get_theta_cell(xmin);
+ unsigned int cell_max = get_theta_cell(xmax);
+
+ // warning: if cell_max==2^31, 2*cell_max==0 hence,
+ // even if the next formula is formally (2*cell_max-cell_min),
+ // expressing it as (cell_max-cell_min)+cell_max is safe.
+ theta_range = (cell_max-cell_min)+cell_max;
+
+ // determination of the phi range
+ // !! taking care of periodicity !!
+ // !! and the theta dependence !!
+ //---------------------------------
+ double ymin,ymax;
+ double extra = asin(R/M_PI);
+ if (xmin<=theta_min+extra){
+ ymin = -M_PI+0.00001;
+ ymax = M_PI-0.00001;
+ } else if (xmax>=theta_max-extra){
+ ymin = -M_PI+0.00001;
+ ymax = M_PI-0.00001;
+ } else {
+ extra = max(1.0/sin(xmin), 1.0/sin(xmax));
+ ymin = (c_phi-R)*extra;
+ while (ymin<-M_PI) ymin+=twopi;
+ while (ymin> M_PI) ymin-=twopi;
+ ymax = (c_phi-R)*extra;
+ while (ymax<-M_PI) ymax+=twopi;
+ while (ymax> M_PI) ymax-=twopi;
+ }
+ cell_min = get_phi_cell(ymin);
+ cell_max = get_phi_cell(ymax);
+
+ // Also, if the interval goes through pi, inversion is needed
+ if (ymax>ymin)
+ phi_range = (cell_max-cell_min)+cell_max;
+ else {
+ phi_range = (cell_min==cell_max)
+ ? PHI_RANGE_MASK
+ : ((PHI_RANGE_MASK^(cell_min-cell_max)) + cell_max);
+ }
+}
+
+// assignment of range
+// - r range to assign to current one
+//---------------------------------------
+Ctheta_phi_range& Ctheta_phi_range::operator = (const Ctheta_phi_range &r){
+ theta_range = r.theta_range;
+ phi_range = r.phi_range;
+
+ return *this;
+}
+
+// add a particle to the range
+// - eta eta coordinate of the particle
+// - phi phi coordinate of the particle
+// \return 0 on success, 1 on error
+//----------------------------------------
+int Ctheta_phi_range::add_particle(const double theta, const double phi){
+ // deal with the eta coordinate
+ theta_range |= get_theta_cell(theta);
+
+ // deal with the phi coordinate
+ phi_range |= get_phi_cell(phi);
+
+ return 0;
+}
+
+
+// test overlap
+// - r1 first range
+// - r2 second range
+// return true if overlap, false otherwise.
+//------------------------------------------
+bool is_range_overlap(const Ctheta_phi_range &r1, const Ctheta_phi_range &r2){
+ // check overlap in eta AND phi
+ return ((r1.theta_range & r2.theta_range) && (r1.phi_range & r2.phi_range));
+}
+
+// compute union
+// Note: we assume that the two intervals overlap
+// - r1 first range
+// - r2 second range
+// \return union of the two ranges
+//------------------------------------------
+const Ctheta_phi_range range_union (const Ctheta_phi_range &r1, const Ctheta_phi_range &r2){
+ Ctheta_phi_range tmp;
+
+ // compute union in eta
+ tmp.theta_range = r1.theta_range | r2.theta_range;
+
+ // compute union in phi
+ tmp.phi_range = r1.phi_range | r2.phi_range;
+
+ return tmp;
+}
+
+}
Property changes on: branches/spherical/siscone/spherical/geom_2d.cpp
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+Date Revision
\ No newline at end of property
Index: branches/spherical/siscone/spherical/split_merge.h
===================================================================
--- branches/spherical/siscone/spherical/split_merge.h (revision 0)
+++ branches/spherical/siscone/spherical/split_merge.h (revision 242)
@@ -0,0 +1,406 @@
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: split_merge.h //
+// Description: header file for splitting/merging (contains the CJet class) //
+// This file is part of the SISCone project. //
+// WARNING: this is not the main SISCone trunk but //
+// an adaptation to spherical coordinates //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: $//
+// $Date:: $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __SPLIT_MERGE_H__
+#define __SPLIT_MERGE_H__
+
+#include "defines.h"
+#include "geom_2d.h"
+#include "momentum.h"
+#include <stdio.h>
+#include <vector>
+#include <set>
+#include <memory>
+#include <string>
+
+namespace siscone{
+
+/**
+ * \class Cjet
+ * real Jet information.
+ *
+ * This class contains information for one single jet.
+ * That is, first, its momentum carrying information
+ * about its centre and pT, and second, its particle
+ * contents
+ */
+class Cjet{
+ public:
+ /// default ctor
+ Cjet();
+
+ /// default dtor
+ ~Cjet();
+
+ Cmomentum v; ///< jet momentum
+ double pt_tilde; ///< p-scheme pt
+ int n; ///< number of particles inside
+ std::vector<int> contents; ///< particle contents (list of indices)
+
+ /// ordering variable used for ordering and overlap in the
+ /// split--merge. This variable is automatically set either to
+ /// pt_tilde, or to mt or to pt, depending on the siscone
+ /// parameter. Note that the default behaviour is pt_tilde and that
+ /// other chices may lead to infrared unsafe situations.
+ /// Note: we use the square of the varible rather than the variable itself
+ double sm_var2;
+
+ /// covered range in eta-phi
+ Ctheta_phi_range range;
+
+ /// pass at which the jet has been found
+ /// It starts at 0 (first pass), -1 means infinite rapidity
+ int pass;
+};
+
+/// ordering of jets in pt
+bool jets_pt_less(const Cjet &j1, const Cjet &j2);
+
+/// ordering of jets in energy (e.g. used in final jets ordering)
+bool jets_E_less(const Cjet &j1, const Cjet &j2);
+
+
+/// the choices of scale variable that can be used in the split-merge
+/// step, both for ordering the protojets and for measuing their
+/// overlap; pt, Et and mt=sqrt(pt^2+m^2) are all defined in E-scheme
+/// (4-momentum) recombination; pttilde = \sum_{i\in jet} |p_{t,i}|
+///
+/// NB: if one changes the order here, one _MUST_ also change the order
+/// in the SISCone plugin
+enum Esplit_merge_scale {
+ SM_pt, ///< transverse momentum (E-scheme), IR unsafe
+ SM_Et, ///< transverse energy (E-scheme), not long. boost inv.
+ ///< original run-II choice [may not be implemented]
+ SM_mt, ///< transverse mass (E-scheme), IR safe except
+ ///< in decays of two identical narrow heavy particles
+ SM_pttilde, ///< pt-scheme pt = \sum_{i in jet} |p_{ti}|, should
+ ///< be IR safe in all cases
+ SM_E ///< pt-scheme pt = \sum_{i in jet} |p_{ti}|, should
+ ///< be IR safe in all cases
+};
+
+/// return the name of the split-merge scale choice
+std::string split_merge_scale_name(Esplit_merge_scale sms);
+
+/**
+ * \class Csplit_merge_comparison
+ * a class that allows us to carry out comparisons of pt of jets, using
+ * information from exact particle contents where necessary.
+ *
+ */
+class Csplit_merge_ptcomparison{
+public:
+ Csplit_merge_ptcomparison() :
+ particles(0), split_merge_scale(SM_E){};
+
+ // return the name corresponding to the SM scale variable
+ std::string SM_scale_name() const {
+ return split_merge_scale_name(split_merge_scale);}
+
+ std::vector<Cmomentum> * particles;
+ std::vector<double> * pt;
+ bool operator()(const Cjet &jet1, const Cjet &jet2) const;
+
+ /**
+ * get the difference between 2 jets, calculated such that rounding
+ * errors will not affect the result even if the two jets have
+ * almost the same content (so that the difference is below the
+ * rounding errors)
+ *
+ * \param j1 first jet
+ * \param j2 second jet
+ * \param v jet1-jet2
+ * \param pt_tilde jet1-jet2 pt_tilde
+ */
+ void get_difference(const Cjet &j1, const Cjet &j2, Cmomentum *v, double *pt_tilde) const;
+
+ /// the following parameter controls the variable we're using for
+ /// the split-merge process i.e. the variable we use for
+ /// 1. ordering jet candidates;
+ /// 2. computing te overlap fraction of two candidates.
+ /// The default value uses pttile (p-scheme pt). Other alternatives are
+ /// pt, mt=sqrt(pt^2+m^2)=sqrt(E^2-pz^2) or Et.
+ /// NOTE: Modifying the default choice can have nasty effects:
+ /// - using pt leads to some IR unsafety when we have two jets,
+ /// e.g. back-to-back, with the same pt. In that case, their ordering
+ /// in pt is random and can be affected by the addition of a
+ /// soft particle. Hence, we highly recommand to keep this to
+ /// the default value i.e. to use pt only for the purpose of
+ /// investigating the IR issue
+ /// - using Et is safe but do not respect boost invariance
+ /// - using mt solves the IR unsafety issues with the pt variable
+ /// for QCD jets but the IR unsafety remains for nack-to-back
+ /// jets of unstable narrow-width particles (e.g. Higgs).
+ /// Therefore, keeping the default value is strongly advised.
+ Esplit_merge_scale split_merge_scale;
+};
+
+
+// iterator types
+/// iterator definition for the jet candidates structure
+typedef std::multiset<siscone::Cjet,Csplit_merge_ptcomparison>::iterator cjet_iterator;
+
+/// iterator definition for the jet structure
+typedef std::vector<siscone::Cjet>::iterator jet_iterator;
+
+
+
+/**
+ * \class Csplit_merge
+ * Class used to split and merge jets.
+ */
+class Csplit_merge{
+ public:
+ /// default ctor
+ Csplit_merge();
+
+ /// default dtor
+ ~Csplit_merge();
+
+
+ //////////////////////////////
+ // initialisation functions //
+ //////////////////////////////
+
+ /**
+ * initialisation function
+ * \param _particles list of particles
+ * \param protocones list of protocones (initial jet candidates)
+ * \param R2 cone radius (squared)
+ * \param Emin minimal energy allowed for jets
+ * \return 0 on success, 1 on error
+ */
+ int init(std::vector<Cmomentum> &_particles, std::vector<Cmomentum> *protocones, double R2, double Emin=0.0);
+
+ /**
+ * initialisation function for particle list
+ * \param _particles list of particles
+ * \return 0 on success, 1 on error
+ */
+ int init_particles(std::vector<Cmomentum> &_particles);
+
+ /**
+ * build initial list of left particles
+ */
+ int init_pleft();
+
+ /**
+ * use an energy-dependent boundary for splitting
+ * When called with true, the criterium for splitting two protojets
+ * will be to compare D1^2/kt1^2 vs. D2^2/kt2^2, the (anti-)kt-weighted
+ * distance instead of the plain distance D1^2 vs. D2^2.
+ * This can be set in order to produce more circular hard jets,
+ * with the same underlying philosophy as for the anti-kt algorithm.
+ * We thus expect a behaviour closer to the IterativeCone one.
+ * By default, we use the standard D1^2 vs. D2^2 comparison and this
+ * function is not called.
+ */
+ inline int set_E_weighted_splitting(bool _use_E_weighted_splitting){
+ use_E_weighted_splitting = _use_E_weighted_splitting;
+ return 0;
+ }
+
+ ////////////////////////
+ // cleaning functions //
+ ////////////////////////
+
+ /// partial clearance
+ int partial_clear();
+
+ /// full clearance
+ int full_clear();
+
+
+ /////////////////////////////////
+ // main parts of the algorithm //
+ /////////////////////////////////
+
+ /**
+ * build the list 'p_uncol_hard' from p_remain by clustering
+ * collinear particles
+ * note that thins in only used for stable-cone detection
+ * so the parent_index field is unnecessary
+ *
+ * Note that soft particles are not removed here
+ * This is just a remnant from the trunk version
+ */
+ int merge_collinear_and_remove_soft();
+
+ /**
+ * add a list of protocones
+ * \param protocones list of protocones (initial jet candidates)
+ * \param R2 cone radius (squared)
+ * \param Emin minimal emergy allowed for jets
+ * \return 0 on success, 1 on error
+ */
+ int add_protocones(std::vector<Cmomentum> *protocones, double R2, double Emin=0.0);
+
+ /**
+ * really do the splitting and merging
+ * At the end, the vector jets is filled with the jets found.
+ * the 'contents' field of each jets contains the indices
+ * of the particles included in that jet.
+ * \param overlap_tshold threshold for splitting/merging transition
+ * \param Emin minimal energy allowed for jets
+ * \return the number of jets is returned
+ */
+ int perform(double overlap_tshold, double Emin=0.0);
+
+
+ //////////////////////////////
+ // save and debug functions //
+ //////////////////////////////
+
+ /// save final jets
+ /// \param flux stream to save the jet contentss
+ int save_contents(FILE *flux);
+
+ /// show jets/candidates status
+ int show();
+
+ // particle information
+ int n; ///< number of particles
+ std::vector<Cmomentum> particles; ///< list of particles
+ std::vector<double> pt; ///< list of particles' pt
+ int n_left; ///< numer of particles that does not belong to any jet
+ std::vector<Cmomentum> p_remain; ///< list of particles remaining to deal with
+ std::vector<Cmomentum> p_uncol_hard; ///< list of particles remaining with collinear clustering
+ int n_pass; ///< index of the run
+
+ /// minimal difference in squared distance between a particle and
+ /// two overlapping protojets when doing a split (useful when
+ /// testing approx. collinear safety)
+ double most_ambiguous_split;
+
+ // jets information
+ std::vector<Cjet> jets; ///< list of jets
+
+ // working entries
+ int *indices; ///< maximal size array for indices works
+ int idx_size; ///< number of elements in indices1
+
+ /// The following flag indicates that identical protocones
+ /// are to be merged automatically each time around the split-merge
+ /// loop and before anything else happens.
+ ///
+ /// This flag is only effective if ALLOW_MERGE_IDENTICAL_PROTOCONES
+ /// is set in 'defines.h'
+ /// Note that this lead to infrared-unsafety so it is disabled
+ /// by default
+ bool merge_identical_protocones;
+
+ /// member used for detailed comparisons of pt's
+ Csplit_merge_ptcomparison ptcomparison;
+
+ /// stop split--merge when the SM_var of the hardest protojet
+ /// is below this cut-off.
+ /// This is not collinear-safe so you should not use this
+ /// variable unless you really know what you are doing
+ /// Note that the cut-off is set on the variable squared.
+ double SM_var2_hardest_cut_off;
+
+ /// pt cutoff for the particles to put in p_uncol_hard
+ /// this is meant to allow removing soft particles in the
+ /// stable-cone search.
+ double stable_cone_soft_pt2_cutoff;
+
+ private:
+ /**
+ * get the overlap between 2 jets
+ * \param j1 first jet
+ * \param j2 second jet
+ * \param v returned overlap^2 (determined by the choice of SM variable)
+ * \return true if overlapping, false if disjoint
+ */
+ bool get_overlap(const Cjet &j1, const Cjet &j2, double *v);
+
+
+ /**
+ * split the two given jets.
+ * during this procedure, the jets j1 & j2 are replaced
+ * by 2 new jets. Common particles are associted to the
+ * closest initial jet.
+ * \param it_j1 iterator of the first jet in 'candidates'
+ * \param it_j2 iterator of the second jet in 'candidates'
+ * \param j1 first jet (Cjet instance)
+ * \param j2 second jet (Cjet instance)
+ * \return true on success, false on error
+ */
+ bool split(cjet_iterator &it_j1, cjet_iterator &it_j2);
+
+ /**
+ * merge the two given jet.
+ * during this procedure, the jets j1 & j2 are replaced
+ * by 1 single jets containing both of them.
+ * \param it_j1 iterator of the first jet in 'candidates'
+ * \param it_j2 iterator of the second jet in 'candidates'
+ * \return true on success, false on error
+ */
+ bool merge(cjet_iterator &it_j1, cjet_iterator &it_j2);
+
+ /**
+ * Check whether or not a jet has to be inserted in the
+ * list of protojets. If it has, set its sm_variable and
+ * insert it to the list of protojets.
+ * \param jet jet to insert
+ */
+ bool insert(Cjet &jet);
+
+ /**
+ * given a 4-momentum and its associated pT, return the
+ * variable tht has to be used for SM
+ * \param v 4 momentum of the protojet
+ * \param pt_tilde pt_tilde of the protojet
+ */
+ double get_sm_var2(Cmomentum &v, double &pt_tilde);
+
+ // jet information
+ /// list of jet candidates
+ std::auto_ptr<std::multiset<Cjet,Csplit_merge_ptcomparison> > candidates;
+
+ /// minimal E
+ double E_min;
+
+ /**
+ * do we have or not to use the energy-weighted splitting
+ * (see description for set_E_weighted_splitting)
+ * This will be false by default
+ */
+ bool use_E_weighted_splitting;
+
+#ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
+ /// checkxor for the candidates (to avoid having twice the same contents)
+ std::set<Creference> cand_refs;
+#endif
+};
+
+}
+
+
+#endif
Property changes on: branches/spherical/siscone/spherical/split_merge.h
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+Date Rev
\ No newline at end of property
Index: branches/spherical/siscone/spherical/geom_2d.h
===================================================================
--- branches/spherical/siscone/spherical/geom_2d.h (revision 0)
+++ branches/spherical/siscone/spherical/geom_2d.h (revision 242)
@@ -0,0 +1,181 @@
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: geom_2d.h //
+// Description: header file for two-dimensional geometry tools //
+// This file is part of the SISCone project. //
+// WARNING: this is not the main SISCone trunk but //
+// an adaptation to spherical coordinates //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: $//
+// $Date:: $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __GEOM_2D_H__
+#define __GEOM_2D_H__
+
+#include <iostream>
+#include <math.h>
+#include "defines.h"
+
+#ifndef M_PI
+#define M_PI 3.141592653589793238462643383279502884197
+#endif
+
+namespace siscone{
+
+/// return a result that corresponds to phi, but in the
+/// range (-pi..pi]; the result is only correct if -3pi < phi <= 3pi
+inline double phi_in_range(double phi) {
+ if (phi <= -M_PI) phi += twopi;
+ else if (phi > M_PI) phi -= twopi;
+ return phi;
+}
+
+/// return the difference between the two phi values,
+/// placed in the correct range (-pi..pi], , assuming that phi1,phi2
+/// are already in the correct range.
+inline double dphi(double phi1, double phi2) {
+ return phi_in_range(phi1-phi2);
+}
+
+
+/// return the absolute difference between the two phi values,
+/// placed in the correct range, assuming that phi1,phi2 are already
+/// in the correct range.
+inline double abs_dphi(double phi1, double phi2) {
+ double delta = fabs(phi1-phi2);
+ return delta > M_PI ? twopi-delta : delta;
+}
+
+/// return the square of the argument
+inline double pow2(double x) {return x*x;}
+
+
+/**
+ * \class Ctwovect
+ * \brief class for holding a two-vector
+ */
+class Ctwovect {
+public:
+ /// default ctor
+ Ctwovect() : x(0.0), y(0.0) {}
+
+ /// ctor with initialisation
+ /// \param _x first coordinate
+ /// \param _y second coordinate
+ Ctwovect(double _x, double _y) : x(_x), y(_y) {}
+
+ /// vector coordinates
+ double x, y;
+
+ /// norm (modulud square) of the vector
+ inline double mod2() const {return pow2(x)+pow2(y);}
+
+ /// modulus of the vector
+ inline double modulus() const {return sqrt(mod2());}
+};
+
+
+/// dot product of two 2-vectors
+/// \param a first 2-vect
+/// \param b second 2-vect
+/// \return a.b is returned
+inline double dot_product(const Ctwovect & a, const Ctwovect & b) {
+ return a.x*b.x + a.y*b.y;
+}
+
+
+/// cross product of two 2-vectors
+/// \param a first 2-vect
+/// \param b second 2-vect
+/// \return a x b is returned
+inline double cross_product(const Ctwovect & a, const Ctwovect & b) {
+ return a.x*b.y - a.y*b.x;
+}
+
+
+/**
+ * \class Ceta_phi_range
+ * \brief class for holding a covering range in eta-phi
+ *
+ * This class deals with ranges in the eta-phi plane. It
+ * implements methods to test if two ranges overlap and
+ * to take the union of two overlapping intervals.
+ */
+class Ctheta_phi_range{
+public:
+ /// default ctor
+ Ctheta_phi_range();
+
+ /// ctor with initialisation
+ /// we initialise with a centre (in theta,phi) and a radius
+ /// \param c_theta theta coordinate of the centre
+ /// \param c_phi phi coordinate of the centre
+ /// \param R radius
+ Ctheta_phi_range(double c_theta, double c_phi, double R);
+
+ /// assignment of range
+ /// \param r range to assign to current one
+ Ctheta_phi_range& operator = (const Ctheta_phi_range &r);
+
+ /// add a particle to the range
+ /// \param theta theta coordinate of the particle
+ /// \param phi phi coordinate of the particle
+ /// \return 0 on success, 1 on error
+ int add_particle(const double theta, const double phi);
+
+ /// theta range as a binary coding of covered cells
+ unsigned int theta_range;
+
+ /// phi range as a binary coding of covered cells
+ unsigned int phi_range;
+
+ /// maximal value for theta
+ static double theta_min;
+ static double theta_max;
+
+private:
+ /// return the cell index corrsponding to an theta value
+ inline unsigned int get_theta_cell(double theta){
+ return (unsigned int) (1 << ((int) (32*((theta-theta_min)/(theta_max-theta_min)))));
+ }
+
+ /// return the cell index corrsponding to a phi value
+ inline unsigned int get_phi_cell(double phi){
+ return (unsigned int) (1 << ((int) (32*phi/twopi+16)%32));
+ }
+};
+
+/// test overlap
+/// \param r1 first range
+/// \param r2 second range
+/// \return true if overlap, false otherwise.
+bool is_range_overlap(const Ctheta_phi_range &r1, const Ctheta_phi_range &r2);
+
+/// compute union
+/// Note: we assume that the two intervals overlap
+/// \param r1 first range
+/// \param r2 second range
+/// \return union of the two ranges
+const Ctheta_phi_range range_union(const Ctheta_phi_range &r1, const Ctheta_phi_range &r2);
+
+}
+
+#endif
Property changes on: branches/spherical/siscone/spherical/geom_2d.h
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+Date Revision
\ No newline at end of property
Index: branches/spherical/siscone/spherical/defines.h
===================================================================
--- branches/spherical/siscone/spherical/defines.h (revision 0)
+++ branches/spherical/siscone/spherical/defines.h (revision 242)
@@ -0,0 +1,130 @@
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: defines.h //
+// Description: header file for generic parameters definitions //
+// This file is part of the SISCone project. //
+// WARNING: this is not the main SISCone trunk but //
+// an adaptation to spherical coordinates //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: $//
+// $Date:: $//
+///////////////////////////////////////////////////////////////////////////////
+
+//! \file defines.h
+#ifndef __DEFINES_H__
+#define __DEFINES_H__
+
+/// program name
+// we get "SISCone" by calling
+// siscone::siscone_package_name
+// defined in siscone.h
+// Otherwise, config.h
+// It is also defined as "PACKAGE_NAME" in config.h but this method
+// might lead to conflicts
+//#define PROGRAM PACKAGE_NAME
+
+// program version
+// we get it from
+// siscone::siscone_version
+// defined in siscone.h
+// It is also defined as "VERSION" in config.h but this method
+// might lead to conflicts
+
+/// perform final stability check using the quadtree
+/// With the following define enabled, the final check for stability
+/// is performed using the quadtree rather than the explicit list of
+/// particles (see Cstable_cone::proceed_with_stability())
+//#define USE_QUADTREE_FOR_STABILITY_TEST
+
+
+/// threshold for recomoutation of the cone (see Cstable_cones::update_cone())
+/// When traversing cone candidates along the angular ordering,
+/// the momentum of the protojet candidate is computed incrementally
+/// from the particles that enter and leave the cone.
+/// When the cumulative change in "|px|+|py|" exceeds the cone "|px|+|py|"
+/// we explicitely recompute the cone contents
+#define PT_TSHOLD 1000.0
+
+
+/// The following parameter controls collinear safety. For the set of
+/// particles used in the search of stable cones, we gather particles
+/// if their distance in eta and phi is smaller than EPSILON_COLLINEAR.
+///
+/// NB: for things to behave sensibly one requires
+/// 1e-15 << EPSILON_COCIRCULAR << EPSILON_COLLINEAR << 1
+///
+/// among the scales that appear in practice (e.g. in deciding to use
+/// special strategies), we have EPSILON_COLLINEAR, EPSILON_COCIRCULAR,
+/// sqrt(EPSILON_COCIRCULAR) and EPSILON_COLLINEAR / EPSILON_COCIRCULAR.
+///
+#define EPSILON_COLLINEAR 1e-8
+
+
+/// The following parameter controls cocircular situations.
+/// When consecutive particles in the ordered vicinity list are separated
+/// (in angle) by less that that limit, we consider that we face a situation
+/// of cocircularity.
+#define EPSILON_COCIRCULAR 1e-12
+
+
+/// The following define enables you to allow for identical protocones
+/// to be merged automatically after each split-merge step before
+/// anything else happens. Whether this happens depends on teh value
+/// of the merge_identical_protocones flag in Csplit_merge.
+///
+/// It we allow such a merging and define allow
+/// MERGE_IDENTICAL_PROTOCONES_DEFAULT_TRUE then the
+/// 'merge_identical_protocones' flag in Csplit_merge to be set to
+/// 'true'. It may be manually reset to false in which case the
+/// merging of identical protocones (protojets) will be turned off.
+///
+/// Note that this merging identical protocones makes the algorithm
+/// infrared-unsafe, so it should be disabled except for testing
+/// purposes.
+//#define ALLOW_MERGE_IDENTICAL_PROTOCONES
+//#define MERGE_IDENTICAL_PROTOCONES_DEFAULT_TRUE
+
+
+/// if EPSILON_SPLITMERGE is defined then, during the split-merge
+/// step, when two jets are found with PTs that are identical to
+/// within a relative difference of EPSILON_SPLITMERGE they are
+/// compared element-by-element to see where the differences are, and
+/// one then uses pt1^2-pt2^2 = (pt1-pt2).(pt1+pt2) as an estimator of
+/// which is harder. NB: in unfortunate cases, this can take the split
+/// merge step up to N n * ln N time, though on normal events there
+/// don't seem to have been any major problems yet.
+#define EPSILON_SPLITMERGE 1e-12
+
+/// definition of 2*M_PI which is useful a bit everyhere!
+const double twopi = 6.283185307179586476925286766559005768394;
+
+/// debugging information
+//#define DEBUG_STABLE_CONES ///< debug messages in stable cones search
+//#define DEBUG_SPLIT_MERGE ///< debug messages in split-merge
+//#define DEBUG ///< all debug messages !
+
+// in case all debug massages allowed, allow them in practice !
+#ifdef DEBUG
+#define DEBUG_STABLE_CONES
+#define DEBUG_SPLIT_MERGE
+#endif
+
+#endif // __DEFINES_H__
+
Property changes on: branches/spherical/siscone/spherical/defines.h
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+Date Rev
\ No newline at end of property
Index: branches/spherical/siscone/spherical/makefile.static
===================================================================
--- branches/spherical/siscone/spherical/makefile.static (revision 0)
+++ branches/spherical/siscone/spherical/makefile.static (revision 242)
@@ -0,0 +1,55 @@
+CC = g++
+LIBOUT = libsiscone.a
+CFLAGS = -Wall -g -O3 -ffast-math
+
+LDFLAGS = -lm #-lprofiler -lpthread -ltcmalloc
+ifeq ($(shell whoami),salam)
+ # needed for Gavin to include tcmalloc
+ LDFLAGS += -L/ada1/lpthe/salam/software/local/lib
+endif
+
+OBJS = ranlux.o reference.o geom_2d.o momentum.o hash.o quadtree.o \
+ vicinity.o protocones.o split_merge.o siscone.o siscone_error.o area.o
+
+SRCS = $(patsubst %.o,%.cpp,$(OBJS))
+
+
+%.o: %.cpp %.h
+ $(CC) -c $(CFLAGS) $<
+
+%.o: %.cpp
+ $(CC) -c $(CFLAGS) $<
+
+all: $(OBJS)
+ ar cru $(LIBOUT) $(OBJS)
+ ranlib $(LIBOUT)
+
+.PHONY: clean
+
+clean:
+ rm -f *.o *~
+
+
+# note the -Y option below avoids including all the standard
+# include directories (which change from one system to another)
+depend:
+ makedepend -- -Y -- $(SRCS)
+# DO NOT DELETE
+
+ranlux.o: ranlux.h
+reference.o: reference.h ranlux.h
+geom_2d.o: geom_2d.h defines.h
+momentum.o: momentum.h reference.h geom_2d.h defines.h
+hash.o: hash.h momentum.h reference.h geom_2d.h defines.h
+quadtree.o: quadtree.h momentum.h reference.h geom_2d.h defines.h
+vicinity.o: vicinity.h momentum.h reference.h geom_2d.h defines.h quadtree.h
+protocones.o: protocones.h momentum.h reference.h geom_2d.h defines.h
+protocones.o: vicinity.h quadtree.h hash.h siscone_error.h circulator.h
+split_merge.o: split_merge.h defines.h geom_2d.h momentum.h reference.h
+split_merge.o: siscone_error.h
+siscone.o: ranlux.h momentum.h reference.h geom_2d.h defines.h siscone.h
+siscone.o: protocones.h vicinity.h quadtree.h hash.h split_merge.h
+siscone.o: siscone_error.h
+siscone_error.o: siscone_error.h
+area.o: area.h momentum.h reference.h geom_2d.h defines.h siscone.h
+area.o: protocones.h vicinity.h quadtree.h hash.h split_merge.h
Index: branches/spherical/siscone/spherical/hash.cpp
===================================================================
--- branches/spherical/siscone/spherical/hash.cpp (revision 0)
+++ branches/spherical/siscone/spherical/hash.cpp (revision 242)
@@ -0,0 +1,207 @@
+///////////////////////////////////////////////////////////////////////////////
+// File: hash.cpp //
+// Description: source file for classes hash_element and hash_cones //
+// This file is part of the SISCone project. //
+// WARNING: this is not the main SISCone trunk but //
+// an adaptation to spherical coordinates //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: $//
+// $Date:: $//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <math.h>
+#include <stdio.h>
+#include "hash.h"
+#include <iostream>
+
+namespace siscone{
+
+using namespace std;
+
+/**************************************************************
+ * implementation of hash_cones *
+ * list of cones candidates. *
+ * We store in this class all the hash_elements and give *
+ * functions to manipulate them. *
+ **************************************************************/
+
+// constructor with initialisation
+// - _Np number of particles
+// - _R2 cone radius (squared)
+//-----------------------------------
+hash_cones::hash_cones(int _Np, double _R){
+ int i;
+
+ n_cones = 0;
+#ifdef DEBUG_STABLE_CONES
+ n_occupied_cells = 0;
+#endif
+
+ // determine hash size
+ // for a ymax=5 and R=0.7, we observed an occupancy around 1/8 N^2 ~ N2 R2/4
+ //mask = 1 << (int) (2*log(double(_Np))/log(2.0));
+ //if (mask<=1) mask=2;
+ int nbits = (int) (log(_Np*_R*_R*_Np/4.0)/log(2.0));
+ if (nbits<1) nbits=1;
+ mask = 1 << nbits;
+
+ // create hash
+ hash_array = new hash_element*[mask];
+ mask--;
+
+ // set the array to 0
+ //? needed ?
+ for (i=0;i<mask+1;i++)
+ hash_array[i] = NULL;
+
+ tan2R = tan(_R);
+ tan2R *= tan2R;
+}
+
+// destructor
+//------------
+hash_cones::~hash_cones(){
+ int i;
+ hash_element *elm;
+
+ for (i=0;i<mask+1;i++){
+ while (hash_array[i]!=NULL){
+ elm = hash_array[i];
+ hash_array[i] = hash_array[i]->next;
+ delete elm;
+ }
+ }
+
+ delete[] hash_array;
+}
+
+
+/*
+ * insert a new candidate into the hash.
+ * - v 4-momentum of the cone to add
+ * - parent parent particle defining the cone
+ * - child child particle defining the cone
+ * - p_io whether the parent has to belong to the cone or not
+ * - c_io whether the child has to belong to the cone or not
+ * return 0 on success, 1 on error
+ ***********************************************************************/
+int hash_cones::insert(Cmomentum *v, Cmomentum *parent, Cmomentum *child, bool p_io, bool c_io){
+ hash_element *elm;
+ int index = (v->ref.ref[0]) & mask;
+
+ // check the array cell corresponding to our reference
+ elm = hash_array[index];
+
+#ifdef DEBUG_STABLE_CONES
+ if (elm==NULL)
+ n_occupied_cells++;
+#endif
+
+ do{
+ // if it is not present, add it
+ if (elm==NULL){
+ // create element
+ elm = new hash_element;
+
+ // set its varibles
+ // Note: at this level, eta and phi have already been computed
+ // through Cmomentum::build_etaphi.
+ elm->centre = *v;
+
+ // if at least one of the two is_closer tests gives a result != from the expected,
+ // the || will be true hence !(...) false as wanted
+ elm->is_stable = !((is_closer(v, parent, tan2R)^p_io)||(is_closer(v, child, tan2R)^c_io));
+ //cout << "-- new status of " << v->ref[0] << ":" << elm->is_stable << endl;
+
+ // update hash
+ elm->next = hash_array[index];
+ hash_array[index] = elm;
+
+ n_cones++;
+ return 0;
+ }
+
+ // if the cone is already there, simply update stability status
+ if (v->ref == elm->centre.ref){
+ // there is only an update to perform to see if the cone is still stable
+ if (elm->is_stable){
+ elm->is_stable = !((is_closer(v, parent, tan2R)^p_io)||(is_closer(v, child, tan2R)^c_io));
+ //cout << " parent/child: "
+ // << parent->ref[0] << ":" << is_closer(v, parent) << ":" << p_io << " "
+ // << child->ref[0] << ":" << is_closer(v, child) << ":" << c_io << endl;
+ //cout << "-- rep status of " << v->ref[0] << ":" << elm->is_stable << endl;
+ //cout << v->eta << " " << v->phi << endl;
+ //cout << (child->eta) << " " << child->phi << endl;
+ }
+ return 0;
+ }
+
+ elm = elm->next;
+ } while (1);
+
+ return 1;
+}
+
+/*
+ * insert a new candidate into the hash.
+ * - v 4-momentum of te cone to add
+ * Note, in this case, we assume stability. We also assume
+ * that eta and phi are computed for v
+ * return 0 on success, 1 on error
+ ***********************************************************************/
+int hash_cones::insert(Cmomentum *v){
+ hash_element *elm;
+ int index = (v->ref.ref[0]) & mask;
+ //cout << "-- stable candidate: " << v->ref[0] << ":" << endl;
+
+ // check the array cell corresponding to our reference
+ elm = hash_array[index];
+ do{
+ // if it is not present, add it
+ if (elm==NULL){
+ // create element
+ elm = new hash_element;
+
+ // set its varibles
+ // Note: at this level, eta and phi have already been computed
+ // through Cmomentum::build_etaphi.
+ elm->centre = *v;
+ elm->is_stable = true;
+
+ // update hash
+ elm->next = hash_array[index];
+ hash_array[index] = elm;
+
+ n_cones++;
+ return 0;
+ }
+
+ // if the cone is already there, we have nothing to do
+ if (v->ref == elm->centre.ref){
+ return 0;
+ }
+
+ elm = elm->next;
+ } while (1);
+
+ return 1;
+}
+
+}
Property changes on: branches/spherical/siscone/spherical/hash.cpp
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+Date Rev
\ No newline at end of property
Index: branches/spherical/siscone/spherical/hash.h
===================================================================
--- branches/spherical/siscone/spherical/hash.h (revision 0)
+++ branches/spherical/siscone/spherical/hash.h (revision 242)
@@ -0,0 +1,115 @@
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: hash.h //
+// Description: header file for classes hash_element and hash_cones //
+// This file is part of the SISCone project. //
+// WARNING: this is not the main SISCone trunk but //
+// an adaptation to spherical coordinates //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: $//
+// $Date:: $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __HASH_H__
+#define __HASH_H__
+
+#include "momentum.h"
+#include "reference.h"
+
+namespace siscone{
+
+/**
+ * \class hash_element
+ * information on store cones candidates.
+ *
+ * We store in this class the information used to count all
+ * protocones in a first pass. This first pass only count
+ * cones with different references and test their stbility
+ * with the parent-child particles (border particles).
+ */
+class hash_element{
+ public:
+ C3vector centre; ///< reference
+ bool is_stable; ///< true if stable w.r.t. "border particles"
+
+ hash_element *next; ///< pointer to the next element
+};
+
+/**
+ * \class hash_cones
+ * list of cones candidates.
+ *
+ * We store in this class all the hash_elements and give
+ * functions to manipulate them.
+ */
+class hash_cones{
+ public:
+ /// constructor with initialisation
+ /// \param _Np number of particles
+ /// \param _R2 cone radius (squared)
+ hash_cones(int _Np, double _R2);
+
+ /// destructor
+ ~hash_cones();
+
+ /**
+ * insert a new candidate into the hash.
+ * \param v 4-momentum of te cone to add
+ * \param parent parent particle defining the cone
+ * \param child child particle defining the cone
+ * \param p_io whether the parent has to belong to the cone or not
+ * \param c_io whether the child has to belong to the cone or not
+ * \return 0 on success, 1 on error
+ */
+ int insert(Cmomentum *v, Cmomentum *parent, Cmomentum *child, bool p_io, bool c_io);
+
+ /**
+ * insert a new candidate into the hash.
+ * \param v 4-momentum of te cone to add
+ * Note, in this case, we assume stability. We also assume
+ * that eta and phi are computed for v
+ * \return 0 on success, 1 on error
+ */
+ int insert(Cmomentum *v);
+
+ /// the cone data itself
+ hash_element **hash_array;
+
+ /// number of elements
+ int n_cones;
+
+ /// number of occupied cells
+#ifdef DEBUG_STABLE_CONES
+ int n_occupied_cells;
+#endif
+
+ /// number of cells-1
+ int mask;
+
+ /// circle radius (squared)
+ /// NOTE: need to be set before any call to 'insert'
+ double R2;
+
+ /// its squreed tangent
+ double tan2R;
+};
+
+}
+#endif
Property changes on: branches/spherical/siscone/spherical/hash.h
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+Date Rev
\ No newline at end of property
Index: branches/spherical/siscone/spherical/Makefile.am
===================================================================
--- branches/spherical/siscone/spherical/Makefile.am (revision 0)
+++ branches/spherical/siscone/spherical/Makefile.am (revision 242)
@@ -0,0 +1,26 @@
+# build information for the SISCone library
+# this is built as a libtool lib.
+lib_LTLIBRARIES = libsiscone.la
+libsiscone_la_SOURCES = ranlux.cpp reference.cpp geom_2d.cpp\
+ momentum.cpp hash.cpp vicinity.cpp\
+ protocones.cpp split_merge.cpp siscone.cpp\
+ siscone_error.cpp
+
+EXTRA_DIST = makefile.static quadtree.cpp quadtree.h area.cpp
+
+# install the SISCone headers
+includedir = ${prefix}/include/siscone
+include_HEADERS = area.h\
+ circulator.h\
+ defines.h\
+ geom_2d.h\
+ hash.h\
+ momentum.h\
+ protocones.h\
+ ranlux.h\
+ reference.h\
+ siscone_error.h\
+ siscone.h\
+ split_merge.h\
+ vicinity.h\
+ config.h

File Metadata

Mime Type
text/x-diff
Expires
Wed, May 14, 11:11 AM (17 h, 53 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5111367
Default Alt Text
(385 KB)

Event Timeline