***** Metadata hookup *****

Current status:
Rt_study_metadata constructor hooks up internally created metadata
Segmentation allows external hookup of parent in constructor.  

DCMTK loading puts items into Rt_study_metadata.  It puts the info 
directly into the right section.  Ditto for GDCM1.

Synthetic_mha creates images and inserts images into an Rt_study.

XiO loader (Rt_study::load_xio) inserts items directly into Rt_study_metadata.

Metadata within Plm_image is never actually used.
You must have an Rt_study to have metadata.
The Rt_study_metadata is passed into Plm_image::save()


***** Metadata ownership *****

Current ownership organization

Rt_study -> Rt_study_metadata
Rt_study_metadata -> shared metadata
Rt_study_metadata -> image metadata
Rt_study_metadata -> dose metadata
Rt_study_metadata -> rtss metadata

Plm_image -> image metadata
Plm_image -> dose metadata
Segmentation -> rtss metadata

image metadata -> shared metadata
rtss metadata -> shared metadata
dose metadata -> shared metadata

***** Bspline methods *****

Method mi-i
Tile loop to create histogram (hist_add omp_v2)
Condense loop to create gradient

Method mi-h 
Serial loop to create histogram
Condense loop to create gradient

Method mi-g == method mi-h

Method mi-f
Tile loop to create histogram (hist_add omp_crit)
Condense loop to create gradient

Method mi-e
Tile loop to create histogram (hist_add omp_v1)
Condense loop to create gradient

Method d == method h

Method mi-c
Serial loop to create histogram
Serial loop to create gradient

Method mse-i
Parallel tile

Method mse-h
Serial tile

Method mse-g == mse-i

Method mse-c
Serial voxel

Method k
Serial loop

Method l
Serial tile loop, condense with sets


***** Overlap fraction *****

The overlap fraction should (?) be tied to score at initial iteration.
This requires stashing the initial score somewhere.  But this needs to 
be done in a general way for various optimizers.

Furthermore, the "best score" concept is probably not implemented for 
the non-Nocedal optimizers.

This is a TODO.

***** Programmability redux *****

Option 1) Internal programmability, with lua
Effort: medium
Pro: Convenient
Con: Lua not popular

Option 2) Internal programmability, with internal language
Effort: medium-high
Pro: Convenient for existing users, not so difficult to implement
Con: Custom languages are lame

Option 3) External wrapping, a la VTK
Effort: medium
Pro: Python popular
Con: 

Option 4) External wrapping with Swig
Effort: medium
Pro: Python popular, other languages supported
Con: 

***** Restartable registration (second try) *****

After a lot of effort, I learned that you can't simply code up 
something like suggested on the ITK web site to create a semaphore
from a condition variable [1].  Doing so does not work, because the 
condition variable does not guarantee that the signalee gets the 
resource before the signaller can re-grab.  N.b. that the DLIB 
implementation has the same problem.

Therefore instead, let's try a producer-consumer style solution, 
with two locks.

master_grab:
  mutex.lock
    slave_waits = true
    master_waits = true
    while master_waits == true
      master_sema.wait       // wait for slave to finish
  mutex.unlock

master_release:
  mutex.lock
    slave_waits = false
    slave_sema.signal      // wake up slave
  mutex.unlock

slave_grab:
  mutex.lock
    while slave_waits == true
      slave_sema.wait      // slave waits to get woken up
  mutex.unlock

slave_release:
  mutex.lock
    master_waits = false;
    master_sema.wait      // slave waits to get woken up
  mutex.unlock

http://itk.org/migrationv4/index.php?action=artikel&cat=3&id=108&artlang=en

***** Restartable registration *****

Here is how it looks using ITK methodology

reg_func:
  halt_sem.Down();
  // do registration
  halt_sem.Up ();

start_registration:
  halt_sem.Initialize (1);
  id = spawn thread(reg_func);
  return;

halt_registration:
  halt_sem.Down();
  return;

wait_for_complete:
  threader.TerminateThread (id)


***** ITK and plastimatch direction cosines *****

There are two ways to have a rotated volume.  The direction cosines 
of the volume might be inherently rotated, or there might be a rigid 
transform associated with it.

ITK direction cosines are stored in the columns of the array.
In other words, if the (DICOM) orientations are A, B, and C 
for the i (fastest), j, and k (slowest) indices, then ITK stores 
them like this:

  itk_dc[0][0] = A[0];
  itk_dc[0][1] = B[0];
  itk_dc[0][2] = C[0];
  itk_dc[1][0] = A[1];
  itk_dc[1][1] = B[1];
  itk_dc[1][2] = C[1];
  itk_dc[2][0] = A[2];
  itk_dc[2][1] = B[2];
  itk_dc[2][2] = C[2];

The plastimatch direction cosines are stored in a one-dimensional
array, also by columns.  

  dc[0] = A[0];
  dc[1] = B[0];
  dc[2] = C[0];
  dc[3] = A[1];
  dc[4] = B[1];
  dc[5] = C[1];
  dc[6] = A[2];
  dc[7] = B[2];
  dc[8] = C[2];

These are then converted into the "step" and "proj" matrices.

  step[0] = spacing[0] * dc[0];
  step[1] = spacing[1] * dc[1];
  step[2] = spacing[2] * dc[2];
  step[3] = spacing[0] * dc[3];
  ...
  step[8] = spacing[2] * dc[8];


***** How to delete items from conquest *****

./dgate --deletepatient:patid

Note: supports wildcards, such as:

./dgate --deletepatient:0522*

***** Subsampling framework *****

legacy vox subsampling      Voxel binning, new voxel center at bin center
new vox subsampling         Convert into standard resampling, allow fraction
mm resampling               Choose by mm
pct resample                Choose by pct of original voxels
dim resample                Choose by number of voxels

res,res_vox,ss
res_mm
res_pct
res_dim

***** When is itk vs native resample used? *****

native:
xform.cxx                       resample gpuit vfs
demons,bspline,transl           registration subsampling

itk:
everywhere else


***** How to detect a "Null" smart pointer *****

Just like a regular pointer.

Plm_image::Pointer p;
if (p) {
   /* Will not be executed because p is null */
}

You can return a null pointer like this:

if (error) {
  return Plm_image::Pointer();
}

***** Plastimatch 2.0 *****

Proposal #1, extend existing language.  The below is an example,
but many improvements could be made.

[GLOBAL]
fixed[0]=image_1a.mha           // support for multi-planar registration
fixed[1]=image_1b.mha
moving[0]=image_2a.mha
moving[1]=image_2b.mha
$aux=image_1a_mask.mha          // load image into a variable
img_out[0]=warped_1a.mha

[FILTER]
action=dmap                     // could be lua script here...
input_1=$fixed[0]               // set input from variable
input_2=$aux                    // set input from variable
input_3=image_1c.mha            // load image into a variable
$f1=$fixed[0]                   // save a copy of the old fixed[0]
fixed[0]=$output                // overwrite fixed[0] with filter output

[STAGE]
xform=translation
optim=rsg
max_its=30
res=4 4 2

[RESUME_STAGE]                  // continue existing stage (yuck)
max_its=50

[STAGE]
fixed[0]=$f1                    // replace fixed image for this stage
xform=bspline

Proposal #2, extend lua scripting.  Something like this:

-- Global (inputs)
r = Registration()
r:fixed[0] = Image.load("image_1a.mha")
r:fixed[1] = Image.load("image_1b.mha")
r:moving[0] = Image.load("image_2a.mha")
r:moving[1] = Image.load("image_2b.mha")
aux = Image.load("image_1a_mask.mha")

-- Filter
f1 = fixed[0]
r:fixed[0] = Dmap:get_output (r:fixed[0], aux, Image.load("Image_1c.mha"))

-- Stage
s = r:Stage ()
s:xform = 'translation'
s:optim = 'rsg'
s:max_its = 30
s:res = '4 4 2'
s:run()

-- Stage (continuation)
s:max_its = 30
s:run()

-- Stage
s = r:Stage(s)
s:fixed[0] = f1
s:xform = 'bspline'
s:run()

-- Global (outputs)
r:get_output():save("warped_1a.mha")


***** What to do about const smart pointers *****

(Your answer here)


***** A trick for forward declaration of nested classes *****

http://stackoverflow.com/questions/2600385/c-nested-class-forward-declaration-issue

(Not the first answer that was accepted though.  The second one 
is the one you want.)


***** Rt_study API example *****

/* Example #1, simple save using images */
itk::Image<short,3>::Pointer itk_image;
itk::Image<float,3>::Pointer itk_dose;
itk::Image<unsigned char,3>::Pointer itk_structure_1;
itk::Image<unsigned char,3>::Pointer itk_structure_2;

Rt_study rt_study;
rt_study.set_image (itk_image);
rt_study.set_dose (itk_dose);
rt_study.add_structure (itk_structure_1, "Body", "255\\0\\0");
rt_study.add_structure (itk_structure_2, "Tumor", "0\\255\\0");
rt_study.save ("output_directory");


/* Example #2, save structure set that references existing CT image */
Rt_study rt_study;
rt_study.add_structure (itk_structure_1, "Body", "255\\0\\0");
rt_study.add_structure (itk_structure_2, "Tumor", "0\\255\\0");

const char *study_uid, *ct_series_uid, *for_uid;
Rt_study_metadata::Pointer = rt_study.get_study_metadata();
rt_study_metadata.set_study_uid (study_uid);
rt_study_metadata.set_ct_series_uid (ct_series_uid);
rt_study_metadata.set_frame_of_reference_uid (for_uid);
rt_study_metadata.set_study_metadata (0x0010, 0x0010, "PATIENT^NAME");
rt_study_metadata.set_study_metadata (0x0010, 0x0020, "PATIENT^ID");

itk::Image<short,3>::Pointer itk_image;
rt_study_metadata.set_image_header (itk_reference_image);
for (int slice = 0; slice < num_slices; slice++) {
    rt_study_metadata.set_slice_uid (slice, uid_string[slice]);
}

rt_study.save ("output_directory");


***** Which metadata goes where? *****

PatientPosition ?
StudyID ?

***** Slice list, slice index *****

Slice_list
    bool m_loaded;
    Plm_image_header m_pih;
    std::vector<Pstring> m_ct_slice_uids;

Slice_index
    bool m_loaded;
    Plm_image_header m_pih;
    Metadata m_demographics;
    Pstring m_study_id;
    Pstring m_ct_study_uid;
    Pstring m_ct_series_uid;
    Pstring m_ct_fref_uid;
    std::vector<Pstring> m_ct_slice_uids;

Dicom_rt_study --> Rename to Rt_study_metadata
    bool m_loaded;
    Plm_image_header m_pih;

    std::string date_string;
    std::string time_string;
    std::string ct_series_uid;
    std::string dose_instance_uid;
    std::string dose_series_uid;
    std::string for_uid;
    std::string rtss_instance_uid;
    std::string rtss_series_uid;
    std::string study_uid;
    Slice_list slice_list;

    Metadata study_metadata;
    Metadata image_metadata;
    Metadata rtss_metadata;
    Metadata dose_metadata;

-- References

Slice_index
    cxt_io
        UIDs are loaded and saved
    dcmtk_rdd
    dicom_util
    gdcm1_dose
    gdcm1_rdd
    gdcm1_rtss
        UIDs, image header, demographics are loaded
    itk_dicom_save
    itk_image_save (cxx only)
    plm_image
    rtss
    xio_ct (h only)
    xio_ct_transform
    rt_study
    segmentation

Slice_list
    dicom_rt_study
    rtss


***** Rtss, rtss_structure_set, ... *****

These names are lousy.  Let's get some new names.

DICOM officially refers to the set of all structures 
as a "RT Structure Set".  The image associated with the structures 
is called a "Contour Image Sequence".  A single structure is 
called an "ROI".  A single polyline is called an "ROI Contour".

Proposed names (polyline types)

  - Rtss_contour          replaces Rtss_polyline
  - Rtss_roi              replaces Rtss_structure
  - Rtss                  replaces Rtss_structure_set

Proposed names (image & polymorphic types)

  - Segmentation          replaces Rtss
  - Segmentation_image    replaces Ss_img


***** Smart pointers part 3 *****

Things to fix

- Plm_image::steal_volume () should be removed
- Rtds::load_dcmtk (const char *dicom_path) - need to be fixed


***** Smart pointers redux *****

Prefer to have "internal" smart pointers

Dlib has 3 kinds

#include "smart_pointers/scoped_ptr.h"
#include "smart_pointers/shared_ptr.h"
#include "smart_pointers/weak_ptr.h"

- shared_ptr is a standard smart pointer
- weak_ptr is a shared_ptr that can go away; you make a special call to 
  see if it's still there
- scoped_ptr doesn't have reference counting

***** DICOM re-org 2013-03-24 *****

Future plan:

Dicom_rt_study
  -> Various metadata
  -> Dcmtk_rt_study
    -> Backpointer to Dicom_rt_study
    -> More metadata
    -> Dcmtk_series (dose) // currently in dcmtk_loader
    -> Dcmtk_series (rtss) // currently in dcmtk_loader
    -> Dcmtk_series (img)  //??
  -> cxt    // currently in dcmtk_loader
  -> dose   // currently in dcmtk_loader
  -> img    // currently in dcmtk_loader

***** MABS re-org *****

Prep/training steps:
(1) convert file format
(2) do registrations, compute dice, possibly optimize registration
(3) warp structures and get distance maps
(4) optimize voting parameters (rho, sigma, thresh)

Workflow -- optimizing registrations
------------------------------------
convert file format
for each image pair
  for each registration parameter
    register
    warp structures
    compute distance maps
    compute dice
    tabulate results
  choose best registration parameter

Workflow -- optimizing voting parameters
----------------------------------------
convert file format
for each image pair
  register
  warp structures
  compute distance maps
for each structure
  for each voting parameter
    for each image pair
      load dmap
      vote
    save weights
    for each thresh
      threshold image
      compute dice
      save results

Workflow -- standard usage
--------------------------
for each image pair
  register
  warp structures
  for each structure
    compute distance maps
    vote
    threshold image
  

Other thoughts:
(1) Make dmap, dice faster

***** Geometry chooser *****

Two use cases.

Use case one:
- Manual overrides
- Fixed image
- Input image

Use case two:
- Manual overrides
- Fixed image
- Reference image
- Compare image

***** DICOM re-org *****

Need patient, study, series hierarchy.

------ Plm_patient
  ---- Plm_study
    -- Plm_series

This should be allowed to be created via dicom.  It might therefore 
be required to move rtss/rtds code into base.  These files would move:

Idea (1).  Plm_series has a "type" field, which tells us if the 
item is an image, rtss, etc.

Idea (2).  Plm_series is a base type, subclassed by image, rtss, etc.

***** Viscous *****

It seems that only certain versions of thrust work with certain versions 
of cuda.

Thrust 1.6.0 does not work with CUDA 3.0
Thrust 1.4.0 does work with CUDA 3.0

***** Metadata Mark II *****

Do we need separate metadata items for image, dose, and rtstruct?
Not sure.  Here are the considerations:

- ITK dicom write (image) requires setting metadata into itk image
- CXT, xio formats need somewhere to store the metadata
- RDD has its own metadata

Where does RTSS metadata get used (version 1.5.9)

- cxt_io.cxx
  - name, id, sex (rtss meta)
  - study id, ct study id, ct series id, ct for id (rdd)
- gdcm1_rtss.cxx
  - name, id, sex, series description
  - study id, ct study id, ct series id, ct for, ct slice ids (rdd)

Where RDD metadata get used (version 1.5.9)

- rtds.cxx
  - name, id, sex, patient position
  - (xio ct transform -- this should be part of metadata??)
- gdcm1_rdd.cxx
  - name, id, sex, patient position

Options: 

(a) All in rtds.
    PRO: simple, heterogenous data structure makes sense
    CON: registration code (and other code which doesn't use rtds) 
    	 still needs somewhere to store metadata
(b) Separate metadata for each item
    PRO: more similar to dicom, works well with registration code
    CON: difficult to synchronize

Final choice:

- Separate metadata for image, struct, dose
- Special structure for ct uids, etc.  These go in rtds instead of image
  (as they are now), because we might have a referenced dicom dir, without 
  an actual image.

***** Debian notes *****

In order to install ITK 3.20, you need to use unstable repository.
Here is what you need:

  sudo apt-get -V install -t unstable \
    libgdcm2-dev libinsighttoolkit3-dev libvtk5-dev

It seems that Debian ITK was built with GDCM 2.X instead of GDCM 1.X.
Too bad.

***** Organization of learning code *****

Use cases:

image: can be 2d (slice) or 3d (vol)
pos: can be 1d (slice loc), 2d (in-plane), or 3d (position)
binary (in/out, male/female)
tri-state (above, near, below)
continuous tri-state (above (+1), near (-1 to +1), below (-1))
conditional position (inside (with position), outside (without position))

- T-spine

slice -> slice loc
slice -> in-plane

- Lung apex

slice -> continuous tri-state

- T-spine

slice + continuous tri-state -> slice loc

Finding training data:

T-spine: Choose only slice or vol centered at fiducial
T-spine: Interpolate fiducials, use all slices
Lung apex: Choose only slice at apex
Lung apex: Choose all slices, compute distance to apex
Lung volume: Choose all slices intersecting mask

Transition plan:

Use hard-coded training routines for different use cases

plastimatch autolabel-train \
    --task t-spine-v1 \
    --input dir \
    --output net

The data needs a hierarchy, to allow for cross-validation on a 
patient-by-patient basis.  Call the data for a single patient 
an Autolabel_data_item

Autolabel_data_item {
  dlib::matrix inputs;
  dlib::matrix outputs;
}

Autolabel_data {
  std::list<Autolabel_data_item>
  choose_subset ()
}

Autolabel_trainer {
  Autolabel_data ad;
  train (parameter_range) {
    for (num_trials) {
      dlib::matrix training_data = ad.choose_subset();
    }
  }
}


***** Organization for irregular volume (transition plan) *****

(1) Use native, not ITK

(2) Only support volumes with irregular slice spacing.  No support 
for things like changing pixel size or direction cosines

(3) Add irregular volume as a member of Volume

class Volume {
      /* Regular volume stuff */
      int npix;
      void *data;

      /* Irregular volume stuff */
      float *irr_spacing;
      void **irr_data;
};

***** Writing a Slicer4 loadable module *****

(1) Use the wizard to make a template

export SD=$HOME/build/slicer-4/Slicer4
python ${SD}/Scripts/ModuleWizard.py \
       --template ${SD}/QTModules/ModuleTemplate \
       --target MY_MODULE_NAME \
       MY_MODULE_NAME

(2) Modify CMakeLists.txt

find_package (Slicer QUIET)
if (SLICER_FOUND)
  include ("${Slicer_USE_FILE}")
  if (SLICER_IS_SLICER4)
    add_subdirectory (QTModules/MY_MODULE_NAME)
  endif ()
endif ()

(3) Copy over TestingMacros.h

cp ${SD}/TestingMacros.h MY_MODULE_NAME

At this point you can compile, and it runs.  But it builds directly 
into the slicer directory.  This can be (partly) defeated using 
the following strategy, but it is a moot point because you can't yet 
set the module search path.  Here is the strategy:

(4) Defeat Slicer overwriting CMAKE_* variables

  if (Slicer_USE_FILE)
    set (OLD_CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
    set (OLD_CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
    set (OLD_CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY})

    include ("${Slicer_USE_FILE}")

    set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${OLD_CMAKE_RUNTIME_OUTPUT_DIRECTORY})
    set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${OLD_CMAKE_LIBRARY_OUTPUT_DIRECTORY})
    set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${OLD_CMAKE_ARCHIVE_OUTPUT_DIRECTORY})
  endif ()

(5) Edit CMakeLists.txt files generated by the python script.  
There are two files to edit: MY_MODULE_NAME/CMakeLists.txt, 
and MY_MODULE_NAME/Logic/CMakeLists.txt.

(5a) For MY_MODULE_NAME/CMakeLists.txt, do the following:

set (lib_name qSlicer${qt_module_name}Module)
set_target_properties (${lib_name} PROPERTIES
  RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${Slicer_INSTALL_QTLOADABLEMODULES_BIN_DIR}"
  LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${Slicer_INSTALL_QTLOADABLEMODULES_LIB_DIR}"
  ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${Slicer_INSTALL_QTLOADABLEMODULES_LIB_DIR}"
  )

(5b) For MY_MODULE_NAME/Logic/CMakeLists.txt, do the following:

SlicerMacroBuildModuleLogic(
  NAME ${module_logic_name}
  DISABLE_WRAP_PYTHON
  EXPORT_DIRECTIVE ${module_logic_export_directive}
  INCLUDE_DIRECTORIES ${module_logic_include_directories}
  SRCS ${module_logic_SRCS}
  TARGET_LIBRARIES ${module_logic_target_libraries}
  )

set_target_properties (${module_logic_name} PROPERTIES
  RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${Slicer_INSTALL_QTLOADABLEMODULES_BIN_DIR}"
  LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${Slicer_INSTALL_QTLOADABLEMODULES_LIB_DIR}"
  ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${Slicer_INSTALL_QTLOADABLEMODULES_LIB_DIR}"
  )

***** Proton dose ideas *****

Stage 1(a): Compute pencil beam in standard grid
(z direction is pdd in water)
(x-y direction is scatter in water, or just 1-d with distance)

Stage 1(b): Compute RPL in interpolated coordinate system
(z axis is beam axis)
(x-y perpendicular to beam, arbitrary v-up vector)

Stage 2: For each voxel
  a) Look up primary in RPL grid
  b) Convolve to find scatter within x-y axis of primary grid (ignoring tilt)

***** File browser design *****

http://www.xvsxp.com/files/file_browsing.php
http://rixstep.com/4/0/xfile/ss.shtml
http://www.ragesw.com/products/explorer/screenshots/1/

***** Writing to stdout in Qt *****

    QTextStream(stdout) << QString("foo") << "\n";

***** dgate quite ref (for wormwood) *****

cd ~/build/conquest-1.4.15
./dgate &

***** dcmtk quick ref *****

Run the dicom server like this:

  $ dcmqrscp

It will read a file "dcmqrscp.cfg" in the current directory, which is used 
to set user/group, port, AET, storage directory.  NOTE: Be very careful 
about extra spaces in the list of remote AETs.  Here the file I used 
for these tests:

--- begin here ---
NetworkType     = "tcp"
NetworkTCPPort  = 9885
MaxPDUSize      = 16384
MaxAssociations = 16
Display         = "no"
UserName        = "gsharp"
GroupName       = "gsharp"
HostTable BEGIN
entry1           = (MOVESCU, localhost, 19530)
entry2           = (STORESCP, localhost, 19335)
HostTable END
VendorTable BEGIN
VendorTable END
AETable BEGIN
READWRITE     /home/gsharp/projects/dicom-test/junk RW (10, 1024mb)  ANY
AETable END
--- end here ---

Send files to database like this:

  $ storescu -aec READWRITE localhost 9885 *.dcm

Query the database like this:

  $ findscu -P -k 0010,0010 -k 0008,0052=PATIENT -aec READWRITE localhost 9885

Retrieve from the database like this:

  $ movescu -v --patient -aet MOVESCU -aem MOVESCU -aec READWRITE --port 19530 -k 0008,0052=PATIENT -k 0010,0020=PL811332912032439 localhost 9885

Or like this:

  $ storescp 19335 &
  $ movescu -v --patient -aet MOVESCU -aem STORESCP -aec READWRITE -k 0008,0052=PATIENT -k 0010,0020=PL811332912032439 localhost 9885


***** Proposed engineering changes: Aug 1, 2009 *****

1) Reduce number of executables

   Old:
     plastimatch [options]
     dicom_to_mha [options]
     warp_mha [options]
   New:
     plastimatch register [options]
     plastimatch convert [options]
     plastimatch warp [options]

   "Simple" executables such as bspline.exe, drr_c.exe etc. will not 
   be merged.

2) Add threading options to plastimatch

   Old:
     implementation=gpuit_cpu
   New:
     implementation=plastimatch
     threading=openmp
     max_threads=2

3) Remove gpuit sub-library, merge into plastimatch1.lib

4) Move source code to src/ subdirectory

***** Consistency of indices *****

By convention:

   k, z = slowest moving index (usually IS)
   j, y = middle moving index (usually AP)
   i, x = fastest moving index (usually RL)

Arrays which hold things like the dimensions are indexed as follows:

   dim[0] = dimensions of fastest moving index
   dim[1] = dimensions of middle moving index
   dim[2] = dimensions of slowest moving index

Loops should be nested from slowest index to fastest index.  
Therefore, the correct nesting is:

    for (k = 0; k < fixed->dim[2]; k++) {
	for (j = 0; j < fixed->dim[1]; j++) {
	    for (i = 0; i < fixed->dim[0]; i++) { ... } } }

Embedded indices, such as (x,y,z) coordinates of the vector 
field at a voxel, should be in the order of x, then y, then z.

When you pass indices into a function it should be 
in order x, then y, then z.  For example:

    int volume_index (int* dims, int i, int j, int k);

***** How to compile libf2c *****

Edit libf2c/makefile.vc, and change:
  CFLAGS = -DUSE_CLOCK -DMSDOS -DNO_ONEXIT -Ot1

To:
  CFLAGS = -DUSE_CLOCK -DMSDOS -DNO_ONEXIT -Ot1 -MD

Edit libf2c/fio.h, and comment out:
  extern int isatty(int);

***** How to compile the .br into .cpp *****

The default compile is simply: 
   brcc -o outfile.cpp infile.br

The FDK code doesn't work for PS20 & ARB targets.

We can use -p flag to set the platform.
   brcc -o outfile.cpp

***** How to compile brook on cygwin/g++ *****

1) The config/DetectOS thing always gets Windows_NT because 
the $OS environment variable is standard in Windows.

2) Need to create a new *.mk file  (To be done)

3) It seems to build OK, but doesn't completely solve the 
problem.  fxc still requires windows style paths, maybe cgc does too.

***** Threads vs OpenMP *****

http://www.intel.com/cd/ids/developer/asmo-na/eng/technologies/threading/hyperthreading/53797.htm

https://computing.llnl.gov/tutorials/openMP/

On GCC:
  gcc -fopenmp openmp_test.c

Visual studio 2005 supports OpenMP 2.0
  cl /openmp

Express version does not support OpenMP (except as described below)
  http://blog.codekills.net/archives/25-OpenMP-and-Visual-C++-the-free-way-sorta.html
MinGW gcc OpenMP is still not fully supported
  http://www.nabble.com/OpenMP-and-shared-libgcc-td17516165.html

***** What is the deal with ITK's oriented images? *****

http://www.itk.org/pipermail/insight-users/2008-August/027102.html

Now, ITK 3.10.2 has two flags (earlier version are similar).
The use of these flags are not well described.

ITK_USE_ORIENTED_IMAGE_DIRECTION
ITK_IMAGE_BEHAVES_AS_ORIENTED_IMAGE

***** Logging *****

For "C" logging, I found 2 projects:

- log4c (LGPL license)
- pantheios (BSD license)

***** Timing *****

Options:
1) clock()
2) time()
3) gettimeofday()
4) QueryPerformanceCounter  // windows only
5) OpenMP timer
6a) clock_gettime(CLOCK_MONOTONIC)
6b) clock_gettime(CLOCK_REALTIME)
6c) clock_gettime(CLOCK_HIGHRES) // solaris only?

http://en.wikipedia.org/wiki/Real-time_clock
http://en.wikipedia.org/wiki/High_Precision_Event_Timer

http://cboard.cprogramming.com/c-programming/106025-clock-vs-gettimeofday.html
http://fixunix.com/linux/6645-negative-response-time-gettimeofday.html
http://code.google.com/p/high-resolution-timer/source/browse/trunk/highrestimer/c%2B%2B_library/wraper_and_library/timer_library.c

***** SVN eol-goop *****

Put the following in your ~/.subversion/config

CMakeLists.txt = svn:eol-style=native;svn:mime-type=text/plain
Makefile = svn:eol-style=native;svn:mime-type=text/plain
README* = svn:mime-type=text/plain;svn:eol-style=native
readme* = svn:mime-type=text/plain;svn:eol-style=native

*.tga = svn:mime-type=image/tga
*.bat = svn:mime-type=text/plain;svn:eol-style=CRLF
*.br = svn:eol-style=native;svn:mime-type=text/plain
*.c = svn:eol-style=native;svn:mime-type=text/plain
*.cmake = svn:mime-type=text/plain;svn:eol-style=native
*.cmd = svn:mime-type=text/plain;svn:eol-style=CRLF
*.cpp = svn:eol-style=native;svn:mime-type=text/plain
*.cu = svn:eol-style=native;svn:mime-type=text/plain
*.cxx = svn:eol-style=native;svn:mime-type=text/plain
*.dsp = svn:eol-style=CRLF;svn:mime-type=text/plain
*.dsw = svn:eol-style=CRLF;svn:mime-type=text/plain
*.f = svn:eol-style=native;svn:mime-type=text/plain
*.h = svn:eol-style=native;svn:mime-type=text/plain
*.jpg = svn:mime-type=image/jpeg
*.m = svn:eol-style=native;svn:mime-type=text/plain
*.pl = svn:eol-style=native;svn:mime-type=text/plain;svn:executable
*.png = svn:mime-type=image/png
*.pm = svn:eol-style=native;svn:mime-type=text/plain
*.sh = svn:mime-type=text/plain;svn:eol-style=LF;svn:executable
*.txt = svn:mime-type=text/plain;svn:eol-style=native
*.xml = svn:mime-type=text/xml;svn:eol-style=native
