def addGuideOffsets(self, cmd, plate, wavelength, pointingID, gprobes): """ Read in the new (needed for APOGEE/MARVELS) plateGuideOffsets interpolation arrays. """ # Get .par file name in the platelist product. # plates/0046XX/004671/plateGuideOffsets-004671-p1-l16600.par path = os.path.join(os.environ['PLATELIST_DIR'], 'plates', '%04dXX' % (int(plate / 100)), '%06d' % (plate), 'plateGuideOffsets-%06d-p%d-l%05d.par' % (plate, pointingID, wavelength)) if not os.path.exists(path): failMsg = ('text="no refraction corrections for ' 'plate {0} at {1:d}A"'.format(plate, wavelength)) cmd.error(failMsg) return False try: ygo = yanny.yanny(path, np=True) guideOffsets = ygo['HAOFFSETS'] cmd.inform('text="loaded guider coeffs for %dA from %s"' % (wavelength, path)) except Exception, e: cmd.error('text="failed to read plateGuideOffsets file %s: %s"' % (path, e)) return False
def get_platePlans(reload=False): """Returns a (cached) copy of platePlans.""" global PLATE_PLANS if PLATE_PLANS is None or reload: PLATE_PLANS = yanny.yanny(get_path('platePlans'), np=True)['PLATEPLANS'] return PLATE_PLANS
def __init__(self, plPlugMapFile, scanDir, cartID, fscanID, fscanMJD): self.scanDir = scanDir self.cartID = cartID self.fscanID = fscanID self.fscanMJD = fscanMJD self.plPlugMap = yanny(filename=plPlugMapFile, np=True) self.objectInds = numpy.argwhere(self.plPlugMap["PLUGMAPOBJ"]["holeType"]=="OBJECT") self.xPos = self.plPlugMap["PLUGMAPOBJ"]["xFocal"][self.objectInds].flatten() self.yPos = self.plPlugMap["PLUGMAPOBJ"]["yFocal"][self.objectInds].flatten() self.radPos = numpy.sqrt(self.xPos**2+self.yPos**2) self.plateID = int(self.plPlugMap["plateId"])
def updateHeader(self): """This is necessary because it seems calling plPlugMap.append(updateDict) erases the previously entered fiber map! WTF? """ updateDict = { "fscanMJD": int(self.fscanMJD), "fscanId": int(self.fscanID), "cartridgeId": int(self.cartID), "instruments": "APOGEE_SOUTH" } plPlugMap = yanny(filename=self.filePath, np=True) plPlugMap.append(updateDict) os.remove(self.filePath) plPlugMap.write(self.filePath)
def definition_from_id(def_id): """Returns a custom dictionary merging the defaults file with plateDefinition.""" if def_id == -1: raise ValueError('SDSS I/II plates don\'t have definition files.') custom_defs_file = get_path('plateDefinition', designid=def_id) if not custom_defs_file or not os.path.exists(custom_defs_file): raise ValueError('cannot find plateDefinition file for design_id={0}.'.format(def_id)) custom_defs = yanny.yanny(custom_defs_file) # Lowercases and removes symbols custom_defs_lower = dict((kk.lower(), vv) for kk, vv in custom_defs.items() if kk != 'symbols') # Gets defaults file assert 'platetype' in custom_defs_lower, \ '\'platetype\' not defined in {0!r}'.format(custom_defs_file) assert 'platedesignversion' in custom_defs_lower, \ '\'platedesignversion\' not defined in {0!r}'.format(custom_defs_file) defaults_file = get_path('plateDefault', type=custom_defs_lower['platetype'], version=custom_defs_lower['platedesignversion']) if not defaults_file or not os.path.exists(defaults_file): raise ValueError('cannot find plateDefaults file matching design_id={0}.'.format(def_id)) definition = yanny.yanny(defaults_file) definition_lower = dict((kk.lower(), vv) for kk, vv in definition.items() if kk != 'symbols') # Overrrides custom values in defaults definition_lower.update(custom_defs_lower) return definition_lower
def getMangaTileIDs(): """Returns a dictionary of {plateid: manga_tileid} from the plateTargets files stored in mangacore.""" mangacorePath = readPath(config['fields']['mangacore']) plateTargets = glob.glob( os.path.join(mangacorePath, 'platedesign/platetargets/plateTargets-*.par')) if len(plateTargets) == 0: raise TotoroError('no plateTargets files found.') mangaTileIDs = {} neverobserve = {} for plateTargetsFile in plateTargets: pT = yanny.yanny(plateTargetsFile, np=True)['PLTTRGT'] for target in pT: if (target['plateid'] not in mangaTileIDs and target['manga_tileid'] > 0): mangaTileIDs[target['plateid']] = target['manga_tileid'] if target['plateid'] not in neverobserve: neverobserve[target['plateid']] = target['neverobserve'] return mangaTileIDs, neverobserve
def plate_holes_db(inputs, plate_mode=False, verbose=False, overwrite=False, log=None): """Loads plateruns or plates from plateHoles into the DB. Parameters: inputs (list, tuple): A list of plateruns or plates to be ingested into the DB. plate_mode (bool): If ``True``, treats ``inputs`` as a list of plates. Otherwise assumes they are plateruns. verbose (bool): If ``True`` outputs more information in the shell log. overwrite (bool): If ``True``, values in the DB will be overwritten if needed. log (``platedesign.core.logger.Logger`` object): A ``Logger`` object to use. Otherwise it will create a new log. """ log = log or pd_log log.info('running plate_holes_db in mode={0!r}.'.format( 'platerun' if not plate_mode else 'plate')) # Checks the connection conn_status = platedb.database.connected if conn_status: log.info('database connection is open.') else: raise RuntimeError( 'cannot connect to the database. Review you connection settings.') # Creates a list of plates for each platerun and plate. plates = [] if not plate_mode: for platerun in inputs: lines = utils.get_lines_for_platerun(platerun) if len(lines) == 0: raise ValueError( 'no platePlans lines found for platerun {0!r}'.format( platerun)) plates += lines['plateid'].tolist() else: plates = inputs if len(plates) == 0: raise ValueError('no plates found. Your input parameters ' 'do not seem to match any plate.') log.info('loading plateHoles for {0} plates.'.format(len(plates))) with platedb.database.atomic(): for plate_id in plates: plate_holes_path = utils.get_path('plateHoles', plateid=plate_id) plate_holes_filename = os.path.basename(plate_holes_path) assert os.path.exists(plate_holes_path), \ 'cannot find file {0}'.format(plate_holes_path) plate_holes = yanny.yanny(plate_holes_path, np=True)['STRUCT1'] log.debug('loaded file {0}.'.format(plate_holes_filename)) try: plate_dbo = platedb.Plate.get(plate_id=plate_id) except peewee.DoesNotExist: raise ValueError('Could not find plate {0} in the database. ' 'Has the plate been added?'.format(plate_id)) # Populate the plate_holes_file table. phf_dbo, created = platedb.PlateHolesFile.get_or_create( filename=plate_holes_filename, plate_pk=plate_dbo.pk) if not created: log.debug( 'plateHoles file for plate {0} already in the database.'. format(plate_id)) else: log.debug( 'created PlateHolesFile for plate {0}'.format(plate_id)) if created or overwrite: phf_dbo.save() if len(phf_dbo.plate_holes) > 0: if not overwrite: log.debug( 'found plate holes already in the DB for plate {0}. ' 'Skipping this plate.'.format(plate_id)) continue else: warnings.warn( 'found plate holes in the DB for plate {0}. ' 'Overwriting.'.format(plate_id), UserWarning) log.debug('removing any previous plate holes for plate {0}'.format( plate_id)) ph_delete = platedb.PlateHole.delete().where( platedb.PlateHole.plate_holes_file_pk == phf_dbo.pk) ph_delete.execute() nn = 0 for plate_hole in plate_holes: ph_dbo = platedb.PlateHole() ph_dbo.plate_holes_file = phf_dbo ph_dbo.xfocal = plate_hole['xfocal'] ph_dbo.yfocal = plate_hole['yfocal'] ph_dbo.tmass_h = plate_hole['tmass_h'] ph_dbo.tmass_j = plate_hole['tmass_j'] ph_dbo.tmass_k = plate_hole['tmass_k'] ph_dbo.pointing_number = plate_hole['pointing'] ph_dbo.apogee_target1 = plate_hole['apogee2_target1'] \ if 'apogee2_target1' in plate_hole.dtype.names else None ph_dbo.apogee_target2 = plate_hole['apogee2_target2'] \ if 'apogee2_target2' in plate_hole.dtype.names else None # Populate the rest of the plate_hole table from queries. try: pht_dbo = platedb.PlateHoleType.get( label=plate_hole['holetype']) ph_dbo.plate_hole_type = pht_dbo except peewee.DoesNotExist: raise RuntimeError( 'PlateHoleType {0!r} does not appear to exist in the DB. ' 'Add it to the PlateHoleType table manually and load ' 'this plate again.'.format(plate_hole['holetype'])) try: ot_dbo = platedb.ObjectType.get( label=plate_hole['targettype']) ph_dbo.objectType = ot_dbo except peewee.DoesNotExist: raise RuntimeError( 'ObjectType {0!r} does not appear to exist in the DB. ' 'Add it to the ObjectType table manually and load ' 'this plate again.'.format(plate_hole['targettype'])) nn += 1 ph_dbo.save() log.info('loaded {0} plateHoles for plate {1}'.format( nn, plate_id))
def populate_obs_range(plates, verbose=False, log=None, ignore_missing=False): """Loads observing ranges into the DB. Parameters: plates (list, tuple): A list of plates for which to load or update the observing ranges. verbose (bool): If ``True`` outputs more information in the shell log. log (``platedesign.core.logger.Logger`` object): A ``Logger`` object to use. Otherwise it will create a new log. ignore_missing (bool): If ``True``, does not fail if a PlatePointing object cannot be found for the plate. """ log = log or pd_log # Checks the connection conn_status = platedb.database.connected if conn_status: log.debug('database connection is open.') else: raise RuntimeError('cannot connect to the database. Review you connection settings.') # values we want to read keys_to_read = ['ha_observable_min', 'ha_observable_max', 'npointings', 'pointing_name'] with platedb.database.atomic(): for plate_id in sorted(plates): log.info('loading observing ranges for plate {0}.'.format(plate_id)) pl_plugmap_p = utils.get_path('plPlugMapP', plateid=plate_id) assert os.path.exists(pl_plugmap_p), 'cannot find file {0}'.format(pl_plugmap_p) plugmap = yanny.yanny(pl_plugmap_p) for key in keys_to_read: assert key in plugmap, 'cannot find key {0} in {1}'.format(key, pl_plugmap_p) # determine the pointing number if int(plugmap['npointings']) == 1: pno = 1 else: warnings.warn('skipping plate {0} that ' 'has multiple pointings.'.format(plate_id), UserWarning) continue # select the correct value from the list ha_observable_min = float(plugmap['ha_observable_min'].split()[pno - 1]) ha_observable_max = float(plugmap['ha_observable_max'].split()[pno - 1]) # Fetch the plate_pointing object plate_pointing_dbo = platedb.PlatePointing.select().join( platedb.Plate).switch(platedb.PlatePointing).join(platedb.Pointing).where( platedb.Plate.plate_id == plate_id, platedb.Pointing.pointing_no == pno) if plate_pointing_dbo.count() == 0: if not ignore_missing: raise RuntimeError('Could not find PlatePointing for plate {0}. ' 'Has this been loaded into the db?'.format(plate_id)) else: continue elif plate_pointing_dbo.count() > 1: raise RuntimeError('Multiple plate pointings ' 'found for plate_id {0}'.format(plate_id)) plate_pointing_dbo = plate_pointing_dbo.first() if np.any(exceptions['plateid'] == plate_id): warnings.warn('plate {0}: override value used.'.format(plate_id), UserWarning) row = exceptions[exceptions['plateid'] == plate_id][0] plate_pointing_dbo.ha_observable_min = row['ha_observable_min'] plate_pointing_dbo.ha_observable_max = row['ha_observable_max'] else: plate_pointing_dbo.ha_observable_min = ha_observable_min plate_pointing_dbo.ha_observable_max = ha_observable_max plate_pointing_dbo.save()
def doPointing(plateID, pointing, fscanIDs, nGuides=16): """Creates the plPlugMapM files for a specific pointing.""" pointingName = '' if pointing == 'A' else pointing filename = os.path.join( os.environ['PLATELIST_DIR'], 'plates', '{0:06d}'.format(plateID)[:-2] + 'XX', '{0:06d}'.format(plateID), 'plPlugMapP-{0:d}{1}.par'.format(plateID, pointingName)) assert os.path.exists(filename) yannyFile = yanny.yanny(filename, np=True) rawFile = open(filename, 'r').read().splitlines() plPlugMapObj = yannyFile['PLUGMAPOBJ'] # Manually retrieves the header from the raw lines. header = [] for line in rawFile: if line.strip().startswith('typedef enum {'): break header.append(line) # Loops over fscanIDs for fscanID in fscanIDs: # Calculates the range of fiberIds that correspond to this pointing # and fscanID. pointingNum = string.uppercase.index(pointingName) preIndex = nGuides * 3 * pointingNum fiberID_range = preIndex + np.arange(1 + (fscanID - 1) * nGuides, 1 + fscanID * nGuides) outFileName = 'plPlugMapM-{0}{3}-{1}-{2:02d}.par'.format( plateID, mjd, fscanID, pointingName) # Gets a list of the holes that we should keep for this fscanID validHoles = plPlugMapObj[ (plPlugMapObj['holeType'] == 'LIGHT_TRAP') | (np.in1d(plPlugMapObj['fiberId'], fiberID_range))] # Gets the minimum fiberId greater than 0 for the valid holes. minFiberId = np.unique(np.sort(validHoles['fiberId']))[1] - 1 # Renames the fiberIds to be in the range [1, 16] validHoles['fiberId'][validHoles['fiberId'] > 0] -= minFiberId enums = { 'holeType': ['HOLETYPE', yannyFile._enum_cache['HOLETYPE']], 'objType': ['OBJTYPE', yannyFile._enum_cache['OBJTYPE']] } yanny.write_ndarray_to_yanny(outFileName, validHoles, enums=enums, structname='PLUGMAPOBJ') # Replaces the guidenums with the slice used for this file for ii, line in enumerate(header): if line.startswith('guidenums' + str(pointingNum + 1)): guides = str('guidenums' + str(pointingNum + 1)) + ' ' + \ ' '.join(map(str, np.arange(1, nGuides + 1))) header[ii] = guides break addHeader(header, outFileName, plateID, fscanID)
def makeApogeePlugMap(self, plugmap, newfilename, plate): """Return the plPlugMapM given a plateId and pointingName""" from sqlalchemy import and_ # replace the \r with \n to get yanny to parse the text properly import re data = re.sub("\r", "\n", plugmap.file) # append to the standard plPlugMap to add 2mass_style and J, H, Ks mags par = yanny.yanny() par._contents = data par._parse() p0 = par # update the definition of PLUGMAPOBJ pos = 0 for t in p0.tables(): if t == 'PLUGMAPOBJ': p0['symbols']['struct'][pos] = ( p0['symbols']['struct'][pos]).replace( 'secTarget;', 'secTarget;\n char tmass_style[30];') break else: pos += 1 p0['symbols']['PLUGMAPOBJ'].append('tmass_style') p0['PLUGMAPOBJ']['tmass_style'] = [] for i in range(p0.size('PLUGMAPOBJ')): p0['PLUGMAPOBJ']['tmass_style'].append('-') # get the needed information from the plate_hole ph = self.mysession.query(Fiber).join(PlateHole).\ filter(Fiber.pl_plugmap_m_pk==plugmap.pk).order_by(Fiber.fiber_id).\ values('fiber_id','tmass_j','tmass_h','tmass_k','apogee_target1','apogee_target2') # SDSS-V plates if (plate >= 15000): # loop through the list and update the PLUGMAPOBJ tmass_style = 'Unknown' for fid, j_mag, h_mag, k_mag, t1, t2 in ph: count = p0['PLUGMAPOBJ']['fiberId'].count(fid) if count >= 1: # we have more than one entry for this fiberId -> get the APOGEE ind = -1 for i in range(count): pos = p0['PLUGMAPOBJ']['fiberId'][ind + 1:].index(fid) ind = pos + ind + 1 if p0['PLUGMAPOBJ']['spectrographId'][ind] == 2: break # print "fid=%d t1=%d t2=%d" % (fid,t1,t2) # only modify the fibers for APOGEE (2) that are not sky fibers if p0['PLUGMAPOBJ']['spectrographId'][ind] == 2 and p0[ 'PLUGMAPOBJ']['objType'][ind] != 'SKY': if not (j_mag and h_mag and k_mag): #cmd.warn('text="some IR mags are bad: j=%s h=%s k=%s"' % (j_mag, h_mag, k_mag)) logging.warn( 'text="some IR mags are bad: j=%s h=%s k=%s"' % (j_mag, h_mag, k_mag)) p0['PLUGMAPOBJ']['mag'][ind][ 0] = j_mag if j_mag else 0.0 p0['PLUGMAPOBJ']['mag'][ind][ 1] = h_mag if h_mag else 0.0 p0['PLUGMAPOBJ']['mag'][ind][ 2] = k_mag if k_mag else 0.0 p0['PLUGMAPOBJ']['tmass_style'][ind] = tmass_style if (p0['PLUGMAPOBJ']['objType'][ind] == 'STAR_BHB'): p0['PLUGMAPOBJ']['objType'][ind] = 'STAR' elif (p0['PLUGMAPOBJ']['objType'][ind] == 'SPECTROPHOTO_STD'): p0['PLUGMAPOBJ']['objType'][ind] = 'HOT_STD' # APOGEE-1/2 plates else: # we'll use the target1 and target2 to define the type of target # these are 32 bits each with each bit indicating a type skymask = 16 hotmask = 512 extmask = 1024 starmask = skymask | hotmask # loop through the list and update the PLUGMAPOBJ tmass_style = 'Unknown' for fid, j_mag, h_mag, k_mag, t1, t2 in ph: count = p0['PLUGMAPOBJ']['fiberId'].count(fid) if count >= 1: # we have more than one entry for this fiberId -> get the APOGEE ind = -1 for i in range(count): pos = p0['PLUGMAPOBJ']['fiberId'][ind + 1:].index(fid) ind = pos + ind + 1 if p0['PLUGMAPOBJ']['spectrographId'][ind] == 2: break # print "fid=%d t1=%d t2=%d" % (fid,t1,t2) # only modify the fibers for APOGEE (2) that are not sky fibers if p0['PLUGMAPOBJ']['spectrographId'][ind] == 2 and p0[ 'PLUGMAPOBJ']['objType'][ind] != 'SKY': if not (j_mag and h_mag and k_mag): #cmd.warn('text="some IR mags are bad: j=%s h=%s k=%s"' % (j_mag, h_mag, k_mag)) logging.warn( 'text="some IR mags are bad: j=%s h=%s k=%s"' % (j_mag, h_mag, k_mag)) p0['PLUGMAPOBJ']['mag'][ind][ 0] = j_mag if j_mag else 0.0 p0['PLUGMAPOBJ']['mag'][ind][ 1] = h_mag if h_mag else 0.0 p0['PLUGMAPOBJ']['mag'][ind][ 2] = k_mag if k_mag else 0.0 p0['PLUGMAPOBJ']['tmass_style'][ind] = tmass_style if (t2 & skymask) > 0: p0['PLUGMAPOBJ']['objType'][ind] = 'SKY' elif (t2 & hotmask) > 0: p0['PLUGMAPOBJ']['objType'][ind] = 'HOT_STD' elif (t1 & extmask) > 0: p0['PLUGMAPOBJ']['objType'][ind] = 'EXTOBJ' elif (t2 & starmask) == 0 and (t1 & extmask) == 0: p0['PLUGMAPOBJ']['objType'][ind] = 'STAR' # delete file if it already exists if os.path.isfile(newfilename): os.remove(newfilename) p0.write(newfilename) # write a copy to the archive directory # define the current mjd archive directory to store the plPlugMapA file mjd = astroMJD.mjdFromPyTuple(time.gmtime()) fmjd = str(int(mjd + 0.3)) arch_dir = os.path.join(self.archive_dir, fmjd) if not os.path.isdir(arch_dir): os.mkdir(arch_dir, 0o0775) res = os.path.split(newfilename) archivefile = os.path.join(arch_dir, res[1]) p0.write(archivefile) return
def plate_addenda_db(inputs, design_mode=False, verbose=False, log=None): """Loads plateDefinitionAddendas to the DB from plateruns or designs. Parameters: inputs (list, tuple): A list of plateruns or plates to be ingested into the DB. design_mode (bool): If ``True``, treats ``inputs`` as a list of design ids. Otherwise assumes they are plateruns. verbose (bool): If ``True`` outputs more information in the shell log. log (``platedesign.core.logger.Logger`` object): A ``Logger`` object to use. Otherwise it will create a new log. """ log = log or pd_log log.info('running plate_addenda_db in mode={0!r}.'.format( 'platerun' if not design_mode else 'plate')) # Checks the connection conn_status = platedb.database.connected if conn_status: log.info('database connection is open.') else: raise RuntimeError( 'cannot connect to the database. Review you connection settings.') # Creates a list of plates for each platerun and plate. designs = [] if not design_mode: for platerun in inputs: lines = utils.get_lines_for_platerun(platerun) if len(lines) == 0: raise ValueError( 'no platePlans lines found for platerun {0!r}'.format( platerun)) designs += lines['designid'].tolist() else: designs = inputs if len(designs) == 0: raise ValueError('no designs found. Your input parameters ' 'do not seem to match any plate.') log.info('loading plateDefinitionAddenda for {0} designs.'.format( len(designs))) with platedb.database.atomic(): for design_id in designs: log.info('loading plateDefinitionAddenda for design {0}'.format( design_id)) plate_definition_path = utils.get_path('plateDefinitionAddenda', designid=design_id) if not os.path.exists(plate_definition_path): warnings.warn( 'cannot find a plateDefinitionAddenda ' 'for design {0}. Skipping it.'.format(design_id), UserWarning) continue definition = yanny.yanny(plate_definition_path) definition_lower = dict((kk.lower(), vv) for kk, vv in definition.items() if kk != 'symbols') # Fetch design try: design_dbo = platedb.Design.get(pk=design_id) except peewee.DoesNotExist: raise RuntimeError( 'the design {0} cannot be found in the DB. ' 'Make sure you have loaded it first.'.format(design_id)) for key in definition_lower: field_name = key value = definition_lower[key] # Gets or creates the field object design_field_dbo, created = platedb.DesignField.get_or_create( label=field_name) if created: warnings.warn( 'design_id={0}: the design field {1} was not found. Adding it.' .format(design_id, field_name), UserWarning) # Check if there is an existing value with this key design_value_dbo = platedb.DesignValue.select().where( platedb.DesignValue.design_pk == design_dbo.pk, platedb.DesignValue.design_field_pk == design_field_dbo.pk).first() if design_value_dbo is None: # Create a new value design_value_dbo = platedb.DesignValue() design_value_dbo.design_field_pk = design_field_dbo.pk design_value_dbo.design_pk = design_dbo.pk log.debug( 'design_id={0}: adding new (field, value)=({1!r}, {2!r}).' .format(design_id, design_value_dbo.field.label, value)) # Updates the value from the plateDefinitionAddenda value design_value_dbo.value = value design_field_dbo.save() design_value_dbo.save()
def create_plPlugMapM_LCO(plateID, pointing, field, mjd, lookupTable=None, fscanId=1): """Converts the plPlugMapP files for a `plateID` into a plPlugMapM. This scripts converts the plPlugMapP files for a `plateID` into a plPlugMapM given a lookup table that simulates a mapping. Each guider commissioning plate contains four pointings, each with 3 sets of 16 guiding stars (fields). """ lookupArray = getLookupArray(lookupTable) pointingName = '' if pointing == 'A' else pointing filename = os.path.join( os.environ['PLATELIST_DIR'], 'plates', '{0:06d}'.format(plateID)[:-2] + 'XX', '{0:06d}'.format(plateID), 'plPlugMapP-{0:d}{1}.par'.format(plateID, pointingName)) assert os.path.exists(filename) yannyFile = yanny.yanny(filename, np=True) rawFile = open(filename, 'r').read().splitlines() plPlugMapObj = yannyFile['PLUGMAPOBJ'] # Manually retrieves the header from the raw lines. header = [] for line in rawFile: if line.strip().startswith('typedef enum {'): break header.append(line) # Calculates the range of fiberIds that correspond to this pointing # and fscanID. pointingNum = string.uppercase.index(pointingName) preIndex = nGuides * 3 * pointingNum fiberID_range = preIndex + np.arange(1 + (field - 1) * nGuides, 1 + field * nGuides) print(fiberID_range) outFileName = 'plPlugMapM-{0}{3}-{1}-{2:02d}_{4}.par'.format( plateID, mjd, fscanId, pointingName, colourDict[field]) # Gets a list of the holes that we should keep for this fscanID validHoles = plPlugMapObj[(plPlugMapObj['holeType'] == 'LIGHT_TRAP') | (np.in1d(plPlugMapObj['fiberId'], fiberID_range))] lightTraps = validHoles[validHoles['holeType'] == 'LIGHT_TRAP'] guides = validHoles[validHoles['holeType'] == 'GUIDE'] alignments = validHoles[validHoles['holeType'] == 'ALIGNMENT'] guides = guides[lookupArray[:, 1] - 1] guides['fiberId'] = lookupArray[:, 0] sortedPlPlugMapM = np.concatenate((lightTraps, alignments, guides)) enums = {'holeType': ['HOLETYPE', yannyFile._enum_cache['HOLETYPE']], 'objType': ['OBJTYPE', yannyFile._enum_cache['OBJTYPE']]} yanny.write_ndarray_to_yanny(outFileName, sortedPlPlugMapM, enums=enums, structname='PLUGMAPOBJ') # Replaces the guidenums with the slice used for this file for ii, line in enumerate(header): if line.startswith('guidenums' + str(pointingNum + 1)): guides = str('guidenums' + str(pointingNum + 1)) + ' ' + \ ' '.join(map(str, np.arange(1, nGuides + 1))) header[ii] = guides break addHeader(header, outFileName, plateID, fscanId, field, mjd, colourDict[field]) return