***The hopefully not-too-crippling dogma of GalSim development***, v0.1

1. Style: 

Use the LSST documents on C++, Python and Documentation overall as a guide for new code,
exert pragmatism with pre-existing code.  Unless you have good reason for hating LSST style,
or the style suggested here, in which case share it!

Biggish things to highlight/add/modify are...
 4 space indentation, rather than 2 space.

 No tabs.  Just spaces.

 No using statements.  Now all namespaces (especially std::) are explicit (equvalent will be
 adopted in Python, i.e. no "import * from moduleX" or "from moduleY import Z").

 Use C++ std library when possible.  e.g. MAX -> std::max, Assert -> assert, PI -> M_PI, etc.

 Will be readable at 100 character width (this is a departure from LSST style, which specifies
 120 but is slightly annoying for laptop use).

 Python 2.7.x will be supported, not Python 3.x...

 We adhere to the Zen of Python; open python, type "import this", hit enter.

 We use all lowercase letters for all Python packages.  That's a bit of a Python convention, 
 and while it's mostly aimed at compatibility with case-insensitive filesystems, we think we 
 should stick with it anyway.

 We will adopt the SBProfile capitalization style wherever sensible for code filenames, as it's by 
 far the most significant chunk of C/C++ we are currently using.  This makes include/*.h files
 capitalized.  

 Overall capitalization rules:
 * File names are CamelCase**
 * Classes (and structs) are CamelCase
 * Free functions are CamelCase
 * Member functions are camelCase
 * Public variables (including function parameters and kwargs) are lower_case
 * Private variables are _lower_case
 * Local scope variables/functions can be whatever the author prefers.
 ** Note that when using camelCase or CamelCase, acronyms should still be capitalized, i.e. CCD and
 PSF, not Ccd and Psf.

 Python unit testing modules will be placed in tests/, and called test_<Module>.py

 For executables that perform tests (e.g. in non-Python code units) these will be called 
 test_<function>* to match the naming conventions of Python test modules.


For vim users, Mike Jarvis has put the c.vim file in the devutils/ directory.  If you put that 
in  .vim/ftplugin/ and add the line "filetype plugin on" in your .vimrc file, then you will 
automatically get the formatting to match what is currently in SBProfile.  We don't (yet) 
have a corresponding file for emacs.  (Sorry.)

LSST Style Guides available here --
http://dev.lsstcorp.org/trac/wiki/DocumentationStandards
http://dev.lsstcorp.org/trac/wiki/PythonCodeStandards
http://dev.lsstcorp.org/trac/wiki/C%2B%2BStandard

Broad reasons for choice of LSST style: These documents just seem to be a fairly sensible 
source of code and  documentation formatting guidance, although note that we have diverged in some
places.  See also Peter Melchior's slides for sound advice in general, and on documentation:
dl.dropbox.com/u/26820102/talks/software_engineering_150410.pdf


2. Version control: 
Git

Broad reasons why: Modern/distributed. Slightly better general purpose/branching capabilities 
than Hg, albeit at the cost of a mildly steeper learning curve.  Neither is rocket science!


3. Repository hosting: 
Github, with push/pull access to all those in the GalSim-developers organization (based on
the great3-code@princeton.edu mailing list).

Broad reasons why: Code review features, wiki features, popularity within GalSim-developers, 
project forking.


4. Documentation: DOxygen
Broad reasons why: Well-supported by many in GalSim-developers.


5. Builds: SCons
Broad reasons why: Seemingly greater experience among GalSim-developers.

One of the SCons defaults is WARN=false.  This is recommended for end users, so we don't 
saddle them with a bunch of warning messages if they use a new compiler that we haven't
tested on yet.  However, developers should always run with WARN=true to help catch
bugs.  Even if you know the warning is benign, please fix it.  We want all compilations 
to be warning-free on as many compilers as possible.  

Note: because SCons automatically caches all parameters you pass it, you will only need
to do `scons WARN=true` once, and then it will be set that way for all future scons 
commands.


6. Libraries: 
FFTW, Numpy, Pyfits, TMV (+BLAS & LAPACK if tuned versions present), Boost.python, 
Boost.shared_ptr, Boost.random (flexibility to other RNGs)

Notes: will add more if really useful/necessary, but want to keep this list as short as 
possible.  Matplotlib plotting  in Python not featured by default.


7. Array/pixel indexing:

Numpy arrays in Python use the (matrix-style) indexing [y, x], whereas the SBProfile class and the
more arguably natural ordering is (x, y).  PyFITS, and a number of other Numpy-dependent Python
libraries have also adopted the [y, x] paradigm, as well as a number of astronomers who do a lot in
Python.

We will write our Python classes to accept arguments in the (x, y) order, particularly the
galsim.Image class.  However, it will be possible to create an Image using a Numpy array, and also
to get a Numpy view into an image.

This places the boundary between our classes and NumPy.  Our classes would be (x,y) in both C++ and
Python, but we wouldn't make any effort to fit NumPy into that paradigm.

Jim gives a couple more reasons on why this is a good place to put the boundary:
- Square brackets will consistently be [y,x], and parentheses will consistently be (x,y), due to 
  the (usually annoying) fact that you can't overload operator[] with two argument in C++.

- Even in Python, [y,x] is really only used for NumPy arrays - note that matplotlib's plot 
  function takes 1-d x and y arrays in that order, for instance, even though matplotlib expects 
  arrays used as images to be [y,x].

Jim gives a nice example of this functionality for what he has in mind for the Python API of the
galsim.Image class:

>>> import galsim
>>> import numpy
>>> arr1 = numpy.arange(6).reshape(2,3)
>>> print arr1
[[0 1 2]
[3 4 5]]
>>> im1 = galsim.ImageD(arr1, x0=10, y0=100)  # im shares data with arr1
>>> arr2 = im1.array
>>> assert(arr2 is arr1)
>>> print im1(12, 101) # (x, y); includes offsets passed in constructor
5
>>> im2 = galsim.ImageD(x0=1, y0=2, w=3, h=4)
>>> arr3 = im2.array   # arr3 shares data with m3
>>> print arr3.shape   # shape is (h, w)
(4, 3)
>>> arr4 = arr1.transpose()    # arr4 is column-major
>>> im3 = galsim.ImageD(arr4)  # can't do this
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
ValueError: Cannot create image from noncontiguous array.

This last point is important: Numpy arrays must be kept in c_contiguous storage order, i.e. row-
major.  Some of numpy's array routines invisibly change arrays to Fortran-style (i.e. column-major)
storage, or disrupt contiguous storage altogether.  While developing, keep track of this using

>>> array.flags

in particular ensure that

>>> array.flags.c_contiguous == True

Check out the np.copy() function in Numpy, or array.copy() method to see how to make a c_contiguous
array, also see np.ascontiguousarray() or the array.transpose() method.

Finally, the FITS standard is to begin indexing all arrays at (1, 1), and this is the convention
SBProfile currently adopts.  However, we think that our image objects will also carry around an
attribute for the coordinate origin, so this should not be too much of a headache at the interface 
with Python/Numpy (famous last words).


8. Compiler warning flags

By default, SCons adds the flags -Wall -Werror to the list of compiler flags.  This tends to 
catch a lot of things that cause portability issues as we use the code on different systems
as well as outright bugs in the coding that are otherwise missed.  Not all of the things 
that come up are bugs per se, but it catches enough things that really are bugs that we feel 
it worthwhile to make that the default.  Developers are expected to fix their code to get rid 
of all these warnings before committing.

Even if everyone does this, it is possible that you might come across warnings from someone
else's code.  e.g. They may use a different compiler that warns about somewhat different things.
If you know how to fix the problem, go ahead and do so.  If you don't, please email the 
person responsible (or go to our GitHub page and comment on the commit that causes the problem) 
to ask them to fix it.  Basically the same thing you would do if code failed to compile for a 
non-warning compiler error.

When we eventually release the code to the public, we will switch the default to not use
these warning flags in case some users have a different compiler that none of us tested on.
The code is regularly tested with various versions of g++, clang++ and icpc.  Maybe more.
But if they use something different, we don't want the code to fail because it is a stickler
for some C++ detail that we didn't catch in our builds.  Turning on and off the warnings is 
done with the SCons option WARN.  Use WARN=false to turn them off, and WARN=true to turn them 
back on.  But again, you shouldn't really have to do this.  You should fix the warnings rather 
than ignore them by turning them off.


9. Random number generators (RNG)

First, we realize that it's unlikely that *any* library RNG would come with a guarantee that a 
given seed will produce the same sequence in all past and future versions (unless it's software 
that is never revised, like NR!).  So if we want to GalSim to have this property (we do), then we 
need to package some fixed version of something with GalSim.

Gary has created a subdirectory GalSim/include/galsim/boost1_48_0.random which contains the needed 
files (and subdirectory) from Boost.Random.  If the compiler flag DIVERT_BOOST_RANDOM is defined, 
then all of the include directives for Random.h are directed to this directory instead of to 
boost/random.  And I hacked all these Boost files so that their includes for any element of 
Boost.Random are also sent to galsim/boost1_48_0.random.  Hence a compilation will not reach the 
local boost/random and there will be no name collisions... 

***as long as no module that includes our Random.h also explicitly includes the normal boost/random
files.***

In other words we need to have a rule that any use of RNG's accesses them ONLY via our Random.h 
wrappers.  This would be good practice in any case.

Some of the hacked Boost.Random files refer to other parts of Boost.  I have *not* diverted these to
private copies - they will come from the user's distribution so there will be no name or code 
collisions if anyone uses other parts of Boost.  I've confirmed that the Boost.Random 1.48.0 
routines work when the 1.46 versions of the other Boost libraries are included (that's the one that
fink likes).

At the Python level, we want to be using this same RNG.  This means we'll need to make a Python
wrapper for the C++ Random class, and use it, which means we need to avoid the temptation to use 
numpy.random.  Work on this wrapper will begin ASAP (we'll probably want to put some effort into 
making the wrappers for the C++ RNG class very NumPy-friendly anyway).

There remains the risk that future Boost releases will break our "frozen" Boost.Random.  We'll need
to record that possibility for posterity.

