10.2.  Basic Examples

10.2.1.  Basic Examples Summary

Descriptions of the 5 basic examples are provided here along with links to source code documentation automatically generated with Doxygen.

Example B1 (see also Doxygen page )

  • Simple geometry with a few solids
  • Geometry with simple placements (G4PVPlacement)
  • Scoring total dose in a selected volume in user action classes
  • Geant4 physics list (QBBC)

Example B2 (see also Doxygen page )

  • Simplified tracker geometry with uniform magnetic field
  • Geometry with simple placements (G4PVPlacement) and parameterisation (G4PVParameterisation)
  • Scoring within tracker via G4 sensitive detector and hits
  • Geant4 physics list (FTFP_BERT) with step limiter
  • Started from novice N02 example

Example B3 (see also Doxygen page )

  • Schematic Positron Emission Tomography system
  • Geometry with simple placements with rotation (G4PVPlacement)
  • Radioactive source
  • Scoring within Crystals via G4 scorers
  • Modular physics list built via builders provided in Geant4

Example B4 (see also Doxygen page )

  • Simplified calorimeter with layers of two materials
  • Geometry with replica (G4PVReplica)
  • Scoring within layers in four ways: via user actions (a), via user own object (b), via G4 sensitive detector and hits (c) and via scorers (d)
  • Geant4 physics list (FTFP_BERT)
  • Saving histograms and ntuple in a file using Geant4 analysis tools
  • UI commands defined using G4GenericMessenger
  • Started from novice/N03 example

Example B5 (see also Doxygen page )

  • A double-arm spectrometer with wire chambers, hodoscopes and calorimeters with a local constant magnetic field
  • Geometry with placements with rotation, replicas and parameterisation
  • Scoring within wire chambers, hodoscopes and calorimeters via G4 sensitive detector and hits
  • Geant4 physics list (FTFP_BERT) with step limiter
  • UI commands defined using G4GenericMessenger
  • Saving histograms and ntuple in a file using Geant4 analysis tools
  • Started from extended/analysis/A01

Table 10.1, Table 10.2 and Table 10.3 display the "item charts" for the examples currently prepared in the basic level.

Example B1 Example B2
Description Simple application for accounting dose in a selected volume Fixed target tracker geometry
Geometry
  • solids: box, cons, trd
  • simple placements with translation
  • solids: box, tubs
  • simple placements with translation (a)
  • parameterised volume (b)
  • uniform magnetic field
Physics Geant4 physics list: QBBC Geant4 physics list: FTFP_BERT
Primary generator Particle gun Particle gun
Scoring User action classes Sensitive detector & hits
Vis/GUI Detector & trajectory drawing
  • Detector, trajectory & hits drawing
  • GUI
Stacking - -
Analysis - -

Table 10.1.  The "item chart" for basic level examples B1 and B2.


Example B3 Example B4
Description Schematic Positron Emitted Tomography system Simplified calorimeter with layers of two materials
Geometry
  • solids: box, tubs
  • simple placements with rotation
  • solids: box
  • simple placements with translation
  • replica
  • uniform magnetic field
Physics Modular physics list with Geant4 builders Geant4 physics list: FTFP_BERT
Primary generator Radioactive source (particle gun with Fluor ions) Particle gun
Scoring Multi functional (sensitive) detector & scorers
  • (a) User action classes
  • (b) User own object (runData)
  • (c) Sensitive detector & hits
  • (d) Multi functional (sensitive) detector & scorers
Vis/GUI Detector, trajectory & hits drawing
  • Detector, trajectory & hits drawing
  • GUI
Stacking Killing all neutrina -
Analysis - Histograms 1D, ntuple

Table 10.2.  The "item chart" for basic level examples B3 and B4.


Example B5
Description Double-arm spectrometer with several detectors and a local constant magnetic field
Geometry
  • solids: box, tubs
  • simple placements with rotation
  • replica
  • parameterised volume
  • local constant magnetic field
  • modifying geometry between runs
Physics Geant4 physics list: FTFP_BERT
Primary generator Particle gun
Scoring Sensitive detectors & hits
Vis/GUI
  • Detector, trajectory & hits drawing
  • User defined visualization attributes
Stacking -
Analysis
  • Histograms 1D, ntuple
  • Saving file per run

Table 10.3.  The "item chart" for basic level example B5.


10.2.2.  Basic Examples Macros

All basic examples can be run either interactively or in a batch mode (see section Section 2.1 and Section 2.10) and they are provided with the following set of macros:

  • init_vis.mac
  • vis.mac
  • [gui.mac]
  • run1.mac, run2.mac
  • exampleBN.in

The selection is done automatically according to the application build configuration.

The init_vis.mac macro is always executed just after the Geant4 kernel and user application classes instantiation. It sets first some defaults, then performs Geant4 kernel initialization and finally calls the vis.mac macro with visualization setting.

The vis.mac macros in each of the examples all have the same structure - except for example B1, see below. There are only a few lines in each example with a setting different from the other examples and so they can be easily spotted when looking in the macro. Various commands are proposed in commented blocks of lines with explanations so that a user can just uncomment lines and observe the effect. Additionally, in example B4, there are some visualization tutorial macros in macros/visTutor/. See more on visualization in section Section 2.11 and chapter Chapter 8.

From Release 9.6 the vis.mac macro in example B1 has additional commands that demonstrate additional functionality of the vis system, such as displaying text, axes, scales, date, logo and shows how to change viewpoint and style. Consider copying these to your favourite example or application. To see even more commands use help or ls or browse the available UI commands in section Section 7.1.

The gui.mac macros are provided in examples B2 and B4. This macro is automatically executed if Geant4 is built with any GUI session. See more on graphical user interfaces in section Section 2.9.

When running interactively, the example program stops after processing the init_vis.mac macro and the Geant4 kernel initialization, invoked from the macro, with the prompt Idle>. At this stage users can type in the commands from run1.mac line by line (recommended when running the example for the first time) or execute all commands at once using the "/control/execute run1.mac" command.

The run2.mac macros define conditions for execution a run with a larger number of events and so they are recommended to be executed in a batch. The exampleBN.in macros are also supposed to be run in a batch mode and their outputs from the Geant4 system testing are available in the files exampleBN.out.

10.2.3.  Multi-threading

10.2.3.1.  Multi-threading mode

All basic examples have been migrated to multi-threading (MT). No special steps are needed to build the examples in multi-threading mode. They will automatically run in MT when they are built against the Geant4 libraries built with MT mode activated, otherwise they will run in sequential mode.

The choice of multi-threading mode is done be creating G4MTRunManager instead of G4RunManager in the example main():

#ifdef G4MULTITHREADED
  G4MTRunManager* runManager = new G4MTRunManager;
#else
  G4RunManager* runManager = new G4RunManager;
#endif

The compiler flag -DG4MULTITHREADED is automatically set when building applications using Geant4's CMake (via GEANT4_USE_FILE) and GNUmake systems, and is listed in the flags reported by the --cflags option of the geant4-config program.

10.2.3.2.  Action Initialization class [ B1, B2, B3, B4, B5 ]

A newly introduced BnActionInitialization class derived from G4VUserActionInitialization, present in all basic examples, instantiates and registers all user action classes with the Geant4 kernel .

While in sequential mode the action classes are instatiated just once, via invocation of the method BnActionInitialization::Build() . In multi-threading mode the same method is invoked for each worker thread, so all user action classes are defined thread-locally.

A run action class is instantiated both thread-locally and globally; that is why its instance is created also in the method BnActionInitialization::BuildForMaster(), which is invoked only in multi-threading mode.

10.2.4.  Example B1

Basic concept:

This example demonstrates a simple (medical) application within which users will familiarize themselves with simple placement, use the NIST material database, and can utilize electromagnetic and/or hadronic physics processes. Two items of information are collected in this example: the energy deposited and the total dose for a selected volume.

This example uses the Geant4 physics list QBBC, which is instantiated in the main() function. It requires data files for electromagnetic and hadronic processes. See more on installation of the datasets in Geant4 Installation Guide, Chapter 3.3: Note On Geant4 Datasets . The following datasets: G4LEDATA, G4LEVELGAMMADATA, G4NEUTRONXSDATA, G4SAIDXSDATA and G4ENSDFSTATEDATA are mandatory for this example.

Classes:

  • B1DetectorConstruction

    The geometry is constructed in the B1DetectorConstruction class. The setup consists of a box shaped envelope containing two volumes: a circular cone and a trapezoid.

    Some common materials from medical applications are used. The envelope is made of water and the two inner volumes are made from tissue and bone materials. These materials are created using the G4NistManager class, which allows one to build a material from the NIST database using their names. Available materials and their compositions can be found in the Appendix Section 6.

    The physical volumes are made from Constructive Solid Geometry (CSG) solids and placed without rotation using the G4PVPlacement class.

  • B1PrimaryGeneratorAction

    The default kinematics is a 6 MeV gamma, randomly distributed in front of the envelope across 80% of the transverse (X,Y) plane. This default setting can be changed via the commands of the G4ParticleGun class.

  • B1SteppingAction

    It is in the UserSteppingAction() function that the energy deposition is collected for a selected volume.

  • B1EventAction

    The statistical event by event accumulation of energy deposition. At the end of event, the acummulated values are passed in B1RunAction and summed over the whole run.

  • B1RunAction

    Sums the event energy depositions. In multi-threading mode the energy deposition accumulated in G4Accumulable objects per worker is merged to the master. Information about the primary particle is printed in this class along with the computation of the dose. An example of creating and computing new units (e.g., dose) is also shown in the class constructor.

    G4Accumulable<G4double> type instead of G4double is used for the B1RunAction data members in order to facilitate merging of the values accumulated on workers to the master. At present the accumulables have to be registered to G4AccumulablesManager and G4ParametersManager::Merge() has to be called from the users code. This is planned to be further simplified with a closer integration of G4Accumulable classes in the Geant4 kernel next year.

10.2.5.  Example B2

This example simulates a simplified fixed target experiment. To demonstrate alternative ways of constructing the geometry two variants are provided: B2a (explicit construction) and B2b (parametrized volumes).

The set of available particles and their physics processes are defined in the FTFP_BERT physics list. This Geant4 physics list is instantiated in the main() function. It requires data files for electromagnetic and hadronic processes. See more on installation of the datasets in Geant4 Installation Guide, Chapter 3.3: Note On Geant4 Datasets . The following datasets: G4LEDATA, G4LEVELGAMMADATA, G4NEUTRONXSDATA, G4SAIDXSDATA and G4ENSDFSTATEDATA are mandatory for this example.

This example also illustrates how to introduce tracking constraints like maximum step length via G4StepLimiter, and minimum kinetic energy, etc., via the G4UserSpecialCuts processes. This is accomplished by adding G4StepLimiterPhysics to the physics list.

Classes:

  • B2[a, b]DetectorConstruction

    The setup consists of a target followed by six chambers of increasing transverse size at defined distances from the target. These chambers are located in a region called the Tracker region. Their shape are cylinders constructed as simple cylinders (in B2aDetectorConstruction) and as parametrised volumes (in B2bDetectorConstruction) - see also B2bChamberParameterisation class.

    In addition, a global uniform transverse magnetic field can be applied using G4GlobalMagFieldMessenger, instantiated in ConstructSDandField() with a non zero field value, or via an interactive command. An instance of the B2TrackerSD class is created and associated with each logical chamber volume (in B2a) and with the one G4LogicalVolume associated with G4PVParameterised (in B2b).

    One can change the materials of the target and the chambers interactively via the commands defined in B2aDetectorMessenger (or B2bDetectorMessenger).

    This example also illustrates how to introduce tracking constraints like maximum step length, minimum kinetic energy etc. via the G4UserLimits class and associated G4StepLimiter and G4UserSpecialCuts processes. The maximum step limit in the tracker region can be set by the interactive command defined in B2aDetectorMessenger (or B2bDetectorMessenger).

  • B2PrimaryGeneratorAction

    The primary generator action class employs the G4ParticleGun. The primary kinematics consists of a single particle which hits the target perpendicular to the entrance face. The type of the particle and its energy can be changed via the G4 built-in commands of the G4ParticleGun class.

  • B2EventAction

    The event number is written to the log file every requested number of events in BeginOfEventAction() and EndOfEventAction(). Moreover, for the first 100 events and every 100 events thereafter information about the number of stored trajectories in the event is printed as well as the number of hits stored in the G4VHitsCollection.

  • B2RunAction

    The run number is printed at BeginOfRunAction(), where the G4RunManager is also informed how to SetRandomNumberStore for storing initial random number seeds per run or per event.

  • B2TrackerHit

    The tracker hit class is derived from G4VHit. In this example, a tracker hit is a step by step record of the track identifier, the chamber number, the total energy deposit in this step, and the position of the energy deposit.

  • B2TrackerSD

    The tracker sensitive detector class is derived from G4VSensitiveDetector. In ProcessHits() - called from the Geant4 kernel at each step - it creates one hit in the selected volume so long as energy is deposited in the medium during that step. This hit is inserted in a HitsCollection. The HitsCollection is printed at the end of each event (via the method B2TrackerSD::EndOfEvent()), under the control of the "/hits/verbose 2" command.

10.2.6.  Example B3

This example simulates a Schematic Positron Emission Tomography system. To demonstrate alternative ways of accumulation event statistics in a run two variants are provided: B3a (using new G4Accumulable class) and B3b (using G4Run class).

Classes:

Geant4 Installation Guide, Chapter 3.3: Note On Geant4 Datasets
  • B3DetectorConstruction

    Crystals are circularly arranged to form a ring. A number rings make up the full detector (gamma camera). This is done by positionning Crystals in Ring with an appropriate rotation matrix. Several copies of Ring are then placed in the full detector.

    The Crystal material, Lu2SiO5, is not included in the G4Nist database. Therefore, it is explicitly built in DefineMaterials().

    Crystals are defined as scorers in DetectorConstruction::CreateScorers(). There are two G4MultiFunctionalDetector objects: one for the Crystal (EnergyDeposit), and one for the Patient (DoseDeposit).

  • B3PhysicsList

    The physics list contains standard electromagnetic processes and the radioactiveDecay module for GenericIon. It is defined in the B3PhysicsList class as a Geant4 modular physics list with registered Geant4 physics builders:

    • G4DecayPhysics
    • G4RadioactiveDecayPhysics
    • G4EmStandardPhysics

  • B3PrimaryGeneratorAction

    The default particle beam is an ion (F18), at rest, randomly distributed within a zone inside a patient and is defined in GeneratePrimaries().

  • B3aEventAction , B3aRunAction

    Energy deposited in crystals is summed by G4Scorer. At the end of event, the values acummulated in B3aEventAction are passed in B3aRunAction and summed over the whole run. In multi-threading mode the data accumulated in G4Accumulable objects per workers is merged to the master in B3aRunAction::EndOfRunAction() and the final result is printed on the screen.

    G4Accumulable<> type instead of G4double and G4int types is used for the B3aRunAction data members in order to facilitate merging of the values accumulated on workers to the master. At present the accumulables have to be registered to G4AccumulablesManager and G4AccumulablesManager::Merge() has to be called from the users code. This is planned to be further simplified with a closer integration of G4Accumulable classes in the Geant4 kernel next year.

  • B3bRun , B3bRunAction

    Energy deposited in crystals is summed by G4Scorer. B3Run::RecordEvent() collects information event by event from the hits collections, and accumulates statistics for B3RunAction::EndOfRunAction(). In multi-threading mode the statistics accumulated per worker is merged to the master in Run::Merge().

  • B3StackingAction

    Beta decay of Fluorine generates a neutrino. One wishes not to track this neutrino; therefore one kills it immediately, before created particles are put in a stack.

10.2.7.  Example B4

This example simulates a simple Sampling Calorimeter setup. To demonstrate several possible ways of data scoring, the example is provided in four variants: B4a, B4b, B4c, B4d. (See also examples/extended/electromagnetic/TestEm3).

The set of available particles and their physics processes are defined in the FTFP_BERT physics list. This Geant4 physics list is instantiated in the main() function. It requires data files for electromagnetic and hadronic processes. See more on installation of the datasets in Geant4 Installation Guide, Chapter 3.3: Note On Geant4 Datasets . The following datasets: G4LEDATA, G4LEVELGAMMADATA, G4NEUTRONXSDATA, G4SAIDXSDATA and G4ENSDFSTATEDATA are mandatory for this example.

Classes:

  • B4[c, d] DetectorConstruction

    The calorimeter is a box made of a given number of layers. A layer consists of an absorber plate and of a detection gap. The layer is replicated. In addition a transverse uniform magnetic field can be applied using G4GlobalMagFieldMessenger, instantiated in ConstructSDandField() with a non zero field value, or via interactive commands.

  • B4PrimaryGeneratorAction

    The primary generator action class uses G4ParticleGun. It defines a single particle which hits the calorimeter perpendicular to the input face. The type of the particle can be changed via the G4 built-in commands of the G4ParticleGun class.

  • B4RunAction

    It accumulates statistics and computes dispersion of the energy deposit and track lengths of charged particles with the aid of analysis tools. H1D histograms are created in BeginOfRunAction() for the energy deposit and track length in both Absorber and Gap volumes. The same values are also saved in an ntuple. The histograms and ntuple are saved in the output file in a format accoring to a selected technology in B4Analysis.hh. In EndOfRunAction(), the accumulated statistics and computed dispersion are printed. When running in multi-threading mode, the histograms accumulated on threads are automatically merged in a single output file, while the ntuple is written in files per thread.

Classes in B4a (scoring via user actions):

  • B4aSteppingAction

    In UserSteppingAction() the energy deposit and track lengths of charged particles in each step in the Absober and Gap layers are collected and subsequently recorded in B4aEventAction.

  • B4aEventAction

    It defines data members to hold the energy deposit and track lengths of charged particles in the Absorber and Gap layers. In EndOfEventAction(), these quantities are printed and filled in H1D histograms and ntuple to accumulate statistic and compute dispersion.

Classes in B4b (via user own object):

  • B4bRunData

    A data class, derived from G4Run, which defines data members to hold the energy deposit and track lengths of charged particles in the Absober and Gap layers. It is instantiated in B4bRunAction::GenerateRun. The data are collected step by step in B4bSteppingAction, and the accumulated values are entered in histograms and an ntuple event by event in B4bEventAction.

  • B4bSteppingAction

    In UserSteppingAction() the energy deposit and track lengths of charged particles in Absorber and Gap layers are collected and subsequently recorded in B4bRunData.

  • B4bEventAction

    In EndOfEventAction(), the accumulated quantities of the energy deposit and track lengths of charged particles in Absorber and Gap layers are printed and then stored in B4bRunData.

Classes in B4c (via Geant4 sensitive detector and hits):

  • B4cDetectorConstruction

    In addition to materials, volumes and uniform magnetic field definitions as in B4DetectorConstruction, in ConstructSDandField() two instances of the B4cCalorimeterSD class are created and associated with Absorber and Gap volumes.

  • B4cCalorHit

    The calorimeter hit class is derived from G4VHit. It defines data members to store the energy deposit and track lengths of charged particles in a selected volume.

  • B4cCalorimeterSD

    The calorimeter sensitive detector class is derived from G4VSensitiveDetector. Two instances of this class are created in B4cDetectorConstruction and associated with Absorber and Gap volumes. In Initialize(), it creates one hit for each calorimeter layer and one more hit for accounting the total quantities in all layers. The values are accounted in hits in the ProcessHits() function, which is called by the Geant4 kernel at each step.

  • B4cEventAction

    In EndOfEventAction(), the accumulated quantities of the energy deposit and track lengths of charged particles in Absorber and Gap layers are printed and then stored in the hits collections.

Classes in B4d (via Geant4 scorers):

  • B4dDetectorConstruction

    In addition to materials, volumes and uniform magnetic field definitions as in B4DetectorConstruction, in ConstructSDandField() sensitive detectors of G4MultiFunctionalDetector type with primitive scorers are created and associated with Absorber and Gap volumes.

  • B4dEventAction

    In EndOfEventAction(), the accumulated quantities of the energy deposit and track lengths of charged particles in Absober and Gap layers are printed and then stored in the hits collections.

10.2.8.  Example B5

This example simulates a a double-arm spectrometer with wire chambers, hodoscopes and calorimeters with a uniform local magnetic field.

The set of available particles and their physics processes are defined in the FTFP_BERT physics list. This Geant4 physics list is instantiated in the main() function. It requires data files for electromagnetic and hadronic processes. See more on installation of the datasets in Geant4 Installation Guide, Chapter 3.3: Note On Geant4 Datasets . The following datasets: G4LEDATA, G4LEVELGAMMADATA, G4NEUTRONXSDATA, G4SAIDXSDATA and G4ENSDFSTATEDATA are mandatory for this example.

This example also illustrates how to introduce tracking constraints like maximum step length via G4StepLimiter, and minimum kinetic energy, etc., via the G4UserSpecialCuts processes. This is accomplished by adding G4StepLimiterPhysics to the physics list.

This example can be built with excluding visualization and/or Geant4 user interface via G4VIS_USE and G4UI_USE compiler options (see exampleB5.cc). These options are defined by default with Geant4 configuration; they can be switched off at compilation time via the CMake options G4VIS_NONE or G4UI_NONE or via the environment variables of the same name if using GNUmake build.

Classes:

  • B5DetectorConstruction ,

    The spectrometer consists of two detector arms. One arm provides position and timing information of the incident particle while the other collects position, timing and energy information of the particle after it has been deflected by a magnetic field centered at the spectrometer pivot point.

    First arm: box filled with air, also containing:

    • 1 hodoscope (15 vertical strips of plastic scintillator)
    • 1 drift chamber (horizontal argon gas layers with a "virtual wire" at the center of each layer)

    Second arm: box filled with air, also containing:

    • 1 hodoscope (25 vertical strips of plastic scintillator)
    • 1 drift chamber (5 horizontal argon gas layers with a "virtual wire" at the center of each layer)
    • 1 electromagnetic calorimeter: a box sub-divided along x,y and z axes into cells of CsI (see also B5CellParameterisation class)
    • 1 hadronic calorimeter: a box sub-divided along x,y, and z axes into cells of lead, with a layer of plastic scintillator placed at the center of each cell

    The magnetic field region is represented by an air-filled cylinder which contains the field (see B5MagneticField).. The maximum step limit in the magnetic field region is also set via the G4UserLimits class in a similar way as in Example B2.

    The rotation angle of the second arm and the magnetic field value can be set via the interactive command defined using the G4GenericMessenger class.

  • B5PrimaryGeneratorAction

    The primary generator action class employs the G4ParticleGun. The primary kinematics consists of a single particle which is is sent in the direction of the first spectrometer arm.

    The type of the particle and its several properties can be changed via the Geant4 built-in commands of the G4ParticleGun class or this example command defined using the G4GenericMessenger class.

  • B5EventAction

    An event consists of the generation of a single particle which is transported through the first spectrometer arm. Here, a scintillator hodoscope records the reference time of the particle before it passes through a drift chamber where the particle position is measured. Momentum analysis is performed as the particle passes through a magnetic field at the spectrometer pivot and then into the second spectrometer arm. In the second arm, the particle passes through another hodoscope and drift chamber before interacting in the electromagnetic calorimeter. Here it is likely that particles will induce electromagnetic showers. The shower energy is recorded in a three-dimensional array of CsI crystals. Secondary particles from the shower, as well as primary particles which do not interact in the CsI crystals, pass into the hadronic calorimeter. Here, the remaining energy is collected in a three-dimensional array of scintillator-lead sandwiches.

    In first execution of BeginOfEventAction() the hits collections identifiers are saved in data members of the class and then used in EndOfEventAction() for accessing the hists collections and filling the accounted information in defined histograms and ntuples and printing its summary in a log file. The frequency of printing can be tuned with the built-in command "/run/printProgress frequency".

  • B5RunAction

    The run action class handles the histograms and ntuples with the aid of Geant4 analysis tools in a similar way as in Example B4. From Release 10.2 the vectors of energy deposits in Electromagnetic and Hadronic calorimeter cells are also stored in the ntuple.

  • Hit and Sensitive Detector Classes

    All the information required to simulate and analyze an event is recorded in hits. This information is recorded in the following sensitive detectors:

    The hit classes include methods GetAttDefs and CreateAttValues to define and then fill extra "HepRep-style" Attributes that the visualization system can use to present extra information about the hits. For example, if you pick a B5HadCalorimeterHit in OpenGL or a HepRep viewer, you will be shown the hit's "Hit Type", "Column ID", "Row ID", "Energy Deposited" and "Position".

    These attributes are essentially arbitrary extra pieces of information (integers, doubles or strings) that are carried through the visualization. Each attribute is defined once in G4AttDef object and then is filled for each hit in a G4AttValue object. These attributes can also be used by commands to filter which hits are drawn: "/vis/filtering/hits/drawByAttribute".

    Detector Geometry and trajectories also carry HepRep-style attributes, but these are filled automatically in the base classes. HepRep is further described at: http://www.slac.stanford.edu/~perl/heprep/