| {% extends "base.html" %} |
| {% block title %}Predict — IrisAI{% endblock %} |
|
|
| {% block body %} |
| <div class="page"> |
| <div class="container"> |
|
|
| <div class="page-header"> |
| <h1>Iris Flower Classifier</h1> |
| <p>Enter measurements below to identify the species using Random Forest ML.</p> |
| </div> |
|
|
| {% with messages = get_flashed_messages(with_categories=true) %} |
| {% if messages %} |
| <div class="flashes"> |
| {% for cat, msg in messages %} |
| <div class="flash {{ cat }}">{{ msg }}</div> |
| {% endfor %} |
| </div> |
| {% endif %} |
| {% endwith %} |
|
|
| <div style="display:grid;grid-template-columns:1fr 1fr;gap:1.5rem;align-items:start"> |
|
|
| |
| <div class="card"> |
| <h2 class="serif" style="font-size:1.2rem;margin-bottom:1.25rem">🔬 Enter Measurements</h2> |
| <form method="POST" action="{{ url_for('predict') }}"> |
|
|
| <p class="small muted" style="margin-bottom:1rem">Sepal dimensions (cm)</p> |
| <div class="grid-2"> |
| <div class="form-group"> |
| <label for="sepal_length">Sepal Length</label> |
| <input type="number" id="sepal_length" name="sepal_length" step="0.1" min="0.1" max="20" |
| placeholder="e.g. 5.1" value="{{ form_data.get('sepal_length', '') }}" required /> |
| <div class="input-hint">Typical: 4.3 – 7.9</div> |
| </div> |
| <div class="form-group"> |
| <label for="sepal_width">Sepal Width</label> |
| <input type="number" id="sepal_width" name="sepal_width" step="0.1" min="0.1" max="20" |
| placeholder="e.g. 3.5" value="{{ form_data.get('sepal_width', '') }}" required /> |
| <div class="input-hint">Typical: 2.0 – 4.4</div> |
| </div> |
| </div> |
|
|
| <p class="small muted" style="margin-bottom:1rem;margin-top:.5rem">Petal dimensions (cm)</p> |
| <div class="grid-2"> |
| <div class="form-group"> |
| <label for="petal_length">Petal Length</label> |
| <input type="number" id="petal_length" name="petal_length" step="0.1" min="0.1" max="20" |
| placeholder="e.g. 1.4" value="{{ form_data.get('petal_length', '') }}" required /> |
| <div class="input-hint">Typical: 1.0 – 6.9</div> |
| </div> |
| <div class="form-group"> |
| <label for="petal_width">Petal Width</label> |
| <input type="number" id="petal_width" name="petal_width" step="0.1" min="0.1" max="20" |
| placeholder="e.g. 0.2" value="{{ form_data.get('petal_width', '') }}" required /> |
| <div class="input-hint">Typical: 0.1 – 2.5</div> |
| </div> |
| </div> |
|
|
| <button type="submit" class="btn btn-primary btn-full" style="margin-top:.5rem"> |
| Classify Flower → |
| </button> |
| </form> |
|
|
| <hr class="divider" /> |
|
|
| |
| <p class="small muted" style="margin-bottom:.6rem">Try an example:</p> |
| <div style="display:flex;gap:.5rem;flex-wrap:wrap"> |
| <button class="btn btn-outline" style="font-size:.8rem;padding:.35rem .9rem" |
| onclick="fillExample(5.1,3.5,1.4,0.2)">🌸 Setosa</button> |
| <button class="btn btn-outline" style="font-size:.8rem;padding:.35rem .9rem" |
| onclick="fillExample(6.0,2.9,4.5,1.5)">💜 Versicolor</button> |
| <button class="btn btn-outline" style="font-size:.8rem;padding:.35rem .9rem" |
| onclick="fillExample(6.5,3.0,5.5,1.8)">🌺 Virginica</button> |
| </div> |
| </div> |
|
|
| |
| <div> |
| |
| {% if result %} |
| <div class="result-card" style="background:var(--surface);margin-bottom:1.5rem" |
| {% if result.info.color %}style="border-color:{{ result.info.color }}33;background:var(--surface)"{% endif %}> |
| <p class="small muted" style="margin-bottom:.25rem">Prediction</p> |
| <div class="result-name"> |
| {{ result.info.emoji }} Iris {{ result.name | capitalize }} |
| </div> |
| <p class="small muted">{{ result.info.description }}</p> |
|
|
| <div style="margin-top:1.25rem"> |
| <div style="display:flex;justify-content:space-between;font-size:.8rem"> |
| <span class="muted">Confidence</span> |
| <span class="mono">{{ result.confidence }}%</span> |
| </div> |
| <div class="confidence-bar-wrap"> |
| <div class="confidence-bar" style="width:{{ result.confidence }}%"></div> |
| </div> |
| </div> |
|
|
| <div class="prob-grid"> |
| {% for cls, prob in result.all_probs.items() %} |
| <span class="prob-pill {% if cls == result.name %}active{% endif %}"> |
| {{ cls }}: {{ prob }}% |
| </span> |
| {% endfor %} |
| </div> |
| </div> |
| {% else %} |
| <div class="card" style="text-align:center;padding:3rem 2rem;color:var(--muted)"> |
| <div style="font-size:3rem;margin-bottom:.75rem">🌿</div> |
| <p class="serif" style="font-size:1.1rem;color:var(--text)">No prediction yet</p> |
| <p class="small" style="margin-top:.4rem">Fill in the measurements and click classify.</p> |
| </div> |
| {% endif %} |
|
|
| |
| <div class="card" style="padding:1.25rem"> |
| <p class="small" style="font-weight:600;margin-bottom:.5rem">About the Model</p> |
| <p class="small muted">Random Forest Classifier · 100 estimators</p> |
| <p class="small muted">Dataset: UCI Iris (150 samples) · <strong style="color:var(--green)">90% accuracy</strong></p> |
| <p class="small muted" style="margin-top:.5rem"> |
| Source: <a href="https://archive.ics.uci.edu/dataset/53/iris" target="_blank" |
| style="color:var(--accent)">archive.ics.uci.edu</a> |
| </p> |
| </div> |
| </div> |
| </div> |
|
|
| |
| {% if history %} |
| <div class="card" style="margin-top:1.5rem"> |
| <h3 class="serif" style="font-size:1.1rem;margin-bottom:1rem">📋 Your Recent Predictions</h3> |
| <div style="overflow-x:auto"> |
| <table> |
| <thead> |
| <tr> |
| <th>Species</th> |
| <th>Sepal L</th><th>Sepal W</th><th>Petal L</th><th>Petal W</th> |
| <th>Confidence</th> |
| <th>When</th> |
| </tr> |
| </thead> |
| <tbody> |
| {% for row in history %} |
| <tr> |
| <td><span class="badge badge-{{ row.prediction }}">{{ row.prediction | capitalize }}</span></td> |
| <td class="mono">{{ row.sepal_length }}</td> |
| <td class="mono">{{ row.sepal_width }}</td> |
| <td class="mono">{{ row.petal_length }}</td> |
| <td class="mono">{{ row.petal_width }}</td> |
| <td class="mono">{{ "%.1f"|format(row.confidence) }}%</td> |
| <td class="muted">{{ row.timestamp[:16] }}</td> |
| </tr> |
| {% endfor %} |
| </tbody> |
| </table> |
| </div> |
| </div> |
| {% endif %} |
|
|
| </div> |
| </div> |
|
|
| <script> |
| function fillExample(sl, sw, pl, pw) { |
| document.getElementById('sepal_length').value = sl; |
| document.getElementById('sepal_width').value = sw; |
| document.getElementById('petal_length').value = pl; |
| document.getElementById('petal_width').value = pw; |
| } |
| </script> |
| {% endblock %} |
|
|