def m3_generic_tags(label): """ get values for tags found in all m3 observational products """ get_pds3 = get_from_and_apply(label) return { "{product_id}": get_pds3("PRODUCT_ID"), "{detector_temperature}": get_pds3("DETECTOR_TEMPERATURE"), "{start_time}": get_pds3("START_TIME", func=dt.datetime.isoformat), "{stop_time}": get_pds3("STOP_TIME", func=dt.datetime.isoformat), "{spacecraft_clock_start}": get_pds3("SPACECRAFT_CLOCK_START_COUNT"), "{spacecraft_clock_stop}": get_pds3("SPACECRAFT_CLOCK_STOP_COUNT"), "{orbit_number}": get_pds3("ORBIT_NUMBER"), "{instrument_mode_id}": get_pds3("INSTRUMENT_MODE_ID").capitalize(), "{swath_length}": get_pds3("CH1:SWATH_LENGTH", "value"), "{swath_width}": get_pds3("CH1:SWATH_WIDTH", "value"), "{product_creation_time}": get_pds3("PRODUCT_CREATION_TIME", func=dt.datetime.isoformat), "{software_name}": get_pds3("SOFTWARE_NAME"), "{software_version}": get_pds3("SOFTWARE_VERSION_ID"), }
def generate_tag_mapping(self): """ make a dictionary of mappings to tags in PDS4 label template. no arguments, looks for parameters in self.LABEL. """ get_pds3 = get_from_and_apply(self.LABEL) m3_info = interpret_m3_basename(self.filename) try: rfl_file_size = str(os.stat(self.sup_file).st_size) sup_file_size = str(os.stat(self.sup_file).st_size) except (AttributeError, FileNotFoundError): print("Converted FITS image files have not " + "been written yet or were not found. Using placeholder " + "9999 value for file sizes in label.") rfl_file_size = "9999" sup_file_size = "9999" # note that the RFL and SUP files have the same number # of lines and samples. l2_dictionary = { "{basename_lower}": m3_info["basename"].lower(), "{lines}": get_pds3("RFL_FILE", "RFL_IMAGE", "LINES"), "{samples}": get_pds3("RFL_FILE", "RFL_IMAGE", "LINE_SAMPLES"), "{rfl_bands}": get_pds3("RFL_FILE", "RFL_IMAGE", "BANDS"), "{rfl_file_size}": rfl_file_size, "{sup_file_size}": sup_file_size, "{rad_gain_file}": get_pds3("CH1:RAD_GAIN_FACTOR_FILE_NAME")[:-4].lower(), "{spectral_calibration_file}": get_pds3("CH1:SPECTRAL_CALIBRATION_FILE_NAME")[:-4].lower(), "{stat_pol}": get_pds3("CH1:STATISTICAL_POLISHER_FILE_NAME")[:-4].lower(), "{photo_corr}": get_pds3("CH1:PHOTOMETRY_CORR_FILE_NAME")[:-4].lower(), "{solar_spec}": get_pds3("CH1:SOLAR_SPECTRUM_FILE_NAME")[:-4].lower(), "{thermal_correction_flag}": "true" if get_pds3("CH1:THERMAL_CORRECTION_FLAG") == "Y" else "false", } generic_dictionary = m3_generic_tags(self.LABEL) orientation_dictionary = m3_orientation_tags(self.LABEL) latlon_dictionary = m3_latlon_tags(self) return merge( l2_dictionary, generic_dictionary, orientation_dictionary, latlon_dictionary, )
def clementine_edr_target_tags(label): """ map target names to context product names / lidvid references """ get_pds3 = get_from_and_apply(label) target_name = get_pds3('TARGET_NAME') target_dictionary = TARGET_TAG_MAPPING[target_name] target_based_deletions = {} if target_name == 'SKY': target_based_deletions['{delete:planetodetic}'] = True if target_name == "UNK": target_based_deletions['{delete:unknown_target}'] = True return merge(target_dictionary, target_based_deletions)
def generate_tag_mapping(self): """ make a dictionary of mappings to tags in PDS4 label template. no arguments, looks for parameters in self.LABEL. """ get_pds3 = get_from_and_apply(self.LABEL) m3_info = interpret_m3_basename(self.filename) try: obs_file_size = str(os.stat(self.obs_file).st_size) loc_file_size = str(os.stat(self.loc_file).st_size) rdn_file_size = str(os.stat(self.rdn_file).st_size) except (AttributeError, FileNotFoundError): print("Converted prefix table and/or FITS image files have not " + "been written yet or were not found. Using placeholder " + "9999 value for file sizes in label.") obs_file_size = "9999" loc_file_size = "9999" rdn_file_size = "9999" # note that the LOC, RDN, and OBS files all have the same number # of lines and samples. l1b_dictionary = { "{basename_lower}": m3_info["basename"].lower(), "{lines}": get_pds3("RDN_FILE", "RDN_IMAGE", "LINES"), "{samples}": get_pds3("RDN_FILE", "RDN_IMAGE", "LINE_SAMPLES"), "{rdn_bands}": get_pds3("RDN_FILE", "RDN_IMAGE", "BANDS"), "{rdn_file_size}": rdn_file_size, "{loc_file_size}": loc_file_size, "{obs_file_size}": obs_file_size, "{rad_gain_file}": get_pds3("CH1:RAD_GAIN_FACTOR_FILE_NAME")[:-4].lower(), "{spectral_calibration_file}": get_pds3("CH1:SPECTRAL_CALIBRATION_FILE_NAME")[:-4].lower(), } generic_dictionary = m3_generic_tags(self.LABEL) orientation_dictionary = m3_orientation_tags(self.LABEL) latlon_dictionary = m3_latlon_tags(self) return merge( l1b_dictionary, latlon_dictionary, generic_dictionary, orientation_dictionary, )
def clementine_mosaic_tags(label): """ get values for "simple" tags found in all clementine mosaic products. ( not all of these values are _used_ in all products.) """ get_pds3 = get_from_and_apply(label) generic_dictionary = {} # note that target distance has units and solar doesn't generic_dimensionless_attrs = [ # note that, unlike in the EDR PSD3 labels, # bandwidth and center wavelength are not # encoded as PVL values with units, just regular strings "bandwidth", "center_filter_wavelength", "edr_software_name", "filter_name", "frame_sequence_number", "gain_mode_id", "light_source_name", "mcp_gain_mode_id", "mission_phase_name", "offset_mode_id", "original_product_id", "producer_institution_name", "product_id", "revolution_number", "sequence_table_id", "spacecraft_solar_distance", ] for attr in generic_dimensionless_attrs: generic_dictionary["{" + attr + "}"] = get_pds3(attr.upper()) supplemental_generic_items = { "{modification_date}": dt.datetime.now().isoformat()[:-16], "{product_creation_time}": get_pds3( "PRODUCT_CREATION_TIME", func=dt.datetime.isoformat ) + "Z", } return merge(generic_dictionary, supplemental_generic_items)
def generate_tag_mapping(self): """ make a dictionary of mappings to tags in PDS4 label template. no arguments, looks for parameters in self.LABEL. """ get_pds3 = get_from_and_apply(self.LABEL) m3_info = interpret_m3_basename(self.filename) try: clock_file_size = str(os.stat(self.clock_file).st_size) fits_file_size = str(os.stat(self.fits_image_file).st_size) except (AttributeError, TypeError, FileNotFoundError): print("Converted prefix table and/or FITS image files have not " + "been written yet or were not found. Using placeholder " + "9999 value for file sizes in label.") clock_file_size = "9999" fits_file_size = "9999" l0_dictionary = { "{basename_lower}": m3_info["basename"].lower(), "{line_samples}": get_pds3("L0_FILE", "L0_IMAGE", "LINE_SAMPLES"), # in many (perhaps all) of the target-mode L0 PDS3 labels, # the line prefix tables are incorrectly specified as having # many more rows than they do, so that field can't be used to # generate new labels. "{rows}": get_pds3("L0_FILE", "L0_IMAGE", "LINES"), "{bands}": get_pds3("L0_FILE", "L0_IMAGE", "BANDS"), "{file_records}": get_pds3("L0_FILE", "FILE_RECORDS"), "{record_bytes}": get_pds3("L0_FILE", "RECORD_BYTES"), "{clock_file_size}": clock_file_size, "{fits_file_size}": fits_file_size, } generic_dictionary = m3_generic_tags(self.LABEL) if '{minimum_longitude}' in template_tags(self.template): # i.e., if it's not a 'lonely' EDR product with no reduced # friends in the archive latlon_dictionary = m3_latlon_tags(self) else: latlon_dictionary = {} return merge(l0_dictionary, generic_dictionary, latlon_dictionary)
def m3_orientation_tags(label): """ construct template tags for m3 orientation model attributes from PDS3 labels. used in L1B and L2 products """ get_pds3 = get_from_and_apply(label) # these attributes should always be present tag_dictionary = { "{spacecraft_yaw_direction}": get_pds3("CH1:SPACECRAFT_YAW_DIRECTION").capitalize(), "{orbit_limb_direction}": get_pds3("CH1:ORBIT_LIMB_DIRECTION").capitalize(), "{solar_distance}": get_pds3("SOLAR_DISTANCE", func=lambda x: str(x.value)), } # initialize blank values for all attitude-dependent tags for tag in [ "{orientation_epoch_time}", "{spacecraft_rotation_rate}", "{initial_spacecraft_orientation_tag}", "{initial_roll_tag}", "{initial_pitch_tag}", "{initial_yaw_tag}", "{close_initial_spacecraft_orientation_tag}", "{spacecraft_orientation_rates_tag}", "{roll_rate_tag}", "{pitch_rate_tag}", "{yaw_rate_tag}", "{close_spacecraft_orientation_rates_tag}", "{spacecraft_orientation_axis_vector_tag}", "{x_unit_tag}", "{y_unit_tag}", "{z_unit_tag}", "{close_spacecraft_orientation_axis_vector_tag}", "{spacecraft_orientation_tag}", "{roll_tag}", "{pitch_tag}", "{yaw_tag}", "{close_spacecraft_orientation_tag}", ]: tag_dictionary[tag] = "" # should always be present spacecraft_orientation = get_pds3("SPACECRAFT_ORIENTATION") # this variable is basically the entirety of model 1 if "N/A" not in spacecraft_orientation: # populate model 1 spacecraft_orientation = literal_eval(spacecraft_orientation) tag_dictionary[ "{spacecraft_orientation_tag}"] = "<chan1:Spacecraft_Orientation>" tag_dictionary["{roll_tag}"] = ("""<chan1:roll unit="deg">""" + str(spacecraft_orientation[0]) + "</chan1:roll>") tag_dictionary["{pitch_tag}"] = ("""<chan1:pitch unit="deg">""" + str(spacecraft_orientation[1]) + "</chan1:pitch>") tag_dictionary["{yaw_tag}"] = ("""<chan1:yaw unit="deg">""" + str(spacecraft_orientation[2]) + "</chan1:yaw>") tag_dictionary[ "{close_spacecraft_orientation_tag}"] = "</chan1:Spacecraft_Orientation>" initial_orientation = get_pds3("CH1:INITIAL_SC_ORIENTATION") if "N/A" not in initial_orientation: initial_orientation = literal_eval(initial_orientation) tag_dictionary[ "{initial_spacecraft_orientation_tag}"] = "<chan1:Initial_Spacecraft_Orientation>" tag_dictionary["{initial_roll_tag}"] = ("""<chan1:roll unit="deg">""" + str(initial_orientation[0]) + "</chan1:roll>") tag_dictionary["{initial_pitch_tag}"] = ( """<chan1:pitch unit="deg">""" + str(initial_orientation[1]) + "</chan1:pitch>") tag_dictionary["{initial_yaw_tag}"] = ("""<chan1:yaw unit="deg">""" + str(initial_orientation[2]) + "</chan1:yaw>") tag_dictionary[ "{close_initial_spacecraft_orientation_tag}"] = "</chan1:Initial_Spacecraft_Orientation>" orientation_epoch_time = get_pds3("CH1:SC_ORIENTATION_EPOCH_TDB_TIME") if "N/A" not in orientation_epoch_time: tag_dictionary["{orientation_epoch_time}"] = ( """<chan1:orientation_epoch_time unit="s">""" + orientation_epoch_time + "</chan1:orientation_epoch_time>") rotation_axis_vector = get_pds3("CH1:SC_ROTATION_AXIS_VECTOR") if "N/A" not in rotation_axis_vector: # get model 3 data. ok throwing errors here if it's not all present, # means we need to check this process. rotation_axis_vector = literal_eval(rotation_axis_vector) tag_dictionary["{spacecraft_rotation_rate}"] = ( """<chan1:spacecraft_rotation_rate unit="deg/s">""" + get_pds3("CH1:SC_ROTATION_RATE") + "</chan1:spacecraft_rotation_rate>") tag_dictionary[ "{spacecraft_orientation_axis_vector_tag}"] = "<chan1:Spacecraft_Orientation_Axis_Vector>" tag_dictionary["{x_unit_tag}"] = ("<chan1:x_unit>" + str(rotation_axis_vector[0]) + "</chan1:x_unit>") tag_dictionary["{y_unit_tag}"] = ("<chan1:y_unit>" + str(rotation_axis_vector[1]) + "</chan1:y_unit>") tag_dictionary["{z_unit_tag}"] = ("<chan1:z_unit>" + str(rotation_axis_vector[2]) + "</chan1:z_unit>") tag_dictionary[ "{close_spacecraft_orientation_axis_vector_tag}"] = "</chan1:Spacecraft_Orientation_Axis_Vector>" orientation_rate = get_pds3("CH1:SC_ORIENTATION_RATE") if "N/A" not in orientation_rate: # get model 2 data. ok throwing errors here if it's not all present, # means we need to check this process. orientation_rate = literal_eval(orientation_rate) tag_dictionary[ "{spacecraft_orientation_rates_tag}"] = "<chan1:Spacecraft_Orientation_Rates>" tag_dictionary["{roll_rate_tag}"] = ( """<chan1:roll_rate unit="deg/s">""" + str(orientation_rate[0]) + "</chan1:roll_rate>") tag_dictionary["{pitch_rate_tag}"] = ( """<chan1:pitch_rate unit="deg/s">""" + str(orientation_rate[1]) + "</chan1:pitch_rate>") tag_dictionary["{yaw_rate_tag}"] = ( """<chan1:yaw_rate unit="deg/s">""" + str(orientation_rate[2]) + "</chan1:yaw_rate>") tag_dictionary[ "{close_spacecraft_orientation_rates_tag}"] = "</chan1:Spacecraft_Orientation_Rates>" return tag_dictionary
def clementine_edr_tags(label): """ get values for "simple" tags found in all clementine EDR products. (not all of these values are _used_ in all products.) """ get_pds3 = get_from_and_apply(label) generic_dictionary = {} generic_value_attrs = [ "bandwidth", "center_dec", "center_filter_wavelength", "center_latitude", "center_longitude", "center_ra", "cryocooler_temperature", "cryocooler_duration", "declination", "emission_angle", "exposure_duration", "focal_plane_temperature", "horizontal_pixel_scale", "incidence_angle", "lens_temperature", "light_source_distance", "light_source_incidence_angle", "light_source_phase_angle", "local_hour_angle", "north_azimuth", "phase_angle", "right_ascension", "slant_distance", "smear_azimuth", "smear_magnitude", "sub_light_source_azimuth", "sub_light_source_latitude", "sub_light_source_longitude", "sub_solar_azimuth", "sub_solar_latitude", "sub_solar_longitude", "sub_spacecraft_azimuth", "sub_spacecraft_latitude", "sub_spacecraft_longitude", "target_center_distance", "twist_angle", "vertical_pixel_scale", ] # note that target distance has units and solar doesn't generic_dimensionless_attrs = [ "edr_software_name", "filter_name", "frame_sequence_number", "gain_mode_id", "light_source_name", "mcp_gain_mode_id", "mission_phase_name", "offset_mode_id", "original_product_id", "producer_institution_name", "product_id", "revolution_number", "sequence_table_id", "spacecraft_solar_distance", ] generic_image_attrs = [ "lines", "line_samples", ] for attr in generic_value_attrs: generic_dictionary["{" + attr + "}"] = get_pds3(attr.upper(), "value") for attr in generic_dimensionless_attrs: generic_dictionary["{" + attr + "}"] = get_pds3(attr.upper()) for attr in generic_image_attrs: generic_dictionary["{" + attr + "}"] = get_pds3("IMAGE", attr.upper()) # clean up items with "UNK" temperatures and such (all assigned # to non-nillable attributes in various namespaces) for attr in ["cryocooler_temperature", "focal_plane_temperature", "lens_temperature", "cryocooler_duration"]: if generic_dictionary["{" + attr + "}"] == "None": generic_dictionary["{delete:" + attr + "}"] = True if ( ("{delete:cryocooler_temperature}" in generic_dictionary) and ("{delete:focal_plane_temperature}" in generic_dictionary) and ("{delete:lens_temperature}" in generic_dictionary) ): generic_dictionary["{delete:device_temperatures}"] = True # clean up items with unknown sequence table id # (string-type attribute, retain as explicitly unknown) if generic_dictionary["{sequence_table_id}"] == "": generic_dictionary["{sequence_table_id}"] = "UNKNOWN" # clean up items with unknown filters # (these are assigned to non-nillable attributes in the img namespace) for attr in ["bandwidth", "center_filter_wavelength"]: if generic_dictionary["{" + attr + "}"] == "None": generic_dictionary["{delete:filter_values}"] = True supplemental_generic_items = { "{modification_date}": dt.datetime.now().isoformat()[:-16], "{product_creation_time}": get_pds3( "PRODUCT_CREATION_TIME", func=dt.datetime.isoformat ) + "Z", "{start_time}": get_pds3( "START_TIME", func=dt.datetime.isoformat )[:-9] + "Z", "{uncorrected_start_time}": get_pds3( "UNCORRECTED_START_TIME", func=dt.datetime.isoformat )[:-9] + "Z" } return merge(generic_dictionary, supplemental_generic_items)