Index: branches/tap_branches/psastro/src/psastroLoadRefstars.c
===================================================================
--- branches/tap_branches/psastro/src/psastroLoadRefstars.c	(revision 25900)
+++ branches/tap_branches/psastro/src/psastroLoadRefstars.c	(revision 27838)
@@ -1,5 +1,5 @@
 /** @file psastroLoadRefstars.c
  *
- *  @brief 
+ *  @brief
  *
  *  @ingroup libpsastro
@@ -50,5 +50,31 @@
         return false;
     }
+
+    // the name in the recipe may be one of:
+    // (A) the actual directory name
+    // (B) a reference to the name in the PSASTRO.CATDIRS folder in site.config
+    // (C) a reference to a folder in the PSASTRO.CATDIRS folder in site.config, containing multiple copy locations
     char *catdir_virtual = psMetadataLookupStr(&status, catdirs, catdir_recipe);
+
+    psMetadata *catdir_folder = psMetadataLookupMetadata(&status, catdirs, catdir_recipe);
+    if (catdir_folder) {
+        // randomly choose one of the entries
+        psLogMsg ("psastro", 3, "choosing catdir_folder\n");
+        int nEntry = catdir_folder->list->n;
+
+        psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS);
+        double frnd = psRandomUniform(rng);
+        int entry = PS_MIN(nEntry - 1, PS_MAX(0, nEntry * frnd));
+        psFree(rng);
+
+        psMetadataItem *item = psListGet(catdir_folder->list, entry);
+	assert (item);
+        if (item->type != PS_DATA_STRING) {
+            psError(PSASTRO_ERR_CONFIG, true, "Invalid entry in PSASTRO.CATDIR folder: %s\n", item->name);
+            return false;
+        }
+        catdir_virtual = item->data.str;
+    }
+
     char *catdir = (catdir_virtual == NULL) ? catdir_recipe : catdir_virtual;
 
@@ -56,4 +82,6 @@
     psString CATDIR = pmConfigConvertFilename(catdir, config, false, false); // Resolved filename
     PS_ASSERT (CATDIR, NULL);
+
+    psLogMsg ("psastro", 3, "looking up reference objects in %s\n", CATDIR);
 
     char *getstarCommand = psStringCopy(psMetadataLookupStr(NULL, recipe, "DVO.GETSTAR"));
@@ -106,4 +134,6 @@
     psTrace ("psastro", 3, "%s\n", getstarCommand);
 
+    psLogMsg("psastro", PS_LOG_INFO, "getstar command: %s", getstarCommand);
+
     // XXX use psPipe: catch stderr, stdout, allow for Nsec timeout...
     // use fork to add timeout capability
@@ -133,6 +163,6 @@
       // assert (outfile);
       // for (int nn = 0; nn < refstars->n; nn++) {
-      // 	  pmAstromObj *ref = refstars->data[nn];
-      // 	  fprintf (outfile, "%lf %lf\n", ref->sky->r*PS_DEG_RAD, ref->sky->d*PS_DEG_RAD);
+      //          pmAstromObj *ref = refstars->data[nn];
+      //          fprintf (outfile, "%lf %lf\n", ref->sky->r*PS_DEG_RAD, ref->sky->d*PS_DEG_RAD);
       // }
       // fclose (outfile);
@@ -190,10 +220,10 @@
             ref->sky->d   = RAD_DEG*psMetadataLookupF32 (&status, row, "DEC");
             ref->Mag      = 0.001*psMetadataLookupS32 (&status, row, "MAG");  // ELIXIR uses millimags
-	    ref->Color    = 0.0;
+            ref->Color    = 0.0;
         } else {
             ref->sky->r   = RAD_DEG*psMetadataLookupF64 (&status, row, "RA");
             ref->sky->d   = RAD_DEG*psMetadataLookupF64 (&status, row, "DEC");
             ref->Mag      = psMetadataLookupF32 (&status, row, "MAG"); // PANSTARRS uses mags
-	    ref->Color    = 0.0;
+            ref->Color    = 0.0;
         }
 
@@ -232,10 +262,10 @@
         float MagC1   = psMetadataLookupF32 (&status, row, "MAG_C1");
         float MagC2   = psMetadataLookupF32 (&status, row, "MAG_C2");
-	if (!isnan(MagC1) && !isnan(MagC2)) {
-	    ref->Color = MagC1 - MagC2;
-	} else {
-	    // XXX save the color and the slope in the table header?
-	    ref->Color = 0.0;
-	}
+        if (!isnan(MagC1) && !isnan(MagC2)) {
+            ref->Color = MagC1 - MagC2;
+        } else {
+            // XXX save the color and the slope in the table header?
+            ref->Color = 0.0;
+        }
 
         // XXX VERY temporary hack to avoid M31 bulge
