Source code for planetmagfields.utils

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
import importlib
import importlib.util
import numpy as np
from .models import planetlist

stdDatDir = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'data/')

UNITS = {
    'nt':    (1.,   'nT'),
    'mut':   (1e-3, r'$\mu$T'),
    'gauss': (1e-5, 'Gauss'),
}

UNIT_TEXT = {'nt': 'nT', 'mut': 'μT', 'gauss': 'G'}

INSTALL_HINTS = {
    'shtns':   'https://bitbucket.org/nschaeff/shtns',
    'pyevtk':  'pip install pyevtk',
    'pyvista': 'pip install pyvista',
    'cartopy': 'pip install cartopy',
}


def get_unit(units):
    """Returns (factor, label) converting nT to the requested units."""
    try:
        return UNITS[units.lower()]
    except KeyError:
        raise ValueError("Unknown units '%s', must be one of 'nT', 'muT' or 'Gauss'"
                         % units) from None


def unit_text(units):
    """Plain text unit label, e.g. for plotly figures."""
    get_unit(units)
    return UNIT_TEXT[units.lower()]


def has_module(name):
    return importlib.util.find_spec(name) is not None


def require(name):
    """Imports an optional dependency, raising an ImportError with an
    installation hint if it is missing."""
    try:
        return importlib.import_module(name)
    except ImportError as exc:
        pkg = name.split('.')[0]
        raise ImportError("This requires the %s library: %s"
                          % (pkg, INSTALL_HINTS.get(pkg, 'pip install ' + pkg))) from exc


[docs] def get_models(planetname,datDir=stdDatDir): """Prints available models for a planet. Parameters ---------- datDir : str Directory where the data file is present. Files are assumed to be named as <planetname>_<modelname>.dat, e.g.: earth_igrf13.dat, jupiter_jrm09.dat etc. planetname : str Name of the planet Returns ------- models : str array Array of available model names """ from glob import glob planetname = planetname.lower() dataFiles = glob(os.path.join(datDir, planetname+"_*.dat")) models = [os.path.basename(f)[len(planetname)+1:-len('.dat')] for f in dataFiles] return np.sort(models)
def is_dark_color(color): """ Determine if a color is dark using relative luminance. Parameters ---------- color : str or tuple Color as hex string ('#RRGGBB'), RGB tuple (r, g, b) with values 0-255, or normalized RGB tuple (r, g, b) with values 0-1. Returns ------- bool True if color is dark, False if light. """ # Parse color to RGB values (0-255) if isinstance(color, str): color = color.lstrip('#') if len(color) == 6: r, g, b = tuple(int(color[i:i+2], 16) for i in (0, 2, 4)) elif len(color) == 3: r, g, b = tuple(int(c*2, 16) for c in color) else: # Named colors import matplotlib.colors as mcolors rgb = mcolors.to_rgb(color) r, g, b = int(rgb[0]*255), int(rgb[1]*255), int(rgb[2]*255) elif isinstance(color, (tuple, list)): if all(0 <= c <= 1 for c in color): # Normalized RGB r, g, b = int(color[0]*255), int(color[1]*255), int(color[2]*255) else: # 0-255 RGB r, g, b = color[0], color[1], color[2] else: raise ValueError(f"Unknown color format: {color}") # Calculate relative luminance (ITU-R BT.709) # Human eye is most sensitive to green, least to blue luminance = (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255 # Threshold of 0.5 is standard; can adjust based on preference return luminance < 0.5