Pushpak21 commited on
Commit
5c8d4fd
·
verified ·
1 Parent(s): e93edf5

Upload folder using huggingface_hub

Browse files
Files changed (4) hide show
  1. Dockerfile +18 -0
  2. app.py +90 -0
  3. index.html +85 -0
  4. requirements.txt +4 -0
Dockerfile ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # Dockerfile
3
+ FROM python:3.11
4
+
5
+ # Install backend dependencies
6
+ COPY requirements.txt /app/requirements.txt
7
+ WORKDIR /app
8
+ RUN pip install -r requirements.txt
9
+
10
+ # Copy backend and frontend
11
+ COPY app.py /app/app.py
12
+ COPY index.html /app/index.html
13
+
14
+ # Add CORS and serve index.html statically
15
+ RUN mkdir -p /app/static
16
+
17
+ # Run both backend (FastAPI) and static file server
18
+ CMD uvicorn app:app --host 0.0.0.0 --port 7860
app.py ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from fastapi import FastAPI, UploadFile, File
3
+ from fastapi.responses import JSONResponse, FileResponse
4
+ from fastapi.middleware.cors import CORSMiddleware
5
+ import os
6
+
7
+ app = FastAPI()
8
+
9
+ app.add_middleware(
10
+ CORSMiddleware,
11
+ allow_origins=["*"], allow_credentials=True,
12
+ allow_methods=["*"], allow_headers=["*"],
13
+ )
14
+
15
+ @app.get("/")
16
+ def serve_frontend():
17
+ return FileResponse("index.html")
18
+
19
+ @app.post("/parse")
20
+ async def parse_file(file: UploadFile = File(...)):
21
+ content = await file.read()
22
+ return JSONResponse(content=parse_dcm_assembly(content))
23
+
24
+ def parse_dcm_assembly(file_bytes):
25
+ lines = file_bytes.decode("utf-8").splitlines()
26
+ blocks, current = [], []
27
+
28
+ for line in lines:
29
+ if line.startswith("CLASS"):
30
+ if current:
31
+ blocks.append(current)
32
+ current = []
33
+ current.append(line.strip())
34
+ if current: blocks.append(current)
35
+
36
+ parts, geometry, constraints = [], {}, []
37
+ plane_map, tag_to_plane, label_map = {}, {}, {}
38
+
39
+ for block in blocks:
40
+ head = block[0]
41
+ if "CLASS SET " in head:
42
+ part, members = {}, []
43
+ for line in block:
44
+ if "DCM3_TEXT_LABEL" in line:
45
+ part['name'] = line.split("DCM3_TEXT_LABEL", 1)[1].strip()
46
+ elif "FMEMBER TAGS" in line:
47
+ members = list(map(int, line.split()[2:]))
48
+ if 'name' in part:
49
+ part['member_tags'] = members
50
+ parts.append(part)
51
+
52
+ elif "CLASS PLANE " in head:
53
+ pid = int(head.split()[-1])
54
+ base, norm = None, None
55
+ for line in block:
56
+ if "FBASE_POINT" in line:
57
+ base = tuple(map(float, line.split()[1:]))
58
+ elif "FNORMAL" in line:
59
+ norm = tuple(map(float, line.split()[1:]))
60
+ if base and norm:
61
+ plane_map[pid] = {'base_point': base, 'normal': norm}
62
+
63
+ elif "CLASS WORK_PLANE " in head:
64
+ wid = int(head.split()[-1])
65
+ tag, label = None, None
66
+ for line in block:
67
+ if "FMY_PLANE TAG" in line:
68
+ tag = int(line.split()[-1])
69
+ elif "DCM3_TEXT_LABEL" in line:
70
+ label = line.split("DCM3_TEXT_LABEL", 1)[1].strip()
71
+ if tag:
72
+ tag_to_plane[wid] = tag
73
+ label_map[wid] = label
74
+
75
+ elif "CLASS CONSTRAINT " in head:
76
+ con = {}
77
+ for line in block:
78
+ if "FEND_1 TAG" in line:
79
+ con['from'] = int(line.split()[-1])
80
+ elif "FEND_2 TAG" in line:
81
+ con['to'] = int(line.split()[-1])
82
+ elif "DCM3_TEXT_LABEL" in line:
83
+ con['label'] = line.split("DCM3_TEXT_LABEL", 1)[1].strip()
84
+ if con: constraints.append(con)
85
+
86
+ for wid, pid in tag_to_plane.items():
87
+ if pid in plane_map:
88
+ geometry[wid] = {**plane_map[pid], 'label': label_map.get(wid)}
89
+
90
+ return { "parts": parts, "geometry": geometry, "constraints": constraints }
index.html ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ <!DOCTYPE html>
4
+ <html lang="en">
5
+ <head>
6
+ <meta charset="UTF-8" />
7
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8
+ <title>DCM Assembly Visualizer</title>
9
+ <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
10
+ <style>
11
+ body { font-family: sans-serif; padding: 20px; }
12
+ #plot { width: 100%; height: 700px; }
13
+ </style>
14
+ </head>
15
+ <body>
16
+ <h1>DCM Assembly Visualizer</h1>
17
+ <p>This visualizer is now intended to be used with a Streamlit frontend for file upload.</p>
18
+ <div id="plot"></div>
19
+
20
+ <script>
21
+ let allTraces = [];
22
+ let normalTraces = [];
23
+
24
+ async function drawFromServer() {
25
+ const res = await fetch("/parsed_data.json");
26
+ const payload = await res.json();
27
+ allTraces = [];
28
+ normalTraces = [];
29
+
30
+ for (const [color, label, data] of payload.files) {
31
+ extractTraces(data, color, label);
32
+ }
33
+
34
+ Plotly.newPlot('plot', [...allTraces, ...normalTraces.filter(t => t.visible)], {
35
+ margin: { t: 30 },
36
+ scene: { aspectmode: 'data' },
37
+ title: '3D Assembly Viewer'
38
+ });
39
+ }
40
+
41
+ function extractTraces(data, baseColor, normalColor) {
42
+ for (const [tag, g] of Object.entries(data.geometry)) {
43
+ const [x, y, z] = g.base_point;
44
+ const [nx, ny, nz] = g.normal;
45
+
46
+ allTraces.push({
47
+ type: 'scatter3d',
48
+ mode: 'markers+text',
49
+ x: [x], y: [y], z: [z],
50
+ marker: { color: baseColor, size: 5 },
51
+ text: [g.label || tag],
52
+ textposition: 'top center'
53
+ });
54
+
55
+ normalTraces.push({
56
+ type: 'scatter3d',
57
+ mode: 'lines',
58
+ x: [x, x + nx],
59
+ y: [y, y + ny],
60
+ z: [z, z + nz],
61
+ line: { color: normalColor, width: 2 },
62
+ visible: true
63
+ });
64
+ }
65
+
66
+ for (const c of data.constraints) {
67
+ const g1 = data.geometry[c.from];
68
+ const g2 = data.geometry[c.to];
69
+ if (g1 && g2) {
70
+ const [x1, y1, z1] = g1.base_point;
71
+ const [x2, y2, z2] = g2.base_point;
72
+ allTraces.push({
73
+ type: 'scatter3d',
74
+ mode: 'lines',
75
+ x: [x1, x2], y: [y1, y2], z: [z1, z2],
76
+ line: { color: 'green', dash: 'dot', width: 2 }
77
+ });
78
+ }
79
+ }
80
+ }
81
+
82
+ drawFromServer();
83
+ </script>
84
+ </body>
85
+ </html>
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+
2
+ fastapi
3
+ uvicorn
4
+ python-multipart