File size: 8,000 Bytes
b8fe962
 
 
 
 
 
 
 
 
 
 
 
72b4fe9
b8fe962
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
from flask import Flask, render_template, request, jsonify
import google.generativeai as genai
from PIL import Image
import io
import fitz
import markdown2
import re
import matplotlib.pyplot as plt
import base64
import json

# Configure the Gemini API
genai.configure(api_key="AIzaSyAP_HLW93ErBBhmwxBilrFak_m8D6LQf04")

app = Flask(__name__)
app.secret_key = "supersecretkey"


def process_file(file):
    """Process file into an appropriate format for Gemini."""
    if file.content_type == 'application/pdf':
        try:
            pdf_bytes = file.read()
            pdf_document = fitz.open(stream=pdf_bytes, filetype="pdf")
            first_page = pdf_document[0]
            pix = first_page.get_pixmap()
            img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
            return img, file.filename
        except Exception as e:
            raise Exception(f"Error processing PDF {file.filename}: {str(e)}")
    else:
        try:
            image_bytes = file.read()
            image = Image.open(io.BytesIO(image_bytes))
            return image, file.filename
        except Exception as e:
            raise Exception(f"Error processing image {file.filename}: {str(e)}")


def format_markdown(text):
    """Improve markdown formatting for the output."""
    lines = [line.strip() for line in text.split('\n')]
    formatted_lines = []
    for i, line in enumerate(lines):
        if line.startswith('#'):
            if i > 0:
                formatted_lines.append('')
            formatted_lines.append(line)
            formatted_lines.append('')
        elif line:
            formatted_lines.append(line)
    text = '\n'.join(formatted_lines)
    text = re.sub(r'(?m)^(\s*)-', r'\1•', text)
    text = re.sub(r'\n(•[^\n]+)(?:\n(?!•)|\Z)', r'\n\1\n', text)
    return text


def generate_nutrient_chart(labels, data):
    """Generate a bar chart for nutrient levels using provided labels and data, and return it as a base64 encoded PNG."""
    fig, ax = plt.subplots(figsize=(6, 4))
    ax.bar(labels, data, color=['#FF6384', '#36A2EB', '#FFCE56'], edgecolor=['#FF6384', '#36A2EB', '#FFCE56'],
           linewidth=1)
    ax.set_ylabel('Nutrient Levels (lbs/100 sq ft)')
    ax.set_title('Nutrient Levels')
    ax.set_ylim(0, max(data) * 1.5)

    buf = io.BytesIO()
    plt.savefig(buf, format='png', bbox_inches='tight')
    plt.close(fig)
    buf.seek(0)
    img_data = base64.b64encode(buf.getvalue()).decode('utf-8')
    return f"data:image/png;base64,{img_data}"


@app.route("/", methods=["GET", "POST"])
def index():
    if request.method == "POST":
        if "files" not in request.files:
            return jsonify({"error": "No files uploaded"})
        files = request.files.getlist("files")
        if not files or files[0].filename == "":
            return jsonify({"error": "No files selected"})

        try:
            processed_files = []
            for file in files:
                processed_content, filename = process_file(file)
                processed_files.append((processed_content, filename))
            filenames = [f[1] for f in processed_files]
            files_list = "\n".join([f"- {fname}" for fname in filenames])
            content_parts = []
            for img, _ in processed_files:
                content_parts.append(img)
            # Updated prompt: we now instruct Gemini to include a section "NUTRIENT_DATA:"
            # with a complete JSON object for chart generation.
            content_parts.append(
                f"""Please analyze all {len(files)} soil reports provided and generate a comprehensive, detailed soil analysis report in markdown format. Use simple, everyday language that farmers and non-technical users can easily understand.

Divide the report into the following clearly labeled sections (each with distinct formatting when rendered):

1. **Overview:**  
   Provide a detailed snapshot of the soil's overall health in plain language.

2. **Soil Composition:**  
   Explain the proportions of sand, silt, and clay, and describe how these affect water retention, drainage, and fertility.

3. **Nutrient Levels:**  
   Present an in-depth analysis of key nutrients (e.g. Nitrogen, Phosphorus, Potassium) and include recommendations.

4. **pH Balance & Moisture Content:**  
   Describe the soil’s pH level and moisture content, and explain how they influence crop performance.

5. **Recommendations & Actionable Steps:**  
   Provide clear, practical advice to improve soil quality (such as lime application, fertilizer usage, and adding organic matter) with this  aslo provide  which crops should we should  cultivate with  season and  weather condition that will help me to  improve my soil  condition and let me develop  more and  also which crops should  i avoid  with this  can you also  recommend me  any home remedies  or natural remedies  that will help me to improve my soil  condition  also  recommend me what  agriculture  practices whill help me to  maintain my soil condition   in terms of the  future of 5 to 10 years   .

6. **Graphical Representation:**  
   In addition to the text, generate a bar chart displaying nutrient levels.  
   Also, please include a section labeled **NUTRIENT_DATA:** containing a JSON object with two keys: "labels" (a list of nutrient names) and "values" (a list of corresponding numerical values). The data may vary based on the analysis.

Reports being analyzed:
{files_list}

Ensure that every section is clearly labeled and formatted so that the output is easy to understand and visually appealing."""
            )

            model = genai.GenerativeModel("gemini-1.5-flash")
            response = model.generate_content(content_parts)

            if response and response.text:
                summary = response.text.strip()
                if summary.lower().startswith("please provide"):
                    return jsonify({"error": "Could not analyze the documents"})

                # Extract nutrient data from the analysis if available
                nutrient_data = None
                if "NUTRIENT_DATA:" in summary:
                    try:
                        parts = summary.split("NUTRIENT_DATA:")
                        summary = parts[0].strip()
                        # Assume the nutrient JSON is on the first line after the marker
                        nutrient_json_str = parts[1].strip().split("\n")[0]
                        nutrient_data = json.loads(nutrient_json_str)
                    except Exception as e:
                        nutrient_data = None

                final_output = f"""
# 🌱 Soil Report Analysis

{summary}

---
                """
                fixed_output = format_markdown(final_output)
                html_output = markdown2.markdown(
                    fixed_output,
                    extras=[
                        'tables',
                        'fenced-code-blocks',
                        'break-on-newline',
                        'cuddled-lists',
                        'code-friendly'
                    ]
                )
                # Generate chart image using dynamic data if available
                if nutrient_data and 'labels' in nutrient_data and 'values' in nutrient_data:
                    chart_img = generate_nutrient_chart(nutrient_data['labels'], nutrient_data['values'])
                else:
                    chart_img = generate_nutrient_chart(['Nitrogen', 'Phosphorus', 'Potassium'], [0.15, 0.2, 0.3])

                return jsonify({
                    "summary": fixed_output,
                    "html_summary": html_output,
                    "chart_img": chart_img
                })
            else:
                return jsonify({"error": "No analysis could be generated"})
        except Exception as e:
            return jsonify({"error": f"Error processing files: {str(e)}"})
    return render_template("index2.html")


if __name__ == "__main__":
    app.run(debug=True, port=1234)