source: branches/pixel-map-branch/src/param.hh @ 1441

Last change on this file since 1441 was 254, checked in by Matthew Whiting, 17 years ago

Added functionality to use only a subsection in the statistics calculations. This includes:

  • A new Section class.
  • New input parameters.
  • Altering the setCubeStats() function to test for this.
  • Some documentation on the new parameters.
File size: 21.9 KB
Line 
1#ifndef PARAM_H
2#define PARAM_H
3
4#include <iostream>
5#include <string>
6#include <vector>
7#include <math.h>
8#include <wcs.h>
9#include <wcshdr.h>
10#include <Utils/utils.hh>
11#include <Utils/Section.hh>
12#include <ATrous/filter.hh>
13
14class FitsHeader; // foreshadow this so that Param knows it exists
15
16/**
17 * Class to store general parameters.
18 *
19 * This is a general repository for parameters that are used by all
20 * functions. This is how the user interacts with the program, as
21 * parameters are read in from disk files through functions in this
22 * class.
23 */
24
25class Param
26{
27public:
28  Param();
29  virtual ~Param(){if(sizeOffsets>0) delete [] offsets;};
30  Param(const Param& p);
31  Param& operator= (const Param& p);
32  //-----------------
33  // Functions in param.cc
34  //
35  /** Read in parameters from a disk file. */
36  int    readParams(std::string paramfile);
37
38  /** Copy certain necessary FITS header parameters from a FitsHeader
39      object */
40  void   copyHeaderInfo(FitsHeader &head);
41
42  /** Determine filename in which to save the Hanning-smoothed
43      array. */
44  std::string outputSmoothFile();
45
46  /** Determine filename in which to save the reconstructed array. */
47  std::string outputReconFile();
48
49  /** Determine filename in which to save the residual array from the
50      atrous reconstruction. */
51  std::string outputResidFile();
52
53  /** Print the parameter set in a readable fashion. */
54  friend std::ostream& operator<< ( std::ostream& theStream, Param& par);
55  friend class Image;
56  //------------------
57  // Functions in FitsIO/subsection.cc
58  //
59  /** Make sure the subsection string is OK, and read the axis
60      subsections. */
61  int    verifySubsection();
62
63  /** Set the correct offset values for each axis */
64  void   setOffsets(struct wcsprm *wcs);
65
66  //--------------------
67  // These are inline functions.
68  //
69  /** Is a pixel value a BLANK?
70   *  Tests whether the value passed as the argument is BLANK or not.
71   *   If flagBlankPix is false, return false.
72   *   Otherwise, compare to the relevant FITS keywords, using integer
73   *   comparison.
74   */
75  bool   isBlank(float &value){
76    return this->flagBlankPix &&
77      (this->blankKeyword == int((value-this->bzeroKeyword)/this->bscaleKeyword));
78  };
79
80  /** Is a given channel flagged as being in the Milky Way?*/           
81  bool   isInMW(int z){return ( flagMW && (z>=minMW) && (z<=maxMW) );};
82
83
84  /** Is a given pixel position OK for use with stats calculations? */
85  bool   isStatOK(int x, int y, int z){
86    int xval=x,yval=y,zval=z;
87    if(flagSubsection){
88      xval += pixelSec.getStart(0);
89      yval += pixelSec.getStart(1);
90      zval += pixelSec.getStart(2);
91    }
92    return !flagStatSec || statSec.isInside(xval,yval,zval);
93  };
94
95
96  //--------------------
97  // Basic inline accessor functions
98  //
99  std::string getImageFile(){return imageFile;};
100  void   setImageFile(std::string fname){imageFile = fname;};
101  std::string getFullImageFile(){
102    if(flagSubsection) return imageFile+pixelSec.getSection();
103    else return imageFile;
104  };
105  bool   getFlagSubsection(){return flagSubsection;};
106  void   setFlagSubsection(bool flag){flagSubsection=flag;};
107  std::string getSubsection(){return pixelSec.getSection();};
108  void   setSubsection(std::string range){pixelSec.setSection(range);};
109  bool   getFlagReconExists(){return flagReconExists;};
110  void   setFlagReconExists(bool flag){flagReconExists=flag;};
111  std::string getReconFile(){return reconFile;};
112  void   setReconFile(std::string file){reconFile = file;};
113  bool   getFlagSmoothExists(){return flagSmoothExists;};
114  void   setFlagSmoothExists(bool flag){flagSmoothExists=flag;};
115  std::string getSmoothFile(){return smoothFile;};
116  void   setSmoothFile(std::string file){smoothFile = file;};
117  //
118  bool   getFlagLog(){return flagLog;};
119  void   setFlagLog(bool flag){flagLog=flag;};
120  std::string getLogFile(){return logFile;};
121  void   setLogFile(std::string fname){logFile = fname;};
122  std::string getOutFile(){return outFile;};
123  void   setOutFile(std::string fname){outFile = fname;};
124  std::string getSpectraFile(){return spectraFile;};
125  void   setSpectraFile(std::string fname){spectraFile = fname;};
126  bool   getFlagOutputSmooth(){return flagOutputSmooth;};
127  void   setFlagOutputSmooth(bool flag){flagOutputSmooth=flag;};
128  bool   getFlagOutputRecon(){return flagOutputRecon;};
129  void   setFlagOutputRecon(bool flag){flagOutputRecon=flag;};
130  bool   getFlagOutputResid(){return flagOutputResid;};
131  void   setFlagOutputResid(bool flag){flagOutputResid=flag;};
132  bool   getFlagVOT(){return flagVOT;};
133  void   setFlagVOT(bool flag){flagVOT=flag;};
134  std::string getVOTFile(){return votFile;};
135  void   setVOTFile(std::string fname){votFile = fname;};
136  bool   getFlagKarma(){return flagKarma;};
137  void   setFlagKarma(bool flag){flagKarma=flag;};
138  std::string getKarmaFile(){return karmaFile;};
139  void   setKarmaFile(std::string fname){karmaFile = fname;};
140  bool   getFlagMaps(){return flagMaps;};
141  void   setFlagMaps(bool flag){flagMaps=flag;};
142  std::string getDetectionMap(){return detectionMap;};
143  void   setDetectionMap(std::string fname){detectionMap = fname;};
144  std::string getMomentMap(){return momentMap;};
145  void   setMomentMap(std::string fname){momentMap = fname;};
146  bool   getFlagXOutput(){return flagXOutput;};
147  void   setFlagXOutput(bool b){flagXOutput=b;};
148  //
149  bool   getFlagNegative(){return flagNegative;};
150  void   setFlagNegative(bool flag){flagNegative=flag;};
151  bool   getFlagBlankPix(){return flagBlankPix;};
152  void   setFlagBlankPix(bool flag){flagBlankPix=flag;};
153  float  getBlankPixVal(){return blankPixValue;};
154  void   setBlankPixVal(float v){blankPixValue=v;};
155  int    getBlankKeyword(){return blankKeyword;};
156  void   setBlankKeyword(int v){blankKeyword=v;};
157  float  getBscaleKeyword(){return bscaleKeyword;};
158  void   setBscaleKeyword(float v){bscaleKeyword=v;};
159  float  getBzeroKeyword(){return bzeroKeyword;};
160  void   setBzeroKeyword(float v){bzeroKeyword=v;};
161  bool   getFlagUsingBlank(){return flagUsingBlank;};
162  void   setFlagUsingBlank(bool b){flagUsingBlank=b;};
163  bool   getFlagMW(){return flagMW;};
164  bool   setFlagMW(bool flag){flagMW=flag;};
165  int    getMaxMW(){return maxMW;};
166  void   setMaxMW(int m){maxMW=m;};
167  int    getMinMW(){return minMW;};
168  void   setMinMW(int m){minMW=m;};
169  void   setBeamSize(float s){numPixBeam = s;};
170  float  getBeamSize(){return numPixBeam;};
171  bool   getFlagUsingBeam(){return flagUsingBeam;};
172  void   setFlagUsingBeam(bool b){flagUsingBeam=b;};
173  //
174  bool   getFlagCubeTrimmed(){return flagTrimmed;};
175  void   setFlagCubeTrimmed(bool flag){flagTrimmed = flag;};
176  long   getBorderLeft(){return borderLeft;};
177  void   setBorderLeft(long b){borderLeft = b;};
178  long   getBorderRight(){return borderRight;};
179  void   setBorderRight(long b){borderRight = b;};
180  long   getBorderBottom(){return borderBottom;};
181  void   setBorderBottom(long b){borderBottom = b;};
182  long   getBorderTop(){return borderTop;};
183  void   setBorderTop(long b){borderTop = b;};
184  //
185  long   getXOffset(){return xSubOffset;};
186  void   setXOffset(long o){xSubOffset = o;};
187  long   getYOffset(){return ySubOffset;};
188  void   setYOffset(long o){ySubOffset = o;};
189  long   getZOffset(){return zSubOffset;};
190  void   setZOffset(long o){zSubOffset = o;};
191  //
192  int    getMinPix(){return minPix;};
193  void   setMinPix(int m){minPix=m;};
194  //     
195  bool   getFlagGrowth(){return flagGrowth;};
196  void   setFlagGrowth(bool flag){flagGrowth=flag;};
197  float  getGrowthCut(){return growthCut;};
198  void   setGrowthCut(float c){growthCut=c;};
199  //     
200  bool   getFlagFDR(){return flagFDR;};
201  void   setFlagFDR(bool flag){flagFDR=flag;};
202  float  getAlpha(){return alphaFDR;};
203  void   setAlpha(float a){alphaFDR=a;};
204  //
205  bool   getFlagBaseline(){return flagBaseline;};
206  void   setFlagBaseline(bool flag){flagBaseline = flag;};
207  //
208  bool   getFlagStatSec(){return flagStatSec;};
209  void   setFlagStatSec(bool flag){flagStatSec=flag;};
210  std::string getStatSec(){return statSec.getSection();};
211  void   setStatSec(std::string range){statSec.setSection(range);};
212  float  getCut(){return snrCut;};
213  void   setCut(float c){snrCut=c;};
214  float  getThreshold(){return threshold;};
215  void   setThreshold(float f){threshold=f;};
216  bool   getFlagUserThreshold(){return flagUserThreshold;};
217  void   setFlagUserThreshold(bool b){flagUserThreshold=b;};
218  //     
219  bool   getFlagSmooth(){return flagSmooth;};
220  void   setFlagSmooth(bool b){flagSmooth=b;};
221  int    getHanningWidth(){return hanningWidth;};
222  void   setHanningWidth(int f){hanningWidth=f;};
223  //     
224  bool   getFlagATrous(){return flagATrous;};
225  void   setFlagATrous(bool flag){flagATrous=flag;};
226  int    getReconDim(){return reconDim;};
227  void   setReconDim(int i){reconDim=i;};
228  int    getMinScale(){return scaleMin;};
229  void   setMinScale(int s){scaleMin=s;};
230  float  getAtrousCut(){return snrRecon;};
231  void   setAtrousCut(float c){snrRecon=c;};
232  int    getFilterCode(){return filterCode;};
233  void   setFilterCode(int c){filterCode=c;};
234  std::string getFilterName(){return reconFilter.getName();};
235  Filter& filter(){ Filter &rfilter = reconFilter; return rfilter; };
236  //     
237  bool   getFlagAdjacent(){return flagAdjacent;};
238  void   setFlagAdjacent(bool flag){flagAdjacent=flag;};
239  float  getThreshS(){return threshSpatial;};
240  void   setThreshS(float t){threshSpatial=t;};
241  float  getThreshV(){return threshVelocity;};
242  void   setThreshV(float t){threshVelocity=t;};
243  int    getMinChannels(){return minChannels;};
244  void   setMinChannels(int n){minChannels=n;};
245  //
246  std::string getSpectralMethod(){return spectralMethod;};
247  void   setSpectralMethod(std::string s){spectralMethod=s;};
248  std::string getSpectralUnits(){return spectralUnits;};
249  void   setSpectralUnits(std::string s){spectralUnits=s;};
250  bool   drawBorders(){return borders;};
251  void   setDrawBorders(bool f){borders=f;};
252  bool   drawBlankEdge(){return blankEdge;};
253  void   setDrawBlankEdge(bool f){blankEdge=f;};
254
255  /** Are we in verbose mode? */
256  bool   isVerbose(){return verbose;};
257  void   setVerbosity(bool f){verbose=f;};
258 
259private:
260  // Input files
261  std::string imageFile;  ///< The image to be analysed.
262  bool   flagSubsection;  ///< Whether we just want a subsection of
263                          ///   the image
264  Section pixelSec;       ///< The Section object storing the pixel
265                          ///   subsection information.
266  bool   flagReconExists; ///< The reconstructed array is in a FITS
267                          ///   file on disk.
268  std::string reconFile;  ///< The FITS file containing the
269                          ///   reconstructed array.
270  bool   flagSmoothExists;///< The Hanning-smoothed array is in a FITS
271                          ///   file.
272  std::string smoothFile; ///< The FITS file containing the smoothed
273                          ///   array.
274
275  // Output files
276  bool   flagLog;         ///< Should we do the intermediate logging?
277  std::string logFile;    ///< Where the intermediate logging goes.
278  std::string outFile;    ///< Where the final results get put.
279  std::string spectraFile;///< Where the spectra are displayed
280  bool   flagOutputSmooth;///< Should the Hanning-smoothed cube be
281                          ///   written?
282  bool   flagOutputRecon; ///< Should the reconstructed cube be
283                          ///   written?
284  bool   flagOutputResid; ///< Should the reconstructed cube be
285                          ///   written?
286  bool   flagVOT;         ///< Should we save results in VOTable
287                          ///   format?
288  std::string votFile;    ///< Where the VOTable goes.
289  bool   flagKarma;       ///< Should we save results in Karma
290                          ///   annotation format?
291  std::string karmaFile;  ///< Where the Karma annotation file goes.
292  bool   flagMaps;        ///< Should we produce detection and moment
293                          ///   maps in postscript form?
294  std::string detectionMap;///< The name of the detection map
295                           ///   (postscript file).
296  std::string momentMap;  ///< The name of the 0th moment map (ps file).
297  bool   flagXOutput;     ///< Should there be an xwindows output of
298                          ///   the detection map?
299
300  // Cube related parameters
301  bool   flagNegative;    ///< Are we going to search for negative
302                          ///   features?
303  bool   flagBlankPix;    ///< A flag that indicates whether there are
304                          ///   pixels defined as BLANK and whether we
305                          ///   need to remove & ignore them in
306                          ///   processing.
307  float  blankPixValue;   ///< Pixel value that is considered BLANK.
308  int    blankKeyword;    ///< The FITS header keyword BLANK.
309  float  bscaleKeyword;   ///< The FITS header keyword BSCALE.
310  float  bzeroKeyword;    ///< The FITS header keyword BZERO.
311  bool   flagUsingBlank;  ///< If true, we are using the blankPixValue
312                          ///   keyword, otherwise we use the value in
313                          ///   the FITS header.
314  bool   flagMW;          ///< A flag that indicates whether to ignore
315                          ///   the Milky Way channels.
316  int    maxMW;           ///< Last  Milky Way channel
317  int    minMW;           ///< First Milky Way channel
318  float  numPixBeam;      ///< Size (area) of the beam in pixels.
319  bool   flagUsingBeam;   ///< If true, we are using the numPixBeam
320                          ///   parameter, otherwise we use the value
321                          ///   in the FITS header.
322  // Trim-related
323  bool   flagTrimmed;     ///< Has the cube been trimmed of excess
324                          ///   BLANKs around the edge?
325  long   borderLeft;      ///< The number of BLANK pixels trimmed from
326                          ///   the left of the cube;
327  long   borderRight;     ///< The number trimmed from the Right of
328                          ///   the cube;
329  long   borderBottom;    ///< The number trimmed from the Bottom of
330                          ///   the cube;
331  long   borderTop;       ///< The number trimmed from the Top of the
332                          ///   cube;
333  // Subsection offsets
334  long  *offsets;         ///< The array of offsets for each FITS axis.
335  long   sizeOffsets;     ///< The size of the offsets array.
336  long   xSubOffset;      ///< The subsection's x-axis offset
337  long   ySubOffset;      ///< The subsection's y-axis offset
338  long   zSubOffset;      ///< The subsection's z-axis offset
339  // Baseline related
340  bool   flagBaseline;    ///< Whether to do baseline subtraction
341                          ///   before reconstruction and/or searching.
342  // Detection-related
343  int    minPix;          ///< Minimum number of pixels for a detected
344                          ///   object to be counted
345  // Object growth
346  bool   flagGrowth;      ///< Are we growing objects once they are
347                          ///   found?
348  float  growthCut;       ///< The SNR that we are growing objects
349                          ///   down to.
350  // FDR analysis
351  bool   flagFDR;         ///< Should the FDR method be used?
352  float  alphaFDR;        ///< Alpha value for FDR detection algorithm
353  // Basic detection
354  bool   flagStatSec;     ///< Whether we just want to use a
355                          ///   subsection of the image to calculate
356                          ///   the statistics.
357  Section statSec;       ///< The Section object storing the statistics
358                          ///   subsection information.
359  float  snrCut;          ///< How many sigma above mean is a
360                          ///   detection when sigma-clipping
361  float  threshold;       ///< What the threshold is (when
362                          ///   sigma-clipping).
363  bool   flagUserThreshold;///< Whether the user has defined a
364                           ///   threshold of their own.
365  // Smoothing of the cube
366  bool   flagSmooth;      ///< Should the cube be smoothed before
367                          ///   searching?
368  int    hanningWidth;    ///< Width for hanning smoothing.
369  // A trous reconstruction parameters
370  bool   flagATrous;      ///< Are we using the a trous reconstruction?
371  int    reconDim;        ///< How many dimensions to use for the
372                          ///   reconstruction?
373  int    scaleMin;        ///< Min scale used in a trous reconstruction
374  float  snrRecon;        ///< SNR cutoff used in a trous
375                          ///   reconstruction (only wavelet coefficients
376                          ///   that survive this threshold are kept)
377  Filter reconFilter;     ///< The filter used for reconstructions.
378  int    filterCode;      ///< The code number for the filter to be
379                          ///   used (saves having to parse names)
380  std::string filterName; ///< The code number converted into a name,
381                          ///   for outputting purposes.
382
383  // Volume-merging parameters
384  bool   flagAdjacent;    ///< Whether to use the adjacent criterion
385                          ///   for judging if objects are to be merged.
386  float  threshSpatial;   ///< Maximum spatial separation between
387                          ///   objects
388  float  threshVelocity;  ///< Maximum channels separation between
389                          ///   objects
390  int    minChannels;     ///< Minimum no. of channels to make an object
391  // Input-Output related
392  std::string spectralMethod; ///< A string indicating choice of
393                              ///   spectral plotting method: choices are
394                              ///   "peak" (default) or "sum"
395  std::string spectralUnits;   ///< A string indicating what units the
396                               ///   spectral axis should be quoted in.
397  bool   borders;         ///< Whether to draw a border around the
398                          ///   individual pixels of a detection in the
399                          ///   spectral display
400  bool   blankEdge;       ///< Whether to draw a border around the
401                          ///   BLANK pixel region in the moment maps and
402                          ///   cutout images
403  bool   verbose;         ///< Whether to use maximum verbosity -- use
404                          ///   progress indicators in the reconstruction
405                          ///   & merging steps.
406
407};
408
409//===========================================================================
410
411/**
412 *  Class to store FITS header information.
413 *
414 *   Stores information from a FITS header, including WCS information
415 *    in the form of a wcsprm struct, as well as various keywords.
416 */
417class FitsHeader
418{
419
420public:
421  FitsHeader();
422  virtual ~FitsHeader(){wcsvfree(&nwcs,&wcs);};
423  FitsHeader(const FitsHeader& h);
424  FitsHeader& operator= (const FitsHeader& h);
425
426  //--------------------
427  // Functions in param.cc
428  //
429  /** Assign correct WCS parameters.  */
430  void    setWCS(struct wcsprm *w);
431
432  /** Return the WCS parameters in a WCSLIB wcsprm struct. */
433  struct wcsprm *getWCS();
434
435  // front ends to WCS functions
436  /** Convert pixel coords to world coords for a single point. */
437  int     wcsToPix(const double *world, double *pix);
438
439  /** Convert pixel coords to world coords for many points. */
440  int     wcsToPix(const double *world, double *pix, const int npts);
441
442  /** Convert world coords to pixel coords for a single point. */
443  int     pixToWCS(const double *pix, double *world);
444
445  /** Convert world coords to pixel coords for many points. */
446  int     pixToWCS(const double *pix, double *world, const int npts);
447
448  /** Convert a (x,y,z) position to a velocity. */
449  double  pixToVel(double &x, double &y, double &z);
450
451  /** Convert a set of  (x,y,z) positions to a set of velocities. */
452  double *pixToVel(double &x, double &y, double *zarray, int size);
453
454  /** Convert a spectral coordinate to a velocity coordinate.*/
455  double  specToVel(const double &z);
456
457  /** Convert a velocity coordinate to a spectral coordinate.*/
458  double  velToSpec(const float &vel);
459
460  /** Get an IAU-style name for an equatorial or galactic coordinates. */
461  std::string  getIAUName(double ra, double dec);
462
463  /** Correct the units for the spectral axis */
464  void    fixUnits(Param &par);
465 
466  //--------------------
467  // Functions in FitsIO/headerIO.cc
468  //
469  /** Read all header info. */
470  int     readHeaderInfo(std::string fname, Param &par);
471
472  /** Read BUNIT keyword */
473  int     readBUNIT(std::string fname);
474
475  /** Read BLANK & related keywords */
476  int     readBLANKinfo(std::string fname, Param &par);
477
478  /** Read beam-related keywords */
479  int     readBeamInfo(std::string fname, Param &par);
480 
481  //--------------------
482  // Function in FitsIO/wcsIO.cc
483  //
484  /** Read the WCS information from a file. */
485  int     defineWCS(std::string fname, Param &par);
486
487  //--------------------
488  // Basic inline accessor functions
489  //
490  bool    isWCS(){return wcsIsGood;};
491  int     getNWCS(){return nwcs;};
492  void    setNWCS(int i){nwcs=i;};
493  std::string  getSpectralUnits(){return spectralUnits;};
494  void    setSpectralUnits(std::string s){spectralUnits=s;};
495  std::string  getSpectralDescription(){return spectralDescription;};
496  void    setSpectralDescription(std::string s){spectralDescription=s;};
497  std::string  getFluxUnits(){return fluxUnits;};
498  void    setFluxUnits(std::string s){fluxUnits=s;};
499  std::string  getIntFluxUnits(){return intFluxUnits;};
500  void    setIntFluxUnits(std::string s){intFluxUnits=s;};
501  float   getBeamSize(){return beamSize;};
502  void    setBeamSize(float f){beamSize=f;};
503  float   getBmajKeyword(){return bmajKeyword;};
504  void    setBmajKeyword(float f){bmajKeyword=f;};
505  float   getBminKeyword(){return bminKeyword;};
506  void    setBminKeyword(float f){bminKeyword=f;};
507  int     getBlankKeyword(){return blankKeyword;};
508  void    setBlankKeyword(int f){blankKeyword=f;};
509  float   getBzeroKeyword(){return bzeroKeyword;};
510  void    setBzeroKeyword(float f){bzeroKeyword=f;};
511  float   getBscaleKeyword(){return bscaleKeyword;};
512  void    setBscaleKeyword(float f){bscaleKeyword=f;};
513  float   getAvPixScale(){
514    return sqrt( fabs ( (wcs->pc[0]*wcs->cdelt[0])*
515                        (wcs->pc[wcs->naxis+1]*wcs->cdelt[1])));
516  };
517
518
519private:
520  struct wcsprm *wcs;           ///< The WCS parameters for the cube in a struct from the wcslib library.
521  int     nwcs;                 ///< The number of WCS parameters
522  bool    wcsIsGood;            ///< A flag indicating whether there is a valid WCS present.
523  std::string  spectralUnits;        ///< The units of the spectral dimension
524  std::string  spectralDescription;  ///< The description of the spectral dimension (Frequency, Velocity, ...)
525  std::string  fluxUnits;            ///< The units of pixel flux (from header)
526  std::string  intFluxUnits;         ///< The units of pixel flux (from header)
527  float   beamSize;             ///< The calculated beam size in pixels.
528  float   bmajKeyword;          ///< The FITS header keyword BMAJ.
529  float   bminKeyword;          ///< The FITS header keyword BMIN.
530  int     blankKeyword;         ///< The FITS header keyword BLANK.
531  float   bzeroKeyword;         ///< The FITS header keyword BZERO.
532  float   bscaleKeyword;        ///< The FITS header keyword BSCALE.
533  double  scale;                ///< scale param for converting spectral coords
534  double  offset;               ///< offset param for converting spectral coords
535  double  power;                ///< power param for converting spectral coords
536};
537
538std::string makelower( std::string s );
539
540#endif
Note: See TracBrowser for help on using the repository browser.