Skip to main content

Python library for controlling SciGlob scientific instrumentation: Head Sensors, Trackers, Filter Wheels, and more

Project description

SciGlob Library

Python library for controlling SciGlob scientific instrumentation

Python 3.9+ License: MIT


Overview

SciGlob Library provides a unified Python interface for controlling scientific instruments used in atmospheric monitoring systems, including:

Component Description Protocol
Head Sensor Main communication hub (SciGlobHSN1, SciGlobHSN2) RS-232
Tracker Azimuth/Zenith motor control (Directed Perceptions, LuftBlickTR1) via Head Sensor
Filter Wheels FW1, FW2 with 9 positions each via Head Sensor
Shadowband Shadowband arm positioning via Head Sensor
Temperature Controller TETech1 (16-bit), TETech2 (32-bit) RS-232
Humidity Sensor HDC2080EVM RS-232
GPS/Positioning GlobalSat (GPS), Novatel (GPS+Gyro) RS-232

Installation

From Source

git clone https://github.com/ashutoshjoshi1/SciGlob-Library.git
cd SciGlob-Library
pip install -e .

With Development Dependencies

pip install -e ".[dev]"

Quick Start

Head Sensor with Tracker & Filter Wheels

from sciglob import HeadSensor

with HeadSensor(port="/dev/ttyUSB0") as hs:
    # Get device info
    print(f"Device: {hs.device_id}")
    print(f"Type: {hs.sensor_type}")
    
    # Read internal sensors (SciGlobHSN2 only)
    if hs.sensor_type == "SciGlobHSN2":
        print(f"Temperature: {hs.get_temperature()}°C")
        print(f"Humidity: {hs.get_humidity()}%")
        print(f"Pressure: {hs.get_pressure()} mbar")
    
    # Control tracker (azimuth/zenith motors)
    tracker = hs.tracker
    tracker.move_to(zenith=45.0, azimuth=180.0)
    print(f"Position: {tracker.get_position()}")
    
    # Control filter wheel
    fw1 = hs.filter_wheel_1
    fw1.set_filter("OPEN")
    print(f"Current filter: {fw1.current_filter}")

Tracker Commands

# Movement in degrees
tracker.move_to(zenith=45.0, azimuth=180.0)  # Absolute position
tracker.move_relative(delta_zenith=10.0, delta_azimuth=-20.0)  # Relative
tracker.pan(azimuth=90.0)   # Azimuth only
tracker.tilt(zenith=30.0)   # Zenith only

# Movement in steps
tracker.move_to_steps(zenith_steps=4500, azimuth_steps=-1200)

# Get position
zenith, azimuth = tracker.get_position()       # In degrees
azi_steps, zen_steps = tracker.get_position_steps()  # In steps

# Special commands
tracker.home()          # Go to home position
tracker.park()          # Go to parking position
tracker.reset()         # Soft reset
tracker.power_reset()   # Power cycle

# LuftBlickTR1 specific
if tracker.is_luftblick:
    temps = tracker.get_motor_temperatures()
    alarms = tracker.get_motor_alarms()
    tracker.check_alarms()  # Raises exception if alarm present

Filter Wheel Commands

# Select by position (1-9)
fw1.set_position(5)

# Select by filter name
fw1.set_filter("U340")

# Get current state
print(fw1.position)       # Current position number
print(fw1.current_filter) # Current filter name

# Get filter configuration
print(fw1.get_filter_map())        # {1: "OPEN", 2: "U340", ...}
print(fw1.get_available_filters()) # ["OPEN", "U340", ...]

# Reset to home
fw1.reset()

Temperature Controller

from sciglob import TemperatureController

with TemperatureController(port="/dev/ttyUSB1", controller_type="TETech1") as tc:
    # Read temperature
    print(f"Current: {tc.get_temperature()}°C")
    print(f"Setpoint: {tc.get_setpoint()}°C")
    
    # Set temperature
    tc.set_temperature(25.0)
    
    # Control output
    tc.enable_output()
    tc.disable_output()

Humidity Sensor

from sciglob import HumiditySensor

with HumiditySensor(port="/dev/ttyUSB2") as hs:
    print(f"Temperature: {hs.get_temperature()}°C")
    print(f"Humidity: {hs.get_humidity()}%")

GPS Positioning

from sciglob import GlobalSatGPS, NovatelGPS

# Simple GPS
with GlobalSatGPS(port="/dev/ttyUSB3") as gps:
    pos = gps.get_position()
    print(f"Lat: {pos['latitude']}, Lon: {pos['longitude']}")

# GPS + Gyroscope
with NovatelGPS(port="/dev/ttyUSB4") as gps:
    pos = gps.get_position()
    orient = gps.get_orientation()
    print(f"Yaw: {orient['yaw']}°, Pitch: {orient['pitch']}°")

Architecture

┌─────────────────────────────────────────────────────────────────┐
│                        Application                               │
└─────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                    SciGlob Library API                          │
│  ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐   │
│  │  Head   │ │ Tracker │ │ Filter  │ │  Temp   │ │  GPS    │   │
│  │ Sensor  │ │         │ │  Wheel  │ │ Control │ │         │   │
│  └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘   │
│       │           │          │          │          │            │
│       └──────────┴──────────┘          │          │            │
│                  │                      │          │            │
└──────────────────┼──────────────────────┼──────────┼────────────┘
                   │                      │          │
                   ▼                      ▼          ▼
           ┌────────────┐          ┌────────────────────────┐
           │ Head Sensor│          │   Independent Devices  │
           │   RS-232   │          │       RS-232           │
           │  (9600 bd) │          │      (9600 bd)         │
           └────────────┘          └────────────────────────┘

Device Commands Quick Reference

Head Sensor

Command Response Description
? Device ID Query identification
HTt? HT!<value> Temperature (÷100 = °C)
HTh? HT!<value> Humidity (÷1024 = %)
HTp? HT!<value> Pressure (÷100 = mbar)

Tracker

Command Response Description
TRp<steps> TR0 Pan (azimuth only)
TRt<steps> TR0 Tilt (zenith only)
TRb<azi>,<zen> TR0 Move both axes
TRw TRh<azi>,<zen> Query position
TRr TR0 Soft reset
TRs TR0 Power reset

Filter Wheel

Command Response Description
F1<1-9> F10 Set FW1 position
F2<1-9> F20 Set FW2 position
F1r F10 Reset FW1
F2r F20 Reset FW2

Error Handling

from sciglob import (
    HeadSensor,
    ConnectionError,
    TrackerError,
    PositionError,
    FilterWheelError,
    MotorAlarmError,
)

try:
    with HeadSensor(port="/dev/ttyUSB0") as hs:
        # This will raise PositionError if out of limits
        hs.tracker.move_to(zenith=100.0, azimuth=180.0)
        
except ConnectionError as e:
    print(f"Connection failed: {e}")
except PositionError as e:
    print(f"Position out of range: {e.position} not in [{e.min_pos}, {e.max_pos}]")
except MotorAlarmError as e:
    print(f"Motor alarm on {e.axis}: code {e.alarm_code}")
except TrackerError as e:
    print(f"Tracker error: {e}")

Configuration

Head Sensor Configuration

hs = HeadSensor(
    port="/dev/ttyUSB0",
    baudrate=9600,
    tracker_type="LuftBlickTR1",     # or "Directed Perceptions"
    degrees_per_step=0.01,           # 100 steps per degree
    motion_limits=[0, 90, 0, 360],   # [zen_min, zen_max, azi_min, azi_max]
    home_position=[0.0, 180.0],      # [zenith_home, azimuth_home]
    fw1_filters=["OPEN", "U340", "BP300", "LPNIR", "ND1", "ND2", "ND3", "ND4", "OPAQUE"],
    fw2_filters=["OPEN", "DIFF", "U340+DIFF", ...],
)

Logging

import logging

# Enable debug logging
logging.basicConfig(level=logging.DEBUG)
logging.getLogger("sciglob").setLevel(logging.DEBUG)

# Or for specific components
logging.getLogger("sciglob.Tracker").setLevel(logging.DEBUG)
logging.getLogger("sciglob.serial").setLevel(logging.DEBUG)

Requirements

  • Python 3.9+
  • pyserial >= 3.5
  • pyyaml >= 6.0

License

MIT License - see LICENSE for details.


Documentation


Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Run tests: pytest
  5. Submit a pull request

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sciglob-0.1.3.tar.gz (53.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sciglob-0.1.3-py3-none-any.whl (41.0 kB view details)

Uploaded Python 3

File details

Details for the file sciglob-0.1.3.tar.gz.

File metadata

  • Download URL: sciglob-0.1.3.tar.gz
  • Upload date:
  • Size: 53.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.8

File hashes

Hashes for sciglob-0.1.3.tar.gz
Algorithm Hash digest
SHA256 99a85b66dfa91b716685ceb48dbdd98f92e03d2299534d2a5e3c580f2e2b7db1
MD5 b9cd694faa92d0193bd6f6737c926a23
BLAKE2b-256 dcb73aa206aebd906a861bdcf3040bc13041dba455855a2b709a7f09a43d06eb

See more details on using hashes here.

File details

Details for the file sciglob-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: sciglob-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 41.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.8

File hashes

Hashes for sciglob-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 331ea9ac980c6e34e28368946f2ef6606163a0a56315e998ac54cec45d862d03
MD5 58a1289687f9ce4c8bb2b8f57f7a628f
BLAKE2b-256 c063aa38019118279131325ed1539a9ff7cb0807262be294fc2de8fc5adea97d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page