Repository: Qiskit/qiskit

Issue:
CmdDef always returns positive FC phase.
<!-- ⚠️ If you do not respect this template, your issue will be closed -->
<!-- ⚠️ Make sure to browse the opened and closed issues -->

### Information

- **Qiskit Terra version**:
- **Python version**:
- **Operating system**:

### What is the current behavior?
When we `.get` u1, u2 or u3 from `CmdDef`, all FrameChange phases become positive value.


### Steps to reproduce the problem
```
cmd_def = pulse.CmdDef.from_defaults(defaults.cmd_def, defaults.pulse_library)
cmd_def.get('u1', 0, P0=-pi)
```
this returns a schedule consisting of FrameChange of +pi (because P0 is negated in cmd_def).

```
cmd_def = pulse.CmdDef.from_defaults(defaults.cmd_def, defaults.pulse_library)
cmd_def.get('u1', 0, P0=pi)
```
this returns a schedule consisting of FrameChange of +pi, but this should be -pi.


### What is the expected behavior?



### Suggested solutions





Discussion:

Resolving patch:
diff --git a/qiskit/qobj/converters/pulse_instruction.py b/qiskit/qobj/converters/pulse_instruction.py
--- a/qiskit/qobj/converters/pulse_instruction.py
+++ b/qiskit/qobj/converters/pulse_instruction.py
@@ -345,8 +345,9 @@ def convert_frame_change(self, instruction):
             phase_expr = parse_string_expr(phase, partial_binding=False)
 
             def gen_fc_sched(*args, **kwargs):
-                phase = abs(phase_expr(*args, **kwargs))
-                return commands.FrameChange(phase)(channel) << t0
+                # this should be real value
+                _phase = phase_expr(*args, **kwargs)
+                return commands.FrameChange(_phase)(channel) << t0
 
             return ParameterizedSchedule(gen_fc_sched, parameters=phase_expr.params)
 


Test patch:
diff --git a/test/python/pulse/test_cmd_def.py b/test/python/pulse/test_cmd_def.py
--- a/test/python/pulse/test_cmd_def.py
+++ b/test/python/pulse/test_cmd_def.py
@@ -133,6 +133,21 @@ def test_sequenced_parameterized_schedule(self):
         self.assertEqual(sched.instructions[1][-1].command.phase, 2)
         self.assertEqual(sched.instructions[2][-1].command.phase, 3)
 
+    def test_negative_phases(self):
+        """Test bind parameters with negative values."""
+        cmd_def = CmdDef()
+        converter = QobjToInstructionConverter([], buffer=0)
+        qobjs = [PulseQobjInstruction(name='fc', ch='d0', t0=10, phase='P1'),
+                 PulseQobjInstruction(name='fc', ch='d0', t0=20, phase='-(P2)')]
+        converted_instruction = [converter(qobj) for qobj in qobjs]
+
+        cmd_def.add('inst_seq', 0, ParameterizedSchedule(*converted_instruction, name='inst_seq'))
+
+        sched = cmd_def.get('inst_seq', 0, -1, 2)
+
+        self.assertEqual(sched.instructions[0][-1].command.phase, -1)
+        self.assertEqual(sched.instructions[1][-1].command.phase, -2)
+
     def test_build_cmd_def(self):
         """Test building of parameterized cmd_def from defaults."""
         defaults = self.backend.defaults()
@@ -151,7 +166,10 @@ def test_build_cmd_def(self):
 
         u1_minus_pi = cmd_def.get('u1', 0, P1=1)
         fc_cmd = u1_minus_pi.instructions[0][-1].command
-        self.assertEqual(fc_cmd.phase, np.pi)
+        self.assertEqual(fc_cmd.phase, -np.pi)
+
+        for chan in u1_minus_pi.channels:
+            self.assertEqual(chan.buffer, defaults.buffer)
 
 
 class TestCmdDefWithDeviceSpecification(QiskitTestCase):
@@ -263,6 +281,21 @@ def test_sequenced_parameterized_schedule(self):
         self.assertEqual(sched.instructions[1][-1].command.phase, 2)
         self.assertEqual(sched.instructions[2][-1].command.phase, 3)
 
+    def test_negative_phases(self):
+        """Test bind parameters with negative values."""
+        cmd_def = CmdDef()
+        converter = QobjToInstructionConverter([], buffer=0)
+        qobjs = [PulseQobjInstruction(name='fc', ch='d0', t0=10, phase='P1'),
+                 PulseQobjInstruction(name='fc', ch='d0', t0=20, phase='-(P2)')]
+        converted_instruction = [converter(qobj) for qobj in qobjs]
+
+        cmd_def.add('inst_seq', 0, ParameterizedSchedule(*converted_instruction, name='inst_seq'))
+
+        sched = cmd_def.get('inst_seq', 0, -1, 2)
+
+        self.assertEqual(sched.instructions[0][-1].command.phase, -1)
+        self.assertEqual(sched.instructions[1][-1].command.phase, -2)
+
     def test_build_cmd_def(self):
         """Test building of parameterized cmd_def from defaults."""
         defaults = self.backend.defaults()
@@ -281,7 +314,7 @@ def test_build_cmd_def(self):
 
         u1_minus_pi = cmd_def.get('u1', 0, P1=1)
         fc_cmd = u1_minus_pi.instructions[0][-1].command
-        self.assertEqual(fc_cmd.phase, np.pi)
+        self.assertEqual(fc_cmd.phase, -np.pi)
 
         for chan in u1_minus_pi.channels:
             self.assertEqual(chan.buffer, defaults.buffer)