Untitled
import pandas as pd import re import numpy as np # Existing parse_data function def parse_data(data): blocks = data.split("{@BLOCK") # Split only at {@BLOCK global part_number # Declare it globally at the start of the function measurements = [] platform = "NAN" # Default to NAN if no platform is found part_number = "" # Default to NAN if no part number is found skipped_count = 0 # Track number of skipped lines for block in blocks: # Ensure the block begins with {@BLOCK block = "{@BLOCK" + block if not block.startswith("{@BLOCK") else block # Parse the platform if `@BATCH` and `{@BTEST` are found if "@BATCH" in block and "{@BTEST" in block: batch_line = re.search(r"\{@BATCH[^\{]*\{@BTEST[^\{]*", block) if batch_line: parts = batch_line.group().split('|') # Parse platform (9th split logic) if len(parts) >= 15: platform = parts[9].strip() # 9th split is index 8 (0-based indexing) # Parse part number (from index 1 or fallback logic) if len(parts) > 1 and parts[1].strip(): part_number = parts[1].strip() else: for i in range(10, len(parts)): # Start from the 10th part part = parts[i].strip() if part: part_number = part.split("{@BATCH")[0].strip() if "{@BATCH" in part else part.strip() break # Define the pattern to match measurement data pattern = r"\{@([\w-]+)\|([^\|]*)\|([^\|]*)\|?([^\|{]*)\{@(LIM2|LIM3)\|([+-]?\d*\.?\d+(?:E[+-]?\d+)?)(?:\|([+-]?\d*\.?\d+(?:E[+-]?\d+)?))?(?:\|([+-]?\d*\.?\d+(?:E[+-]?\d+)?))" matches = re.findall(pattern, block) a = [] # Process each match for match in matches: prefix = match[0] if prefix not in {"BLOCK", "BTEST", "BATCH"}: # Ignore these prefixes a.append(prefix) # Process `@BTEST` if present if "{@BTEST" in block: dataBlockSplit = str(block).split('@BTEST')[1].split("{")[0].split("|") runs = dataBlockSplit[-1].strip() serial = dataBlockSplit[1].strip() datatime = dataBlockSplit[3].strip() if len(dataBlockSplit) > 3 else "" # Extract test details from `@BLOCK` block_matches = re.findall(r"@BLOCK\|([^|]+)\|(\d{2})", block) for test_name, pass_fail_code in block_matches: # Clean test name test_name = re.sub(r'^\d+%', '', test_name) pass_fail = "Pass" if pass_fail_code == "00" else "Fail" category_matches = re.findall( r"@([A-Z-]+)\|(\d)\|([+-]?\d*\.?\d+(?:E[+-]?\d+)?)(?:\|(.+?))?\{", block ) # Extract limits lim2_match = re.findall( r"@LIM2\|([+-]?\d*\.?\d+(?:E[+-]?\d+)?)\|([+-]?\d*\.?\d+(?:E[+-]?\d+)?)", block ) lim3_match = re.findall( r"@LIM3\|([+-]?\d*\.?\d+(?:E[+-]?\d+)?)\|([+-]?\d*\.?\d+(?:E[+-]?\d+)?)\|([+-]?\d*\.?\d+(?:E[+-]?\d+)?)", block ) if lim3_match: for num in range(len(lim3_match)): category_match = category_matches[num] typeValue = a[num] subtest = category_match[3] if category_match[3] else "None" pass_fail_code = category_match[1] # Extract pass/fail code (0 or 1) measurement = float(category_match[2]) # Extract measurement pass_fail = "Pass" if pass_fail_code == "0" else "Fail" upper_limit = lower_limit = nominal_value = np.nan nominal_value, upper_limit, lower_limit = map(float, lim3_match[num]) # Assuming nominal_value, upper_limit, and lower_limit are defined tol_plus = (upper_limit - nominal_value) / nominal_value * 100 if not np.isnan( nominal_value) else np.nan tol_minus = (lower_limit - nominal_value) / nominal_value * 100 if not np.isnan( nominal_value) else np.nan # Format tol_plus and tol_minus to 1 decimal place tol_plus = round(tol_plus, 1) if not np.isnan(tol_plus) else np.nan tol_minus = round(tol_minus, 1) if not np.isnan(tol_minus) else np.nan # Skip logic: Skip if typeValue is "A-JUM" and measurement is negative if typeValue == "A-JUM" and measurement < 0: skipped_count += 1 # Increment the skip counter continue # Skip this iteration # Ensure tol_minus is positive (absolute value) tol_minus = abs(tol_minus) measurements.append({ "Test Name": test_name, "DateTime": datatime, "Subtest": subtest, "Serial#": serial, "Measure": measurement, }) elif lim2_match: for num in range(len(lim2_match)): if num < len(category_matches): category_match = category_matches[num] # Continue processing else: # Handle mismatch, e.g., skip or log an error print(f"Warning: No matching category for index {num} in block.") continue # Skip the current iteration typeValue = a[num] subtest = category_match[3] if category_match[3] else "None" pass_fail_code = category_match[1] measurement = float(category_match[2]) pass_fail = "Pass" if pass_fail_code == "0" else "Fail" upper_limit = lower_limit = nominal_value = np.nan upper_limit, lower_limit = map(float, lim2_match[num]) tol_plus = (upper_limit - nominal_value) / nominal_value * 100 if not np.isnan( nominal_value) else np.nan tol_minus = (lower_limit - nominal_value) / nominal_value * 100 if not np.isnan( nominal_value) else np.nan # Skip logic: Skip if typeValue is "A-JUM" and measurement is negative if typeValue == "A-JUM" and measurement < 0: skipped_count += 1 # Increment the skip counter continue # Skip this iteration measurements.append({ "Test Name": test_name, "DateTime": datatime, "Subtest": subtest, "Serial#": serial, "Measure": measurement, }) return pd.DataFrame(measurements), skipped_count # Simple input and print example def input_and_parse_data(): # Take input from the user data = """ {@BATCH|000540-||903|1||btest|240221155154||I30704CE243BQ75|OP5|RevA|OP5|| {@BTEST|24052C0G0|00|240221224006|000017|0|all||n|n|240221224023||001|default_SN1 {@PF|1%pins|0|0 } {@TS|0|000|000|000|1%shorts } {@BLOCK|1%c2|00 {@A-CAP|0|+9.940980E-06{@LIM3|+1.050000E-05|+1.363950E-05|+7.360500E-06}} } {@BLOCK|1%c13|00 {@A-CAP|0|+9.767915E-06{@LIM3|+1.000100E-05|+1.299130E-05|+7.010701E-06}} } {@BLOCK|1%c15|00 {@A-CAP|0|+9.722146E-06{@LIM3|+1.010000E-05|+1.311990E-05|+7.080100E-06}} } {@BLOCK|1%c17|00 {@A-CAP|0|+1.070258E-07{@LIM3|+1.000000E-07|+1.299000E-07|+7.010000E-08}} } {@BLOCK|1%c18|00 {@A-CAP|0|+1.113787E-07{@LIM3|+1.000000E-07|+1.296000E-07|+7.010000E-08}} } {@BLOCK|1%c12|00 {@A-CAP|0|+1.556213E-09{@LIM3|+1.500000E-09|+1.875000E-09|+1.125000E-09}} } {@BLOCK|1%c19|00 {@A-CAP|0|+1.546055E-09{@LIM3|+1.500000E-09|+1.875000E-09|+1.125000E-09}} } {@BLOCK|1%c20|00 {@A-CAP|0|+1.651738E-09{@LIM3|+1.500000E-09|+1.875000E-09|+1.125000E-09}} } {@BLOCK|1%c21|00 {@A-CAP|0|+1.568304E-09{@LIM3|+1.500000E-09|+1.875000E-09|+1.125000E-09}} } {@BLOCK|1%l2|00 {@A-JUM|0|+2.836620E+00{@LIM2|+1.000000E+01|+0.000000E+00}} } {@BLOCK|1%r12|00 {@A-RES|0|+9.946286E+02{@LIM3|+1.000000E+03|+1.100000E+03|+9.000000E+02}} } {@BLOCK|1%r14|00 {@A-RES|0|+9.884425E+02{@LIM3|+1.000000E+03|+1.100000E+03|+9.000000E+02}} } {@BLOCK|1%r17|00 {@A-RES|0|+9.923311E+02{@LIM3|+1.000000E+03|+1.100000E+03|+9.000000E+02}} } {@BLOCK|1%r3|00 {@A-RES|0|+1.210560E+05{@LIM3|+1.210000E+05|+1.282600E+05|+1.137400E+05}} } {@BLOCK|1%r4|00 {@A-RES|0|+2.468543E+05{@LIM3|+2.490000E+05|+2.639400E+05|+2.340600E+05}} } {@BLOCK|1%r6|00 {@A-RES|0|+2.870011E+06{@LIM3|+3.000000E+06|+3.300000E+06|+2.700000E+06}} } {@BLOCK|1%r8|00 {@A-RES|0|+3.028053E+06{@LIM3|+3.000000E+06|+3.300000E+06|+2.700000E+06}} } {@BLOCK|1%r13|00 {@A-RES|0|+3.000838E+06{@LIM3|+3.000000E+06|+3.300000E+06|+2.700000E+06}} } {@BLOCK|1%r18|00 {@A-RES|0|+2.980830E+06{@LIM3|+3.000000E+06|+3.300000E+06|+2.700000E+06}} } {@BLOCK|1%r15|00 {@A-JUM|0|+2.331387E+00{@LIM2|+1.000000E+01|+0.000000E+00}} } {@BLOCK|1%r16|00 {@A-JUM|0|+2.520171E+00{@LIM2|+1.000000E+01|+0.000000E+00}} } {@BLOCK|1%d1|00 {@A-ZEN|0|+7.107842E+00{@LIM3|+7.800000E+00|+8.580000E+00|+6.630000E+00}} } {@BLOCK|1%d2|00 {@A-ZEN|0|+7.221235E+00{@LIM3|+7.800000E+00|+8.580000E+00|+6.630000E+00}} } {@BLOCK|1%u1_clamp_diode|00 {@A-DIO|0|+6.795377E-01|pin_1_gnd{@LIM2|+9.500000E-01|+4.500000E-01}} {@A-DIO|0|+6.788366E-01|pin_2_gnd{@LIM2|+9.500000E-01|+4.500000E-01}} {@A-DIO|0|+7.409673E-01|pin_3_gnd{@LIM2|+9.500000E-01|+4.500000E-01}} {@A-DIO|0|+6.794062E-01|pin_4_gnd{@LIM2|+9.500000E-01|+4.500000E-01}} {@A-DIO|0|+7.580992E-01|pin_5_gnd{@LIM2|+9.500000E-01|+4.500000E-01}} {@A-DIO|0|+3.094703E-01|pin_7_gnd{@LIM2|+9.500000E-01|+1.500000E-01}} {@A-DIO|0|+3.976275E-01|pin_12_gnd{@LIM2|+9.500000E-01|+2.500000E-01}} {@A-DIO|0|+6.616171E-01|pin_14_gnd{@LIM2|+9.500000E-01|+4.500000E-01}} } {@BLOCK|1%u2_clamp_diode|00 {@A-DIO|0|+1.796006E-01|pin_1_gnd{@LIM2|+6.500000E-01|+1.000000E-01}} {@A-DIO|0|+2.157485E-01|pin_2_gnd{@LIM2|+6.500000E-01|+1.000000E-01}} {@A-DIO|0|+5.671504E-01|pin_4_gnd{@LIM2|+6.500000E-01|+4.000000E-01}} {@A-DIO|0|+7.377249E-01|pin_5_gnd{@LIM2|+8.500000E-01|+5.000000E-01}} } {@BLOCK|1%u3_clamp_diode|00 {@A-DIO|0|+5.671066E-01|pin_11_gnd{@LIM2|+9.500000E-01|+4.500000E-01}} {@A-DIO|0|+5.819601E-01|pin_15_gnd{@LIM2|+9.500000E-01|+4.500000E-01}} {@A-DIO|0|+6.283609E-01|pin_20_gnd{@LIM2|+9.500000E-01|+3.500000E-01}} {@A-DIO|0|+5.839756E-01|pin_22_gnd{@LIM2|+9.500000E-01|+4.500000E-01}} {@A-DIO|0|+5.835813E-01|pin_23_gnd{@LIM2|+9.500000E-01|+4.500000E-01}} {@A-DIO|0|+5.844576E-01|pin_28_gnd{@LIM2|+9.500000E-01|+4.500000E-01}} {@A-DIO|0|+5.836689E-01|pin_29_gnd{@LIM2|+9.500000E-01|+4.500000E-01}} {@A-DIO|0|+5.847205E-01|pin_33_gnd{@LIM2|+9.500000E-01|+4.500000E-01}} {@A-DIO|0|+5.877876E-01|pin_34_gnd{@LIM2|+9.500000E-01|+4.500000E-01}} {@A-DIO|0|+4.068726E-01|pin_41_gnd{@LIM2|+9.500000E-01|+3.000000E-01}} {@A-DIO|0|+5.843262E-01|pin_42_gnd{@LIM2|+9.500000E-01|+4.500000E-01}} } {@BLOCK|1%u4_clamp_diode|00 {@A-DIO|0|+2.263519E-01|pin_8_gnd{@LIM2|+6.500000E-01|+1.000000E-01}} } {@BLOCK|1%testjet|00 {@TJET|00|0000|1%u1 } {@TJET|00|0000|1%u3 } } {@BLOCK|1%u2|00 {@A-MEA|0|+1.660344E+00|boost{@LIM2|+2.000000E+00|+1.000000E+00}} {@A-MEA|0|+2.685606E+00|bypass{@LIM2|+3.150000E+00|+1.200000E+00}} {@D-T|0|384||0|1%u2 } } }} {@BATCH|000540-||903|1||btest|240221093810||I30704CE243BQ75|OP5|RevA|OP5|| {@BTEST|24052C000|00|240221095434|000020|0|all||n|n|240221095454||001|default_SN1 {@PF|1%pins|0|0 } {@TS|0|000|000|000|1%shorts } {@BLOCK|1%c2|00 {@A-CAP|0|+1.015362E-05{@LIM3|+1.050000E-05|+1.363950E-05|+7.360500E-06}} } {@BLOCK|1%c13|00 {@A-CAP|0|+9.518092E-06{@LIM3|+1.000100E-05|+1.299130E-05|+7.010701E-06}} } {@BLOCK|1%c15|00 {@A-CAP|0|+9.622979E-06{@LIM3|+1.010000E-05|+1.311990E-05|+7.080100E-06}} } {@BLOCK|1%c17|00 {@A-CAP|0|+1.063337E-07{@LIM3|+1.000000E-07|+1.299000E-07|+7.010000E-08}} } {@BLOCK|1%c18|00 {@A-CAP|0|+1.096751E-07{@LIM3|+1.000000E-07|+1.296000E-07|+7.010000E-08}} } {@BLOCK|1%c12|00 {@A-CAP|0|+1.621750E-09{@LIM3|+1.500000E-09|+1.875000E-09|+1.125000E-09}} } {@BLOCK|1%c19|00 {@A-CAP|0|+1.615462E-09{@LIM3|+1.500000E-09|+1.875000E-09|+1.125000E-09}} } {@BLOCK|1%c20|00 {@A-CAP|0|+1.640613E-09{@LIM3|+1.500000E-09|+1.875000E-09|+1.125000E-09}} } {@BLOCK|1%c21|00 {@A-CAP|0|+1.630214E-09{@LIM3|+1.500000E-09|+1.875000E-09|+1.125000E-09}} } {@BLOCK|1%l2|00 {@A-JUM|0|+2.828650E+00{@LIM2|+1.000000E+01|+0.000000E+00}} } {@BLOCK|1%r12|00 {@A-RES|0|+9.896323E+02{@LIM3|+1.000000E+03|+1.100000E+03|+9.000000E+02}} } {@BLOCK|1%r14|00 {@A-RES|0|+9.917171E+02{@LIM3|+1.000000E+03|+1.100000E+03|+9.000000E+02}} } {@BLOCK|1%r17|00 {@A-RES|0|+9.903231E+02{@LIM3|+1.000000E+03|+1.100000E+03|+9.000000E+02}} } {@BLOCK|1%r3|00 {@A-RES|0|+1.209783E+05{@LIM3|+1.210000E+05|+1.282600E+05|+1.137400E+05}} } {@BLOCK|1%r4|00 {@A-RES|0|+2.471828E+05{@LIM3|+2.490000E+05|+2.639400E+05|+2.340600E+05}} } {@BLOCK|1%r6|00 {@A-RES|0|+2.884832E+06{@LIM3|+3.000000E+06|+3.300000E+06|+2.700000E+06}} } {@BLOCK|1%r8|00 {@A-RES|0|+3.004989E+06{@LIM3|+3.000000E+06|+3.300000E+06|+2.700000E+06}} } {@BLOCK|1%r13|00 {@A-RES|0|+2.972655E+06{@LIM3|+3.000000E+06|+3.300000E+06|+2.700000E+06}} } {@BLOCK|1%r18|00 {@A-RES|0|+3.003106E+06{@LIM3|+3.000000E+06|+3.300000E+06|+2.700000E+06}} } {@BLOCK|1%r15|00 {@A-JUM|0|+2.359659E+00{@LIM2|+1.000000E+01|+0.000000E+00}} } {@BLOCK|1%r16|00 {@A-JUM|0|+2.528427E+00{@LIM2|+1.000000E+01|+0.000000E+00}} } {@BLOCK|1%d1|00 {@A-ZEN|0|+7.104972E+00{@LIM3|+7.800000E+00|+8.580000E+00|+6.630000E+00}} } {@BLOCK|1%d2|00 {@A-ZEN|0|+7.247071E+00{@LIM3|+7.800000E+00|+8.580000E+00|+6.630000E+00}} } {@BLOCK|1%u1_clamp_diode|00 {@A-DIO|0|+6.788804E-01|pin_1_gnd{@LIM2|+9.500000E-01|+4.500000E-01}} {@A-DIO|0|+6.781356E-01|pin_2_gnd{@LIM2|+9.500000E-01|+4.500000E-01}} {@A-DIO|0|+7.446916E-01|pin_3_gnd{@LIM2|+9.500000E-01|+4.500000E-01}} {@A-DIO|0|+6.773469E-01|pin_4_gnd{@LIM2|+9.500000E-01|+4.500000E-01}} {@A-DIO|0|+7.584059E-01|pin_5_gnd{@LIM2|+9.500000E-01|+4.500000E-01}} {@A-DIO|0|+3.095579E-01|pin_7_gnd{@LIM2|+9.500000E-01|+1.500000E-01}} {@A-DIO|0|+3.947794E-01|pin_12_gnd{@LIM2|+9.500000E-01|+2.500000E-01}} {@A-DIO|0|+6.624057E-01|pin_14_gnd{@LIM2|+9.500000E-01|+4.500000E-01}} } {@BLOCK|1%u2_clamp_diode|00 {@A-DIO|0|+1.801263E-01|pin_1_gnd{@LIM2|+6.500000E-01|+1.000000E-01}} {@A-DIO|0|+2.163181E-01|pin_2_gnd{@LIM2|+6.500000E-01|+1.000000E-01}} {@A-DIO|0|+5.671504E-01|pin_4_gnd{@LIM2|+6.500000E-01|+4.000000E-01}} {@A-DIO|0|+7.378564E-01|pin_5_gnd{@LIM2|+8.500000E-01|+5.000000E-01}} } {@BLOCK|1%u3_clamp_diode|00 {@A-DIO|0|+5.667999E-01|pin_11_gnd{@LIM2|+9.500000E-01|+4.500000E-01}} {@A-DIO|0|+5.827926E-01|pin_15_gnd{@LIM2|+9.500000E-01|+4.500000E-01}} {@A-DIO|0|+6.286238E-01|pin_20_gnd{@LIM2|+9.500000E-01|+3.500000E-01}} {@A-DIO|0|+5.840195E-01|pin_22_gnd{@LIM2|+9.500000E-01|+4.500000E-01}} {@A-DIO|0|+5.832746E-01|pin_23_gnd{@LIM2|+9.500000E-01|+4.500000E-01}} {@A-DIO|0|+5.836689E-01|pin_28_gnd{@LIM2|+9.500000E-01|+4.500000E-01}} {@A-DIO|0|+5.830555E-01|pin_29_gnd{@LIM2|+9.500000E-01|+4.500000E-01}} {@A-DIO|0|+5.837566E-01|pin_33_gnd{@LIM2|+9.500000E-01|+4.500000E-01}} {@A-DIO|0|+5.873494E-01|pin_34_gnd{@LIM2|+9.500000E-01|+4.500000E-01}} {@A-DIO|0|+4.056457E-01|pin_41_gnd{@LIM2|+9.500000E-01|+3.000000E-01}} {@A-DIO|0|+5.855968E-01|pin_42_gnd{@LIM2|+9.500000E-01|+4.500000E-01}} } {@BLOCK|1%u4_clamp_diode|00 {@A-DIO|0|+2.209188E-01|pin_8_gnd{@LIM2|+6.500000E-01|+1.000000E-01}} } {@BLOCK|1%testjet|00 {@TJET|00|0000|1%u1 } {@TJET|00|0000|1%u3 } } {@BLOCK|1%u2|00 {@A-MEA|0|+1.667443E+00|boost{@LIM2|+2.000000E+00|+1.000000E+00}} {@A-MEA|0|+2.686483E+00|bypass{@LIM2|+3.150000E+00|+1.200000E+00}} {@D-T|0|384||0|1%u2 } } }} """ # Parse the data using the existing function df, skipped = parse_data(data) # Redirect output to a text file output_file = "parsed_output.txt" with open(output_file, "w") as f: # Write parsed details to the file f.write("\nParsed Data:\n") f.write(df.to_string(index=False)) # Ensure readable DataFrame output f.write(f"\nSkipped Count: {skipped}\n") print(f"Output written to {output_file}") # Call the function to input and parse data input_and_parse_data()
Leave a Comment