def get_fieldname_pyart(datatype):
    """
    maps the config file radar data type name into the corresponding rainbow
    Py-ART field name

    Parameters
    ----------
    datatype : str
        config file radar data type name

    Returns
    -------
    field_name : str
        Py-ART field name

    """
    if datatype == 'dBZ':
        field_name = 'reflectivity'
    elif datatype == 'dBuZ':
        field_name = 'unfiltered_reflectivity'
    elif datatype == 'dBZc':
        field_name = 'corrected_reflectivity'
    elif datatype == 'dBuZc':
        field_name = 'corrected_unfiltered_reflectivity'
    elif datatype == 'dBZv':
        field_name = 'reflectivity_vv'
    elif datatype == 'dBZvc':
        field_name = 'corrected_reflectivity_vv'
    elif datatype == 'dBuZv':
        field_name = 'unfiltered_reflectivity_vv'
    elif datatype == 'dBuZvc':
        field_name = 'corrected_unfiltered_reflectivity_vv'
    elif datatype == 'dBZ_bias':
        field_name = 'reflectivity_bias'
    elif datatype == 'eta_h':
        field_name = 'volumetric_reflectivity'
    elif datatype == 'eta_v':
        field_name = 'volumetric_reflectivity_vv'
    elif datatype == 'rcs_h':
        field_name = 'radar_cross_section_hh'
    elif datatype == 'rcs_v':
        field_name = 'radar_cross_section_vv'
    elif datatype == 'ZDR':
        field_name = 'differential_reflectivity'
    elif datatype == 'ZDRu':
        field_name = 'unfiltered_differential_reflectivity'
    elif datatype == 'ZDRc':
        field_name = 'corrected_differential_reflectivity'
    elif datatype == 'ZDRuc':
        field_name = 'corrected_unfiltered_differential_reflectivity'
    elif datatype == 'ZDR_prec':
        field_name = 'differential_reflectivity_in_precipitation'
    elif datatype == 'ZDR_snow':
        field_name = 'differential_reflectivity_in_snow'
    elif datatype == 'ZDR_col':
        field_name = 'differential_reflectivity_column_height'
    elif datatype == 'dBm':
        field_name = 'signal_power_hh'
    elif datatype == 'dBmv':
        field_name = 'signal_power_vv'
    elif datatype == 'Nh':
        field_name = 'noisedBZ_hh'
    elif datatype == 'Nv':
        field_name = 'noisedBZ_vv'
    elif datatype == 'NdBADUh':
        field_name = 'noisedBADU_hh'
    elif datatype == 'NdBADUv':
        field_name = 'noisedBADU_vv'
    elif datatype == 'NdBmh':
        field_name = 'noisedBm_hh'
    elif datatype == 'NdBmv':
        field_name = 'noisedBm_vv'
    elif datatype == 'NADUh':
        field_name = 'noiseADU_hh'
    elif datatype == 'NADUv':
        field_name = 'noiseADU_vv'
    elif datatype == 'noise_pos_h':
        field_name = 'noise_pos_h'
    elif datatype == 'noise_pos_v':
        field_name = 'noise_pos_v'
    elif datatype == 'WBN':
        field_name = 'wide_band_noise'
    elif datatype == 'WBNc':
        field_name = 'corrected_wide_band_noise'
    elif datatype == 'ST1':
        field_name = 'stat_test_lag1'
    elif datatype == 'ST1c':
        field_name = 'corrected_stat_test_lag1'
    elif datatype == 'ST2':
        field_name = 'stat_test_lag2'
    elif datatype == 'ST2c':
        field_name = 'corrected_stat_test_lag2'
    elif datatype == 'TXh':
        field_name = 'transmitted_signal_power_h'
    elif datatype == 'TXv':
        field_name = 'transmitted_signal_power_v'
    elif datatype == 'SNRh':
        field_name = 'signal_to_noise_ratio_hh'
    elif datatype == 'SNRv':
        field_name = 'signal_to_noise_ratio_vv'
    elif datatype == 'CCORh':
        field_name = 'clutter_correction_ratio_hh'
    elif datatype == 'CCORv':
        field_name = 'clutter_correction_ratio_vv'
    elif datatype == 'dBm_sun_hit':
        field_name = 'sun_hit_power_h'
    elif datatype == 'dBmv_sun_hit':
        field_name = 'sun_hit_power_v'
    elif datatype == 'ZDR_sun_hit':
        field_name = 'sun_hit_differential_reflectivity'
    elif datatype == 'dBm_sun_est':
        field_name = 'sun_est_power_h'
    elif datatype == 'dBmv_sun_est':
        field_name = 'sun_est_power_v'
    elif datatype == 'ZDR_sun_est':
        field_name = 'sun_est_differential_reflectivity'
    elif datatype == 'sun_pos_h':
        field_name = 'sun_hit_h'
    elif datatype == 'sun_pos_v':
        field_name = 'sun_hit_v'
    elif datatype == 'sun_pos_zdr':
        field_name = 'sun_hit_zdr'
    elif datatype == 'RhoHV':
        field_name = 'cross_correlation_ratio'
    elif datatype == 'RhoHVu':
        field_name = 'unfiltered_cross_correlation_ratio'
    elif datatype == 'uRhoHV':
        field_name = 'uncorrected_cross_correlation_ratio'
    elif datatype == 'RhoHVc':
        field_name = 'corrected_cross_correlation_ratio'
    elif datatype == 'RhoHV_rain':
        field_name = 'cross_correlation_ratio_in_rain'
    elif datatype == 'L':
        field_name = 'logarithmic_cross_correlation_ratio'
    elif datatype == 'CDR':
        field_name = 'circular_depolarization_ratio'
    elif datatype == 'PhiDP':
        field_name = 'differential_phase'
    elif datatype == 'uPhiDPu':
        field_name = 'uncorrected_unfiltered_differential_phase'
    elif datatype == 'uPhiDP':
        field_name = 'uncorrected_differential_phase'
    elif datatype == 'PhiDPc':
        field_name = 'corrected_differential_phase'
    elif datatype == 'PhiDP0':
        field_name = 'system_differential_phase'
    elif datatype == 'PhiDP0_bin':
        field_name = 'first_gate_differential_phase'
    elif datatype == 'KDP':
        field_name = 'specific_differential_phase'
    elif datatype == 'uKDP':
        field_name = 'uncorrected_specific_differential_phase'
    elif datatype == 'KDPc':
        field_name = 'corrected_specific_differential_phase'
    elif datatype == 'MPH':
        field_name = 'mean_phase'
    elif datatype == 'MPHc':
        field_name = 'corrected_mean_phase'
    elif datatype == 'V':
        field_name = 'velocity'
    elif datatype == 'Vu':
        field_name = 'unfiltered_velocity'
    elif datatype == 'dealV':
        field_name = 'dealiased_velocity'
    elif datatype == 'Vc':
        field_name = 'corrected_velocity'
    elif datatype == 'dealVc':
        field_name = 'dealiased_corrected_velocity'
    elif datatype == 'estV':
        field_name = 'retrieved_velocity'
    elif datatype == 'stdV':
        field_name = 'retrieved_velocity_std'
    elif datatype == 'diffV':
        field_name = 'velocity_difference'
    elif datatype == 'W':
        field_name = 'spectrum_width'
    elif datatype == 'Wu':
        field_name = 'unfiltered_spectrum_width'
    elif datatype == 'Wc':
        field_name = 'corrected_spectrum_width'
    elif datatype == 'wind_vel_h_az':
        field_name = 'azimuthal_horizontal_wind_component'
    elif datatype == 'wind_vel_v':
        field_name = 'vertical_wind_component'
    elif datatype == 'wind_vel_h_u':
        field_name = 'eastward_wind_component'
    elif datatype == 'wind_vel_h_v':
        field_name = 'northward_wind_component'
    elif datatype == 'windshear_v':
        field_name = 'vertical_wind_shear'
    elif datatype == 'WIND_SPEED':
        field_name = 'wind_speed'
    elif datatype == 'WIND_DIRECTION':
        field_name = 'wind_direction'
    elif datatype == 'EDR':
        field_name = 'turbulence'
    elif datatype == 'Ah':
        field_name = 'specific_attenuation'
    elif datatype == 'Ahc':
        field_name = 'corrected_specific_attenuation'
    elif datatype == 'PIA':
        field_name = 'path_integrated_attenuation'
    elif datatype == 'PIAc':
        field_name = 'corrected_path_integrated_attenuation'
    elif datatype == 'Adp':
        field_name = 'specific_differential_attenuation'
    elif datatype == 'Adpc':
        field_name = 'corrected_specific_differential_attenuation'
    elif datatype == 'PIDA':
        field_name = 'path_integrated_differential_attenuation'
    elif datatype == 'PIDAc':
        field_name = 'corrected_path_integrated_differential_attenuation'
    elif datatype == 'TEMP':
        field_name = 'temperature'
    elif datatype == 'ISO0':
        field_name = 'iso0'
    elif datatype == 'H_ISO0':
        field_name = 'height_over_iso0'
    elif datatype == 'HZT':
        field_name = 'iso0_height'
    elif datatype == 'cosmo_index':
        field_name = 'cosmo_index'
    elif datatype == 'hzt_index':
        field_name = 'hzt_index'
    elif datatype == 'ml':
        field_name = 'melting_layer'
    elif datatype == 'VIS':
        field_name = 'visibility'
    elif datatype == 'minvisel':
        field_name = 'minimum_visible_elevation'
    elif datatype == 'minvisalt':
        field_name = 'minimum_visible_altitude'
    elif datatype == 'echoID':
        field_name = 'radar_echo_id'
    elif datatype == 'CLT':
        field_name = 'clutter_exit_code'
    elif datatype == 'occurrence':
        field_name = 'occurrence'
    elif datatype == 'freq_occu':
        field_name = 'frequency_of_occurrence'
    elif datatype == 'RR':
        field_name = 'radar_estimated_rain_rate'
    elif datatype == 'RRc':
        field_name = 'corrected_radar_estimated_rain_rate'
    elif datatype == 'Raccu':
        field_name = 'rainfall_accumulation'
    elif datatype == 'hydro':
        field_name = 'radar_echo_classification'
    elif datatype == 'hydroc':
        field_name = 'corrected_radar_echo_classification'
    elif datatype == 'entropy':
        field_name = 'hydroclass_entropy'
    elif datatype == 'propAG':
        field_name = 'proportion_AG'
    elif datatype == 'propCR':
        field_name = 'proportion_CR'
    elif datatype == 'propLR':
        field_name = 'proportion_LR'
    elif datatype == 'propRP':
        field_name = 'proportion_RP'
    elif datatype == 'propRN':
        field_name = 'proportion_RN'
    elif datatype == 'propVI':
        field_name = 'proportion_VI'
    elif datatype == 'propWS':
        field_name = 'proportion_WS'
    elif datatype == 'propMH':
        field_name = 'proportion_MH'
    elif datatype == 'propIH':
        field_name = 'proportion_IH'
    elif datatype == 'time_avg_flag':
        field_name = 'time_avg_flag'
    elif datatype == 'colocated_gates':
        field_name = 'colocated_gates'
    elif datatype == 'nsamples':
        field_name = 'number_of_samples'
    elif datatype == 'bird_density':
        field_name = 'bird_density'
    elif datatype == 'std':
        field_name = 'standard_deviation'
    elif datatype == 'sum':
        field_name = 'sum'
    elif datatype == 'sum2':
        field_name = 'sum_squared'
    elif datatype == 'diff':
        field_name = 'fields_difference'
    elif datatype == 'ShhADU':
        field_name = 'complex_spectra_hh_ADU'
    elif datatype == 'ShhADUu':
        field_name = 'unfiltered_complex_spectra_hh_ADU'
    elif datatype == 'SvvADU':
        field_name = 'complex_spectra_vv_ADU'
    elif datatype == 'SvvADUu':
        field_name = 'unfiltered_complex_spectra_vv_ADU'
    elif datatype == 'sPhhADU':
        field_name = 'spectral_power_hh_ADU'
    elif datatype == 'sPhhADUu':
        field_name = 'unfiltered_spectral_power_hh_ADU'
    elif datatype == 'sPvvADU':
        field_name = 'spectral_power_vv_ADU'
    elif datatype == 'sPvvADUu':
        field_name = 'unfiltered_spectral_power_vv_ADU'
    elif datatype == 'sPhhdBADU':
        field_name = 'spectral_power_hh_dBADU'
    elif datatype == 'sPhhdBADUu':
        field_name = 'unfiltered_spectral_power_hh_dBADU'
    elif datatype == 'sPvvdBADU':
        field_name = 'spectral_power_vv_dBADU'
    elif datatype == 'sPvvdBADUu':
        field_name = 'unfiltered_spectral_power_vv_dBADU'
    elif datatype == 'sPhhdBm':
        field_name = 'spectral_power_hh_dBm'
    elif datatype == 'sPhhdBmu':
        field_name = 'unfiltered_spectral_power_hh_dBm'
    elif datatype == 'sPvvdBm':
        field_name = 'spectral_power_vv_dBm'
    elif datatype == 'sPvvdBmu':
        field_name = 'unfiltered_spectral_power_vv_dBm'
    elif datatype == 'sNh':
        field_name = 'spectral_noise_power_hh_dBZ'
    elif datatype == 'sNv':
        field_name = 'spectral_noise_power_vv_dBZ'
    elif datatype == 'sNdBADUh':
        field_name = 'spectral_noise_power_hh_dBADU'
    elif datatype == 'sNdBADUv':
        field_name = 'spectral_noise_power_vv_dBADU'
    elif datatype == 'sNdBmh':
        field_name = 'spectral_noise_power_hh_dBm'
    elif datatype == 'sNdBmv':
        field_name = 'spectral_noise_power_vv_dBm'
    elif datatype == 'sNADUh':
        field_name = 'spectral_noise_power_hh_ADU'
    elif datatype == 'sNADUv':
        field_name = 'spectral_noise_power_vv_ADU'
    elif datatype == 'sPhasehh':
        field_name = 'spectral_phase_hh'
    elif datatype == 'sPhasehhu':
        field_name = 'unfiltered_spectral_phase_hh'
    elif datatype == 'sPhasevv':
        field_name = 'spectral_phase_vv'
    elif datatype == 'sPhasevvu':
        field_name = 'unfiltered_spectral_phase_vv'
    elif datatype == 'sdBZ':
        field_name = 'spectral_reflectivity_hh'
    elif datatype == 'sdBuZ':
        field_name = 'unfiltered_spectral_reflectivity_hh'
    elif datatype == 'sdBZv':
        field_name = 'spectral_reflectivity_vv'
    elif datatype == 'sdBuZv':
        field_name = 'unfiltered_spectral_reflectivity_vv'
    elif datatype == 'sZDR':
        field_name = 'spectral_differential_reflectivity'
    elif datatype == 'sZDRu':
        field_name = 'unfiltered_spectral_differential_reflectivity'
    elif datatype == 'sPhiDP':
        field_name = 'spectral_differential_phase'
    elif datatype == 'sPhiDPu':
        field_name = 'unfiltered_spectral_differential_phase'
    elif datatype == 'sRhoHV':
        field_name = 'spectral_copolar_correlation_coefficient'
    elif datatype == 'sRhoHVu':
        field_name = 'unfiltered_spectral_copolar_correlation_coefficient'
    elif datatype == 'IQhhADU':
        field_name = 'IQ_hh_ADU'
    elif datatype == 'IQvvADU':
        field_name = 'IQ_vv_ADU'
    elif datatype == 'IQNh':
        field_name = 'IQ_noise_power_hh_dBZ'
    elif datatype == 'IQNv':
        field_name = 'IQ_noise_power_vv_dBZ'
    elif datatype == 'IQNdBADUh':
        field_name = 'IQ_noise_power_hh_dBADU'
    elif datatype == 'IQNdBADUv':
        field_name = 'IQ_noise_power_vv_dBADU'
    elif datatype == 'IQNdBmh':
        field_name = 'IQ_noise_power_hh_dBm'
    elif datatype == 'IQNdBmv':
        field_name = 'IQ_noise_power_vv_dBm'
    elif datatype == 'IQNADUh':
        field_name = 'IQ_noise_power_hh_ADU'
    elif datatype == 'IQNADUv':
        field_name = 'IQ_noise_power_vv_ADU'
    elif datatype == 'POH':
        field_name = 'probability_of_hail'
    elif datatype == 'VIL':
        field_name = 'vertically_integrated_liquid'
    elif datatype == 'ETOP15':
        field_name = 'echo_top_15dBZ'
    elif datatype == 'ETOP20':
        field_name = 'echo_top_20dBZ'
    elif datatype == 'ETOP45':
        field_name = 'echo_top_45dBZ'
    elif datatype == 'ETOP50':
        field_name = 'echo_top_50dBZ'
    elif datatype == 'MAXECHO':
        field_name = 'maximum_echo'
    elif datatype == 'HMAXECHO':
        field_name = 'maximum_echo_height'
    elif datatype == 'AZC01':
        field_name = 'rainfall_accumulation'
    elif datatype == 'AZC03':
        field_name = 'rainfall_accumulation'
    elif datatype == 'AZC06':
        field_name = 'rainfall_accumulation'
    elif datatype == 'aZC01':
        field_name = 'rainfall_accumulation'
    elif datatype == 'aZC03':
        field_name = 'rainfall_accumulation'
    elif datatype == 'aZC06':
        field_name = 'rainfall_accumulation'
    elif datatype == 'CPC0005':
        field_name = 'radar_estimated_rain_rate'
    elif datatype == 'CPC0060':
        field_name = 'rainfall_accumulation'
    elif datatype == 'CPC0180':
        field_name = 'rainfall_accumulation'
    elif datatype == 'CPC0360':
        field_name = 'rainfall_accumulation'
    elif datatype == 'CPC0720':
        field_name = 'rainfall_accumulation'
    elif datatype == 'CPC1440':
        field_name = 'rainfall_accumulation'
    elif datatype == 'CPC2880':
        field_name = 'rainfall_accumulation'
    elif datatype == 'CPC4320':
        field_name = 'rainfall_accumulation'
    elif datatype == 'CPCH0005':
        field_name = 'radar_estimated_rain_rate'
    elif datatype == 'CPCH0060':
        field_name = 'rainfall_accumulation'
    elif datatype == 'CPCH0180':
        field_name = 'rainfall_accumulation'
    elif datatype == 'CPCH0360':
        field_name = 'rainfall_accumulation'
    elif datatype == 'CPCH0720':
        field_name = 'rainfall_accumulation'
    elif datatype == 'CPCH1440':
        field_name = 'rainfall_accumulation'
    elif datatype == 'CPCH2880':
        field_name = 'rainfall_accumulation'
    elif datatype == 'CPCH4320':
        field_name = 'rainfall_accumulation'
    elif datatype == 'nowpal60_P60':
        field_name = 'rainfall_accumulation'
    elif datatype == 'nowpal90_P90':
        field_name = 'rainfall_accumulation'
    elif datatype == 'nowpal180_P180':
        field_name = 'rainfall_accumulation'
    elif datatype == 'nowpal360_P360':
        field_name = 'rainfall_accumulation'
    elif datatype == 'nowpal720_P720':
        field_name = 'rainfall_accumulation'
    elif datatype == 'nowpal90_P30':
        field_name = 'rainfall_accumulation'
    elif datatype == 'nowpal90_P30_F60':
        field_name = 'rainfall_accumulation'
    elif datatype == 'nowpal90_F60':
        field_name = 'rainfall_accumulation'
    elif datatype == 'nowpal180_P60':
        field_name = 'rainfall_accumulation'
    elif datatype == 'nowpal180_P60_F120':
        field_name = 'rainfall_accumulation'
    elif datatype == 'nowpal180_F120':
        field_name = 'rainfall_accumulation'
    elif datatype == 'nowpal360_P120':
        field_name = 'rainfall_accumulation'
    elif datatype == 'nowpal360_P120_F240':
        field_name = 'rainfall_accumulation'
    elif datatype == 'nowpal360_F240':
        field_name = 'rainfall_accumulation'
    elif datatype == 'nowpal720_P360':
        field_name = 'rainfall_accumulation'
    elif datatype == 'nowpal720_P360_F360':
        field_name = 'rainfall_accumulation'
    elif datatype == 'nowpal720_F360':
        field_name = 'rainfall_accumulation'
    elif datatype == 'dACC':
        field_name = 'rainfall_accumulation'
    elif datatype == 'dACCH':
        field_name = 'rainfall_accumulation'
    elif datatype == 'dARC':
        field_name = 'rainfall_accumulation'
    elif datatype == 'RZC':
        field_name = 'radar_estimated_rain_rate'
    elif datatype == 'R1F':
        field_name = 'radar_estimated_rain_rate'
    elif datatype == 'rZC':
        field_name = 'radar_estimated_rain_rate'
    elif datatype == 'RZF':
        field_name = 'radar_estimated_rain_rate'
    elif datatype == 'dRZC':
        field_name = 'radar_estimated_rain_rate'
    elif datatype == 'BZC':
        field_name = 'probability_of_hail'
    elif datatype == 'dBZC':
        field_name = 'probability_of_hail'
    elif datatype == 'MZC':
        field_name = 'maximum_expected_severe_hail_size'
    elif datatype == 'dMZC':
        field_name = 'maximum_expected_severe_hail_size'
    elif datatype == 'GZC':
        field_name = 'probability_of_hail'
    elif datatype == 'dGZC':
        field_name = 'probability_of_hail'
    elif datatype == 'CZC':
        field_name = 'maximum_echo'
    elif datatype == 'dCZC':
        field_name = 'maximum_echo'
    elif datatype == 'HZC':
        field_name = 'maximum_echo_height'
    elif datatype == 'EZC15':
        field_name = 'echo_top_15dBz'
    elif datatype == 'EZC20':
        field_name = 'echo_top_20dBz'
    elif datatype == 'EZC45':
        field_name = 'echo_top_45dBz'
    elif datatype == 'EZC50':
        field_name = 'echo_top_50dBz'
    elif datatype == 'dEZC15':
        field_name = 'echo_top_15dBZ'
    elif datatype == 'dEZC20':
        field_name = 'echo_top_20dBz'
    elif datatype == 'dEZC45':
        field_name = 'echo_top_45dBz'
    elif datatype == 'dEZC50':
        field_name = 'echo_top_50dBz'
    elif datatype == 'LZC':
        field_name = 'vertically_integrated_liquid'
    elif datatype == 'dLZC':
        field_name = 'vertically_integrated_liquid'
    elif datatype == 'OZC01':
        field_name = 'reflectivity'
    elif datatype == 'OZC02':
        field_name = 'reflectivity'
    elif datatype == 'OZC03':
        field_name = 'reflectivity'
    elif datatype == 'OZC04':
        field_name = 'reflectivity'
    elif datatype == 'OZC05':
        field_name = 'reflectivity'
    elif datatype == 'OZC06':
        field_name = 'reflectivity'
    elif datatype == 'OZC07':
        field_name = 'reflectivity'
    elif datatype == 'OZC08':
        field_name = 'reflectivity'
    elif datatype == 'OZC09':
        field_name = 'reflectivity'
    elif datatype == 'OZC10':
        field_name = 'reflectivity'
    elif datatype == 'OZC11':
        field_name = 'reflectivity'
    elif datatype == 'OZC12':
        field_name = 'reflectivity'
    elif datatype == 'OZC13':
        field_name = 'reflectivity'
    elif datatype == 'OZC14':
        field_name = 'reflectivity'
    elif datatype == 'OZC15':
        field_name = 'reflectivity'
    elif datatype == 'OZC16':
        field_name = 'reflectivity'
    elif datatype == 'OZC17':
        field_name = 'reflectivity'
    elif datatype == 'OZC18':
        field_name = 'reflectivity'
    elif datatype == 'ff':
        field_name = 'wind_speed'
    elif datatype == 'dd':
        field_name = 'wind_direction'
    elif datatype == 'u':
        field_name = 'eastward_wind_component'
    elif datatype == 'v':
        field_name = 'northward_wind_component'
    elif datatype == 'w':
        field_name = 'vertical_wind_component'
    elif datatype == 'width':
        field_name = 'height_resolution'
    elif datatype == 'gap':
        field_name = 'gap'
    elif datatype == 'dbz':
        field_name = 'bird_reflectivity'
    elif datatype == 'eta':
        field_name = 'volumetric_reflectivity'
    elif datatype == 'dens':
        field_name = 'bird_density'
    elif datatype == 'n':
        field_name = 'number_of_samples_velocity'
    elif datatype == 'n_dbz':
        field_name = 'number_of_samples_reflectivity'
    elif datatype == 'sd_vvp':
        field_name = 'retrieved_velocity_std'
    elif datatype == 'DBZH':
        field_name = 'reflectivity'
    elif datatype == 'n_all':
        field_name = 'number_of_samples_velocity_all'
    elif datatype == 'n_dbz_all':
        field_name = 'number_of_samples_reflectivity_all'
    elif datatype == 'wind_vel_rad':
        field_name = 'radial_wind_speed'
    elif datatype == 'wind_vel_rad_ci':
        field_name = 'radial_wind_speed_ci'
    elif datatype == 'wind_vel_rad_status':
        field_name = 'radial_wind_speed_status'
    elif datatype == 'WD':
        field_name = 'doppler_spectrum_width'
    elif datatype == 'WD_err':
        field_name = 'doppler_spectrum_mean_error'
    elif datatype == 'atmos_type':
        field_name = 'atmospherical_structures_type'
    elif datatype == 'beta_rel':
        field_name = 'relative_beta'
    elif datatype == 'beta_abs':
        field_name = 'absolute_beta'
    elif datatype == 'CNR':
        field_name = 'cnr'
    elif datatype == 'SNR':
        field_name = 'SNR'
    elif datatype == 'VEL':
        field_name = 'VEL'
    elif datatype == 'RMS':
        field_name = 'RMS'
    elif datatype == 'LDR':
        field_name = 'LDR'
    elif datatype == 'NPK':
        field_name = 'NPK'
    elif datatype == 'SNRgc':
        field_name = 'SNRgc'
    elif datatype == 'VELgc':
        field_name = 'VELgc'
    elif datatype == 'RMSgc':
        field_name = 'RMSgc'
    elif datatype == 'LDRgc':
        field_name = 'LDRgc'
    elif datatype == 'NPKgc':
        field_name = 'NPKgc'
    elif datatype == 'SNRg':
        field_name = 'SNRg'
    elif datatype == 'VELg':
        field_name = 'VELg'
    elif datatype == 'RMSg':
        field_name = 'RMSg'
    elif datatype == 'LDRg':
        field_name = 'LDRg'
    elif datatype == 'NPKg':
        field_name = 'NPKg'
    elif datatype == 'SNRplank':
        field_name = 'SNRplank'
    elif datatype == 'VELplank':
        field_name = 'VELplank'
    elif datatype == 'RMSplank':
        field_name = 'RMSplank'
    elif datatype == 'LDRplank':
        field_name = 'LDRplank'
    elif datatype == 'NPKplank':
        field_name = 'NPKplank'
    elif datatype == 'SNRrain':
        field_name = 'SNRrain'
    elif datatype == 'VELrain':
        field_name = 'VELrain'
    elif datatype == 'RMSrain':
        field_name = 'RMSrain'
    elif datatype == 'LDRrain':
        field_name = 'LDRrain'
    elif datatype == 'NPKrain':
        field_name = 'NPKrain'
    elif datatype == 'SNRcl':
        field_name = 'SNRcl'
    elif datatype == 'VELcl':
        field_name = 'VELcl'
    elif datatype == 'RMScl':
        field_name = 'RMScl'
    elif datatype == 'LDRcl':
        field_name = 'LDRcl'
    elif datatype == 'NPKcl':
        field_name = 'NPKcl'
    elif datatype == 'SNRice':
        field_name = 'SNRice'
    elif datatype == 'VELice':
        field_name = 'VELice'
    elif datatype == 'RMSice':
        field_name = 'RMSice'
    elif datatype == 'LDRice':
        field_name = 'LDRice'
    elif datatype == 'NPKice':
        field_name = 'NPKice'
    elif datatype == 'RHO':
        field_name = 'RHO'
    elif datatype == 'DPS':
        field_name = 'DPS'
    elif datatype == 'LDRnormal':
        field_name = 'LDRnormal'
    elif datatype == 'RHOwav':
        field_name = 'RHOwav'
    elif datatype == 'DPSwav':
        field_name = 'DPSwav'
    elif datatype == 'SKWg':
        field_name = 'SKWg'
    elif datatype == 'HSDco':
        field_name = 'HSDco'
    elif datatype == 'HSDcx':
        field_name = 'HSDcx'
    elif datatype == 'Ze':
        field_name = 'Ze'
    elif datatype == 'Zg':
        field_name = 'Zg'
    elif datatype == 'Z':
        field_name = 'Z'
    elif datatype == 'RRcr':
        field_name = 'RR'
    elif datatype == 'LWCcr':
        field_name = 'LWC'
    elif datatype == 'TEMPcr':
        field_name = 'TEMP'
    elif datatype == 'ISDRco':
        field_name = 'ISDRco'
    elif datatype == 'ISDRcx':
        field_name = 'ISDRcx'
    elif datatype == 'SNRcx':
        field_name = 'SNRcx'
    elif datatype == 'SNRCorFaCo':
        field_name = 'SNRCorFaCo'
    elif datatype == 'SNRCorFaCo':
        field_name = 'SNRCorFaCo'
    elif datatype == 'avgdBZ':
        field_name = 'avg_reflectivity'
    elif datatype == 'NdBZ':
        field_name = 'npoints_reflectivity'
    elif datatype == 'quant05dBZ':
        field_name = 'quant05_reflectivity'
    elif datatype == 'quant10dBZ':
        field_name = 'quant10_reflectivity'
    elif datatype == 'quant20dBZ':
        field_name = 'quant20_reflectivity'
    elif datatype == 'quant50dBZ':
        field_name = 'quant50_reflectivity'
    elif datatype == 'quant80dBZ':
        field_name = 'quant80_reflectivity'
    elif datatype == 'quant90dBZ':
        field_name = 'quant90_reflectivity'
    elif datatype == 'quant95dBZ':
        field_name = 'quant95_reflectivity'
    elif datatype == 'avgRR':
        field_name = 'avg_radar_estimated_rain_rate'
    elif datatype == 'NRR':
        field_name = 'npoints_radar_estimated_rain_rate'
    elif datatype == 'quant05RR':
        field_name = 'quant05_radar_estimated_rain_rate'
    elif datatype == 'quant10RR':
        field_name = 'quant10_radar_estimated_rain_rate'
    elif datatype == 'quant20RR':
        field_name = 'quant20_radar_estimated_rain_rate'
    elif datatype == 'quant50RR':
        field_name = 'quant50_radar_estimated_rain_rate'
    elif datatype == 'quant80RR':
        field_name = 'quant80_radar_estimated_rain_rate'
    elif datatype == 'quant90RR':
        field_name = 'quant90_radar_estimated_rain_rate'
    elif datatype == 'quant95RR':
        field_name = 'quant95_radar_estimated_rain_rate'
    elif datatype == 'avgV':
        field_name = 'avg_velocity'
    elif datatype == 'NV':
        field_name = 'npoints_velocity'
    elif datatype == 'quant05V':
        field_name = 'quant05_velocity'
    elif datatype == 'quant10V':
        field_name = 'quant10_velocity'
    elif datatype == 'quant20V':
        field_name = 'quant20_velocity'
    elif datatype == 'quant50V':
        field_name = 'quant50_velocity'
    elif datatype == 'quant80V':
        field_name = 'quant80_velocity'
    elif datatype == 'quant90V':
        field_name = 'quant90_velocity'
    elif datatype == 'quant95V':
        field_name = 'quant95_velocity'
    elif datatype == 'avgVc':
        field_name = 'avg_corrected_velocity'
    elif datatype == 'NVc':
        field_name = 'npoints_corrected_velocity'
    elif datatype == 'quant05Vc':
        field_name = 'quant05_corrected_velocity'
    elif datatype == 'quant10Vc':
        field_name = 'quant10_corrected_velocity'
    elif datatype == 'quant20Vc':
        field_name = 'quant20_corrected_velocity'
    elif datatype == 'quant50Vc':
        field_name = 'quant50_corrected_velocity'
    elif datatype == 'quant80Vc':
        field_name = 'quant80_corrected_velocity'
    elif datatype == 'quant90Vc':
        field_name = 'quant90_corrected_velocity'
    elif datatype == 'quant95Vc':
        field_name = 'quant95_corrected_velocity'
    else:
        raise ValueError('ERROR: Unknown data type ' + datatype)
    return field_name


@classmethod
def find_in_registry(cls, entity_registry_id: str, registry_id: str=None,
    registry_name: str=None):
    """Get an entity from a registry by their ids.

        :param entity_registry_id: entity registry id
        :param registry_id: registery id. If none, 'registry_name' must be provided.
        :param registry_name: registry name. If None, 'registry_id' must be provided
        :return: instance
        """
    entities = cls.get_in_registry([entity_registry_id], registry_id=
        registry_id, registry_name=registry_name)
    if entities:
        return entities[0]
    return None


def put_identity_policy(Identity=None, PolicyName=None, Policy=None):
    """
    Adds or updates a sending authorization policy for the specified identity (an email address or a domain).
    Sending authorization is a feature that enables an identity owner to authorize other senders to use its identities. For information about using sending authorization, see the Amazon SES Developer Guide .
    This action is throttled at one request per second.
    See also: AWS API Documentation

    Examples
    The following example adds a sending authorization policy to an identity:
    Expected Output:

    :example: response = client.put_identity_policy(
        Identity='string',
        PolicyName='string',
        Policy='string'
    )

    :type Identity: string
    :param Identity: [REQUIRED]
            The identity to which the policy will apply. You can specify an identity by using its name or by using its Amazon Resource Name (ARN). Examples: user@example.com , example.com , arn:aws:ses:us-east-1:123456789012:identity/example.com .
            To successfully call this API, you must own the identity.

    :type PolicyName: string
    :param PolicyName: [REQUIRED]
            The name of the policy.
            The policy name cannot exceed 64 characters and can only include alphanumeric characters, dashes, and underscores.

    :type Policy: string
    :param Policy: [REQUIRED]
            The text of the policy in JSON format. The policy cannot exceed 4 KB.
            For information about the syntax of sending authorization policies, see the Amazon SES Developer Guide .

    :rtype: dict
    :return: {}

    """
    pass


def is_multiprocessing_queue(queue):
    """Return whether `queue` is a multiprocessing queue."""
    return queue.__module__.startswith('multiprocessing')


def put_data(f, data, big=True, isfloat=False):
    """
    Put data to file object with given endianness and data type.
    """
    if isfloat:
        if big:
            f.write(data.astype('>f8').tostring())
        else:
            f.write(data.astype('<f8').tostring())
    elif big:
        f.write(data.astype('>i4').tostring())
    else:
        f.write(data.astype('<i4').tostring())
    return


@classmethod
def get(cls, name):
    """Query to get a single user."""
    return cls.list() + " AND usename = '{name}'".format(name=name)


def setDebugCore(on=True):
    """Function for establising __DEBUG_CORE_FLAG__ to True/False

    Keyword Arguments:
        on {boolean} -- Set's True or False the Debug messages for Core Logger calls (default: {True})
    """
    global __DEBUG_CORE_FLAG__
    __DEBUG_CORE_FLAG__ = on


@classmethod
def getUnitBySymbol(cls, symbol):
    """Return the unit with symbol `symbol`.

        Args:
            symbol (str): symbol to look-up

        Returns:
            :class:`Unit` sub-class, if a unit with given `symbol` exists
                within the :class:`Unit` sub-class associated with this
                :class:`Quantity` sub-class, otherwise None
        """
    return cls.Unit.getUnitBySymbol(symbol)


def get_ciphertext_fetched():
    """Return the number of bytes fetched by the helpe for this upload,
        or 0 if the helper did not need to fetch any bytes (or if there was
        no helper)."""


@staticmethod
def _passwd_tuple(pw_str):
    """
        split passwd line into tuple
        """
    passwd_fields = pw_str.split(':')
    return passwd_fields[0], passwd_fields[1], int(passwd_fields[2]), int(
        passwd_fields[3]), passwd_fields[4], passwd_fields[5], passwd_fields[6]


def _get_indentation(string):
    """Return the number of spaces before the current line."""
    return len(string) - len(string.lstrip(' '))


def helpEpilog():
    """
    text for help epilog
    """
    inputFileFormatHelp = """
------------------------------------------------------
Input File Format
------------------------------------------------------
iterativeWGCNA expects a tab-delimited text file containing
gene expression data arranged such that there is one
row per gene and one column per sample.  The first column
should contain unique gene identifiers.  For example:

GENE    Sample1    Sample2    Sample3
Gata1    500    715    1000
Phtf2    60    1000    1600
"""
    wgcnaParametersHelp = """
------------------------------------------------------
WGCNA Parameters
------------------------------------------------------
iterativeWGCNA can accept any parameter valid for the WGCNA
blockwiseModules function.

See http://www.inside-r.org/packages/cran/wgcna/docs/blockwiseModules

To specify these parameters use the --wgcnaParameters flag followed by
a comma separated list of parameter=value pairs.  For example:

--wgcnaParameters maxBlockSize=5000,corType=bicor,power=10

sets the maximum block size to 5000 genes,
the correlation type to the biweight correlation,
and the power-law scaling factor (beta) to 10

If parameters are not specified, iterativeWGCNA uses the default WGCNA settings,
except for the following:

minModuleSize=20
saveTOMs=FALSE
minKMEtoStay=0.8
minCoreKME=0.8
networkType=signed
numericLabels=TRUE

"""
    return inputFileFormatHelp + '\n\n' + wgcnaParametersHelp


def get_intervals(positions, window):
    """ find windows of genomic regions for getting variants within.

    This merges overlapping intervals
    """
    intervals = []
    for pos in sorted(positions):
        if intervals and pos - window < intervals[-1][1]:
            intervals[-1][1] = pos + window
        else:
            intervals.append([pos - window, pos + window])
    return intervals


def equilibrium_point(iterable):
    """
    Equilibrium point is the index in the iterable in which the sum of elements on the
    left hand side and the right side of that index are equal.
    :param iterable: The iterable should be of type list or tuple
    :return: It returns the index position of the equilibrium point in the iterable,
             and if no such index is present or list is empty it returns -1

        Eg: equilibrium_point([-9, 1, 5, 2, -6, 3, 0]) returns 3
            Here the sum of elements on either side of the index 3 is '-3'.
    """
    if type(iterable) == list or type(iterable) == tuple:
        pass
    else:
        raise TypeError('Iterable should be of either list or tuple')
    for item in iterable:
        if not isinstance(item, int):
            raise ValueError('Only numbers are accepted in the iterable')
    total = sum(iterable)
    left_sum = 0
    for i in range(len(iterable)):
        total -= iterable[i]
        if total == left_sum:
            return i
        left_sum += iterable[i]
    return -1


def filter_data_points(x, y, xmin, xmax, ymin, ymax):
    """
    Remove points outside the axes limits
    """
    xnew, ynew = [], []
    for xi, yi in zip(x, y):
        if xi is None or yi is None:
            continue
        elif xmin <= xi <= xmax and ymin <= yi <= ymax:
            xnew.append(xi)
            ynew.append(yi)
    return xnew, ynew


def _read_only_property(key, doc=None):
    """Create property that gives read-only access to instance._data[key]"""
    if doc is None:
        doc = 'data from key {!r}'.format(key)
    return property(lambda self: self._data[key], doc=doc)


def scan_setup_py():
    """Validate the contents of setup.py against Versioneer's expectations."""
    found = set()
    setters = False
    errors = 0
    with open('setup.py', 'r') as f:
        for line in f.readlines():
            if 'import versioneer' in line:
                found.add('import')
            if 'versioneer.get_cmdclass()' in line:
                found.add('cmdclass')
            if 'versioneer.get_version()' in line:
                found.add('get_version')
            if 'versioneer.VCS' in line:
                setters = True
            if 'versioneer.versionfile_source' in line:
                setters = True
    if len(found) != 3:
        print('')
        print('Your setup.py appears to be missing some important items')
        print('(but I might be wrong). Please make sure it has something')
        print('roughly like the following:')
        print('')
        print(' import versioneer')
        print(' setup( version=versioneer.get_version(),')
        print('        cmdclass=versioneer.get_cmdclass(),  ...)')
        print('')
        errors += 1
    if setters:
        print("You should remove lines like 'versioneer.VCS = ' and")
        print("'versioneer.versionfile_source = ' . This configuration")
        print('now lives in setup.cfg, and should be removed from setup.py')
        print('')
        errors += 1
    return errors


@staticmethod
def output_calc_freq(speed, period):
    """
		Calculate frequency from period and speed
		:param speed: Speed
		:param period: Period
		:return: Frequency
		"""
    return float(speed) / float(period)


def get_exchange_reactions(model):
    """Yield IDs of all exchange reactions from model.

    This helper function would be useful when creating
    :class:`.ReactionDeletionStrategy` objects.

    Args:
        model: :class:`psamm.metabolicmodel.MetabolicModel`.
    """
    for reaction_id in model.reactions:
        if model.is_exchange(reaction_id):
            yield reaction_id


def _pretty_time_delta(td):
    """Creates a string representation of a time delta.

    Parameters
    ----------
    td : :class:`datetime.timedelta`

    Returns
    -------
    pretty_formatted_datetime : str
    """
    seconds = td.total_seconds()
    sign_string = '-' if seconds < 0 else ''
    seconds = abs(int(seconds))
    days, seconds = divmod(seconds, 86400)
    hours, seconds = divmod(seconds, 3600)
    minutes, seconds = divmod(seconds, 60)
    d = dict(sign=sign_string, days=days, hours=hours, minutes=minutes,
        seconds=seconds)
    if days > 0:
        return '{sign}{days}d{hours:02d}h{minutes:02d}m:{seconds:02d}s'.format(
            **d)
    elif hours > 0:
        return '{sign}{hours:02d}h{minutes:02d}m:{seconds:02d}s'.format(**d)
    elif minutes > 0:
        return '{sign}{minutes:02d}m:{seconds:02d}s'.format(**d)
    else:
        return '{sign}{seconds:02d}s'.format(**d)


@classmethod
def _from_et(cls, root, parent):
    """
        Create a :class:`Designrules` from a :code:`designrules` element.

        :param root: The element tree tree to parse.
        :param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
        :rtype: :class:`Designrules`
        """
    n = cls()
    n._init_from_et(root, parent)
    return n


def frame_id(event):
    """
    Gets a unique identifier for a data frame retrieved from Karabo at XFEL.

    Returns a label that unambiguosly identifies, within an event, the frame currently
    being processed. At the European XFEL facility, the index of the frame within its
    train is used as identifier.

    Arguments:

         event (:class:`~onda.utils.data_event.DataEvent`): an object storing the event
            data.

    Returns:

        str: a unique frame identifier (within an event).
    """
    return str(event.current_frame)


def serialize(ignoreDefault=False):
    """Return a string representation of the field.

        If ignoreDefault is True, and the value is the default, return None,
        which signals insist to ignore the value for dumping purposes.
        """


@classmethod
def _format_parsing_error(cls, e):
    """Transform a pyparsing exception into an error message

        Does a best effort to be useful, but might need to be improved.
        """
    return '{}\n{}^\n{}'.format(e.line, (e.column - 1) * ' ', e)


def post_process_request(req, template, data, metadata=None, method=None):
    """Do any post-processing the request might need

        This typically means adding values to the template `data`
        dictionary, or changing the Jinja2 template.

        `data` and `metdata` may be updated in place.

        Always returns a tuple of ``(template, data)`` or ``(template,
        data, metadata)``, even if unchanged.

        Be aware that returning a ``(template, data, None)`` triple
        will be interpreted as using the legacy API and will indicate
        that the template is a legacy Genshi template. The same will
        happen if the third value of the tuple is a string.

        The `method` last parameter is deprecated and is now supposed
        to be passed as `'method'` in the `metadata` dict. Even
        better, use directly the `'text'` indication (`True` or
        `False`).

        Note that `template`, `data`, `content_type` will be `None` if:
         - called when processing an error page
         - the default request handler did not return any result

        :Since 1.0: Clearsilver templates are no longer supported.

        :Since 1.1.2: the rendering `method` will be passed if it is returned
           by the request handler, otherwise `method` will be `None`. For
           backward compatibility, the parameter is optional in the
           implementation's signature.

        :Since 1.3.2: Genshi templates are still supported, and if
           `process_request` used the old API (`(template, data,
           content_type)`), the `metadata` parameter passed to
           `post_process_request` will actually be the `content_type`
           value (`String` or `None`).  This support for the old API
           will be removed in Trac 1.5.1, in which `metadata` will
           always be a `dict` or `None`.

        """


def list_difference(l1, l2):
    """list substraction compatible with Python2"""
    return list(set(l1) - set(l2))


def accuracy(input, targs):
    """Computes accuracy with `targs` when `input` is bs * n_classes."""
    n = targs.shape[0]
    input = input.argmax(dim=-1).view(n, -1)
    targs = targs.view(n, -1)
    return (input == targs).float().mean()


def quaternion_real(quaternion):
    """Return real part of quaternion.

    >>> quaternion_real([3, 0, 1, 2])
    3.0

    """
    return float(quaternion[0])


@classmethod
def team_merge_request_expired(cls, val):
    """
        Create an instance of this class set to the
        ``team_merge_request_expired`` tag with value ``val``.

        :param TeamMergeRequestExpiredType val:
        :rtype: EventType
        """
    return cls('team_merge_request_expired', val)


def glClearDepth(depth: int):
    """Specify the clear value for the depth buffer

    :param depth: Specifies the depth value used when the depth buffer is cleared. The initial value is 1.
    :type depth: int
    """
    pass


def get_pagination_url(request, page_param_name):
    """Remove pagination param from request url"""
    url = request.path
    params = request.GET.copy()
    params.pop(page_param_name, None)
    if params:
        return f'{url}?{params.urlencode()}&'
    return f'{url}?'


def composite_index(data):
    """
    Create a composite index based on the sentiment analysis based on Loughran and McDonald's
    dictionary and script.

    :param data: String to analyse.
    :return: List of values. See unused variable OUTPUT_FIELDS in the source, there is a lot.
    """
    OUTPUT_FIELDS = ['file type', 'file size', 'number of words',
        '% positive', '% negative', '% uncertainty', '% litigious',
        '% modal-weak', '% modal moderate', '% modal strong',
        '% constraining', '# of alphabetic', '# of digits', '# of numbers',
        'avg # of syllables per word', 'average word length', 'vocabulary']
    if data[2] + data[3] + data[4]:
        result = (data[3] - data[4]) / data[2]
    else:
        result = 0
    return result


@staticmethod
def p_number_number_string_value_list(p):
    """number_number_string_value_list : number_number_string_value
                                           | number_number_string_value number_number_string_value_list"""
    try:
        p[0] = [p[1]] + p[2]
    except IndexError:
        p[0] = [p[1]]


def conditional_content_removal(request, response):
    """
    Removes the content of responses for HEAD requests, 1xx, 204 and 304
    responses. Ensures compliance with RFC 2616, section 4.3.
    """
    if 100 <= response.status_code < 200 or response.status_code in (204, 304):
        if response.streaming:
            response.streaming_content = []
        else:
            response.content = b''
        response['Content-Length'] = '0'
    if request.method == 'HEAD':
        if response.streaming:
            response.streaming_content = []
        else:
            response.content = b''
    return response


def p_ExtendedAttributeList_empty(p):
    """ExtendedAttributeList : """
    p[0] = []


def get_analysis_result(raw_scan_id, db_analysis=db_analysis):
    """
    Get data from analysis store with given raw_scan_id=uid.
    More rich search can be implemented here.

    Parameters
    ----------
    raw_scan_id : int
        scan_id of original scan
    db : analysis store, optional
        where analysis result is to be saved

    Returns
    -------
    header
    """
    res = db_analysis(raw_scan_id=raw_scan_id)
    res = list(res)
    if not len(res):
        print('No analysis result is found for {}.'.format(raw_scan_id))
        return
    res = sorted(res, key=lambda x: x.start.time)
    uid = res[-1].start.uid
    hdr = db_analysis[uid]
    return hdr


def sqlchoices():
    """
    utility for AdminServerForm
    """
    for index, choice in enumerate(['local', 'mysql']):
        yield index, choice


def is_mandatory(err: str, words: list) ->bool:
    """
    This function checks whether a word containing the error string exists.
    :param err: error string
    :param words: list of words
    :return: whether the correction can be specified as mandatory
    """
    for word in words:
        if err in word:
            return False
    else:
        return True


def _validate_value(value, data):
    """Validate data against given value directly

    :param value: list or tupple with allowed data
    :param data: the data itself (string or number)
    """
    passed = False
    if data == value.value:
        passed = True
    return passed


@staticmethod
def get_json_object_property(json_object_IN, name_IN, default_IN=None):
    """
        Accepts name of a JSON property that you expect to be contained in the
           JSON object passed in.  Returns property that corresponds to name. If
           not found, returns default value (which defaults to None).
        """
    value_OUT = None
    if name_IN in json_object_IN:
        value_OUT = json_object_IN[name_IN]
    else:
        value_OUT = default_IN
    return value_OUT


def query_plan(query):
    """Light sanity checking and query partitioning

    Parameters
    ----------
    query : str
        The query to operate on

    Returns
    -------
    list of tuple
        The (query type, query).

    Raises
    ------
    ValueError
       When there are no queries
    """
    if query.startswith('where'):
        part = query.split('where', 1)[1].strip()
        if not part:
            raise ValueError('No query')
        return [('where', part)]
    parts = query.split('where', 1)
    for part in parts:
        if not part:
            raise ValueError('No query')
    if len(parts) == 1:
        return [('set', parts[0].strip())]
    else:
        return [('set', parts[0].strip()), ('where', parts[1].strip())]


@classmethod
def _get_xml_node_value(cls, root, *name):
    """
        return the named value from an XML node, if it exists
        """
    if len(name) == 1:
        node = root.find(name[0])
    elif len(name) == 2:
        node = root.find(name[0], name[1])
    if not node:
        return None
    elif len(node.text) < 1:
        return None
    else:
        return node.text.strip()


@staticmethod
def draw_path(ctx, center_x, center_y, width, height=None):
    """Draws an upright triangle on the Cairo context without stroking or
        filling it.

        @see: ShapeDrawer.draw_path"""
    height = height or width
    ctx.move_to(center_x - width / 2, center_y + height / 2)
    ctx.line_to(center_x, center_y - height / 2)
    ctx.line_to(center_x + width / 2, center_y + height / 2)
    ctx.close_path()


@classmethod
def isproduct(cls):
    """Check if the DataType is the product of a Recipe"""
    return False


def format_cpf(cpf_string):
    """
    Formats CPF to standard format.

    :param cpf_string: Unformatted CPF (string)
    :return: A string in the CPF format XXX.XXX.XXX-XX
    """
    return cpf_string[:3] + '.' + cpf_string[3:6] + '.' + cpf_string[6:9
        ] + '-' + cpf_string[9:]


def eval_kwarg(x):
    """If x is a string, eval it. Otherwise just return it.

    Args:
        x (str, obj): String to be evaluated as an object or an object.

    Returns:
        obj: Result of evaluated string or the input object.

    """
    if isinstance(x, str):
        try:
            return eval(x)
        except NameError:
            return x
    return x


def delete():
    """Erase selected strips from the sequencer

    """
    pass


def json_to_tags(tags):
    """format json Tags as simple tag list"""
    tag_list = ''
    for index, _ in enumerate(tags):
        if index == 0:
            tag_list += tags[index]['Key'] + '=' + tags[index]['Value']
        else:
            tag_list += ', ' + tags[index]['Key'] + '=' + tags[index]['Value']
    return tag_list


@classmethod
def manual(cls, number: int):
    """
        Get the manual enum attribute for an earthing stick number.

        :param number: the earthing stick (1..6)
        :return: the manual enum
        """
    return getattr(cls, 'manual_{}'.format(number))


def alert(alertText='', alertHeading='', extraPadding=False, alertLevel=
    'warning'):
    """ *Generate a alert - TBS style*

    **Key Arguments:**
        - ``alertText`` -- the text to be displayed in the alert
        - ``extraPadding`` -- for longer messages, increase the padding on the top and bottom of the alert wrapper
        - ``alertLevel`` -- the level of the alert [ "warning" | "error" | "success" | "info" ]

    **Return:**
        - ``alert`` -- the alert """
    falseList = [extraPadding]
    for i in range(len(falseList)):
        if not falseList[i]:
            falseList[i] = ''
    [extraPadding] = falseList
    if alertLevel == 'default':
        alertLevel = ''
    else:
        alertLevel = 'alert-%(alertLevel)s' % locals()
    if extraPadding:
        extraPadding = 'alert-block'
        alertHeading = '
%(alertHeading)s
' % locals()
    else:
        alertHeading = '%(alertHeading)s' % locals()
    alert = (
        """

          <button type="button" class="close" data-dismiss="alert">×</button>
          %(alertHeading)s %(alertText)s

"""
         % locals())
    return alert


@classmethod
def export_to_hdf5(cls, h5_file, model, eids):
    """exports the elements in a vectorized way"""
    pids = []
    nodes = []
    for eid in eids:
        element = model.elements[eid]
        pids.append(element.pid)
        nodes.append(element.nodes)
    h5_file.create_dataset('eid', data=eids)
    h5_file.create_dataset('pid', data=pids)
    h5_file.create_dataset('nodes', data=nodes)


def write_gauss(file_name, atoms, points, temp_name, proj_name='gaussian'):
    """
    Write a Gaussian input file.

    A template file needs to be prepared which has the name as XXX__NAME__XXX,
    the positions as XXX__POS__XXX and the (optional) charges as
    XXX__CHARGES__XXX.

    Parameters
    ----------
    file_name : str
        Name of the Gaussian input file to be written
    atoms : list of Atom objects
        Atoms to be calculated with Gaussian
    points : list of Atom objects or None
        The Atom objects should have a charge. If there is no XXX__CHARGES__XXX
        in the template file, this doesn't matter and can be None
    temp_name : str
        Name of the template file
    proj_name : str
        Project name, default 'gaussian'

    """
    with open(temp_name) as temp_file:
        temp_content = temp_file.readlines()
    out_file = open(file_name, 'w')
    for line in temp_content:
        if 'XXX__NAME__XXX' in line:
            out_file.write(line.replace('XXX__NAME__XXX', proj_name))
        elif 'XXX__POS__XXX' in line:
            for atom in atoms:
                atomStr = '{:>6} {:10.6f} {:10.6f} {:10.6f}'.format(atom.
                    elem, atom.x, atom.y, atom.z) + '\n'
                out_file.write(atomStr)
        elif 'XXX__CHARGES__XXX' in line:
            for point in points:
                point_str = '{:10.6f} {:10.6f} {:10.6f} {:10.6f}'.format(point
                    .x, point.y, point.z, point.q) + '\n'
                out_file.write(point_str)
        else:
            out_file.write(line)
    out_file.close()
    return


def degrees_to_angle(value):
    """1 degree = 60000 angles"""
    return int(round(value * 60000))


def take(data, indices, dim):
    """Takes elements from an input array along the given dim.

    Parameters
    ----------
    data : Tensor
        The data tensor.
    indices : Tensor
        The indices tensor.
    dim : Tensor
        The dimension to gather along.
    """
    pass


@classmethod
def from_ip(cls, ip):
    """Retrieve webacc id associated to a webacc ip"""
    result = cls.list({'items_per_page': 500})
    webaccs = {}
    for webacc in result:
        for server in webacc['servers']:
            webaccs[server['ip']] = webacc['id']
    return webaccs.get(ip)


def delete_edgeloop(use_face_split: bool=True):
    """Delete an edge loop by merging the faces on each side

    :param use_face_split: Face Split, Split off face corners to maintain surrounding geometry
    :type use_face_split: bool
    """
    pass


def det_prob_query(p1: float, k: int, l: int) ->float:
    """
    Compute the probability of finding point q < cR

    Parameters
    ----------
    p1
        P_1 as determined with Union[floky.stats.collision_prob_cosine, floky.stats.collision_prob_l2]
    k
        Number of hash digits.
    l
        Number of hash tables.

    Returns
    -------
    Pq
        Prob. of finding point q < cR
    """
    return 1.0 - (1.0 - p1 ** k) ** l


def with_metaclass(meta, *bases):
    """Create a base class with a metaclass."""
    return meta('NewBase', bases, {})


def _sims_parse(res):
    """Converts N/A to `nan` and otherwise tries to parse integers"""
    try:
        return int(res)
    except ValueError:
        if res.lower() == 'n/a':
            return float('nan')
        else:
            return res


def available_tensors(graph):
    """All tensors in the model's graph."""
    tensors = []
    ops = graph.get_operations()
    for m in ops:
        for tensor in m.outputs:
            tensors.append((tensor.name, m.type, tensor.shape.as_list()))
    return tensors


def p_trackitem(t):
    """trackitem : index
                 | isrc
                 | pregap
                 | postgap
                 | flags
                 | title
                 | performer
                 | songwriter"""
    t[0] = t[1]


def multi_polygon(coordinates=None):
    """Create a valid GeoJSON MultiPolygon."""
    return {'type': 'MultiPolygon', 'coordinates': [] if coordinates is
        None else coordinates}


def config_logger(write_logs, log_level, log_file, verbose):
    """
    Initialize the logger for ToolDog. By default, only WARNING, ERROR and CRITICAL are
    written on STDERR. You can also write logs to a log file.

    :param write_logs: Decide to write logs to output log file.
    :type write_logs: BOOLEAN
    :param log_level: Select the level of logs. 'debug', 'info' or 'warn'. Other value    is considered as 'warn'.
    :type log_level: STRING
    :param log_file: path to output log file.
    :type log_file: STRING

    :return: Config dictionnary for logger.
    :rtype: DICT
    """
    cfg = {'version': 1, 'formatters': {'written': {'format':
        '%(asctime)s :: %(name)s ' + ':: %(levelname)s :: %(message)s'},
        'printed': {'format': '%(name)s :: ' +
        '%(levelname)s :: %(message)s'}}, 'handlers': {}, 'loggers': {}}
    if write_logs:
        cfg_logfile = {'class': 'logging.handlers.RotatingFileHandler',
            'formatter': 'written', 'maxBytes': 1000000, 'backupCount': 1}
        cfg_logfile['level'] = log_level
        cfg_logfile['filename'] = log_file
        cfg['handlers']['logfile'] = cfg_logfile
    cfg_stderr = {'class': 'logging.StreamHandler', 'formatter': 'printed'}
    cfg_stderr['level'] = 'WARNING'
    if verbose:
        cfg_stderr['level'] = 'INFO'
    cfg['handlers']['stderr'] = cfg_stderr
    modules = ['annotate.galaxy', 'annotate.cwl', 'annotate.edam_to_galaxy',
        'analyse', 'analyse.tool_analazer', 'analyse.code_collector',
        'analyse.language_analyzer', 'biotool_model', 'main', 'analyse']
    logger = {'handlers': ['stderr'], 'propagate': False, 'level': 'DEBUG'}
    if write_logs:
        logger['handlers'].append('logfile')
    for module in modules:
        cfg['loggers']['tooldog.' + module] = logger
    return cfg


@classmethod
def realname(cls):
    """Return real name of an object class"""
    return cls.__module__ + '.' + cls.__name__


def calculate_range_parameter(part_size, part_index, num_parts, total_size=None
    ):
    """Calculate the range parameter for multipart downloads/copies

    :type part_size: int
    :param part_size: The size of the part

    :type part_index: int
    :param part_index: The index for which this parts starts. This index starts
        at zero

    :type num_parts: int
    :param num_parts: The total number of parts in the transfer

    :returns: The value to use for Range parameter on downloads or
        the CopySourceRange parameter for copies
    """
    start_range = part_index * part_size
    if part_index == num_parts - 1:
        end_range = ''
        if total_size is not None:
            end_range = str(total_size - 1)
    else:
        end_range = start_range + part_size - 1
    range_param = 'bytes=%s-%s' % (start_range, end_range)
    return range_param


def p_delta_unit(p):
    """delta_unit : MINUTE
                  | HOUR
                  | DAY"""
    p[0] = p[1].lower()[:1]


def prod(array, *args, **kwargs):
    """
    Product of array elements.

    See Also
    --------
    Array.prod
    """
    return array.prod(*args, **kwargs)


def from_cstr_to_pystr(data, length):
    """Revert C pointer to Python str

    Parameters
    ----------
    data : ctypes pointer
        pointer to data
    length : ctypes pointer
        pointer to length of data
    """
    res = []
    for i in range(length.value):
        try:
            res.append(str(data[i].decode('ascii')))
        except UnicodeDecodeError:
            res.append(str(data[i].decode('utf-8')))
    return res


def plus_or_dot(pieces):
    """Return a + if we don't already have one, else return a ."""
    if '+' in pieces.get('closest-tag', ''):
        return '.'
    return '+'


@staticmethod
def is_this_request_from_same_traversal(response, traversal):
    """
        This mean the current request came from this  traversal,
        so we can put max pages condition on this, otherwise for different
        traversals of different spiders, adding max_page doest make sense.
        """
    traversal_id = traversal['traversal_id']
    current_request_traversal_id = response.meta.get(
        'current_request_traversal_id', None)
    return current_request_traversal_id == traversal_id


def render_git_describe_long(pieces):
    """TAG-DISTANCE-gHEX[-dirty].

    Like 'git describe --tags --dirty --always -long'.
    The distance/hash is unconditional.

    Exceptions:
    1: no tags. HEX[-dirty]  (note: no 'g' prefix)
    """
    if pieces['closest-tag']:
        rendered = pieces['closest-tag']
        rendered += '-%d-g%s' % (pieces['distance'], pieces['short'])
    else:
        rendered = pieces['short']
    if pieces['dirty']:
        rendered += '-dirty'
    return rendered


Numscrypt-0.0.40//numscrypt/linalg/eigen_mpmath - Copy.pyfile:/numscrypt/linalg/eigen_mpmath - Copy.py:function:eig_tr_r/eig_tr_r

def eig_tr_r(ctx, A):
    """
    This routine calculates the right eigenvectors of an upper right triangular matrix.

    input:
      A      an upper right triangular matrix

    output:
      ER     a matrix whose columns form the right eigenvectors of A

    return value: ER
    """
    n = A.rows
    ER = ctx.eye(n)
    eps = ctx.eps
    unfl = ctx.ldexp(ctx.one, -ctx.prec * 30)
    smlnum = unfl * (n / eps)
    simin = 1 / ctx.sqrt(eps)
    rmax = 1
    for i in range(1, n):
        s = A[i, i]
        smin = max(eps * abs(s), smlnum)
        for j in range(i - 1, -1, -1):
            r = 0
            for k in range(j + 1, i + 1):
                r += A[j, k] * ER[k, i]
            t = A[j, j] - s
            if abs(t) < smin:
                t = smin
            r = -r / t
            ER[j, i] = r
            rmax = max(rmax, abs(r))
            if rmax > simin:
                for k in range(j, i + 1):
                    ER[k, i] /= rmax
                rmax = 1
        if rmax != 1:
            for k in range(0, i + 1):
                ER[k, i] /= rmax
    return ER


@classmethod
def mock(cls, **kwargs):
    """fake current time,don't need to change OS time,it is helpful for test"""
    cls.mock_offset = kwargs


def _donothing_func(*args, **kwargs):
    """Perform no good and no bad"""
    pass


@staticmethod
def interleaveblastresults(query, subject):
    """
        Creates an interleaved string that resembles BLAST sequence comparisons
        :param query: Query sequence
        :param subject: Subject sequence
        :return: Properly formatted BLAST-like sequence comparison
        """
    matchstring = ''
    blaststring = ''
    for i, bp in enumerate(query):
        if bp == subject[i]:
            matchstring += '|'
        else:
            matchstring += ' '
    prev = 0
    for j in range(0, len(query), 60):
        """
            0000 OLC ATGAAGAAGATATTTGTAGCGGCTTTATTTGCTTTTGTTTCTGTTAATGCAATGGCAGCT
                     ||||||||||| ||| | |||| ||||||||| || ||||||||||||||||||||||||
                 ref ATGAAGAAGATGTTTATGGCGGTTTTATTTGCATTAGTTTCTGTTAATGCAATGGCAGCT
            0060 OLC GATTGTGCAAAAGGTAAAATTGAGTTCTCTAAGTATAATGAGAATGATACATTCACAGTA
                     ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
                 ref GATTGTGCAAAAGGTAAAATTGAGTTCTCTAAGTATAATGAGAATGATACATTCACAGTA
            """
        blaststring += '{} OLC {}\n         {}\n     ref {}\n'.format('{:04d}'
            .format(j), query[prev:j + 60], matchstring[prev:j + 60],
            subject[prev:j + 60])
        prev = j + 60
    return blaststring


def set_additional_var_attributes(ds, meta_data_dict):
    """
    Set further descriptive variable
    attributes for interpolated variables
    """
    for var in ds.variables:
        try:
            meta_data_var = meta_data_dict[var]
        except KeyError:
            continue
        for key, value in meta_data_var.items():
            ds[var].attrs[key] = value
    return ds


def _ply_header(num_vertices, num_faces, use_vertex_colors=False):
    """
    Return a string representing the PLY format header for the given data properties.
    """
    hdr_top = 'ply\nformat ascii 1.0\ncomment Generated by Brainload\n'
    hdr_verts = (
        'element vertex %d\nproperty float x\nproperty float y\nproperty float z\n'
         % num_vertices)
    hdr_vertex_colors = """property uchar red
property uchar green
property uchar blue
property uchar alpha
"""
    hdr_face = ('element face %d\nproperty list uchar int vertex_indices\n' %
        num_faces)
    hdr_end = 'end_header\n'
    if use_vertex_colors:
        hdr_elements = [hdr_top, hdr_verts, hdr_vertex_colors, hdr_face,
            hdr_end]
    else:
        hdr_elements = [hdr_top, hdr_verts, hdr_face, hdr_end]
    return ''.join(hdr_elements)


def discretiseRegularGeoN(GF, D):
    """
    regular discretisation in geometric space given fixed number of
    points per xi direction
    """
    pass


@classmethod
def sso_change_policy(cls, val):
    """
        Create an instance of this class set to the ``sso_change_policy`` tag
        with value ``val``.

        :param SsoChangePolicyType val:
        :rtype: EventType
        """
    return cls('sso_change_policy', val)


def scroll_forward(event, half=False):
    """
    Scroll window down.
    """
    w = event.app.layout.current_window
    b = event.app.current_buffer
    if w and w.render_info:
        info = w.render_info
        ui_content = info.ui_content
        scroll_height = info.window_height
        if half:
            scroll_height //= 2
        y = b.document.cursor_position_row + 1
        height = 0
        while y < ui_content.line_count:
            line_height = info.get_height_for_line(y)
            if height + line_height < scroll_height:
                height += line_height
                y += 1
            else:
                break
        b.cursor_position = b.document.translate_row_col_to_index(y, 0)


def _add_doc(func, doc):
    """
    Add documentation to a function.
    """
    func.__doc__ = doc


def get_quality_by_depth(var):
    """
    Returns the quality by depth or the variant confidence,
    or None if it isn't present in the VCF.
    """
    return var.INFO.get('QD')


def verify():
    """
        Ensure that the schema that's installed can be used by this
        RelStorage.

        If it cannot, for example it's history-preserving and we were configured
        to be history-free, raise an exception.
        """


@classmethod
def topic(cls, **kwargs) ->str:
    """Get MQTT topic for this message type."""
    site_id = kwargs.get('site_id', '+')
    return f'rhasspy/asr/{site_id}/trainSuccess'


def getArguments(parser):
    """Provides additional validation of the arguments collected by argparse."""
    return parser.parse_args()


def get_app_qt4(*args, **kwargs):
    """Create a new qt4 app or return an existing one."""
    from PyQt4 import QtGui
    app = QtGui.QApplication.instance()
    if app is None:
        if not args:
            args = [''],
        app = QtGui.QApplication(*args, **kwargs)
    return app


def printAllWidgets(qApplication, ofType=None):
    """ Prints list of all widgets to stdout (for debugging)
    """
    print("Application's widgets {}".format('of type: ' + str(ofType) if
        ofType else ''))
    for widget in qApplication.allWidgets():
        if ofType is None or isinstance(widget, ofType):
            print('  {!r}'.format(widget))


@classmethod
def _convert_to_color(cls, color_spec):
    """
        Convert ``color_spec`` to an openpyxl v2 Color object.

        Parameters
        ----------
        color_spec : str, dict
            A 32-bit ARGB hex string, or a dict with zero or more of the
            following keys.
                'rgb'
                'indexed'
                'auto'
                'theme'
                'tint'
                'index'
                'type'

        Returns
        -------
        color : openpyxl.styles.Color
        """
    from openpyxl.styles import Color
    if isinstance(color_spec, str):
        return Color(color_spec)
    else:
        return Color(**color_spec)


def connect(r=0.75):
    """ Connector (circle)

        Parameters
        ----------
        r: float
            Radius of connector circle
    """
    elem = {'name': 'CONNECT', 'extend': False, 'lblloc': 'center',
        'lblofst': 0, 'theta': -90}
    elem['anchors'] = {'W': [r, -r], 'E': [r, r], 'S': [2 * r, 0], 'N': [0, 0]}
    elem['move_cur'] = False
    elem['shapes'] = [{'shape': 'circle', 'center': [r, 0], 'radius': r}]
    return elem


def merge_two_dicts(x, y):
    """
    Given two dicts, merge them into a new dict as a shallow copy.
    Any overlapping keys in `y` will override the values in `x`.

    Taken from https://stackoverflow.com/questions/38987/
    how-to-merge-two-python-dictionaries-in-a-single-expression

    Parameters:
        x, y: dicts

    Returns:
        A dictionary containing a union of all keys in both original dicts.
    """
    z = x.copy()
    z.update(y)
    return z


def join_infile_path(*paths):
    """
    Join path components using '/' as separator.
    This method is defined as an alternative to os.path.join, which uses '\\'
    as separator in Windows environments and is therefore not valid to navigate
    within data files.

    Parameters:
    -----------
    *paths: all strings with path components to join

    Returns:
    --------
    A string with the complete path using '/' as separator.
    """
    path = '/'.join(paths)
    path = path.replace('//', '/')
    return path


def title_or_value(vocabulary, value):
    """
    Given a `vocabulary` and a `value` in that vocabulary, return the
    corresponding title or `value` if there is no title.
    """
    try:
        return vocabulary.getTerm(value).title or value
    except LookupError:
        return value


@classmethod
def _get_apic_classes(cls):
    """
        Get the APIC classes used by this acitoolkit class.

        :returns: list of strings containing APIC class names
        """
    resp = ['arpInst']
    return resp


def viz_white_wrap(body, char, bgcolor='white'):
    """Wrap body with hidden text for graphviz"""
    return (
        ' {body}{char}'
        .format(**locals()))


@classmethod
def set_label(cls, label):
    """
        update the internal counter if needed
        """
    if len(label) == 1:
        code = ord(label) - 97
    elif len(label) == 2:
        code = (ord(label[0]) - 96) * 26 + (ord(label[1]) - 97)
    else:
        code = (ord(label[0]) - 96) * 26 * 26 + (ord(label[1]) - 97) * 26 + (
            ord(label) - 97)
    if cls.last_label <= code:
        cls.last_label = code + 1
    return code


def from_keyed_iterable(iterable, key, filter_func=None):
    """Construct a dictionary out of an iterable, using an attribute name as
    the key. Optionally provide a filter function, to determine what should be
    kept in the dictionary."""
    generated = {}
    for element in iterable:
        try:
            k = getattr(element, key)
        except AttributeError:
            raise RuntimeError('{} does not have the keyed attribute: {}'.
                format(element, key))
        if filter_func is None or filter_func(element):
            if k in generated:
                generated[k] += [element]
            else:
                generated[k] = [element]
    return generated


def df_variant_id(row):
    """Get variant ID from pyvcf in DataFrame"""
    if row['ID'] != '.':
        return row['ID']
    else:
        return row['CHROM'] + ':' + str(row['POS'])


def meta_separate():
    """Put the contents of a metastrip back in the sequencer

    """
    pass


@classmethod
def create_read(cls, value):
    """ Create a new read capacity from a response """
    return cls(value['CapacityUnits'], 0)


@classmethod
def load(cls, data):
    """Load a sequence from a json formatted dictionary."""
    sequence = cls(data['bases'], name=data['name'])
    sequence.cyclic = data['isCircular']
    sequence.name = data['name']
    sequence.description = data.get('description', None)
    for a in data['annotations']:
        sequence.annotate(a['start'], a['end'] - 1, a['name'], a['type'], a
            ['color'])
    return sequence


@staticmethod
def interpolate_list(timeseries_list, timestep):
    """ Interpolates timeseries list with new timestep
        :param timestep:
        :return:
        """
    result_list = {}
    for name, ts in timeseries_list.items():
        ts_intp = ts.interpolate(timestep)
        result_list[ts_intp.name] = ts_intp
    return result_list


def copy_to(input, ctx):
    """Copy the given tensor to the context.

    Parameters
    ----------
    input : Tensor
        The input tensor
    ctx :
        A framework-specific context object.

    Returns
    -------
    Tensor
        The tensor on the given context.
    """
    pass


def int_to_binstr(i, bits):
    """Convert integer to a '01' string.

    Args:
        bits (int): Number of bits for this integer.

    Returns:
        str: binary representation of the integer.

    """
    output = ''
    for j in range(0, bits):
        bit = (i & 1 << j) >> j
        output = str(bit) + output
    return output


def psi_Ca_K_Cl_PK74(T, P):
    """c-c'-a: calcium potassium chloride [PK74]."""
    psi = -0.015
    valid = T == 298.15
    return psi, valid


@classmethod
def Register4(cls, *args, **kwargs):
    """
`Register4(...)` is a shortcut for `RegisterAt(4, ...)`

**Also See**

* `phi.builder.Builder.RegisterAt`
* `phi.builder.Builder.RegisterMethod`
        """
    return cls.RegisterAt(4, *args, **kwargs)


def create_hue_success_response(entity_id, attr, value):
    """Create a success response for an attribute set on a light."""
    success_key = f'/lights/{entity_id}/state/{attr}'
    return {'success': {success_key: value}}


@classmethod
def object(cls, pos, keys, children):
    """Create a Node object from params.

        Keyword argument:
            pos -- node's file index
            values -- a tuple with position, keys and children
        """
    keys = list(zip(*([iter(keys)] * 2)))
    return cls(pos, keys=keys, children=children)


def countLines(fname):
    """Returns the number of lines in a file"""
    with open(fname) as f:
        for i, l in enumerate(f):
            pass
    return i + 1


def closestpredecessors(repo, nodeid):
    """yield the list of next predecessors pointing on visible changectx nodes

    This function respect the repoview filtering, filtered revision will be
    considered missing.
    """
    precursors = repo.obsstore.predecessors
    stack = [nodeid]
    seen = set(stack)
    while stack:
        current = stack.pop()
        currentpreccs = precursors.get(current, ())
        for prec in currentpreccs:
            precnodeid = prec[0]
            if precnodeid in seen:
                continue
            seen.add(precnodeid)
            if precnodeid in repo:
                yield precnodeid
            else:
                stack.append(precnodeid)


def split():
    """Split selected strips at their midpoints

    """
    pass


@classmethod
def fromkeys(cls, keys, value=None):
    """Creates a new trie with given keys set.

        This is roughly equivalent to calling the constructor with a ``(key,
        value) for key in keys`` generator.

        Args:
            keys: An iterable of keys that should be set in the new trie.
            value: Value to associate with given keys.

        Returns:
            A new trie where each key from ``keys`` has been set to the given
            value.
        """
    trie = cls()
    for key in keys:
        trie[key] = value
    return trie


def extract_bits(data, shift, length):
    """Extract a portion of a bit string. Similar to substr()."""
    bitmask = (1 << length) - 1 << shift
    return (data & bitmask) >> shift


def plot_stations(inventory, fname, ext='png', projection='local', **kwargs):
    """
    Plot station map

    :param inventory: |Inventory| object with coordinates
    :param projection,\\*\\*kwargs: passed to |Inventory.plot| method
    """
    inventory.plot(projection, outfile=fname + '.' + ext, **kwargs)


def encode_blob(value):
    """Encode a blob, this is actually a link which
	may point to an S3 location"""
    from StringIO import StringIO
    ret = {'__type__': '__blob__'}
    if not isinstance(value.file, StringIO):
        ret['__href__'] = value.file.generate_url(3600)
    return ret


def select_loose(extend: bool=False):
    """Select loose geometry based on the selection mode

    :param extend: Extend, Extend the selection
    :type extend: bool
    """
    pass


@classmethod
def y_unit_vector(cls):
    """Returns the unit vector (0 | 1 | 0)"""
    return cls(0, 1, 0)


@classmethod
def expand(cls, aliases, tree):
    """Expand aliases in tree, recursively.

        'aliases' is a dictionary mapping user defined aliases to alias objects.
        """
    return cls._expand(aliases, tree, [], {})


def _serp_query_string(parse_result):
    """
    Some search engines contain the search keyword in the fragment so we
    build a version of a query string that contains the query string and
    the fragment.

    :param parse_result: A URL.
    :type parse_result:  :class:`urlparse.ParseResult`
    """
    query = parse_result.query
    if parse_result.fragment != '':
        query = '{}&{}'.format(query, parse_result.fragment)
    return query


def extract_div(search, data):
    """ extract <div> record. """
    from bs4 import BeautifulSoup
    soup = BeautifulSoup(data)
    divs = soup('div')
    for div in divs:
        if div.get(search):
            return div


def getTermByToken(token):
    """Return an ITokenizedTerm for the passed-in token.

        If `token` is not represented in the vocabulary, `LookupError`
        is raised.
        """


def remove_extra_spaces(inputstr):
    """Remove extra spaces in *inputstr* so that there are only single spaces.

    Parameters
    ----------
    inputstr : str

    Returns
    -------
    str
    """
    while '  ' in inputstr:
        inputstr = inputstr.replace('  ', ' ')
    return inputstr.strip()


@classmethod
def available(cls, cmd_binary=None):
    """
        Class method that reports whether the command binary is
        available.
        """
    if cmd_binary is None:
        cmd_binary = cls.cmd_binary
    if not cmd_binary:
        return False
    try:
        cls._execute(cmd_binary=cmd_binary)
    except OSError:
        return False
    return True


def colors(graph, node_type_attr='type'):
    """
    Utility function that generates colors for node
    types for drawing graph in Ipython Notebook.

    :param graph: networkx.Graph
    :returns: Dict. Nodes as keys, colors as values.
    """
    colors_dict = {}
    colors = []
    counter = 1
    for node, attrs in graph.nodes(data=True):
        if attrs[node_type_attr] not in colors_dict:
            colors_dict[attrs[node_type_attr]] = float(counter)
            colors.append(float(counter))
            counter += 1
        else:
            colors.append(colors_dict[attrs[node_type_attr]])
    return colors


def setInitialState(state, comment=None):
    """Set initial state for the context object.

        Will also set a unique id for this new workflow.

        Fires a transition event.
        """


def __init__(name, paths):
    """Create the XMI node.

        @param name: the name of the XMI node
        @param paths: contains a list of xml file names.
        """


def _get_platform_builder_group_name(platform_name):
    """
    Returns the logGroup name of associated with the custom platform identified by `platform_name`
    :param platform_name: A custom platform whose logs to stream
    :return:
    """
    return '/aws/elasticbeanstalk/platform/{}'.format(platform_name)


def count_reads(exons, ckreads, multiple, stranded):
    """Adds (#aligned nucleotides/read length) to exon counts.
    Deals with indels, junctions etc.
    :param multiple: divide the count by the NH tag.
    :param stranded: for strand-specific protocols, use the strand information."""
    current_idx = 0
    nexons = len(exons)
    for alignment in ckreads:
        if current_idx >= nexons:
            return 0
        exon_end = exons[current_idx].end
        ali_pos = alignment.pos
        while exon_end <= ali_pos:
            current_idx += 1
            if current_idx >= nexons:
                return 0
            exon_end = exons[current_idx].end
        idx2 = current_idx
        exon_start = exons[idx2].start
        read_len = alignment.rlen
        ali_len = 0
        for op, shift in alignment.cigar:
            if op in [0, 2, 3]:
                if ali_pos < exon_start:
                    pos = ali_pos
                    ali_pos = min(exon_start, pos + shift)
                    shift = max(0, pos + shift - exon_start)
                while ali_pos + shift >= exon_end:
                    if op == 0:
                        ali_len += exon_end - ali_pos
                        exons[idx2].increment(float(ali_len) / float(
                            read_len), alignment, multiple, stranded)
                    shift -= exon_end - ali_pos
                    ali_pos = exon_end
                    ali_len = 0
                    idx2 += 1
                    if idx2 >= nexons:
                        return 0
                    exon_start = exons[idx2].start
                    exon_end = exons[idx2].end
                    if ali_pos < exon_start:
                        pos = ali_pos
                        ali_pos = min(exon_start, pos + shift)
                        shift = max(0, pos + shift - exon_start)
                if op == 0:
                    ali_len += shift
                ali_pos += shift
            elif op == 1:
                ali_len += shift
        exons[idx2].increment(float(ali_len) / float(read_len), alignment,
            multiple, stranded)


@classmethod
def as_decorator(cls, func=None, **kwargs):
    """
        A decorator for validating the units of arguments to functions.

        Unit specifications can be provided as keyword arguments to the decorator,
        or by using function annotation syntax. Arguments to the decorator
        take precedence over any function annotations present.

        A `~astropy.units.UnitsError` will be raised if the unit attribute of
        the argument is not equivalent to the unit specified to the decorator
        or in the annotation.
        If the argument has no unit attribute, i.e. it is not a Quantity object, a
        `ValueError` will be raised unless the argument is an annotation. This is to
        allow non Quantity annotations to pass through.

        Where an equivalency is specified in the decorator, the function will be
        executed with that equivalency in force.

        Notes
        -----

        The checking of arguments inside variable arguments to a function is not
        supported (i.e. \\*arg or \\**kwargs).

        Examples
        --------

        .. code-block:: python

            import astropy.units as u
            @u.quantity_input(myangle=u.arcsec)
            def myfunction(myangle):
                return myangle**2

        .. code-block:: python

            import astropy.units as u
            @u.quantity_input
            def myfunction(myangle: u.arcsec):
                return myangle**2

        Also you can specify a return value annotation, which will
        cause the function to always return a `~astropy.units.Quantity` in that
        unit.

        .. code-block:: python

            import astropy.units as u
            @u.quantity_input
            def myfunction(myangle: u.arcsec) -> u.deg**2:
                return myangle**2

        Using equivalencies::

            import astropy.units as u
            @u.quantity_input(myenergy=u.eV, equivalencies=u.mass_energy())
            def myfunction(myenergy):
                return myenergy**2

        """
    self = cls(**kwargs)
    if func is not None and not kwargs:
        return self(func)
    else:
        return self


def grep_gtf(args, gene_ids, mrna_ids):
    """
    Grep-like main function for *GTF* files.
    :param args:
    :return:

    :param gene_ids: set of gene IDs to retain/discard.
    :type gene_ids: set

    :param mrna_ids: set of mRNA IDs to retain/discard.
    :type mrna_ids: set

    """
    for record in args.gff:
        if not record:
            continue
        if args.genes is False:
            if record.transcript in mrna_ids:
                if not args.reverse:
                    print(record, file=args.out)
                elif args.reverse:
                    print(record, file=args.out)
        elif record.gene in gene_ids:
            if not args.reverse:
                print(record, file=args.out)
            elif args.reverse:
                print(record, file=args.out)


@classmethod
def KeyError(cls, out_type, name='dictionary'):
    """
        Create an instance of this class suitable for handling
        occurrences of :py:exc:`KeyError` caused by, e.g. dictionary
        access via :py:meth:`~object.__getitem__`.

        :py:attr:`in_type` is implicitly :py:exc:`KeyError` and `name`
        is the name of the dictionary where the error occurred.
        """
    return cls(KeyError, out_type, "Missing '{str}' from {name}", name=name)


def aliases(metadata_dict):
    """Return a list of package aliases found in metadata's 'aliases' field."""
    if 'aliases' not in metadata_dict:
        return []
    import re
    return re.split(',\\s*|\\s+', metadata_dict['aliases'])


@staticmethod
def compare_models(src_model, target_model):
    """
        This method compares two models
        :param src_model: the source energy model in Model object
        :param target_model: the target energy model in Model object
        :type src_model: Model()
        :type target_model: Model()
        :return: none - you will be prompt to a page
        """
    src_model.model_compare(target_model.track_token)
    return


@classmethod
def get_transactions_testnet(cls, address):
    """Gets the ID of all transactions related to an address on the test
        network.

        :param address: The address in question.
        :type address: ``str``
        :raises ConnectionError: If all API services fail.
        :rtype: ``list`` of ``str``
        """
    for api_call in cls.GET_TRANSACTIONS_TEST:
        try:
            return api_call(address)
        except cls.IGNORED_ERRORS:
            pass
    raise ConnectionError('All APIs are unreachable.')


def handle_notes_save(args, configs):
    """Handle the `save` subcommand` of the `notes` subcommand`

    :param args: parsed arguments
    :type args: :py:class:`argparse.Namespace`
    :param configs: configurations object
    :type configs: :py:class:`sfftk.core.configs.Configs`
    :return exit_status: exit status
    :rtype exit_status: int
    """
    from sfftk.notes.modify import save
    return save(args, configs)


def set_test_mode(max_length_threshold: int=244):
    """Only used for unit testing
    """
    global test_mode
    global FULL_LENGTH_WARNING_THRESHOLD
    test_mode = True
    FULL_LENGTH_WARNING_THRESHOLD = max_length_threshold


def p_constant(t):
    """constant : CONST10
                | CONST8
                | CONST16"""
    if len(t[1]) > 9:
        t[0] = t[1] + 'L'
    else:
        t[0] = t[1]


@conf
def modfile(conf, name):
    """
	Turns a module name into the right module file name.
	Defaults to all lower case.
	"""
    if name.find(':') >= 0:
        separator = conf.env.FC_SUBMOD_SEPARATOR or '@'
        modpath = name.split(':')
        modname = modpath[0] + separator + modpath[-1]
        suffix = conf.env.FC_SUBMOD_SUFFIX or '.smod'
    else:
        modname = name
        suffix = '.mod'
    return {'lower': modname.lower() + suffix.lower(), 'lower.MOD': modname
        .lower() + suffix.upper(), 'UPPER.mod': modname.upper() + suffix.
        lower(), 'UPPER': modname.upper() + suffix.upper()}[conf.env.
        FC_MOD_CAPITALIZATION or 'lower']


def render_pep440_pre(pieces):
    """TAG[.post.devDISTANCE] -- No -dirty.

    Exceptions:
    1: no tags. 0.post.devDISTANCE
    """
    if pieces['closest-tag']:
        rendered = pieces['closest-tag']
        if pieces['distance']:
            rendered += '.post.dev%d' % pieces['distance']
    else:
        rendered = '0.post.dev%d' % pieces['distance']
    return rendered


@classmethod
def empty_character(cls):
    """Raise PushError when Character is made from empty string."""
    return cls('Char object cannot be created from empty string.')


def list_commands(client):
    """List AMI commands.

	Args:
	    :client: the pyAMI client [ pyAMI.client.Client ]

	Returns:
	    an array of python dictionnaries.
	"""
    command = ['AMIListCommands']
    return client.execute(command, format='dom_object').get_rows()


def updating_node_validation_error(address=False, port=False, id=False,
    weight=False):
    """
    Verified 2015-06-16:

    - when trying to update a CLB node's address/port/id, which are
      immutable.
    - when trying to update a CLB node's weight to be < 1 or > 100

    At least one of address, port, id, and weight should be `True` for this
    error to apply.

    :param bool address: Whether the address was passed to update
    :param bool port: Whether the port was passed to update
    :param bool id: Whether the ID was passed to update
    :param bool weight: Whether the weight was passed to update and wrong

    :return: a `tuple` of (dict body message, 400 http status code)
    """
    messages = []
    if address:
        messages.append('Node ip field cannot be modified.')
    if port:
        messages.append('Port field cannot be modified.')
    if weight:
        messages.append(
            'Node weight is invalid. Range is 1-100. Please specify a valid weight.'
            )
    if id:
        messages.append('Node id field cannot be modified.')
    return {'validationErrors': {'messages': messages}, 'message':
        'Validation Failure', 'code': 400, 'details': 'The object is not valid'
        }, 400


def extract_div(search, data):
    """ extract <div> record. """
    from bs4 import BeautifulSoup
    soup = BeautifulSoup(data)
    divs = soup('div')
    for div in divs:
        if div.get(search):
            return div


@classmethod
def fromdict(cls, mapping):
    """
        Create a new `udict` from the given `mapping` dict.
        The resulting `udict` will be equivalent to the input
        `mapping` dict but with all dict instances (recursively)
        converted to an `udict` instance.  If you don't want
        this behavior (i.e., you want sub-dicts to remain plain dicts),
        use `udict(mapping)` instead.
        """
    ud = cls()
    for k in mapping:
        v = dict.__getitem__(mapping, k)
        if isinstance(v, dict):
            v = cls.fromdict(v)
        dict.__setitem__(ud, k, v)
    return ud


def cleanup_test_name(name, strip_tags=True, strip_scenarios=False):
    """Clean up the test name for display.

    By default we strip out the tags in the test because they don't help us
    in identifying the test that is run to it's result.

    Make it possible to strip out the testscenarios information (not to
    be confused with tempest scenarios) however that's often needed to
    indentify generated negative tests.
    """
    if strip_tags:
        tags_start = name.find('[')
        tags_end = name.find(']')
        if tags_start > 0 and tags_end > tags_start:
            newname = name[:tags_start]
            newname += name[tags_end + 1:]
            name = newname
    if strip_scenarios:
        tags_start = name.find('(')
        tags_end = name.find(')')
        if tags_start > 0 and tags_end > tags_start:
            newname = name[:tags_start]
            newname += name[tags_end + 1:]
            name = newname
    return name


def load_bedrock_from_github(bedrock_process_name):
    """ Load bedrock from GitHub as TM1py.Process instance

    :param bedrock_process_name:
    :return:
    """
    import requests
    from TM1py.Objects import Process
    url = (
        'https://raw.githubusercontent.com/MariusWirtz/bedrock/master/json/{}.json'
        .format(bedrock_process_name))
    process_as_json = requests.get(url).text
    return Process.from_json(process_as_json)


def get_licensing_info(isamAppliance, check_mode=False, force=False):
    """
    Retrieve the licensing information
    """
    return isamAppliance.invoke_get('Retrieve the licensing information',
        '/lum/is_licensed')


def put_inventory(InstanceId=None, Items=None):
    """
    Bulk update custom inventory items on one more instance. The request adds an inventory item, if it doesn't already exist, or updates an inventory item, if it does exist.
    See also: AWS API Documentation

    :example: response = client.put_inventory(
        InstanceId='string',
        Items=[
            {
                'TypeName': 'string',
                'SchemaVersion': 'string',
                'CaptureTime': 'string',
                'ContentHash': 'string',
                'Content': [
                    {
                        'string': 'string'
                    },
                ]
            },
        ]
    )

    :type InstanceId: string
    :param InstanceId: [REQUIRED]
            One or more instance IDs where you want to add or update inventory items.

    :type Items: list
    :param Items: [REQUIRED]
            The inventory items that you want to add or update on instances.
            (dict) --Information collected from managed instances based on your inventory policy document
            TypeName (string) -- [REQUIRED]The name of the inventory type. Default inventory item type names start with AWS. Custom inventory type names will start with Custom. Default inventory item types include the following: AWS:AWSComponent, AWS:Application, AWS:InstanceInformation, AWS:Network, and AWS:WindowsUpdate.
            SchemaVersion (string) -- [REQUIRED]The schema version for the inventory item.
            CaptureTime (string) -- [REQUIRED]The time the inventory information was collected.
            ContentHash (string) --MD5 hash of the inventory item type contents. The content hash is used to determine whether to update inventory information. The PutInventory API does not update the inventory item type contents if the MD5 hash has not changed since last update.
            Content (list) --The inventory data of the inventory type.
            (dict) --
            (string) --
            (string) --

    :rtype: dict
    :return: {}

    :returns:
    (dict) --

    """
    pass


def _resolve_subkeys(key, separator='.'):
    """Resolve a potentially nested key.

    If the key contains the ``separator`` (e.g. ``.``) then the key will be
    split on the first instance of the subkey::

       >>> _resolve_subkeys('a.b.c')
       ('a', 'b.c')
       >>> _resolve_subkeys('d|e|f', separator='|')
       ('d', 'e|f')

    If not, the subkey will be :data:`None`::

        >>> _resolve_subkeys('foo')
        ('foo', None)

    Args:
        key (str): A string that may or may not contain the separator.
        separator (str): The namespace separator. Defaults to `.`.

    Returns:
        Tuple[str, str]: The key and subkey(s).
    """
    parts = key.split(separator, 1)
    if len(parts) > 1:
        return parts
    else:
        return parts[0], None


def _generate_symbol(path, width, height, command='C'):
    """Sequence generator for SVG path."""
    if len(path) == 0:
        return
    yield 'M'
    yield path[0].anchor[1] * width
    yield path[0].anchor[0] * height
    yield command
    points = zip(path, path[1:] + path[0:1]) if path.is_closed() else zip(path,
        path[1:])
    for p1, p2 in points:
        yield p1.leaving[1] * width
        yield p1.leaving[0] * height
        yield p2.preceding[1] * width
        yield p2.preceding[0] * height
        yield p2.anchor[1] * width
        yield p2.anchor[0] * height
    if path.is_closed():
        yield 'Z'


def palettecolor_lock_all():
    """Lock all Grease Pencil colors to prevent them from being accidentally modified

    """
    pass


@classmethod
def write_str(cls, opc_sync: bool, total_size: int, context: str
    ) ->'IoTransferEventArgs':
    """Creates new IoTransferEventArgs of write string

		:param opc_sync: defines if the command is OPC-synchronised
		:param total_size: size of the data to write
		:param context: SCPI command write. It is truncated to maximum of 100 characters.
		:return: IoTransferEventArgs object of a write string operation."""
    obj = cls(False, opc_sync, total_size, context)
    obj.binary = False
    return obj


@staticmethod
def p_statement_expr(p):
    """statement : expression"""
    p[0] = p[1]


@classmethod
def stop_notifying(cls, user_or_email_, **filters):
    """Delete all watches matching the exact user/email and filters.

        Delete both active and inactive watches. If duplicate watches
        exist due to the get-then-create race condition, delete them all.

        Implementations in subclasses may take different arguments; see the
        docstring of :meth:`is_notifying()`.

        """
    cls._watches_belonging_to_user(user_or_email_, **filters).delete()