Skip to main content

Al Faraheedy Python: A Pythonized version of the Arabic Poetry Rhythm and Rhyme Analyzer Project

Project description

Al-Faraheedy-Python

PyPI version Python version License Downloads

مكتبة بايثون تغلّف نظام الفراهيدي لحوسبة عروض الشعر العربي و قافيته

Al Faraheedy Python: A Pythonized version of the Arabic Poetry Rhythm and Rhyme Analyzer Project

A comprehensive Python library for analyzing Arabic poetry, including classical and free verse forms. This is a Python wrapper and enhancement of the original Faraheedy system for computational analysis of Arabic prosody and rhyme. Named after Al-Khalil ibn Ahmad al-Farahidi (الخليل بن أحمد الفراهيدي), the founder of Arabic prosody.

Original Idea (old unmaintained project): https://github.com/muktarsayedsaleh/Al-Faraheedy-Project

Warning

This module was converted from PHP to Python very quickly so I have not tested it well. I'm anticipating bugs here and there. so contributions are welcomed

تحذير

قمت بتحويل هذه الشيفرة البرمجية من بي إتش بي إلى بايثون بشكل سريع و دون اختبارات مكثفة كتلك التي تمت على نسخة بي اتش بي المستقرّة، لذلك أتوقع ظهور بعض الأخطاء البرمجية و أرحّب بتصحيحاتها المقترحة من قبلكم

Features

  • Classical Poetry Analysis (تحليل الشعر العمودي)

    • Meter identification for 29+ Arabic meters (Poetry "seas") - تحليل بحور الشعر العربي بصورها التامة و غير التامة
    • Prosodic pattern analysis (العروض)
    • Automatic vowel lengthening for irregular patterns (الإشباع)
    • Advanced scansion algorithms
  • Free Verse Analysis (تحليل شعر التفعيلة)

    • Modern Arabic poetry analysis
    • Dominant meter detection
    • Flexible prosodic pattern matching
    • Multi-meter poem handling
  • Rhyme Analysis (تحليل القوافي)

    • Comprehensive rhyme scheme analysis
    • Identification of rhyme components:
      • الروي (Rawee - main rhyme letter)
      • الوصل (Wasel - connection)
      • الخروج (Kharoog - exit)
      • التأسيس (Ta2sees - foundation)
      • الردف (Redf - appendage)
      • الدخيل (Dakheel - intrusion)
    • Detection of rhyme defects (عيوب القافية)
  • Advanced Arabic Linguistic Processing

    • Special Arabic grammatical cases handling
    • Lunar/Solar lam (اللام القمرية والشمسية) processing
    • Hamzat wasl (همزة الوصل) rules implementation
    • Tanween (التنوين) and shaddah (الشدة) processing
    • Divine name variations (لفظ الجلالة)
    • Demonstrative pronouns (أسماء الإشارة)
    • Relative pronouns (الأسماء الموصولة)

Installation

pip install al-faraheedy-python

Quick Start

from al_faraheedy import ArabicPoetryAnalyzer

analyzer = ArabicPoetryAnalyzer()

# Analyze classical verse
poem = [
    "ما بيْن مفْترقٍ و مفْترقِ",
    "ممْلوْءةٌ بمقاتليْ طرقيْ",
    "أنّى التفتّ و حيْثما ضبحتْ",
    "خيْليْ أجدْ رأْسيْ على طبقِ",
    "فوْق الرِّماحِ أرى أعاديهُ",
    "حملوْهُ مفْغوْر الفم الدبقِ",
    "دمهُ يقطّر و هْو يلْعنهمْ",
    "لوْ كنْتُ منْ ماءٍ للمْ أرقِ",
]
for index, verse in enumerate(poem):
    is_ajez = any([index ==0, index % 2 == 0])  # عند تصريع القصيدة، نعامل صدر المطلع معاملة العجز في الإشباع
    result = analyzer.analyze_classical_verse(verse, is_ajez)
    print(f"Verse {index + 1}: {result}")


# Analyze rhyme patterns
verses = ["مفْترقِ", "طرقيْ", "طبقِ", "الدبقِ", "لمْ أرقِ"]
for index, verse in enumerate(verses):
    result = analyzer.analyze_rhyme_patterns(verse)
    print(f"Rhyme {index + 1}: {result}")

# Analyze free verse
free_result = analyzer.analyze_free_verse("تمهّل و لا تمْتحنّيْ بما لا أطيْقُ")
print(f"Free Verse Analysis: {free_result}")

API Reference

Core Classes

ArabicPoetryAnalyzer

The main class for poetry analysis with the following methods:

analyze_classical_verse(text: str, is_ajez: bool = False) -> Dict[str, Any]

Analyzes classical Arabic verse (الشعر العمودي).

Parameters:

  • text (str): The verse text to analyze
  • is_ajez (bool): Whether this is the second hemistich (العجز)

Returns:

  • Dictionary containing:
    • shater: The processed verse
    • arrodi: Prosodic writing (الكتابة العروضية)
    • chars: Extracted characters
    • harakat: Extracted diacritics
    • rokaz: Prosodic pattern (U and -)
    • ba7er_name: Identified meter name
    • tafa3eel: List of prosodic feet
analyze_free_verse(text: str) -> Dict[str, Any]

Analyzes free verse Arabic poetry (شعر التفعيلة).

Parameters:

  • text (str): The poem text to analyze

Returns:

  • Dictionary with analysis results or error message
analyze_rhyme_patterns(verses: List[str]) -> List[QafeehAnalysis]

Analyzes rhyme patterns in a series of verses.

Parameters:

  • verses (List[str]): List of verse endings (second hemistichs)

Returns:

  • List of QafeehAnalysis objects

Data Classes

QafeehAnalysis

Represents comprehensive rhyme analysis results:

@dataclass
class QafeehAnalysis:
    text: str          # Full rhyme text
    type: str          # Rhyme type description
    rawee: str         # الروي (main rhyme consonant)
    wasel: str         # الوصل (connection vowel)
    kharoog: str       # الخروج (exit sound)
    ta2ses: str        # التأسيس (foundation alif)
    dakheel: str       # الدخيل (intrusion)
    redf: str          # الردف (appendage)
    errors: List[str]  # Detected rhyme defects

Supported Arabic Meters (البحور المدعومة)

The library recognizes 29+ classical Arabic meters:

Primary Meters (البحور الأساسية)

  • الطويل (Taweel) - The most common meter in classical Arabic poetry
  • البسيط (Baseet) - Simple meter, widely used
  • الكامل (Kamel) - Perfect meter, frequently used
  • الرجز (Rajaz) - Trembling meter, common in didactic poetry
  • الرمل (Ramal) - Sand meter, lyrical and flowing
  • السريع (Saree') - Fast meter, energetic rhythm
  • الخفيف (Khafeef) - Light meter, graceful flow
  • المنسرح (Munsareh) - Flowing meter
  • الوافر (Wafer) - Abundant meter, rich sound
  • الهزج (Hazaj) - Rocking meter, musical quality
  • المتقارب (Mutakareb) - Approaching meter, uniform rhythm
  • المتدارك (Mutadarak) - Overtaking meter

Truncated Forms (المجزوءات)

  • مجزوء البسيط (Majzoo' Baseet)
  • مجزوء الكامل (Majzoo' Kamel)
  • مجزوء الرمل (Majzoo' Ramal)
  • مجزوء السريع (Majzoo' Saree')
  • مجزوء الخفيف (Majzoo' Khafeef)
  • مجزوء المنسرح (Majzoo' Munsareh)
  • مجزوء المتقارب (Majzoo' Mutakareb)
  • مجزوء المتدارك (Majzoo' Mutadarak)
  • مجزوء الوافر (Majzoo' Wafer)
  • مجزوء الرجز (Majzoo' Rajaz)

Rare and Specialized Meters (البحور النادرة والمتخصصة)

  • المقتضب (Muqtadab)
  • المجتث (Mujtath)
  • المضارع (Mudare')
  • منهوك الرجز (Manhook Rajaz)
  • مخلع البسيط (Mukhalla' Baseet)
  • أعاريض الكامل (A'areed Kamel)

Detailed Examples

Classical Poetry Analysis with Al-Mutanabbi

from al_faraheedy import ArabicPoetryAnalyzer

analyzer = ArabicPoetryAnalyzer()

# Famous verse by Al-Mutanabbi (المتنبي)
verse = "على قدْر أهْل العزْم تأْتي العزائمُ"
result = analyzer.analyze_classical_verse(verse)

print(f"Original: {verse}")
print(f"Prosodic writing: {result['arrodi']}")
print(f"Meter: {result['ba7er_name']}")  # Should identify as 'taweel'
print(f"Pattern: {result['rokaz']}")
print("Prosodic feet:")
for i in range(0, len(result['tafa3eel']), 2):
    foot_name = result['tafa3eel'][i]
    foot_text = result['tafa3eel'][i + 1] if i + 1 < len(result['tafa3eel']) else ''
    print(f"  {foot_name}: {foot_text}")

Comprehensive Rhyme Analysis

# Analyzing a complete qasida's rhyme scheme
verses = [
    "عَلَى قَدْرِ أَهْلِ الْعَزْمِ تَأْتِي الْعَزَائِمُ",  # First verse
    "وَتَأْتِي عَلَى قَدْرِ الْكِرَامِ الْمَكَارِمُ",        # Second verse  
    "وَتَعْظُمُ فِي عَيْنِ الصَّغِيرِ صِغَارُهَا",         # Third verse - should show error
]

# Extract the rhyme parts (second hemistichs)
rhyme_parts = ["الْعَزَائِمُ", "الْمَكَارِمُ", "صِغَارُهَا"]

rhyme_results = analyzer.analyze_rhyme_patterns(rhyme_parts)

for i, analysis in enumerate(rhyme_results):
    if hasattr(analysis, 'text'):
        print(f"\nVerse {i+1} Rhyme Analysis:")
        print(f"  Rhyme text: {analysis.text}")
        print(f"  Rhyme type: {analysis.type}")
        print(f"  Rawee (main letter): {analysis.rawee}")
        print(f"  Wasel (connection): {analysis.wasel}")
        print(f"  Redf (appendage): {analysis.redf}")
        
        if analysis.errors:
            print(f"  ❌ Errors detected:")
            for error in analysis.errors:
                print(f"    - {error}")
        else:
            print(f"  ✅ Rhyme is consistent")

Free Verse Analysis with Modern Poetry

# Modern Arabic poem by Mahmoud Darwish style
modern_poem = '''
وَنَحْنُ نُحِبُّ الحَيَاةَ إذَا مَا اسْتَطَعْنَا إِلَيْهَا سَبِيلاَ
وَنَرْقُصُ بَيْنَ شَهِيدْينِ نَرْفَعُ مِئْذَنَةً لِلْبَنَفْسَجِ بَيْنَهُمَا أَوْ نَخِيلاَ

نُحِبُّ الحَيَاةَ إِذَا مَا اسْتَطَعْنَا إِلَيْهَا سَبِيلاَ
وَنَسْرِقُ مِنْ دُودَةِ القَزِّ خَيْطاً لِنَبْنِي سَمَاءً لَنَا وَنُسَيِّجَ هَذَا الرَّحِيلاَ
وَنَفْتَحُ بَابَ الحَدِيقَةِ كَيْ يَخْرُجَ اليَاسَمِينُ إِلَى الطُّرُقَاتِ نَهَاراً جَمِيلاَ
نُحِبُّ الحَيَاةَ إِذَا مَا اسْتَطَعْنَا إِلَيْهَا سَبِيلاَ

وَنَزْرَعُ حَيْثُ أَقمْنَا نَبَاتاً سَريعَ النُّمُوِّ , وَنَحْصدْ حَيْثُ أَقَمْنَا قَتِيلاَ
وَنَنْفُخُ فِي النَّايِ لَوْنَ البَعِيدِ البَعِيدِ , وَنَرْسُمُ فَوْقَ تُرابِ المَمَرَّ صَهِيلاَ
وَنَكْتُبُ أَسْمَاءَنَا حَجَراً ’ أَيُّهَا البَرْقُ أَوْضِحْ لَنَا اللَّيْلَ ’ أَوْضِحْ قَلِيلاَ
نُحِبُّ الحَيَاةَ إِذا مَا اسْتَطَعْنَا إِلَيْهَا سَبِيلا...'''

result = analyzer.analyze_free_verse(modern_poem)

if 'poemErr' not in result:
    print(f"Detected dominant meter: {result['ba7er']}")
    print(f"Number of prosodic feet: {len(result['tafa3eel'])}")
    print("\nProsodic analysis:")
    
    for i in range(len(result['tafa3eel'])):
        foot_pattern = result['tafa3eel'][i]
        foot_name = result['names'][i] if i < len(result['names']) else 'Unknown'
        foot_text = result['words'][i] if i < len(result['words']) else ''
        print(f"  {foot_pattern} ({foot_name}): {foot_text}")
else:
    print(f"Analysis failed: {result['poemErr']}")

Advanced Usage with Wizard Analysis

# Using wizard analysis for educational purposes
verse = "متى منْ طوْل نزْفك تسْتريْحُ"

# Define expected patterns for طويل meter
expected_patterns = [
    ['U--', 'U-U'],  # First foot options
    ['U---'],        # Second foot
    ['U--', 'U-U'],  # Third foot options  
    ['U---', 'U-U-', 'U--']  # Final foot options
]

pattern_names = [
    ['فَعُولُن', 'فَعُولُ'],
    ['مَفَاعِيلُن'],
    ['فَعُولُن', 'فَعُولُ'],
    ['مَفَاعِيلُن', 'مَفَاعِلُن', 'فَعُولُن']
]

wizard_result = analyzer.wizard_analysis_classical(
    verse, 
    is_ajez=False, 
    rule_patterns=expected_patterns,
    rule_names=pattern_names
)

print("Wizard Analysis Results:")
for result in wizard_result:
    status = "✅" if result['status'] == 'ok' else "❌"
    print(f"{status} {result['taf3eela']}: {result['chars']}")
    
    if result['status'] == 'err' and 'errs' in result:
        for error in result['errs']:
            print(f"    Error: {error}")

Command Line Interface

The package includes a comprehensive CLI tool:

# Analyze a single verse
faraheedy analyze "أرحْ قمْح غيّابٍ يجافوْن منْجلكْ"

# Analyze from file
faraheedy analyze-file poem.txt --type classical

# Analyze free verse
faraheedy analyze-file modern_poem.txt --type free-verse

# Interactive mode for experimentation
faraheedy interactive

# Batch analysis of multiple files
faraheedy batch-analyze poems_directory/ --output results.json

# Get detailed help
faraheedy --help

Advanced Features

Custom Meter Detection

# For researchers working with rare or historical meters
analyzer = ArabicPoetryAnalyzer()

# Enable experimental meter detection
result = analyzer.analyze_classical_verse(
    verse, 
    enable_experimental=True,
    confidence_threshold=0.7
)

if result['ba7er_name'] == 'unknown':
    print("Meter not recognized with standard patterns")
    if 'alternatives' in result:
        print("Possible alternatives:")

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

al_faraheedy_python-1.0.0.tar.gz (32.9 kB view details)

Uploaded Source

Built Distribution

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

al_faraheedy_python-1.0.0-py3-none-any.whl (19.8 kB view details)

Uploaded Python 3

File details

Details for the file al_faraheedy_python-1.0.0.tar.gz.

File metadata

  • Download URL: al_faraheedy_python-1.0.0.tar.gz
  • Upload date:
  • Size: 32.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.9

File hashes

Hashes for al_faraheedy_python-1.0.0.tar.gz
Algorithm Hash digest
SHA256 1c044e1cafc890ea7e90fe8f17b7051785c3a6b10e7b385aa692f0a00bdff2fc
MD5 e7f2c1d55cc53085e1212502c4e84f34
BLAKE2b-256 4b8d15c63fedef77ffab3e107301ce5cb1bf360f109cff385d8974f1b6f2cfec

See more details on using hashes here.

File details

Details for the file al_faraheedy_python-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for al_faraheedy_python-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 decef282effb3ad8616717d7d65077fd46d6b50cc2db1117a86c94be1e8d69bb
MD5 937e9ae70113ea5b711f8f6bb0114112
BLAKE2b-256 95c13fcf763d4e87b1a6963462d947b0a28ef1d0a3ad74b5082442b9d5c7c269

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