Skip to main content

Emotion algebra based on Plutchik's Wheel and Cambria's Hourglass of Emotions — signed integer arithmetic over a 4-axis affective space

Project description

emotion-algebra

Signed integer arithmetic over a 4-axis affective space, grounded in Plutchik's Wheel of Emotions (1980) and Cambria's Hourglass of Emotions (2012). Emotions are first-class mathematical objects; every operator returns a typed result.

from emotion_algebra.emotions import get_emotion

anger = get_emotion("anger")

anger + 1          # → rage          (intensity up)
anger - 1          # → annoyance     (intensity down)
-anger             # → fear          (opposite pole)
anger >> 2         # → hyper anger
anger * fear       # → CompositeEmotion (cross-axis product)

Installation

pip install emotion-algebra

Optional extras:

Extra Deps Enables
[lexicon] pandas lexicons.py — word→emotion CSV lookup
[fast] ahocorasick-ner Phrase-aware Aho-Corasick backend for score_text/from_text

deepmoji-onnx is a core dependency — neural text→emoji→emotion scoring via DeepMojiONNXAdapter is always available.


The model

Four axes (Cambria 2012)

Axis Positive pole Negative pole Hedonic?
Sensitivity rage → anger → annoyance apprehension → fear → terror No
Attention vigilance → anticipation → interest distraction → surprise → amazement No
Pleasantness ecstasy → joy → serenity pensiveness → sadness → grief Yes
Aptitude admiration → trust → acceptance boredom → disgust → loathing Yes

Each axis has three integer intensity levels: ±1 (mild), ±2 (primary), ±3 (intense).

Valence and arousal (Russell 1980)

  • Valence — Pleasantness axis only. anger.valence == 0; joy.valence == 2.
  • Arousalabs(emotional_flow). Axis-independent activation intensity.
  • Type — Russell Circumplex quadrant: "excited positive", "calm positive", "excited negative", "calm negative", "activated neutral", "neutral".

Feelings (Plutchik dyads)

from emotion_algebra.emotions import get_emotion
joy   = get_emotion("joy")
trust = get_emotion("trust")
joy + trust   # → Feeling("love")

Feature overview

Feature API Module
Core emotion algebra Emotion, +, -, *, <<, >> plutchik.py
Named feelings (dyads) Feeling, get_feeling() feelings.py
Multi-axis composites CompositeEmotion composite_emotions.py
Continuous space FloatEmotion, from_embedding() float_emotion.py
Stateful accumulation EmotionalState, EmotionTimeline state.py
Word lexicon from_text(), score_text() text.py
Emoji mapping from_emoji(), score_emojis(), DeepMojiAdapter emoji.py
Mixed word+emoji score_mixed(), from_mixed() text.py
Geometry emotion_distance(), closest_emotion() distance.py
Cognitive appraisal Appraisal, appraisal_to_emotion() appraisal.py
Continuous appraisal appraisal_to_float_emotion(), float_emotion_to_neuro_deltas() appraisal.py
Emotion blending FloatEmotion.blend(joy, trust) float_emotion.py
Need-deficit emotions need_deficit_to_emotion(), CIADrive, MaxNeefNeed, MurrayNeed needs.py
Behavioural reactions REACTIONS, REACTION_TO_EMOTION_MAP behaviour.py
CLI python -m emotion_algebra __main__.py

Quick reference

from emotion_algebra import (
    get_emotion, get_feeling,
    EmotionalState, EmotionTimeline,
    from_text, score_text, score_mixed, from_mixed,
    from_emoji, score_emojis, DeepMojiAdapter,
    register_emoji, unregister_emoji,
    emotion_distance, closest_emotion, emotion_clusters,
    Appraisal, appraisal_to_emotion, appraisal_to_float_emotion,
    float_emotion_to_neuro_deltas,
    FloatEmotion,
    CIADrive, MaxNeefNeed, MurrayNeed,
    need_deficit_to_emotion, need_deficit_to_float_emotion,
)

# --- Emotion properties ---
e = get_emotion("joy")
e.emotional_flow   # 2
e.valence          # 2    (pleasantness axis)
e.arousal          # 2
e.type             # "excited positive"
e.opposite_emotion # sadness
e.as_array         # np.array([0, 0, 2, 0])

# --- State accumulation ---
state = EmotionalState()
state.apply(get_emotion("joy"), weight=0.8)
state.apply(get_emotion("trust"), weight=0.5)
state.decay(0.9)
state.dominant()   # → Emotion or None

# --- Text analysis ---
from_text("rage and fury")          # → Emotion (lexicon)
score_mixed("I'm so happy 😄🎉")   # → EmotionalState (words + emoji)
from_mixed("grief 😭")             # → dominant Emotion

# --- Emoji ---
from_emoji("😊")                   # → Emotion("serenity")
register_emoji("🤖", "trust")      # custom mapping

# --- DeepMoji bridge ---
adapter = DeepMojiAdapter()
adapter.from_scores({"😂": 0.6, "😭": 0.4})  # → Emotion
adapter.score_state({"😂": 0.6, "😭": 0.4})  # → EmotionalState

# --- Geometry ---
a, b = get_emotion("anger"), get_emotion("joy")
emotion_distance(a, b)             # Euclidean distance in 4D Hourglass space
closest_emotion([2, 0, 1, 0])     # nearest named Emotion to a float vector

# --- Cognitive appraisal (Scherer CPM) ---
# Discrete (v1): categorical fields → named Emotion
a = Appraisal(goal_relevance="relevant", goal_congruence="incongruent",
              agency="other", coping_potential="low")
appraisal_to_emotion(a)           # → fear

# Continuous (v2): float fields → FloatEmotion → neuro deltas
a = Appraisal(novelty=0.8, goal_relevance=0.9, goal_congruence=0.3,
              coping_potential=0.2, intrinsic_pleasantness=0.4)
fe = appraisal_to_float_emotion(a)
d, s, adr = float_emotion_to_neuro_deltas(fe)  # (dopamine, serotonin, adrenaline)

# --- Emotion blending ---
joy   = get_emotion("joy")
trust = get_emotion("trust")
FloatEmotion.blend(joy, trust)                 # → pleasantness + aptitude
FloatEmotion.blend(joy, trust, weights=[0.7, 0.3], scale=0.8)

# --- Need-deficit emotions (Max-Neef + Murray) ---
need_deficit_to_emotion(MaxNeefNeed.PROTECTION)  # → fear
need_deficit_to_emotion(MurrayNeed.NURTURANCE)   # → sadness
need_deficit_to_float_emotion("freedom")          # → FloatEmotion (anger axis)

# --- Continuous space ---
FloatEmotion(sensitivity=1.5, pleasantness=-0.8)
FloatEmotion.from_embedding(np.array([0.3, -0.1, 0.7, 0.2]))

CLI

# Info about an emotion, feeling, or dimension
python -m emotion_algebra info anger
python -m emotion_algebra info love
python -m emotion_algebra info pleasantness

# Evaluate an expression
python -m emotion_algebra "joy + trust"
python -m emotion_algebra "rage - 1"

# Single emoji
python -m emotion_algebra 😊

# Interactive REPL (all 24 emotions pre-loaded)
python -m emotion_algebra

Scientific references

  • Plutchik, R. (1980). A general psychoevolutionary theory of emotion. In R. Plutchik & H. Kellerman (Eds.), Emotion: Theory, research, and experience (Vol. 1, pp. 3–33).
  • Cambria, E., Livingstone, A., & Hussain, A. (2012). The Hourglass of Emotions. In A. Esposito et al. (Eds.), Cognitive Behavioural Systems, LNCS 7403.
  • Russell, J. A. (1980). A circumplex model of affect. Journal of Personality and Social Psychology, 39(6), 1161–1178.
  • Posner, J., Russell, J. A., & Peterson, B. S. (2005). The circumplex model of affect: An integrative approach. Development and Psychopathology, 17(3), 715–734.
  • Felbo, B., Mislove, A., Søgaard, A., Rahwan, I., & Lehmann, S. (2017). Using millions of emoji occurrences to learn any-domain representations for detecting sentiment, emotion and sarcasm. EMNLP 2017.
  • Scherer, K. R. (2001). Appraisal considered as a process of multilevel sequential checking. In K. R. Scherer et al. (Eds.), Appraisal processes in emotion (pp. 92–120).
  • Max-Neef, M. (1991). Human Scale Development: Conception, Application and Further Reflections. Apex Press.
  • Murray, H. A. (1938). Explorations in Personality. Oxford University Press.
  • Lövheim, H. (2012). A new three-dimensional model for emotions and monoamine neurotransmitters. Medical Hypotheses, 78(2), 341–348.

License

Apache 2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

emotion_algebra-1.1.0a1.tar.gz (556.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

emotion_algebra-1.1.0a1-py3-none-any.whl (547.6 kB view details)

Uploaded Python 3

File details

Details for the file emotion_algebra-1.1.0a1.tar.gz.

File metadata

  • Download URL: emotion_algebra-1.1.0a1.tar.gz
  • Upload date:
  • Size: 556.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for emotion_algebra-1.1.0a1.tar.gz
Algorithm Hash digest
SHA256 da4ae82be7d389517233be8ee50e6ead8b05882be0b6333c0bd251f34b3c3d3e
MD5 beb4ff2225247232c390305bc4d1474f
BLAKE2b-256 8fc37146fcd560e72e18abee884fba9d0eb1b1d2f5844b34f5c76494bac696e7

See more details on using hashes here.

File details

Details for the file emotion_algebra-1.1.0a1-py3-none-any.whl.

File metadata

File hashes

Hashes for emotion_algebra-1.1.0a1-py3-none-any.whl
Algorithm Hash digest
SHA256 4d5e439bc72cdc73594a54cc95f4c6368af323a1e70d5b5966f7f67c1d0d76b1
MD5 cdc49c5942b3f06a848ba478c1343977
BLAKE2b-256 ad897f0c45ca2ddd336400ff910f3c8afb51f7c540ce6a9d2ac04616bf26e471

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page