Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stharrold/ce469bbe797118c2a591 to your computer and use it in GitHub Desktop.
Save stharrold/ce469bbe797118c2a591 to your computer and use it in GitHub Desktop.
20150314T130000_file_metadata_inspection_on_lonestar.txt
login1.ls4(37)$ pwd
/corral-repl/utexas/White_Dwarf_Archive/ProEM_1024B
login1.ls4(38)$ cd 20141121
login1.ls4(39)$ ls
bias dark dome_flat SDSSJ0651+2844 WDJ0117+2513
login1.ls4(40)$ cd SDSSJ0651+2844/
login1.ls4(41)$ ls | less
login1.ls4(42)$ tail SDSSJ0651+2844.spe
??5&?D?BP'?? K?"?!18+?? ??????67?7
$7D9/:62@&?,"+<2?E7$%HH5=(??O9M0=7Iw0?&KT)/:3?QO(X.D<=#$;p6VJ68+OAQ-@?
)MF<u0#&3/3$[NKCx(6?=58%8
3M/<??O-70:/B$3!#5!;4(?G4D
;!???-
+??!7
?
?????????4????5?'??
??&$
???7V#"4
6$ "/?Z? LS$Z$Cj672(?S8"?=
[&==9'/'4?l\#:)60QI59a]9P1*@?555?7GY4?%E*5 %?,0:0"!;DP5_U?rGH5S"0
B4I;4o79N(@< '>@%**P8(G#
?9/?+?
Q
?7%??*?5?
-&#???? ??%???????????????5)
,09?,? *</9%?:#+?? ?)5"+(%L0ONF<-V&',05;09"93=41/?OcI/C&=?*1IS#>05!
5QC16m,S+&,QP?*?)E6?K?,?4d5(N]0B-FF UI?\F$65&-3$8PK/)C+L=?"
?!??d%?3B?'??
G????? ?'
1???(.?????? ?????
????.?1????*?"6
/#*M1+N*@KWb%?&C?1H+3-/89?&'&4KO??!M0$@!!!?Q7?A:
1<9<,4X;,?+0XF3F 1+7H
?,)6*/T3FD^k=m(H?/`?'""M*, ??&6??????E?;?
???1?U<SpeFormat version="3.0" xmlns="http://www.princetoninstruments.com/spe/2009"><DataFormat><DataBlock type="Frame" count="1615" pixelFormat="MonochromeUnsigned16" size="131072" stride="131096" metaFormat="1"><DataBlock type="Region" calibrations="1,2" count="1" width="256" height="256" size="131072" stride="131072" /></DataBlock></DataFormat><MetaFormat><MetaBlock id="1"><TimeStamp event="ExposureStarted" type="Int64" bitDepth="64" resolution="1000000" absoluteTime="2014-11-21T07:46:41.7946296Z" /><TimeStamp event="ExposureEnded" type="Int64" bitDepth="64" resolution="1000000" absoluteTime="2014-11-21T07:46:41.7946296Z" /><FrameTrackingNumber type="Int64" bitDepth="64" /></MetaBlock></MetaFormat><Calibrations><SensorInformation id="1" orientation="Normal" width="1024" height="1024" /><SensorMapping id="2" x="0" y="0" height="1024" width="1024" xBinning="4" yBinning="4" /></Calibrations><DataHistories><DataHistory id="1"><Origin creator="admin" created="2014-11-21T07:46:41.7666268Z" software="LightField" softwareVersion="4.9.0.1409" softwareCompany="Princeton Instruments"><Experiment xmlns="http://www.princetoninstruments.com/experiment/2009" version="6" xmlns:r="http://www.princetoninstruments.com/experiment/restore/2009" r:version="1"><System><Cameras count="1"><Camera deviceID="1" model="ProEM: 1024B" serialNumber="2202120003" computerInterface="Gigabit Ethernet" demo="False" /></Cameras><LightSources count="1"><LightSource deviceID="2" model="LightSource" /></LightSources><DeviceLinks count="1"><DeviceLink firstDeviceID="1" firstDeviceLinkNode="Input" secondDeviceID="2" secondDeviceLinkNode="Output" /></DeviceLinks></System><Devices><Cameras count="1"><Camera deviceID="1"><Sensor><Layout><ActiveArea><Width r:priority="1" type="Int32">1024</Width><Height r:priority="1" type="Int32">1024</Height><TopMargin type="Int32">2</TopMargin><LeftMargin type="Int32">32</LeftMargin><BottomMargin type="Int32">6</BottomMargin><RightMargin type="Int32">16</RightMargin></ActiveArea><MaskedArea><Height type="Int32">1024</Height><TopMargin type="Int32">7</TopMargin><BottomMargin type="Int32">6</BottomMargin></MaskedArea></Layout><Information><SensorName r:readOnly="True" type="String">E2V 1024 x 1024 (CCD 201)(B)</SensorName><CcdCharacteristics r:readOnly="True" type="CcdCharacteristics">BackIlluminated</CcdCharacteristics><Type r:readOnly="True" type="SensorType">Ccd</Type><ActiveArea><Height r:readOnly="True" type="Int32">1024</Height><Width r:readOnly="True" type="Int32">1024</Width><BottomMargin r:readOnly="True" type="Int32">6</BottomMargin><LeftMargin r:readOnly="True" type="Int32">32</LeftMargin><RightMargin r:readOnly="True" type="Int32">16</RightMargin><TopMargin r:readOnly="True" type="Int32">2</TopMargin></ActiveArea><MaskedArea><BottomMargin r:readOnly="True" type="Int32">6</BottomMargin><Height r:readOnly="True" type="Int32">1024</Height><TopMargin r:readOnly="True" type="Int32">7</TopMargin></MaskedArea><Pixel><Width r:readOnly="True" type="Double">13</Width><Height r:readOnly="True" type="Double">13</Height><GapWidth r:readOnly="True" type="Double">0</GapWidth><GapHeight r:readOnly="True" type="Double">0</GapHeight></Pixel><Secondary><ActiveArea><Height r:readOnly="True" type="Int32">0</Height></ActiveArea><MaskedArea><Height r:readOnly="True" type="Int32">0</Height></MaskedArea></Secondary></Information><Temperature><SetPoint type="Double">-55</SetPoint><Reading r:readOnly="True" type="Double">-55</Reading><Status r:readOnly="True" type="SensorTemperatureStatus">Locked</Status><DisableCoolingFan type="Boolean">False</DisableCoolingFan></Temperature><Cleaning><FinalSectionHeight type="Int32">1024</FinalSectionHeight><FinalSectionCount type="Int32">1</FinalSectionCount><CleanSerialRegister relevance="False" type="Boolean">True</CleanSerialRegister><CleanUntilTrigger type="Boolean">True</CleanUntilTrigger><CycleCount type="Int32">1</CycleCount><CycleHeight type="Int32">1024</CycleHeight><CleanBeforeExposure relevance="False" type="Boolean">True</CleanBeforeExposure></Cleaning></Sensor><ShutterTiming><ExposureTime type="Double">9998</ExposureTime><DelayResolution r:readOnly="True" type="Double">1000</DelayResolution><OpeningDelay type="Double">0</OpeningDelay><Mode type="ShutterTimingMode">AlwaysOpen</Mode><ClosingDelay type="Double">0</ClosingDelay></ShutterTiming><ReadoutControl><Mode r:priority="2" type="ReadoutControlMode">FrameTransfer</Mode><Time r:readOnly="True" type="Double">147.58800000000005</Time><Orientation r:readOnly="True" type="ReadoutOrientation">Normal</Orientation><StorageShiftRate r:priority="5" type="Double">1.2</StorageShiftRate><VerticalShiftRate relevance="False" r:priority="5" type="Double">1.2</VerticalShiftRate><RegionsOfInterest><Selection r:priority="2" type="RegionsOfInterestSelection">BinnedSensor</Selection><BinningProvider r:priority="2" type="FeatureProvider">Hardware</BinningProvider><CustomRegions r:priority="5" count="1" relevance="False" type="RegionOfInterestCollection"><RegionOfInterest id="0" x="0" width="1024" xBinning="1" y="0" height="1024" yBinning="1" /></CustomRegions><BinnedSensor><XBinning r:priority="3" type="Int32">4</XBinning><YBinning r:priority="3" type="Int32">4</YBinning></BinnedSensor><LineSensor><RowBinning relevance="False" r:priority="3" type="Int32">1</RowBinning></LineSensor><Result r:readOnly="True" type="RegionOfInterestCollection" count="1"><RegionOfInterest id="0" x="0" width="1024" xBinning="4" y="0" height="1024" yBinning="4" /></Result></RegionsOfInterest><Kinetics><WindowHeight relevance="False" r:priority="1" type="Int32">10</WindowHeight></Kinetics></ReadoutControl><HardwareIO><OutputSignal type="OutputSignal">Exposing</OutputSignal><TriggerDetermination type="TriggerDetermination">RisingEdge</TriggerDetermination><TriggerResponse type="TriggerResponse">ReadoutPerTrigger</TriggerResponse><InvertOutputSignal type="Boolean">False</InvertOutputSignal></HardwareIO><Adc><Speed type="Double">1</Speed><BitDepth r:readOnly="True" type="Int32">16</BitDepth><AnalogGain type="AdcGain">High</AnalogGain><EMGain relevance="False" type="Int32">1</EMGain><Quality r:priority="2" type="AdcQuality">LowNoise</Quality><CorrectPixelBias type="Boolean">True</CorrectPixelBias></Adc><Acquisition><Orientation r:readOnly="True" type="ReadoutOrientation">Normal</Orientation><NormalizeOrientation relevance="False" r:priority="3" type="Boolean">True</NormalizeOrientation><PixelFormat r:readOnly="True" type="PixelFormat">MonochromeUnsigned16</PixelFormat><FrameSize r:readOnly="True" type="Int32">131072</FrameSize><FrameStride r:readOnly="True" type="Int32">131096</FrameStride><FramesPerReadout r:readOnly="True" type="Int32">1</FramesPerReadout><ReadoutStride r:readOnly="True" type="Int32">131596</ReadoutStride><PixelDepth r:readOnly="True" type="Int32">16</PixelDepth><ReadoutRate r:readOnly="True" type="Double">0.10000761658007874</ReadoutRate><FrameRate r:readOnly="True" type="Double">0.10000761658007874</FrameRate><FrameTracking><BitDepth r:readOnly="True" type="Int32">64</BitDepth><Enabled type="Boolean">True</Enabled></FrameTracking><TimeStamping><BitDepth r:readOnly="True" type="Int32">64</BitDepth><Resolution r:readOnly="True" type="Int64">1000000</Resolution><Stamps type="TimeStamps">ExposureStarted, ExposureEnded</Stamps></TimeStamping></Acquisition><Experiment><Acquisition><FramesToStore type="Int64">99999</FramesToStore><FrameSize r:readOnly="True" type="Int32">131072</FrameSize><FrameStride r:readOnly="True" type="Int32">131096</FrameStride><PixelDepth r:readOnly="True" type="Int32">16</PixelDepth><PixelFormat r:readOnly="True" type="PixelDataFormat">MonochromeUnsigned16</PixelFormat><Orientation><Result r:readOnly="True" type="ImageOrientation">Normal</Result></Orientation><OutputFiles><Result r:readOnly="True" type="String">D:\sync_to_White_Dwarf_Archive\20141121\SDSSJ0651+2844\SDSSJ0651+2844.spe</Result></OutputFiles></Acquisition><FileNameGeneration><Directory r:priority="4" type="String">D:\sync_to_White_Dwarf_Archive\20141121\SDSSJ0651+2844</Directory><BaseFileName r:priority="4" type="String">SDSSJ0651+2844</BaseFileName><AttachTime r:priority="4" type="Boolean">False</AttachTime><AttachDate r:priority="4" type="Boolean">False</AttachDate><FileFormatLocation relevance="False" r:priority="3" type="FileFormatLocation">Suffix</FileFormatLocation><AttachIncrement r:priority="4" type="Boolean">False</AttachIncrement><TimeFormat relevance="False" r:priority="5" type="TimeFormat">hh_mm_ss_24hr</TimeFormat><DateFormat relevance="False" r:priority="5" type="DateFormat">yyyy_mm_dd</DateFormat><IncrementNumber relevance="False" r:priority="5" type="Int32">1</IncrementNumber><IncrementMinimumDigits relevance="False" r:priority="5" type="Int32">1</IncrementMinimumDigits><SaveRawData relevance="False" r:priority="1" type="Boolean">True</SaveRawData></FileNameGeneration><OnlineProcessing><FrameCombination><FramesCombined r:priority="2" type="Int64">1</FramesCombined><Method relevance="False" r:priority="3" type="FrameCombinationMethod">Average</Method></FrameCombination></OnlineProcessing><OnlineCorrections><OrientationCorrection><Enabled r:priority="1" type="Boolean">False</Enabled><FlipHorizontally relevance="False" r:priority="2" type="Boolean">False</FlipHorizontally><FlipVertically relevance="False" r:priority="2" type="Boolean">False</FlipVertically><RotateClockwise relevance="False" r:priority="2" type="Int32">0</RotateClockwise></OrientationCorrection><BlemishCorrection><Enabled r:priority="3" type="Boolean">False</Enabled><DefinitionFile relevance="False" r:priority="4" type="String">D:\LightField_Defaults\Correction Files\BlemishCorrection.CSV</DefinitionFile></BlemishCorrection><BackgroundCorrection><Enabled r:priority="3" type="Boolean">False</Enabled><ReferenceFile relevance="False" r:priority="4" type="String">D:\LightField_Defaults\Correction Files\BackgroundReference.spe</ReferenceFile></BackgroundCorrection><FlatfieldCorrection><Enabled r:priority="3" type="Boolean">False</Enabled><ReferenceFile relevance="False" r:priority="4" type="String">D:\LightField_Defaults\Correction Files\FlatfieldReference.spe</ReferenceFile></FlatfieldCorrection><CosmicRayCorrection><Enabled r:priority="3" type="Boolean">False</Enabled><Method relevance="False" r:priority="4" type="CosmicRayCorrectionMethod">MedianFilter</Method><KernelSize relevance="False" r:priority="5" type="Int32">5</KernelSize></CosmicRayCorrection></OnlineCorrections></Experiment></Camera></Cameras></Devices><Environment><WorkingDirectory type="String">D:\LightField_Defaults</WorkingDirectory><ScratchDirectory type="String">D:\LightField_Defaults</ScratchDirectory></Environment></Experiment></Origin></DataHistory></DataHistories><GeneralInformation><FileInformation creator="ARGOS-DEV2\admin" created="2014-11-21T12:16:54.2073435Z" lastModified="2014-11-21T12:16:54.2073435Z" /></GeneralInformation></SpeFormat>login1.ls4(43)$
login1.ls4(43)$ cd /work/02109/ccd/White_Dwarf_Archive_Software/src/tsphot/
login1.ls4(44)$ ipython
WARNING: Attempting to work in a virtualenv. If you encounter problems, please install IPython inside the virtualenv.
Python 2.7.7 |Anaconda 2.0.1 (64-bit)| (default, Jun 2 2014, 12:34:02)
Type "copyright", "credits" or "license" for more information.
IPython 2.1.0 -- An enhanced Interactive Python.
Anaconda is brought to you by Continuum Analytics.
Please check out: http://continuum.io/thanks and https://binstar.org
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
In [1]: !pwd
/work/02109/ccd/White_Dwarf_Archive_Software/src/tsphot
In [2]: from __future__ import print_function
In [3]: import os
In [4]: import read_spe
Caching the list of root modules, please wait!
(This will only be done once - type '%rehashx' to reset cache!)
This is taking too long, we give up.
Display all 329 possibilities? (y or n)
In [4]: import read_spe
In [5]: file_path = '/corral-repl/utexas/White_Dwarf_Archive/ProEM_1024B'
In [6]: file_name = 'SDSSJ0651+2844.spe'
In [7]: file_full = os.path.join(file_path, file_name)
In [8]: spe = read_spe.File(file_full)
---------------------------------------------------------------------------
IOError Traceback (most recent call last)
<ipython-input-8-f1bc44bb5e84> in <module>()
----> 1 spe = read_spe.File(file_full)
/work/02109/ccd/White_Dwarf_Archive_Software/src/tsphot/read_spe.py in __init__(self, fname)
58 # For final reductions, read more complete metadata from XML footer.
59 self._fname = fname
---> 60 self._check_spe()
61 self._fid = open(fname, 'rb')
62 self._load_header_metadata()
/work/02109/ccd/White_Dwarf_Archive_Software/src/tsphot/read_spe.py in _check_spe(self)
72 """
73 if not os.path.isfile(self._fname):
---> 74 raise IOError(("File does not exist: {fname}").format(fname=self._fname))
75 (fbase, fext) = os.path.splitext(self._fname)
76 if fext != '.spe':
IOError: File does not exist: /corral-repl/utexas/White_Dwarf_Archive/ProEM_1024B/SDSSJ0651+2844.spe
In [9]: file_path = '/corral-repl/utexas/White_Dwarf_Archive/ProEM_1024B/SDSSJ0651+2844'
In [10]: file_full = os.path.join(file_path, file_name)
In [11]: spe = read_spe.File(file_full)
---------------------------------------------------------------------------
IOError Traceback (most recent call last)
<ipython-input-11-f1bc44bb5e84> in <module>()
----> 1 spe = read_spe.File(file_full)
/work/02109/ccd/White_Dwarf_Archive_Software/src/tsphot/read_spe.py in __init__(self, fname)
58 # For final reductions, read more complete metadata from XML footer.
59 self._fname = fname
---> 60 self._check_spe()
61 self._fid = open(fname, 'rb')
62 self._load_header_metadata()
/work/02109/ccd/White_Dwarf_Archive_Software/src/tsphot/read_spe.py in _check_spe(self)
72 """
73 if not os.path.isfile(self._fname):
---> 74 raise IOError(("File does not exist: {fname}").format(fname=self._fname))
75 (fbase, fext) = os.path.splitext(self._fname)
76 if fext != '.spe':
IOError: File does not exist: /corral-repl/utexas/White_Dwarf_Archive/ProEM_1024B/SDSSJ0651+2844/SDSSJ0651+2844.spe
In [12]: file_path = '/corral-repl/utexas/White_Dwarf_Archive/ProEM_1024B/20141121/SDSSJ0651+2844'
In [13]: file_full = os.path.join(file_path, file_name)
In [14]: spe = read_spe.File(file_full)
In [15]: # helps when you read your input
In [16]: dir(spe)
Out[16]:
['__class__',
'__delattr__',
'__dict__',
'__doc__',
'__format__',
'__getattribute__',
'__hash__',
'__init__',
'__module__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'_binary_to_ntype',
'_bits_per_byte',
'_check_spe',
'_datatype_to_ntype',
'_fid',
'_fname',
'_get_bytes_per_frame',
'_get_bytes_per_metadata_elt',
'_get_bytes_per_metadata_set',
'_get_bytes_per_stride',
'_get_eof_offset',
'_get_pixel_ntype',
'_get_pixels_per_frame',
'_get_start_offset',
'_get_xdim',
'_get_ydim',
'_load_footer_metadata',
'_load_header_metadata',
'_metadata_ntype',
'_ntype_to_bits',
'_num_metadata',
'_read_at',
'_spe_30_required_offsets',
'close',
'current_frame_idx',
'footer_metadata',
'get_frame',
'get_num_frames',
'header_metadata']
In [17]: spe.footer_metadata
Out[17]: ''
In [18]: spe._f
spe._fid spe._fname
In [18]: spe._fname
Out[18]: '/corral-repl/utexas/White_Dwarf_Archive/ProEM_1024B/20141121/SDSSJ0651+2844/SDSSJ0651+2844.spe'
In [19]: spe.header_metadata
Out[19]:
Binary Type_Name Offset \
0 16s ControllerVersion 0
1 16s LogicOutput 2
2 16u AmpHiCapLowNoise 4
3 16u xDimDet 6
4 16s mode 8
5 32f exp_sec 10
6 16s VChipXdim 14
7 16s VChipYdim 16
8 16u yDimDet 18
9 8s date[DATEMAX] 20
10 16s VirtualChipFlag 30
11 8s Spare_1[2] 32
12 16s noscan 34
13 32f DetTemperature 36
14 16s DetType 40
15 16u xdim 42
16 16s stdiode 44
17 32f DelayTime 46
18 16u ShutterControl 50
19 16s AbsorbLive 52
20 16u AbsorbMode 54
21 16s CanDoVirtualChipFlag 56
22 16s ThresholdMinLive 58
23 32f ThresholdMinVal 60
24 16s ThresholdMaxLive 64
25 32f ThresholdMaxVal 66
26 16s SpecAutoSpectroMode 70
27 32f SpecCenterWlNm 72
28 16s SpecGlueFlag 76
29 32f SpecGlueStartWlNm 78
.. ... ... ...
217 8s calib_valid 3587
218 8s input_unit 3588
219 8s polynom_unit 3589
220 8s polynom_order 3590
221 8s calib_count 3591
222 64f pixel_position[10] 3592
223 64f calib_value[10] 3672
224 64f polynom_coeff[6] 3752
225 64f laser_position 3800
226 8s reserved3 3808
227 8u new_calib_flag 3809
228 8s calib_label[81] 3810
229 8s expansion[87] 3891
230 8s Istring[40] 3978
231 8s Spare_6[25] 4018
232 8u SpecType 4043
233 8u SpecModel 4044
234 8u PulseBurstUsed 4045
235 32u PulseBurstCount 4046
236 64f PulseBurstPeriod 4050
237 8u PulseBracketUsed 4058
238 8u PulseBracketType 4059
239 64f PulseTimeConstFast 4060
240 64f PulseAmplitudeFast 4068
241 64f PulseTimeConstSlow 4076
242 64f PulseAmplitudeSlow 4084
243 16s AnalogGain; 4092
244 16s AvGainUsed 4094
245 16s AvGain 4096
246 16s lastvalue 4098
Description Value
0 Hardware Version NaN
1 Definition of Output BNC NaN
2 Amp Switching Mode NaN
3 Detector x dimension of chip. 256
4 timing mode NaN
5 alternative exposure, in sec. NaN
6 Vitual Chip X dim NaN
7 Virtual Chip Y dim NaN
8 y dimension of CCD or detector. 256
9 date NaN
10 On/Off NaN
11 NaN NaN
12 Old number of scans - should always be -1 -1
13 Detector Temperature Set NaN
14 CCD/DiodeArray type NaN
15 actual of pixels on x axis 256
16 trigger diode NaN
17 Used with Async Mode NaN
18 Normal, Disabled Open, Disabled Closed NaN
19 On/Off NaN
20 Reference Strip or File NaN
21 T/F Cont/Chip able to do Virtual Chip NaN
22 On/Off NaN
23 Threshold Minimum Value NaN
24 On/Off NaN
25 Threshold Maximum Value NaN
26 T/F Spectrograph Used NaN
27 Center Wavelength in Nm NaN
28 T/F File Is Glued NaN
29 Starting Wavelength in Nm NaN
.. ... ...
217 flag if calibration is valid NaN
218 current input units for calib_value NaN
219 linear UNIT and used in the polynom_coeff NaN
220 ORDER of calibration POLYNOM NaN
221 valid calibration data pairs NaN
222 pixel pos. of calibration data NaN
223 calibration VALUE at above pos NaN
224 polynom COEFFICIENTS NaN
225 laser wavenumber for relative WN NaN
226 reserved NaN
227 If set to 200, valid label below NaN
228 Calibration label (NULL termed) NaN
229 Calibration Expansion area NaN
230 special intensity scaling string NaN
231 NaN NaN
232 spectrometer type (acton, spex, etc) NaN
233 spectrometer model (type dependent) NaN
234 pulser burst mode on/off NaN
235 pulser triggers per burst NaN
236 pulser burst period (in usec) NaN
237 pulser bracket pulsing on/off NaN
238 pulser bracket pulsing type NaN
239 pulser slow exponential time NaN
240 pulser fast exponential amplitude constant NaN
241 pulser slow exponential time constant (in usec) NaN
242 pulser slow exponential amplitude constant NaN
243 analog gain NaN
244 avalanche gain was used NaN
245 avalanche gain value NaN
246 Always the LAST value in the header 21845
[247 rows x 5 columns]
In [20]: # the footer metadata wasn't extracted, but the footer metadata exists. what went wrong?
In [21]: # https://github.com/ccd-utexas/tsphot/issues/108
In [22]: exit()
login1.ls4(45)$
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment