doc: add README
This commit is contained in:
parent
094d90715e
commit
0262a27f2c
2 changed files with 153 additions and 35 deletions
94
README.md
Normal file
94
README.md
Normal file
|
@ -0,0 +1,94 @@
|
|||
# Communication System README
|
||||
|
||||
This repository contains a Python-based transmitter/receiver system for sending 40-character text messages over a simulated noisy channel (local or remote server).
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
* Python 3.7+
|
||||
* NumPy
|
||||
|
||||
Install dependencies:
|
||||
|
||||
```bash
|
||||
pip install numpy
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Files
|
||||
|
||||
* `encoder.py` — builds codebook and encodes messages.
|
||||
* `decoder.py` — decodes received samples back into text.
|
||||
* `channel.py` — local channel simulator.
|
||||
* `client.py` — client stub to send samples to the remote server.
|
||||
* `main.py` — main driver: wraps encode → channel → decode, plus performance testing.
|
||||
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
All commands assume you are in the project root directory.
|
||||
|
||||
### 1. Test locally for 1 trial
|
||||
|
||||
```bash
|
||||
python3 main.py \
|
||||
--message "This is a 40-character test message...." \
|
||||
--trials 1 \
|
||||
--mode local
|
||||
```
|
||||
|
||||
### 2. Test locally for 500 trials
|
||||
|
||||
```bash
|
||||
python3 main.py \
|
||||
--message "This is a 40-character test message...." \
|
||||
--trials 500 \
|
||||
--mode local
|
||||
```
|
||||
|
||||
### 3. Test on the remote server (1 trial)
|
||||
|
||||
This will write `input.txt` and `output.txt` in your working directory.
|
||||
|
||||
```bash
|
||||
python3 main.py \
|
||||
--message "This is a 40-character test message...." \
|
||||
--trials 1 \
|
||||
--mode server \
|
||||
--input_file input.txt \
|
||||
--output_file output.txt \
|
||||
--hostname iscsrv72.epfl.ch \
|
||||
--port 80
|
||||
```
|
||||
|
||||
> After running, `input.txt` contains your transmitted samples, and `output.txt` contains the noisy output from the server.
|
||||
|
||||
---
|
||||
|
||||
## Manual decoding of server output
|
||||
|
||||
If you want to decode `output.txt` yourself:
|
||||
|
||||
```bash
|
||||
python3 - << 'EOF'
|
||||
import numpy as np
|
||||
import encoder, decoder
|
||||
|
||||
# Load noisy samples
|
||||
Y = np.loadtxt("output.txt")
|
||||
|
||||
# Rebuild codebook
|
||||
C = encoder.make_codebook(r=5, num_blocks=40)
|
||||
|
||||
# Decode
|
||||
msg = decoder.decode_blocks(Y, C)
|
||||
print("Decoded message:", msg)
|
||||
EOF
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Feel free to adjust `--trials` or swap between `local` and `server` modes as needed.
|
94
main.py
94
main.py
|
@ -7,36 +7,52 @@ import encoder
|
|||
import decoder
|
||||
import channel
|
||||
import subprocess
|
||||
import tempfile
|
||||
import pathlib
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
# Global paths for debugging
|
||||
INPUT_FILE = None
|
||||
OUTPUT_FILE = None
|
||||
|
||||
def transmit(msg, C):
|
||||
"""
|
||||
'''
|
||||
Transmitter: encodes the message into real-valued samples using the codebook C.
|
||||
"""
|
||||
'''
|
||||
return encoder.encode_message(msg, C)
|
||||
|
||||
|
||||
def receive_local(c):
|
||||
"""
|
||||
'''
|
||||
Sends the samples through the local channel simulation.
|
||||
"""
|
||||
'''
|
||||
return channel.channel(c)
|
||||
|
||||
|
||||
def receive_server(c, hostname, port):
|
||||
"""
|
||||
Sends the samples to the remote server via client.py and retrieves the output.
|
||||
"""
|
||||
# Write input samples to a temporary file
|
||||
with tempfile.NamedTemporaryFile(suffix='.txt', delete=False) as in_f:
|
||||
np.savetxt(in_f.name, c)
|
||||
in_name = in_f.name
|
||||
# Prepare output file
|
||||
out_fd, out_name = tempfile.mkstemp(suffix='.txt')
|
||||
os.close(out_fd)
|
||||
'''
|
||||
Sends the samples to the remote server via client.py. If INPUT_FILE and/or
|
||||
OUTPUT_FILE are set, uses those filenames (and preserves them); otherwise uses temporary files.
|
||||
'''
|
||||
global INPUT_FILE, OUTPUT_FILE
|
||||
# Determine input file path
|
||||
if INPUT_FILE:
|
||||
in_name = INPUT_FILE
|
||||
np.savetxt(in_name, c)
|
||||
delete_in = False
|
||||
else:
|
||||
with tempfile.NamedTemporaryFile(suffix='.txt', delete=False) as in_f:
|
||||
np.savetxt(in_f.name, c)
|
||||
in_name = in_f.name
|
||||
delete_in = True
|
||||
# Determine output file path
|
||||
if OUTPUT_FILE:
|
||||
out_name = OUTPUT_FILE
|
||||
delete_out = False
|
||||
else:
|
||||
out_fd, out_name = tempfile.mkstemp(suffix='.txt')
|
||||
os.close(out_fd)
|
||||
delete_out = True
|
||||
# Invoke client.py
|
||||
cmd = [
|
||||
sys.executable,
|
||||
|
@ -50,30 +66,31 @@ def receive_server(c, hostname, port):
|
|||
subprocess.run(cmd, check=True)
|
||||
Y = np.loadtxt(out_name)
|
||||
finally:
|
||||
# Clean up temp files
|
||||
os.remove(in_name)
|
||||
os.remove(out_name)
|
||||
if delete_in and os.path.exists(in_name):
|
||||
os.remove(in_name)
|
||||
if delete_out and os.path.exists(out_name):
|
||||
os.remove(out_name)
|
||||
return Y
|
||||
|
||||
|
||||
def receive(c, mode, hostname, port):
|
||||
"""
|
||||
'''
|
||||
Wrapper to choose local or server channel.
|
||||
"""
|
||||
'''
|
||||
if mode == 'local':
|
||||
return receive_local(c)
|
||||
elif mode == 'server':
|
||||
return receive_server(c, hostname, port)
|
||||
else:
|
||||
raise ValueError("Mode must be 'local' or 'server'")
|
||||
raise ValueError('Mode must be \'local\' or \'server\'')
|
||||
|
||||
|
||||
def test_performance(msg, num_trials, mode, hostname, port):
|
||||
"""
|
||||
'''
|
||||
Runs num_trials transmissions of msg through the specified channel and reports accuracy.
|
||||
"""
|
||||
'''
|
||||
if len(msg) != 40:
|
||||
raise ValueError("Message must be exactly 40 characters.")
|
||||
raise ValueError('Message must be exactly 40 characters.')
|
||||
# Build codebook for 64 symbols, 40 blocks
|
||||
C = encoder.make_codebook(r=5, num_blocks=40)
|
||||
successes = 0
|
||||
|
@ -88,27 +105,34 @@ def test_performance(msg, num_trials, mode, hostname, port):
|
|||
successes += 1
|
||||
pct = successes / num_trials * 100
|
||||
# Display results
|
||||
print(f"Message: {msg}")
|
||||
print(f"Trials: {num_trials}")
|
||||
print(f"Mode: {mode}")
|
||||
print(f"Correct decodings: {successes}")
|
||||
print(f"Accuracy: {pct:.2f}%")
|
||||
print(f'Message: {msg}')
|
||||
print(f'Trials: {num_trials}')
|
||||
print(f'Mode: {mode}')
|
||||
print(f'Correct decodings: {successes}')
|
||||
print(f'Accuracy: {pct:.2f}%')
|
||||
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser(description="Test communication system performance.")
|
||||
parser = argparse.ArgumentParser(description='Test communication system performance.')
|
||||
parser.add_argument('--message', '-m', type=str, required=True,
|
||||
help="40-character message to send.")
|
||||
parser.add_argument('--trials', '-n', type=int, default=1,
|
||||
help="Number of trials.")
|
||||
help='40-character message to send.')
|
||||
parser.add_argument('--trials', '-n', type=int, default=200,
|
||||
help='Number of trials.')
|
||||
parser.add_argument('--mode', choices=['local','server'], default='local',
|
||||
help="Channel mode: 'local' or 'server'.")
|
||||
parser.add_argument('--hostname', type=str, default='iscsrv72.epfl.ch',
|
||||
help="Server hostname for server mode.")
|
||||
help='Server hostname for server mode.')
|
||||
parser.add_argument('--port', type=int, default=80,
|
||||
help="Server port for server mode.")
|
||||
help='Server port for server mode.')
|
||||
parser.add_argument('--input_file', '-i', type=str, default=None,
|
||||
help='Path to write server input samples (input.txt).')
|
||||
parser.add_argument('--output_file', '-o', type=str, default=None,
|
||||
help='Path to write server output samples (output.txt).')
|
||||
return parser.parse_args()
|
||||
|
||||
if __name__ == '__main__':
|
||||
args = parse_args()
|
||||
# Set global paths
|
||||
INPUT_FILE = args.input_file
|
||||
OUTPUT_FILE = args.output_file
|
||||
test_performance(args.message, args.trials, args.mode, args.hostname, args.port)
|
||||
|
|
Loading…
Add table
Reference in a new issue