Run
There are two steps involved in using the InstruPy package for calculation of data-metrics associated with an instrument and an access-event:
Initialize the relevant instrument model from a python dictionary or json-string. Description of the expected model-parameters from the user can be obtained from the Instrument Models section. Specifications of example instruments (in the required JSON format) is available in the
instrupy/examples/directory.Invoke the
calc_data_metricsfunction from the model instance by passing the access-event information. The access-event information is most commonly the observation-time, state (position/velocity) of the observer and the location of the target. Another type of access-event specification involve specifying the incidence angle at the target, which is available for the synthetic aperture radar model. For more details please refer to the (API Reference) section of the respective modules.
All the instrument-models have identical interface functions, i.e.:
The model-instances can be obtained by using the
from_dict/from_jsonfunctions in which the model parameters are passed as dict/json.The
to_dictfunction can be used to obtain a dictionary representation of the model.The
calc_data_metricsfunction can be used to calculate data-metrics by passing the access-event information as the input argument.
Example:
A passive optical scanner instrument model.
from instrupy.passive_optical_scanner_model import PassiveOpticalScannerModel
# instrument specifications in a python dictionary
firesat_dict = { "@type": "Passive Optical Scanner",
"name": "FireSat",
"mass": 28,
"volume": 0.12,
"power": 32,
"fieldOfViewGeometry": {
"shape": "RECTanGULAR",
"angleHeight": 0.628,
"angleWidth": 115.8
},
"scanTechnique": "WhiskBROOM",
"orientation": {
"referenceFrame": "SC_BODY_FIXED",
"convention": "SIDE_loOK",
"sideLookAngle": 0
},
"dataRate": 85,
"numberDetectorRows": 256,
"numberDetectorCols": 1,
"detectorWidth": 30e-6,
"focalLength": 0.7,
"operatingWavelength": 4.2e-6,
"bandwidth": 1.9e-6,
"quantumEff": 0.5,
"targetBlackBodyTemp": 290,
"bitsPerPixel": 8,
"opticsSysEff": 0.75,
"numOfReadOutE": 25,
"apertureDia": 0.26,
"Fnum": 2.7,
"atmosLossModel": "LOWTRAN7"}
# obtain the instrument model instance from the python dict
firesat = PassiveOpticalScannerModel.from_dict(firesat_dict)
# define the access event (time of observation, position, velocity of observer and position of target)
epoch_JDUT1 = 2451623.999630
sc_orbit_state = {'time [JDUT1]':epoch_JDUT1, 'x [km]': 7078.137, 'y [km]': 0, 'z [km]': 0, 'vx [km/s]': 0, 'vy [km/s]': 7.5, 'vz [km/s]': 0} # equatorial orbit, altitude about 700 km
target_coords = {'lat [deg]': 0, 'lon [deg]': 0} # lat = 0, lon = 0 corresponds to [6378, 0, 0] km in ECI for observer position, check using Matlab function: eci2lla([6378, 0, 0] ,[2000 3 20 11 59 28.000])
# execute the data metrics calculation
data_metrics = firesat.calc_data_metrics(sc_orbit_state, target_coords)
print(data_metrics)
>> {'ground pixel along-track resolution [m]': 31.34, 'ground pixel cross-track resolution [m]': 32.91,
'SNR': 148.15, 'dynamic range': 902.27, 'noise-equivalent delta T [K]': 0.30609}
Instrument class
The instrupy.base.Instrument class can be used to model a instrument with several operating modes. The Instrument class
has the same interface functions as that of the instrument-model classes (i.e. from_dict/ from_json, to_dict and calc_data_metrics).
Each mode corresponds to a specific operating point and the mode-only specifications are stored as a list under the mode key.
A mode-identifier can be specified by the user with which the corresponding mode can be referenced. Also see here.
Note
The Instrument class may be used without specifying any modes. This may be desirable if one wishes to avoid using different classes
for each instrument-model. Since the Instrument class provides the same interface functions as the instrument-model classes, the
usage is identical. Refer to base module API reference.
Example
Consider a Synthetic Aperture Radar instrument which can operate in single-pol or dual-pol. Such an instrument is considered
to be made up of two modes and the polarization specifications are included in a list under the mode key. Such an instrument specification
effectively makes two synthetic aperture radar models with common parameters specified by the key/value pairs other then the mode key/value.
One model shall use single-pol and the other model uses dual-pol.
Note the 3dB difference in the NESZ results of the below example.
from instrupy.base import Instrument
specs = { "@type": "Synthetic Aperture Radar",
"orientation": {
"referenceFrame": "SC_BODY_FIXED",
"convention": "SIDE_LOOK",
"sideLookAngle": 30
},
"mode":[{
"@id": "dual-pol",
"polarization": {
"@type": "dual",
"pulseConfig": {"@type": "AIRSAR"}
}
},
{
"@id": "single-pol",
"polarization": {
"@type": "single"
}
}
],
"pulseWidth": 14.16e-6,
"antenna":{"shape": "RECTANGULAR", "height": 14.38, "width": 1.48,
"apertureEfficiency": 0.6, "apertureExcitationProfile": "UNIFORM"},
"operatingFrequency": 1280e6,
"peakTransmitPower": 1000,
"chirpBandwidth": 0.86e6,
"minimumPRF": 1,
"maximumPRF": 20000,
"radarLoss": 2,
"systemNoiseFigure": 2,
"swathConfig": {
"@type": "fixed",
"fixedSwathSize": 50
}
}
# obtain the instrument model instance from the python dict
instru = Instrument.from_dict(specs)
# define the access event (time of observation, position, velocity of observer and position of target)
epoch_JDUT1 = 2451623.999630# 2000 3 20 11 59 28.000
# lat = 0, lon = 0 corresponds to [6378, 0, 0] km in ECI for observer position, check using Matlab function: eci2lla([6378, 0, 0] ,[2000 3 20 11 59 28.000])
sc_orbit_state = {'time [JDUT1]':epoch_JDUT1, 'x [km]': 6378.137 + 600, 'y [km]': 0, 'z [km]': 0, 'vx [km/s]': 0, 'vy [km/s]': 7.559, 'vz [km/s]': 0} # equatorial orbit, altitude 600 km
target_coords = {'lat [deg]': 2, 'lon [deg]': 0} # incidence angle to the target is 28.9855 deg
# execute the data metrics calculation
data_metrics = instru.calc_data_metrics(mode_id="single-pol", sc_orbit_state=sc_orbit_state, target_coords=target_coords)
print(data_metrics)
>> {'ground pixel along-track resolution [m]': 6.13, 'ground pixel cross-track resolution [m]': 431.62, 'NESZ [dB]': -39.58,
'incidence angle [deg]': 28.99, 'swath-width [km]': 50.0, 'PRF [Hz]': 2494}
data_metrics = instru.calc_data_metrics(mode_id="dual-pol", sc_orbit_state=sc_orbit_state, target_coords=target_coords)
print(data_metrics)
>> {'ground pixel along-track resolution [m]': 6.13, 'ground pixel cross-track resolution [m]': 431.62, 'NESZ [dB]': -36.57,
'incidence angle [deg]': 28.99, 'swath-width [km]': 50.0, 'PRF [Hz]': 2494}