Spaces:
Sleeping
Sleeping
import asyncio | |
import random | |
from datetime import datetime, timedelta | |
import numpy as np | |
import pandas as pd | |
from .downtime import machine_errors | |
TOOLS_COUNT = 2 | |
async def generate_data(state): | |
""" | |
Generate synthetic production data for a manufacturing process. | |
""" | |
current_time = state["date"] if state["date"] else datetime.now() | |
part_id = state["part_id"] if state["part_id"] else 0 | |
non_compliance_rates = { | |
1: 0.05, | |
2: 0.10, | |
} | |
if 'raw_df' not in state['data']: | |
state['data']['raw_df'] = pd.DataFrame(columns=[ | |
"Part ID", "Timestamp", "Position", "Orientation", "Tool ID", | |
"Compliance", "Event", "Error Code", "Error Description", | |
"Downtime Start", "Downtime End" | |
]) | |
for _ in range(1000): | |
if not state["running"]: | |
break | |
if random.random() < 0.01: # 0.005 | |
error_key = random.choice(list(machine_errors.keys())) | |
error = machine_errors[error_key] | |
downtime = error["downtime"] | |
new_row = pd.DataFrame([{ | |
"Part ID": "N/A", | |
"Timestamp": current_time.strftime("%Y-%m-%d %H:%M:%S"), | |
"Position": "N/A", | |
"Orientation": "N/A", | |
"Tool ID": "N/A", | |
"Compliance": "N/A", | |
"Event": "Machine Error", | |
"Error Code": error_key, | |
"Error Description": error["description"], | |
"Downtime Start": current_time.strftime("%Y-%m-%d %H:%M:%S"), | |
"Downtime End": (current_time + downtime).strftime("%Y-%m-%d %H:%M:%S") | |
}]) | |
state['data']['raw_df'] = pd.concat([state['data']['raw_df'], new_row], ignore_index=True) | |
current_time += downtime | |
else: | |
position = np.random.normal(loc=0.4, scale=0.03) | |
orientation = np.random.normal(loc=0.4, scale=0.06) | |
tool_id = (part_id % TOOLS_COUNT) + 1 | |
if random.random() < non_compliance_rates[tool_id]: | |
position = np.random.normal(loc=0.4, scale=0.2) | |
orientation = np.random.normal(loc=0.4, scale=0.3) | |
compliance = 'OK' if (0.3 <= position <= 0.5) and (0.2 <= orientation <= 0.6) else 'NOK' | |
new_row = pd.DataFrame([{ | |
"Part ID": part_id, | |
"Timestamp": current_time.strftime("%Y-%m-%d %H:%M:%S"), | |
"Position": round(position, 4), | |
"Orientation": round(orientation, 4), | |
"Tool ID": tool_id, | |
"Compliance": compliance, | |
"Event": "N/A", | |
"Error Code": "N/A", | |
"Error Description": "N/A", | |
"Downtime Start": "N/A", | |
"Downtime End": "N/A" | |
}]) | |
if ( | |
(not new_row.empty and not new_row.isna().all().all()) | |
and \ | |
(not state['data']['raw_df'].empty and not state['data']['raw_df'].isna().all().all()) | |
): | |
state['data']['raw_df'] = pd.concat([state['data']['raw_df'], new_row], ignore_index=True) | |
elif not new_row.empty and not new_row.isna().all().all(): | |
state['data']['raw_df'] = new_row.copy() | |
#print(f"- part {part_id} data generated") | |
part_id += 1 | |
await asyncio.sleep(0.2) | |
current_time += timedelta(seconds=1) | |
state["date"] = current_time | |
state["part_id"] = part_id |